17 KiB
Plan: Heading-basiertes Chunking (umgesetzt fuer INB)
Status: umgesetzt (Phase 1). Die Entscheidungen unten sind getroffen; das Chunking ist als deterministischer, embedding-freier Schritt implementiert und fuer die INB aktiv.
Getroffene Entscheidungen (Phase 1)
- Ablage: separater Baum
output/chunks/<scope>/<domaene>/<docslug>/(Option A). Das Voll-Dokument inoutput/processed/bleibt der primaere Feed. - Chunks getrennt vom approved-Feed (Parent-Document-Muster ueber
parent_url/parent_hash). - Per-Quelle aktivierbar ueber
options.chunk(Defaultoff); gemeinsame Defaults inconfig/chunking.yaml, pro Quelle ueberschreibbar (effective_opts). - Nur deterministische, embedding-freie Strategien (
headings | faq | recursive). - Contextual Retrieval (deterministisch): Kontext-Vorspann je Chunk
(
> Kontext: <Dokument> > <Abschnitt>), kein LLM/Embedding. - Inkrementell: jeder Chunk traegt
parent_hash(Inhalt) +chunk_fingerprint(wirksame Optionen/Strategie). Es wird nur neu gechunkt, wenn sich einer der beiden aendert; deaktivierte Orte/verwaiste Chunks werden entfernt. Laeuft am Ende vonsrc.mainautomatisch mit. - Lauf:
python -m src.chunk --data output(offline aufoutput/processed). Erste Aktivierung: INB 2026 + INB 2027 (chunk: headings).
Code: src/transformers/chunker.py (Logik), src/chunk.py (Runner), config/chunking.yaml
(Defaults), src/model.py (Chunk-Felder im Frontmatter).
Plan: Heading-basiertes Chunking (urspruengliches Konzept)
Ziel & Grundidee
Grosse Dokumente (v.a. INB, Regelwerke, lange Confluence-Baeume) sind als eine Markdown-Datei fuer Retrieval/Zitate unhandlich. Idee: zusaetzlich zur Voll-Datei Chunks entlang der Ueberschriften erzeugen.
Wichtig (Vorgabe):
- Die Voll-Datei bleibt immer erhalten (kein Informationsverlust, Single Source of Truth).
- Chunks sind additiv und abgeleitet -> jederzeit neu erzeugbar.
- Wir stellen die Vektor-DB NICHT. Wer anschliesst, soll die Wahl haben: Voll-Dokument einlesen oder die fertigen Chunks nutzen oder selbst chunken.
Warum an Ueberschriften?
- Strategie-uebergreifend nutzbar: das Chunking arbeitet auf dem erzeugten Markdown, nicht auf der Quelle. Damit ist es ein Transform-Schritt nach dem Extrahieren und funktioniert (potenziell) fuer ALLE Strategien.
- Ueberschriften sind die natuerliche, semantische Schnittkante.
- Befund INB-Hauptdokument 2026 (Review): ~751 KB, 746
##-Ueberschriften, davon 91 mit „Ziffer X.Y…" (z.B.7.3.1.1.1.1 Kapazität). Ideale Schnittpunkte + praezise Zitierbarkeit.
Eignung je Strategie
| Strategie | Ueberschriften vorhanden? | Chunking sinnvoll? |
|---|---|---|
pdf (pymupdf, INB/Regelwerk) |
ja (##), teils „Ziffer" |
sehr (grosse Dokumente) |
confluence_tree/page |
ja (Hn aus storage->md) | ja bei langen Seiten |
confluence_faq |
je Frage ### |
ja (1 Chunk je Frage/Antwort) |
sitemap/crawler (Web) |
meist (html2text #) |
mittel (Seiten oft kurz) |
file/gitlab_md |
ja (Markdown) | ja bei langen Dateien |
-> Generischer Helfer chunk_by_headings(markdown, level, min_chars) + Opt-in pro Quelle.
Chunk-Format (Vorschlag)
Jeder Chunk = eigene Markdown-Datei mit Frontmatter, das die Herkunft referenziert:
---
kind: "chunk" # Voll-Dokument: kind: "document" (Default)
parent_url: "<url der Voll-Quelle>"
parent_hash: "<content_hash der Voll-Datei>"
section: "7.3.1.1.1.1 Kapazität"
ziffer: "7.3.1.1.1.1" # nur wenn erkannt
chunk_index: 12
domain/tool/scope/tags/owners/contact/source: geerbt
content_hash: "<hash des Chunk-Texts>"
---
## 7.3.1.1.1.1 Kapazität
... Abschnittstext ...
- Heading bleibt im Chunk-Text (Chunk ist selbst-erklaerend).
- Stabiler Slug aus
ziffer/Heading; Kollision -> Index anhaengen.
Ablage (Entscheidung offen, s.u.)
- Option A: separater Baum
output/chunks/<scope>/<domaene>/<docslug>/NNN-...md. Vorteil:output/processed/bleibt „eine Datei pro Quelle/Seite", Chunks klar opt-in. - Option B: Unterordner neben der Voll-Datei:
output/processed/.../<docslug>.chunks/. Vorteil: Chunks liegen direkt beim Dokument.
Empfehlung: Option A (sauberer Feed; processed/ = Dokumente, chunks/ = abgeleitet).
Konfiguration (pro Quelle, additiv, Default AUS)
options:
chunk: headings # off (Default) | headings
chunk_level: 2 # welche Heading-Ebene schneidet (Default: kleinste vorhandene)
chunk_min_chars: 200 # kleinere Chunks mit Vorgaenger zusammenfassen
INB-Quellen bekaemen chunk: headings. Alles andere bleibt zunaechst aus.
Umsetzungs-Skizze (spaeter)
src/transformers/chunker.py:chunk_by_headings(md, level, min_chars) -> [(section, ziffer, text)]make_chunks(doc) -> list[Document](erbt Metadaten, setzt kind/parent/section/ziffer).
src/model.py:Documentumkind,parent_url,parent_hash,section,ziffer,chunk_indexerweitern (Frontmatter).src/main.py: nach Filter/Freigabe, wennsource.options.chunk == "headings"und Docapproved-> Chunks erzeugen und ueber das Gate schreiben (nachoutput/chunks/).src/store.py+src/site.py:kindlesen; auf der Uebersicht Chunks standardmaessig ausblenden (Toggle „Chunks anzeigen"), damit die Bestandszahlen (Dokumente) sauber bleiben; eigener Zaehler fuer Chunks.- Robustheit: Mini-Chunks zusammenfassen, sehr grosse optional spaeter weiter teilen (Absatz/Token-Budget, evtl. Overlap).
- Tests: Splitten je Level, Mini-Merge, Ziffer-Extraktion, Parent-Verknuepfung, content_hash stabil.
Phasen
- Phase 1: generischer Chunker + nur fuer INB aktiv; zweites Artefakt; UI-Toggle.
- Phase 2: weitere grosse Dokumente (Regelwerk, lange Confluence-Baeume).
- Phase 3 (optional): token-bewusstes Sub-Splitting + Overlap.
Offene Entscheidungen
- Ablage:
output/chunks/(Option A, empfohlen) vs. Unterordner beim Dokument (Option B). - Chunks in den „approved Feed" (
output/processed/) aufnehmen oder bewusst getrennt halten (Empfehlung: getrennt, damit Voll-Dokument der primaere Feed bleibt). - Heading-Ebene: automatisch kleinste vorhandene vs. pro Quelle konfiguriert.
- Mini-/Max-Groessen (
chunk_min_chars, spaeter Token-Budget). - Reihenfolge: zuerst INB (Phase 1) – ja/nein.
Recherche (Stand 2025/2026) & begruendete Empfehlungen
Quellen (Inhalte fuer Compliance umformuliert, keine Originalzitate): Weaviate-/Firecrawl-Ueberblick, Digital Applied – Retrieval Playbook 2026, CustomGPT – Chunking Strategies, Langcopilot – Practical Guide, Airbyte – Chunking Strategies, Anthropic – Contextual Retrieval.
Was die Forschung sagt (verdichtet)
- Chunking entscheidet stark ueber die Qualitaet – mehr als die Modellwahl. Ein Weaviate-Benchmark (Sept 2025) misst bis zu ~9 % Unterschied bei Recall zwischen bester und schlechtester Methode (gleicher Korpus/Retriever).
- Recursive Splitting (erst an Ueberschriften, dann Absaetze, Saetze, Woerter) gilt breit als bester Allrounder/Default (gute Balance Qualitaet/Kosten).
- Struktur-/Heading-basiertes Splitting ist ideal fuer technische Dokumente mit klarer Gliederung – genau unser INB/Regelwerk-Fall.
- Semantic Chunking bringt nochmal Genauigkeit, ist aber deutlich teurer (mehrfache Rechenkosten, teils ~14x langsamer) – eher spaeter/optional.
- Overlap bringt laut neueren Analysen (Jan 2026) kaum messbaren Nutzen -> als Default 0, nur optional aktivierbar.
- Chunk-Groesse: verbreiteter Richtwert ~400–800 Tokens; sehr grosse Chunks (Richtung ~2,5k Tokens „context cliff") verschlechtern Treffer.
- Contextual Retrieval (Anthropic): jedem Chunk einen kurzen Kontext voranstellen (Dokumenttitel + Abschnittspfad) reduziert Retrieval-Fehler erheblich. Deterministisch (ohne LLM) machbar, indem wir die Heading-Breadcrumb in jeden Chunk schreiben.
- Parent-Document-Retrieval: kleine Chunks zum Finden, grosses Dokument zum Antworten. Das ist genau das gewuenschte Muster „ein Dokument + zugehoerige Chunks".
Empfehlungen zu den offenen Entscheidungen
1) Ablage: separater Baum output/chunks/ (EMPFOHLEN)
- Pro:
output/processed/bleibt „eine Datei pro Quelle/Seite" = stabiler, einfacher Feed; Chunks sind klar als abgeleitet/optional erkennbar; getrennt loeschbar/regenerierbar; Bestandszahlen auf den Pages bleiben sauber. - Contra: zwei Wurzelverzeichnisse; Konsument muss wissen, dass es beides gibt
(loesen wir per Frontmatter
parent_*+ Doku auf der Chatbot-Seite). - Alternative B (Unterordner beim Dokument) vermischt Voll-Doc und Chunks im selben Baum -> Feed wird unuebersichtlich. Daher A.
2) Chunks NICHT in den primaeren output/processed-Feed (EMPFOHLEN)
- Voll-Dokument bleibt der primaere, eindeutige Feed (1 Seite = 1 Datei). Chunks liegen
in
output/chunks/mitparent_url/parent_hash-> klassisches Parent-Document-Muster. - Konsument hat die Wahl: nur
processed/(grob), nurchunks/(fein) oder beides (Parent-Document-Retrieval). Wir geben die Vektor-DB nicht vor -> maximale Flexibilitaet.
3) Heading-Ebene: automatisch kleinste sinnvolle, pro Quelle ueberschreibbar
- Default: feinste durchgaengig vorhandene Ebene erkennen (INB:
##). chunk_level: Nerlaubt manuelles Setzen, falls die Auto-Erkennung schlecht trifft.
4) Groessen/Overlap (Defaults, grounded)
chunk_min_chars: 200(Mini-Abschnitte mit Vorgaenger zusammenfassen).chunk_max_charsoptional (z.B. ~4–6k Zeichen ≈ ~1–1.5k Tokens); zu grosse Abschnitte fallen per Recursive-Sub-Split kleiner.chunk_overlap: 0als Default (Overlap nur optional).- Breadcrumb-Prefix je Chunk (Dokumenttitel + Abschnittspfad) standardmaessig AN (billiger Contextual-Retrieval-Effekt).
5) Reihenfolge: zuerst INB (Phase 1) – JA.
Chunk-Strategien als Menue (was die Tool-Eintragenden waehlen koennen)
Pro Quelle ueber options.chunk waehlbar (Default off):
chunk: Wert |
Was passiert | Wofuer geeignet |
|---|---|---|
off (Default) |
kein Chunking, nur Voll-Datei | kurze Seiten, Kundeninfos |
headings |
Split an Markdown-Ueberschriften (chunk_level) |
INB, Regelwerk, lange Confluence-Baeume |
recursive |
Ueberschriften -> Absaetze -> Saetze, Zielgroesse chunk_size |
Doks ohne saubere Gliederung (manche PDFs/Webseiten) |
faq |
je Frage/Antwort ein Chunk (Spezialfall headings auf ###) |
confluence_faq |
pages |
ein Chunk je PDF-Seite | PDFs mit unbrauchbaren Ueberschriften |
Zusatz-Optionen (alle optional): chunk_level, chunk_size, chunk_min_chars,
chunk_max_chars, chunk_overlap, chunk_breadcrumb: true|false.
Nicht im ersten Wurf (spaeter): semantic (Embedding-basiert, teuer) und
contextual (LLM-generierter Kontext je Chunk) – beide hohe Kosten, erst wenn Bedarf.
Empfohlener Startpunkt
- Generischen
headings- +recursive-Splitter bauen, Breadcrumb-Prefix an, Overlap 0, Ablageoutput/chunks/, Chunks getrennt vom Feed,parent_*im Frontmatter. - Phase 1 nur fuer INB aktiv (
chunk: headings), dann Treffer evaluieren, dann ausweiten.
Recherche (Stand 2026) & fundierte Empfehlungen
Quellen (Auswahl, paraphrasiert; Inhalte zur Lizenzkonformitaet umformuliert):
- Firecrawl – Best Chunking Strategies for RAG (2026)
- Digital Applied – RAG Chunking Playbook (Mai 2026)
- customgpt.ai – RAG Chunking Strategies
- langcopilot – Document Chunking for RAG (2026)
- denser.ai – 8 Methods Compared
Was die Recherche zeigt (Kernbefunde)
- Die Chunk-Strategie beeinflusst die Retrieval-Qualitaet oft staerker als das Modell. Ein Weaviate-Benchmark (Sept 2025) nennt bis zu ~9 % Unterschied in der Trefferquote zwischen bester und schlechtester Methode auf demselben Korpus.
- Struktur-/dokumentbewusstes Chunking (Ueberschriften, Tabellen, Codebloecke erhalten) gilt als entscheidend fuer strukturierte Inhalte; customgpt.ai berichtet hier deutliche Genauigkeitsgewinne. Genau das sind die INB/Regelwerke.
- Recursive Splitting (~400-800 Token, 10-20 % Overlap) ist der gaengige Allzweck-Default.
- Semantisches Chunking kann die Trefferquote spuerbar heben, ist aber teuer (jeder Satz wird eingebettet, teils ~14x langsamer) -> braucht ein Embedding-Modell.
- Overlap-Mythos: eine Analyse (Jan 2026) findet kaum messbaren Nutzen von Overlap; bei semantischen Schnittkanten (Ueberschriften) ist Overlap ohnehin weniger noetig.
- „Context Cliff" ~2.5k Token: sehr grosse Chunks „verwaessern" das Embedding -> Obergrenze sinnvoll.
- Contextual Retrieval (Anthropic): ein kurzer Kontext-Vorspann pro Chunk (z.B. Dokumenttitel + Abschnittspfad) reduziert Retrieval-Fehler stark -> billig & deterministisch machbar.
Was das fuer UNS bedeutet (wichtige Einordnung)
Wir stellen die Vektor-DB nicht und wollen deterministische, reproduzierbare Artefakte in Git. Daraus folgt eine klare Linie:
- Wir liefern, was man ohne Embedding-Modell sauber erzeugen kann: strukturerhaltende, ueberschriften-basierte Chunks + saubere Voll-MD. Das ist laut Recherche der mit Abstand wichtigste Hebel („clean, document-aware input").
- Semantisches / late / contextual-embedding-Chunking gehoert zum Anschliesser (er hat Embedding-Modell + Vektor-DB). Wir wuerden es NICHT fest verdrahten – wir liefern die ideale Vorlage dafuer.
- Deshalb ist „ein Voll-Dokument + zugehoerige Chunks" genau richtig: maximale Wahl, kein Lock-in.
Empfehlung je offener Entscheidung
| Entscheidung | Optionen | Empfehlung | Begruendung |
|---|---|---|---|
| Ablage | (A) separater Baum output/chunks/<scope>/... · (B) Unterordner beim Dok · (C) in output/processed/ |
A | Voll-Dok bleibt der primaere, eindeutige Feed; Chunks klar opt-in/abgeleitet; Konsument waehlt „processed ODER chunks" ohne Doppel-Embedding. |
| Chunks in approved-Feed? | rein / getrennt | getrennt | Verhindert, dass derselbe Inhalt doppelt im Index landet; output/processed bleibt „eine Datei pro Quelle". |
| Heading-Ebene | fix / auto / konfigurierbar | konfigurierbar mit smartem Default (kleinste sinnvolle Ebene; klein -> mergen, gross -> bis Zielband teilen) | Recursive-Prinzip: Struktur respektieren, aber Zielgroesse halten (gegen Mini-Fragmente & Context Cliff). |
| Zielgroesse | – | ~300-1200 Token Band, hartes Max < ~2000 Token | gaengiger Default-Korridor; unter Context Cliff. |
| Overlap | 0 / 10-20 % | Default 0 (optional aktivierbar) | „Overlap-Mythos"; Ueberschriften sind semantische Grenzen. |
| Kontext-Vorspann | aus / an | an (empfohlen): 1 Zeile „aus > " je Chunk | Contextual-Retrieval-Effekt, deterministisch, billig. |
Chunk-Strategien als Menue fuer Tool-Eintragende
Pro Quelle waehlbar ueber options.chunk (Default off). Bewusst nur deterministische,
embedding-freie Verfahren – Semantik-Chunking bleibt dem Anschliesser:
chunk: |
Was es tut | Wann nutzen |
|---|---|---|
off (Default) |
nur Voll-Dokument | kurze Seiten, Standard |
headings |
schneidet an Markdown-Ueberschriften; klein -> mergen, gross -> bis Zielband; ziffer/Abschnitt als Metadatum |
strukturierte, lange Dokumente (INB, Regelwerk, lange Confluence-Baeume) |
faq |
ein Chunk je Frage/Antwort | confluence_faq-Quellen |
recursive |
groessenbasiert: Absatz -> Satz bis Zielband (ohne Embeddings) | lange Dokumente ohne brauchbare Ueberschriften |
pages (spaeter) |
ein Chunk je PDF-Seite | paginierte PDFs (gewann NVIDIA-2024-Benchmark fuer paginierte Docs) |
Gemeinsame Optionen: chunk_target_tokens (Default ~500), chunk_max_tokens (~1800),
chunk_min_chars (~200), chunk_overlap (Default 0), chunk_context_header (Default an).
Bewusst NICHT angeboten (Begruendung dokumentieren): semantic/late/contextual-embedding
-> brauchen ein Embedding-Modell und gehoeren in die Vektor-DB des Anschliessers. Wir liefern
dafuer die saubere, strukturierte Vorlage.
Empfohlener Startpunkt (Phase 1)
INB-Quellen: chunk: headings, chunk_level: auto, chunk_target_tokens: 500,
chunk_max_tokens: 1800, chunk_overlap: 0, chunk_context_header: on. Ablage unter
output/chunks/allgemein/regulierung/inb-2026/<ziffer-oder-slug>.md. Voll-MD bleibt
unveraendert in output/processed/.