你们系统支持多轮对话吗?用户第一轮问了车险保障范围,第二轮追问'这个怎么申请',你的系统能理解'这个'指的是什么吗
P1 · rag · 🏢 京东
🏷 标签:multi-turn, query-rewriting, coreference-resolution
1️⃣ 考察意图
面试官想考察你对多轮对话RAG系统的实战理解,而非简单背概念。核心是查询重写(Query Rewriting) 和指代消解(Coreference Resolution) 的工程落地能力。刁钻点在于:用户第二轮“这个怎么申请”中的“这个”是模糊指代,系统必须结合历史上下文(第一轮“车险保障范围”)才能正确检索。答好了能展示你对对话状态管理、上下文压缩、检索效率与准确性的权衡,以及处理真实用户模糊表达的硬实力。
2️⃣ 标准答
多轮对话RAG系统的核心挑战是上下文理解,尤其是代词和省略句。我的方案分三步:对话历史管理、查询重写、检索与生成。
- 对话历史管理:不直接拼接所有历史,而是用滑动窗口保留最近3-5轮(约2000 token),避免长上下文噪声。每轮存储用户输入和系统回复,用
session_id标识。坑:历史过长会导致检索延迟飙升,且无关信息干扰相关性。解法:对历史做摘要压缩,用LLM生成每轮关键实体(如“车险保障范围”),而非原始文本。 - 查询重写:这是核心模块。检测当前查询是否包含代词(“这个”“它”“那里”)或省略(“怎么申请”无主语)。用规则+轻量模型混合:规则层:正则匹配“这个/那个/它”等代词,若命中,从上一轮用户输入或系统回复中提取主语(如“车险保障范围”),拼接成完整查询:“车险保障范围怎么申请”。
- 模型层:若规则失败(如“怎么申请”无显式代词),用微调后的T5-small做查询重写,输入格式:
[CLS] 历史: {上一轮用户输入} [SEP] 当前: {当前查询} [SEP],输出重写后查询。训练数据用公开数据集(如CANARD)或自标注(模拟用户多轮对话)。 - 工程取舍:规则快但覆盖不全,模型准但延迟高(约50ms)。生产环境用级联策略:先规则(<5ms),若置信度低(如无匹配),再调模型。这平衡了响应速度和准确性。 检索与生成:重写后的查询(如“车险保障范围怎么申请”)送入检索模块。用BM25+稠密检索混合:BM25(k1=1.5, b=0.75)处理关键词匹配,稠密检索(如BGE-small)处理语义相似度,最后用Cohere Rerank排序Top-5。生成阶段,将重写查询+检索结果+对话历史(压缩后)拼成prompt,调用LLM(如Qwen2.5-7B)生成答案。实际落地的坑:用户可能连续追问(如“那理赔呢?”),指代可能跨多轮。解法:用指代链追踪,维护一个实体列表(如“车险”),每轮更新。若当前查询无主语,从列表取最近实体。示例:第一轮“车险保障范围”,第二轮“这个怎么申请” → 实体列表为[“车险保障范围”],重写为“车险保障范围怎么申请”。第三轮“那理赔呢?” → 实体列表为[“车险保障范围”, “理赔”],重写为“车险理赔怎么申请”。
3️⃣ 答题模板(30 秒电梯版)
“这个问题我从三个层面回答:第一,对话历史管理,用滑动窗口保留最近3轮并压缩摘要,避免噪声;第二,查询重写,用规则+轻量模型级联处理代词和省略,规则快但模型兜底;第三,检索与生成,用BM25+稠密检索混合,再Rerank。总结一句:核心是通过上下文融合把模糊查询重写为完整查询,确保检索准确性。”
4️⃣ 高频追问 & 应对
追问 1:如果用户说“那另一个呢?”,“另一个”指代什么?你的系统怎么处理?
这是跨轮指代,需要实体列表。我的系统维护一个
entity_stack,每轮提取关键实体(如“车险保障范围”),按时间排序。当前查询“另一个”触发规则,从栈中取上一个实体(如“车险保障范围”),但“另一个”暗示对比,所以重写为“车险保障范围之外的另一个是什么”。若栈为空或匹配失败,用模型预测。坑:实体提取可能出错,用NER模型(如spaCy)做后备,并加置信度阈值。
追问 2:查询重写模型训练数据怎么来?冷启动怎么办?
冷启动用公开数据集(CANARD,约3万条多轮查询重写对),但领域不匹配。解法:用自监督生成,拿历史对话日志,用LLM(如GPT-4)自动生成重写标签,人工抽检10%保证质量。训练时用T5-small,batch size=32,学习率3e-5,3个epoch。坑:LLM生成可能引入幻觉,所以加规则过滤(如重写后查询必须包含原查询关键词)。
追问 3:如果用户第一轮问“车险”,第二轮说“具体点”,系统怎么理解?
“具体点”是省略句,无显式代词。我的规则层会检测“具体/详细/展开”等关键词,从上一轮用户输入提取主题(“车险”),重写为“车险具体点”。但“具体点”可能指代多个方面(保障范围、价格等),所以模型层会结合历史回复(如系统第一轮回答了“保障范围”),重写为“车险保障范围具体点”。坑:多义性,用意图分类(如“具体点”映射到“detail”意图)辅助,再根据意图选择重写策略。
5️⃣ 避坑 · 常见错误答法
- ❌ 直接说“用LLM理解上下文,LLM能自动处理指代” → ✅ 必须给出具体模块(查询重写、历史管理),LLM只是生成器,不能依赖它做检索前的上下文理解,否则延迟高且不可控。
- ❌ 只提规则,不提模型兜底 → ✅ 规则覆盖80%场景,但20%复杂指代(如跨轮省略)需要模型,级联策略才是工程正确做法。
- ❌ 忽略对话历史长度控制,直接拼接所有历史 → ✅ 历史过长(>10轮)会导致检索噪声和延迟,必须用滑动窗口+摘要压缩,控制输入在2000 token内。
6️⃣ 简历呼应
- 如果你有RAG项目:从查询重写模块切入,强调你如何用规则+模型级联处理多轮指代,并给出延迟优化(如规则5ms vs 模型50ms)。可提你用的数据集(CANARD)和微调细节。
- 如果你只做过传统NLP:用指代消解任务类比,说你从CRF或BERT-based coreference模型迁移到查询重写,重点在如何把序列标注问题转化为生成问题(T5微调)。
- 如果你是校招无项目:聚焦论文复现,说你读过《Query Rewriting for Conversational Search》并实现demo,用CANARD数据集训练T5-small,在Colab上跑通,并分析规则与模型的trade-off。
- 《Query Rewriting for Conversational Search》(论文,CANARD数据集)
- 《End-to-End Query Rewriting for Multi-Turn Dialogue》(博客,T5微调实践)
- 《RAG with Multi-Turn Context: A Practical Guide》(工具,LangChain对话历史管理)
- 《Coreference Resolution in NLP: A Survey》(综述,指代消解方法)
- 《BM25 vs Dense Retrieval: Trade-offs in Production》(博客,混合检索策略)