From a1a1212858934805669211397e5d8cc96dc45208 Mon Sep 17 00:00:00 2001 From: Rogee Date: Tue, 18 Aug 2026 11:23:47 +0800 Subject: [PATCH 1/2] =?UTF-8?q?H-264:=20=E6=B2=89=E6=B7=80=E5=85=AC?= =?UTF-8?q?=E7=BD=91=E6=A8=A1=E5=9E=8B=E5=A4=96=E5=91=BC=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=E6=9E=B6=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: multica-agent --- README.md | 1 + docs/architecture/public-model-outbound.md | 302 +++++++++++++++++++++ 2 files changed, 303 insertions(+) create mode 100644 docs/architecture/public-model-outbound.md diff --git a/README.md b/README.md index bc256d2..0c19b97 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,4 @@ 智语声呐 - [AI 外呼 SaaS 调研与架构指南](docs/research/ai-outbound-saas.md) +- [公网模型外呼目标架构](docs/architecture/public-model-outbound.md) diff --git a/docs/architecture/public-model-outbound.md b/docs/architecture/public-model-outbound.md new file mode 100644 index 0000000..e4b5936 --- /dev/null +++ b/docs/architecture/public-model-outbound.md @@ -0,0 +1,302 @@ +# 公网模型外呼目标架构 + +> 状态:100 通受控 PoC 的实施基线。模型、价格和外部资料访问日期为 2026-08-17。 +> 本文沉淀 H-265 已验收设计;H-261 调研基线见[《AI 外呼 SaaS 调研与架构指南》](../research/ai-outbound-saas.md)。如候选调研与本文冲突,PoC 以本文的最终选型为准。 + +## 1. 最终选型与适用边界 + +主链路只使用阿里云百炼华北 2(北京)的一套模型,减少地域、鉴权和网络路径。唯一备选仍在同一地域,只覆盖单模型限流、故障或版本回归;它不覆盖阿里云账号、网络或地域级故障。 + +| 环节 | 主模型 | 地域、端点与协议 | 鉴权边界 | 官方原价 | +| --- | --- | --- | --- | ---: | +| 流式 ASR | `fun-asr-realtime-2026-02-28` | 北京;`wss://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api-ws/v1/inference`;`run-task` 后发送单声道二进制音频,以 `finish-task` / `task-finished` 收口 [^fun-asr] [^fun-asr-ws] | 服务端在握手头设置 `Authorization: Bearer `;浏览器、线路和租户均不得获得密钥 | `0.00033 元/输入音频秒`,输出不计费 | +| 流式 LLM | `qwen3.7-flash-2026-07-15`,非思考模式 | 北京;`POST https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1/chat/completions`;OpenAI 兼容 Chat Completions,`stream=true` 返回 SSE [^qwen37] [^openai-compatible] | 仅会话编排器持有服务端 Bearer API Key;工具调用必须再经过本地白名单和幂等门禁 | 单次输入不超过 32K Token:输入 `0.2 元/百万 Token`、输出 `0.8 元/百万 Token` | +| 流式 TTS | `cosyvoice-v3.5-plus`;定制音色预先由 `voice-enrollment` 注册 | 北京;同一 WebSocket inference 端点;`run-task`、多次 `continue-task`、`finish-task`,返回二进制音频流 [^cosyvoice35] [^tts-ws] | 仅会话编排器持有密钥;只接受已审批、未过期且未撤回的 voice ID | `1.5 元/万计费字符`;汉字计 2 字符,其余字符计 1;音色注册暂无公开价 [^tts-price] [^voice-enrollment] | + +TTS 官方当前精确模型 ID 就是 `cosyvoice-v3.5-plus`,没有日期快照 ID。每通固化请求模型 ID、voice ID 和供应商实际返回的模型标识,避免静默升级后无法对账或回溯。 + +唯一故障备选为: + +- ASR:`paraformer-realtime-8k-v2`; +- LLM:`qwen-flash-2025-07-28`; +- TTS:`cosyvoice-v3-flash`,使用预先生成并审批的独立备份 voice ID。 + +备选必须预热和通过同一契约测试,但不做常态路由 [^paraformer] [^qwen-flash] [^cosyvoice3-flash]。同一环节最多切换一次;主备均失败时播放本地缓存、已批准且已授权的结束语并挂断。账号、网络或北京地域故障时停止新呼叫,不再增加第二家供应商。 + +### 1.1 事实、决策、假设和待核实项 + +| 类别 | 内容 | +| --- | --- | +| 已核实事实 | 上述模型 ID、北京地域端点、流式协议、Bearer 鉴权、模型能力和 2026-08-17 官方原价 | +| 已验收决策 | PostgreSQL 是事实源;Redis 仅存可丢短态;PG outbox 代替消息队列;每环节只切一次备选;PoC 只需控制/worker 与媒体/会话两个逻辑进程 | +| 规划假设 | 每接通分钟含 60 秒 ASR、3,000 输入 Token、600 输出 Token、125 汉字;固定成本 `9,900 元/月`、月接通 `198,000 分钟`;不使用缓存或 Batch | +| 待合同/控制台/PoC | 现有线路双向媒体、上下行分离/AEC、及时停播、回调签名/序号、线路计费起点与取整;音色注册、媒体和存储成本;真实延迟、账单差异及生产留存期限 | + +任一线路前提不成立即为 PoC 阻断项:没有实时双向媒体;不能及时停止尚未播放的下行音频;上下行混流且无可靠 AEC;无法验签、防重放或查询真实终态;不能提供逐通计费量、单位、取整和 provider call ID。 + +## 2. 组件边界与端到端数据流 + +```mermaid +flowchart TB + subgraph C[控制面] + UI[运营控制台] --> API[租户 API] + API --> AUTH[Logto] + API --> PG[(PostgreSQL)] + API --> OBJ[(现有对象存储)] + WORKER[调度 / 恢复 / 对账 worker] <--> PG + WORKER --> ADAPTER[现有线路适配器] + end + subgraph D[实时数据面] + LINE[现有线路双向媒体] <--> MEDIA[媒体网关\nG.711 / 抖动缓冲 / 连续重采样] + MEDIA --> VAD[VAD / 端点检测] + VAD --> ASR[流式 ASR] + ASR --> SESSION[会话编排器] + SESSION --> LLM[流式 LLM] + LLM --> TTS[流式 TTS / 已授权音色] + TTS --> MEDIA + SESSION -. 路由 / 租约 / generation .-> REDIS[(Redis)] + end + ADAPTER <--> LINE + PG <--> SESSION + SESSION --> OBJ +``` + +这些是逻辑职责,不要求拆成微服务。PoC 复用现有 PostgreSQL、Redis、对象存储和部署;无吞吐证据前不增加 Kafka/RabbitMQ、工作流引擎、服务网格、独立计费服务或事件溯源框架。 + +| 组件 | 最小职责 | 不负责 | +| --- | --- | --- | +| 租户 API | 验证 Logto token;配置和发布不可变话术/音色/线路版本;写审计 | 实时音频、供应商状态解释 | +| 调度/恢复/对账 worker | 批次展开、时段/黑名单/频控、租户与线路并发、PG 槽位、outbox、模糊结果查询恢复、逐通对账 | 直接处理媒体帧 | +| 线路适配器 | 幂等发起/挂断/停播、能力声明、回调验签、事件映射、状态查询、用量原样返回 | 对话策略、租户授权 | +| 媒体网关 | G.711、20 ms 帧、抖动缓冲、连续重采样、上下行隔离/AEC、VAD、立即停播 | 业务动作和长期事实 | +| 会话编排器 | 固化本通版本;ASR→LLM→TTS 流;generation、打断、取消、超时、一次备选和工具门禁 | 身份源、批量调度、最终账单 | +| PostgreSQL | 业务和通话唯一事实源、事件 inbox/outbox、审计与用量 | 媒体帧和不稳定 partial | +| Redis | 带 TTL 的 session 路由、短租约、心跳、快速限流与 generation | 终态、额度事实、唯一账单 | +| 对象存储 | 经授权的参考音频、录音和导出对象;租户前缀隔离 | 密钥和检索索引 | + +正常数据流:控制面发布不可变版本;worker 在一个 PG 事务内抢占并发槽、创建 call 和 outbox;事务提交后适配器幂等发起呼叫;接通媒体直接进入实时数据面;每轮固化稳定转写、回合边界、工具副作用、generation、延迟和供应商用量;挂断后 worker 查询线路用量并追加对账结果。 + +### 2.1 状态所有权与数据落点 + +| PostgreSQL:必须持久化 | Redis:可丢失并重建 | 仅进程内有界缓冲 | +| --- | --- | --- | +| organization、套餐/并发上限、批次/task item、联系人来源与黑名单、不可变话术/音色授权版本、call/provider call 映射、幂等键与请求哈希、允许的状态迁移、原始回调摘要与 event ID、稳定转写/回合边界/工具副作用、generation、模型与线路用量、账单 adjustment、审计、删除任务 | session→媒体节点路由、租户/线路快速拒绝缓存、限流计数、短租约/心跳、播放 generation/cancel token;丢失后从 PG 重建,不能改变终态或额度 | RTP/PCM 帧、VAD 窗口、抖动缓冲、ASR partial、LLM token、未播放 TTS chunk;不持久化模型思维链 | + +Redis 不可用时停止新呼叫,已有通话可依靠进程内状态安全结束;PG 不可写时停止新呼叫和新工具副作用,已有通话仅允许安全结束。正在通话的媒体节点失联且线路不支持重连时,不伪装恢复对话:适配器挂断并记录 `media_lost`。 + +## 3. 主要接口与错误语义 + +### 3.1 线路适配器 + +```text +ValidateConfig(config) -> capabilities +Originate(idempotency_key, caller, callee, media, metadata) -> provider_call_id +Hangup(provider_call_id, reason) # 幂等 +StopPlayback(provider_call_id, generation_id) # 必须有及时生效的确认语义 +GetCall(provider_call_id | idempotency_key) -> provider_state +GetUsage(provider_call_id) -> quantity/unit/rounding/window +VerifyWebhook(headers, raw_body, received_at) -> normalized_event +``` + +`capabilities` 必须声明双向媒体方式、上下行分离或 AEC、codec、采样率、20 ms ptime、最大并发、DTMF、停播确认、回调重试/排序、计费起点和取整。`metadata` 只放内部不可逆关联标识,不发送联系人明文、租户密钥或无关个人数据。 + +统一事件为 `requested/ringing/answered/media_started/ended/failed`,至少包含 provider event ID、provider call ID、发生时间或序号、标准原因与原始原因摘要。标准错误至少区分: + +| 错误 | 语义与处理 | +| --- | --- | +| `invalid_request` / `invalid_number` | 确定性失败,不重试;释放槽位并审计 | +| `rate_limited` / `provider_unavailable` | 尚未产生外部副作用时按上限退避;受时段和任务期限约束 | +| `originate_unknown` | 发起请求超时且结果未知;必须先 `GetCall(idempotency_key)`,禁止直接重拨 | +| `auth_failed` / `webhook_untrusted` | 停止新任务或拒绝事件;告警;绝不通过重试绕过鉴权 | +| `media_lost` / `stop_playback_unsupported` | 当前通话安全挂断;后者直接判定 PoC No-Go | +| `usage_incomplete` | 不覆盖旧账单;追加异常并进入对账队列 | + +Webhook 进入状态机前必须限制 body 大小、校验 Content-Type/schema、用原始 body 做常量时间签名校验,并检查时间窗/nonce 防重放。唯一约束 `(adapter, provider_event_id)` 去重;供应商没有 event ID 时才用规范化原始载荷哈希作为降级指纹,并把该缺陷列入适配器风险。 + +### 3.2 模型流与取消 + +模型客户端对编排器暴露统一的流式语义,而不是把供应商事件泄漏给业务: + +```text +StartASR(call_id, generation_id, audio_format) -> partial/final/usage +StreamLLM(call_id, generation_id, prompt_version, messages, allowed_tools) -> token/tool_call/usage +StartTTS(call_id, generation_id, voice_version, text) -> audio_chunk/usage +Cancel(call_id, generation_id, reason) -> acknowledged +``` + +每个分片都关联 call ID 和 generation ID。generation 变化后,旧 ASR/LLM/TTS 分片一律丢弃。工具调用只有在结构校验、租户授权和本地幂等门禁全部通过后才执行;一旦工具产生外部副作用或音频已经播放,不透明重试该回合。 + +媒体路径固定为: + +```text +上行 G.711 A-law/μ-law 8 kHz mono → 解码 → 有状态重采样 16 kHz → VAD / ASR +TTS PCM(供应商输出采样率)→ 低通 → 有状态重采样 8 kHz → G.711 → 下行 20 ms 帧 +``` + +滤波器和重采样器状态必须跨帧连续。优先使用独立上行;若只能得到混流,必须由线路/AEC PoC 证明机器人播音不会触发自身 VAD。录音按上下行独立轨保存或明确标注混音,禁止把机器人播音再次计入 ASR。 + +## 4. 状态机、时序与恢复 + +```mermaid +stateDiagram-v2 + [*] --> scheduled + scheduled --> dispatching + scheduled --> cancelled + dispatching --> requested + dispatching --> cancelled + dispatching --> failed + requested --> ringing + requested --> answered + requested --> cancelled + requested --> failed + ringing --> answered + ringing --> failed + answered --> media_active + answered --> ending + media_active --> ending + media_active --> failed + ending --> ended + failed --> [*] + cancelled --> [*] + ended --> [*] +``` + +允许供应商跳过中间事件向前推进,例如 `requested → answered`;`ended/failed/cancelled` 是终态,迟到的 `ringing/answered` 不得令其回退。回调顺序不等于事实顺序:优先使用供应商序号/发生时间和允许迁移表;仍冲突时保留原始事件并调用 `GetCall`,以追加 correction/audit 的方式收敛。账单修正也只追加 adjustment。 + +实时会话子状态 `listening → thinking → speaking` 主要驻留内存。只将回合边界、稳定转写、工具副作用、generation、延迟和用量落 PG。 + +### 4.1 正常通话与用户打断 + +```mermaid +sequenceDiagram + participant W as worker + participant P as PostgreSQL + participant A as 线路适配器 + participant M as 媒体网关 + participant O as 会话编排器 + participant X as ASR/LLM/TTS + + W->>P: 抢占槽位 + call + outbox(同一事务) + W->>A: Originate(idempotency_key) + A-->>P: requested/ringing/answered(验签、去重) + A->>M: G.711 上行 + M->>X: 连续重采样音频 + X-->>O: ASR final + O->>X: LLM SSE → 完整短句 → TTS + X-->>M: generation N 音频块 + M-->>A: G.711 下行 + alt 用户在播报时开口 + M->>M: 清空本地播放队列 + M->>A: StopPlayback(call, N) + M->>O: generation N → N+1 + O->>X: Cancel(N) + X-->>O: 迟到 token/音频 N + O->>O: 丢弃,不阻断新上行 ASR + end + A-->>P: ended(唯一终态) + W->>A: GetUsage(provider_call_id) + W->>P: 模型用量 + 线路用量 + adjustment +``` + +### 4.2 模型超时与回调乱序 + +- 主模型在阶段超时且尚未调用工具或播放音频:同环节切换唯一备选一次。 +- 已调用工具或已播放内容后失败:不透明重试;播放已批准的澄清/结束语。 +- 备选也失败或模型熔断:停止新任务;当前通话安全结束并记 `model_degraded`。 +- `ended(seq=9)` 先到:验签并落 inbox,call 进入终态;随后 `answered(seq=5)` 只保留事件,不回退状态。 +- 重复 `ended`:唯一约束命中后返回 2xx,不重复释放槽位或结算。 +- 无序号或终态冲突:`GetCall` 查询真实状态并追加 correction;原始事件不删除。 + +调度任务可在节点重启后从 PG 恢复;对话媒体不能无损恢复时立即挂断。恢复器扫描过期租约和非终态 call,先查询线路真实状态,再决定释放槽位、恢复监听或收敛终态,禁止依据本地超时直接假定呼叫不存在。 + +## 5. 超时、重试、SLO 与降级 + +以下是 PoC 验收目标,不是供应商承诺: + +| 指标 | 目标 / 测量边界 | +| --- | --- | +| 同租户幂等键重复发起 | 第二通为 0;同 key 同请求返回原 call,不同请求哈希返回冲突 | +| 用户开口到最后一帧机器人音频 | P95 ≤ 200 ms;从首个有效上行语音帧计到线路最后播放帧 | +| 用户回合结束到首段可播放音频 | P95 ≤ 1.0 s;以线路收到首块而非 TTS 服务返回计时 | +| 回调验签入库 | P99 ≤ 2 s;重复事件返回 2xx,不能触发重试风暴 | +| 终态收敛 | 99.9% 在挂断后 5 分钟内;其余在 30 分钟内查询收敛或告警 | +| 租户/线路并发上限 | 超额发起为 0;PG 槽位是硬门禁,Redis 仅作快路径 | +| 逐通账单差异 | 汇总差异 ≤ 5%,每个差异可追到单位、取整、重试或缺失用量 | + +退避采用有上限的指数退避加抖动,并受通话剩余时限、呼叫时段和批次期限约束。ASR 连接仅在协议确认可安全续传音频时重连,否则结束该回合。固定降级顺序为:主模型 → 唯一备选 → 本地缓存的已批准结束语 → 挂断。控制面故障时不启动新批次,已建立的数据面会话只继续到安全终态。 + +## 6. 成本公式与计费边界 + +每接通分钟的规划用量为:60 秒上行 ASR;4 个回合合计 3,000 输入 Token、600 输出 Token;机器人播报 30 秒,按 250 汉字/播报分钟即 125 汉字,暂不计标点;无缓存、无 Batch、单次 LLM 输入不超过 32K Token。 + +| 项目 | 显式复算(元/接通分钟) | +| --- | ---: | +| 现有线路 | `60 秒 × 0.1 元 / 60 秒 = 0.10000` | +| ASR | `60 × 0.00033 = 0.01980` | +| LLM 输入 | `3,000 / 1,000,000 × 0.2 = 0.00060` | +| LLM 输出 | `600 / 1,000,000 × 0.8 = 0.00048` | +| TTS | `125 汉字 × 2 计费字符 × 1.5 / 10,000 = 0.03750` | +| **线路 + 已知模型变量小计** | **`0.15838`** | +| 固定摊销规划值 | `F/M = 9,900 / 198,000 = 0.05000` | +| **当前可复算规划值** | **`0.20838 元/接通分钟`** | + +规划容量 `M = 30 并发 × 60 × 10 小时/日 × 22 日 × 50% 有效利用率 = 198,000 接通分钟/月`。`F=9,900 元/月`覆盖应用、PostgreSQL、Redis、对象存储和监控基线,是 H-260 规划假设,不是供应商报价。完整公式为: + +`C = 0.20838 + V_media/storage + E_voice / 该音色累计接通分钟` + +`V_media/storage` 和音色注册费 `E_voice` 均待合同、控制台或 PoC,不能藏入 `0.20838`。全部已选项目均以人民币计价;保留 `1 USD = 7.20 CNY` 仅作未来外币账单规划汇率,对当前结果影响为 0。 + +计费边界:ASR 预算先按每个识别会话向上取整到秒,待账单确认;LLM 按每请求实际输入/输出 Token 且不计缓存优惠;TTS 按实际计费字符,标点、数字和空格各计 1;线路题设按精确接通分钟计算,若合同按每通向上取整,应替换为 `0.1 × ceil(通话秒/60) / (通话秒/60)`。 + +每通必须保存供应商返回的模型、音频秒、输入/输出 Token、计费字符、线路计费量/单位/取整和内部公式版本。PoC 用真实 usage、账单、`F`、`V_media/storage` 和 `E_voice` 替换规划值。 + +## 7. 安全、租户、声音授权与留存 + +- Logto token 必验签名、`iss/aud/exp`、organization 和 scope;organization 来自 token,不接受请求体覆盖。业务主键/唯一约束、对象前缀、Redis key、幂等键和用量聚合均包含 organization。 +- 北京 API Key 只存在服务端密钥管理系统;开发、测试、生产分工作空间和密钥,组件只取得调用所需最小权限。密钥、Authorization、完整 webhook body、联系人号码和参考音频不得进入普通日志。 +- 线路回调签名与 Logto 是独立信任边界。回调中的租户字段不能直接选租户,只能通过已存在的 provider call 映射恢复 organization。 +- 音色保存实名/主体、用途、渠道、期限、授权文本版本、样本哈希、审批人和撤回状态。只有 `approved` 且未过期/撤回的 voice ID 可进入不可变发布版本;撤回立即阻止新通话并清理主备派生 voice 和缓存。 +- 每通开场披露企业身份、AI 语音身份和录音事实,并提供拒绝/退订路径;保存披露事件和音频时间点。人声按敏感个人信息边界处理,电话场景具体法律适用仍需律师确认 [^pipl] [^deep-synthesis] [^ai-label]。 +- 不保存模型思维链;工具参数字段级脱敏。对象存储服务端加密、按租户前缀隔离,使用短时签名 URL;账单和审计只存必要摘要。 + +PoC 只呼叫已同意的内部号码;参考音频、录音和转写在验收后 7 日内删除,不含内容的用量、延迟、安全和审计摘要保留 180 日。生产录音/转写、授权证据期限与删除 SLA 必须由合同、线路规则和法律意见确认后配置;在此之前不默认长期留存。 + +## 8. 最小 PoC 与实现拆分 + +按以下顺序拆任务即可,不需要先搭建额外基础设施: + +1. **线路契约与 mock**:实现 capabilities、幂等发起/挂断/停播、验签、防重放、乱序/重复事件、查询恢复和用量取整契约测试。 +2. **调度与持久化**:实现 PG call/task/slot/inbox/outbox、单调状态机、租户/线路硬并发门禁、恢复和 adjustment;Redis 只做可丢快路径。 +3. **媒体与打断**:用固定 G.711 8 kHz 样本验证连续重采样、上下行隔离/AEC、20 ms 帧、generation 丢弃和 StopPlayback。 +4. **模型编排**:接入主模型和唯一备选,验证流式、取消、工具幂等、有界超时、一次切换与已批准结束语。 +5. **受控通话与对账**:只用测试凭据和已同意的内部号码完成 100 通,采集首帧、VAD、ASR final、LLM 首 token、TTS 首块、线路首/末播放帧、generation、模型/线路 usage 和账单。 + +100 通需覆盖正常对话、噪声/口音、连续打断、沉默、忙线、主 ASR/LLM/TTS 分别注入超时、WebSocket 断开、重复/乱序回调和节点重启。 + +Go 条件: + +1. 双向媒体、上下行分离或 AEC、StopPlayback 全部通过,否则直接 No-Go。 +2. 重复发起、终态分叉、并发超额和回调验签绕过均为 0。 +3. 打断 P95 ≤ 200 ms,用户回合结束到线路首音频 P95 ≤ 1.0 s。 +4. 三个主模型分别故障时,唯一备选能受控降级;备选失败时安全结束且不重放工具副作用。 +5. 内部逐通用量与线路/模型账单总差异 ≤ 5%,差异可解释,并用实测值替换 `0.20838` 的规划输入。 +6. 未授权、过期或撤回音色调用为 0;跨租户读写、缓存命中、对象 URL 和回调映射越权为 0。 + +## 9. 官方来源 + +以下资料均访问于 2026-08-17;采购和实施前应重新核验价格、地域和模型状态。 + +[^fun-asr]: 阿里云百炼,[Fun-ASR 实时语音识别模型与价格](https://help.aliyun.com/zh/model-studio/fun-asr-realtime)。 +[^fun-asr-ws]: 阿里云百炼,[Fun-ASR WebSocket API](https://help.aliyun.com/zh/model-studio/fun-asr-realtime-websocket-api)。 +[^qwen37]: 阿里云百炼,[Qwen3.7 Flash 模型、快照、能力与价格](https://help.aliyun.com/zh/model-studio/qwen3-7-flash)。 +[^openai-compatible]: 阿里云百炼,[OpenAI 兼容端点与流式调用](https://help.aliyun.com/zh/model-studio/compatibility-of-openai-with-dashscope)。 +[^cosyvoice35]: 阿里云百炼,[CosyVoice v3.5 Plus 模型与价格](https://help.aliyun.com/zh/model-studio/cosyvoice-v3-5-plus)。 +[^tts-price]: 阿里云百炼,[语音合成模型与计费字符规则](https://help.aliyun.com/zh/model-studio/tts-model/)。 +[^tts-ws]: 阿里云百炼,[CosyVoice WebSocket API](https://help.aliyun.com/zh/model-studio/cosyvoice-websocket-api)。 +[^voice-enrollment]: 阿里云百炼,[声音复刻 API 与公开定价说明](https://help.aliyun.com/zh/model-studio/voice-enrollment)。 +[^paraformer]: 阿里云百炼,[Paraformer 实时 8k v2](https://help.aliyun.com/zh/model-studio/paraformer-realtime-8k-v2)。 +[^qwen-flash]: 阿里云百炼,[Qwen Flash](https://help.aliyun.com/zh/model-studio/qwen-flash)。 +[^cosyvoice3-flash]: 阿里云百炼,[CosyVoice v3 Flash](https://help.aliyun.com/zh/model-studio/cosyvoice-v3-flash)。 +[^pipl]: 全国人大,[中华人民共和国个人信息保护法](http://www.npc.gov.cn/npc/c2/c30834/202108/t20210820_313088.html)。 +[^deep-synthesis]: 国家互联网信息办公室,[互联网信息服务深度合成管理规定](https://www.cac.gov.cn/2022-12/11/c_1672221949354811.htm)。 +[^ai-label]: 国家互联网信息办公室,[人工智能生成合成内容标识办法](https://www.cac.gov.cn/2025-03/14/c_1743654684782215.htm)。 -- 2.54.0 From 31e4591854689f40e61724da202396b270e3ceb7 Mon Sep 17 00:00:00 2001 From: Rogee Date: Tue, 18 Aug 2026 11:44:40 +0800 Subject: [PATCH 2/2] =?UTF-8?q?H-264:=20=E8=A1=A5=E9=BD=90=E6=8E=A5?= =?UTF-8?q?=E9=80=9A=E5=90=8E=E5=A4=B1=E8=B4=A5=E6=94=B6=E6=95=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: multica-agent --- docs/architecture/public-model-outbound.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/architecture/public-model-outbound.md b/docs/architecture/public-model-outbound.md index e4b5936..6694ac3 100644 --- a/docs/architecture/public-model-outbound.md +++ b/docs/architecture/public-model-outbound.md @@ -153,6 +153,7 @@ stateDiagram-v2 ringing --> failed answered --> media_active answered --> ending + answered --> failed media_active --> ending media_active --> failed ending --> ended @@ -163,6 +164,8 @@ stateDiagram-v2 允许供应商跳过中间事件向前推进,例如 `requested → answered`;`ended/failed/cancelled` 是终态,迟到的 `ringing/answered` 不得令其回退。回调顺序不等于事实顺序:优先使用供应商序号/发生时间和允许迁移表;仍冲突时保留原始事件并调用 `GetCall`,以追加 correction/audit 的方式收敛。账单修正也只追加 adjustment。 +线路已接通但尚未收到 `media_started` 即失败时,call 收敛到 `failed`;该终态迁移的唯一获胜者写 outbox,执行幂等 `Hangup`、单次释放 PG 槽位并调用 `GetUsage` 对账。重复 `failed` 或迟到的 `media_started/answered` 只入 inbox/audit 并返回 2xx,不重复挂断、释放槽位或结算,也不回退终态。 + 实时会话子状态 `listening → thinking → speaking` 主要驻留内存。只将回合边界、稳定转写、工具副作用、generation、延迟和用量落 PG。 ### 4.1 正常通话与用户打断 @@ -265,7 +268,7 @@ PoC 只呼叫已同意的内部号码;参考音频、录音和转写在验收 按以下顺序拆任务即可,不需要先搭建额外基础设施: -1. **线路契约与 mock**:实现 capabilities、幂等发起/挂断/停播、验签、防重放、乱序/重复事件、查询恢复和用量取整契约测试。 +1. **线路契约与 mock**:实现 capabilities、幂等发起/挂断/停播、验签、防重放、乱序/重复事件、查询恢复和用量取整契约测试;覆盖无 `media_started` 的 `requested → ringing → answered → failed`,断言终态收敛、槽位只释放一次且仍执行计费/对账,再注入重复 `failed` 和迟到事件验证不重复副作用。 2. **调度与持久化**:实现 PG call/task/slot/inbox/outbox、单调状态机、租户/线路硬并发门禁、恢复和 adjustment;Redis 只做可丢快路径。 3. **媒体与打断**:用固定 G.711 8 kHz 样本验证连续重采样、上下行隔离/AEC、20 ms 帧、generation 丢弃和 StopPlayback。 4. **模型编排**:接入主模型和唯一备选,验证流式、取消、工具幂等、有界超时、一次切换与已批准结束语。 -- 2.54.0