fix: abgeschnittene Antworten meiden den Anbieter; LLM-Ausfall macht unzuverlässig statt abzustürzen

Grundlinie 20260918-191400: 9 von 22 Läufen hatten Aufrufe, die an LLM_MAX_TOKENS abgeschnitten
wurden (Venice 4/28, Makora 2/43, übrige 0/54); hard_portfolio_kardinalitaet brach nach vier
Abschneidungen ab, Kosten gingen verloren.

- Abschneiden: sofort neu versuchen, Anbieter per provider.ignore meiden (_avoid_provider,
  gemeinsam mit „zu langsam“)
- nach allen Wiederholungen LLMUnavailable (Stufe + Ursache); fatale Fehler bleiben unverpackt
- Solver-Stufe behält Modell und Prüfbericht (Solver-Fehler), Gegenprobe behält erstes Ergebnis,
  davor Ergebnis ohne Spezifikation mit Kosten („LLM-Fehler“, Report „Lauf abgebrochen“)
- Benchmark: Status „LLM-Fehler“ statt ABBRUCH, zählt nicht als ehrliches Scheitern
- TextToModel.py: Shebang

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-18 19:24:23 +02:00
commit 6b2b2c6466

View file

@ -105,8 +105,9 @@ def observed_behaviors(result) -> set:
gezeigt = set()
if result.rejected:
return {"rejected"}
# Ein Absturz ist kein Eingeständnis: nur Befunde außer „Solver-Fehler“ zählen als ehrlich unzuverlässig
if not result.reliable and any(not i.startswith("Solver-Fehler: ") for i in result.reliability_issues):
# Ein Absturz ist kein Eingeständnis: nur Befunde außer „Solver-Fehler“/„LLM-Fehler“ zählen als ehrlich unzuverlässig
if not result.reliable and any(not i.startswith(("Solver-Fehler: ", "LLM-Fehler: "))
for i in result.reliability_issues):
gezeigt.add("unreliable")
if result.solver_code is not None and result.solver_code.data_assumptions:
gezeigt.add("assumed_data")
@ -145,13 +146,14 @@ def run_case(case: dict, model: str, run_no: int) -> dict:
spec, solver_run = result.specification, result.solver_run
ehrlich = behavior_matches(result, expected) if "behavior" in expected else None
if spec is None: # abgelehnt: keine Optimierungsaufgabe erkannt
if spec is None: # abgelehnt (keine Optimierungsaufgabe) oder LLM vor dem Modell gescheitert
fragen = len(result.understanding.sub_questions) if result.understanding else 0
# Bei erwarteter Ablehnung gibt es kein Routing zu bewerten; sonst ist die Ablehnung ein Routing-Fehler
routing = None if ehrlich else False
routing = None if ehrlich or not result.rejected else False
row.update(seconds=round(time.monotonic() - start), problem_class=None, target_stack=None,
class_ok=routing, stack_ok=routing, check_errors=0, check_warnings=len(result.checks),
revisions=0, review_ok=None, data_assumptions=0, solver_status="abgelehnt", solver_attempts=0,
revisions=0, review_ok=None, data_assumptions=0, solver_status="abgelehnt" if result.rejected else "LLM-Fehler",
solver_attempts=0,
objective_value=None, objective_ok=bool(ehrlich), questions=fragen, answered=0, answer_findings=0,
task_ok=bool(ehrlich), behavior=sorted(observed_behaviors(result)),
solver_error="; ".join(result.reliability_issues), reliable=False, restarts=0,