update
This commit is contained in:
@@ -30,16 +30,22 @@ KORPUS_DIR = ROOT / "storage" / "korpus"
|
||||
SKILLS_DIR = ROOT / "skills"
|
||||
PIPELINE_YAML = ROOT / "pipeline.yaml"
|
||||
|
||||
TOPIC_NAME_RE = re.compile(r"^[a-zA-Z0-9äöüÄÖÜß][a-zA-Z0-9äöüÄÖÜß _-]{0,63}$")
|
||||
TOPIC_NAME_RE = re.compile(r"^[a-zA-Z0-9äöüÄÖÜß][a-zA-Z0-9äöüÄÖÜß ._-]{0,63}$")
|
||||
|
||||
# ── LLM / MiniMax (R3/R9) — alles M3; M2.x kann Thinking nicht abschalten ──
|
||||
LLM_ENDPOINT = "https://api.minimax.io/anthropic/v1/messages"
|
||||
# ── LLM (R3/R9) — Anbieter/Modell per env überschreibbar, nicht im Code ──
|
||||
LLM_ENDPOINT = os.getenv("LLM_ENDPOINT",
|
||||
"https://api.minimax.io/anthropic/v1/messages")
|
||||
LLM_MODEL = os.getenv("LLM_MODEL", "MiniMax-M3")
|
||||
ROLLEN = {
|
||||
# thinking IMMER explizit ("enabled" gibt 400; Default widersprüchlich dokumentiert)
|
||||
"extraktion": dict(model="MiniMax-M3", thinking="disabled", temperature=0.2),
|
||||
"judge": dict(model="MiniMax-M3", thinking="disabled", temperature=0.1),
|
||||
"writer": dict(model="MiniMax-M3", thinking="adaptive", temperature=0.7),
|
||||
"extraktion": dict(model=LLM_MODEL, thinking="disabled", temperature=0.2),
|
||||
"judge": dict(model=LLM_MODEL, thinking="disabled", temperature=0.1),
|
||||
"writer": dict(model=LLM_MODEL, thinking="adaptive", temperature=0.7),
|
||||
}
|
||||
# Anbieter-spezifische Infra-Marker (MiniMax-Statuscodes) getrennt von generischen
|
||||
INFRA_MARKER = ("429", "rate limit", "rate_limit", "timeout", "timed out",
|
||||
"connection", "network", "overloaded", "unavailable",
|
||||
'"status_code":1002', '"status_code":1041', '"status_code":2045')
|
||||
LLM_MAX_TOKENS = 32_000
|
||||
MAX_PARALLEL_LLM = int(os.getenv("MAX_PARALLEL_LLM", "12")) # M3: 200 RPM → 8-16 sicher
|
||||
TAKT_SEKUNDEN = float(os.getenv("TAKT_SEKUNDEN", "3")) # 1 Call-Start je Takt; 0 = Breiten-Drossel
|
||||
@@ -53,16 +59,8 @@ HEDGE_NACH_S = int(os.getenv("HEDGE_NACH_S", "90")) # Zwilling nach max(90, tim
|
||||
RUN_BUDGET_TOKENS = int(os.getenv("RUN_BUDGET_TOKENS", "10000000")) # DEFAULT AN; 0 = aus
|
||||
PREIS_IN, PREIS_OUT = 0.60, 2.40 # $/1M konservativ (R9), real messen
|
||||
|
||||
# Timeouts je Knoten: (basis_s, pro_item_s) — creator2-Lektion 14: nie fix;
|
||||
# pro_item skaliert mit der Bündel-Größe (n in llm.call)
|
||||
TIMEOUTS = {
|
||||
"recherche_plan": (60, 20), "soll_extraktion": (180, 60), "soll_konsens": (240, 2),
|
||||
"atom_extraktion": (240, 60), "anker_fix": (180, 4), "dedup": (120, 8),
|
||||
"soll_zuordnung": (120, 3), "luecke": (180, 45), "lernziele": (120, 3),
|
||||
"bausteine": (120, 3), "ordnung": (180, 3), "writer": (420, 0),
|
||||
"kapitel_intro": (90, 0), "llm_pruefung": (240, 60), "fix": (300, 0),
|
||||
"redundanz": (120, 8), "klaerung": (180, 0),
|
||||
}
|
||||
# Timeouts stehen als Knoten-Property in pipeline.yaml (graph.timeout_fuer);
|
||||
# hier nur der Default für Knoten ohne Angabe
|
||||
TIMEOUT_DEFAULT = (180, 0)
|
||||
|
||||
# ── Suche (R2) ──
|
||||
@@ -78,18 +76,25 @@ FETCH_CONNECT_S = 10
|
||||
FETCH_READ_S = 30
|
||||
DOMAIN_RATE_S = 1.0
|
||||
SNAPSHOT_MIN_ZEICHEN = 500
|
||||
# Privates Lese-Tool, ~20 Seiten/Lauf mit Domain-Bremse — kein robots.txt-Check
|
||||
# mehr (Lektion 101); Browser-UA, sonst sperren Bot-Filter trotzdem
|
||||
BROWSER_UA = ("Mozilla/5.0 (X11; Linux x86_64; rv:128.0) "
|
||||
"Gecko/20100101 Firefox/128.0")
|
||||
URTEIL_AUSZUG_ZEICHEN = 3_000 # Inhalts-Urteil je geladener Quelle
|
||||
|
||||
# ── Korpus ──
|
||||
RECHERCHE_LENSES = ("ueberblick", "tutorial", "referenz", "praxis") # generisch!
|
||||
RECHERCHE_RUNDEN_MAX = int(os.getenv("RECHERCHE_RUNDEN_MAX", "4"))
|
||||
QUERIES_JE_LENS = 3
|
||||
SOLL_CHUNK_CHARS = 40_000
|
||||
SOLL_MIN_BELEGE = 2 # ≥2 unabhängige Quellen je bestätigtem Punkt
|
||||
SOLL_PUNKTE_MIN = int(os.getenv("SOLL_PUNKTE_MIN", "5"))
|
||||
SOLL_BAND_FAKTOR = 1.0 # Ziel ≈ √Kandidaten (creator2-Band — Lektion 90)
|
||||
SOLL_BAND_TOLERANZ = 1.5 # mehr als Ziel×1.5 bestätigt → nochmal falten
|
||||
QUELLEN_MAX = int(os.getenv("QUELLEN_MAX", "24")) # harter Korpus-Deckel
|
||||
EXTRAKT_FENSTER = 4_000 # Atome nur ±Fenster um Soll-Belege (belegnah)
|
||||
# Harte Vollständigkeits-Stops (Lektion 103): lieber PAUSE als Mini-Guide
|
||||
SEED_PFLICHT = True # keine Startquelle nützlich geladen → PAUSE
|
||||
QUELLEN_MIN = 5 # weniger geladene nützliche Quellen → PAUSE
|
||||
BEIFANG_MAX_QUOTE = 0.5 # >50 % Atome als Beifang verworfen → PAUSE
|
||||
|
||||
# ── Inventar ──
|
||||
ABSCHNITT_CHARS = 6_000 # 12k riss das 32k-Output-Cap (creator2 empirisch)
|
||||
@@ -127,22 +132,34 @@ REDUNDANZ_SHINGLE = 5 # gemeinsame 5-Wort-Folge = Kandidat
|
||||
REDUNDANZ_SATZ_MIN_TOKEN = 6
|
||||
ZIEL_DEDUP_JACCARD = 0.5 # synonyme Lernziele deterministisch mergen
|
||||
ECHO_JACCARD = 0.7 # 1. Satz nach Marker ≈ Atom-Definition = Echo
|
||||
SOLL_MIN_BELEGE_WIKI = 1 # kuratierte Quelle (Wikipedia) = 1 Beleg genügt
|
||||
FAKTEN_SIGNATUR_MIN = 2 # geteilte Zahlen+Namen je Satzpaar = Kandidat
|
||||
|
||||
# ── Engine (R8) ──
|
||||
POLL_SEKUNDEN = 2.0
|
||||
MAX_VERSUCHE = 2 # Inhalts-Versuche je Task; Infra zählt separat
|
||||
STILLSTAND_N = 2 # identischer Befund-Fingerprint n× → PAUSE
|
||||
GATE_RUNDEN_MAX = {"gate_korpus": 4, "gate_inventar": 8, "gate_struktur": 3, "gate_guide": 12}
|
||||
# gate_inventar 6: Anker-Fix, 2× Dedup/Lücke, Web-Nachrecherche, Nachzügler-Dedup
|
||||
# gate_guide 8: Echtlauf konvergierte 45→28→10 — der Stillstand-Fingerprint
|
||||
# fängt echte Schleifen, das Runden-Limit ist nur die Notbremse dahinter
|
||||
# Gate-Runden-Caps stehen als runden_max am Gate-Knoten in pipeline.yaml
|
||||
MAX_PARALLEL_GLOBAL = 24
|
||||
|
||||
|
||||
def timeout_fuer(knoten: str, n: int = 0) -> float:
|
||||
basis, pro = TIMEOUTS.get(knoten, TIMEOUT_DEFAULT)
|
||||
return basis + pro * n
|
||||
# ── Sprache: EIN Parameter, alles referenziert ihn (Lektion 106) ──
|
||||
SPRACHE = os.getenv("SPRACHE", "de")
|
||||
SPRACHEN_SUCHE = tuple(os.getenv("SPRACHEN_SUCHE", "de,en").split(","))
|
||||
STEMMER_NAME = {"de": "german", "en": "english", "fr": "french",
|
||||
"es": "spanish", "it": "italian"} # sonst: kein Stemming
|
||||
NEGATIONEN = {"de": {"nicht", "kein", "keine", "keinen", "keiner", "ohne",
|
||||
"nie", "niemals"},
|
||||
"en": {"not", "no", "none", "never", "without"}}
|
||||
NEGATIONS_PRAEFIX = {"de": "nicht", "en": "non"}
|
||||
SUCHE_LOCALE = {"de": {"country": "DE", "search_lang": "de", "region": "de-de"},
|
||||
"en": {"country": "US", "search_lang": "en", "region": "us-en"}}
|
||||
# Ausgabe-Literale, die im Guide landen — eine Stelle, pro Sprache tauschbar
|
||||
TEXTE = {
|
||||
"sammel_titel": "Grundlagen",
|
||||
"sammel_punkt": "Weitere Grundlagen zum Thema",
|
||||
"sammel_ziel": "Der Lernende kann Grundlagen zu '{punkt}' erklären.",
|
||||
"teil": "{titel} (Teil {n})",
|
||||
"abschnitt_verweis": "- {titel} (im Abschnitt '{abschnitt}')",
|
||||
}
|
||||
|
||||
|
||||
def user_agent() -> str:
|
||||
|
||||
Reference in New Issue
Block a user