Strategier for oppdeling: fast størrelse, setninger eller rekursivt
Implementer og sammenlign tekstdelere basert på fast størrelse, setningsgrenser og rekursive tegn, og forstå hvordan delestørrelse og overlapp påvirker kvaliteten på uthentingen.
Strategier for oppdeling: fast størrelse, setninger eller rekursivt er en gratis leksjon i AI Engineering Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i AI Engineering Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i AI Engineering Academy inneholder totalt 4 leksjoner.
Hvorfor kvaliteten på tekstbitene er viktig
Oppdeling i tekstbiter er prosessen med å dele innlastede dokumenter i mindre deler som får plass i LLM-ens kontekstvindu, og som kan indekseres og hentes individuelt. Måten De deler opp teksten på, påvirker kvaliteten på søket mer enn nesten alle andre faktorer. Hvis en tekstbit deler et svar mellom to deler, er ingen av delene alene tilstrekkelig til å besvare spørsmålet. En tekstbit som blander to urelaterte emner, blir hentet ved spørsmål om begge, men er nyttig for ingen av dem.
Oppdeling i tekstbiter med fast størrelse
Oppdeling i tekstbiter med fast størrelse deler tekst i biter med nøyaktig N tegn eller N token, uavhengig av setnings- eller avsnittsgrenser. Dette er den enkleste strategien og er rask å implementere. Den største ulempen er at den ofte deler setninger i to, slik at tekstbiter begynner eller slutter midt i en tanke. Dette kan aksepteres for tett, ensartet formatert tekst, for eksempel databaseeksporter, men gir dårlig søkekvalitet for fortellende prosa eller teknisk dokumentasjon.
def fixed_size_chunks(text, chunk_size=500, overlap=50):
'''Split text into fixed-size character chunks with overlap'''
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunk = text[start:end]
chunks.append(chunk)
start += chunk_size - overlap # overlap keeps context at boundaries
return chunks
example = 'This is a long document. ' * 100
chunks = fixed_size_chunks(example, chunk_size=200, overlap=20)
print(f'Produced {len(chunks)} chunks, first: {chunks[0][:80]}...')Legge til overlapp i tekstbiter med fast størrelse
Den viktigste forbedringen av oppdeling i tekstbiter med fast størrelse er overlapp: hver tekstbit deler N tegn med den forrige tekstbiten. Dette sikrer at informasjon nær grensen mellom tekstbiter finnes i begge nabotekstbitene. Med 50–100 token overlapp vil en setning som krysser en grense, være fullstendig med i minst én av de to tekstbitene. Større overlapp gir bedre dekning, men også større indeks og mer overflødig innhold i søkeresultatene.
# Overlap example with a sentence at the boundary
text = 'A B C D E F G H I J'
chunk_size = 6 # characters
overlap = 2
i = 0
while i < len(text):
print(repr(text[i:i+chunk_size]))
i += chunk_size - overlap
# Output shows overlapping content:
# 'A B C D'
# 'C D E F'
# 'E F G H'
# Each adjacent pair shares 2 charsOppdeling ved setningsgrenser
Oppdeling ved setningsgrenser bruker NLP-biblioteker som nltk eller spacy til å finne slutten på setninger før teksten deles opp. Dette garanterer at ingen setning deles i to. Setninger samles til den neste setningen ville overskredet målstørrelsen, og deretter startes en ny tekstbit. Resultatet er tekstbiter som alltid inneholder hele tanker, noe som gir betydelig bedre embedding-kvalitet enn oppdeling etter et fast antall tegn.
import nltk
nltk.download('punkt', quiet=True)
def sentence_chunks(text, max_tokens=300):
sentences = nltk.sent_tokenize(text)
chunks = []
current = []
current_len = 0
for sent in sentences:
sent_tokens = len(sent.split())
if current_len + sent_tokens > max_tokens and current:
chunks.append(' '.join(current))
current = []
current_len = 0
current.append(sent)
current_len += sent_tokens
if current:
chunks.append(' '.join(current))
return chunksRekursiv oppdeling av tekst etter tegn
Rekursiv tegnoppdeling er den mest brukte strategien i RAG-systemer i produksjon. Den prøver et hierarki av skilletegn i rekkefølge: først avsnittsbrudd (\n\n), deretter linjeskift (\n), så punktum som avslutter setninger, mellomrom og til slutt enkelttegn. Den deler ved den største meningsfulle grensen som holder tekstbiten under målstørrelsen, og resultatet er tekstbiter som respekterer dokumentstrukturen i størst mulig grad.
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # target size in characters
chunk_overlap=200, # overlap between consecutive chunks
separators=['\n\n', '\n', '. ', '! ', '? ', ' ', ''],
length_function=len
)
with open('document.txt') as f:
text = f.read()
chunks = splitter.split_text(text)
print(f'Split into {len(chunks)} chunks')
for i, chunk in enumerate(chunks[:3]):
print(f'Chunk {i}: {len(chunk)} chars — {chunk[:60]}...')Token-bevisst oppdeling
Antall tegn er en upresis tilnærming til antall token. En tekstbit på 1000 tegn kan være på 200 eller 400 token, avhengig av ordlengde og språk. For presis kontroll deler De opp etter token-antall ved hjelp av tiktoken. Dette er viktig for å tilpasse tekstbiter til modellens kontekstvindu og for nøyaktig kostnadsberegning. LangChains TokenTextSplitter pakker inn tiktoken for token-bevisst oppdeling.
from langchain_text_splitters import TokenTextSplitter
import tiktoken
# Split by actual token count, not characters
splitter = TokenTextSplitter(
encoding_name='cl100k_base', # GPT-4 tokenizer
chunk_size=256, # target tokens per chunk
chunk_overlap=32 # overlap in tokens
)
chunks = splitter.split_text(text)
# Verify token count
enc = tiktoken.get_encoding('cl100k_base')
for chunk in chunks[:3]:
tokens = len(enc.encode(chunk))
print(f'Chunk: {tokens} tokens')Velge riktig størrelse på tekstbitene
Størrelsen på tekstbitene er en kritisk hyperparameter. Små tekstbiter (100–200 token) er presise – de inneholder tett fokusert informasjon som egner seg godt for embedding. Men de mister omkringliggende kontekst, slik at LLM-en kanskje ikke har nok informasjon til å svare. Store tekstbiter (500–1000 token) gir mer kontekst, men embeddingene deres blir et gjennomsnitt over et bredere emne, noe som gjør dem vanskeligere å hente ved spesifikke spørsmål. De fleste produksjonssystemer bruker 256–512 token og tester empirisk på egne data.
Legge til kontekst i tekstbiter
En kraftig forbedring er kontekstuelle tekstbitoverskrifter: legg dokumenttittelen og seksjonsoverskriften foran teksten i hver tekstbit før embedding. Da fanger embedding-en ikke bare opp innholdet i tekstbiten, men også hvor den kom fra i dokumentet. En tekstbit som lyder Fordeler og ferieordning: Ansatte opptjener 15 dager årlig ..., hentes langt mer presist ved spørsmål om ferieordningen enn den samme teksten uten overskriften.
def create_contextual_chunks(doc, splitter):
title = doc['metadata'].get('title', '')
section = doc['metadata'].get('section', '')
text = doc['text']
raw_chunks = splitter.split_text(text)
contextual_chunks = []
for chunk in raw_chunks:
# Prepend document context to each chunk
context_header = f'{title}\n{section}\n\n' if title else ''
contextual_chunks.append({
'text': context_header + chunk,
'metadata': doc['metadata']
})
return contextual_chunksSammenligne strategier på egne data
Ingen strategi for oppdeling i tekstbiter er best i alle tilfeller. Lag en rask evaluering: Ta 20 spørsmål som De kjenner svarene på, kjør søk med hver oppdelingsstrategi, og mål hvor ofte den riktige tekstbiten rangeres blant de fem beste resultatene (treffrate@5). Dette tar en time å sette opp og sparer Dem for flere uker med gjetting. De vil ofte oppdage at det bestemte dokumentformatet Deres (tett juridisk prosa kontra strukturerte tekniske dokumenter) klart favoriserer én strategi fremfor de andre.
def evaluate_chunking_strategy(questions_and_answers, retriever):
hits = 0
for qa in questions_and_answers:
results = retriever.retrieve(qa['question'], top_k=5)
result_texts = [r['text'] for r in results]
# Check if answer text appears in any retrieved chunk
if any(qa['answer'] in text for text in result_texts):
hits += 1
hit_rate = hits / len(questions_and_answers)
print(f'Hit rate@5: {hit_rate:.1%} ({hits}/{len(questions_and_answers)})')
return hit_rateHåndtering av spesielle dokumenttyper
Noen dokumenttyper trenger spesialtilpasset oppdeling. kodefiler bør deles opp etter funksjons- eller klassegrenser, ikke etter antall tegn. Markdown-filer bør deles ved overskriftsgrenser, slik at hver tekstbit tilsvarer én seksjon. Tabeller bør holdes samlet som én tekstbit (hvis de deles midt i tabellen, blir innholdet uforståelig). Planlegg strategien for oppdeling basert på dokumenttypene i korpuset, i stedet for å bruke én løsning for alle.
from langchain_text_splitters import MarkdownHeaderTextSplitter
# Split Markdown by header hierarchy
md_splitter = MarkdownHeaderTextSplitter(
headers_to_split_on=[
('#', 'h1'),
('##', 'h2'),
('###', 'h3')
]
)
with open('documentation.md') as f:
md_text = f.read()
# Each chunk gets metadata from its heading hierarchy
chunks = md_splitter.split_text(md_text)
for chunk in chunks[:3]:
print('Section:', chunk.metadata)
print('Text:', chunk.page_content[:80])
print()Sporing av tekstbitenes opphav
Hver tekstbit trenger en stabil, unik ID som er avledet fra kildedokumentet og plasseringen. Bruk denne ID-en til å oppdatere bestemte tekstbiter når dokumenter endres, uten å indeksere hele korpuset på nytt. En deterministisk hash av kildebanen og tekstbitindeksen fungerer godt. Registrer også tekstbitens plassering i metadataene – for eksempel tekstbit 3 av 12 fra dokument X. Dette gjør det enklere å sette sammen hele seksjoner igjen når flere tekstbiter etter hverandre blir hentet sammen.
import hashlib
def assign_chunk_ids(chunks, source_path):
for i, chunk in enumerate(chunks):
key = f'{source_path}::chunk_{i}'
chunk_id = hashlib.sha256(key.encode()).hexdigest()[:16]
chunk['id'] = chunk_id
chunk['metadata']['chunk_index'] = i
chunk['metadata']['total_chunks'] = len(chunks)
return chunks
# IDs are stable across re-runs if source and position match
chunks = sentence_chunks(text)
chunks = [{'text': c, 'metadata': {}} for c in chunks]
assign_chunk_ids(chunks, 'docs/policy_v3.pdf')Kort kontroll
Test forståelsen Deres av AI Engineering-konseptene fra denne leksjonen.
Oppsummering av leksjonen
I denne leksjonen har De lært at oppdeling i tekstbiter med fast størrelse er enkelt, men deler setninger i to, at oppdeling ved setningsgrenser bevarer hele tanker, at rekursiv tegnoppdeling respekterer dokumentstrukturen og er det vanligste valget i produksjon, samt om avanserte teknikker, blant annet token-bevisst oppdeling, kontekstuelle overskrifter, spesialtilpassede oppdelere for Markdown og kode og stabile ID-er for trinnvise oppdateringer. Neste tema er hvordan De lager embedding-vektorer av disse tekstbitene og lagrer dem i en vektordatabase.
Lær deg Python med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 30
- Leksjoner
- 120
Ofte stilte spørsmål
Er leksjonen «Strategier for oppdeling: fast størrelse, setninger eller rekursivt» gratis?
Ja – hele teksten i «Strategier for oppdeling: fast størrelse, setninger eller rekursivt» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av AI Engineering Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i AI Engineering Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Strategier for oppdeling: fast størrelse, setninger eller rekursivt»?
Implementer og sammenlign tekstdelere basert på fast størrelse, setningsgrenser og rekursive tegn, og forstå hvordan delestørrelse og overlapp påvirker kvaliteten på uthentingen. Du øver på AI Engineering Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med AI Engineering Academy?
Ingen tidligere erfaring er nødvendig. AI Engineering Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Strategier for oppdeling: fast størrelse, setninger eller rekursivt»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne AI Engineering Academy-leksjonen?
Ja. Alle AI Engineering Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Laste inn dokumenter og hente ut tekst
- Strategier for oppdeling: fast størrelse, setninger eller rekursivt
- Indeksering: embedde og lagre deler
- Spørre, hente ut og generere