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