update
This commit is contained in:
@@ -137,14 +137,24 @@ def _luecke(prompt: str):
|
||||
|
||||
|
||||
def _artefakt_generate(prompt: str):
|
||||
ids = [int(i) for i in re.findall(r"ATOM (\d+):", prompt)]
|
||||
# Form je Atom-Typ [in Klammern] wählen (wie die typgesteuerte Regel im Prompt)
|
||||
paare = re.findall(r"ATOM (\d+):[^\[\n]*\[(\w+)\]", prompt)
|
||||
out = []
|
||||
for i in ids:
|
||||
for raw, typ in paare:
|
||||
i = int(raw)
|
||||
out += [{"atom": i, "typ": "flashcard", "frage": f"Was besagt Atom {i}?",
|
||||
"antwort": "Siehe Beleg — deterministische Fake-Antwort."},
|
||||
{"atom": i, "typ": "flashcard", "frage": f"Wozu dient Atom {i}?",
|
||||
"antwort": "Zum Lernen — deterministische Fake-Antwort."},
|
||||
{"atom": i, "typ": "beispiel", "text": f"Beispiel zu Atom {i}: Schritt 1, Schritt 2."}]
|
||||
"antwort": "Zum Lernen — deterministische Fake-Antwort."}]
|
||||
if typ == "verfahren":
|
||||
out.append({"atom": i, "typ": "beispiel", "form": "code",
|
||||
"sprache": "python", "code": f"print({i} + 1)"})
|
||||
elif typ == "begriff":
|
||||
out.append({"atom": i, "typ": "beispiel", "form": "tabelle",
|
||||
"tabelle": f"| Fall | Ergebnis |\n|---|---|\n| Atom {i} | passt |"})
|
||||
else: # aussage → Text-Beispiel
|
||||
out.append({"atom": i, "typ": "beispiel", "form": "text",
|
||||
"text": f"Beispiel zu Atom {i}: Schritt 1, Schritt 2."})
|
||||
return out
|
||||
|
||||
|
||||
@@ -196,24 +206,40 @@ def _zyklus(prompt: str):
|
||||
return {"von": int(m.group(1)), "zu": int(m.group(2))} if m else {}
|
||||
|
||||
|
||||
def _braucht_aufloesung(prompt: str):
|
||||
# je ANGABE den Kandidaten mit den meisten geteilten Tokens (Substring, ≥4 Zeichen)
|
||||
# wählen, sonst null — spiegelt den Substring-Prefilter der Auflösung.
|
||||
def toks(s):
|
||||
return {t for t in re.findall(r"\w+", s.lower()) if len(t) >= 4}
|
||||
out = []
|
||||
bloecke = re.split(r"ANGABE (\d+):", prompt)[1:]
|
||||
for i in range(0, len(bloecke), 2):
|
||||
n, body = int(bloecke[i]), bloecke[i + 1]
|
||||
mp = re.search(r"Voraussetzung „([^“]+)", body)
|
||||
ph = mp.group(1) if mp else ""
|
||||
pl, pt = ph.lower(), toks(ph)
|
||||
ranked = []
|
||||
for kid, ktitel in re.findall(r"- atom (\d+): (.+?) —", body):
|
||||
geteilt = {t for t in toks(ktitel) if t in pl} | {t for t in pt if t in ktitel.lower()}
|
||||
if geteilt:
|
||||
ranked.append((-len(geteilt), len(ktitel), int(kid)))
|
||||
ranked.sort()
|
||||
out.append({"phrase": n, "atom": ranked[0][2] if ranked else None})
|
||||
return out
|
||||
|
||||
|
||||
def _writer(prompt: str):
|
||||
ziel = re.search(r"Lernziel: (.+)", prompt)
|
||||
marker = re.findall(r"MARKER \(exakt so übernehmen\): (<!-- atom: \d+ \| (.+?) -->)",
|
||||
prompt)
|
||||
defs = re.findall(r"Definition: (.+)", prompt)
|
||||
fragen = re.findall(r"^- (.+\?)$", prompt, re.MULTILINE)[:2]
|
||||
lo = int(re.search(r"hat (\d+)–", prompt).group(1)) if re.search(r"hat (\d+)–", prompt) else 40
|
||||
absaetze = [f"Ziel dieser Einheit: {ziel.group(1) if ziel else 'Lernen'}. Formal: $n \\ge 0$."]
|
||||
fuellung = "Daran anknüpfend gehen wir das Schritt für Schritt am Beispiel durch. " * 5
|
||||
diag = re.findall(r"(<!-- diagramm: \d+ -->)", prompt) # angebotene Diagramme
|
||||
for n, ((mk, titel), d) in enumerate(zip(marker, defs)):
|
||||
block = f"#### {titel} verstehen\n{mk}\n{d} {fuellung}"
|
||||
if n == 0 and diag: # erstes Diagramm beim ersten Absatz platzieren
|
||||
block += f"\n\n{diag[0]}"
|
||||
absaetze.append(block)
|
||||
absaetze.append("**Kernpunkte:**\n" + "\n".join(f"- {t} sitzt" for _, t in marker))
|
||||
if fragen:
|
||||
absaetze.append("**Prüfe dich:**\n" + "\n".join(f"- {f}" for f in fragen))
|
||||
for (mk, titel), d in zip(marker, defs):
|
||||
# Beispiel-/Diagramm-Marker setzt jetzt _marker_platzieren deterministisch,
|
||||
# nicht mehr der Writer.
|
||||
absaetze.append(f"#### {titel} verstehen\n{mk}\n{d} {fuellung}")
|
||||
lang = "\n\n".join(absaetze)
|
||||
while len(lang.split()) < lo:
|
||||
lang += "\nNoch ein Übungssatz zur Vertiefung des Gelernten."
|
||||
@@ -222,8 +248,8 @@ def _writer(prompt: str):
|
||||
|
||||
|
||||
def _diagramm_plan(prompt: str):
|
||||
# deterministisch: die Fake-Welt braucht kein LLM-Diagramm (DAG-Pfad wird
|
||||
# getestet). Unit-Tests für den LLM-Zweig monkeypatchen diesen Handler.
|
||||
# deterministisch: die Fake-Welt braucht kein Diagramm. Unit-Tests für den
|
||||
# LLM-Diagramm-Zweig monkeypatchen diesen Handler auf noetig=True.
|
||||
return {"noetig": False, "typ": ""}
|
||||
|
||||
|
||||
@@ -269,7 +295,7 @@ _HANDLER = {
|
||||
"Artefakt-Generate": _artefakt_generate, "Artefakt-Verify": _artefakt_verify,
|
||||
"Artefakt-Fix": _artefakt_fix, "Lernziele": _lernziele, "Kapitel-Intro": _kapitel_intro,
|
||||
"Kapitel-Schnitt": _kapitel_schnitt, "Level-Kalibrierung": _level_kalibrierung,
|
||||
"Kanten-Zyklus": _zyklus,
|
||||
"Kanten-Zyklus": _zyklus, "Braucht-Aufloesung": _braucht_aufloesung,
|
||||
"Guide-Writer": _writer, "Guide-Pruefer": _pruefer, "Guide-Fix": _fix,
|
||||
"QA-Guide-Falsch": _qa_falsch, "QA-Guide-Falsch-Check": _qa_falsch_check,
|
||||
"Diagramm-Plan": _diagramm_plan, "Diagramm-Spec": _diagramm_spec,
|
||||
|
||||
Reference in New Issue
Block a user