Работа с ограничениями контекстного окна
Работа с ограничениями контекстного окна
Контекстное окно — это ограничение на количество токенов, которые модель может обработать за один запрос (включая системный промпт, историю диалога, пользовательский запрос и ответ). Даже большие контекстные окна создают проблемы при работе с объемными документами, базами знаний или длинными диалогами.
Почему это критично
Проблема 1: Превышение лимита
Большие документы могут не помещаться в контекстное окно модели. Если добавить системный промпт, инструкции и оставить место для ответа, вы можете выйти за пределы доступного контекста.
Проблема 2: Деградация качества
Даже если документ помещается в окно, модели могут хуже работать с информацией в середине длинного контекста. Важные детали могут быть пропущены.
Проблема 3: Стоимость
Чем больше токенов в запросе, тем выше стоимость. Отправка большого количества токенов для ответа на простой вопрос экономически неэффективна.
Стратегия 1: Chunking (разбиение на части)
Разделите документ на логические части (chunks) и обрабатывайте их последовательно или параллельно.
Подход A: Последовательная обработка с аккумуляцией
document = load_large_document()
chunks = split_into_chunks(document, chunk_size=3000)
accumulated_insights = []
for i, chunk in enumerate(chunks):
prompt = f"""
Ты анализируешь часть {i+1} из {len(chunks)} большого документа.
Предыдущие находки: {accumulated_insights}
Текущая часть:
{chunk}
Найди ключевые риски и добавь к списку.
"""
result = llm.generate(prompt)
accumulated_insights.append(result)
# Финальная агрегация
final_summary = llm.generate(f"""
Объедини все найденные риски в итоговый отчет:
{accumulated_insights}
""")
Плюсы: Простота, работает с любым размером документа
Минусы: Медленно (N последовательных запросов), может терять связи между частями
Подход B: Параллельная обработка
chunks = split_into_chunks(document, chunk_size=3000)
# Обрабатываем все части параллельно
results = parallel_process([
f"Найди риски в этой части договора:\n{chunk}"
for chunk in chunks
])
# Агрегируем результаты
final_report = llm.generate(f"""
Объедини риски из всех частей документа в единый отчет:
{'\n\n'.join(results)}
Убери дубликаты и группируй по категориям.
""")
Плюсы: Быстрее (параллельные запросы)
Минусы: Может пропустить связи между частями, требует финальной агрегации
Стратегия 2: Map-Reduce подход
Классический паттерн для обработки больших данных:
- Map: Применить операцию к каждому chunk независимо
- Reduce: Объединить результаты в финальный ответ
Пример: Анализ тональности отзывов
# MAP фаза
reviews_chunks = split_reviews_into_batches(all_reviews, batch_size=50)
map_results = []
for chunk in reviews_chunks:
result = llm.generate(f"""
Проанализируй тональность отзывов. Для каждого укажи: позитивный/негативный/нейтральный.
Отзывы:
{chunk}
Формат ответа: JSON список [{{"id": 1, "sentiment": "positive"}}, ...]
""")
map_results.append(result)
# REDUCE фаза
final_stats = llm.generate(f"""
Агрегируй статистику по тональности:
{map_results}
Выведи:
- Общее распределение (позитивных/негативных/нейтральных)
- Топ-3 темы в негативных отзывах
- Топ-3 темы в позитивных отзывах
""")
Когда использовать: Задачи агрегации (статистика, суммаризация, классификация больших объемов)
Стратегия 3: Суммаризация с сохранением деталей
Для очень длинных документов создайте иерархию суммаризаций:
Исходный документ (большой объем)
↓
Суммаризация по главам (несколько саммари)
↓
Итоговое executive summary (краткое саммари)
Реализация
# Уровень 1: Суммаризация глав
chapters = split_by_chapters(document)
chapter_summaries = []
for chapter in chapters:
summary = llm.generate(f"""
Создай краткое саммари этой главы, сохраняя ключевые факты и цифры:
{chapter}
""")
chapter_summaries.append(summary)
# Уровень 2: Итоговое саммари
executive_summary = llm.generate(f"""
Создай executive summary документа на основе саммари глав:
{'\n\n'.join(chapter_summaries)}
Фокус: ключевые выводы и рекомендации.
""")
Важно: Сохраняйте промежуточные суммаризации для возможности drill-down в детали.
Стратегия 4: Приоритизация информации
Не вся информация одинаково важна. Используйте предварительную фильтрацию:
Пример: Поиск ответа в базе знаний
# Шаг 1: Семантический поиск релевантных секций
query = "Как настроить двухфакторную аутентификацию?"
relevant_sections = vector_search(knowledge_base, query, top_k=5)
# Шаг 2: Ранжирование по релевантности
ranked_sections = llm.generate(f"""
Оцени релевантность каждой секции для вопроса: "{query}"
Секции:
{relevant_sections}
Выведи ID секций в порядке убывания релевантности.
""")
# Шаг 3: Используем только топ-3 для финального ответа
top_sections = ranked_sections[:3]
answer = llm.generate(f"""
Ответь на вопрос на основе этих секций документации:
{top_sections}
Вопрос: {query}
""")
Стратегия 5: Streaming и итеративное уточнение
Для интерактивных сценариев используйте итеративный подход:
# Первый проход: быстрый анализ
quick_scan = llm.generate(f"""
Быстро просмотри документ и определи, в каких разделах может быть информация о рисках:
{document_table_of_contents}
""")
# Второй проход: детальный анализ только релевантных разделов
relevant_sections = extract_sections(document, quick_scan.section_ids)
detailed_analysis = llm.generate(f"""
Детально проанализируй эти разделы на риски:
{relevant_sections}
""")
Оптимизация размера chunks
Правильный размер chunk зависит от задачи:
| Задача | Рекомендуемый подход | Обоснование |
|---|---|---|
| Извлечение фактов | Небольшие chunks | Факты обычно локальны |
| Суммаризация | Средние chunks | Нужен контекст параграфа/раздела |
| Анализ аргументации | Большие chunks | Аргументы могут быть распределены |
| Поиск ответов на вопросы | Средние chunks | Баланс между контекстом и точностью |
Принцип: Chunk должен содержать достаточно контекста для выполнения задачи, но не больше.
Работа с перекрытием (overlap)
Чтобы не потерять информацию на границах chunks, используйте перекрытие:
def split_with_overlap(text, chunk_size=1000, overlap=200):
chunks = []
start = 0
while start < len(text):
end = start + chunk_size
chunk = text[start:end]
chunks.append(chunk)
start = end - overlap # Перекрытие
return chunks
Небольшое перекрытие между chunks — хороший баланс между избыточностью и сохранением контекста.
Ключевые принципы
- Измеряйте перед оптимизацией: Используйте токенизатор модели для точного подсчета
- Выбирайте стратегию под задачу: Map-reduce для агрегации, chunking для извлечения, суммаризация для понимания
- Сохраняйте промежуточные результаты: Позволяет отладку и drill-down
- Тестируйте на граничных случаях: Очень короткие и очень длинные документы
- Мониторьте качество: Длинные цепочки обработки могут накапливать ошибки
Правильная работа с контекстным окном превращает ограничение в архитектурное решение.
AI-generated · source-grounded review
🛡 Fact-checked: 0 risky claims verified · 7 removed · confidence: medium
A second opinion has not checked this lesson.
On your own course these buttons answer instantly, quizzes track what you've mastered, and lessons adapt to your gaps. Sign up free →