共计 1742 个字符,预计需要花费 5 分钟才能阅读完成。
问题定义:为什么我们需要上下文理解?
想象一个电商客服场景:

用户:这个手机有红色版本吗?客服:有的,库存充足
用户:它多少钱?← 这里的 "它" 指什么?
传统机器人会直接报出所有手机价格,因为无法关联上文中的 ” 红色版本手机 ”。这就是典型的 上下文断裂 问题,会导致:
- 指代消解失败(它 / 那个 / 上次说的)
- 多轮对话状态丢失(购物车→支付流程)
- 话题跳跃误判(突然询问运费却得到产品参数)
技术方案对比
| 方案类型 | 维护成本 | 准确率 | 响应延迟 | 适用场景 |
|---|---|---|---|---|
| 规则模板 | 高 | 40%-60% | <50ms | 固定流程(密码重置) |
| RNN 序列建模 | 中 | 65%-75% | 100-300ms | 简单多轮对话 |
| Transformer | 低 | 80%-95% | 200-500ms | 开放域复杂对话 |
核心实现步骤
1. 对话嵌入构建
使用 Sentence-BERT 将对话片段转化为向量:
from sentence_transformers import SentenceTransformer
# NOTE: 选择轻量级模型平衡性能与速度
encoder = SentenceTransformer('paraphrase-MiniLM-L6-v2')
def get_embedding(text):
return encoder.encode(text, convert_to_tensor=True)
2. 上下文注意力计算
通过权重分配突出相关历史对话:
import torch
import torch.nn.functional as F
# current_input: 当前用户语句嵌入
# history: 历史对话嵌入列表
def attention_layer(current_input, history):
keys = torch.stack(history)
query = current_input.unsqueeze(0)
# NOTE: 缩放点积注意力机制
weights = F.softmax(torch.matmul(query, keys.T) / torch.sqrt(torch.tensor(keys.shape[1])), dim=-1)
context = torch.sum(weights * keys, dim=0)
return context
3. 对话状态机设计
from enum import Enum
class DialogState(Enum):
GREETING = 0
PRODUCT_QUERY = 1
PRICE_CONFIRM = 2
CHECKOUT = 3
class DialogAgent:
def __init__(self):
self.state = DialogState.GREETING
self.context = []
def update_state(self, user_input):
# NOTE: 基于规则 + 语义相似度的混合状态判断
emb = get_embedding(user_input)
if len(self.context) > 0:
context_vec = attention_layer(emb, self.context)
else:
context_vec = emb
# 状态转移逻辑...
生产环境考量
内存泄漏检测
import weakref
class DialogSession:
def __init__(self):
self._data = {}
self._finalizer = weakref.finalize(self, self._cleanup)
def _cleanup(self):
print(f"释放会话资源")
# 清理数据库连接等资源
上下文窗口测试数据
| 窗口大小 | 内存占用 | 平均响应时间 | 准确率 |
|---|---|---|---|
| 3 轮 | 15MB | 120ms | 72% |
| 5 轮 | 22MB | 180ms | 85% |
| 10 轮 | 40MB | 320ms | 88% |
三大常见陷阱
- 未做会话隔离
- 现象:用户 A 的对话历史泄露给用户 B
-
解决:为每个会话创建独立实例
-
过度依赖余弦相似度
- 现象:” 苹果手机 ” 和 ” 吃的苹果 ” 被误判为相似
-
解决:结合实体识别 + 领域词典
-
忽略时态一致性
- 现象:用户问 ” 明天天气 ”,机器人用昨天数据回答
- 解决:在上下文编码中加入时间戳特征
开放性问题
当用户突然说 ” 算了,聊点别的 ” 时:
– 应该立即清空上下文吗?
– 如何区分话题切换和话题延伸?(如从 ” 手机 ” 转到 ” 手机壳 ”)
– 是否需要保留部分通用上下文(用户偏好等)?
这些策略需要根据业务场景权衡,你会怎么设计?
正文完
发表至: 人工智能
近三天内
