update
This commit is contained in:
@@ -71,10 +71,7 @@ TIMEOUTS = {
|
||||
|
||||
# Auswahl-Auftrag je Format: (Mindest-Anteil, Maximal-Anteil, Mindestanzahl, Zweck).
|
||||
FORMAT_ANTEIL = {
|
||||
"MiniGuide": (0.05, 0.10, 8, "einen kompakten Anfänger-Guide — der schnelle Einstieg ins Thema"),
|
||||
"Guide": (0.25, 0.35, 20, "einen ausführlichen Anfänger-Guide — ein solides Fundament im Thema"),
|
||||
"ProGuide": (0.0, 1.0, 0, "einen fokussierten Guide — alles Relevante ohne Randthemen"),
|
||||
"FullGuide": (0.90, 1.00, 0, "einen Komplett-Guide — das ganze Thema"),
|
||||
"Guide": (0.0, 1.0, 0, "einen fokussierten Guide — alles Relevante ohne Randthemen"),
|
||||
}
|
||||
|
||||
# Provider-Stacks: komplett unabhängig, einer kann jederzeit entfernt werden.
|
||||
|
||||
@@ -71,7 +71,7 @@ def _topic_context(topic: str, limit: int = 12000) -> str:
|
||||
bp = bausteine_path(topic)
|
||||
if bp.exists():
|
||||
parts.append(bp.read_text(encoding="utf-8"))
|
||||
for fmt in ("FullGuide", "ProGuide", "Guide", "MiniGuide", "OnePager"):
|
||||
for fmt in ("Guide", "OnePager"):
|
||||
content = _json_datei(guide_content_path(topic, fmt))
|
||||
if content:
|
||||
for ch in content.get("chapters", []):
|
||||
|
||||
@@ -408,17 +408,17 @@ async def _generate_sections(
|
||||
"Wähle, was diesem Zweck dient — lass weg, was dafür nicht nötig ist."
|
||||
)
|
||||
|
||||
# Subbausteine je Baustein (Sidecar) — früh geladen: ProGuide wählt darüber aus,
|
||||
# Nicht-FullGuide filtert später Rand-Subbausteine. Fehlt sie → {} (Fallback).
|
||||
# Subbausteine je Baustein (Sidecar) — früh geladen: „Guide" wählt darüber aus
|
||||
# (Bausteine mit ≥1 relevantem Sub) und filtert später Rand-Subs. Fehlt sie → {} (Fallback).
|
||||
subs_raw = _load_subbausteine(topic)
|
||||
|
||||
# Schritt 0: Auswahl. ProGuide ist deterministisch — alle Bausteine mit ≥1
|
||||
# Schritt 0: Auswahl. „Guide" ist deterministisch — alle Bausteine mit ≥1
|
||||
# relevantem Subbaustein. Fallback (keine Relevanz-Daten): alle Bausteine.
|
||||
if format_name == "ProGuide":
|
||||
if format_name == "Guide":
|
||||
auswahl = [num for num in entries
|
||||
if any(s.get("relevanz") == "relevant" for s in subs_raw.get(_titel(entries[num]), []))]
|
||||
if not auswahl:
|
||||
_log(topic, "ProGuide: keine Relevanz-Daten — alle Bausteine genommen")
|
||||
_log(topic, "Guide: keine Relevanz-Daten — alle Bausteine genommen")
|
||||
auswahl = list(entries)
|
||||
else:
|
||||
# Auswahl-Konsens (5 Agenten → Voting → Mapping → Klärungs-Loop)
|
||||
@@ -501,16 +501,14 @@ async def _generate_sections(
|
||||
# dieselbe Aufteilung: 1 Agent je ~30 Bausteine (gedeckelt).
|
||||
total_sections = sum(len(c["nums"]) for c in plan)
|
||||
chunks = _split_chunks(plan, min(WRITER_MAX, max(1, math.ceil(total_sections / WRITER_SECTIONS))))
|
||||
# Subbausteine je Baustein. Rand-Subbausteine fliegen aus allen Guides AUSSER
|
||||
# FullGuide (Fokus). Subs ohne Relevanz-Feld (Alt-Themen) bleiben erhalten.
|
||||
# Subbausteine je Baustein. Rand-Subbausteine fliegen aus dem Guide (Fokus auf
|
||||
# Relevantes). Subs ohne Relevanz-Feld (Alt-Themen) bleiben erhalten.
|
||||
# Fehlt die Sidecar → leer → Inhalte/Writer laufen auf Baustein-Granularität.
|
||||
subs_by_titel = subs_raw
|
||||
if format_name != "FullGuide":
|
||||
subs_by_titel = {
|
||||
t: [s for s in subs if s.get("relevanz") != "rand"]
|
||||
for t, subs in subs_raw.items()
|
||||
}
|
||||
subs_by_titel = {t: subs for t, subs in subs_by_titel.items() if subs}
|
||||
subs_by_titel = {
|
||||
t: [s for s in subs if s.get("relevanz") != "rand"]
|
||||
for t, subs in subs_raw.items()
|
||||
}
|
||||
subs_by_titel = {t: subs for t, subs in subs_by_titel.items() if subs}
|
||||
zuteilungen = [_zuteilung_subs(chunk, entries, subs_by_titel) for chunk in chunks]
|
||||
chunk_sizes = [sum(len(c["nums"]) for c in chunk) for chunk in chunks]
|
||||
writer_count = len(chunks)
|
||||
|
||||
@@ -3,10 +3,7 @@ from typing import Literal
|
||||
|
||||
FormatType = Literal[
|
||||
"OnePager",
|
||||
"MiniGuide",
|
||||
"Guide",
|
||||
"ProGuide",
|
||||
"FullGuide",
|
||||
]
|
||||
|
||||
ProviderType = Literal["claude", "minimax", "lokal"]
|
||||
|
||||
@@ -18,12 +18,11 @@ from paths import bausteine_path, guide_content_path
|
||||
from textkit import _norm_titel
|
||||
|
||||
MAX_OFFENE_GUIDES = 3
|
||||
# Lineare Progression: jedes Format schaltet das nächste frei, sobald ALLE Bausteine
|
||||
# der Vorstufe das geforderte Niveau (Score-Meilenstein 10/20/30) erreicht haben.
|
||||
VORSTUFE = {"Guide": "MiniGuide", "ProGuide": "Guide", "FullGuide": "ProGuide"}
|
||||
# absolviert=6 · verstanden=12 · gemeistert=18 (siehe lernen.NOETIG/MASTERY/MEISTERN).
|
||||
FREISCHALT_LEVEL = {"Guide": "absolviert", "ProGuide": "verstanden", "FullGuide": "gemeistert"}
|
||||
FORMATE = ("MiniGuide", "Guide", "ProGuide", "FullGuide")
|
||||
# Nur noch EIN Format „Guide" (alle relevanten Bausteine, Prüfung 0–30). Keine Progression,
|
||||
# keine Vorstufe → der Guide ist immer freischaltbar. „Rest"/OnePager separat.
|
||||
VORSTUFE: dict[str, str] = {}
|
||||
FREISCHALT_LEVEL: dict[str, str] = {}
|
||||
FORMATE = ("Guide",)
|
||||
|
||||
# Geforderter Score je Freischalt-Niveau — nur für die Sperr-Meldung.
|
||||
_LEVEL_WORT = {
|
||||
@@ -106,8 +105,8 @@ def ist_absolviert(topic: str, fmt: str, guides: list[dict], progress: dict[str,
|
||||
|
||||
|
||||
def thema_abgeschlossen(topic: str, guides: list[dict], progress: dict[str, set[str]], levels: dict[str, dict[str, set[str]]]) -> bool:
|
||||
"""Thema fertig: neuester fertiger FullGuide, alle Bausteine gemeistert (25)?"""
|
||||
return ist_level(topic, "FullGuide", guides, progress, levels["gemeistert"])
|
||||
"""Thema fertig: neuester fertiger Guide, alle Bausteine gemeistert (18)?"""
|
||||
return ist_level(topic, "Guide", guides, progress, levels["gemeistert"])
|
||||
|
||||
|
||||
def formate_stats(guides: list[dict], progress: dict[str, set[str]], levels: dict[str, dict[str, set[str]]]) -> dict:
|
||||
|
||||
Reference in New Issue
Block a user