想象你走进一家热闹的餐厅,接待你的是一位资深服务员。你刚落座说“我想吃点辣的”,他点头记下;你补一句“别放香菜”,他又在便签本上添了一笔;等朋友到了你说“那就再加个水煮鱼吧”,他不用你重复,张口就问“还是老规矩,微辣、不要香菜对吧?”你惊讶于他的记性,其实秘密全在那本便签本上——每一轮对话他都把关键信息记下来、更新掉、合并好。对话式搜索系统就像这位服务员,用户说的每一句话都会被拆解成“槽位”,填进一张不断更新的状态表里。这张表叫对话状态(Dialogue State),更新它的机制叫对话状态跟踪(DST),而“那个菜”“就那家吧”这种含糊说法要靠指代消解,残缺的查询要靠改写补全,便签太多又要靠上下文管理来取舍。这篇教程,就带你拆解这套“服务员的便签系统”如何支撑起多轮对话式搜索。

岗位关联

掌握对话状态跟踪与上下文管理,是构建真正能“聊下去”的搜索产品的核心能力——它将决定你的 AI 是像耐心的领班,还是只有三秒记忆的金鱼。

目录
  1. 可视化演示
  2. 对话状态跟踪:服务员的便签本
  3. 指代消解:听懂“那个、它、这家”
  4. 查询改写:把半句话补完整
  5. 上下文窗口管理:翻篇的艺术
  6. 多轮检索交互:渐进式点菜
  7. 精度与延迟权衡:记得多与反应快
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

演示对话式搜索中的多轮状态跟踪:DST状态演化、查询改写与指代消解过程,以及上下文窗口长度对精度与延迟的影响。

本节配有交互动效(进入视口后自动加载,约 3KB)。

多轮对话状态跟踪 每轮对话更新DST状态,维护用户意图与槽位信息 跨轮上下文累积,渐进式获取用户需求 状态置信度随轮次增加而收敛 S(t)=Update(S(t-1),u(t)) 状态跟踪模型维护对话历史

对话状态跟踪:服务员的便签本

一家高档餐厅里,最受好评的服务员往往有“过耳不忘”的本领。这并非他记忆力超群,而是他随身带一本便签本:客人每说一句,他就记一笔——“3号桌,两位,一位忌辣、一位素食”。对话式搜索引擎的本质,就是给 AI 配一本这样的便签本。这本便签本在技术领域有一个专门的名字:对话状态。而维护这本便签本的系统机制,就是对话状态跟踪(Dialogue State Tracking,DST)。

对话状态不是把用户的每句话原封不动地抄下来,而是像服务员那样只记“关键字段”。这些字段被称为“槽位”(Slot)。用户说“我想找一家朝阳区的川菜馆”,系统会将其拆成两个槽位:区域=朝阳区,菜系=川菜。这套“提取槽位并填值”的动作就是槽位填充。整本便签本的内容,就是一张不断累积、更新的状态表。

槽位填充之外,更重要的是状态更新。客人中途改主意怎么办?用户先说“想吃川菜”,下一轮又说“算了,换粤菜”。如果便签本只增不改,状态表里就会同时存在两个矛盾的菜系。因此 DST 需要一套状态更新策略:覆盖旧值、追加新值或删除整个槽位。实际系统中,更新往往不是非黑即白的,而是给每个候选槽值打一个置信度分——就像服务员也会犹豫:“刚才这位客人好像说不要香菜,但也有可能是我听岔了。”

有了这本会更新、会打分的便签本,系统就能在客人说出“那还是算了”时,迅速判断该修改哪个槽位。DST 做得好不好,直接决定了后续所有搜索与推荐动作的起点——正如便签本记错了,整桌菜都会上错。

P(st∣h1:t)=α⋅P(ot∣st,h1:t−1)⋅P(st∣st−1,h1:t−1)P(s_t \mid h_{1:t}) = \alpha \cdot P(o_t \mid s_t, h_{1:t-1}) \cdot P(s_t \mid s_{t-1}, h_{1:t-1})
这个公式描述了对话状态如何逐轮更新:新状态的概率由“当前观测能否解释”和“新状态是否承接旧状态”共同决定。
  1. 当前状态 s_t第 t 轮对话结束时,便签本上应该记录的槽位值组合,也就是我们想推断的目标。
    sts_t
  2. 历史 h_{1t-1}:从第 1 轮到第 t-1 轮的全部对话,相当于服务员脑海里前几页便签的内容。
    h1:t−1h_{1:t-1}
  3. 观测概率与转移概率P(o_t|s_t) 衡量“当前状态解释用户本轮话”的可信度,P(s_t|s_{t-1}) 衡量“新状态承接上一轮状态”的自然程度,两者相乘再归一化,得到后验概率。
    P(ot∣st)⋅P(st∣st−1)P(o_t \mid s_t) \cdot P(s_t \mid s_{t-1})
  4. 归一化常数 α让所有候选状态的概率之和等于 1,保证结果是一个合法的概率分布。
    α=1∑st′P(ot∣st′) P(st′∣st−1)\alpha = \frac{1}{\sum_{s'_t} P(o_t \mid s'_t) \, P(s'_t \mid s_{t-1})}

指代消解:听懂“那个、它、这家”

客人翻着菜单忽然说“就那个吧”,服务员不会愣住。他会顺着客人的目光,或结合刚才的对话推断出“那个”指的是“水煮鱼”。这就是指代消解(Coreference Resolution):把对话里模糊的指代词,对齐到具体的事物上。

在对话式搜索里,指代消解发生在两个层面。第一类是代词消解:用户说“它环境怎么样”,系统要搞清楚“它”指上一轮提到的哪家餐厅。第二类是省略补全:用户说“来一份和刚才一样的”,整句话没出现任何名词,全靠历史推断。两者本质相同:从候选集合里挑出最可能被指代的那个实体。

现代检索系统通常把候选实体表示成向量,再计算指代词与候选实体的语义相似度,得分最高的胜出。这里有一个常见陷阱:指代消解不能只看最近提到的实体,还要结合 DST 状态表——用户连续三轮都在聊“第二家店”,那么“那家”的候选就应该优先考虑状态表里记录的选择项。

指代消解就是服务员的“读眼神”能力。能听懂“那个”“这家”的搜索系统,才能让用户像跟老朋友聊天一样,只说半句话就把结果找到。

score(ci)=cos⁡(vm,vci)=vm⋅vci∥vm∥⋅∥vci∥\mathrm{score}(c_i) = \cos(\mathbf{v}_m, \mathbf{v}_{c_i}) = \frac{\mathbf{v}_m \cdot \mathbf{v}_{c_i}}{\|\mathbf{v}_m\| \cdot \|\mathbf{v}_{c_i}\|}
指代消解本质上是一个排序问题:把模糊指代词映射到得分最高的历史实体上。
  1. 指代词向量 v_m把“那个”“它”转成向量表示,也就是它在语义空间中的位置。
    vm\mathbf{v}_m
  2. 候选实体向量 v_{c_i}对话历史里出现过的每个餐厅、商品、地点都对应一个向量。
    vci\mathbf{v}_{c_i}
  3. 点积与模长点积衡量两个向量的方向一致性,再除以各自模长消除长度影响,得到取值在 -1 到 1 之间的余弦相似度。
    vm⋅vci∥vm∥⋅∥vci∥\frac{\mathbf{v}_m \cdot \mathbf{v}_{c_i}}{\|\mathbf{v}_m\| \cdot \|\mathbf{v}_{c_i}\|}

查询改写:把半句话补完整

服务员不只是记性好,他还特别会“翻译”。客人说“还是老样子”,他在下单时写的是“美式咖啡,大杯,少糖”——完整、可执行。对话式搜索也一样:用户的下一条指令往往支离破碎,但检索器需要的是一个完整的查询语句。这个“翻译”过程就是查询改写(Query Rewriting)。

查询改写通常做三件事。第一是指代改写:把“那里的酱牛肉怎么样”中的“那里”直接替换成上一轮的店名。第二是缺失补全:用户说“有没有包间”,改写后变成“刚才那家店有没有包间”。第三是历史融合:把多轮中提到的条件合并成一条完整查询,比如“川菜 + 朝阳区 + 人均100”。这些动作都和 DST 共享同一张状态表——DST 负责记,查询改写负责用。

工程上有两类实现方式。早期的规则式系统用模板替换,如今的主流方案是用自然语言生成模型把历史与当前查询拼起来做端到端改写。改写质量直接影响检索效果:改写得残缺,检索器就像服务员只听到半句话就跑去下单。

查询改写让搜索“耳朵”变得更聪明:用户不必每次把话说全,系统就能准确执行。这正是对话式搜索比传统“搜索框+回车”用户体验更像真人服务的关键所在。

qt′=fθ(qt; h1:t−1)=generate([qt⊕summarize(h1:t−1)])q'_t = f_\theta(q_t;\, h_{1:t-1}) = \text{generate}([q_t \oplus \text{summarize}(h_{1:t-1})])
查询改写把当前不完整的口语输入,结合历史摘要,生成一条完整可检索的查询语句。
  1. 当前查询 q_t用户本轮的原始输入,往往是不完整、口语化的表达。
    qtq_t
  2. 历史摘要 summarize(h)把前面几轮的关键信息压缩成一句话,相当于便签本裁剪后的精华版。
    summarize(h1:t−1)\text{summarize}(h_{1:t-1})
  3. 拼接与生成 generate模型把原始查询与历史摘要拼在一起,产出完整的检索式查询——这就是“补全”动作的数学表达。
    [qt⊕summarize(h1:t−1)]→qt′[q_t \oplus \text{summarize}(h_{1:t-1})] \to q'_t

上下文窗口管理:翻篇的艺术

便签本总不能无限厚。服务员记得越多,翻页越慢,还容易把旧单子跟新单子搞混。所以有经验的服务员会定期总结:把前面几页的细节浓缩成两三行要点,然后痛快地翻篇。对话式搜索里的上下文管理,处理的就是这个“翻篇”问题。

大语言模型一次能处理的 token 数量是有限的,这个上限就是上下文窗口。窗口太小,模型记不住早轮信息;窗口太大,计算开销暴涨且容易淹没关键信号。上下文窗口管理因此成为对话式搜索的工程核心,常见策略有三种:固定窗口截断、滑动窗口、历史摘要压缩。

滑动窗口机制会在注意力计算中加一个掩码(Mask),让每个位置只能关注前后 k 个位置的信息,窗口之外直接视为“不存在”。这样既能把有效上下文控制在合理长度内,又能显著降低计算量。摘要压缩则更进一步:在窗口快满时,调用模型把旧对话压成一段摘要,再接续新对话。这就像服务员趁上菜间隙,把前几页便签重新誊成一行要点。

上下文窗口管理,就是服务员那套“记重点、加快餐、定期翻篇”的职业习惯。好的窗口策略让系统既记得住关键,又不被旧信息拖慢脚步。

Mij={0∣i−j∣≤k−∞otherwiseM_{ij} = \begin{cases} 0 & |i - j| \le k \\ -\infty & \text{otherwise} \end{cases}
掩码矩阵决定了注意力可以“看”多远:窗口内的 token 正常参与计算,窗口外的一律忽略。
  1. 位置下标 i, j分别表示当前 token 和历史 token 在序列中的位置,差值越大说明距离越远。
    ∣i−j∣|i - j|
  2. 窗口半径 k允许关注的最近范围。k 越大,窗口越宽,保留的历史信息越多。
    kk
  3. 掩码值 0 与 -∞注意力分数加 0 保持不变;加 -∞ 经过 softmax 后趋近于 0,相当于完全忽略远处的 token。
    MijM_{ij}

多轮检索交互:渐进式点菜

训练有素的服务员不会傻站着等客人一次把菜点完。他会在客人犹豫时提议“要不先来个招牌菜?”,在客人选好一桌菜后确认“这一桌是辣口还是清淡口?”——边聊边收窄。多轮对话式搜索正是这样一种渐进式点菜过程。

每一轮用户输入都会被 DST 解析,再经查询改写补全,随后触发一轮检索。但多轮检索不是把各轮结果简单堆在一起,而是有三层设计。第一层是渐进式检索:每轮在上轮结果基础上追加筛选条件,候选集合逐轮收窄。第二层是澄清机制:当系统发现某个槽位缺失且对结果影响很大时,主动向用户提问。第三层是结果融合:把本轮检索结果与历史轮次的结果合并重排。

结果融合时,系统通常会计算一个联合分数:本轮相关度与历史相关度的加权和。如果用户连续四轮都在比较同一批餐厅,那历史相关度就应占更高权重。工程上要小心:融合不当会造成“早期错误反复强化”,所以有的系统还会加上去重与多样性控制。

多轮检索让搜索从“一次定终身”变成“步步紧逼,层层筛选”。像老练的服务员一样,系统在确认中推进、在澄清中收敛,最终把最合适的答案端到用户面前。

R(d∣h1:t)=λ⋅rcur(d∣qt′)+(1−λ)⋅rhist(d)R(d \mid h_{1:t}) = \lambda \cdot r_{\text{cur}}(d \mid q'_t) + (1 - \lambda) \cdot r_{\text{hist}}(d)
候选文档的最终得分是“本轮相关性”和“跨轮历史相关性”的加权平均。
  1. 候选文档 d候选池中一个可能满足用户意图的搜索结果。
    dd
  2. 当前轮相关度 r_cur本轮改写后的查询与文档的相关性打分。
    rcur(d∣qt′)r_{\text{cur}}(d \mid q'_t)
  3. 历史相关度 r_hist文档与之前几轮对话主题的匹配程度,体现“我们一直在聊的东西”。
    rhist(d)r_{\text{hist}}(d)
  4. 权重 λ控制本轮与历史的平衡。λ 大则更看重当前指令,λ 小则更尊重历史偏好。
    λ\lambda

精度与延迟权衡:记得多与反应快

谁不喜欢一个记得全的服务员?但他要是每回答一句话都要翻五遍便签本,客人早就等急了。现实中的服务员都在“记得多”与“反应快”之间找平衡。对话式搜索系统面临同样的抉择:上下文越长,状态跟踪的精度可能越高,但延迟也会随之上升。

问题的根源在于注意力机制的计算复杂度。Transformer 的自注意力复杂度是 O(L²),也就是说上下文长度翻倍,计算量约翻四倍。延迟的另外两笔开销来自 DST 和查询改写:状态表越大,槽位匹配越慢;历史越长,改写时的输入也越长。“搜得快”和“记得多”因此成了一对直接矛盾。

业界的常见折中策略包括:对历史做句子级裁剪,只保留与当前查询相关度最高的若干句;对早期轮次的键值缓存进行压缩,用粗粒度摘要替代细粒度 token;还有“先快后慢”的分级检索——第一轮用轻量模型粗筛,候选变少后再调用更大的重排模型精排。

精度与延迟的权衡没有标准答案——街边快餐店追求快,米其林餐厅追求精细。对话式搜索产品要根据用户场景选择自己的“便签本厚度”:客服机器人要快,知识问答可以慢一点但要准。理解了这层权衡,才算真正理解对话式搜索的工程全貌。

T(L)=a⋅L+b⋅L2\mathcal{T}(L) = a \cdot L + b \cdot L^2
系统总延迟由线性项和平方项构成:长度增加时,平方项主导,延迟近似按二次曲线上升。
  1. 上下文长度 L系统实际携带的 token 总数,即“便签本总页数”。
    LL
  2. 线性项 a·L编码阶段的开销,与长度成正比,类似“逐页翻找”。
    a⋅La \cdot L
  3. 平方项 b·L²注意力计算的开销,长度翻倍时约变成原来的四倍,类似“每页都要和所有页做一次比对”。
    b⋅L2b \cdot L^2

AI 应用场景

电商售后客服机器人

阶段:检索前处理与多轮查询理解

解决的问题:传统客服需要用户反复提供订单号、商品名等完整信息,体验割裂。AI 用 DST 跟踪当前会话中的订单实体与售后意图,用指代消解把“那件衣服”对齐到历史订单商品,再结合查询改写生成完整的检索式,从订单库和知识库中精准召回答案。

具体案例:某电商平台的售后机器人收到用户第一轮提问“我的订单怎么还没到”,第二轮追问“那件黑色的外套呢”。系统通过状态表锁定会话中的订单实体,把“那件黑色的外套”改写成“订单 #20240518 中的黑色外套”,直接调取物流信息回答,无需用户重新描述。

本地生活对话式推荐

阶段:多轮检索与结果重排

解决的问题:用户找餐厅时往往边想边说,条件逐步追加。传统搜索每轮独立处理,无法累积“川菜+朝阳+人均100”这样的复合条件。AI 利用 DST 逐轮累积槽位,查询改写自动融合历史条件,上下文窗口管理保证模型只关注最近有效的约束条件。

具体案例:用户先说“找个地方吃饭”,系统不急着检索;再说“川菜吧”,检索范围收窄到川菜;“在朝阳区”“人均一百左右”逐轮追加后,系统结合“三个人”的人数槽位与历史结果融合,最终推荐 3 家符合全部条件的餐厅,并主动澄清“需要包间吗”。

企业知识库问答助手

阶段:上下文管理与状态更新

解决的问题:企业内部知识库中,员工常连续追问同一主题的多个维度。AI 依靠上下文窗口维护“当前讨论对象”,用 DST 记录该对象的属性槽位,避免每次提问都要完整重述项目名或文档名。

具体案例:员工问“这个项目的截止时间?”系统返回后,再问“那预算呢?”系统根据窗口内的“项目对象”自动补全问题为“这个项目的预算”,直接检索知识库对应文档并返回数字,效率比传统搜索大幅提升。

Python 演示

python59 行
# -*- coding: utf-8 -*-"""对话状态跟踪与查询改写演示:基于槽位规则的DST"""import re class DialogueStateTracker:    def __init__(self):        self.slots = {}     def update(self, utterance):        """从用户话语中抽取槽位并更新状态表"""        if "川菜" in utterance:            self.slots["cuisine"] = "川菜"        if "粤菜" in utterance:            self.slots["cuisine"] = "粤菜"        if "朝阳" in utterance:            self.slots["district"] = "朝阳区"        if "人均" in utterance:            match = re.search(r"人均\s*(\d+)", utterance)            if match:                self.slots["budget"] = int(match.group(1))        match = re.search(r"(\d+)\s*人", utterance)        if match:            self.slots["party_size"] = int(match.group(1))        return self.slots def resolve_coreference(utterance, state):    """指代消解:把'那家''那个'替换为状态表已知实体"""    if "那家" in utterance and "district" in state.slots:        return utterance.replace("那家", state.slots["district"] + "的餐厅")    if "那个" in utterance and "cuisine" in state.slots:        return utterance.replace("那个", state.slots["cuisine"])    return utterance def rewrite_query(utterance, state):    """查询改写:用状态表补全缺失条件,拼出完整检索式"""    conditions = [state.slots.get("cuisine", ""),                  state.slots.get("district", "")]    prefix = " ".join([c for c in conditions if c])    return (prefix + " " + utterance).strip() def main():    tracker = DialogueStateTracker()    turns = [        "我想吃川菜",        "就在朝阳区找",        "人均一百左右",        "三个人,那家能带宠物吗"    ]    for i, turn in enumerate(turns, 1):        turn = resolve_coreference(turn, tracker)        tracker.update(turn)        full_query = rewrite_query(turn, tracker)        print(f"第{i}轮 用户原话: {turn}")        print(f"      状态表: {tracker.slots}")        print(f"      改写查询: {full_query}")        print() if __name__ == "__main__":    main()
目的:演示一个极简规则版 DST——逐轮抽取槽位、消解指代、改写查询,展示对话式搜索“预处理”环节的完整链路。
  1. self.slots = {}初始化状态表(便签本),所有槽位值都累积在这里。
  2. if "川菜" in utterance: self.slots["cuisine"] = "川菜"槽位填充的规则式实现。
  3. re.search(r"人均\s*(\d+)", utterance)用正则从自然语言中抽取数字型槽位。
  4. if "那家" in utterance and "district" in state.slots指代消解:只有当状态表里有“区域”信息时才做替换,避免盲目替换。
  5. conditions = [state.slots.get("cuisine", ""), ...]查询改写把状态表中的历史条件收集起来。
  6. prefix = " ".join([c for c in conditions if c])过滤空槽位后融合成前缀,实现历史信息融合。
  7. turn = resolve_coreference(turn, tracker)先消解指代,再填充槽位,顺序体现 DST 的“先理解、后记录”。

常见误区

误区“对话状态跟踪不就是把用户说的每句话都存下来吗?记性好的人就是把每句话都背下来。”

正解DST 存的是结构化槽位(如“菜系=川菜”),不是原始文本。原始文本属于历史记录,状态表是语义化的“当前最可靠用户意图”。就像服务员记的是“3号桌忌辣”,而不是逐字背下客人所有的闲聊。存原话不仅浪费存储,检索时也难以对齐槽位、更新状态。

为何常见:“记住所有内容”在直观上最保险,而且很多简单缓存方案确实直接存原文,容易混淆两者。

误区“要保证不丢信息,把整场对话都塞进上下文窗口才最准。”

正解上下文过长会引入噪声,旧轮信息干扰新轮判断,且注意力复杂度 O(L²) 导致延迟暴涨。窗口管理的核心是“留关键、丢冗余”,在精度和延迟之间找平衡。与其全塞进去,不如用摘要压缩把历史“提纯”。

为何常见:直觉上“信息全 = 效果全”,忽略了噪声干扰与计算成本这两个工程现实。

误区“指代消解就是把'它''这个'找出来,没有代词就不用做。”

正解省略才是重头戏。用户说“跟刚才一样”“还是要那个”,句中没有显式代词,但需求必须靠历史推断补全。菜单上的“还是老样子”没有代词,服务员照样明白。指代消解的本质是“补齐所指”,而非“找代词”。

为何常见:术语“指代”让人首先联想到代词,忽略了省略也是指代的一种形态。

误区“改写就是把用户的话换成更高级的同义词,让搜索更准。”

正解查询改写核心是补全缺失信息和消解指代,把口语残缺句变成完整可检索语句。比如“有包间吗”要改写成“刚才那家川菜馆有包间吗”,而不是把“包间”换成“包厢”这种同义替换。改写服务的是检索器,不是修辞学。

为何常见:“改写”的字面意思容易让人联想到同义句转换,忽略了它补全信息的主要使命。

误区“系统主动反问用户显得很笨,最好每次都靠猜。”

正解澄清是阻断错误链传递的关键策略。当槽位缺失且对结果影响很大时,反问一句比连续猜错三轮更高效、更省时。服务员的“确认一下,您忌辣对吧?”不是笨,而是专业的风险控制。

为何常见:产品经理往往害怕“打扰用户”,但在多轮搜索中,试错成本远高于一次确认的成本。

面试题

Q1. 对话状态跟踪(DST)的核心任务是什么?

单选题 · easy

  • A.记住用户每一句的原文
  • B.维护结构化的槽位状态表← 正确答案
  • C.压缩并总结完整对话历史
  • D.生成最终的自然语言回复

答案:B。DST 的核心是把用户意图结构化为槽位状态表(如“菜系=川菜”),而非存储原文、压缩历史或生成回复。存储原文是缓存模块的职责,摘要压缩属于上下文管理,生成回复是生成模型的事。

Q2. 用户说“我想吃川菜”,DST 会将其记录为?

单选题 · easy

  • A.存储一条完整原文记录
  • B.填充槽位“菜系=川菜”← 正确答案
  • C.转换成一段稠密向量
  • D.生成一条结构化 SQL 语句

答案:B。DST 的槽位填充动作把口语解析成“槽位-值”对。向量表示服务于检索匹配,SQL 语句服务于数据库查询,都不是 DST 的直接产物。就像服务员记“菜系=川菜”,而不是背下整句话。

Q3. 滑动窗口撤出最旧对话后,被撤内容通常如何处理?

单选题 · easy

  • A.仍然参与每一次检索
  • B.彻底从系统中永久删除
  • C.可能被摘要压缩后保留← 正确答案
  • D.随机抽样部分继续参与

答案:C。被撤出窗口的内容通常先尝试摘要压缩,保留关键信息后释放空间,而不是彻底删除或继续参与检索。这与服务员把旧便签页浓缩成一行要点再翻篇的道理一致。

Q4. 用户说“算了换粤菜吧”,DST 状态表最合理的更新是?

单选题 · mid

  • A.追加“菜系=粤菜”新槽值
  • B.覆盖原槽值为“菜系=粤菜”← 正确答案
  • C.删除菜系槽位并清空所有值
  • D.保留川菜同时保留粤菜

答案:B。“算了换”表示用户修改意图,应覆盖原先的“菜系=川菜”。追加会导致两个菜系同时存在造成矛盾,删除则丢失了用户仍想吃中餐的信息。就像服务员听到客人改口后,用橡皮擦掉旧菜名重写。

Q5. 查询改写最主要的目标是?

单选题 · mid

  • A.把口语补全成完整检索式← 正确答案
  • B.把查询翻译成多种语言
  • C.将结果翻译成用户母语
  • D.把长查询缩短减少计算

答案:A。查询改写的核心是补全缺失信息、消解指代,让“还是那家”变成“朝阳区那家川菜馆”,从而适配检索器。翻译和压缩都不是它的主要目标。这就像服务员把客人的“老样子”翻译成完整可执行的订单。

Q6. 上下文窗口管理的常见策略包括?

多选题 · mid

  • A.固定窗口截断最旧对话← 正确答案
  • B.滑动窗口加注意力掩码← 正确答案
  • C.摘要压缩历史对话信息← 正确答案
  • D.无限扩大模型的窗口上限

答案:ABC。截断、滑窗、摘要压缩是三种主流策略。“无限扩大窗口”不现实,因为注意力计算 O(L²) 成本爆炸,硬件内存也有限。窗口管理的本质是在有限资源内做取舍,而非无限扩张。

Q7. 自注意力复杂度 O(L²) 意味着上下文翻倍时,注意力计算量?

单选题 · mid

  • A.约增加到原来的两倍
  • B.约增加到原来的四倍← 正确答案
  • C.保持不变没有任何变化
  • D.约增加到原来的一半

答案:B。O(L²) 是平方复杂度,L 变为 2L 后,L² 变为 4L²,计算量约增至四倍。这解释了为什么“便签本厚一倍的代价是翻页慢四倍”,也是上下文窗口必须管理的根本原因。

Q8. 关于掩码 M_ij=-∞(|i-j|>k)的作用,下列说法正确的是?

多选题 · hard

  • A.窗口外 token 的注意力权重被抹零← 正确答案
  • B.能够降低注意力计算开销← 正确答案
  • C.对窗口外 token 使用随机注意力
  • D.增强窗口外 token 的重要性

答案:AB。-∞ 经 softmax 后权重趋于 0,相当于抹零窗口外 token,同时因为限制了注意力范围,计算量也随之下降。随机注意力和增强远距离 token 与掩码的语义完全相反。

Q9. 多轮检索结果融合时,历史相关度权重过大可能导致?

单选题 · hard

  • A.系统延迟显著降低
  • B.早期错误被反复强化放大← 正确答案
  • C.用户查询被完全忽略
  • D.候选文档自动去重精简

答案:B。历史权重过大时,早期检索中的错误结果会在后续每轮都被赋予高相关度,形成“错误放大”效应。这正是需要引入去重和多样性控制的原因。就像服务员记错了忌口,后面每道菜都会错。

Q10. 下列哪些措施能缓解多轮搜索精度与延迟的矛盾?

多选题 · hard

  • A.对历史做句子级相关度裁剪← 正确答案
  • B.压缩早期轮次的 KV 缓存← 正确答案
  • C.分级检索先粗筛后精排← 正确答案
  • D.无条件增大上下文窗口

答案:ABC。句子级裁剪减少保留 token,KV 压缩降低显存与计算,分级检索把重计算放在小候选集上,三者都能在保住精度的同时降低延迟。无条件增大窗口只会加剧延迟,是错误选项。