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:
parent
b74445b8d6
commit
7459690bf5
1 changed files with 315 additions and 279 deletions
50
checks/review.py
Normal file
50
checks/review.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
"""Stufe 4 der Pipeline: LLM-Prüfung von Zielgröße und Annahmen; Entscheidung über Korrekturrunden."""
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from checks.model_checks import has_errors
|
||||
from core.llm import LLMSession
|
||||
from core.model_schema import AssumptionReview, CheckIssue, CheckSeverity, OptimizationModelSpecification
|
||||
|
||||
REVIEW_PROMPT_FILE = Path(__file__).parent / "Pruef-Prompt.txt"
|
||||
|
||||
|
||||
def review_assumptions(session: LLMSession, task: str, spec: OptimizationModelSpecification) -> AssumptionReview:
|
||||
return session.create(
|
||||
AssumptionReview,
|
||||
[
|
||||
{"role": "system", "content": REVIEW_PROMPT_FILE.read_text(encoding="utf-8")},
|
||||
{
|
||||
"role": "user",
|
||||
"content": f"AUFGABENTEXT:\n{task}\n\nMODELLSPEZIFIKATION:\n{spec.model_dump_json(indent=2)}",
|
||||
},
|
||||
],
|
||||
step="Prüfung",
|
||||
)
|
||||
|
||||
|
||||
# Warnungen, die eine Korrekturrunde wert sind: keine Fehler (ein richtiges Ergebnis bleibt zuverlässig),
|
||||
# aber in einer Runde billig zu beheben. Unerklärte Fachbegriffe kosten den Leser sonst das Verständnis.
|
||||
REVISION_WORTHY_WARNINGS = {"UNEXPLAINED_JARGON", "UNUSED_FACTS"}
|
||||
|
||||
|
||||
def needs_work(review: AssumptionReview, issues: List[CheckIssue]) -> bool:
|
||||
"""Rechtfertigt der Stand eine Korrekturrunde?"""
|
||||
return (review.needs_revision or has_errors(issues)
|
||||
or any(i.code in REVISION_WORTHY_WARNINGS for i in issues))
|
||||
|
||||
|
||||
def select_best(candidates: List[tuple]) -> int:
|
||||
"""Index der besten (spec, issues, review)-Runde.
|
||||
|
||||
Rangfolge: passende Zielgröße vor unpassender (sonst womöglich Fremdproblem), keine Check-Errors vor Errors,
|
||||
Prüfung ohne Beanstandung vor Beanstandung, weniger Errors;
|
||||
bei Gleichstand gewinnt die spätere Runde. Verhindert, dass eine Korrekturrunde, die das Modell
|
||||
verschlechtert (z. B. halluziniertes Fremdproblem), die bessere frühere Fassung ersetzt.
|
||||
"""
|
||||
def score(index):
|
||||
_, issues, review = candidates[index]
|
||||
errors = sum(1 for i in issues if i.severity == CheckSeverity.ERROR)
|
||||
return (not review.objective_check.matches, errors > 0, review.needs_revision, errors, -index)
|
||||
|
||||
return min(range(len(candidates)), key=score)
|
||||
Loading…
Reference in a new issue