AI Engineering Academy · Lektion

Dokumentspezifische Strategien für Code und HTML

Setzen Sie spezialisiertes Chunking ein: für Python-Code mit AST-basierten Funktions-Splittern, für HTML mit Parsern, die Tags berücksichtigen, und für Markdown anhand der Hierarchie von Überschriften.

Lektion 4 von 413 Schritte

Dokumentspezifische Strategien für Code und HTML ist eine kostenlose AI Engineering Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des AI Engineering Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum generisches Chunking bei spezialisierten Dokumenten scheitert

Textbasiertes Chunking wurde für Fließtext entwickelt, reale Daten umfassen jedoch auch Quellcode, HTML-Seiten und Markdown-Dokumentation. Wird Code an einer festen Zeichengrenze geteilt, kann eine Funktion mitten in ihrem Rumpf getrennt werden, wodurch der Chunk für den Abruf unbrauchbar wird. Spezialisierte Dokumente benötigen Chunker, die ihre interne Struktur verstehen – nicht nur ihre Länge.

Python-Code-Chunking auf AST-Basis

Der Abstract Syntax Tree (AST) einer Python-Datei erfasst jede Funktion, Klasse und jedes Modul als strukturierten Knoten. Durch das Durchlaufen des AST können Sie jede Funktion oder Methode als eigenen Chunk extrahieren und dabei Signatur, Docstring und Rumpf zusammenhalten. LangChains PythonCodeTextSplitter verwendet intern diesen Ansatz.

import ast
import textwrap

def extract_functions(source_code: str) -> list[dict]:
    tree = ast.parse(source_code)
    chunks = []
    for node in ast.walk(tree):
        if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)):
            start = node.lineno - 1
            end = node.end_lineno
            lines = source_code.splitlines()[start:end]
            chunks.append({
                'name': node.name,
                'code': '\n'.join(lines),
                'start_line': node.lineno,
            })
    return chunks

Chunking an Klassengrenzen

Bei objektorientierten Codebasen ist Chunking auf Klassenebene oft besser geeignet als auf Funktionsebene. Ein Klassen-Chunk erhält die Beziehung zwischen Methoden und dem gemeinsamen Zustand, auf den sie zugreifen. Sie können den Docstring der Klasse und alle Methodenrümpfe als einen einzigen Chunk aufnehmen und anschließend nur für lange Methoden separate, feiner aufgelöste Chunks erstellen.

from langchain_text_splitters import Language, RecursiveCharacterTextSplitter

python_splitter = RecursiveCharacterTextSplitter.from_language(
    language=Language.PYTHON,
    chunk_size=1000,
    chunk_overlap=100,
)

with open('my_module.py', 'r') as f:
    source = f.read()

chunks = python_splitter.create_documents([source])
print(f'Created {len(chunks)} code chunks')

Code-Metadaten zu Chunks hinzufügen

Unbearbeitete Code-Chunks sind nur so nützlich wie ihre Metadaten. Wenn Sie Code-Chunks in einer Vektordatenbank speichern, sollten Sie den Dateipfad, den Funktionsnamen, die Programmiersprache und den Zeilenbereich aufnehmen. Diese Metadaten ermöglichen es dem Retriever, nach Sprache oder Datei zu filtern, und dem LLM, in seiner Antwort die genaue Quellposition anzugeben.

from langchain_core.documents import Document

def chunk_python_file(filepath: str) -> list[Document]:
    with open(filepath) as f:
        source = f.read()

    functions = extract_functions(source)  # from previous example
    docs = []
    for fn in functions:
        docs.append(Document(
            page_content=fn['code'],
            metadata={
                'source': filepath,
                'function': fn['name'],
                'language': 'python',
                'start_line': fn['start_line'],
            }
        ))
    return docs

HTML: Struktur vor Zeichen

HTML-Dokumente sind hierarchisch strukturiert und bestehen aus Überschriften, Abschnitten, Absätzen und Listen. Das Aufteilen von HTML nach Zeichenanzahl schneidet häufig Tags durch und erzeugt fehlerhafte Fragmente. Der richtige Ansatz besteht darin, das HTML mit einem geeigneten Parser wie BeautifulSoup zu analysieren und semantisch aussagekräftige Elemente wie <article>-, <section>- und <p>-Tags zu extrahieren.

from bs4 import BeautifulSoup

def chunk_html_by_section(html: str) -> list[dict]:
    soup = BeautifulSoup(html, 'html.parser')
    chunks = []
    for tag in soup.find_all(['h1', 'h2', 'h3', 'p', 'li']):
        text = tag.get_text(separator=' ', strip=True)
        if len(text) > 40:  # skip trivial fragments
            chunks.append({
                'tag': tag.name,
                'text': text,
            })
    return chunks

Hierarchisches HTML-Chunking nach Überschriften

Eine anspruchsvollere HTML-Strategie gruppiert Inhalte unter ihrer jeweils nächstgelegenen Überschrift. Jeder Absatz und jede Liste nach einer <h2>-Überschrift gehört zu diesem Abschnitt. Indem Sie Text mit seiner übergeordneten Überschrift gruppieren, bewahren Sie den thematischen Kontext, den ein eigenständiger Absatz sonst verlieren würde. LangChains HTMLHeaderTextSplitter implementiert dies automatisch.

from langchain_text_splitters import HTMLHeaderTextSplitter

headers_to_split_on = [
    ('h1', 'Header 1'),
    ('h2', 'Header 2'),
    ('h3', 'Header 3'),
]

splitter = HTMLHeaderTextSplitter(headers_to_split_on=headers_to_split_on)

with open('page.html') as f:
    html = f.read()

sections = splitter.split_text(html)
for sec in sections[:3]:
    print(sec.metadata)
    print(sec.page_content[:200])
    print('---')

Markdown: Die Überschriftenhierarchie berücksichtigen

Markdown-Dokumentation ist mit Überschriften auf den Ebenen #, ## und ### organisiert. Der MarkdownHeaderTextSplitter teilt an Überschriftengrenzen und speichert die Überschriftenhierarchie in den Metadaten. Dadurch kennt jeder Chunk seinen vollständigen Überschriftenpfad, was die Relevanz des abgerufenen Kontexts deutlich verbessert, wenn Benutzer Fragen zu bestimmten Dokumentationsabschnitten stellen.

from langchain_text_splitters import MarkdownHeaderTextSplitter

headers_to_split_on = [
    ('#', 'H1'),
    ('##', 'H2'),
    ('###', 'H3'),
]

md_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)

with open('README.md') as f:
    markdown = f.read()

docs = md_splitter.split_text(markdown)
for doc in docs[:2]:
    print('Metadata:', doc.metadata)
    print('Content:', doc.page_content[:300])
    print()

Sekundäres Aufteilen nach dem Überschriften-Split

Auch nach dem Aufteilen anhand von Überschriften können einzelne Abschnitte für das Token-Limit Ihres Embedding-Modells noch zu lang sein. Empfohlen wird ein zweistufiges Aufteilen: Teilen Sie zunächst anhand der Überschriftenhierarchie, um den semantischen Kontext zu bewahren, und wenden Sie anschließend auf jeden Abschnitt, der Ihr Chunk-Größenlimit überschreitet, einen zeichenbasierten Splitter an. So ist kein Chunk zu groß, während die Überschriftenmetadaten erhalten bleiben.

from langchain_text_splitters import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitter

header_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=[('#', 'H1'), ('##', 'H2')]
)
char_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,
    chunk_overlap=50,
)

with open('docs.md') as f:
    md = f.read()

header_chunks = header_splitter.split_text(md)
final_chunks = char_splitter.split_documents(header_chunks)
print(f'{len(final_chunks)} final chunks produced')

PDFs mit Tabellenbewusstsein chunken

Mit Tools wie PyMuPDF oder pdfplumber extrahierte PDFs verlieren häufig ihre Tabellenstruktur, wodurch unleserliche Textzeilen entstehen. Verwenden Sie hierfür layoutbewusste PDF-Parser, die Begrenzungsrahmen von Tabellen erkennen und sie vor dem Chunking in Markdown- oder CSV-Format umwandeln. Behandeln Sie jede Tabelle als einen einzigen Chunk mit strukturierten Metadaten, die sie als Tabelle und nicht als Fließtext ausweisen.

import pdfplumber

def extract_pdf_chunks(pdf_path: str) -> list[dict]:
    chunks = []
    with pdfplumber.open(pdf_path) as pdf:
        for page_num, page in enumerate(pdf.pages):
            # Extract tables separately
            for table in page.extract_tables():
                rows = ['|'.join(str(c) for c in row) for row in table]
                chunks.append({
                    'type': 'table',
                    'content': '\n'.join(rows),
                    'page': page_num + 1,
                })
            # Extract prose text
            text = page.extract_text()
            if text:
                chunks.append({'type': 'text', 'content': text, 'page': page_num + 1})
    return chunks

Spracherkennung für gemischte Korpora

Wissensdatenbanken in Unternehmen enthalten oft verschiedene Dateitypen: Python-Skripte, API-Dokumentation in HTML, Architekturnotizen in Markdown und Datenexporte im CSV-Format. Eine robuste Chunking-Pipeline sollte den Dateityp erkennen, und zwar anhand der Erweiterung oder des MIME-Typs, und jedes Dokument an den passenden spezialisierten Chunker weiterleiten. So wird verhindert, dass Code-Splitting auf Fließtext oder umgekehrt angewendet wird.

from pathlib import Path

def route_document(filepath: str) -> list[dict]:
    ext = Path(filepath).suffix.lower()
    if ext == '.py':
        return chunk_python_file(filepath)
    elif ext in ('.html', '.htm'):
        with open(filepath) as f:
            return chunk_html_by_section(f.read())
    elif ext == '.md':
        # use MarkdownHeaderTextSplitter
        return chunk_markdown(filepath)
    elif ext == '.pdf':
        return extract_pdf_chunks(filepath)
    else:
        # fallback: plain text recursive splitter
        return chunk_plain_text(filepath)

Kontext durch umgebende Zeilen bewahren

Beim Chunking von Code nach Funktionen ist es oft sinnvoll, einige Zeilen umgebenden Kontext einzubeziehen, etwa Importanweisungen am Anfang der Datei oder die Klassendefinition, die eine Methode enthält. Dieser Kontext hilft dem LLM zu verstehen, welche Bibliotheken verfügbar sind und welche Rolle die Funktion innerhalb der übergeordneten Klasse spielt, wodurch sich die Qualität der generierten Antworten verbessert.

def chunk_with_imports(source_code: str, fn_node, lines: list[str]) -> str:
    # Gather top-of-file imports (first block before first non-import)
    import_lines = []
    for line in lines:
        stripped = line.strip()
        if stripped.startswith('import ') or stripped.startswith('from '):
            import_lines.append(line)
        elif stripped and not stripped.startswith('#'):
            break

    fn_body = '\n'.join(lines[fn_node.lineno - 1:fn_node.end_lineno])
    return '\n'.join(import_lines) + '\n\n' + fn_body

Kurze Überprüfung

Testen Sie Ihr Verständnis der dokumentspezifischen Chunking-Strategien aus dieser Lektion.

Zusammenfassung der Lektion

In dieser Lektion haben Sie gelernt: AST-basiertes Chunking bewahrt die Grenzen von Python-Funktionen und -Klassen, HTMLHeaderTextSplitter und MarkdownHeaderTextSplitter berücksichtigen die Überschriftenhierarchie, um den Kontext mit seinem Abschnitt zu verknüpfen, und ein zweistufiger Ansatz (Aufteilen nach Überschriften, gefolgt von zeichenbasiertem Aufteilen) verarbeitet übergroße Abschnitte, ohne strukturelle Metadaten zu verlieren. Als Nächstes untersuchen wir die hybride Suche, die dichten und sparsamen Abruf kombiniert.

Kostenlos starten

Lerne Python mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
30
Lektionen
120

Häufig gestellte Fragen

Ist die Lektion „Dokumentspezifische Strategien für Code und HTML“ kostenlos?

Ja — der vollständige Text von „Dokumentspezifische Strategien für Code und HTML“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des AI Engineering Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der AI Engineering Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Dokumentspezifische Strategien für Code und HTML“?

Setzen Sie spezialisiertes Chunking ein: für Python-Code mit AST-basierten Funktions-Splittern, für HTML mit Parsern, die Tags berücksichtigen, und für Markdown anhand der Hierarchie von Überschrifte… Du übst AI Engineering Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um AI Engineering Academy zu starten?

Keine Vorkenntnisse erforderlich. AI Engineering Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.

Wie lange dauert die Lektion „Dokumentspezifische Strategien für Code und HTML“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser AI Engineering Academy-Lektion Code schreiben und ausführen?

Ja. Jede AI Engineering Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Warum naives Chunking den Abruf verschlechtert
  2. Semantisches Chunking mit Embedding-Ähnlichkeit
  3. Parent-Child- und Small-to-Big-Retrieval
  4. Dokumentspezifische Strategien für Code und HTML
← Zurück zu AI Engineering Academy