共计 2122 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点:为什么需要上下文压缩?
在开发对话系统(Dialogue System)或智能助手(Agent)时,我们常常遇到一个棘手问题:随着对话轮次增加,上下文(Context)会像滚雪球一样越来越大。最近做一个客服机器人项目时,就遇到了这样的场景——当用户连续咨询 10 个问题后,API 调用成本直接翻倍,响应时间从 500ms 飙升到 2 秒。

传统全量存储模式的主要问题:
- 内存压力:每 1000 个 token 的对话内容,GPT- 3 类模型就需要占用约 4KB 内存
- API 成本:主流 NLP 服务按 token 计费,长上下文直接拉高运营成本
- 响应延迟:上下文越长,模型推理时间呈指数增长(实测 512token vs 2048token 相差 300ms)
技术方案对比:三种主流压缩策略
通过对比实验,我们筛选出三种效果较好的压缩方法:
| 方法 | 压缩率 | 信息保留度 | 适用场景 |
|---|---|---|---|
| 摘要压缩 | 60-70% | 中 | 需要保留叙事的场景 |
| 向量化压缩 | 80-90% | 高 | 语义检索类任务 |
| 关键信息提取 | 50-60% | 高 | 表单填写等结构化场景 |
其中向量化压缩 + 关键信息提取的混合方案,在我们的电商客服场景中实现了 82% 的压缩率,同时保持 91% 的意图识别准确率。
核心实现:Python 代码实战
基于 BERT 的关键信息提取
from transformers import BertTokenizer, BertForTokenClassification
import torch
# 加载预训练模型
model = BertForTokenClassification.from_pretrained('dbmdz/bert-large-cased-finetuned-conll03-english')
tokenizer = BertTokenizer.from_pretrained('bert-base-cased')
def extract_keywords(text):
inputs = tokenizer(text, return_tensors="pt")
outputs = model(**inputs)
# 提取实体标签(PER/LOC/ORG 等)predictions = torch.argmax(outputs.logits, dim=2)
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])
return [token for token, pred in zip(tokens, predictions[0])
if pred.item() in [1,3,5]] # 只保留关键实体
对话摘要向量生成
from sentence_transformers import SentenceTransformer
import numpy as np
model = SentenceTransformer('paraphrase-MiniLM-L6-v2')
def summarize_to_vector(dialogues):
# 生成每个句子的嵌入向量
embeddings = model.encode(dialogues)
# 取对话向量的均值作为摘要
return np.mean(embeddings, axis=0)
内存监控装饰器(实用工具)
import psutil
import functools
def memory_monitor(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
before = psutil.virtual_memory().used / 1024 / 1024
result = func(*args, **kwargs)
after = psutil.virtual_memory().used / 1024 / 1024
print(f"Memory usage: {after-before:.2f} MB")
return result
return wrapper
生产环境优化经验
压缩率与信息保留的平衡
我们开发了一个动态调整策略:
- 首轮对话:保留 100% 原始内容
- 2- 5 轮:启用轻度压缩(保留 70% 内容)
- 5 轮以上:启动激进压缩(保留 30% 核心信息)
配合余弦相似度检测,当检测到话题切换时自动重置压缩策略。
连贯性保障方案
- 维护一个对话状态机(Dialogue State Machine)
- 对压缩后的内容添加时间戳和话题标签
- 使用类似
[前面提到过...]的占位符保持上下文衔接
避坑指南:血泪教训总结
-
不要过度压缩技术文档:当处理 API 文档等专业内容时,我们发现压缩后丢失了关键参数说明,导致回答错误。解决方案是建立领域术语白名单。
-
处理多语言混合场景:中英文混杂时,直接压缩会导致语义断裂。我们的应对方案是:
- 先进行语言识别
- 按语言分段处理
-
最后合并结果
-
时间信息处理:” 明天下午 3 点 ” 压缩后可能变成 ” 某个时间 ”,需要特殊处理时间表达式。
开放讨论:压缩效果的评估
在我们内部测试中,当压缩率达到 90% 时,常规的 BLEU 评分已经不能准确反映质量。建议尝试:
- HuggingFace 的 BERTScore 评估
- 人工设计的关键信息检查表(Checklist)
- 基于用户行为的间接评估(如后续问题跟进率)
你遇到过哪些有趣的上下文压缩场景?欢迎分享你的评估方案。
正文完
