Strategie specifiche per documenti di codice e HTML
Applichi un chunking specializzato al codice Python usando splitter di funzioni basati sull'AST, all'HTML usando parser consapevoli dei tag e a Markdown usando la gerarchia degli header.
Strategie specifiche per documenti di codice e HTML è una lezione AI Engineering Academy gratuita su CoddyKit. Questa è la lezione 4 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Engineering Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Engineering Academy include 4 lezioni in totale.
Perché il chunking generico non funziona con i documenti specializzati
Il chunking basato sul testo è stato progettato per la prosa, ma i dati del mondo reale includono codice sorgente, pagine HTML e documentazione Markdown. Suddividere il codice a un confine di caratteri fisso può interrompere una funzione nel mezzo del corpo, rendendo il chunk inutilizzabile per il recupero. I documenti specializzati richiedono chunker in grado di comprenderne la struttura interna, non solo la lunghezza.
Chunking del codice Python basato sull'AST
L'Abstract Syntax Tree (AST) di un file Python rappresenta ogni funzione, classe e modulo come un nodo strutturato. Percorrendo l'AST è possibile estrarre ogni funzione o metodo come chunk autonomo, mantenendo insieme firma, docstring e corpo. PythonCodeTextSplitter di LangChain utilizza internamente questo approccio.
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 chunksChunking in base ai confini delle classi
Per le basi di codice orientate agli oggetti, suddividere il codice a livello di classe è spesso preferibile alla suddivisione a livello di funzione. Un chunk relativo a una classe conserva la relazione tra i metodi e lo stato condiviso su cui operano. È possibile includere la docstring della classe e tutti i corpi dei metodi in un unico chunk, creando poi chunk separati e più granulari solo per i metodi lunghi.
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')Aggiunta dei metadati del codice ai chunk
I chunk di codice grezzo sono utili solo quanto i relativi metadati. Quando si archiviano i chunk di codice in un database vettoriale, è opportuno includere il percorso del file, il nome della funzione, il linguaggio di programmazione e l'intervallo di righe. Questi metadati consentono al retriever di filtrare in base al linguaggio o al file e all'LLM di citare nella risposta la posizione esatta della fonte.
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 docsHTML: la struttura prima dei caratteri
I documenti HTML sono strutturati gerarchicamente con titoli, sezioni, paragrafi ed elenchi. Suddividere l'HTML in base al numero di caratteri spesso interrompe i tag, producendo frammenti malformati. L'approccio corretto consiste nell'analizzare l'HTML con un parser appropriato come BeautifulSoup ed estrarre elementi semanticamente significativi, ad esempio i tag <article>, <section> e <p>.
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 chunksChunking HTML gerarchico basato sui titoli
Una strategia HTML più sofisticata raggruppa il contenuto sotto il titolo più vicino. Ogni paragrafo ed elenco successivo a un titolo <h2> appartiene a quella sezione. Raggruppando il testo con il titolo padre, si preserva il contesto dell'argomento che un paragrafo isolato perderebbe. HTMLHeaderTextSplitter di LangChain implementa automaticamente questo comportamento.
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: rispetto della gerarchia dei titoli
La documentazione Markdown è organizzata con i titoli #, ## e ###. MarkdownHeaderTextSplitter suddivide il testo ai confini dei titoli e memorizza la gerarchia dei titoli nei metadati. Ciò significa che ogni chunk conosce il proprio percorso completo di titoli, migliorando notevolmente la rilevanza del contesto recuperato quando gli utenti chiedono informazioni su sezioni specifiche della documentazione.
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()Suddivisione secondaria dopo quella basata sui titoli
Dopo la suddivisione in base ai titoli, le singole sezioni potrebbero essere ancora troppo lunghe per il limite di token del modello di embedding. Il pattern consigliato è una suddivisione in due passaggi: prima si suddivide in base alla gerarchia dei titoli per preservare il contesto semantico, poi si applica uno splitter basato sui caratteri alle sezioni che superano il limite di dimensione dei chunk. In questo modo nessun chunk è troppo grande e i metadati dei titoli vengono preservati.
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')Chunking dei PDF con gestione delle tabelle
I PDF estratti con strumenti come PyMuPDF o pdfplumber spesso perdono la struttura delle tabelle, producendo righe di testo confuse. Per gestire questo problema, utilizzi parser PDF consapevoli del layout, in grado di rilevare i riquadri delle tabelle e convertirli in formato Markdown o CSV prima del chunking. Tratti ogni tabella come un singolo chunk con metadati strutturati che la identifichino come tabella e non come prosa.
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 chunksRilevamento della lingua per corpora misti
Le basi di conoscenza aziendali spesso combinano diversi tipi di file: script Python, documentazione API in HTML, note sull'architettura in Markdown ed esportazioni di dati in CSV. Una pipeline di chunking solida dovrebbe rilevare il tipo di file dall'estensione o dal tipo MIME e indirizzare ogni documento al chunker specializzato appropriato. In questo modo si evita di applicare la logica di suddivisione del codice alla prosa, o viceversa.
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)Preservare il contesto con le righe circostanti
Quando si suddivide il codice in base alle funzioni, spesso è utile includere alcune righe di contesto circostante, ad esempio le istruzioni di importazione all'inizio del file o la definizione della classe che contiene un metodo. Questo contesto aiuta l'LLM a comprendere quali librerie sono disponibili e quale ruolo svolge la funzione all'interno della classe più ampia, migliorando la qualità delle risposte generate.
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_bodyVerifica rapida
Verifichi la Sua comprensione delle strategie di chunking specifiche per i documenti presentate in questa lezione.
Riepilogo della lezione
In questa lezione ha imparato che: il chunking basato sull'AST preserva i confini delle funzioni e delle classi Python, HTMLHeaderTextSplitter e MarkdownHeaderTextSplitter rispettano la gerarchia dei titoli per mantenere il contesto associato alla relativa sezione e un approccio in due passaggi (suddivisione per titoli seguita da suddivisione per caratteri) gestisce le sezioni troppo grandi senza perdere i metadati strutturali. Nel prossimo argomento esploreremo la ricerca ibrida, che combina il recupero denso e quello sparso.
Domande Frequenti
La lezione «Strategie specifiche per documenti di codice e HTML» è gratuita?
Sì — il testo completo di «Strategie specifiche per documenti di codice e HTML» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Engineering Academy, passa a CoddyKit PRO. Il corso AI Engineering Academy include 4 lezioni in totale.
Cosa imparerò in «Strategie specifiche per documenti di codice e HTML»?
Applichi un chunking specializzato al codice Python usando splitter di funzioni basati sull'AST, all'HTML usando parser consapevoli dei tag e a Markdown usando la gerarchia degli header. Eserciti AI Engineering Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare AI Engineering Academy?
Non è richiesta alcuna esperienza precedente. AI Engineering Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 4 di 4.
Quanto tempo richiede la lezione «Strategie specifiche per documenti di codice e HTML»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione AI Engineering Academy?
Sì. Ogni lezione AI Engineering Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Perché il chunking ingenuo danneggia il retrieval
- Chunking semantico con la similarità degli embedding
- Retrieval parent-child e small-to-big
- Strategie specifiche per documenti di codice e HTML