This commit is contained in:
team3
2026-06-17 11:54:45 +02:00
parent e8214598ea
commit 390ec12bbf
5 changed files with 69 additions and 25 deletions

View File

@@ -25,6 +25,7 @@ MEISTERN = 25 # Score bis "gemeistert" (Tier 3, Maximum)
VERTIEFUNG_TIMEOUT = 600
CHAT_TIMEOUT = 240
PRUEFUNG_TIMEOUT = 120 # kurze JSON-Turns; deckelt die Serien-Latenz pro Prüfungs-Schritt
GRUENDLICH_TIMEOUT = 600 # „Gründlich prüfen": starkes Modell (role guide) braucht länger
KRITIK_MAX_RUNDEN = 2 # Generator → Kritiker → ggf. Neu, höchstens so oft
@@ -137,21 +138,21 @@ def _bewertung_schema(data) -> dict | None:
return {"feedback": feedback, "bewertung": bewertung, "bestanden": data.get("bestanden") is True}
async def _gen_call(name: str, role: str, schema, provider: str, **kwargs) -> dict | None:
async def _gen_call(name: str, role: str, schema, provider: str, timeout: int = PRUEFUNG_TIMEOUT, **kwargs) -> dict | None:
"""Generator-Agent: Template füllen, laufen lassen, per schema parsen · None bei Fehler."""
returncode, stdout, _ = await run_agent(
name.lower() + "-" + str(uuid.uuid4()), _prompt(name, **kwargs), PRUEFUNG_TIMEOUT,
name.lower() + "-" + str(uuid.uuid4()), _prompt(name, **kwargs), timeout,
provider=provider, role=role, capabilities="none", lane="interactive",
)
return schema(_parse_json_text(stdout)) if returncode == 0 else None
async def _kritik_call(name: str, provider: str, **kwargs) -> list[str]:
"""Kritiker-Agent (role judge): leere Liste = in Ordnung. Fail-open: Ausfall des
async def _kritik_call(name: str, provider: str, role: str = "judge", timeout: int = PRUEFUNG_TIMEOUT, **kwargs) -> list[str]:
"""Kritiker-Agent (Default role judge): leere Liste = in Ordnung. Fail-open: Ausfall des
Kritikers darf den Turn nicht blockieren, also dann ebenfalls leere Liste."""
returncode, stdout, _ = await run_agent(
name.lower() + "-" + str(uuid.uuid4()), _prompt(name, **kwargs), PRUEFUNG_TIMEOUT,
provider=provider, role="judge", capabilities="none", lane="interactive",
name.lower() + "-" + str(uuid.uuid4()), _prompt(name, **kwargs), timeout,
provider=provider, role=role, capabilities="none", lane="interactive",
)
if returncode != 0:
return []
@@ -199,18 +200,20 @@ async def _frage_mit_kritik(
async def _bewertung_mit_kritik(
topic: str, baustein: str, section_block: str, vertiefung_block: str,
frage: str, transcript: str, gute_antworten: int, provider: str,
frage: str, transcript: str, gute_antworten: int, provider: str, role: str = "judge",
) -> dict | None:
"""Antwort bewerten (gut/schlecht), vom Kritiker prüfen lassen, bei Fehlurteil neu.
`frage` ankert die geprüfte Frage; der Dialog (transcript) liefert die Antwort und
eine etwaige Diskussion — so kann eine Re-Bewertung das Argument sehen.
`role` = "judge" (schnell) oder "guide" (gründlich, starkes Modell mit Thinking).
"""
timeout = GRUENDLICH_TIMEOUT if role == "guide" else PRUEFUNG_TIMEOUT
kritik_block = "(keine)"
bew = None
for _ in range(KRITIK_MAX_RUNDEN):
bew = await _gen_call(
"Baustein-Bewertung", "judge", _bewertung_schema, provider,
"Baustein-Bewertung", role, _bewertung_schema, provider, timeout,
topic=topic, baustein=baustein, section_block=section_block,
vertiefung_block=vertiefung_block, frage=frage, transcript=transcript,
gute_antworten=gute_antworten, noetig=NOETIG, kritik_block=kritik_block,
@@ -218,7 +221,7 @@ async def _bewertung_mit_kritik(
if bew is None:
return None
probleme = await _kritik_call(
"Baustein-Bewertung-Kritik", provider,
"Baustein-Bewertung-Kritik", provider, role=role, timeout=timeout,
topic=topic, baustein=baustein, section_block=section_block,
vertiefung_block=vertiefung_block, frage=frage, transcript=transcript,
bewertung_block=_bewertung_text(bew),
@@ -253,9 +256,11 @@ async def pruefung_frage(
async def pruefung_bewertung(
topic: str, baustein: str, section: str, vertiefung: str | None,
frage: str, messages: list[dict], gute_antworten: int, provider: str = DEFAULT_PROVIDER,
role: str = "judge",
) -> dict | None:
"""Aktion 'antwort_pruefen': verbindlich bewerten (Evaluator + Kritiker).
`role` = "guide" für „Gründlich prüfen" (starkes Modell), sonst "judge".
Gibt {"feedback", "bewertung": gut|schlecht, "bestanden"} · None bei Fehler.
"""
try:
@@ -263,7 +268,7 @@ async def pruefung_bewertung(
transcript = _transcript(messages) if messages else "(leer)"
return await _bewertung_mit_kritik(
topic, baustein, section_block, vertiefung_block,
frage.strip() or "(keine Frage übergeben)", transcript, gute_antworten, provider,
frage.strip() or "(keine Frage übergeben)", transcript, gute_antworten, provider, role,
)
except Exception:
log.warning("[%s] Bewertung fehlgeschlagen (%s)", topic, baustein, exc_info=True)