Стратегии работы с окном контекста в 2+ миллиона токенов
Введение: Смена парадигмы в эпоху бесконечного контекста
Коллеги, добро пожаловать в новую эру разработки на базе LLM. Еще совсем недавно, во времена GPT-4 (8k) или ранних версий Claude, мы тратили 80% времени на инженерные ухищрения: как «утрамбовать» базу знаний в крошечное окно, как нарезать документы на чанки, какой алгоритм поиска (RAG) выбрать, чтобы не потерять смысл.
С появлением Gemini 3 и его окна в 2+ миллиона токенов (и более в экспериментальных ветках), правила игры фундаментально изменились. Это не просто количественный рост, это качественный скачок. Теперь вы можете загрузить в промпт целиком:
- Всю кодовую базу среднего проекта.
- Видеозапись часового совещания вместе с транскрипцией.
- Десятки PDF-файлов технической документации.
Однако, здесь кроется ловушка. Многие разработчики думают: «Отлично, я просто закину всё в контекст, и RAG мне больше не нужен». Это опасное заблуждение. Работа с таким объемом данных требует новых стратегий управления вниманием модели, оптимизации задержки (latency) и контроля расходов (cost management). В этом уроке мы разберем, как перестать бороться с лимитами и начать эффективно управлять изобилием.
Физика больших контекстов: NIAH и «Lost in the Middle»
Прежде чем писать код, давайте разберемся, как модель «читает» 2 миллиона токенов. Gemini 3 демонстрирует выдающиеся результаты в тестах NIAH (Needle In A Haystack). Это означает, что если вы спрячете один специфический факт («иголку») в массиве текста размером с «Войну и мир», умноженную на 10 («стог сена»), модель найдет его с точностью выше 99%.
Но есть нюансы, о которых не пишут в пресс-релизах:
- Эффект «Сфокусированного начала»: Инструкции, расположенные в самом начале или в самом конце промпта, имеют больший «вес» для внимания модели. Середина контекста обрабатывается отлично, но если инструкции сложные, их лучше дублировать.
- Когнитивная нагрузка: Чем больше контекст, тем сложнее модели выполнять многоступенчатые логические рассуждения (Reasoning) над всеми данными сразу. Найти факт — легко. Сравнить и синтезировать информацию из 50 разных источников внутри контекста — сложнее.
- Latency (Задержка): Обработка 1 миллиона токенов занимает время. Даже у Gemini Flash это не мгновенно. Если вы каждый раз отправляете книгу в чат, Time-to-First-Token (TTFT) будет неприемлемым для real-time приложений.
Именно поэтому нам нужна стратегия Context Caching.
Context Caching: Революция в экономике токенов
Представьте, что вы разрабатываете бота-юриста, который отвечает на вопросы по Гражданскому кодексу и десяткам пленумов Верховного суда. Общий объем — 500,000 токенов.
Сценарий без кеширования:
Пользователь задает вопрос (50 токенов). Вы отправляете: 500,000 (база) + 50 (вопрос). Вы платите за обработку 500,050 токенов. Пользователь ждет 20 секунд препроцессинга.
Следующий вопрос? Снова платите за 500,000 токенов.
Сценарий с Context Caching в Gemini 3:
Вы загружаете базу знаний один раз и создаете кеш. Токены обрабатываются единожды. В дальнейшем вы отправляете только 50 токенов вопроса и ссылку на кеш.
Результат:
1. Снижение стоимости на порядки (ввод кешированных токенов значительно дешевле).
2. Мгновенный старт генерации (нет фазы препроцессинга большого контекста).
Ниже рассмотрим, как это реализовать программно.
import os
import time
from google import genai
from google.genai import types
# Инициализация клиента Gemini 3 (гипотетический SDK v3, базирующийся на текущих принципах)
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
# 1. Подготовка данных (представим, что это массивные тексты или код)
doc_path = "large_technical_manual.txt" # Файл весом в 1М токенов
print("Загрузка файла в хранилище...")
file_ref = client.files.upload(path=doc_path)
# Ожидание обработки файла (важный шаг для больших файлов)
while file_ref.state.name == "PROCESSING":
print(".", end="", flush=True)
time.sleep(2)
file_ref = client.files.get(name=file_ref.name)
print(f"\nФайл готов. URI: {file_ref.uri}")
# 2. Создание кеша контекста
# Мы задаем TTL (время жизни). Например, 1 час.
cache_name = "tech_manual_cache"
print("Создание кешированного контекста...")
cached_content = client.caching.cached_contents.create(
model="gemini-3.0-pro-001",
display_name=cache_name,
system_instruction="Ты - эксперт технической поддержки. Отвечай строго по документации.",
contents=[types.Content(
role="user",
parts=[types.Part.from_uri(file_uri=file_ref.uri, mime_type="text/plain")]
)],
ttl="3600s" # 1 час
)
print(f"Кеш создан: {cached_content.name}")
# 3. Использование кеша в запросах
# Обратите внимание: мы не передаем файл снова!
response = client.models.generate_content(
model="gemini-3.0-pro-001",
contents="Как сбросить настройки устройства до заводских?",
# Подключаем наш кеш
cached_content=cached_content.name
)
print("Ответ модели:")
print(response.text)
# Расход токенов будет отображать использование кеша
print(response.usage_metadata)
Стратегия Many-Shot In-Context Learning
Окно в 2 миллиона токенов убивает необходимость в Fine-Tuning (дообучении) для 90% задач. Раньше, если нам нужно было научить модель специфическому стилю отчетов или переводу на редкий диалект (например, юридический русский), мы собирали датасет и тренировали адаптер (LoRA).
Теперь мы используем стратегию Many-Shot. Вместо 3-5 примеров (Few-Shot), мы можем дать модели сотни и тысячи примеров идеального выполнения задачи прямо в промпте.
Архитектура промпта для Many-Shot:
<system_instructions>
Ты - аналитик данных. Твоя задача - преобразовывать неструктурированные логи в JSON.
</system_instructions>
<examples>
<example_1>
Вход: ...
Выход: ...
</example_1>
... (здесь могут быть тысячи примеров) ...
<example_500>
Вход: ...
Выход: ...
</example_500>
</examples>
<task>
Вот новые данные для обработки:
...
</task>Исследования показывают, что качество работы Gemini 3 при использовании ~1000 примеров в контексте сопоставимо, а часто и превосходит качество дообученных моделей, при этом сохраняя гибкость (вы можете изменить примеры в любой момент без переобучения).
Спроектируйте решение для компании, у которой есть архив внутренних PDF-документов за 10 лет (общий объем ~1.5 млн токенов). Сотрудникам нужно задавать вопросы по истории проектов в чате. <br><br>Требования:<br>1. Минимальная задержка ответа (Low Latency).<br>2. Ответы должны быть строго обоснованы документами.<br>3. Бюджет ограничен (нельзя загружать 1.5 млн токенов на каждый вопрос «Где туалет?»).<br><br>Опишите словами архитектуру, используя концепции Context Caching и классификации запросов.
Когда НЕ нужно использовать 2 миллиона токенов?
Несмотря на мощь большого контекста, классический RAG (Retrieval-Augmented Generation) не умер. Существует точка перегиба эффективности.
Используйте полное окно (Long Context), когда:
- Вам нужен глобальный анализ («Какие общие паттерны ошибок есть во всех этих 50 лог-файлах?»).
- Ответ зависит от связей между удаленными частями текста (сюжетные линии в книге).
- Вы не знаете заранее, какая часть информации важна.
Используйте RAG (поиск кусочков), когда:
- У вас гигантская база (терабайты данных) — в 2 млн токенов всё не влезет.
- Вам нужен точечный факт («Какой номер телефона у клиента ID 123?»). Загружать всю CRM в контекст ради одного номера — стрельба из пушки по воробьям.
- Вам нужна максимальная дешевизна единичного запроса без предварительного прогрева кеша.
Совет профи: Лучшая архитектура для Gemini 3 — это RAG, который достает большие куски (по 50-100к токенов) и скармливает их модели. Это «Fat RAG».
Вы разрабатываете систему анализа юридических договоров. Каждый договор занимает около 100,000 токенов. Пользователь загружает договор и задает по нему 20 разных вопросов подряд в течение часа. Какая стратегия будет наиболее оптимальной по соотношению цена/скорость?