fix: Vergleichstabellen nicht als Summenabweichung melden; Verstehen-Prompt in Prompt-Kennung

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-17 13:34:54 +02:00
commit 7aac3ff3ec
4 changed files with 40 additions and 2 deletions

View file

@ -26,9 +26,10 @@ RESULTS_DIR = BENCHMARK_DIR / "results"
# Nach dem ersten fatalen API-Fehler (Kontingent/Guthaben/Key) keine weiteren Läufe starten
quota_exhausted = threading.Event()
# Dateien, die das LLM-Verhalten steuern: die drei System-Prompts und die Feldbeschreibungen
# Dateien, die das LLM-Verhalten steuern: die vier System-Prompts und die Feldbeschreibungen
# (Field(description=...) geht als JSON-Schema mit und wirkt wie eine Prompt-Anweisung).
PROMPT_FILES = ("modeling/Routing-und-Extraktions-Prompt.txt", "checks/Pruef-Prompt.txt", "solving/Solver-Prompt.txt",
PROMPT_FILES = ("understanding/Verstehen-Prompt.txt", "modeling/Routing-und-Extraktions-Prompt.txt", "checks/Pruef-Prompt.txt",
"solving/Solver-Prompt.txt",
"core/model_schema.py")
# Umgebungsvariablen, die das Verhalten ändern – ohne sie ließe sich ein A/B-Lauf nicht zuordnen

View file

@ -271,6 +271,17 @@ def _is_sum_row(row, value=None, others=None) -> bool:
return _close(value, sum(others))
def _is_comparison(values, no_sum_row: bool, total: float, objective_value) -> bool:
"""Vergleichstabelle: jede Zeile ist ein eigener Zielwert (Konfiguration, Szenario), keine Zerlegung.
Erkennbar daran, dass die Summe nicht passt, aber genau eine Zeile den gemeldeten Zielwert trägt.
Beobachtet: "Vergleich der Konfigurationen" (Portfolio Nr. 2) galt sonst als "Summe weicht ab".
"""
if objective_value is None or not no_sum_row or len(values) < 2 or _close(total, objective_value):
return False
return sum(_close(v, objective_value) for v in values) == 1
def _close(a: float, b: float) -> bool:
return abs(a - b) <= 1e-3 * max(abs(a), abs(b)) + 1e-6
@ -303,6 +314,8 @@ def parse_result_tables(raw_tables: list, objective_value) -> tuple:
warnings.append(f"Tabelle '{table.title}': Spalte '{table.objective_column}' enthält nicht nur Zahlen – Summe nicht prüfbar.")
continue
total = sum(values)
if _is_comparison(values, len(values) == len(cells), total, objective_value):
continue
if objective_value is not None and not _close(total, objective_value):
warnings.append(
f"Tabelle '{table.title}': Summe der Spalte '{table.objective_column}' ({total:.6g}) "

View file

@ -309,6 +309,7 @@ def test_benchmark_records_the_prompt_state():
assert len(stand["prompts"]) == 12 and stand["commit"]
assert "modeling/Routing-und-Extraktions-Prompt.txt" in PROMPT_FILES
assert "core/model_schema.py" in PROMPT_FILES # Feldbeschreibungen wirken wie Prompt-Anweisungen
assert "understanding/Verstehen-Prompt.txt" in PROMPT_FILES
def test_deviating_settings_are_recorded(monkeypatch):

View file

@ -228,3 +228,26 @@ def test_ascii_form_present_in_the_task_is_not_replaced():
zuordnung = umlaut_map("Herr Müller und die Firma Mueller liefern.")
assert "mueller" not in zuordnung
assert fix_transliterations("Firma Mueller", zuordnung) == "Firma Mueller"
# beobachtet in Portfolio Nr. 2: eine Zeile je Konfiguration, die gewählte trägt den Zielwert
COMPARISON = {
"title": "Vergleich der Konfigurationen",
"columns": ["Konfiguration", "lambda1", "lambda2", "Zielfunktionswert"],
"rows": [["Reine Varianzminimierung", "1.0", "0.0", 0.18217355],
["Reine Korrelationsminimierung", "0.0", "1.0", -187.29514112],
["Ausgewogene Skalarisierung", "0.5", "0.5", -93.56364364]],
"objective_column": "Zielfunktionswert",
}
def test_comparison_table_is_not_a_sum_mismatch():
tables, warnings = parse_result_tables([COMPARISON], objective_value=0.18217353985482126)
assert warnings == [] and len(tables) == 1
def test_decomposition_with_one_term_equal_to_objective_is_still_checked():
# eine Summenzeile macht daraus eine Zerlegung – deren Fehler bleibt sichtbar
table = dict(DECOMPOSITION, rows=[["Rendite", 0.097557], ["Kosten", -0.05], ["Zielwert", 0.2]])
_, warnings = parse_result_tables([table], objective_value=0.097557)
assert any("weicht vom Zielwert" in w for w in warnings)