Сжатие контекста
Сокращение контекста до действительно важной информации
«Сжатие контекста» — бесплатный урок AI Prompt Engineering на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения AI Prompt Engineering, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс AI Prompt Engineering содержит 4 уроков всего.
Зачем сжимать контекст
Найденные фрагменты зашумлены: релевантный фрагмент может почти целиком состоять из шаблонного текста и содержать всего одно ключевое предложение. Сжатие контекста сокращает найденный текст до действительно отвечающей на запрос части, прежде чем он попадёт к генератору.
Преимущества накапливаются: снижаются затраты на токены и задержка, становится меньше отвлекающих сведений, а эффект потери информации в середине ослабевает благодаря уменьшению контекста, который должна обработать модель.
def compress(query, chunks):
# Goal: keep only spans that bear on the query,
# dropping boilerplate, navigation, and off-topic sentences.
return [extract_relevant(query, c) for c in chunks]Экстрактивное и абстрактивное сжатие
extractive-сжатие выбирает дословные фрагменты — предложения или отрывки, релевантные запросу, — сохраняя точную формулировку и происхождение данных. Абстрактивное сжатие перефразирует или обобщает текст, обеспечивая более сильное сжатие, но повышая риск потери информации и появления новых ошибок.
Для фактологической RAG с цитатами предпочитайте extractive-сжатие, чтобы утверждения можно было отследить до источника; применяйте абстрактивное сжатие только в тех случаях, когда достоверность можно проверить.
def extractive(query, chunk):
sents = split_sentences(chunk.text)
scored = [(s, relevance(query, s)) for s in sents]
kept = [s for s, r in scored if r > TAU]
return ' '.join(kept) or top1(scored) # never return emptyФильтрация на уровне предложений
Это простой и надёжный метод: оцените каждое предложение каждого фрагмента относительно запроса с помощью небольшого кросс-энкодера или сходства векторных представлений и удалите предложения с низкой оценкой. Так сохраняются ценные предложения и отбрасывается наполнитель.
Сохраняйте для каждого фрагмента минимальный контекст, чтобы не удалить соседнее предложение, придающее факту смысл.
def sentence_filter(query, chunk, keep_ratio=0.4):
sents = split_sentences(chunk.text)
scores = embed_sim_batch(query, sents)
n_keep = max(1, int(len(sents) * keep_ratio))
idx = sorted(range(len(sents)), key=lambda i: -scores[i])[:n_keep]
return ' '.join(sents[i] for i in sorted(idx)) # keep original orderСжатие контекста на основе LLM
LLM может сжимать каждый фрагмент отдельно: попросите её извлечь из отрывка только части, релевантные запросу, и вернуть фрагмент без изменений, но с удалёнными лишними частями, либо пустой маркер, если релевантных частей нет.
Это шаблон LangChain ContextualCompressionRetriever. Он точнее фильтров на основе векторных представлений, но добавляет отдельный вызов LLM для каждого фрагмента, поэтому используйте его в критически важных конвейерах или обрабатывайте фрагменты пакетно.
def llm_compress(query, chunk):
prompt = (
'Extract ONLY sentences from the passage relevant to the query. '
'If none are relevant, output NONE. Do not paraphrase.\n'
'Query: ' + query + '\nPassage: ' + chunk.text
)
out = llm(prompt, temperature=0).strip()
return None if out == 'NONE' else outСокращение на уровне токенов (LLMLingua)
Такие методы, как LLMLingua, сжимают текст на уровне токенов: небольшая модель оценивает информативность каждого токена и удаляет малоинформативные токены. Это позволяет добиться значительного коэффициента сжатия, сохранив сигнал, необходимый большой модели.
Компромисс заключается в том, что сжатый текст становится менее понятным человеку, поэтому такой подход подходит для контекста, предназначенного только для модели, но не для отображения пользователю.
def token_prune(context, target_ratio=0.3):
# small LM estimates per-token information (perplexity-based);
# drop the least informative tokens down to target_ratio length
scores = small_lm_token_importance(context)
return keep_top_fraction(context, scores, target_ratio)С учётом запроса и без учёта запроса
Сжатие с учётом запроса сохраняет сведения, релевантные этому запросу, и создаёт наиболее компактный контекст, но должно выполняться для каждого запроса. Сжатие без учёта запроса — например, заранее подготовленные краткие содержания фрагментов — дешевле во время обработки запроса, но не может сосредоточиться на конкретном вопросе.
Гибридный подход сохраняет сжатые версии фрагментов, подготовленные заранее, и применяет лёгкое удаление лишнего с учётом запроса во время обработки.
# Offline: precompute a dense summary per chunk (query-agnostic)
chunk.summary = summarize(chunk.text)
# Online: query-aware trim over summaries (cheap) then verify on full
ctx = [sentence_filter(query, Chunk(c.summary)) for c in top_chunks]Защита от потери информации
Агрессивное сжатие может удалить единственную важную оговорку. Защититесь с помощью проверки полноты: убедитесь, что из сжатого контекста по-прежнему следует ответ, или сохраняйте запасной вариант с несжатым фрагментом, если компрессор вернул подозрительно мало текста.
Никогда не позволяйте сжатию превращать фрагмент в пустой, если переранжировщик оценил его как высокорелевантный: это указывает на сбой компрессора, а не на нерелевантность.
def safe_compress(query, chunk):
out = llm_compress(query, chunk)
if out is None and chunk.rerank_score > 0.7:
return chunk.text # trust re-ranker over compressor
return out or chunk.textСохранение происхождения данных
Сжатие должно сохранять указание источника. Помечайте каждый сохранённый фрагмент его фрагментом и ID документа, чтобы генератор мог сослаться на него. Если при сжатии удалить метаданные, вы потеряете возможность проверки и обнаружения галлюцинаций.
Передавайте ID через конвейер в структурированных полях, а не в виде произвольного текста, который сжатие может удалить.
def compress_with_ids(query, chunks):
out = []
for c in chunks:
span = safe_compress(query, c)
out.append({'id': c.id, 'doc': c.meta['doc_id'], 'text': span})
return out # generator cites id; provenance preservedСжатие и бюджет токенов
Сжатие позволяет находить больше кандидатов для повышения полноты, сохраняя небольшой итоговый промпт. Установите бюджет токенов для контекстного окна и жадно добавляйте наиболее ценные сжатые фрагменты, пока бюджет не будет исчерпан.
Это отделяет объём найденных данных от объёма ресурсов, затрачиваемых на генерацию, и служит важным рычагом эффективности.
def pack(spans, budget_tokens, tok):
spans = sorted(spans, key=lambda s: -s['score'])
used, packed = 0, []
for s in spans:
t = tok(s['text'])
if used + t > budget_tokens:
continue
packed.append(s); used += t
return packedИзмерение качества сжатия
Отслеживайте три показателя: коэффициент сжатия — сколько токенов удалось сэкономить, точность ответа — сохранилось ли качество, — и достоверность — не изменил ли компрессор факты. Цель состоит в том, чтобы достичь наибольшего коэффициента сжатия без изменения точности ответа.
Проверьте разные уровни агрессивности сжатия и выберите точку Парето, которая соответствует целевой стоимости и не снижает качество.
def eval_compression(eval_set, levels):
return {
lvl: {
'ratio': mean_ratio(eval_set, lvl),
'acc': answer_accuracy(eval_set, lvl),
'faith': faithfulness(eval_set, lvl),
} for lvl in levels
}Конвейер с учётом сжатия
Сквозной процесс выглядит так: выполните широкий поиск, переранжируйте результаты, сожмите каждый оставшийся фрагмент — экстрактивным методом или на основе LLM — вместе с данными о происхождении, защититесь от чрезмерного сокращения, добавьте фрагменты в пределах бюджета токенов и сгенерируйте ответ с цитатами.
Сжатие — это слой, который делает поиск с высокой полнотой доступным по стоимости и помогает генератору сосредоточиться на важном.
def pipeline(query):
top = rerank(query, hybrid_retrieve(query, 50))[:12]
spans = compress_with_ids(query, top)
spans = [s for s in spans if s['text']]
packed = pack(spans, budget_tokens=2000, tok=count_tokens)
return generate_with_citations(query, packed)Быстрая проверка
Выберите правильный подход к сжатию для фактологической RAG-системы с цитатами.
Итоги
Главные выводы:
- Сжатие сокращает найденные фрагменты до содержимого, релевантного запросу, снижая затраты, задержку и количество отвлекающих сведений.
- Для фактологической RAG с цитатами предпочитайте extractive-сжатие — дословное и прослеживаемое — абстрактивному; сокращение на уровне токенов подходит для контекста, предназначенного только для модели.
- Сжатие с учётом запроса даёт наиболее компактный результат, но выполняется для каждого запроса; для эффективности сочетайте его с заранее подготовленными краткими содержаниями.
- Защищайтесь от потери информации и сохраняйте происхождение фрагментов и документов для цитирования.
- Используйте сжатие, чтобы выполнять широкий поиск и одновременно сохранять небольшие промпты; настройте его на максимальный коэффициент сжатия без потери точности ответа.
Часто задаваемые вопросы
Урок «Сжатие контекста» бесплатный?
Да — полный текст урока «Сжатие контекста» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс AI Prompt Engineering, подпишись на CoddyKit PRO. Курс AI Prompt Engineering содержит 4 уроков всего.
Чему я научусь в уроке «Сжатие контекста»?
Сокращение контекста до действительно важной информации Ты практикуешь AI Prompt Engineering с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать AI Prompt Engineering?
Предыдущий опыт не требуется. AI Prompt Engineering на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Сжатие контекста»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке AI Prompt Engineering?
Да. Каждый урок AI Prompt Engineering включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- За пределами наивного RAG
- Переранжирование найденных фрагментов
- Сжатие контекста
- Переписывание запросов и HyDE