update
This commit is contained in:
@@ -136,12 +136,19 @@ async def _recherche_runde(ctx: llm.Kontext, runde: int) -> int:
|
||||
inhalt = str(q.get("inhalt", "")).strip()
|
||||
if len(inhalt) < 500: # leere/dünne Funde sind keine Quelle
|
||||
continue
|
||||
url = str(q.get("url", ""))[:500]
|
||||
# URL-Dedup: dieselbe Seite über Runden erneut geholt liefert leicht
|
||||
# abweichende Extrakte (anderer Content-Hash) und zählte dann als
|
||||
# „unabhängiger" Beleg im ≥2-Quellen-Konsens (Lernen: eine URL 4×).
|
||||
if url and db.one("SELECT id FROM quellen WHERE topic=? AND url=?",
|
||||
(ctx.topic, url)):
|
||||
continue
|
||||
snap = _snapshot_schreiben(ctx.topic, inhalt)
|
||||
if snap is None:
|
||||
continue
|
||||
titel = str(q.get("titel", ""))[:200]
|
||||
db.insert("quellen", topic=ctx.topic, art="web", titel=titel,
|
||||
url=str(q.get("url", ""))[:500], snapshot=snap[0], hash=snap[1],
|
||||
url=url, snapshot=snap[0], hash=snap[1],
|
||||
runde=runde, status="neu", rolle=_rolle(titel, lens))
|
||||
neu += 1
|
||||
return neu
|
||||
@@ -331,38 +338,76 @@ def messen(ctx: llm.Kontext) -> list[dict]:
|
||||
return befunde
|
||||
|
||||
|
||||
async def _beleg_nachsuchen(ctx: llm.Kontext, soll_id: int) -> bool:
|
||||
"""Gezielter Beleg-Judge in noch nicht zitierten Quellen; ein bestätigter
|
||||
Punkt ohne Fund wird zum Kandidaten zurückgestuft (Konsens-Regel bleibt
|
||||
hart). → True nur, wenn sich etwas geändert hat."""
|
||||
p = db.one("SELECT * FROM soll WHERE id=?", (soll_id,))
|
||||
if not p:
|
||||
async def _belege_nachsuchen(ctx: llm.Kontext, soll_ids: list[int]) -> bool:
|
||||
"""Gezielte Beleg-Judges, gebündelt: EIN Call je Quelle mit ALLEN dort noch
|
||||
offenen Punkten — Punkt×Quelle einzeln waren 3072 Calls / 27 % der
|
||||
Themen-Tokens (Lernen). Negativ-Cache soll.geprueft: erfolglos geprüfte
|
||||
(Punkt, Quelle)-Paare werden über Repair-Iterationen nie wiederholt.
|
||||
Bestätigte Punkte ohne Fund in irgendeiner Quelle → zurück zu Kandidat."""
|
||||
punkte = [p for s in dict.fromkeys(soll_ids)
|
||||
if (p := db.one("SELECT * FROM soll WHERE id=?", (s,)))]
|
||||
if not punkte:
|
||||
return False
|
||||
belegte = {bl["quelle"] for bl in db.uj(p["belege"])}
|
||||
andere = [q for q in db.query("SELECT * FROM quellen WHERE topic=?", (ctx.topic,))
|
||||
if q["id"] not in belegte]
|
||||
for q in andere:
|
||||
quellen = db.query("SELECT * FROM quellen WHERE topic=?", (ctx.topic,))
|
||||
bewegt = False
|
||||
|
||||
async def eine_quelle(q: dict) -> None:
|
||||
nonlocal bewegt
|
||||
faellig = []
|
||||
for p in punkte:
|
||||
belegte = {bl["quelle"] for bl in db.uj(p["belege"])}
|
||||
if q["id"] not in belegte and q["id"] not in db.uj(p["geprueft"]):
|
||||
faellig.append(p)
|
||||
if not faellig:
|
||||
return
|
||||
text = quelltext(q)
|
||||
liste = "\n".join(f"{p['id']}: {p['punkt']}" for p in faellig)
|
||||
res = await llm.call(ctx, stage="soll_beleg", template="Korpus-Soll-Beleg",
|
||||
schritt="soll", role="judge", item=f"s{p['id']}-q{q['id']}",
|
||||
werte={"punkt": p["punkt"],
|
||||
"text": quelltext(q)[:SOLL_CHUNK_CHARS]},
|
||||
erwartet=dict)
|
||||
zitat = str((res or {}).get("zitat", "")).strip()
|
||||
if zitat and textkit.finde_zitat(quelltext(q), zitat) is not None:
|
||||
belege = db.uj(p["belege"]) + [{"quelle": q["id"], "zitat": zitat}]
|
||||
db.update("soll", "id", p["id"], belege=db.j(belege))
|
||||
return True
|
||||
if p["status"] == "bestaetigt":
|
||||
db.update("soll", "id", p["id"], status="kandidat")
|
||||
return True
|
||||
return False
|
||||
schritt="soll", role="judge", item=f"q{q['id']}",
|
||||
n=len(faellig),
|
||||
werte={"punkte": liste, "text": text[:SOLL_CHUNK_CHARS]},
|
||||
erwartet=list)
|
||||
if res is None:
|
||||
return # Ausfall: nicht als „geprüft" verbuchen
|
||||
gefunden: dict[int, str] = {}
|
||||
for e in res:
|
||||
if not isinstance(e, dict):
|
||||
continue
|
||||
zitat = str(e.get("zitat", "")).strip()
|
||||
if zitat and e.get("soll") in {p["id"] for p in faellig} \
|
||||
and textkit.finde_zitat(text, zitat) is not None:
|
||||
gefunden[e["soll"]] = zitat
|
||||
for p in faellig:
|
||||
frisch = db.one("SELECT * FROM soll WHERE id=?", (p["id"],))
|
||||
if p["id"] in gefunden:
|
||||
belege = db.uj(frisch["belege"]) + [{"quelle": q["id"],
|
||||
"zitat": gefunden[p["id"]]}]
|
||||
db.update("soll", "id", p["id"], belege=db.j(belege))
|
||||
bewegt = True
|
||||
else:
|
||||
geprueft = sorted(set(db.uj(frisch["geprueft"])) | {q["id"]})
|
||||
db.update("soll", "id", p["id"], geprueft=db.j(geprueft))
|
||||
|
||||
await llm.alle(eine_quelle(q) for q in quellen)
|
||||
for p in punkte:
|
||||
frisch = db.one("SELECT * FROM soll WHERE id=?", (p["id"],))
|
||||
if frisch["status"] != "bestaetigt" \
|
||||
or len(db.uj(frisch["belege"])) > len(db.uj(p["belege"])):
|
||||
continue
|
||||
belegte = {bl["quelle"] for bl in db.uj(frisch["belege"])}
|
||||
rest = [q for q in quellen if q["id"] not in belegte
|
||||
and q["id"] not in db.uj(frisch["geprueft"])]
|
||||
if not rest: # wirklich überall erfolglos gesucht — Konsens-Regel bleibt hart
|
||||
db.update("soll", "id", p["id"], status="kandidat")
|
||||
bewegt = True
|
||||
return bewegt
|
||||
|
||||
|
||||
async def reparieren(ctx: llm.Kontext, befunde: list[dict]) -> bool:
|
||||
ctx.ebene = EBENE
|
||||
punkte = [int(b["item"]) for b in befunde if b["art"] == "soll_wenig_belege"]
|
||||
offene = [int(b["item"]) for b in befunde if b["art"] == "soll_kandidat_offen"]
|
||||
bewegt = any(await llm.alle(_beleg_nachsuchen(ctx, s) for s in punkte + offene))
|
||||
bewegt = await _belege_nachsuchen(ctx, punkte + offene)
|
||||
if offene: # neu falten: die Nachrunden im Konsens erzwingen die Zuordnung
|
||||
await _konsens(ctx)
|
||||
noch = db.query("SELECT id FROM soll WHERE topic=? AND status='kandidat'",
|
||||
|
||||
Reference in New Issue
Block a user