text_to_solver_program/modeling/extraction.py
dschlueter 3c4d2fb92c fix: Nebenpfade behalten Kontext – Gegenprobe, --von, --resolve, UNDERSTAND_RETRIES=-1
- UNDERSTAND_RETRIES=-1 (A/B-Arm der Verstehensstufe) stürzte seit dem Ablehnungstor ab
- Unlösbar-Gegenprobe bekommt Verständnis, Datenprofil und Datendateien; ihre Lösung
  durchläuft dieselbe Abnahme (_assess_run)
- --von pruefung behält Verständnis, Abbildungen und Datenprofil
- --resolve überschreibt frühere Befunde nicht mehr (nur Zulässigkeit neu)
- --daten wirkt auch mit --resolve und --von
- Prüfung und Korrektur sehen das Datenprofil
- Reparaturmeldung nennt alle Befundarten zugleich
- Test der Balkenhöhe prüft die Höhe tatsächlich; unbenutzte Imports entfernt

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 13:22:53 +02:00

69 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Stufen 2 und 5 der Pipeline: Modellspezifikation aus dem Text extrahieren und nach der Prüfung korrigieren."""
from pathlib import Path
from typing import List
from core.llm import LLMSession
from core.model_schema import (
AssumptionReview,
CheckIssue,
CheckSeverity,
OptimizationModelSpecification,
TaskUnderstanding,
)
ROUTING_PROMPT_FILE = Path(__file__).parent / "Routing-und-Extraktions-Prompt.txt"
def text_to_model(session: LLMSession, task: str,
understanding: TaskUnderstanding | None = None,
data_prompt: str = "") -> OptimizationModelSpecification:
inhalt = task if not data_prompt else f"{task}\n\n{data_prompt}"
if understanding is not None:
# Die Verstehensstufe hat Teilfragen und Zahlen schon erfasst – die Extraktion muss den Text
# nicht noch einmal danach absuchen, sondern baut darauf auf.
inhalt += ("\n\nBEREITS ERFASSTES VERSTÄNDNIS (Teilfragen und Zahlen; übernimm die Werte aus facts "
"in extracted_values, statt sie neu zu suchen):\n" + understanding.model_dump_json(indent=2))
return session.create(
OptimizationModelSpecification,
[
{"role": "system", "content": ROUTING_PROMPT_FILE.read_text(encoding="utf-8")},
{"role": "user", "content": inhalt},
],
step="Extraktion",
)
def revise_model(
session: LLMSession, task: str, spec: OptimizationModelSpecification, review: AssumptionReview,
issues: List[CheckIssue] = (), data_prompt: str = "",
) -> OptimizationModelSpecification:
errors = [i for i in issues if i.severity == CheckSeverity.ERROR]
check_text = "\n".join(f"- [{i.code}] {i.message}" for i in errors) or "keine"
# Warnungen lösen für sich keine Korrekturrunde aus; findet aber ohnehin eine statt,
# sollen sie mit behoben werden – sonst erreicht z. B. unerklärter Fachjargon das LLM nie.
hinweise = [i for i in issues if i.severity == CheckSeverity.WARNING]
hinweis_text = "\n".join(f"- [{i.code}] {i.message}" for i in hinweise) or "keine"
aufgabe = f"{task}\n\n{data_prompt}" if data_prompt else task # Datenprofil wie bei der Extraktion
return session.create(
OptimizationModelSpecification,
[
{"role": "system", "content": ROUTING_PROMPT_FILE.read_text(encoding="utf-8")},
{
"role": "user",
"content": (
f"AUFGABENTEXT:\n{aufgabe}\n\n"
f"BISHERIGE MODELLSPEZIFIKATION:\n{spec.model_dump_json(indent=2)}\n\n"
f"PRÜFBERICHT:\n{review.model_dump_json(indent=2)}\n\n"
f"FEHLER DER AUTOMATISCHEN KONSISTENZPRÜFUNG:\n{check_text}\n\n"
f"HINWEISE DER AUTOMATISCHEN PRÜFUNG (kein Fehler, aber zu verbessern):\n{hinweis_text}\n\n"
"Überarbeite die Modellspezifikation: Setze alle Korrekturen aus dem Prüfbericht um, "
"behebe alle Fehler der Konsistenzprüfung, passe die betroffenen Restriktionen, Variablen "
"und Parameter an und weise fehlende Annahmen in open_assumptions aus. "
"Arbeite auch die Hinweise ab, soweit das Modell dadurch nicht schlechter wird – "
"unerklärte Fachbegriffe gehören in executive_summary, nicht weggelassen. "
"Behalte korrekte Teile unverändert bei."
),
},
],
step="Korrektur",
)