29 KiB
Agent-Memory — pv-agent
Rollender Übergabe-Log für agent-Threads. Workflow: .agents/SKILL.md
(agent-memory-Skill). Ergänzen, nicht überschreiben.
Current focus
API-first-Festigung (D19): Der eigenständige Wissensdienst erhält einen versionierten, authentisierbaren v1-Vertrag und eine explizite Privacy-Grenze. Als Nächstes folgt der dünne Odoo-Client; Lohndaten bleiben bis zum separaten tenant-autorisierten Datenvertrag außerhalb der Agenten-API.
Completed (2026-09-14)
- Planung (
planung.md): Architektur, Grounding-Regeln, Modellfeld, Meilensteine M1–M4; Skill.agents/skills/pv-rag-agent/SKILL.md. - Commits:
25eb285(Wissensbasis-Import),bf8191b(Planung + Skills),2cba72a(M1+M2-Implementierung, 41 Tests). - Implementierung M1+M2 (
agent/): kb/ingest/retrieve/generate/ ollama_client/api/cli/eval, Goldset 31 Fragen, Test-Chat. - Ollama-Anbindung verifiziert (Ziel-Instanz
http://100.103.83.12:11435, Ollama 0.32.13):bge-m3per API gepullt;qwen3.8:27bwar bereits installiert. Hybrid-Index: 3.005 Chunks, alle eingebettet (144 s). - M1-Akzeptanz erreicht: Retrieval Hybrid Hit-Rate 0,968 · Recall@8 0,952 (>0,9 ✓) · MRR 0,690 (BM25-only: 0,871/0,855/0,476).
- M2-Antwortmodus-Eval (qwen3.8:27b, Thinking aus): Zitier-Präzision
100 % (4 Regenerierungen, alle geheilt) · Verweigerung korrekt
94,3 % · erwartete Quelle zitiert 80,6 % · Latenz mean 32 s / p95 53 s.
Report:
data/eval-qwen38.json. - Der ATZ-Konfliktfall (28,5 vs. 27,5 %) wird korrekt mit ⚠ und beiden IDs beantwortet; harte Verweigerung (UStVA, Retrieval nicht leer) funktioniert.
- Topologie geklärt:
100.103.83.12ist die Remote-GPU-Maschine (Entwicklungsumgebung, R9700, Tailscale); die Dev-Maschine selbst hat einen eigenen, fast leeren Ollama auf localhost:11434 (dorthin ging der erste bge-m3-Pull — auf die GPU-Maschine neu gepullt). Ziel-Instanz ist ausschließlichhttp://100.103.83.12:11435. - Bake-off M3 — abgeschlossen (D7): alle 6 Kandidaten gemessen
(Tabelle in
planung.mdAbschnitt 13).qwen3.8:27bgewinnt (100 % Zitier-Präzision, 94,3 % Verweigerung korrekt, 80,6 % erwartete Quelle, 32 s mean).gemma4:26b= dokumentierter Latenz-Kandidat (7,9 s mean, 100 % Zitier-Präzision, aber 67,7 % Quellentreue, 3 Fehlverweigerungen). mistral-small3.1: 71,4 % Verweigerungskorrektheit — Deutsch-Hypothese praktisch widerlegt. muse-glimmer:latest (nachgereicht): 100 % Zitier-Präzision bei nur 1 Regenerierung (diszipliniertestes Modell), aber 8/35 falsche Verweigerungen (Überverweigerung teils trotz vorhandener Zitate) und 37,5 s mean — Rang 5 von 6, schlägt qwen3.8 in keiner Kennzahl. qwen3.6:27B: 2 dauerhafte Zitierverletzungen, 10 Regenerierungen. gemma4:12B: 2 Verletzungen. Reports:data/eval-*.json. q-008/q-031 verweigern alle Top-Kandidaten — Prompt-/Retrieval-Tuning (nicht modellspezifisch). - Remote-GPU-Maschine: nach
systemctl restart ollama(User-Aktion) liefen alle Läufe stabil; zwischen Kandidaten wurde perkeep_alive: 0entladen (Crash-Ursache war der Modell-Swap-Stress beim gemma4-Lauf).
Completed (2026-09-15)
-
KB-Erweiterung um WKO-Kollektivverträge + RIS-Gesetze (User-Auftrag):
.firecrawl/kv-portal/wko-kv/docs/(614 KV-Dokumente: Lohn-/Gehaltsordnungen mit Lohntabellen, KV-Abschlüsse, Erläuterungen, Zusatz-KVs) und.firecrawl/ris/gesetze/(59 Gesetze, nur die im Lexis360-Bestand zitierten §-Ausschnitte, Stand 2026-09-13) → 1 274 Layer-2-Einträge (kv-kvt-001…614,ris-<prefix>-nn), 14 984 Chunks, Reindex 8,5 min (11 947 neue Embeddings, bge-m3 auf :11435).- D9 (2026-09-15): kv/ris-Einträge sind quellentreu generiert
(keine Eigene-Worte-Kuratierung — Gesetze sind amtliche Werke, KV-
Lohntabellen zahlenexakt; Konvention 2 der Wissensbasis gilt nur für
die lizenzierten Quellen lb/wk). Tool-Output:
tools/ingest_sources.pytools/build_registry.py(Registry in diesem Repo neu gebaut — das Lexis-Toolbuild_lexis_kb.pylebt im Schwesterprojekt), eingefrorene Katalogetools/catalogs/*.json(nur Metadaten, versioniert).
- ID-Räume:
kv-kvt-<nnn>(ein Clusterkollektivvertraege, Branche als Tag) undris-<cluster-prefix>-<nn>auf der bestehenden Cluster-Map + 7 neue Cluster (kvt/zvr/avr/agg/lst/abo/nso);LAW_MAPintools/kb_common.pydokumentiert die 59 Zuordnungen. - D10 (Retrieval-Kalibrierung, Goldset-Sweep 2026-09-15): Korpus-
verdopplung drückte Recall@8 auf 0,851 — kalibriert auf
dense_weight=2.0(Dense-Liste relativ zu BM25 gewichtet; BM25 ist durch KV-§-Titel-Matches inflationiert),rrf_k=20,candidate_pool=150→ Recall@8 0,923 (>0,9 ✓), Hit-Rate 0,973 (36/37), MRR 0,667. ENV:PV_DENSE_WEIGHT/PV_RRF_K/PV_CANDIDATE_POOL. Entry-RRF-Variante getestet: kein Mehrwert. - Antwortmodus-Eval (qwen3.8:27b, 42 Fragen): Zitier-Präzision
95,2 % (2 Verletzungen), Verweigerung korrekt 90,5 % (4 Fehlver-
weigerungen, u.a. q-022/q-029), erwartete Quelle zitiert 83,8 %,
Latenz mean 31 s / p95 53 s, 9 Regenerierungen — unter den M3-
Gates (100 % / 94,3 %): Korpusverdopplung macht Grounding härter;
das laufende Fehlverweigerungs-Tuning (uncommittete Änderungen in
generate.py/retrieve.py/goldset.yaml, unangetastet) ist weiteres
Thema. Report:
data/eval-qwen38-kvris.json. - Goldset: +7 Fragen (q-101–106 KV-Preise/§-Fragen, r-005 Branchen-
Refusal) — append-only. q-021 rekalibriert: erwartete ID jetzt
lb-kar-04(„Karenz - Anspruch, Beginn und Dauer“, Top-1, deckt Beginn/Dauer vollständig; lb-kar-01 nur Nachbarschaft — dokumentiert im Goldset-Note). - Tests: 41 → 49, alle grün (neue ID-Räume, html-Source, Konverter, LAW_MAP-Vollabdeckung, Korpus-Integrationszahl 1 274).
- D9 (2026-09-15): kv/ris-Einträge sind quellentreu generiert
(keine Eigene-Worte-Kuratierung — Gesetze sind amtliche Werke, KV-
Lohntabellen zahlenexakt; Konvention 2 der Wissensbasis gilt nur für
die lizenzierten Quellen lb/wk). Tool-Output:
-
D15 (Rechtsprechungs-Intake, 2026-09-15):
.rechtsprechung/→ neuer ID-Raumrj-rjs-*, gemeinsamer Clusterrechtsprechung: 320 RIS-OGD- Entscheidungen/Rechtssätze, 23 zitierte RIS-Normauszüge und 5 als nichtamtlich markierte EuGH-lexetius-Textwiedergaben. Parser:tools/ingest_sources.py --source rj; lange Volltexte werden an Absatzgrenzen in H2-Chunks geteilt.rj_catalog.jsonfriert die IDs ein; Registry/Index und Agent-Zitatvalidierung kennenrj-*. Korpus 1.274 → 1.622 Einträge / 77 Cluster; Reindex: 16.480 Chunks, 1.496 neue Embeddings in 75 s. Retrieval-Goldset erweitert um q-120–123: Hit-Rate 0,956 · Recall@8 0,922 (Gate ✓) · MRR 0,661, alle vier neuen Fälle gefunden. Gezielte Antwortläufe q-120–123: alle zitiergültig, nicht verweigert, keine Regenerierung; Systemprompt verlangt für als nicht amtlich markierte Quellen die gleiche Einschränkung in der Antwort (q-123 verifiziert). Voller Antwortmodus-Eval (50 Fragen): 100 % Zitier-Präzision, 100 % Verweigerung korrekt, erwartete Quelle 93,3 %, mean 39,4 s / p95 82,2 s, 5 Regenerierungen; Reportdata/eval-qwen38-rj.json(lokal/unversioniert). Offline-Tests: 65 grün. Nicht als generelle Commit-Freigabe lesen: Die gelieferten OGH/VwGH/VfGH-Dateien nennen überwiegend RIS-OGD, der User sprach jedoch von Lexis/opendataloader; die Publikations-/Lizenzfreigabe der quellentreuen Volltexte ist vor Commit ausdrücklich zu prüfen. EuGH-Wiedergaben sind als nichtamtlich markiert und verweisen auf EUR-Lex.
Completed (2026-09-16)
-
D16 (Gestaltungsfragen / Retrieval-Tuning): Goldset um q-124–126 erweitert (500-Euro-Zusatzzahlung, Alternativen, Mitarbeiterprämie 2026).
agent/query_planner.pyerkennt Decision-Support deterministisch und zerlegt in drei gesetzlich gescopte Queries: Mitarbeiterprämie samt §-49-Konflikt, Zukunftssicherung sowie Sach-/zweckgebundene Leistungen. Decision-Support läuft alsspecific, nicht als Survey/Map-Reduce.Retriever.search()nutzt denselben Plan im Offline-Eval;search_multi()behält Scope/Jahr auch bei einer einzelnen Query. Ergebnis (53 Goldsetfragen / 48 Retrieval-Fälle): q-124/q-125/q-126 jeweils Recall@8 1,00, gesamt Recall@8 0,9271 (Gate >0,9), Hit-Rate 0,9583, MRR 0,6158. Bekannte Altfehler q-015/q-113 bleiben unverändert. -
Decision-Support-Grounding: Systemprompt trennt Barzahlung von zweckgebundenen Leistungen, verbietet pauschale Sieger ohne Kontext, verlangt vergleichbare Abgabendimensionen und genau eine Rückfrage. Der bekannte Konflikt Mitarbeiterprämie 2026 wird offen dargestellt:
wk-akt-04nennt SV/BV/DB/DZ/KommSt-Pflicht,lb-sva-03ordnet die Prämie systematisch in den taxativen Katalog beitragsfreier Bezüge ein. Zusätzlich erzwingt ein semantischer Post-Validation-Gate ⚠ + beide IDs + korrekte Rollen und verhindert interne Regelverweise bzw. Quellenpriorisierung. Gezielte Real-Läufe: q-124/q-125 nicht verweigert, zitiergültig; q-126 war bereits sauber. Tests 72 grün;git diff --checksauber. -
D16 Voll-Eval (2026-09-16): 53 Fragen mit
qwen3.8:27b; Reportdata/eval-qwen38-decision-support.json(lokal/gitignored). Retrieval: Hit-Rate 0,9583, Recall@8 0,9271, MRR 0,6266. Antworten: Zitier-Präzision 98,11 %, Verweigerung korrekt 98,11 %, erwartete Quelle 91,67 %, mean 40,3 s / p95 98,4 s, 4 Regenerierungen. Einziger Gate-Fehler: q-125 eskalierte nach zwei semantisch unzureichenden Antworten zuUNCERTAIN(verified=false). Direkte Wiederholung von q-125 war mit einer Regenerierung vollständig, zitiergültig und stellte den Konflikt korrekt dar — verbleibend ist stochastische Gate-/Regenerierungs-Flakiness, kein Retrieval-Fehler. q-124 und q-126 bestanden im Voll-Eval. -
D16 Stabilisierung/Bestätigung (2026-09-16): Bei vollständig ausgelassenem, aber retrieved Mitarbeiterprämien-Konflikt ergänzt die Pipeline deterministisch eine feste, ausschließlich aus
lb-sva-03undwk-akt-04formulierte ⚠-Notiz. Eigene Konfliktversuche bleiben ungeändert und werden weiter auf Rollenfehler/Priorisierung geprüft. Der semantische Gate akzeptiert gleichwertige Verben (ordnet,listet,führt) statt fragiler exakter Wortwahl. Sonden: q-124 3/3 ohne Regenerierung, q-125 3/3 verifiziert, q-126 verifiziert. Voller Bestätigungslauf (53 Fragen), Reportdata/eval-qwen38-decision-support-confirm.json: Zitier-Präzision 100 %, erwartete Quelle 93,75 %, mean 40,3 s / p95 69,6 s, 3 Regenerierungen; q-124–126 alle bestanden. Verweigerungskorrektheit 98,11 % nur wegen der bekannten stochastischen Survey-Fehlverweigerung q-029; direkte q-029- Wiederholung antwortete verifiziert (aber sehr langsam, 280 s). -
q-015 fachlich rekalibriert: Eine allgemeine Tagesgeldfrage mischt zwei Ebenen: Der KV regelt vorrangig den arbeitsrechtlichen Anspruch, das EStG den steuerfreien Satz. Branchen-KV-Treffer sind deshalb korrekt; q-015 hat keine künstliche Einzel-Pflicht-ID mehr. Neue q-127 prüft ausdrücklich nur die steuerliche Höhe und findet
lb-rei-09. Goldset 54 Fragen; Offline-Retrieval nun Hit-Rate 0,9792, Recall@8 0,9479, MRR 0,6653. Tests 75 grün. -
llama.cpp-LLM-Eval (2026-09-16): Lokaler/privater OpenAI-kompatibler Server aus
.envgetestet (Zugangsdaten/URLs nicht dokumentiert oder versioniert); nur das LLM wurde gewechselt, Retrieval und bge-m3-Index blieben unverändert. llama.cpp benötigtchat_template_kwargs.enable_thinking=false; Chatmodell meldet sich alsqwen3.8. 54-Fragen-Report:data/eval-llamacpp-qwen38.json(lokal/gitignored). Zitier-Präzision 100 %, Verweigerung korrekt 96,3 %, erwartete Quelle 91,67 %, mean 54,9 s / p95 104,8 s, 2 Regenerierungen. q-124–126 bestanden alle ohne Regenerierung. Fehlverweigerungen: q-029 (bekannte Survey-Flakiness, 357 s) und q-102. q-102 ist kein LLM-Defizit: Mit Planner lieferte der KV-Scope viele ähnlich benannte KVs und nur einen irrelevanten Abschnitt von kv-kvt-197; ohne Planner beantwortete dasselbe llama.cpp-Modell die Frage in 14,8 s korrekt aus kv-kvt-056. Schluss: llama.cpp ist grounding-stabil, aber langsamer als die Ollama-Basislinie; q-102 erfordert später Planner-/Retrieval-Tuning, nicht Modell-Tuning. -
llama.cpp-Rerun nach Server-Tuning (2026-09-16): Report
data/eval-llamacpp-qwen38-rerun.json(lokal/gitignored), gleicher Aufbau wie zuvor: nur LLM über llama.cpp, Retrieval/bge-m3 unverändert. Ergebnis: Zitier-Präzision 100 %, Verweigerung korrekt 98,15 %, erwartete Quelle 95,83 %, mean 53,5 s / p95 105,4 s, 6 Regenerierungen. Gegenüber dem ersten Lauf: q-029 geheilt, erwartete Quelle +4,16 Prozentpunkte, mean ca. 1,3 s schneller; q-102 bleibt als einzige Fehlverweigerung reproduzierbar (Planner-/Kontextproblem). q-124–126 bestehen weiterhin; q-125/q-126 benötigten diesmal je eine Regenerierung. Das Server-Tuning ist damit qualitativ besser, erhöht aber die Regenerierungen (2 → 6); Latenz bleibt deutlich über der Ollama-Basislinie. -
llama.cpp Full-Stack (Chat + Embeddings, 2026-09-16): llama.cpp- Embeddings sind trotz gleicher Dimension 1024 inkompatibel zu Ollama
bge-m3(Same-Text-Cosinus nur ca. -0,004 bis 0,017); deshalb separater, lokaler Indexdata/index-llamacpp.db. Vollständig 16.480 Chunks; der Embedding-Server lehnt einzelne Texte > ca. 9.000 Zeichen ab, daher wurden nur für diesen Test längere Embedding-Inputs deterministisch auf 9.000 Zeichen gekürzt (KB und Produktionsindex unverändert). Indexbau ca. 17,4 min. Retrieval ohne Neukalibrierung: Hit-Rate 0,9583, Recall@8 0,9323, MRR 0,5977 (Gate >0,9 erfüllt). Vollreportdata/eval-llamacpp-fullstack.json(lokal/gitignored): Zitier-Präzision 100 %, Verweigerung korrekt 94,44 %, erwartete Quelle 87,5 %, mean 44,6 s, p95 130,8 s, 3 Regenerierungen. Full-Stack ist schneller als llama.cpp-LLM + bge-m3 (53,5 s), aber fachlich schwächer: Fehlverweigerungen q-029, q-102, q-111. q-102: korrektes Dokument kv-kvt-056, aber falscher repräsentativer Abschnitt; q-111: Embedding-Retrieval verfehlt kv-kvt-001 komplett und liefert fremde Lehrlingstabellen. Decision-Support q-124–126 besteht weiter. Fazit: Full-Stack ist testfähig und erfüllt das Retrieval- Recall-Gate, ersetzt bge-m3 aber noch nicht; zuerst eigene RRF-/Dense- Kalibrierung und KV-Metadaten-/Representative-Section-Tuning nötig. -
llama.cpp Full-Stack Rerun (2026-09-16): identischer separater Index und unveränderte Parameter; Report
data/eval-llamacpp-fullstack-rerun.json. Zitier-Präzision 100 %, Verweigerung korrekt 98,15 %, erwartete Quelle 91,67 %, mean 49,5 s / p95 101,2 s, nur 1 Regenerierung. Gegenüber erstem Full-Stack-Lauf: q-029 und q-111 geheilt, Fehlverweigerungen 3 → 1, erwartete Quelle +4,17 Prozentpunkte, Regenerierungen 3 → 1; Latenz dagegen 44,6 → 49,5 s. Einziger reproduzierbarer Fehler bleibt q-102 (korrektes Dokument, falscher Representative-Section-Kontext). q-124–126 alle ohne Regenerierung bestanden. Full-Stack erreicht damit dieselbe Verweigerungs- korrektheit wie der aktualisierte llama.cpp-LLM+bge-m3-Lauf, bleibt aber bei erwarteter Quelle darunter (91,67 % vs. 95,83 %). -
D17 (Runtime-Entscheidung, 2026-09-16): Nach den llama.cpp-LLM- und Full-Stack-Vergleichen bleibt der Agent bei Ollama mit
qwen3.8:27b+bge-m3. Gründe: beste bzw. stabilere Gesamtbalance aus erwarteter Quellentreue, Verweigerungskorrektheit und Latenz; llama.cpp- Full-Stack zeigte embedding-spezifische KV-/Representative-Section-Fehler und höhere Flakiness. Der letzte angeforderte Full-Stack-Rerun wurde nach drei Fragen vom User abgebrochen und nicht gewertet. Lokale llama.cpp- Indizes/Reports und.envbleiben unversioniert; keine Integration in die Produktionskonfiguration. -
Finaler Ollama-54-Eval (2026-09-16): Nach Rückkehr zum Ziel-Stack
qwen3.8:27b+bge-m3, Reportdata/eval-qwen38-final-54.json(lokal/gitignored). Retrieval: Hit-Rate 0,9792, Recall@8 0,9479, MRR 0,6378. Antworten: Zitier-Präzision 100 %, Verweigerung korrekt 100 %, erwartete Quelle 95,83 %, mean 38,8 s, p95 67,2 s, 2 Regenerierungen. q-029 sowie q-124–127 bestanden; damit beide Haupt-Gates erstmals im finalen 54er-Set vollständig erfüllt. Zwei Quellentreue- Abweichungen ohne Grounding-Verstoß: q-127 zitiert alternative Reisekosten- Quellen (lb-rei-01/03,wk-rei-01plus KVs) statt erwarteterlb-rei-09; q-025 zitiert Betriebsübergangs-/Insolvenzquellen statt der bisherigen Expected-ID. Optional später Goldset-Expected-IDs fachlich rekalibrieren, aber kein Release-Blocker. -
D18 (Rechtsprechungsnutzung, 2026-09-16, User-Freigabe): Auf gerichtliche Entscheidungen darf in Antworten verwiesen werden. Ihr Inhalt darf in eigenen Worten wiedergegeben und stellenweise zitiert werden. Die Agentenantwort muss weiterhin die retrieved
rj-*-/RIS-KB-ID nennen, nichtamtliche Wiedergaben ausdrücklich kennzeichnen und darf keine nicht retrieved Entscheidung ergänzen. Diese Freigabe umfasst Referenz, Zusammenfassung und auszugsweise Zitate; sie ist keine pauschale Freigabe zur Veröffentlichung vollständiger quellentreuer Entscheidungstexte.
Open issues / blockers
- Push: Remote localhost:3003 aus der Sandbox nicht erreichbar — User pusht vom Host.
- Fehlverweigerungen — Stand nach Prompt v2: q-008 und q-031 sind behoben (Section-Priorität + Regel 8). Verbleibend: q-029 („Welche Neuerungen behandelt WIKU Personal aktuell 2026?“) — breite Survey-Frage über 12 Hefte; Kontext enthält echte Zusammenfassungen, Modell verweigert trotzdem (sicherer Fehlermodus). Mögliche spätere Hebel: Survey-Rule im Prompt, mehr Kontextblöcke oder Map-Reduce-artige Zusammenfassung. Weitere Iterationen erst mit neuen Evaluationsdaten.
- Latenz: mean 32 s/ Antwort ist hoch (Dense 27B + große Prompts). Hebel: weniger Kontextblöcke (aktuell 8+6), schnellere Kandidaten.
- Cloud-Modelle (
*:cloudauf der Ollama-Instanz) sind für Antworten tabu (Anforderung: lokal). Nicht versehentlich konfigurieren. - Bake-off M3 — erledigt (siehe Completed; Entscheidung D7 in
planung.md). Nach Tuning von Prompt/Retrieval: erneuter kurzer Bestätigungslauf nur mit dem Sieger. - M4 Odoo: native LLM-Module des konkreten Odoo-19-Stands verifizieren (keine API-Annahmen); Option A (dünnes Custom-Modul + Service-API) ist Default.
- Nach KV/RIS-Erweiterung (2026-09-15): Antwortmodus vor dem Tuning
(D10-Follow-up) unter den Gates (Zitier-Präzision 95,2 % — 2 Verlet-
zungen; Verweigerung 90,5 % — 4 Fehlverweigerungen, u.a. q-022/q-029;
erwartete Quelle 83,8 %) — Report
data/eval-qwen38-kvris.json. D11-Fix behoben die 4 Fehlverweigerungen: Antwortmodus jetzt Zitier-Präzision 97,6 %, Verweigerung 97,6 % (>94,3 %-Gate ✓), erwartete Quelle 91,9 %, Retrieval Recall@8 0,946 — Reportdata/eval-qwen38-kvris-tuned.json. Verbleibend: q-015 (Branchen- Noise) und q-024 als transiente Flakiness (leerer Draft — Think-Ghost- Verdacht bei 32k-Kontext; beobachten). - q-015 (Tagesgelder Dienstreisen) — Branchen-Noise: 8 Branchen-KV- Einträge verdrängen lb-rei-01/09 (EStG-Taggeld-Abrechnung) aus Top-8; generische Branchen-Frage ist mehrdeutig geworden. Hebel: Frage präzisieren (Branche/Kontext) oder KV-§-Titel-Matches dämpfen.
Decisions & conventions
- D1 (Planung): Schlanke Eigen-Pipeline statt LangChain/LlamaIndex — Grounding-Kontrolle schlägt Framework-Komfort bei 601 Dokumenten.
- D2: Retrieval-Korpus ist nur Layer 2; Layer 1 bleibt aus Prompts
(Lizenz); Antworten zitieren
[kb-id]+(Stand YYYY-MM). - D3: Umlaut-Folding für FTS (NFKD, ß→ss) — gilt konsistent für Index und Query; ASCII-Slug-Konvention der Wissensbasis bleibt davon unberührt.
- D4: Post-Validierung strikt: zitierte IDs ⊆ Retrieved-Set (Block-Kopf- IDs); Fließtext-Verweis-IDs sind KEINE Belege (Systemprompt-Regel 2) — Verstoß → 1× Regenerierung → Verweigerung (UNCERTAIN_MESSAGE).
- D5: Vektoren-Tabelle ist Cache (Content-Hash × Modell), Rebuild
löscht sie nicht;
--no-embedsetztembed_offim Config-Copy. - D6: Leeres Retrieval → deterministische Verweigerung ohne LLM-Call.
- D7 (Bake-off 2026-09-14):
qwen3.8:27bist das fixierte Antwortmodell (100 % Zitier-Präzision, 94,3 % Verweigerung korrekt).gemma4:26bals dokumentierter Latenz-Kandidat; ein Modellwechsel läuft nur erneut über das dokumentierte Protokoll (Skill). - D8 (Prompt-Tuning 2026-09-14): Prompt v2 + Kontext-Section-
Priorität. (a) Regel 4 erlaubt Teilantworten bei unvollständiger Deckung;
Regel 8 verlangt Prämisse-Korrektur statt Verweigerung (Muster-Beispiel
„Mindestlohngesetz“). (b)
_representative_chunkwählt pro Eintrag die beste Inhaltssektion (Zusammenfassung > Kernwerte > RechtsgrundlagenPayroll > sonstige; „Verweise“ nur als letzter Rückgriff — BM25 rangiert die dünnen Navigations-Chunks bevorzugt, q-008-Ursache). Ergebnis v1→v2: Zitier-Präzision 100 % gehalten; q-008 + q-031 behoben; erwartete Quelle 80,6 → 83,9 %; Verweigerung 94,3 % (Fehler getauscht: neu q-029 — breite Survey-Frage über 12 Hefte, sicherer Fehlermodus). Report
data/eval-qwen38-v2.json. - D9 (KV/RIS-Erweiterung, 2026-09-15): kv-/ris-Einträge sind
quellentreu generiert (keine Eigene-Worte-Kuratierung — Gesetze
sind amtliche Werke, KV-Lohntabellen zahlenexakt; Konvention 2 der
Wissensbasis gilt nur für die lizenzierten Quellen lb/wk).
Tool-Output:
tools/ingest_sources.py+tools/build_registry.py(Registry in diesem Repo neu gebaut — das Lexis-Toolbuild_lexis_kb.pylebt im Schwesterprojekt), eingefrorene Katalogetools/catalogs/*.json(nur Metadaten, versioniert). IDs:kv-kvt-<nnn>(ein Clusterkollektivvertraege, Branche als Tag),ris-<cluster-prefix>-<nn>auf der bestehenden Cluster-Map + 7 neue Cluster;LAW_MAPintools/kb_common.py(59 Gesetze). - D10 (Retrieval-Kalibrierung, 2026-09-15): nach KV/RIS-Erweiterung (3.005 → 14 984 Chunks) dense_weight=2.0 (Dense relativ zu BM25 gewichtet — BM25 durch KV-§-Titel-Matches inflationiert), rrf_k=20, candidate_pool=150 → Recall@8 0,851 → 0,923 (>0,9 ✓), Hit-Rate 0,973, MRR 0,667. ENV: PV_DENSE_WEIGHT / PV_RRF_K / PV_CANDIDATE_POOL. Entry-RRF-Variante getestet: kein Mehrwert.
- D11 (Prompt-Budget + Kontext-Abdeckung, 2026-09-15): lange KV-Chunks
ueberlieferten num_ctx=16384 (q-022: 62,7 KB Prompt ≈ 18k Tokens) —
Ollama trunciert den Systemprompt vorn, das Modell verliert die
Zitierregeln („Block 8“-Zitate statt IDs → Regenerierung → Verweigerung).
Fix: num_ctx 32 768,
trim_results(max_context_chars=90 000, Tail- Bloecke ganz weg statt trunciert, Mindestbestand 6) und cross_ref_expand 3 → 6 (die Top-3 sind oft Branchen-KV-Bloecke mit leeren cross_refs — kuratierte Nachbarn kamen sonst nie nach). Ergebnis: alle 4 Fehlverweigerungs-Faelle (q-001/q-019/q-022/q-029) geheilt, 10/10 Bestaetigungslaeufe OK. Eval: Zitier-Praezision 97,6 %, Verweigerung 97,6 % (> 94,3 %-Gate ✓), erwartete Quelle 91,9 % (vorher 83,8 %), Retrieval Recall@8 0,946 (cross_ref-Extras bringen Expected-IDs nach), MRR 0,671. Latenz mean 33 s. Reportdata/eval-qwen38-kvris-tuned.json. Restrisiko: q-024 flaky (1/3 Laeufe — transienter leerer Draft, Think-Ghost-Verdacht); q-015 Branchen-Noise bleibt offen. - D12 (Komplexe-Fragen-Stufe 1 / M6, 2026-09-15): Query-Planer vor dem
Retrieval: Heuristik-Gate (Jahreszahl, Vergleichs-/Aggregationsmarker,
Laenge) entscheidet, ob ein kleiner LLM-Call die Frage in 1-3 Sub-Queries
zerlegt (JSON, temp 0, num_predict 220; Fehler -> Original als Einzel-
Query). Multi-Query-Retrieval: je Sub-Query BM25+Dense, Beitraege
summieren; Per-Query-Slots (2 je Sub-Query) sichern jeden Frage-
aspekt im Kontext — ohne sie dominieren Eintraege, die in mehreren
Sub-Queries mittelgut matchen (q-113: 5 KV-Urlaubs-SS schlugen
lb-url-05 (Rang 6) und ris-url-01 (>Top-12) ueber beide Sub-Queries).
Scope-Filter je Sub-Query: Planer markiert "gesetz" (nur Lexis/WIKU/
RIS-Chunks) bzw. "kv" (nur Branchen-KV) — q-113 geheilt (ris-url-01/
lb-url-05 + KV-Ss im selben Kontext). Scope-Fallback: gefilterte Suche
leer -> unscoped. Temporal-Intent: stand_year je Sub-Query, kv-Eintraege
im Geltungsjahr erhalten temporal_boost (default 0 — FTS-Tag-Signal
jahr-YYYYreichte in der Messung). Grounding unveraendert: ein Kontext aus der Union, Post-Validierung ueber die gesamte Retrieved- Menge, Verweigerungspflicht unveraendert. Eval (46 Fragen): Zitier-Praezision 97,8 %, Verweigerung 97,8 % (Gate > 94,3 % erfuellt), erwartete Quelle 90,2 %, Latenz mean 33,5 s. Temporal-Fragen laufen sogar ohne Planer gut (Jahr-Toknen matchenjahr-YYYY-Tags). Neue komplexe Fragen im Goldset: q-110 (Temporal 2023, nach Korrektur — eine 2024er-Friseur-Lohnordnung existiert im Korpus NICHT: kv-kvt-161 ist der Mantelvertrag ohne Lohntabelle; korrekt verweigert), q-111 (Temporal 2025), q-112 (Abfertigung Vergleich), q-113 (Gesetz+KV Multi-Source). Tests 50 -> 57. Offen: q-029 Survey (Stufe-2-Hebel: Map-Reduce), q-113 Planer- Scope flaky (1/2 Laeufe ohne gesetz-Marker). - D13 (Antworttyp-Routing / Stufe 2, 2026-09-15): (a) Planer liefert
jetzt
type: survey|specific; Survey-Fragen („Welche Neuerungen …“) laufen ueber Map-Reduce: breiteres Retrieval (survey_blocks=16, PV_SURVEY_BLOCKS), ein Map-Call destilliert JE Block als Stichpunkte mit seiner KB-ID (MAP_SYSTEM_PROMPT), ein Reduce-Call synthetisiert daraus die Antwort mit dem normalen Grounding-Prompt; Zitier- Validierung weiterhin strikt ueber die Retrieved-Union, leerer Map-Output -> Fallback Einzelantwort. (b) Systemprompt-Regel 9: bei wesentlicher Kontextabhaengigkeit (Branche, Bundesland, Zeitraum) belegte allgemeine Aussage + EINE Rueckfrage statt Verweigerung (API-first; Odoo-Chat kann die Rueckfrage als Follow-up nutzen). Ergebnis: q-029 geheilt (vorher jahrelange Fehlverweigerung; jetzt Teilantwort mit 5 belegten Heften, 95 s — Map-Reduce-Latenz nur bei Survey-Fragen), q-015 antwortet mit expliziter KV-Abhaengigkeit + Rueckfrage statt Branchen-Noise. Eval (46 Fragen): Zitier-Praezision 97,8 %, Verweigerung 97,8 % (Gate erfuellt), erwartete Quelle 90,2 %, Latenz mean 34,2 s. Tests 57 -> 59. Reportdata/eval-qwen38-stage2.json. Verbleibend: q-024 transiente Flakiness (Think-Ghost-Verdacht, 2/3 Laeufe sauber). - D14 (Output-Budget + length-Retry, 2026-09-15): q-024-Flakiness
Ursache gefunden — NICHT Thinking (Hypothese widerlegt: thinking-Feld
leer, keine Tags), sondern
num_predict=1024: lange belegte Antworten wurden beidone_reason=lengthabgschnitten (q-024: 3/3 Sondenlaeufe) → unvollstaendige Zitationen → CITE_RE matcht partielle IDs → Verletzung → Regen-Eskalation → UNCERTAIN. Fix: (a) num_predict 1024 → 2048; (b)OllamaClient.chat_full()liefert (content, done_reason); (c)chat_with_length_retry: ein technischer Retry mit 2× num_predict bei length (zaehlt nicht als Regel-Regenerierung, laeuft auch im Map- und im Regenerierungspfad). Voll-Eval: Zitier-Praezision 100 %, Verweigerung korrekt 100 % (46/46 — alle M3-Gates erfuellt, erstmals ueber Basislinie), erwartete Quelle 92,7 %, Latenz mean 39,6 s / p95 78 s (+5 s: vollstaendige statt abgeschnittener Antworten). q-024: 4/4 stabil. Tests 59 → 60. Reportdata/eval-qwen38-lengthfix.json. - D19 (API-first-Vertrag, 2026-09-16):
/v1/ask,/v1/healthund/v1/reindexsind die stabilen Endpunkte; alte Pfade bleiben deprecated. Der Ask-Response enthält Status, Quellen, belegte Konflikte, extrahierte Rückfrage, Planungs- und Grounding-Metadaten sowie eine Request-ID. Optionaler Bearer-Schutz überPV_API_KEY; Reindex kann mitPV_ADMIN_API_KEYgetrennt werden. Leere Keys sind nur lokaler Entwicklungsmodus. Health und öffentliche Fehler nennen keine internen Hosts/Exceptions. v1 ist zustandslos,knowledge_base_only, lehnt unbekannte JSON-Felder ab und akzeptiert keine Payroll-/Mitarbeiterobjekte. Odoo-Lohndaten erfordern später einen separaten tenant-autorisierten Vertrag mit Datensatzregeln, Datenminimierung, Audit und Cross-Tenant-Tests. Vertrag:docs/API.md. Der gemeinsame SQLite-Retriever ist durchcheck_same_thread=FalseplusRLockworker-thread-sicher. Neue Nicht-lokaler CLI-Bind ohnePV_API_KEYwird fail-closed abgelehnt. Neue API-/Concurrency-Tests erhöhen die Offline-Suite von 75 auf 82 grüne Tests. - Bake-off-Protokoll (Skill): Modellwechsel nur über dokumentierten Goldset-Vergleich; Kriterium: Zitier-Präzision > Verweigerungs- korrektheit > Latenz.
Files that matter right now
planung.md— Plan + Entscheidungspunkte (Abschnitt 12) + Stand..agents/skills/pv-rag-agent/SKILL.md— verbindliche Regeln.agent/README.md— Betrieb, Konfiguration, Host-Schritte.docs/API.md— v1-Vertrag, Authentisierung, Privacy-Grenze und Odoo-Aufruf.agent/api.py— versionierte Service-Oberfläche und Sicherheitsgrenzen.agent/eval/goldset.yaml— Goldset (IDs gegen kb.json verifiziert).agent/generate.py— Grounding-Kern (Prompt, Post-Validierung).wissensbasis/README.md— Layer-2-Schema + Rechtsprechungs-Provenance.tools/ingest_sources.py/tools/catalogs/rj_catalog.json— rj-Intake und gefrorene IDs.agent/eval/goldset.yaml— q-120–123; als Nächstes Antwortmodus-Eval.