This commit is contained in:
team3
2026-07-12 16:13:50 +02:00
parent a284e03225
commit 31a42bbf1d
48 changed files with 3625 additions and 253 deletions

View File

@@ -9,6 +9,7 @@ import logging
import artefakte
import db
import diagramme
import guide
import inventar
import korpus
@@ -18,7 +19,7 @@ import struktur
log = logging.getLogger("creator2.qa")
MODULE = {"korpus": korpus, "inventar": inventar, "artefakte": artefakte,
"struktur": struktur, "guide": guide}
"struktur": struktur, "diagramme": diagramme, "guide": guide}
# Gewichte je Befund-Art: kritisch 3.0 (verletzt Kernprinzip), mittel 1.5, stil 0.5.
GEWICHTE = {
@@ -32,7 +33,9 @@ GEWICHTE = {
"kapitel_zerstueckelt": 1.5, "titel_katalog": 1.5, "quelle_unvollstaendig": 3.0,
"section_fehlt": 3.0, "marker_fehlend": 3.0, "marker_fremd": 3.0,
"ziel_ohne_anker": 3.0, "fachlich_falsch": 3.0, "laenge": 0.5, "vorwaerts": 0.5,
"det_check": 0.5,
"det_check": 0.5, "fix_offen": 1.5,
"diagramm_parse_fehler": 3.0, "diagramm_ungegroundet": 3.0,
"diagramm_unverifiziert": 0.5, "diagramm_marker_tot": 3.0,
}
@@ -45,6 +48,7 @@ def _basis(topic: str, ebene: str) -> int:
" AND status NOT IN ('gemerged','verworfen')",
"struktur": "SELECT COUNT(*) n FROM atome WHERE topic=?"
" AND status NOT IN ('gemerged','verworfen')",
"diagramme": "SELECT COUNT(*) n FROM bausteine WHERE topic=?",
"guide": "SELECT COUNT(*) n FROM bausteine WHERE topic=?"}[ebene]
row = db.one(z, (topic,))
return max(1, int(row["n"]) if row else 1)
@@ -62,21 +66,30 @@ def note(befunde: list[dict], basis: int) -> float:
def _persistieren(ctx: llm.Kontext, ebene: str, befunde: list[dict]) -> None:
"""Offene Alt-Befunde, die nicht mehr auftreten → repariert; Neues → offen.
Bestehende offene Zeilen bleiben (kein Duplikat)."""
alte = db.query("SELECT * FROM befunde WHERE run_id=? AND ebene=? AND status='offen'",
(ctx.run_id, ebene))
neu_keys = {(b["art"], str(b["item"])) for b in befunde}
Schlüssel schließt detail EIN — mehrere Befunde gleicher (art, item) mit
verschiedenen Details (z. B. mehrere det_check je Section) sind legitim und
brauchen je eine Zeile; ohne detail kollabierten sie und alte Details blieben
für immer offen. topic-scoped (JOIN runs), damit auch offene Zeilen früherer
Läufe geschlossen werden, wenn der Befund nicht mehr auftritt."""
alte = db.query(
"SELECT b.* FROM befunde b JOIN runs r ON r.id=b.run_id"
" WHERE r.topic=? AND b.ebene=? AND b.status='offen'", (ctx.topic, ebene))
def schluessel(art, item, detail) -> tuple:
return (art, str(item), (detail or "")[:500])
neu_keys = {schluessel(b["art"], b["item"], b.get("detail", "")) for b in befunde}
alt_keys = set()
for alt in alte:
key = (alt["art"], alt["item"])
if key in neu_keys:
alt_keys.add(key)
k = schluessel(alt["art"], alt["item"], alt["detail"])
if k in neu_keys:
alt_keys.add(k)
else:
db.update("befunde", "id", alt["id"], status="repariert")
for b in befunde:
if (b["art"], str(b["item"])) not in alt_keys:
if schluessel(b["art"], b["item"], b.get("detail", "")) not in alt_keys:
db.insert("befunde", run_id=ctx.run_id, ebene=ebene, art=b["art"],
item=str(b["item"]), detail=b["detail"][:500], status="offen")
item=str(b["item"]), detail=(b.get("detail") or "")[:500], status="offen")
async def messen(ctx: llm.Kontext, ebene: str, mit_llm: bool = True) -> tuple[float, list[dict]]: