feat: Aufgaben mit Abbildungen (docling-Markdown), mit Gegenprobe beim Ablesen
Eingebettete Base64-Bilder und Bilddateien werden aus dem Aufgabentext gelöst und nur der Verstehensstufe als Bild übergeben; sie überträgt jede Abbildung in Text. Eine zweite, unabhängige Lesung wird Zahl für Zahl verglichen (bei Abweichung entscheidet eine dritte, sonst reliable=False). Alle weiteren Stufen rechnen mit der Übertragung, der Report zeigt Original und Übertragung nebeneinander. LLM_MODEL_UNDERSTANDING wählt das Bildmodell. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
915c79c1c8
commit
b07dd16143
2 changed files with 484 additions and 36 deletions
|
|
@ -18,6 +18,8 @@ DEFAULT_MODEL = os.environ.get("LLM_MODEL", "deepseek/deepseek-v4.1-flash")
|
|||
# Modell je Pipeline-Stufe: ein starkes Modell für Extraktion/Prüfung, ein schnelles für den Solver-Code
|
||||
# (oder umgekehrt, je nach Messung). Leer = das Modell der Session (LLM_MODEL bzw. --model).
|
||||
STEP_MODEL_ENV = {
|
||||
"Verstehen": "LLM_MODEL_UNDERSTANDING", # muss Bilder lesen können, wenn die Aufgabe Abbildungen hat
|
||||
"Abbildungen": "LLM_MODEL_UNDERSTANDING",
|
||||
"Extraktion": "LLM_MODEL_EXTRACTION",
|
||||
"Prüfung": "LLM_MODEL_REVIEW",
|
||||
"Korrektur": "LLM_MODEL_REVISION",
|
||||
|
|
|
|||
|
|
@ -118,6 +118,32 @@ class IgnoredNumber(BaseModel):
|
|||
"'Teil der Einheit (in 1000 Stunden)', 'Seitenzahl'")
|
||||
|
||||
|
||||
class FigureInput(BaseModel):
|
||||
"""Eine Abbildung der Aufgabe (eingebettet als Base64 oder als Bilddatei) – Bilddaten, kein LLM-Feld."""
|
||||
id: str
|
||||
alt: str = ""
|
||||
mime: str
|
||||
data: str = Field(description="Bildinhalt als Base64")
|
||||
source: str = Field(default="eingebettet", description="'eingebettet' oder der Pfad der Bilddatei")
|
||||
|
||||
|
||||
class FigureTranscription(BaseModel):
|
||||
"""Eine Abbildung, vollständig in Text übertragen – danach arbeitet die Pipeline nur noch mit diesem Text."""
|
||||
id: str = Field(description="Kennung wie im Text, z. B. 'Abbildung 1'")
|
||||
shows: str = Field(description="Was die Abbildung zeigt, in einem Satz (z. B. 'gerichteter Graph mit 4 Knoten')")
|
||||
transcription: str = Field(
|
||||
description="Vollständige Übertragung ALLER Inhalte: jede Zahl, jede Beschriftung, jede Pfeilrichtung, "
|
||||
"am besten als Tabelle oder Liste (z. B. 'Pfeil 1→2: 3'). Nichts ergänzen, was nicht zu sehen ist.")
|
||||
uncertain: List[str] = Field(
|
||||
default_factory=list,
|
||||
description="Stellen, die nicht sicher lesbar sind (verdeckt, unscharf, mehrdeutig); leer = alles sicher gelesen")
|
||||
|
||||
|
||||
class FigureReading(BaseModel):
|
||||
"""Unabhängige zweite Übertragung der Abbildungen – Gegenprobe zur Verstehensstufe."""
|
||||
figures: List[FigureTranscription]
|
||||
|
||||
|
||||
class TaskUnderstanding(BaseModel):
|
||||
"""Was in der Aufgabe steht – vor jeder Modellierung: Fragen, Zahlen, Machbarkeit."""
|
||||
is_optimization_task: bool = Field(
|
||||
|
|
@ -129,6 +155,9 @@ class TaskUnderstanding(BaseModel):
|
|||
facts: List[Fact] = Field(description="Alle Zahlenwerte des Textes, die Eingabegrößen des Modells sind")
|
||||
ignored_numbers: List[IgnoredNumber] = Field(
|
||||
default_factory=list, description="Zahlen im Text, die keine Eingabegrößen sind, mit Begründung")
|
||||
figures: List[FigureTranscription] = Field(
|
||||
default_factory=list,
|
||||
description="Nur wenn der Aufgabe Abbildungen beiliegen: je Abbildung eine vollständige Übertragung; sonst leer")
|
||||
|
||||
|
||||
class ObjectiveDefinition(BaseModel):
|
||||
|
|
@ -430,6 +459,8 @@ class LLMUsage(BaseModel):
|
|||
|
||||
class PipelineResult(BaseModel):
|
||||
task: str = ""
|
||||
figures: List[FigureInput] = Field(
|
||||
default_factory=list, description="Abbildungen der Aufgabe; ihre Übertragung steht im Aufgabentext (task)")
|
||||
data_files: List[DataFileProfile] = Field(
|
||||
default_factory=list, description="Profile der beigelegten Datendateien (--daten)")
|
||||
understanding: Optional[TaskUnderstanding] = Field(
|
||||
|
|
|
|||
Loading…
Reference in a new issue