Ist-Sprachpfad (Phase N0, Vermessung)¶
Stand: 05.10.2026 ~17:00 UTC (19:00 MESZ). Basis: Branch selbstverbesserung 4a0aff7, Produktion 0d7f4e8 (per /health), Schalter-Schnappschuss der Produktion in
produktion_flags_20261005.json. Maschinenlesbar: ist_sprachpfad.json (erzeugt von tools/native_ist_sprachpfad.py, Scanner tools/native_llm_pfad_scan.py).
Kein Refactoring in dieser Phase - nur Vermessung.
1. Befund in drei Saetzen¶
- Die Produktion formuliert heute ohne generatives Modell:
LENNY_OUTPUT_MODE=deterministic,LENNY_ENABLE_LLM_FORM_ANSWER=0,LENNY_ALLOW_OLLAMA_FINAL_ANSWER=0,LENNY_ALLOW_CLAIM_GATE_LLM_FINAL=0. Die LLM-Verbalisierung (qwen2.5:7b ueber Ollama) ist schaltbarer Altbestand, kein laufender Pfad. - Die deterministische Formulierung besteht aus ~25 Antworterzeugern, die Saetze als Zeichenketten bauen (feste Vorlagen aus Fakten), danach eine duenne Sprachschicht, Sprecher, Grad-/Herkunfts-Fusszeilen.
Die Qualitaet ist "Roboterdeutsch" (siehe 4.). Inhalt und Sprache sind nicht getrennt: aus dem fertigen Text wird die Quelle zurueckgelesen (
_infer_lenny_answer_source). - Es gibt Stellen, an denen Modelltext in die Antwort gelangen kann, ohne dass ein Schalter sie schuetzt: die aktive Anfrage (
_active_inquiry_temporary_surface_answer->_request_ollama_evidence, nur Budget, kein Schalter) und zwei Diagnose-Eingaben. Sie sind im Native-Modus technisch zu sperren (NLG-025/048).
2. Stationen des Antwortpfads (POST /v1/chat/completions)¶
| Nr | Station | Ort | LLM |
|---|---|---|---|
| 1 | Auth, Rate-Limit, Tenant-Kontext | api_server.chat_completions |
nein |
| 2 | Retrieval (Hybrid/Graph); Einbettung ueber /api/embed |
_do_retrieval -> ask_lenny._embed_batch |
nur Einbettung (nicht generativ) |
| 3 | Signalbaum in den Trace | _signalbaum_in_trace |
nein |
| 4 | Model-Runtime (LENNY_MODEL_RUNTIME, Standard aus) |
api_server ~5342 |
eigene Laufzeit, aus |
| 5 | Trefferguete-Filter -> Antwortbasis | _nach_trefferguete_gefiltert |
nein |
| 6 | Router -> Text des Antworterzeugers | ask_lenny._weighted_answer_router (7056/7078) |
nein (deterministisch) |
| 7 | Deutung der Frage (Absicht, Subjekt, Zweitsubjekt, Form) | core/frage_deutung.py, core/frage_zerlegung.py |
nein |
| 8 | Schichten (Nutzer-/Firmenwissen) | core/schichten.py |
nein |
| 9 | Assistent-Modus (llm_assistant) |
ask_lenny._llm_assistant_answer (10682) |
ja, aus |
| 10 | Sprachrohr / Ausgabe-Router deterministic \| language_brain \| llm |
api_server._render_signal_output (4997), ask_lenny._signal_voice_answer (10789) |
ja nur im Modus llm (aus) |
| 11 | Sprachschicht (Wendungen mit Neu-Behauptungs-Pruefung) | ask_lenny._language_layer_apply (7903) |
nein |
| 12 | Sprachschicht-Schatten (Phase 5) | core/language_shadow.py |
nein |
| 13 | Sprecher (Signalbaum-Satz anhaengen) | core/sprecher.py |
nein |
| 14 | Kreativ-Hinweis (bei Absage) / Sicherheitsgrad "Stufe x von 7" (bei Antwort) | _kreativ_oder_grad_anhaengen (4606) |
nein |
| 15 | Finalizer: Sanitisierung, Status-Fusszeile, Tenant-Gedaechtnis | _completion_or_stream_with_observation_event_hook (3201) |
nein |
| 16 | Antwortfelder lenny_herkunft, lenny_stimme, lenny_deutung, lenny_sicherheitsgrad, lenny_relationsantwort |
_antwortfelder (4638) |
nein |
Station 10 ist die vorgesehene Naht: der Modus language_brain ist dort als "Eigenes Language Brain noch nicht angebunden" vorbereitet, und _signal_voice_answer sagt im Docstring "das eigene Language Brain ersetzt diese Funktion spaeter am selben Punkt".
Die Native Language Engine haengt deshalb an _render_signal_output (neuer Schalter LENNY_LANGUAGE_MODE, Standard off).
3. LLM-Aufrufe: Eingabe, Ausgabe, was vorher feststeht, was das Modell erzeugt¶
| Stelle | Eingabe | Ausgabe | Steht vor dem Modell fest | Das Modell erzeugt | Nachher | Gate | Produktion |
|---|---|---|---|---|---|---|---|
_llm_form_enriched_answer -> format_facts_as_answer (core/llm_form_answer.py) |
Fakten-Tripel + Frage | 1-4 Saetze | alle Fakten (Vertrauensregel, Admin-Sperre) | Formulierung, Reihenfolge, Verknuepfung | Erfindungs-Sperre (grossgeschriebene Inhaltswoerter), Kennzeichnung | LENNY_ENABLE_LLM_FORM_ANSWER |
0 |
_signal_voice_answer (via _render_signal_output) |
Frage + fertiger Text + Antwortbasis | umformulierter Text | der gesamte Inhalt | Umformulierung | Erfindungs-Sperre, Schrift-Sperre | LENNY_OUTPUT_MODE=llm |
deterministic |
_llm_assistant_answer |
Nutzernachricht + Grounding oder frei | Antwort bis 800 Tokens | Grounding (falls da) | alles Sprachliche, im freien Fall auch Inhalt | Assistant-Guard, Defekt-Verwerfen, Etikett | LENNY_OUTPUT_MODE=llm_assistant |
aus |
try_ollama, try_ollama_streaming, _stream_ollama_sse ("alte Luke") |
Frage + Fragment-Kontext | Antworttext (auch gestreamt) | Kontext | alles | - | LENNY_ALLOW_OLLAMA_FINAL_ANSWER |
0 |
_run_claim_gate, _claim_gate_llm_call, extract_claims_via_llm |
AllowedClaimsBundle-Prompt | LLM-Antwort, danach Claim-Pruefung | erlaubte Claims | Formulierung | Claim-Verifikation | LENNY_ALLOW_CLAIM_GATE_LLM_FINAL |
0 |
_request_ollama_evidence via _active_inquiry_temporary_surface_answer |
Bedeutungsfrage zum unbekannten Begriff | Modelltext als "unverifizierte Evidenz" -> vorlaeufige Antwortflaeche | nichts (Absage des Routers) | der Inhalt selbst | Kennzeichnung "externe Evidenz" | kein Schalter, nur Budget (1 je Fragment/Frage/Anfrage) | Code erreichbar; in der Sondenmessung kein Aufruf beobachtet |
_format_ollama_connection_diagnostic_observation, _format_ollama_generate_smoke_observation |
Diagnose-Eingabe | Diagnosetext (Smoke-Antwort) | - | Smoke-Text | - | Text-Observation | erreichbar |
Nicht verbalisierend (bleiben, ausserhalb des Antworttexts): Einbettung _embed_batch (bge-m3), Extraktion/Aufnahme/Beurteilung (relation_extractor, knowledge_ingestion, candidate_auto_promotion; Auto-Promotion per Schalter aus),
Betriebsprozesse (ops/gemma_loop_server.py u. a.), Modellidentitaet (/api/tags). Der Scanner zaehlt 28 Fundstellen: 11 Verbalisierung, 1 Evidenz, 2 Diagnose, 4 Extraktion, 2 Einbettung, 6 Sonde, 2 Betrieb, 0 unbekannt.
4. Antworttypen und Qualitaet heute (Sondenmessung an der Produktion, 05.10.2026)¶
| Frage | Antwort (gekuerzt) | Befund |
|---|---|---|
| Was ist ein Hund? | "Hund ist eine Fauna, bedeutet Haustier, dessen Vorfahre der Wolf ist und ist freundlich. Hund hat ein Fell und Beine und empfindet Schmerz." | kein Artikel, Satzfuegung bedeutet ..., dessen ... ohne Bezug, "Fauna" aus den Daten |
| Ist ein Hund ein Tier? | Ja - belegt: "Hund" ist ein "Tier" (ist_ein). |
Systembegriff ist_ein im Satz |
| Was ist der Unterschied zwischen Hund und Katze? | Es teilen "Hund" und "Katze" folgende Kategorie-Kandidaten: ... |
beantwortet Gemeinsamkeiten statt Unterschied |
| Welche Eigenschaften hat ein Hund? | Zu "Hund" liegen folgende Eigenschafts-Kandidaten vor: "Fell", "Beine", "freundlich". Im geprueften Wissen haengt Hund an Tier. |
Roboterdeutsch |
| Erzaehl mir etwas ueber Wasser | ... Wasser bedeutet kein Plural: ... Wasser herkunft von Mittelhochdeutsch ... (vgl. |
Datenrauschen ("kein Plural"), abgebrochener Satz |
| Woher kommt das Wort Hund? | Zitat der Wiktionary-Herkunft | Zitat, kein Satz |
| Warum bellt ein Hund? | Liste interner Fragment-IDs (frag:derived:...) |
unbrauchbar, sollte ehrliche Absage sein |
| Wie funktioniert ein Backup? | "Zu dieser Frage liegen mir aktuell noch keine ausreichend gewichteten Fragmente ..." | Absage korrekt, steif |
Der Antwortkanal liefert bereits strukturierte Nebenfelder (lenny_deutung: Absicht/Subjekt/Zweitsubjekt/Form; lenny_relationsantwort; lenny_sicherheitsgrad; lenny_herkunft; lenny_stimme).
Der Vertrag core/spur_vertrag.py ("Naht zwischen Sprache und Wissen") beschreibt Anfrage und Befund (Fakten mit Schicht, Belegart, Beleg) - benutzt wird er heute nur von frage_deutung.
5. Daten, auf denen die Sprache steht¶
Fragmentspeicher (Produktion, 05.10.2026): 369 Relationstypen, 21.265 Kanten im Namensraum general; dominant ist_ein (10.416), hat_eigenschaft (8.194), besteht_aus (938), alias_von (445), contrast (295), bedeutet (152), herkunft (145),
siehe_auch (57), danach ein langer Schwanz offener Verben (bilden, enthaelt, besitzen, ...). Genus: handgepflegte Tabelle (~70 Kategorienomen) + Wiktionary-Genus (494) + ausnahmslose Endungsregeln; Plural nur fuer ~60 Kategorienomen.
Die Daten sind verrauscht (z. B. haustier klein, Fauna, kein Plural als Bedeutung): die Native Engine muss das sprachlich abfangen (Normalisierung, Filter), nicht die Daten korrigieren.
6. Konsequenzen fuer den Ausbau¶
- Die Native Engine bekommt keinen Text, sondern einen Semantic Answer Frame, gebaut aus (Deutung der Frage) + (Fakten ueber dieselben Funktionen wie die Erzeuger:
_trusted_facts_for_termmit Admin-Sperre und Vertrauensregel) + (Sicherheitsgrad/Herkunft). - Die Naht ist
api_server._render_signal_output(Moduslanguage_brain->native); Fusszeilen/Status/Grad bleiben Sache des Finalizers (Station 14/15), die Native Engine liefert nur den Antwortkoerper und meldet "Absage/Rueckfrage" explizit an den Trace, damit kein Grad an eine Absage gehaengt wird. - Die Firewall sperrt im Native-Modus alle Fundstellen der Klassen Verbalisierung, Evidenz und Diagnose - nicht nur die per Schalter geschlossenen.
- Der Scanner dient als automatischer Pfadtest (
tests/test_native_llm_pfad.py): eine neue, unbekannte Stelle laesst ihn rot werden.