Self-Listening:让语音助手听见自己的声音,打断后知道说到哪

全双工语音助手,真的知道自己说到哪了吗?

你打断了语音助手,问它:"我刚才数到几了?"它停下来,自信地回答:"数到了 22。"可你明明只听到 17。五个数字的落差看上去像一次口误,但论文作者用受控实验把这件事量化之后发现,这不是个案,而是全双工语音模型的结构性失忆:在被打断的那一刻,它以为自己说过的,和用户实际听到的,是两回事。

要解释为什么它会把用户只听到 17 的进度报成 22,得先回到全双工出现前的对话方式。早期语音助手是轮流制,用户说完、助手再说,说话权清晰交接,"我说到哪了"根本不构成问题。全双工模型可以一边听一边说,用户会在它开口时直接插话,打断是常态而非异常,就像两个人打电话同时说话。没有外部仲裁者来标记进度,"我说到了哪"只能靠模型自己跟踪。轮流制的时间线上,助手的播放与用户的麦克风永不重叠;全双工允许两路语音短暂交叠,用户可以在助手仍在说话时开口,助手必须当场决定是让位还是继续说。这个技能以前用不上,现在却成了产品体验的命门:实时语音助手把"边说边听"变成了日常,接错话的代价从无害误差变成实打实的尴尬。

麻烦在于,"说"这个动作被拆成了三段异步流水线:文本生成、语音合成、音频播放。生成跑得最快,合成慢一拍,真正从扬声器播到用户耳朵又慢一拍。模型内部对"我说过什么"的记账跟着第一段走,而用户听到的永远来自最后一站,两边进度天然脱节。

论文把这种脱节放到显微镜下,设计了一个数数探测:让助手从 1 数到 30,中途打断,问它"刚才数到几",然后画出"实际说到的数 a"与"随后上报的数 r"。

图注:论文的受控数数探测。横轴是打断时实际说到的数 a,纵轴是模型随后上报的数 r,虚线对角线 r=a 代表完美锚定;三个商用系统的垂直段可视化锚定差距 Δ_anchor=r−a,× 标记无效回答。Self-Listening

读这张图的重点不在精确数值,而在所有垂直段都偏离了对角线。论文用锚定差距 Δ_anchor = r − a 形式化这个落差,Δ_anchor = 0 才是完美锚定,结论是一句不留情面的话:被评测的实时语音系统,没有一个能可靠锚定到自己实际说出的话。Self-Listening 这里有个反差点值得挑明:模型生成数字的速度远快于播放,这与系统按生成进度而非播放进度作答的解释一致,但单靠该行为结果不能确定内部记账机制。理论上模型当然"知道"自己生成过什么,它亲手写出了那些 token;真正的难点在换算,把"我生成过"折算成"用户听到过",中间隔着合成与播放两段没人核对的延迟。Doubao-Realtime 严重报前,有时直接报出 30;GPT-Realtime-2.1 在早期打断点落差很大;Gemini-3.1-Flash-Live-Preview 最接近对角线,但超过 20 之后也开始偏移。更糟的是底部的 Moshi 与 Freeze-Omni,它们连"从 1 数到 30"这条初始指令都无法可靠执行,只能被排除在探测之外。

为什么这些对话 AI 会集体失忆?这类"能一边听一边说"的模型是近四年才出现的。dGSLM 于 2022 年首次公开(arXiv:2203.16502;期刊版 TACL 2023,论文正文以 Nguyen et al. 2023 引用),是最初的双通道全双工原型;直到 2024 年,Moshi 的 intro 仍自述 dGSLM 是此前唯一的全双工对话系统,并指出它有三个限制:not online、no text-LLM、no acoustic modeling。Moshi 2025 年起评测与综述体系成型,把全双工模型分成 engineered 与 learned 两种同步路线,该综述视野止于 2025-09。FDSLM Survey 能力在涨,但"说到哪了"这个最底层的问题,一直没人正面回答。

这不是播放卡顿,而是模型与自己的实际输出失联。这种失联在架构里到底出在哪一步?有没有一个系统的名字?下一章给出答案。

"我说到哪了"为什么这么难:锚定中断,与一个听回自己的答案

论文给这场失联起了正式名字:锚定中断(anchor interruption)。因为文本生成、语音合成、音频播放三者异步,模型"以为自己说过的"与"用户实际听到的"脱节,所以"重复最后一项""你数到哪了""继续"这类请求,必须以用户真正听到的播放前缀(played prefix)为准,而不是以模型内部生成的进度为准。否则模型要么重复用户已经听过的话,要么跳过用户还没听到的内容。这不再只是教科书问题,任何基于"重复最后一项"或"从打断处继续"的交互,都直接押注在模型对播放边界的记忆上。Self-Listening

名字有了,答案是什么?论文提出的修法直觉上几乎显然:让模型听回自己已经播放出去的语音。灵感来自人的自我监听。人说话时通过骨传导持续听到自己的声音,大脑据此实时核对每个字有没有发对;模型也该一样,把自己已经播给用户的波形,通过语音输入通路重新听回来。

图注:论文对 Self-Listening 的灵感示意:左图为人类说话时通过骨传导听到自己的声音,右图为模型把已播放波形回灌进 LLM 的听力通路,让模型锚定在用户实际听到的内容上。Self-Listening

这个设计里承重的是播放因果(playback-causal)一词:只有到当下为止已经到达用户端播放的波形帧才进入模型输入,"计划说但还没播出去"的内容一律不算。它也和另一类技术划清了界限。回声消除(acoustic echo cancellation)把扬声器漏回麦克风的回声当作干扰减掉;self-listening 则把它当成一条新的信号加进来。一个做减法,一个做加法,方向正好相反。这个词承重,是因为 s_t 里装什么直接决定模型能不能区分"说过了"与"还没说":装已播放的波形,边界清清楚楚;装生成完毕的文本,边界立刻消失。

你可能会问:Moshi 这类原生全双工(native full-duplex)模型不是早就有文本流跟踪自己的进度吗?确实有。Moshi 的 Inner Monologue 在每个时间步先预测一个文本 token 再生成语音 token,但那条流跟踪的是"我想说什么",不是"用户听到了什么"。意图与事实之间的落差,恰恰就是失联发生的地方。Moshi

顺带预告一个同期发现:几乎同时公开的 PACE 把同一现象称作 Generative Context Mis-anchoring(GCM),但它选择在 middleware 侧修,第六章再展开这个对偶。先回到 Self-Listening 本身:通道到底怎么落进架构?

怎么把"用户听到的"接进模型:三通道交错,与一条可调的粒度谱系

把"听回自己"落到实处,就是让模型在每个逻辑时间步(40ms)上同时读三路输入:用户语音 u_t、自己已播放的语音 s_t、自己的文本 x_t,串成一条三通道交错序列,记为 H=[u_0,s_0,x_0,u_1,s_1,x_1,…]。Self-Listening

图注:Self-Listening 三通道架构:顶部用户语音进入模型,中部 self-listening 通道只回灌已播放波形,底部模型文本通道输出普通回复 token 与 <stop>/<continue> 等控制 token 直接指挥 TTS;重叠时高亮 10 步约 400ms 的反应窗口。Self-Listening

两个设计点值得停下来看。其一,self-listening 通道 s_t 只收已播放波形,没有播放时就放一个 <silence> token,这是播放因果的落地;模型文本则被增量地发给冻结的 MOSS-TTS-Realtime 做流式合成。其二,打断决策不是瞬时切换,而是一段受控的反应窗口:检测到用户与模型声音重叠时,模型先发 <overlap>,在 K=10 步(约 400ms)内再落定为 <stop>(终止 TTS)或 <continue>(保持说话)。全部原生控制 token 有五类:<wait>/<overlap>/<stop>/<continue>/<silence>。顺带把推理时的分工说清楚:模型文本是唯一被采样的输出,普通 token 增量发给 TTS 合成,u_t 与 s_t 两条音频通道全程只是观察,原本的语音生成分支被关掉,发声这件事整体交给了专门的合成器。

这里可以放一段"电影":用户说"给我念明天的日程",模型念到"11:30 电话"时用户插话"改成两点"。模型先发 <overlap>,表示"听到了,我在拿主意",然后在约 400ms 的反应窗内落定 <stop>,TTS 即刻闭嘴,把说话权交还给用户。整个决策不是外部 VAD 的硬切换,而是模型自己在文本通道里写出来的一个明确的中间态。

可以把这三条流想成一间录音棚的三轨录音:用户人声轨、扬声器输出轨、文字脚本轨,模型像混音师,每 40ms 同时读一遍三轨当前的采样。关键在第二轨放的不是"我打算播什么"的草稿,而是"扬声器此刻真的在播什么"的实录。这个格局并不陌生:Moshi 的联合序列也是每列一个时间步、多路子序列并行,虚线以下由模型采样、虚线以上来自用户输入。Self-Listening 的新意不在这个列布局,而在文本与播放流的来源换了主人:从"意图文本"变成"经 self-listening 听到的已播放语音"。同一张图纸,换了一条信号源。Moshi

如果把"通道怎么切"当作一个设计变量,同期工作给出了一条完整的粒度谱系。Moshi 与 Self-Listening 走 per-frame,每个时间步对齐各路。FLM-Audio 放弃 word-level 对齐,改用整段连续的 monologue 加句间 <wait> token,文本流可以领先或落后音频(Lead/Follow 相位),保住预训练 LLM 的整句建模能力。FLM-Audio 它的理由是:word-level 对齐需要细粒度时间戳,成本高,而且为了对齐把完整句子拆碎,会伤语言建模能力。BayLing-Duplex 走块级:三通道按固定 N:M:N(实际取 10:5:10)比例成块交错,把对话状态压成 4 个 vocabulary 内的特殊 token,让打断与续答都退化成普通 next-token prediction。BayLing-Duplex 通道怎么排,是谱系上可调的设计变量;Self-Listening 的取舍,是让其中一条通道只装"用户实际听到的"。

通道搭好了,这些通道到底怎么训出来?loss 该落在哪一路?下一章。

怎么训练一个会听自己的模型:监督信号只放在文本通道

训练哲学的骨架是一句话:u_t 和 s_t 是输入,不是预测目标。模型不需要学会"生成"用户语音,也不需要学会"生成"自己的播放,它只需要在读到这两路输入之后,决定下一步说什么、停不停。所以 next-token 交叉熵损失只计算在 model-text 通道的有效目标上。Self-Listening 这样设计的道理很直白:把 s_t 当预测目标,等于逼模型预测自己接下来会播放什么波形,既浪费容量又不稳定;把 u_t 当目标更是荒谬,模型本就不该预测用户会说什么。文本通道是唯一"模型自己说了算"的输出,监督落在那里,恰好把"听"与"说"的职责分开。

可文本通道里混着两种东西:普通回复词,和稀疏的控制 token。控制 token 在数据里出现频率极低,如果一视同仁,它们会被普通文本稀释到几乎学不到。论文的解法是显式加权:普通文本 1 倍,<wait> 0.1 倍,<overlap>/<stop>/<continue> 各 50 倍。50 倍把"何时打断自己、何时接话"这类罕见决策人为放大,它才可能在梯度里被感知。训练本身分两阶段走:

Stage 1 叫结构适应,约 2000 小时 InstructS2S-200K,学习率 1e-4,先让模型学会三通道交错的格式;Stage 2 叫全双工适应,约 1000 小时四类数据源(细粒度 AnchorSpeech-train、语义锚定中断、一般中断、backchannel),学习率 5e-5,专门学打断与恢复。实现上论文没有从零训一个新模型:主体是 Qwen2.5-Omni-7B 的 Thinker 分支,合成器用冻结的 MOSS-TTS-Realtime,只对可训练线性层挂 rank-32 LoRA,16 张 H100 约 30 小时跑完两阶段。Self-Listening

用自反馈做训练并不稀罕。Moshi 有 speech leakage augmentation,FLM-Audio 有 dual training,在文本流领先与落后音频之间轮换,并加入概率 0.3 的语音泄漏增强。但把"已播放语音"作为一条独立输入通道、且监督只压在文本通道,是这篇论文的特定组合。

训练到位之后,问题来到最难的一步:怎么证明它真的知道自己说到了哪?这需要一把专门量这个能力的尺子。

用一把专门量"说到哪了"的尺子:AnchorSpeech 设计与 73.0% 的对照

评测"知道自己说到哪"比想象中难。如果拿开放聊天来测,模型答错了,你分不清是内容质量差、ASR 出错,还是锚定失败。论文把问题收窄成一个受控子问题:只测结构化有序回答,数数、倒计时、字母表、星期、月份、序数、逐字母拼写这类固定有序序列。每个样本是四轮对话,由 GPT-5.5 按结构化规范生成:初始序列请求、带标注打断边界的脚手架回答、进度询问、目标回复。打断边界只允许落在稳定项之间,即前一项说完、后一项未开始,排除半截词这类模糊情形;held-out 测试集再经人工筛选。固定有序序列的好处在于内容质量几乎恒定,评测里剩下的唯一变量,就是模型记没记住自己实际播放到了哪里;而且每项长什么样在提示里就写死了,答对答错一锤定音,模型没有"话说到一半算不算"的辩护空间。这就是 AnchorSpeech 与它的测试集 AnchorSpeech-test。Self-Listening

评测协议用两遍校准保证公平。第一遍不打断,量出该模型完整播放这段回答的时长 T;第二遍用同样的请求,在 T 内一个预定义的相对位置注入打断。脚手架回答对系统隐藏,系统必须自己生成回答;判定目标不来自模板,而取决于系统实际说到了哪里,最后用 GPT-5.6-Terra 对照已播放前缀判断对错。主指标是锚定准确率 ACC,辅助指标是 STOP(停止延迟)与 RESP(响应延迟)。

主结果把差距摊得很开:

系统ACC (%)STOP (s)RESP (s)
3-ch Self-Listening(本文)73.00.4340.564
GPT-Realtime-2.143.80.2961.548
Gemini-3.1-Flash-Live-Preview30.30.6791.772
2-ch 消融(去掉自听通道)7.80.4250.567
Doubao-Realtime2.30.5881.872
Moshi2.21.0785.674
Freeze-Omni0.00.5881.176

数字逐字来自论文 Table 1:73.0 对比最强商用基线 GPT-Realtime-2.1 高出 29.2 个百分点,对比去掉自听通道的匹配消融高出 65.2 个百分点,即从 7.8% 到 73.0%。Self-Listening 最有信息量的不是 73.0 本身,而是第三列:带自听通道的模型与不带它的消融,STOP(0.434 vs 0.425)和 RESP(0.564 vs 0.567)几乎没变。这意味着增益不是靠"变慢、更谨慎地处理打断"换来的,而是真的来自播放锚定的上下文。左侧的塌方区同样说明问题:Moshi 2.2、Freeze-Omni 0.0,它们连数数都不可靠,遑论记住自己数到哪。

这组数字和现有基准测的不是一回事。FullDuplexBench 把全双工行为拆成四个可观察的维度:停顿处理、backchannel、平滑轮替、用户打断。它的 Interruption 维度看的是模型被打断后是否及时且得体地让位,它不问模型记不记得自己刚说到哪,这正是 AnchorSpeech-test 补上的那块。

图注:FullDuplexBench 的四个评测维度示意:停顿处理、backchannel、平滑轮替与用户打断,每块上为 user 通道、下为 model 通道。它测可观察的轮替行为,AnchorSpeech-test 测的则是模型是否锚定到自己实际渲染的语音前沿。FullDuplexBench

论文也主动交代了代价。在 FullDuplexBench v1.5 上,带自听通道模型的打断场景 Respond(0.60)低于去掉自听通道的 2-ch 模型(0.83),backchannel 场景的 Resume(0.72)也低于后者(0.93),打断与 backchannel 的回复延迟分别是 0.75s 与 0.84s。论文把这个现象直称为"播放锚定与常规轮替管理之间的权衡",并说锚定与轮替是两个不同的能力,联合优化仍是开放问题。Self-Listening

如果 Self-Listening 是模型侧的修法,同一个问题的另一侧还站着谁?最后一章把它摆回坐标。

不只有一种修法:PACE 的对偶、同一条源流坐标与论文的留白

几乎同期,另一篇论文用不同的术语描述同一个现象。PACE(2026-08,比 Self-Listening 早约一个月)把它称作 Generative Context Mis-anchoring(GCM),例子很日常:用户让助手列旅游景点,听完第二项就打断,"那里怎么去?"服务端这时已经生成并记账到第四项,模型便把"那里"解析成用户从未听过的第四个景点。ASR 没错,生成没错,错的是输入被锚定到了用户根本不知道的位置。PACE

修法上两者正好对偶。Self-Listening 在模型一侧动手,让模型学会听回自己;PACE 认为模型不需要变,在 middleware 侧修。它用 OutputTurnLedger 为每段输出记账,客户端每个上行 tick 携带 PlaybackAck,告诉服务端当前播到哪个 turn 的哪个采样点;一旦打断,就快照这条播放边界、取消或撤销过期输出、把关好真实播放内容的上下文重新投影进模型 runtime。投影的方式按后端能力分三档:能用 TTS 时间戳的级联 API,直接改写下一轮 prompt 历史;黑盒实时语音 API 无法编辑对话项时,把最近一段已播放音频重新采样注入,前面拼一句合成提示词做分隔;能力最全的 native 模型则可以回滚到最近的兼容状态。当前原型只实现了音频重注入这一路。全程不动模型服务,对黑盒语音 API 也适用。

图注:PACE 的三栏架构:左侧 Client 维护播放与时钟,中间 middleware 用 Turn ledger 与播放边界 $A_i=\langle\mathtt{turn},\mathtt{sample}\rangle$ 记账,右侧 Model runtime 是不动的模型服务;打断时走快照、门控、取消/撤销、上下文投影的修复路径。PACE

两者的评测也互补:GCM-Bench 的 Referent Anchoring Accuracy 测"回答是否锚定到用户播放到的那一项",从 25.0% 提到 96.3%;AnchorSpeech-test 测"模型是否记得自己中断前最后说完的一项"。一个检验回答是否对齐外部播放边界,另一个检验模型在进度追问中能否报告已播放前缀。PACE 如今这个方向有三把尺子各量一段:FullDuplexBench 量轮替行为本身是否自然,GCM-Bench 量回答是否锚到用户播放到的那一项,AnchorSpeech-test 则量模型对自身播放进度的记忆。

把 Self-Listening 放回源流坐标,全篇只此一版时间线:

时间工作路线
2022-03dGSLM(期刊版 TACL 2023)双通道全双工原型,turn-taking 首次从原始语音涌现
2024-09Moshi多流 + Inner Monologue,实时全双工 LLM 范式定型
2025-03FullDuplexBench四类轮替行为的自动评测基准
2025-09FLM-Audio / FDSLM 综述contiguous monologue 路线;engineered vs learned 二分(综述仅覆盖至 2025-09)
2026-05DuplexSLA在 160ms chunk 上再加一条 action 通道,承载规划与工具调用
2026-06BayLing-Duplex块级交错 + 4 个对话状态 token,小数据出 native duplex
2026-08PACEmiddleware 侧 playback-boundary 修法
2026-09Self-Listening(本文)模型侧听回自己

同一时期并不只有"自听"这一条路:DuplexSLA 把 planning 与 tool call 单独剥成一条和音频共用 160ms 时钟的 action 通道,DuplexSLA BayLing-Duplex 把对话状态压进词表,PACE 在模型外面修边界。它们共享同一个判断:全双工模型必须知道并锚定到自己实际播出的内容,这个能力值得专门设计。

论文的留白也值得原样保留。它只测结构化有序序列,开放语义锚定没有直接测量,语义锚定数据只进了训练集;turn-management 权衡被明确承认;AnchorSpeech 的 train/test 拆分规模没有公开,第三方暂时无法精确复现对照。同期综述(视野止于 2025-09)点名的评测缺口也还敞着:proactive 行为指标缺失,超低延迟下的安全与过滤机制尚未纳入评测。FDSLM Survey 这些是单篇精读的留白,不是结论。Self-Listening

回到开头那个数数场景。让模型回答"说到哪了",人靠骨传导天然做到,过去四年也没人追责;现在这个问题有了名字(anchor interruption)、有了尺子(AnchorSpeech-test)、有了至少两条对偶的修法(模型侧自听与 middleware 修边界)。一个自然的延伸问句也随之而来:既然模型能在 40ms 步上听回自己说过的语音,这套听觉能否进一步覆盖 action 通道,让"知道自己说了什么"与"知道自己调了什么工具"共用同一条时间轴。"知道我说过什么"从此从一个隐性的失职,变成一个可命名、可测量、可对照的公开问题。这本身,就是一篇论文让领域前进的方式。

想深入可以读原文:What Did I Just Say? Self-Listening for Full-Duplex Speech Models — arXiv:2609.05592

参考文献

Self-Listening:让语音助手听见自己的声音,打断后知道说到哪