Стратегии разбиения длинных текстов
Подходы с блоками фиксированного размера, границами предложений и смысловым разбиением
«Стратегии разбиения длинных текстов» — бесплатный урок AI Prompt Engineering на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Prompt Engineering, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Prompt Engineering содержит 4 уроков всего.
Почему длинные документы представляют сложность
У LLM есть контекстное окно — максимальное количество токенов, которое они могут обработать за один раз. GPT-4 поддерживает 128k токенов, Claude — 200k, но многие документы превышают даже эти ограничения. Что ещё важнее, исследования показывают, что точность модели часто снижается при работе с очень длинным контекстом. Разбиение на фрагменты — это разделение документов на небольшие части перед обработкой.
Разбиение на фрагменты фиксированного размера
Разбиение на фрагменты фиксированного размера разделяет текст через каждые N токенов (или символов), не учитывая границы содержания. Это самая простая стратегия, не требующая семантического понимания.
Обычный размер фрагмента: 500–1000 токенов. Фрагменты легко индексировать и извлекать, но предложения могут разрываться посередине, из-за чего на границах теряется смысл.
import tiktoken
def fixed_chunk(text, max_tokens=1000):
enc = tiktoken.get_encoding('cl100k_base')
tokens = enc.encode(text)
chunks = []
for i in range(0, len(tokens), max_tokens):
chunk_tokens = tokens[i:i + max_tokens]
chunks.append(enc.decode(chunk_tokens))
return chunks
chunks = fixed_chunk(long_document)
print(f'Total chunks: {len(chunks)}')Компромиссы при разбиении на фрагменты фиксированного размера
Преимущества:
- Простота реализации — обработка естественного языка не требуется
- Предсказуемый размер фрагментов — проще контролировать затраты на вызовы интерфейса
- Быстрая обработка
Недостатки:
- Разрывает границы предложений и абзацев
- Предложение, разделённое между фрагментами, теряет контекст при поиске
- Плохо подходит для составления краткого содержания — фрагмент может заканчиваться посреди аргумента
Разбиение по границам предложений
Разбиение по границам предложений разделяет текст по естественным границам предложений или абзацев. Каждый фрагмент заканчивается полной точкой, поэтому предложение не разрывается пополам. В результате фрагменты получаются более читабельными и связными.
Используйте токенизатор предложений (spaCy или NLTK), чтобы обнаружить границы, а затем объединяйте предложения, пока фрагмент не достигнет целевого размера.
import spacy
nlp = spacy.load('en_core_web_sm')
def sentence_chunk(text, max_tokens=1000):
doc = nlp(text)
sentences = [sent.text.strip() for sent in doc.sents]
chunks, current, count = [], [], 0
for sent in sentences:
word_count = len(sent.split())
if count + word_count > max_tokens and current:
chunks.append(' '.join(current))
current, count = [], 0
current.append(sent)
count += word_count
if current:
chunks.append(' '.join(current))
return chunksСемантическое разбиение на фрагменты
Семантическое разбиение идёт дальше — оно разделяет текст при смене темы. Получая векторные представления соседних предложений и измеряя сходство по косинусу, можно определить, когда обсуждение переходит к новой теме.
Когда сходство опускается ниже порогового значения, вставляйте границу фрагмента. В результате получаются тематически цельные фрагменты, идеально подходящие для генерации с дополнением поиска (RAG).
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity
import numpy as np
model = SentenceTransformer('all-MiniLM-L6-v2')
def semantic_chunk(sentences, threshold=0.75):
embeddings = model.encode(sentences)
chunks, current = [], [sentences[0]]
for i in range(1, len(sentences)):
sim = cosine_similarity(
[embeddings[i-1]], [embeddings[i]]
)[0][0]
if sim < threshold:
chunks.append(' '.join(current))
current = []
current.append(sentences[i])
if current:
chunks.append(' '.join(current))
return chunksСравнение трёх стратегий
Вот параллельное сравнение, которое поможет сделать выбор:
- Фиксированный размер: самые быстрые, но с наименее точными границами — используйте для простых конвейеров
- Границы предложений: сохраняют целостность предложений — используйте, когда важна связность
- Семантическое разбиение: обеспечивает лучшую тематическую цельность — используйте для RAG, когда критически важен точный поиск
На практике семантическое разбиение увеличивает задержку из-за вычисления векторных представлений. Выбирайте стратегию с учётом требований к точности поиска.
Разбиение на фрагменты для задач поиска
Для генерации с дополнением поиска (RAG) фрагменты становятся единицами поиска. Запрос пользователя преобразуется в векторное представление, после чего извлекаются наиболее похожие фрагменты и добавляются в промпт.
Небольшие фрагменты (200–400 токенов) повышают точность поиска — каждый фрагмент содержит одну чётко выделенную мысль. Более крупные фрагменты (800–1000 токенов) дают больше контекста, но вместе с релевантным отрывком могут содержать и не относящийся к делу материал.
import openai
import numpy as np
client = openai.OpenAI(api_key='sk-...')
def embed(text):
resp = client.embeddings.create(
model='text-embedding-3-small',
input=text
)
return np.array(resp.data[0].embedding)
def retrieve(query, chunks, top_k=3):
q_emb = embed(query)
scores = [(i, np.dot(q_emb, embed(c))) for i, c in enumerate(chunks)]
scores.sort(key=lambda x: x[1], reverse=True)
return [chunks[i] for i, _ in scores[:top_k]]Разбиение на фрагменты для задач суммаризации
Для суммаризации фрагменты должны быть достаточно большими, чтобы содержать полный аргумент или раздел. Хорошо работают фрагменты по границам предложений размером 600–800 токенов.
Каждый фрагмент суммируется отдельно (этап сопоставления), затем сводки объединяются в итоговую сводку (этап сведения). Это классический паттерн «сопоставление — сведение», который рассматривается в следующем уроке.
Перекрытие: устранение разрывов между фрагментами
Один из практических способов уменьшить количество ошибок на границах — добавить перекрытие между фрагментами. Последние 100–200 токенов фрагмента N повторяются в начале фрагмента N+1.
Перекрытие гарантирует, что предложение, проходящее через границу, полностью присутствует хотя бы в одном фрагменте. Это особенно важно для поиска: запрос о теме, проходящей через границу, совпадёт с перекрывающимся фрагментом.
def fixed_chunk_with_overlap(text, max_tokens=1000, overlap=200):
enc = tiktoken.get_encoding('cl100k_base')
tokens = enc.encode(text)
chunks = []
step = max_tokens - overlap
for i in range(0, len(tokens), step):
chunk_tokens = tokens[i:i + max_tokens]
chunks.append(enc.decode(chunk_tokens))
if i + max_tokens >= len(tokens):
break
return chunksОбогащение каждого фрагмента метаданными
Каждый фрагмент должен содержать метаданные, чтобы последующие этапы могли определить его источник:
source: имя файла или URLpage: номер страницыchunk_index: позиция в документеsection: глава или заголовок
Эти метаданные хранятся вместе с векторным представлением в векторной базе данных (Pinecone, Chroma, Weaviate) и возвращаются вместе с найденными фрагментами, чтобы LLM могла ссылаться на источники.
def chunk_with_metadata(text, source='doc.pdf', page=1):
chunks = fixed_chunk_with_overlap(text)
return [
{
'text': chunk,
'metadata': {
'source': source,
'page': page,
'chunk_index': i
}
}
for i, chunk in enumerate(chunks)
]Выбор подходящей стратегии
Краткое руководство по выбору:
- Скорость — приоритет, содержимое — связный текст: разбиение по границам предложений
- Точность поиска критически важна: семантическое разбиение с небольшими фрагментами (300 токенов)
- Составление краткого содержания книги или отчёта: разбиение по границам предложений, более крупные фрагменты (800 токенов), сопоставление — сведение
- Юридические и технические документы: семантическое разбиение, чтобы сохранять пункты целиком
Всегда измеряйте полноту поиска на репрезентативной выборке запросов, прежде чем остановиться на определённой стратегии.
Проверка знаний
Какая стратегия разбиения на фрагменты разделяет текст, когда косинусное сходство между векторными представлениями соседних предложений опускается ниже порогового значения?
Повторение: стратегии разбиения на фрагменты
Вы изучили три основные стратегии разбиения на фрагменты:
- Фиксированного размера: разделение каждые N токенов — быстро, просто, без учета границ
- По границам предложений: разделение в естественных местах окончания предложений — связно, умеренная сложность
- Семантическая: разделение при смене темы на основе сходства векторных представлений — наиболее точно, самые высокие затраты
Добавляйте перекрытие между фрагментами, чтобы уменьшить количество ошибок на границах, и всегда прикрепляйте метаданные (источник, страницу, индекс), чтобы обеспечить цитирование и отслеживаемость. В следующем уроке рассматривается паттерн суммаризации MapReduce.
Часто задаваемые вопросы
Урок «Стратегии разбиения длинных текстов» бесплатный?
Да — полный текст урока «Стратегии разбиения длинных текстов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Prompt Engineering, подпишись на CoddyKit PRO. Курс AI Prompt Engineering содержит 4 уроков всего.
Чему я научусь в уроке «Стратегии разбиения длинных текстов»?
Подходы с блоками фиксированного размера, границами предложений и смысловым разбиением Ты практикуешь AI Prompt Engineering с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Prompt Engineering?
Предыдущий опыт не требуется. AI Prompt Engineering на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Стратегии разбиения длинных текстов»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Prompt Engineering?
Да. Каждый урок AI Prompt Engineering включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Стратегии разбиения длинных текстов
- Шаблон обобщения Map-Reduce
- Иерархическое обобщение
- Сохранение контекста между блоками