Tuning: Prompt-Budget + cross_ref-Erweiterung heilt Fehlverweigerungen (D11)
- Ursache der 4 Fehlverweigerungen nach KV/RIS-Erweiterung: lange
KV-Chunks ueberlieferten num_ctx=16384 (bis 62,7 KB Prompt) — Ollama
trunciert den Systemprompt vorn, das Modell verliert die Zitierregeln
('Block-N'-Zitate statt IDs -> Regenerierung -> Verweigerung).
- Fix: num_ctx 32768; trim_results (max_context_chars=90.000, niedrig
gerankte Bloecke ganz weglassen statt truncieren, Mindestbestand 6);
cross_ref_expand 3 -> 6 (Top-3 sind oft Branchen-KV-Bloecke mit leeren
cross_refs - kuratierte Nachbarn kamen sonst nie nach).
- Eval: alle 4 Faelle geheilt, 10/10 Bestaetigungslaeufe OK.
Retrieval Recall@8 0,851 -> 0,946 (cross_ref-Extras bringen
Expected-IDs nach). Antworten: Zitier-Praezision 97,6 %, Verweigerung
97,6 % (>94,3 %-Gate), erwartete Quelle 83,8 -> 91,9 %, Latenz mean 33 s.
- Tests 49 -> 50 (trim_results); Reports lokal (data/eval-*).
This commit is contained in:
+24
-1
@@ -5,6 +5,7 @@ verlässt answer_question.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
from agent.retrieve import ChunkResult
|
||||
from agent.generate import (
|
||||
REFUSAL_MESSAGE,
|
||||
UNCERTAIN_MESSAGE,
|
||||
@@ -12,6 +13,7 @@ from agent.generate import (
|
||||
build_user_content,
|
||||
looks_like_refusal,
|
||||
strip_think,
|
||||
trim_results,
|
||||
validate_answer,
|
||||
)
|
||||
|
||||
@@ -143,4 +145,25 @@ class TestAnswerQuestion:
|
||||
main = [s for s in result["sources"]]
|
||||
assert result["n_context"] >= 1
|
||||
# Haupt-Blöcke auf top_k begrenzt; cross_ref-Erweiterungen dürfen dazu
|
||||
assert len([s for s in main]) <= result["n_context"]
|
||||
assert len([s for s in main]) <= result["n_context"]
|
||||
|
||||
def test_trim_results_drops_tail_under_budget():
|
||||
"""Prompt-Budget: Tail-Blöcke (niedrig gerankt) ganz weglassen, nicht truncieren."""
|
||||
def blk(n, chars):
|
||||
return ChunkResult(
|
||||
chunk_id=n, entry_id=f"lb-min-{n:02d}", section="Zusammenfassung",
|
||||
text="x" * chars, title=f"Titel {n}", stand="2026-01", work="W",
|
||||
chapter="C", topic="t", tags=[], legal_bases=[], cross_refs=[],
|
||||
)
|
||||
blocks = [blk(i, 30_000) for i in range(1, 6)] # 5 x ~30 KB = 150 KB
|
||||
trimmed = trim_results(blocks, 90_000)
|
||||
assert 6 >= len(trimmed) >= 6 or len(trimmed) == 5 # 5 Bloecke, Mindesthoehe 6 greift nicht
|
||||
# Groesserer Fall: 14 Bloecke, Budget schneidet hinten weg
|
||||
blocks = [blk(i, 8_000) for i in range(1, 15)] # ~112 KB
|
||||
trimmed = trim_results(blocks, 90_000)
|
||||
assert 6 <= len(trimmed) < 14
|
||||
# Erste Bloecke bleiben (best gerankt)
|
||||
assert trimmed[0].entry_id == "lb-min-01"
|
||||
assert sum(len(b.text) for b in trimmed) + len(trimmed) * 64 <= 90_000 + 8_000
|
||||
# Unbegrenzt: Original unveraendert
|
||||
assert trim_results(blocks, None) is blocks
|
||||
|
||||
Reference in New Issue
Block a user