OROpenRealtime
角色资源文档
对话记录

还没有对话记录

OROpenRealtime
角色资源文档
对话记录

还没有对话记录

模块化话轮协调器使用说明

开发与扩展 · 正文语言: 中文

文档目录
全部文档开发与扩展产品功能架构与可替换模块开发与扩展系统架构与消息流程开发与扩展文档与发布边界认识产品与开始使用认识 OpenRealtime知识、工具与记忆用产品资料配置语音助手认识产品与开始使用首页使用指南定制语音 Agent角色配置指南知识、工具与记忆知识库使用指南知识、工具与记忆记忆与会话历史知识、工具与记忆工具权限设置知识、工具与记忆知识与记忆管理指南定制语音 Agent成本与服务选型可选:添加数字人数字人驱动方案可选:添加数字人动作编排使用指南部署与维护本地启动与排错定制语音 Agent连接真实语音与模型服务部署与维护自行部署指南部署与维护前后端分离部署部署与维护可靠性与运维开发与扩展模块化话轮协调器开发与扩展判停与打断插件合约开发与扩展语音 Pipeline 与插件接口开发与扩展知识库选型与接入方案接入你的 Agent接入自己的 Chat Agent

2026-10-01:Web Demo 的 Cascaded Pipeline 默认使用 CoordinatedTurnManagerCapabilityAdapter。Jev 已支持分别替换判停和打断;暂停/恢复、多头语义输出仍属于后续工作。

三个替换接口

接口职责当前实现
TurnManager provider:open → send/events → close会话协调、候选输入、响应归属、模型调度及等待期限server/realtime/capabilities/coordinated_turn_manager.py
classify_request(EotRequest)语义完整性;兼容原有 text/context classifierserver/turn_policy/eot_classifier.py
classify_request(InterruptionRequest)语义打断;兼容原有 classifierserver/turn_policy/semantic_interruption.py

模型提供证据,协调器负责动作。替换整个算法时,在 CascadedPipelineBindings.turn_manager 或部署注册的 TURN_MANAGER 插件槽绑定新 provider。

只调整等待和准入策略时,使用 TurnCoordinationPolicy:

from server.realtime.capabilities.coordinated_turn_manager import (
    CoordinatedTurnManagerCapabilityAdapter,
)
from server.turn_policy.coordination import DefaultTurnCoordinationPolicy

provider = CoordinatedTurnManagerCapabilityAdapter(
    eot_classifier=my_eot_model,
    semantic_interruption_classifier=my_interruption_model,
    coordination_policy_factory=lambda: DefaultTurnCoordinationPolicy(
        incomplete_wait_ms=3000,
        uncertain_wait_ms=300,
    ),
    recovery_timeout_ms=10000,
)

# 将 provider 绑定到 Pipeline 的 turn_manager 槽位。
# 每次 open 创建独立的协调策略、输入记录与事件队列。

自定义策略实现同步、快速的 endpoint_wait_ms(result) 与 interruption(verdict)。后者返回 InterruptionDisposition(stop_response, admit_input);不要在策略内调用播放器或修改 Journal。完整语义合约参见《判停与打断插件合约》。

状态与事件

session.snapshot() 提供两个上层话轮:user/assistant,以及候选输入 ID、文本修订号、响应 ID、是否等待 ASR final。

内部输入和助手响应分别记录,允许助手持有话轮时收集用户插话。兼容现有 UI、Engine 的 idle/listen/speak/dual 事件只是投影;没有额外构造一个负责所有逻辑的五状态 FSM。

会话 actor 串行修改记录。语义模型在后台运行,带输入 ID、revision 和请求 token 的结果回流;VAD/ASR routing 不等待模型推理。新内容使旧证据过期;同文本的 VAD restart 撤销旧 stop,但保持输入 ID。

普通用户输入等待语义完整性与停止条件;助手响应期间的插话候选不调用语义判停,按打断结果、VAD/ASR 停止条件和让出确认请求 ASR final。旧回复停止后,该候选仍保持插话归属直到最终提交。最终提交使用 ASR final 的权威文本,不用较早的 partial 覆盖它。最终提交等待期间保存后继 VAD/ASR 观察,旧轮次的 final 或让出确认不能完成新轮次。

默认策略

  • complete:停止条件满足后推进;incomplete/uncertain:有界等待,可替换等待策略。
  • correction/interrupt:停止旧响应,保留输入。
  • stop:停止旧响应,不创建新请求;如果随后文本变成“别说了,查上海”,最终修订会重新判断。
  • 精确附和规则:稳定边界确认后可抑制;当前助手文本含问号时不直接用附和白名单吞短回答。
  • 模型 backchannel:稳定边界且置信度达到 backchannel_confidence(默认 0.95)时保持助手输出;阈值可通过策略替换。
  • 模型 ignore/uncertain、低置信附和及模型故障:保留最终输入;完成后准入并让出话轮。
  • 输入由唯一内部 ID 跟踪;取消绑定目标 response_id。旧响应的完成事件不会关闭新响应。

以上优先避免丢用户请求,可能带来额外误打断。它不是经过真实语音评测后的最优阈值;后续可用新策略与场景集调整。

等待与恢复

VOICEAGENT_TURN_RECOVERY_TIMEOUT_MS 默认 10000:从最新 ASR 内容修订起计时,纯 VAD 振荡不重置。普通静音/完整性等待、取消确认和 ASR final 等待分别管理。

  • 有文本且当前已停说:到恢复期限可以有界推进,不持续依赖被 VAD 重置的普通计时器。
  • 声学持续显示说话但 ASR 不进展:明确发布 capability failure,交给现有 Runtime 恢复;不伪造静音或无条件截断用户。
  • 缺少 ASR final 或取消确认:有界失败,不永久挂起。
  • 关闭最多等待后台任务 100ms;不响应取消的插件记录警告,插件仍需自行释放资源。

这些失败会进入现有诊断/恢复机制,不能承诺未提交的输入在 provider 重启后自动重放;持久化未决音频与输入恢复是后续范围。默认协调器暂不执行旧 response_prefetcher 的推测准备,避免未经协调的预取生命周期影响准入;Brain 的正常响应路径保持可用。Legacy Adapter 保留供兼容使用。

验证与后续

Jev 分类 API 已于 2026-10-01 复测,结果及重跑命令参见 Jev 复测报告(内部资料);当时尚未切换默认运行模型。2026-10-13 默认语义服务已按用户要求切换为百炼,接口与实测限制见下文。

回归覆盖普通提交、恢复说话、连续 VAD 振荡、慢模型迟到、负面模型结果、纯附和、问答短回复、stop 后纠正、三次连续打断、缺 final、仅 ASR hint、以及现有 Engine/Journal/音频与播放后打断契约。

已用真实 Jev API 跑通模拟 ASR/VAD 的协调器 Demo,没有开展模型训练或真实麦克风/浏览器音频 A/B。暂停/恢复、结束会话控制、多头标签、系统附和保持 TODO;替换模型无需改当前 Pipeline 或输入归属合约。

默认 Qwen Turbo 判停与打断

判停和打断分别通过 VOICEAGENT_EOT_PROVIDER、VOICEAGENT_INTERRUPTION_PROVIDER 选择 qwen-turbo(默认)、bailian、jev 或 llm。Qwen 使用服务端 DASHSCOPE_API_KEY 和独立的 Chat Completions 端点,与回答 LLM 独立。原生百炼继续使用 BAILIAN_API_HOST;当前业务空间对 Qwen 返回 model_not_found,Qwen 默认地址沿用调研中验证的 DashScope 通用端点。

VOICEAGENT_EOT_PROVIDER=qwen-turbo
VOICEAGENT_INTERRUPTION_PROVIDER=qwen-turbo
VOICEAGENT_QWEN_BASE_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
VOICEAGENT_SEMANTIC_DECISION_MODEL=
VOICEAGENT_SEMANTIC_DECISION_TIMEOUT_MS=2000
VOICEAGENT_SEMANTIC_DECISION_MAX_CONCURRENCY=2
VOICEAGENT_SEMANTIC_EOT_MIN_CONFIDENCE=0.8

SEMANTIC_DECISION_MODEL 为空时按 provider 选择默认模型;其他通用参数未设置时兼容已有 VOICEAGENT_JEV_* 数值。原 VAD/ASR 判停条件、confidence 门控、rule-first 打断和 500ms 确认语不在这次切换中调整。两个判定共享应用级模型及容量;工具路由使用独立池。客户端/模型由应用关闭,会话不关闭其他会话的共享服务。

Qwen 的异步 HTTP 依赖包含在基础安装 uv sync 中;选择原生百炼或 Jev 时安装现有 System One SDK extra:uv sync --extra jev。该 extra 名称保留兼容。缺少凭据或非法 provider 会明确报告配置问题,不自动改用其他模型。更改服务端 .env 后需重启服务加载配置。

Qwen 的 confidence 是生成式自评,未经过校准;保留现有数值门槛不代表不同模型置信度等价。研究里的三类打断成绩不能当作本运行时六类打断的准确率,合成接口探测也不构成语音质量验收。详见 接入与真实调用记录(内部资料)。

显式选择 Jev 判停与打断

服务端 .env 中配置以下字段;密钥不得使用 NEXT_PUBLIC_ 前缀。两个 provider 可独立选择,也可只将其中一个设为 Jev。

JEV_API_KEY=你的服务端密钥
VOICEAGENT_EOT_PROVIDER=jev
VOICEAGENT_INTERRUPTION_PROVIDER=jev
VOICEAGENT_JEV_MODEL=jev-1.13.0
VOICEAGENT_JEV_TIMEOUT_MS=2000
VOICEAGENT_JEV_MAX_CONCURRENCY=2
VOICEAGENT_JEV_EOT_MIN_CONFIDENCE=0.8
VOICEAGENT_BACKCHANNEL_CONFIDENCE=0.95

安装并运行独立 Demo:

uv sync --extra jev
uv run --extra jev --env-file .env python -m demos.jev_turn_demo

Demo 调用真实 Jev,模拟 VAD、ASR final 和停播确认,分别输出普通请求、纠正和附和的实际准入动作。 检查 eot_model_result_observed 与 interruption_model_result_observed;只有 committed 而没有模型结果时,不能当作 Jev 成功。 它没有连接真实麦克风或播放器。启动或重启 pnpm dev:server 后,Web Demo 也会读取这些配置;开发启动脚本已包含 Jev 依赖。

Jev 适配器使用 classify_request,输入包含历史、当前文本与观察状态;打断另包含助手文本。 未知的声源明确标为 unknown,不编造声学识别结果。会话身份不发送给模型。 判停低于 VOICEAGENT_JEV_EOT_MIN_CONFIDENCE 时转为 uncertain,等待仍由协调器控制。 打断置信度先经过 VOICEAGENT_SEMANTIC_INTERRUPTION_THRESHOLD(默认 0.8);稳定附和再经过 VOICEAGENT_BACKCHANNEL_CONFIDENCE。 降低附和阈值可能减少误打断,也可能吞掉误判成附和的新请求,需用真实场景验证。

Jev 不重试实时请求,超时/故障交给现有保留输入与恢复策略。Jev 模式的打断超时默认继承 Jev 超时;若显式配置 VOICEAGENT_SEMANTIC_INTERRUPTION_TIMEOUT_MS,则以该值为准。 当前实现每次请求创建并关闭异步客户端,因此连接无法复用。本机实测协调器 Demo 约 1.1–1.6 秒,不能沿用旧评测脚本复用连接时约 300ms 的耗时结论。

实现:server/turn_policy/plugins/jev_classifier.py。实测与限制见 Jev 运行时接入报告(内部资料)。

2026-10-02:首音前的续说候选等待回复 preparing 后取消并组合上一输入,以 continuation_of_turn_id 保留 Journal 修订关系;播放开始后则创建独立插话轮次。打断模型的 assistant_text 固定为开口时客户端进度已确认的完整句段,不使用 BrainTextDelta。缺少 TTS 对齐的未播放完部分保持未知,不以生成全文补齐。详见 VOICE-PLAYBACK-TURN-REQUIREMENTS.md 的实现记录。