refactor: Pipeline-Stufen in Ordner mit ihren Prompts

Im Wurzelverzeichnis liegt nur noch TextToModel.py (Ablauf und CLI).
Jede Stufe liegt mit Code und Prompt in einem eigenen Ordner: core,
understanding, modeling, checks, solving, reporting, data, benchmark;
Tests unter tests/, Aufgaben unter tasks/. understand_task,
text_to_model/revise_model und review_assumptions/needs_work/select_best
sind aus TextToModel.py zu ihren Prompts gewandert, inhaltlich
unveraendert. Prompt-Kennung des Benchmarks bleibt 93744636095a.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-09-17 12:11:51 +02:00
commit 7459690bf5

68
modeling/extraction.py Normal file
View file

@ -0,0 +1,68 @@
"""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] = (),
) -> 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"
return session.create(
OptimizationModelSpecification,
[
{"role": "system", "content": ROUTING_PROMPT_FILE.read_text(encoding="utf-8")},
{
"role": "user",
"content": (
f"AUFGABENTEXT:\n{task}\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",
)