This commit is contained in:
team3
2026-06-21 22:06:02 +02:00
parent 50b1c81bca
commit b4c686f74f
13 changed files with 41 additions and 57 deletions

View File

@@ -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.

View File

@@ -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", []):

View File

@@ -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)

View File

@@ -3,10 +3,7 @@ from typing import Literal
FormatType = Literal[
"OnePager",
"MiniGuide",
"Guide",
"ProGuide",
"FullGuide",
]
ProviderType = Literal["claude", "minimax", "lokal"]

View File

@@ -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 030). 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: