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
1 changed files with 484 additions and 36 deletions
|
|
@ -301,6 +301,27 @@ def _fmt_number(value) -> str:
|
|||
return str(value)
|
||||
|
||||
|
||||
def _figure_blocks(result: PipelineResult) -> list:
|
||||
"""Abbildungen der Aufgabe: Original neben der Übertragung, mit der die Pipeline gerechnet hat."""
|
||||
if not result.figures:
|
||||
return []
|
||||
uebertragen = {f.id: f for f in (result.understanding.figures if result.understanding else [])}
|
||||
doc = [("h3", "Abbildungen"),
|
||||
("p", "Die Pipeline rechnet nicht mit dem Bild, sondern mit seiner Übertragung in Text. "
|
||||
"Bitte Original und Übertragung vergleichen – ein verlesener Wert ändert das ganze Ergebnis.")]
|
||||
for figur in result.figures:
|
||||
doc.append(("h4", figur.id + (f" – {figur.alt}" if figur.alt and figur.alt.lower() != "image" else "")))
|
||||
doc.append(("img", f"data:{figur.mime};base64,{figur.data}", figur.id))
|
||||
t = uebertragen.get(figur.id)
|
||||
if t is None:
|
||||
doc.append(("warn", f"{figur.id} wurde nicht übertragen – ihre Inhalte fehlen im Modell."))
|
||||
continue
|
||||
doc += [("p", f"Übertragung: {t.shows}"), ("pre", t.transcription.strip())]
|
||||
if t.uncertain:
|
||||
doc.append(("warn", f"{figur.id} – unsicher gelesen: " + "; ".join(t.uncertain)))
|
||||
return doc
|
||||
|
||||
|
||||
def _rejected_document(result: PipelineResult) -> list:
|
||||
"""Abgelehnte Aufgabe: Grund und Aufgabentext – kein Modell, keine Zahlen."""
|
||||
grund = result.understanding.reason if result.understanding else "; ".join(result.reliability_issues)
|
||||
|
|
@ -311,7 +332,7 @@ def _rejected_document(result: PipelineResult) -> list:
|
|||
doc.append(("list", [f"Erstellt: {datetime.now():%d.%m.%Y %H:%M}", f"Modell: {result.usage.model}",
|
||||
f"LLM: {result.usage.calls} Aufrufe{cost}"]))
|
||||
if result.task.strip():
|
||||
doc += [("h2", "Aufgabe"), ("pre", result.task.strip())]
|
||||
doc += [("h2", "Aufgabe"), ("pre", result.task.strip())] + _figure_blocks(result)
|
||||
return doc
|
||||
|
||||
|
||||
|
|
@ -342,7 +363,7 @@ def build_document(result: PipelineResult, model: str = "") -> list:
|
|||
doc += _result_section(result)
|
||||
|
||||
if result.task.strip():
|
||||
doc += [("h2", "Aufgabe"), ("pre", result.task.strip())]
|
||||
doc += [("h2", "Aufgabe"), ("pre", result.task.strip())] + _figure_blocks(result)
|
||||
|
||||
if result.data_files:
|
||||
doc += [("h2", "Beigelegte Daten")]
|
||||
|
|
@ -468,6 +489,8 @@ def to_markdown(doc: list) -> str:
|
|||
out.append(f"**{_md_inline(block[1])}**")
|
||||
elif kind == "svg":
|
||||
pass # Diagramme nur im HTML-Report
|
||||
elif kind == "img":
|
||||
out.append(f"![{block[2]}]({block[1]})")
|
||||
elif kind == "list":
|
||||
out.append("\n".join(f"- {_md_inline(item)}" for item in block[1]))
|
||||
elif kind == "math":
|
||||
|
|
@ -591,6 +614,9 @@ def to_html(doc: list) -> str:
|
|||
out.append(f'<p class="lead">{_html_inline(block[1])}</p>')
|
||||
elif kind == "svg":
|
||||
out.append(f'<figure class="viz-root">{block[1]}</figure>')
|
||||
elif kind == "img":
|
||||
out.append(f'<figure><img src="{html.escape(block[1], quote=True)}" alt="{html.escape(block[2])}" '
|
||||
f'style="max-width:100%"><figcaption>{html.escape(block[2])}</figcaption></figure>')
|
||||
elif kind == "list":
|
||||
out.append("<ul>" + "".join(f"<li>{_html_inline(item)}</li>" for item in block[1]) + "</ul>")
|
||||
elif kind == "math":
|
||||
|
|
|
|||
Loading…
Reference in a new issue