Files
creator/backend/config.py
2026-06-24 19:41:34 +02:00

121 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
TEMPLATES_DIR = PROJECT_ROOT / "templates"
STORAGE_DIR = PROJECT_ROOT / "storage"
FRONTEND_DIST = PROJECT_ROOT / "frontend" / "dist"
DB_PATH = STORAGE_DIR / "creator.db"
PROJECTS_DIR = PROJECT_ROOT / "projects"
UNI_DIR = PROJECT_ROOT / "uni"
MAX_CONCURRENT_GENERATIONS = 10
# Lesbarkeits-Gate: deterministischer Prüfer (kleines deutsches Komplexitäts-Modell,
# Skala 17). Zu schwere Sections gehen in die Lese-Prüfungs-Überarbeitung.
# Fehlen transformers/torch oder das Modell → Gate stumm aus.
LESBARKEIT_AKTIV = True
LESBARKEIT_MODELL = "MiriUll/distilbert-german-text-complexity"
# Anker auf der 17-Skala (TextComplexityDE): Leichte Sprache ~1,2; Wikipedia-Schnitt
# ~3,22; ab MOS > 4 gilt ein Satz als „echt komplex" (Vereinfachungs-Grenze des Papers).
LESBARKEIT_MAX = 3.5 # Section zu schwer, wenn der Satz-Schnitt darüber liegt
LESBARKEIT_HART = 4.0 # Einzelsatz ab hier „hart"
LESBARKEIT_HART_ANTEIL = 0.30 # … ODER wenn dieser Anteil der Sätze hart ist
# Deckel für gleichzeitige CLI-Agenten-Prozesse (über alle Generierungen hinweg).
# Eigene Spur für interaktive Aufrufe (Chat, Elemente), damit sie nicht hinter
# laufenden Writern in der Warteschlange hängen.
MAX_CONCURRENT_AGENTS = 10
MAX_CONCURRENT_INTERACTIVE = 8
# Grace-Fenster der Konsens-Races (Bausteine, Guide, OnePager): Nach dem ersten
# gültigen Ergebnis dürfen die übrigen Agenten noch so viele Sekunden fertig
# werden (Kill nur, wenn das Minimum schon steht).
KONSENS_GRACE = 300
# Recherche-Race: längeres Grace-Fenster. Recherche treibt die ganze Bausteine-Anzahl;
# bei langsamen Providern (z.B. MiniMax) sollen ALLE 5 Agenten fertig werden, nicht nur
# das Quorum von 3. Pro-Agent-Timeout (TIMEOUTS["recherche"]=1800s) deckelt echte Hänger.
RECHERCHE_GRACE = 900
# Cap der Klärungs- und Prüf-Loops: maximale Runden, bis alles entschieden sein
# muss. In der letzten Runde MUSS der Mapping-Agent jeden Eintrag entscheiden;
# Prüf-Loops lassen Rest-Beanstandungen danach stehen.
KONSENS_MAX_RUNDEN = 3
# Crawler-Sichtung (Content/Noise) — deterministischer Regel-Filter statt LLM.
# Match: Substring (klein) gegen URL UND Dateiname. Reihenfolge: keep > noise > min_chars > behalten.
# Sonderregeln einfach hier ergänzen.
CRAWL_KEEP_PATTERNS = ["learn-unit", "learn-course"] # immer Content
CRAWL_NOISE_PATTERNS = [ # eindeutig themenfremd → raus
"clubs", "events", "podcasts", "resources", "-u-",
"academy", "pricing", "/plans", "career", "newsletter", "impressum", "login",
]
CRAWL_MIN_CHARS = 400 # zu wenig Text → raus
# Timeouts pro Agenten-Schritt: (Basis-Sekunden, Sekunden pro Baustein/Section).
# Gilt für alle Provider gleich — wer zu langsam ist, wird neu gestartet bzw. überholt.
TIMEOUTS = {
"recherche": (1800, 0), # fix 30 min
"recherche_mapping": (600, 3), # n = vorgemergte Einträge
"auswahl_mapping": (600, 2), # n = Rest-Einträge (Bausteine-Inventar)
"ergaenzung": (900, 0), # Themenfeld-Ergänzung bei Projekten (Web-Recherche)
"plan": (300, 5),
"plan_judge": (600, 5), # Judge liest bis zu 5 Gliederungen, n = Sections
"inhalt": (600, 90), # Inhalte je Baustein im Chunk identifizieren (Websuche)
"inhalt_check": (300, 10), # Inhalts-Prüfung je Baustein im Paket
"subbaustein": (900, 45), # Subbausteine je Baustein im Chunk finden (Websuche)
"subbaustein_check": (300, 15), # Judge entscheidet strittige Subbausteine im Chunk
"stufe": (300, 10), # Subbausteine einstufen je Chunk
"stufe_check": (300, 10), # Judge entscheidet strittige Stufen im Chunk
"relevanz": (300, 10), # Subbausteine relevant/rand je Chunk
"relevanz_check": (300, 10), # Judge entscheidet strittige Relevanz im Chunk
"frage_muster": (300, 15), # Frage-Muster je Baustein (Subbausteine × Typen)
"frage_muster_check": (300, 10), # Kritiker bereinigt die Muster-Tabelle je Baustein
"writer": (600, 120), # pro Section im Chunk
"lese_check": (300, 10), # pro Section im Paket
}
# Zweck je Format — fließt in den Gliederungs-Judge (was der Guide leisten soll).
FORMAT_ZWECK = {
"Guide": "einen fokussierten Guide — alles Relevante ohne Randthemen",
"FullGuide": "einen Komplett-Guide — das ganze Thema inkl. Randthemen",
"Rest": "einen Ergänzungs-Guide — nur die Randthemen",
}
# Provider-Stacks: komplett unabhängig, einer kann jederzeit entfernt werden.
# Rollen: "quick" = Massenarbeit (Recherche, Einordnung),
# "fast" = Interaktion + Voten (Chat, Prüfung, Klärung, Elemente),
# "judge" = Mapping-/Judge-/Prüf-Agenten — kalt (niedrige Temperature,
# ohne Thinking) für stabile Urteile; Claude/Lokal mappen auf "fast",
# "guide" = große Generierung (Vorschläge, Writer).
DEFAULT_PROVIDER = "claude"
PROVIDERS = {
"claude": {
"cli": "claude",
"guide": "claude-opus-4-8[1m]",
"fast": "claude-sonnet-4-6",
"judge": "claude-sonnet-4-6", # CLI kennt keine Temperature
"quick": "claude-sonnet-4-6",
"env_key": None, # Auth via CLAUDE_CODE_OAUTH_TOKEN oder ~/.claude
},
# "minimax-kalt/…" ist KEIN eigener Stack, nur ein opencode-Provider-Eintrag
# (dev-ops/opencode.json) mit niedriger Temperature; M3 dort ohne Thinking.
"minimax": {
"cli": "opencode",
"guide": "minimax/MiniMax-M3",
"fast": "minimax-kalt/MiniMax-M2.7-highspeed",
"judge": "minimax-kalt/MiniMax-M3",
"quick": "minimax/MiniMax-M2.7-highspeed",
"env_key": "MINIMAX_API_KEY",
},
"lokal": {
"cli": "opencode",
"guide": "ollama/qwen3.6:27b",
"fast": "ollama/qwen3.5:9b",
"judge": "ollama/qwen3.5:9b",
"quick": "ollama/qwen3.5:9b",
"env_key": None,
"check_url": "http://localhost:11434/api/tags", # Ollama erreichbar?
},
}