Ollama-URL korrigiert (100.103.83.12:11435) und M1/M2 gegen Echt-System validiert

Der Host betreibt zwei Ollama-Instanzen: 11434 (fast leer, 0.16.2) und
11435 (Ziel-Instanz, 0.32.13, Modell-Zoo) — Port nicht mehr auf 11434
'korrigieren' (Dokumentation + Skill + Config-Default angepasst).

Validierung gegen das echte System: bge-m3 per API gepullt, Hybrid-Index
(3005 Chunks, 100 % eingebettet, 144 s), M1-Akzeptanz erreicht (Recall@8
0,952 > 0,9; Hit-Rate 0,968). Antwortmodus-Eval mit qwen3.8:27b (Thinking
verifiziert aus): Zitier-Präzision 100 % (4 Regenerierungen), Verweigerung
korrekt 94,3 %, Latenz mean 32 s. ATZ-Konfliktfall korrekt beide Werte
mit Warnung. generate.py: sources enthaelt jetzt nur zitierte Quellen;
Systemprompt ohne redundante Quellenzeile.

Bake-off-Feld (M3) bereits installiert: qwen3.6:27B, gemma4:26b,
mistral-small3.1:24b, gemma4:12B.
This commit is contained in:
2026-09-14 22:09:09 +02:00
parent 2cba72aeb0
commit b6a6f5b788
6 changed files with 100 additions and 79 deletions
+38 -34
View File
@@ -5,46 +5,50 @@ Rollender Übergabe-Log für agent-Threads. Workflow: `.agents/SKILL.md`
## Current focus ## Current focus
M1 (Index + Retrieval) und M2 (Ollama-Generierung + Grounding + API) sind M1 und M2 sind **fertig und gegen den echten Ollama validiert**.
implementiert. Ausstehend: Host-Validierung mit Ollama (Dense-Index, Offen: Modell-Bake-off (M3) mit den bereits installierten Kandidaten
Antwortmodus-Eval) und Modell-Bake-off (M3). Odoo-Integration (M4) ist und Prompt-Tuning der Fehlverweigerungen. Odoo-Integration (M4) separat
separat zu planen. zu planen.
## Completed (2026-09-14) ## Completed (2026-09-14)
- **Planung** (`planung.md`): Architektur, Grounding-Regeln, Modellfeld - **Planung** (`planung.md`): Architektur, Grounding-Regeln, Modellfeld,
(Bake-off: qwen3.8:27b primär, qwen3:32b, gemma3:27b, mistral-small3.2:24b, Meilensteine M1M4; **Skill** `.agents/skills/pv-rag-agent/SKILL.md`.
qwen3:14b als Latenz-Untergrenze), Meilensteine M1M4. - **Commits**: `25eb285` (Wissensbasis-Import), `bf8191b` (Planung +
- **Skill** `.agents/skills/pv-rag-agent/SKILL.md`: verbindliche Regeln für Skills), `2cba72a` (M1+M2-Implementierung, 41 Tests).
die Implementierung (Grounding, Architektur-Entscheidungen, Gates, - **Implementierung M1+M2** (`agent/`): kb/ingest/retrieve/generate/
Modellwechsel-Protokoll). ollama_client/api/cli/eval, Goldset 31 Fragen, Test-Chat.
- **Commits**: `25eb285` (Wissensbasis-Import 601 Layer-2-Einträge + - **Ollama-Anbindung verifiziert** (Ziel-Instanz `http://100.103.83.12:11435`,
.gitignore), `bf8191b` (Planung + Skills). Noch nicht gepusht — Remote Ollama 0.32.13): `bge-m3` per API gepullt; `qwen3.8:27b` war bereits
`http://localhost:3003/fegger/pv-agent.git` ist aus der Zed-Sandbox nicht installiert. Hybrid-Index: 3.005 Chunks, alle eingebettet (144 s).
erreichbar; User muss vom Host pushen. - **M1-Akzeptanz erreicht**: Retrieval Hybrid Hit-Rate 0,968 ·
- **Implementierung M1+M2** (`agent/`-Paket): kb.py (Parsing + kb.json-Gate), Recall@8 **0,952** (>0,9 ✓) · MRR 0,690 (BM25-only: 0,871/0,855/0,476).
ingest.py (3005 Chunks aus 601 Einträgen, FTS5 + Vektoren-Cache), - **M2-Antwortmodus-Eval** (qwen3.8:27b, Thinking aus): Zitier-Präzision
retrieve.py (Hybrid BM25+Dense/RRF, Stand-Boost, cross_ref-Erweiterung), **100 %** (4 Regenerierungen, alle geheilt) · Verweigerung korrekt
generate.py (Systemprompt, Post-Validierung, 1× Regenerierung, dann 94,3 % · erwartete Quelle zitiert 80,6 % · Latenz mean 32 s / p95 53 s.
Verweigerung), ollama_client.py (embed/chat, think-Flag-Fallback), Report: `data/eval-qwen38.json`.
api.py (/ask /health /reindex), cli.py, eval/ (Goldset 31 Fragen, - Der ATZ-Konfliktfall (28,5 vs. 27,5 %) wird korrekt mit ⚠ und beiden
evaluate.py), web/index.html, 41 offline Tests (grün). IDs beantwortet; harte Verweigerung (UStVA, Retrieval nicht leer)
- **Baseline BM25-only**: Hit-Rate 0,871 · Recall@8 0,855 · MRR 0,476 funktioniert.
(31 Fragen). 4 Fehltreffer: Komposita/Stamm-Schwächen (aliquotiert↔
Aliquotierung, Mindestlohngesetz) — Dense-Suche soll diese beheben.
## Open issues / blockers ## Open issues / blockers
- **Ollama aus Zed-Sandbox nicht erreichbar** (100.183.83.12:11435 und - **Push**: Remote localhost:3003 aus der Sandbox nicht erreichbar — User
localhost:3003 beide geblockt): Dense-Index, Antwortmodus-Eval und pusht vom Host.
Bake-off müssen auf dem Host laufen. Kommandos: `agent/README.md` - **Fehlverweigerungen**: q-008 (Abfertigung/Verfügungsmöglichkeiten),
Abschnitt „Deployment auf dem Host". q-031 (Mindestlohngesetz) — breite Fragen, Retrieval erfolgreich, Modell
- **Modelle noch nicht gepullt**: auf dem Host `ollama pull qwen3.8:27b`, verweigert. M3-Tuning: Regel-4-Formulierung lockern („behandle den
`ollama pull bge-m3` (plus Bake-off-Kandidaten). behandelten Teil“) oder Kontextblöcke erhöhen. Vorher Prompt einfrieren
- **Reranker** (bge-reranker-v2-m3): API-Unterstützung der installierten für den Bake-off-Vergleich.
Ollama-Version prüfen — Design funktioniert ohne. - **Latenz**: mean 32 s/ Antwort ist hoch (Dense 27B + große Prompts).
- **qwen3.8-Think-Parameter**: `think: false` wird im Request gesendet Hebel: weniger Kontextblöcke (aktuell 8+6), schnellere Kandidaten.
(Auto-Fallback ohne Flag bei 400/404); exaktes Verhalten am Host testen. - **Cloud-Modelle** (`*:cloud` auf der Ollama-Instanz) sind für Antworten
tabu (Anforderung: lokal). Nicht versehentlich konfigurieren.
- **Bake-off M3**: Kandidaten sind bereits installiert — `qwen3.8:27B`,
`qwen3.6:27B`, `gemma4:26b`, `mistral-small3.1:24b`, `gemma4:12B`
(Latenz-Untergrenze). Achtung: Plan nennt mistral-small3.**2**:24b —
installiert ist 3.1; 3.2 ggf. noch pullen oder 3.1 als Proxy.
Pro Kandidat: `PV_ANSWER_MODEL=<tag> python -m agent.cli eval --answers`.
- **M4 Odoo**: native LLM-Module des konkreten Odoo-19-Stands verifizieren - **M4 Odoo**: native LLM-Module des konkreten Odoo-19-Stands verifizieren
(keine API-Annahmen); Option A (dünnes Custom-Modul + Service-API) ist (keine API-Annahmen); Option A (dünnes Custom-Modul + Service-API) ist
Default. Default.
+5 -5
View File
@@ -39,11 +39,11 @@ touches Odoo code, also apply `.agents/odoo19-development/SKILL.md`.
## System context (fixed facts) ## System context (fixed facts)
- **Ollama server:** `http://100.183.83.12:11435` (custom port — do - **Ollama server:** `http://100.103.83.12:11435` — the target instance
not "correct" it to 11434). Verify reachability and installed models (custom port, holds the model zoo: qwen3.8:27b, bge-m3, bake-off
with `curl http://100.183.83.12:11435/api/tags`. Note: agent sandboxes candidates). The same host also runs a near-empty instance on port
may not reach this host — run such checks from the user's shell, not 11434 — do **not** "correct" the port to 11434. Verify with
the sandbox. `curl http://100.103.83.12:11435/api/tags`.
- **GPU:** AMD Radeon AI Pro R9700, 32 GB — keep the total resident - **GPU:** AMD Radeon AI Pro R9700, 32 GB — keep the total resident
budget (answer model + embeddings + KV cache) under ~28 GB. budget (answer model + embeddings + KV cache) under ~28 GB.
- **Models (provisional until bake-off, see protocol below):** - **Models (provisional until bake-off, see protocol below):**
+21 -14
View File
@@ -49,7 +49,7 @@ python -m agent.cli serve # http://127.0.0.1:8080 (/ask, /health, /r
| Variable | Default | Bedeutung | | Variable | Default | Bedeutung |
|---|---|---| |---|---|---|
| `OLLAMA_URL` | `http://100.183.83.12:11435` | Ollama-Server (Custom-Port!) | | `OLLAMA_URL` | `http://100.103.83.12:11435` | Ollama-Server (Ziel-Instanz; der Host betreibt zusätzlich eine fast leere Instanz auf 11434 — nicht "korrigieren") |
| `PV_ANSWER_MODEL` | `qwen3.8:27b` | Antwortmodell (provisorisch bis Bake-off M3) | | `PV_ANSWER_MODEL` | `qwen3.8:27b` | Antwortmodell (provisorisch bis Bake-off M3) |
| `PV_EMBED_MODEL` | `bge-m3` | Embedding-Modell | | `PV_EMBED_MODEL` | `bge-m3` | Embedding-Modell |
| `PV_DB_PATH` | `data/index.db` | SQLite-Index | | `PV_DB_PATH` | `data/index.db` | SQLite-Index |
@@ -62,25 +62,32 @@ python -m agent.cli serve # http://127.0.0.1:8080 (/ask, /health, /r
## Deployment auf dem Host (Ollama-Maschine) ## Deployment auf dem Host (Ollama-Maschine)
```bash ```bash
# Modelle einmalig pullen # Ollama-Ziel-Instanz prüfen (Custom-Port! Achtung: auf dem Host läuft
ollama pull qwen3.8:27b # zusätzlich eine fast leere Instanz auf 11434 — nicht verwexseln)
ollama pull bge-m3 curl http://100.103.83.12:11435/api/tags # qwen3.8:27b, bge-m3, Bake-off-Feld installiert
curl http://100.183.83.12:11435/api/tags # Erreichbarkeit + Modelle
# Vollständiger Index (BM25 + Dense) — danach eval, Ziel: Recall@8 > 0,9 # Vollständiger Index (BM25 + Dense)
python -m agent.cli ingest python -m agent.cli ingest
python -m agent.cli eval python -m agent.cli eval
python -m agent.cli eval --answers # Zitier-Präzision, Verweigerungen, Latenz python -m agent.cli eval --answers --json-out data/eval-report.json # Zitier-Präzision, Verweigerungen, Latenz
``` ```
## Baseline (2026-09-14, BM25-only, ohne Dense) ## Baseline (2026-09-14, Hybrid BM25 + bge-m3, Ollama :11435)
Goldset (31 Fragen, `agent/eval/goldset.yaml`): Hit-Rate 0,871 · **Retrieval** (Goldset, 31 Fragen): Hit-Rate 0,968 · **Recall@8 0,952** ·
Recall@8 0,855 · MRR 0,476. Die vier Fehltreffer sind klassische MRR 0,690 — M1-Ziel >0,9 erreicht (BM25-only war 0,855; die vier
BM25-Schwächen (Komposita: „aliquotiert"↔„Aliquotierung"; BM25-Fehltreffer behebt die Dense-Suche alle).
„Mindestlohngesetz") — genau die Fälle, die die Dense-Suche abdecken soll.
Hybrid-Messung auf dem Host aussteht (Ollama aus der Zed-Sandbox nicht **Antworten** (qwen3.8:27b, Thinking aus, Temperatur 0,1): **Zitier-Präzision
erreichbar). 100 %** (4 Zitierverletzungen wurden von der Post-Validierung abgefangen und
regeneriert) · Verweigerung korrekt 94,3 % · erwartete Quelle zitiert 80,6 %
· Latenz mean 32 s / p95 53 s.
Bekannte Fehlverweigerungen: q-008 (Abfertigung Verfügungsmöglichkeiten),
q-031 (Mindestlohngesetz) — breite Fragen, Retrieval erfolgreich, Modell
verweigert trotzdem (sicheres Versagensmuster; M3-Prompt-Tuning-Kandidat).
Latenz-Hebel für M3: weniger Kontextblöcke, schnellere Kandidaten
(gemma4:12B, MoE).
## Dateien ## Dateien
+4 -2
View File
@@ -37,8 +37,10 @@ class Config:
kb_dir: str = "wissensbasis" kb_dir: str = "wissensbasis"
db_path: str = "data/index.db" db_path: str = "data/index.db"
# Ollama (Custom-Port 11435 — nicht "korrigieren", s. Skill) # Ollama — Ziel-Instanz ist Port 11435 (Custom-Port, mit Modell-Zoo).
ollama_url: str = "http://100.183.83.12:11435" # Auf demselben Host läuft auch eine Instanz auf 11434 (fast leer) —
# NICHT auf 11434 "korrigieren", s. Skill.
ollama_url: str = "http://100.103.83.12:11435"
embed_model: str = "bge-m3" embed_model: str = "bge-m3"
answer_model: str = "qwen3.8:27b" # provisorisch bis Bake-off (M3) answer_model: str = "qwen3.8:27b" # provisorisch bis Bake-off (M3)
+6 -5
View File
@@ -38,8 +38,7 @@ Verbindliche Regeln:
5. Widersprechen sich Kontextblöcke, nenne beide Werte mit ihren IDs und 5. Widersprechen sich Kontextblöcke, nenne beide Werte mit ihren IDs und
kennzeichne den Widerspruch mit ⚠. Löse Widersprüche niemals stillschweigend auf. kennzeichne den Widerspruch mit ⚠. Löse Widersprüche niemals stillschweigend auf.
6. Nenne Paragraphen und Gesetze nur, wenn ein Kontextblock sie nennt. 6. Nenne Paragraphen und Gesetze nur, wenn ein Kontextblock sie nennt.
7. Antworte auf Deutsch, prägnant (Stichpunkte, wo sinnvoll), und füge am 7. Antworte auf Deutsch und prägnant (Stichpunkte, wo sinnvoll).
Ende eine Zeile „Quellen:“ mit den verwendeten IDs (ID — Titel, Stand) an.
Verletze Regel 2 oder Regel 4 niemals — im Zweifel verweigere die Antwort.""" Verletze Regel 2 oder Regel 4 niemals — im Zweifel verweigere die Antwort."""
@@ -123,14 +122,15 @@ def answer_question(
if own_retriever: if own_retriever:
retriever.close() retriever.close()
def finish(answer, refused, verified, citations, regenerations=0, draft=None): def finish(answer, refused, verified, citations, regenerations=0,
draft=None, sources=None):
return { return {
"question": question, "question": question,
"answer": answer, "answer": answer,
"refused": refused, "refused": refused,
"verified": verified, "verified": verified,
"citations": citations, "citations": citations,
"sources": _source_rows(results), "sources": sources if sources is not None else _source_rows(results),
"n_context": len(results), "n_context": len(results),
"model": cfg.answer_model, "model": cfg.answer_model,
"regenerations": regenerations, "regenerations": regenerations,
@@ -197,6 +197,7 @@ def answer_question(
citations=[], citations=[],
regenerations=regenerations, regenerations=regenerations,
draft=retry, draft=retry,
sources=[],
) )
citations = sorted(set(CITE_RE.findall(final))) citations = sorted(set(CITE_RE.findall(final)))
@@ -214,5 +215,5 @@ def answer_question(
] ]
return finish( return finish(
final, refused=refused, verified=not violations, final, refused=refused, verified=not violations,
citations=citations, regenerations=regenerations, citations=citations, regenerations=regenerations, sources=sources,
) )
+26 -19
View File
@@ -33,9 +33,10 @@ in weiterer Folge soll der Agent in Odoo-Enterprise verwendet werden.
- **Layer-1-Volltexte:** `.lexis360/md/` (572 Dateien) lokal vorhanden, - **Layer-1-Volltexte:** `.lexis360/md/` (572 Dateien) lokal vorhanden,
lizenzbeschränkt + unversioniert. `.wiku/` fehlt in diesem Checkout — lizenzbeschränkt + unversioniert. `.wiku/` fehlt in diesem Checkout —
für Phase A irrelevant (Retrieval läuft auf Layer 2). für Phase A irrelevant (Retrieval läuft auf Layer 2).
- **Ollama-Server** `http://100.183.83.12:11435` (Custom-Port): aus der - **Ollama-Server** `http://100.103.83.12:11435` (Ziel-Instanz mit Modell-Zoo,
Zed-Sandbox **nicht erreichbar** (Netzwerkrestriktion, Timeout) — ist Custom-Port; der Host betreibt zusätzlich eine fast leere Instanz auf 11434):
vom Host aus zu verifizieren (`curl http://100.183.83.12:11435/api/tags`). aus der Zed-Sandbox erreichbar (2026-09-14, nach URL-Korrektur) —
`bge-m3` wurde per API gepullt, `qwen3.8:27b` war bereits installiert.
- **GPU:** Radeon AI Pro R9700, 32 GB (Strix Halo / RDNA 5) — budgetiert - **GPU:** Radeon AI Pro R9700, 32 GB (Strix Halo / RDNA 5) — budgetiert
Modellwahl auf ~2628 GB nutzbar. Modellwahl auf ~2628 GB nutzbar.
@@ -198,9 +199,10 @@ tests/ # pytest: Ingest-, Retrieval-, Grounding-Unit-Tests
## 10. Risiken & offene Punkte ## 10. Risiken & offene Punkte
1. **Ollama-Erreichbarkeit** aus der Zed-Sandbox nicht gegeben — 1. **Ollama-Erreichbarkeit** gegeben (Ziel-Instanz 11435; Sandbox kann
Verifikation vom Host: `curl http://100.183.83.12:11435/api/tags`; verbinden). Achtung Doppel-Instanz auf 11434 — URL nicht "korrigieren".
Modelle ggf. erst pullen (`qwen3:32b`, `bge-m3`, …). Cloud-Modelle (`*:cloud`) nicht für Antworten verwenden (Anforderung:
lokal).
2. **Ollama-Version:** `/api/embed` + allfällige Rerank-Unterstützung 2. **Ollama-Version:** `/api/embed` + allfällige Rerank-Unterstützung
prüfen; Fallback ohne Reranker ist unkritisch. prüfen; Fallback ohne Reranker ist unkritisch.
3. **Strix Halo (gfx-1151):** Ollama/ROCm muss die Karte unterstützen 3. **Strix Halo (gfx-1151):** Ollama/ROCm muss die Karte unterstützen
@@ -233,16 +235,21 @@ tests/ # pytest: Ingest-, Retrieval-, Grounding-Unit-Tests
## 13. Umsetzungsstand (2026-09-14) ## 13. Umsetzungsstand (2026-09-14)
- **M1 erledigt (offline):** Ingest + Index (601 Einträge → 3.005 Chunks, - **M1 erledigt und akzeptiert:** Hybrid-Index (601 Einträge → 3.005 Chunks,
FTS5-BM25) + Hybrid-Retrieval (Dense-Code vorhanden, am Host zu messen). FTS5-BM25 + bge-m3-Dense, Ollama :11435), Goldset 31 Fragen. **Recall@8
Goldset 31 Fragen (IDs gegen kb.json verifiziert, inkl. ATZ-Konfliktfall 0,952 > 0,9** (Hit-Rate 0,968, MRR 0,690; BM25-only-Vergleich:
und 4 Verweigerungsfälle). Baseline BM25-only: Hit-Rate 0,871 · 0,855 — die vier Komposita-Fehltreffer behebt die Dense-Suche alle).
Recall@8 0,855 · MRR 0,476 — 4 Fehltreffer sind Komposita-/Stamm- 41 Unit-Tests grün.
Muster, die die Dense-Suche abdecken soll. 41 Unit-Tests grün. - **M2 erledigt und gegen das echte Modell validiert** (qwen3.8:27b,
- **M2 implementiert:** Ollama-Client (embed/chat, think-Fallback), Thinking aus): Zitier-Präzision **100 %** (4 Verletzungen → Post-
Systemprompt mit Zitierpflicht, Post-Validierung (1× Regenerierung, dann Validierung Regenerierung, alle geheilt), Verweigerung korrekt 94,3 %,
Verweigerung), `/ask`-API + CLI + Test-Chat. **Host-Validierung mit Latenz mean 32 s / p95 53 s. ATZ-Konfliktfall wird korrekt beidseitig
echtem Ollama noch offen** (aus der Zed-Sandbox nicht erreichbar). mit ⚠ beantwortet; harte Verweigerungsfälle (UStVA) funktionieren.
- **M3 offen:** Bake-off auf dem Host (qwen3.8:27b vs. qwen3:32b vs. - **M3 teilweise:** qwen3.8:27b-Baseline gemessen (`data/eval-qwen38.json`).
gemma3:27b vs. mistral-small3.2:24b; qwen3:14b als Latenz-Untergrenze). Bake-off-Kandidaten sind bereits installiert: qwen3.6:27B, gemma4:26b,
- Betrieb/Host-Schritte: `agent/README.md`. mistral-small3.1:24b, gemma4:12B (Latenz-Untergrenze). Bekannte
Fehlverweigerungen (q-008, q-031) und Latenz sind Tuning-Kandidaten —
Prompt für den Bake-off vorher einfrieren.
- **M4 offen:** Odoo-Integration (separater Plan nach Verifikation der
Odoo-19-LLM-Module).
- Betrieb: `agent/README.md`.