很多做对话系统的朋友应该都有过这种经历:用户明明在第三轮说过“那家店”,到第八轮又追了一句“那家店到底几点关门”,系统直接懵住——是哪家店?如果只看当前这一句话,任何模型都拿它没办法。这就是典型的多轮对话实体消歧问题。我最近把 OpenClaw 的对话理解链路完整拆了一遍,重点研究了它在多轮对话里做实体消歧时究竟依赖哪些上下文特征、这些特征是怎么被组织和决策的,以及哪些坑最容易踩。这篇文章把拆解结果和我在复现过程中的个人体会整理出来。做智能助手、客服机器人、语音对话系统的人,应该都能从中找到可以直接借鉴的东西。
1. 先搞清楚:多轮对话的实体消歧到底难在哪
1.1 一个指称对应多个候选,单轮信息远远不够
实体消歧的任务说起来很简单:给定一句话里的某个实体指称(mention),判断它到底指向真实世界里的哪个实体。比如用户说“那个套餐”,候选可能有三四种不同档位的套餐;“那家店”可能是用户之前询问过的餐厅、咖啡馆或者便利店。问题在于,用户在日常对话里几乎不会给出完整名称,大量指称都是“那个”“这家”“刚才说的”“第二个”之类的省略表达。
单轮对话里也有实体消歧,但上下文相对干净:如果一句话里出现了“店”“排队”“菜单”这些词,模型基本能判断这是一个餐饮类实体。可一旦进入多轮,前面的轮次会引入大量背景信息,这些信息既是线索,也是干扰。用户可能前两轮还在问天气,中间聊了几句电影,最后又绕回“那家店”,模型必须从整个对话历史里找回那个“店”到底是谁。单轮的局部信息在这个场景下彻底不够用。
1.2 口语对话的省略、指代和主题漂移
多轮对话的实体消歧之所以难,主要是因为口语对话有三个天然特性。
省略是最常见的。用户在对话里不会像写文档一样每次都带全主语和宾语,“嗯就那个就行”这种句子,没有任何显式实体名,全靠历史来推断。指代更麻烦,“它”“这家”“那边”这类词,指称对象可能在前两轮,也可能在十轮之前,需要准确回溯。主题漂移则是多轮对话特有的麻烦,用户聊着聊着突然换话题,换完又可能跳回来,对话里同时存在多个潜在实体,而且活跃度此消彼长。
这三件事叠加在一起,就形成了一个核心矛盾:单轮文本信息太少,但历史信息又可能太多、太杂。如果不对上下文做结构化处理,把所有历史原文一股脑塞给模型,长对话根本吃不消,而且早期实体容易被淹没。
1.3 消歧错误会产生连锁反应
实体消歧从来不是终点,只是个中间步骤。消歧的结果会直接影响后续的槽位填充、知识检索、回复生成。一旦某个实体的判定出错,错误会沿着对话链路往下传播。
举个例子,用户之前提到过“某品牌 X”,系统误消歧成了另一个同名品牌,用户接着说“X 的售后怎么样”,系统检索出来的全是错误实体的售后政策,回答就会偏到十万八千里。更麻烦的是,这个错误会进入共指链,后面用户再说“他们家”,系统会继续沿着错误实体继续走。多轮场景里,一次消歧错误的代价远高于单轮场景,因为错误会被反复引用和放大。这也是为什么 OpenClaw 这类系统必须在上下文特征设计上投入大量精力,而不是简单套一个实体链接模型。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. OpenClaw 的消歧链路:候选如何生成、上下文窗口如何切分
2.1 四段式链路:识别、召回、特征、打分
OpenClaw 的实体消歧不是一个独立的黑盒模块,而是嵌入在整个对话理解链路里。它的完整流程大致分成四个阶段。
首先是指称识别,从当前轮用户输入里找出哪些片段可能是实体指称;然后是候选召回,针对每个指称生成候选实体列表;接着是特征抽取,把当前轮、历史轮、外部知识等信息聚合成特征;最后是打分决策,给每个候选实体计算一个得分,决定消歧结果。
这四个阶段里,候选召回决定了消歧的上限。OpenClaw 的召回策略比较务实:先基于别名表和模糊匹配做一轮硬召回,保证名称相近的候选都在;再用向量召回补充语义相近的候选,最后用类型约束过滤掉明显不符合上下文的候选。比如“那家店”的候选里,如果系统能判断当前主题是餐饮,就优先保留餐厅类候选。
2.2 上下文窗口:原文轮次、结构化历史、对话摘要三件套
我最开始以为 OpenClaw 会把整个对话历史拼成一个长文本喂给模型,看完源码才发现完全不是这样。它保存了三层上下文,各有各的用处。
第一层是最近几轮的用户原文和系统原文,保留局部细节。第二层是结构化实体轨迹,也就是每轮提到过哪些实体、实体之间的共指关系,这一层是消歧时最直接的依据。第三层是对话级摘要向量,用来抵抗长对话带来的信息遗忘。三层上下文叠加,既照顾了细节,又照顾了全局。
这个设计的逻辑很清晰:原始文本信息最丰富但噪声也大,结构化轨迹噪声小但依赖前面的正确率,摘要向量能兜底但粒度太粗。三层配合,无论用户是在短对话里给出明确指代,还是在长对话里绕来绕去,系统都有可用信息。
2.3 特征抽取不是消歧模块的独角戏
还有一个细节很值得关注:OpenClaw 的特征抽取大量复用了对话理解上游已经算好的中间产物。意图识别、情感分类、主题分类这些模块本身就会产生向量和标签,消歧模块直接拿过来用,而不是自己从头再算一遍。
这样做的好处是明显的。多轮对话系统本身就要做意图识别和话题跟踪,这些上游结果天然携带了消歧需要的语义信息。如果消歧模块完全独立,每个模块都维护一套特征体系,工程复杂度会成倍增加。OpenClaw 的做法是让中间表示成为公共设施,消歧只是其中一个消费者。这也是很多落地系统容易忽略的地方。
3. OpenClaw 实际使用的七类上下文特征,逐个拆解
3.1 当前轮局部文本特征:最基础但不该主导
当前轮的局部文本特征是消歧的第一层信号,具体包括指称周围的几个词、命名实体标签、词性标签,以及当前轮用户句子里有没有否定词、疑问词、比较词这类语气标记。
举个例子,用户说“那家店排队吗”,局部文本里的“排队”很明显倾向于餐饮类实体,而“那家店几点开门”则可能更偏向零售类实体。OpenClaw 用一个轻量编码器把这些信息压成一个局部向量,参与最终的消歧打分。
我的体会是,这类特征永远回不掉的,但绝对不能让它成为主导。局部文本只反映了当前轮用户怎么表达,不反映前几轮说了什么。如果单纯依赖局部文本,那它和单轮实体链接就没有区别了。OpenClaw 的消歧打分里给局部向量设的权重并不高,它的主要作用是提供“第一直觉”,真正定调的还是历史信息。
3.2 对话主题与意图轨迹特征:先判断用户在哪条线上
OpenClaw 很重视“当前对话到底在聊什么”这个信息。它维护了一个对话级主题表征,可以是一个语义类别标签,比如餐饮、电影、天气、购物,也可以是由对话编码器算出来的主题向量。
主题特征的帮助在于,它天然给候选实体加了一道约束。如果当前主题是餐饮,那么候选里的体育赛事、数码产品这类实体就算别名匹配上了,分数也要被压低。反过来也一样,用户说到“比赛”,如果主题是体育,那它大概率指某场比赛,而不是某个商品促销活动。
除了主题,OpenClaw 还记录意图轨迹——每一轮用户的意图标签。看单个意图没意义,但把连续几轮的意图串起来,就能看出一个趋势:用户在连续咨询、还是想确认信息、还是在纠正系统。这种轨迹特征能让消歧模块意识到“用户还在延续前面的实体问询”,而不是开启了一个全新的实体。
3.3 共指链与实体轨迹特征:最强但也最容易踩坑
如果让我在七类特征里选一个最关键的,我会选共指链与实体轨迹特征。这也是 OpenClaw 在多轮消歧里区别于单轮实体链接的核心。
共指链做的事情是这样的:把不同轮次里指向同一实体的指称串成一条链。用户第二轮说“那家店”,第五轮说“它”,第七轮说“这家”,系统在建链时发现三个指称都指向同一个候选实体,就形成一个共指链。实体轨迹则是这条链的动态统计:实体最近一次被提到的轮次、总共被提到的次数、第一次被提到的轮次。
为什么这个特征这么强?因为多轮对话里,用户的指称大概率遵循“局部焦点”规律——最新被提到的实体往往是最可能被继续指称的实体。OpenClaw 把实体轨迹特征直接编码成几个数值:recency(距离当前轮多远)、frequency(出现次数)、active(是否在当前焦点)。这些数值喂给打分器后,效果立竿见影。
但这里有个隐藏的坑:共指链本身依赖前面轮次的消歧结果。前一轮如果消歧错了,后面跟着错。OpenClaw 在实现时专门给共指链里的每个节点保存了置信度,低置信度的节点不会参与后续共指传递,避免一个错误被一路放大。这个细节我在后面实测部分还会展开讲。
3.4 轮次距离与时间状态特征:别忽略真实时间流逝
除了共指链,OpenClaw 还引入了一组容易被忽略的特征:轮次距离和真实时间间隔。
轮次距离是指当前指称距离某个候选实体上一次出现的轮数。用户刚在上一轮提到“某品牌 A”,这一轮说“它出了新品”,轮次距离是 1,候选实体 A 自然应该拿高分。但如果用户中间聊了八轮别的话题,这里说的“它”就需要重新判断。
真实时间间隔同样重要,只是很多纯文本模型不会考虑它。如果用户隔了几分钟继续聊同一件事,实体活跃度通常还维持在高位;如果隔了几个小时甚至隔天才回来,实体焦点很可能已经冷却。OpenClaw 在处理用户说“上次说的那个”时,会重点结合时间特征:如果“上次”明确发生在很久以前,那么活跃度阈值会放宽,允许系统回溯到更早的实体。
还有一类状态特征也归在这里:上一轮系统是否给用户展示过列表、卡片、选项等。如果系统刚才展示了三个候选,用户紧接着说“第二个”,这里的“第二个”必须依赖系统状态才能消歧。这类状态特征保存在对话状态管理器里,消歧模块直接读取。
3.5 用户反馈与纠偏信号:多轮对话独有的优势
多轮对话相比单轮文本最大的优势在于,用户会对系统的理解结果给出反馈。OpenClaw 非常看重这个信号,因为它比任何语义推断都更直接。
具体来说,OpenClaw 会记录用户对上一轮系统回复的反馈类型:确认、否定、沉默、追问。如果用户在上一轮说了“不是那个”“我说的是 A”,那么当前轮再出现模糊指称时,上一轮被否定的候选实体的分数会被明显压低。用户纠正的信息是金字招牌,权重相当高。
应用这个特征时要注意时机。用户的纠偏信号不是永久有效的,如果用户后来已经转到全新话题,再揪着之前的纠偏不放反而会干扰消歧。OpenClaw 的做法是给反馈特征加一个时间衰减:越靠近当前轮的反馈影响越大,远了就逐渐退场。
3.6 候选实体的外部知识特征:模糊指称下的先验救命稻草
以上特征大部分都指向“用户指的大概率是历史里谁”,但总有冷启动或者指称极度模糊的情况。这时候外部知识特征就派上用场了。
OpenClaw 给每个候选实体保存了一组先验特征:实体所属类型、别名数量、热门程度、描述与当前主题的语义相似度。当对话上下文很弱时,这些外部特征能提供基础判断。比如用户第一句就问“那个很有名的演员后来怎么样了”,候选实体里热门程度高的演员就会获得更高的先验分。
外部知识特征还有一个用法:候选之间的关联。如果两个候选实体都属于同一个系列或同一作者,OpenClaw 会在候选中做关联传播,把另一个高置信度实体的分数带上去。这种图结构特征在多候选场景里比较有效,但实现成本会高一些。
3.7 跨会话的用户偏好特征:有条件使用的长记忆
OpenClaw 还支持一个条件启用的特征:跨会话的用户画像。这个特征不是每次消歧都参与,而是在用户的长期资料足够丰富时才启动。它记录的是用户历史会话中高频出现过的实体类型、偏好领域、常讨论的品牌等。
这个特征的价值在于处理同一用户第二次提到某些实体时,系统有额外先验。比如某用户历史对话里经常聊数码产品,再次听到“那个新出的”,候选里数码产品会获得微弱加分。OpenClaw 在设计上特意把这类特征的权重限制得很低,因为它只能作为先验,一旦主导当前会话的消歧,很容易把用户的临时意图带偏。另外从隐私角度出发,系统只保存统计偏好,不保存原始对话内容。
4. 特征融合与兜底决策:OpenClaw 怎么打分、怎么交代
4.1 分层编码与门控融合
七类特征的来源和粒度差异太大了,局部文本是向量,轮次距离是数值,用户反馈是标签。OpenClaw 没有简单地把它们拼成一个大向量,而是采用分层编码加门控融合的方式。
具体来说,局部文本和外部知识分别编码成语义向量,共指链和实体轨迹先做数值归一化,主题与意图轨迹则和全局上下文编码器算出来的向量对齐。之后这些不同粒度的表示进入一个融合层,用注意力机制给每一类特征动态分配权重。这个“动态”很关键,因为不同场景下各特征的贡献是不一样的。用户明确说“我之前说的”,共指链权重就会升高;用户开头第一句就很模糊,外部知识和主题先验的权重就会升高。
4.2 置信度阈值与澄清式反问
打分之后,OpenClaw 会把候选实体的得分归一化成概率分布。如果最高概率低于阈值,或者最高与次高的差值不足,系统不会硬猜,而是触发澄清式反问。
澄清式反问不是简单地问“你是哪个意思”,而是利用候选实体之间的差异来生成提问。比如候选是两个餐厅,一个主打火锅一个主打日料,系统会问“您指的是 XX 火锅那家,还是日料那家?”这种方式能让用户快速给出有效反馈,一旦用户确认,后续的消歧直接锁定。
这个兜底策略在真实对话里非常有用。多轮对话系统的目标不是每轮都给出预测结果,而是减少错误率。与其在低置信度时强行消歧导致后续连锁错误,不如主动向用户确认一次。OpenClaw 在阈值设计上留了很大的自定义空间,不同场景可以调不同的严格度。
4.3 可解释性:让每一次消歧都能复盘
OpenClaw 在消歧模块里保留了一份特征贡献记录,每次消歧决策都能输出“哪个特征把得分拉高、哪个特征把得分压低”的解释信息。这个设计刚开始不起眼,但线上调优时帮了大忙。
真实对话系统的错误是常态,关键是怎么快速定位。有一次排查一个连续消歧错误,单看模型输出完全无头绪,后来打开特征贡献记录,发现某个候选实体完全是被外部知识特征里的“热门程度”抬到高分的,而实体轨迹特征其实在强烈反对。问题一下子就定位到特征权重失衡上。这种可解释性能力,我觉得是 OpenClaw 结构设计里最值得抄作业的部分。
5. 实测中的坑与调优记录
5.1 长对话主题漂移:窗口切分太粗暴
我在复现这套特征体系时,遇到的第一个大坑是长对话里的主题漂移。最初把上下文窗口设成最近 20 轮原文加全局摘要,看起来合理,但实际聊天一旦超过 30 轮就会出现问题。
现象很典型:用户前 10 轮一直在聊某餐厅,中间 20 轮聊了电影和购物,最后突然说“那家店还开着吗”。我这个复刻版直接把“那家店”消歧到了最近 20 轮里最活跃的电影相关实体上,完全丢了最开始那家餐厅。
排查链路是这样走的:先看实体轨迹特征,发现餐厅实体最近一次出现的轮次已经超出窗口;再看主题向量,发现当前主题停留在购物;最后看全局摘要,摘要已经把早期餐厅信息压得很淡。问题根源是窗口切分只考虑最近 N 轮,没有考虑对话内部的结构边界。我的解决方案是给对话做分段主题跟踪,把对话切成若干阶段,每个阶段单独存一个主题向量,旧阶段的实体轨迹不删,只是活跃度衰减。消歧时除了当前阶段向量,还保留一份全局摘要做二次参考,问题明显缓解。
5.2 冷启动歧义:低置信度时该不该硬答
第二个坑来自冷启动场景——用户第一轮就给模糊指称,系统没有任何历史可参考。我刚开始把阈值设得比较低,想让系统尽量给出回答,结果发现错误率特别难看。
举个例子,用户一上来就说“那个能折叠的手机怎么样”,候选里有多个折叠屏型号,外部知识特征里热门度高的那款会拿到很高的分数,但用户心里的目标可能根本不是热门款。强行消歧的结果就是答非所问。
排查后发现,这类错误通常伴随候选概率分布比较平坦,最高分和次高分差距很小。把阈值调高、强制低置信度时澄清之后,第一轮准确率没怎么变,但后续对话的整体槽位正确率上升了不少。冷启动场景里,“承认自己不确定”比“硬给一个答案”对用户体验更好。
5.3 误消歧的连锁传播:共指链如何纠偏
第三个坑来自误消歧的连锁传播,这也是前面在共指链特征里提到的置信度问题。
现象很隐蔽:第一轮把“某品牌 A”误消歧成了另一个同名品牌,紧接着几轮用户都顺着这个错误实体在聊,系统居然还能自洽地一路回答下去,因为共指链把每轮错误的指称都串到了一起。等到用户最后反应过来追问时,前面已经积累了四五轮错误。
我的排查方法是看共指链每个节点的置信度,发现第一次消歧的置信度本来就只有 0.5 左右,但系统后续仍然把它当成高置信实体来传递。修复方案和 OpenClaw 的做法一致:每个实体轨迹节点保存置信度,低于阈值的节点不参与后续共指传递;同时一旦用户出现纠偏信号,就追溯该实体关联的所有槽位,做一次性回滚修正。这之后,连锁传播类错误基本不再出现。
5.4 权重敏感度:recency 与主题优先级是矛盾的两端
最后一个想说的坑是特征权重之间的博弈,最典型的是 recency 和主题这两个特征打架。
用户聊着聊着突然岔开话题问了一个临时问题,然后说“回到刚才那个”,这里的“刚才那个”应该指主题切换前的实体,但 recency 特征会倾向于把分数给岔开话题中最后提到的实体。反过来,如果用户在当前主题里提到一个显式指代“之前说的那个”,主题特征会把分数推向当前主题里的高活跃实体,而用户实际想回溯的可能是几轮前另一个主题的实体。
我的调优思路是区分显式指代和隐式指代。显式指代(“之前说的”“刚才那个”“上次提到的”)出现时,把共指链特征权重拉高,让历史实体轨迹主导;没有显式指代时,才让当前主题和 recency 主导。判断方式很简单,检测指称里有没有时间回指词和指示词前缀。这个小改动让两类错误同时减少了不少。
6. 这套上下文特征设计能复制到哪些场景
6.1 智能客服:产品、政策、工单查询非常契合
智能客服是这套设计最适合落地的场景之一。客服对话天然围绕产品、订单、政策这些有清晰目录的实体展开,候选集是可控的,消歧的准确率比开放领域高很多。
在客服场景里移植 OpenClaw 的特征设计时,有一点特别值得做:把用户历史工单和账户信息作为跨会话偏好特征的强来源。用户问“那个套餐的流量用完了怎么办”,如果系统知道用户办的是哪一档套餐,消歧基本不需要靠推测。这个场景里,用户反馈特征也很好用,因为客服对话常常伴随着用户明确的否定和修正。
6.2 语音助手与知识问答
语音助手场景需要额外处理一个语音层面的问题:ASR 会产生同音词错误,比如“社”和“设”混淆,导致别名召回失效。OpenClaw 本身主要处理文本输入,但它的特征框架可以直接借鉴,只要把局部文本特征替换成融合了音频置信度的语义特征,同时保留共指链和系统状态特征。
知识问答场景可以直接复用外部知识特征,因为候选本身就来自知识图谱,每个候选的描述、类型、关联关系都是现成的。比较适合的做法是把“候选间关联特征”用得更狠一些,知识图谱里的实体不是孤立的,两个候选之间的跳数越少,越可能是用户指称的目标。
6.3 轻量化落地的裁剪策略
不是每个系统都需要一口气上七类特征。我给自己的项目定了一个分层裁剪策略,初始版本只保留四类:当前轮局部文本、共指链与实体轨迹、对话主题、候选外部知识。用户反馈和跨会话画像属于锦上添花,等基础准确率上来之后再逐步加入。
落地时还有一个建议:先做特征日志和错误案例收集,再考虑复杂的融合模型。最开始用简单加权就能发现很多问题,调试清楚再往深度模型升级,会平滑很多。开源社区里不少项目跳过了特征工程直接上深度模型,结果上线之后完全没法排查错误,只能从头补日志。OpenClaw 这种“先结构化上下文、再谈消歧决策”的思路,我觉得才是这类系统真正值得学习的地方。
最后再分享一个小技巧:我在复刻这套特征体系时,发现最容易被低估的是用户反馈特征和置信度回溯。很多团队把精力花在花哨的编码器上,但真正稳定提升多轮对话质量的,往往是这种带交互状态的特征。如果你也在做多轮实体消歧,建议先把特征贡献日志做好,每一条错误都留一份可追溯的记录。后面调优的时候,你会发现这些日志比模型本身的输出值有用得多。
