18 KiB
agent-call:部署与开发约束
目录与实施范围
- 项目根目录用于部署,
docs/保存本项目需求、计划与验收资料,不挪回根目录。 sip_mock_server/是计划独立拆仓的子项目,源码、配置、测试和文档均保留在该目录,遵守其AGENTS.md;父项目只通过固定镜像和版本化协议/契约与其集成。- 现有实现为 ASR Web 验证、Asterisk 配置和阿里云主机准备工具,不是完整外呼平台。用户已接受最终方案,后续按
docs/最终开发部署监控与验收计划_v1.0.md开展契约驱动 Mock 开发,再替换真实依赖。 - 用户已决定仅复用 voice_test 的 ASR。禁止复制或启用该仓库的 LLM/TTS;新规范确认前,界面必须明确显示未启用。
- SaaS 指令与所有业务结果均走 RabbitMQ;录音先上传 OSS,再通过 MQ 回传 OSS ID。接口/消息规范由用户制定,不能擅自改成 HTTP 业务回调。
管理平台独立项目约束(用户已确认)
- 整套 SIP 管理平台在
management/实现,作为同仓库内独立项目,拥有自己的配置、依赖、持久化迁移、构建、测试、部署和发布入口;不与其它部署、管理或测试业务耦合。设计与权威契约仍保留在docs/。 - 前端固定使用 https://github.com/Kiranism/tanstack-start-dashboard 作为管理系统基座,实施时锁定上游版本和依赖并核验/保留许可证声明;后端 API 使用 Go。建议目录为
management/frontend/、management/backend/、management/deploy/,由management/README.md给出独立运行与验证步骤。 - 既有
agent_call/sip_management.py仅作契约与行为参考,不作为管理平台运行依赖;禁止导入其它项目内部代码、代理/调用 Python 实现业务 API、共享其它业务数据库或依赖其部署脚本/环境文件/测试夹具。TanStack 服务端仅承担页面及必要会话/转发衔接,不另建业务后端;Go API 负责最终授权和管理逻辑。 - Cell、调度器、身份提供方及统计事实来源通过批准的版本化接口/事件对接,不跨库 JOIN 或修改外部业务表。独立开发/测试使用项目内协议 Mock、自有隔离持久数据库,MQ 集成测试按需配置隔离真实 broker;不以云资源、真实拨号或其它业务测试栈为启动前置。
- 独立部署不取消真实发布安全屏障:外部系统缺失时仍可启动/管理草稿,状态和统计标 unknown/不完整;真实发布/停用需外部确认时必须阻塞或待对账。旧 Python 与新 Go 管理端不得同时写同一资源。不得新增 HTTP 拨号或业务结果回调。
- 契约从
docs/唯一来源生成/同步版本化产物并校验,不维护重复手写 schema;管理平台打包后无需读取其它项目目录。管理功能验收与真实 SIP/其它业务验收分开报告;详见docs/SIP管理后台_接口与页面设计及验收_v1.0.md。
最终实施与 Mock 边界(用户已确认)
- 以最终开发部署监控与验收计划为实施入口,
docs/SaaS交互_OpenAPI与MQ契约规划_v0.1.md正文 v1.0 是字段/路径/状态的唯一维护来源;从 D01 生成 OpenAPI/共用 MQ Schema 开始,不重复等待已接受方案拍板。 - 外部 SaaS、数据库、RabbitMQ、SIP/AI、OSS/云条件并行协调。HTTP Mock 遵守 OpenAPI;MQ 用真实测试 broker,SIP/ARI/RTP及AI流式通道按协议模拟,不改成HTTP业务回调;持久状态使用真实隔离数据库,不用内存字典代替。
mock/mixed/real必须可识别,Mock 默认隔离真实外网,正式模式拒绝 Mock/测试凭证,不静默回退。LLM/TTS 可开发新 Mock 适配,但不得复用旧实现或假称真实供应商已启用。- 已接受原值key一对一绑定、超出224个UTF-8字节路由预算则停发保留原任务而非截断;控制CAS、整体补传、无应用收讫、整任务撤销屏障等规则以主契约为准。
- 最终计划的 DEV/SCALE-MOCK 数值是工程初始测试基线,不是生产SLA/业务额度/消费授权。真实预算、供应商能力、保留与RPO/RTO需在实际部署前登记核验;Mock通过不得替代真实1000路完整AI、N+1及供应商验收。
固定资源与云部署规则
-
区域为阿里云北京
cn-beijing。 -
我方对 SIP 服务商登记的公网出口白名单 IP 是 123.56.71.98。它不是 SIP 服务端地址,不得填入 trunk contact。
-
目标计算资源为阿里云竞价 ECS。必须先使用阿里云 CLI 查询 IP/EIP 与现有实例;确认没有可复用主机后,才允许按明确的实例规格、竞价策略(限价策略需提供价格上限)、磁盘/VSwitch/安全组/SSH KeyPair 创建。
-
固定 IP 是否为本账号可操作的 EIP 必须查询。找不到该 EIP/现有公网 IP 时停止,禁止新分配任意公网 IP 冒充白名单地址。若属于非 EIP 的实例公网 IP,只能复用经明确指定的原实例;回收后的地址保留不能保证。
-
不解绑或覆盖其他实例上的 EIP,不删除、停机或修改无关实例;多个候选实例、未知归属或未授权绑定一律停止。
-
工具默认只读计划;
--apply才执行创建/绑定。用户未明确授权、云凭据未配置、现有绑定不明时,不能实际消费或改绑。竞价策略可使用SpotWithPriceLimit(必须提供正的价格上限)或SpotAsPriceGo(无价格上限;仅在用户已明确确认自动出价时允许)。价格上限(如使用)不包含系统盘/EIP/流量费用;SpotAsPriceGo不提供价格保护。 -
创建使用持久化 ClientToken;创建后绑定失败保留实例ID供恢复,不自动再创建一台、不自动删除实例。竞价回收不等于自动迁移活动通话。
-
使用
aliyunCLI 创建竞价 ECS 进行测试时,测试完成必须先询问用户是否清理。未获得明确清理指令时,保留唯一project=agent-call可用/运行实例,不自动删除或并行创建第二台;用户明确要求清理后,只停止并删除本次创建的实例,不删除、释放或解绑指定 IP/EIP。 -
不把 AK/Secret、ASR Key、ARI 密码、SSH 私钥放入代码、文档、日志或聊天。优先配置 CLI RAM Role/STS,运行时通过环境或受控文件注入。
-
创建主机时必须开通 TCP 22 供后续 SSH 运维;不要求按用户当前源 IP 限制,但不得因此放宽其他端口。创建后必须建立用户
rogee,禁止 root 直接 SSH 登录,并在系统级关闭 root 和普通用户的密码/键盘交互登录(PasswordAuthentication no、KbdInteractiveAuthentication no、PermitRootLogin no)。仅安装以下用户提供的 rogee 公钥,后续命令必须通过 SSH 以rogee用户执行,需要特权时使用受控sudo:ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPoGJTH1JrXbWu+ZhIgaHMhume0oWQiWmadhTwbk75Ny rogee@ipao.vip
不得把对应私钥写入代码、文档、日志或聊天;使用受控本地私钥/SSH agent。不得用密码登录或以 root 作为后续常规命令入口。
-
主机操作系统固定优先使用 Debian 13(Trixie)minimal;该项目无 Ubuntu 专属依赖,Docker/Asterisk/Go/Python 均按 Debian 13 构建和验收。仅当北京区域无可用 Debian 13 镜像时,才使用 Ubuntu 24.04 LTS;创建前必须查询实际可用镜像,不得擅自切换到非 LTS Ubuntu。
-
当前第二组 SIP(
bjmkkj)恢复基线固定使用系统盘快照s-2ze28ulhip70y5vsbnf8(源系统盘d-2ze8yfac91hmae1vx2lz,40 GiB ESSD PL1)。使用前必须查询快照状态为accomplished;不得删除或覆盖该快照。原镜像m-2ze0rw9430vfv6ifym8m不删除;使用前必须查询状态为Available,但若创建接口拒绝该镜像,不得重复盲试。 -
2026-09-16 竞价回收前的当前系统盘备份为快照
s-2zeaj3c0izs18cdcafe7,状态须为accomplished;由该备份制作的恢复镜像为m-2ze9kli7ztwzzqofsyb6,状态须为Available后才可用于恢复远程修改继续定位。
SIP 接入信息
以下为用户提供的 SIP 参数,服务商名称待补充;已记录不代表已完成真实线路验证。
| 服务商 | SIP 服务端 | 主叫号码/标识 | 被叫前缀 |
|---|---|---|---|
| 数企 | 61.132.228.221:5060 |
BD93205882 |
7089 |
| 中鼎 | 60.171.24.90:5060 |
mbkq |
无 |
| 百应 | 160.202.254.79:5060 |
KQ91526 |
mka755 |
SIP 全局共用定义:外呼号码白名单
-
外呼号码白名单:
15003164745、15830461047。 -
所有 SIP 线路仅允许在此列表范围内发起外呼;不在列表内的号码必须拒绝。该列表仅用于已授权的 Mock/明确安排的测试;不得因写入此处而自动发起真实呼叫,原始号码保持不变。
-
主叫标识保留原值(包括
BD),不能按纯数字手机号清洗,也不能直接当成 Digest 认证用户名;具体 From/PAI 等字段映射仍需确认。 -
业务原始被叫号码保持不变;使用该线路时按其规则构造
7089<被叫号码>,避免重复添加或把该前缀带到其他供应商线路。 -
传输协议、IP/Digest 鉴权、是否注册及并发限制仍需供应商确认;当前供应商已反馈需使用 PCMA,Asterisk 配置以
allow=alaw表示,仍需真实线路验证。 -
每条线路目前只提供一个服务端地址,未提供独立备用地址。不能把同一地址重复填写成主备并宣称具备容灾;三条已登记线路应作为独立 trunk 配置,不为凑主备虚构供应商。
多 SIP 供应商方案(用户已确认,测试运行骨架已实现)
- 采用供应商按需预接入 + 每次外呼动态选路。先验证当前供应商,后续逐家新增,不等待所有供应商一次性接入完毕。
- 供应商/线路层预先维护独立 trunk:服务端、协议、鉴权、注册、允许的主叫、被叫改写规则和并发额度。不同供应商不能共用并逐呼覆盖同一份线路配置。
- 呼叫层只从服务端已配置且获授权的线路中选择,按该线路规则设置本次主叫与被叫;不为每个号码重写 pjsip.conf、重载 Asterisk 或重建注册。
- MQ 指令不能让调用方任意注入 SIP 地址、认证凭据或越权主叫;线路选择对应的具体消息字段仍由用户制定,不擅自定接口。
- SIP Trunk、codec、主叫/被叫规则、出口池及多机器 Cell 发布由独立 Asterisk/SIP 管理后台作为唯一写入面统一管理;SaaS 仅可读取受控 Trunk 目录/状态,不直接访问 Asterisk/ARI 管理面或写入 SIP 配置。
- 切换线路时从原始被叫重新应用目标线路规则,不能沿用上一家的前缀或主叫。重试/切换条件需按业务契约另行实现,不能默认重复拨打已接通的电话。
- Asterisk 生成器支持任意数量的独立
trunks;Real Cell 通过受信的 Cell 本地路由表把route_policy_id + caller_profile_id绑定到已配置trunk_id、主叫和被叫前缀,任务不能注入 SIP 地址、认证凭据或主叫。无需逐呼重写pjsip.conf、重载 Asterisk 或重建注册;生产路由表仍由 SIP 管理后台发布。
生产容量与网络架构基线(用户已确认,运行代码待实现)
- 目标口径是至少 1000 路同时已接通的完整 AI 通话,包括 ASR/LLM/TTS;拨号、振铃、CPS 和故障冗余必须另行计入,不能把 1000 路在途呼叫当作验收结果。
- 生产主方案为多机器 + 多 EIP 直连:每个语音 Cell(Asterisk、媒体适配和本地执行器)绑定固定出口 IP;调度器选择
trunk_id + egress_pool_id + cell_id,一通电话从建立到结束固定在同一 Cell/出口,不逐呼重写共享 SIP 配置。 - 每个 Cell/出口要维护独立的供应商白名单、RTP 端口范围、并发上限、CPS 令牌、编解码和健康状态。供应商限制优先于本地理论容量;不能用随机轮询突破供应商配额。
- 采用 N+1 或更高冗余:按压测得到的单 Cell 安全容量计算
(Cell数量 - 1) × 单Cell安全容量 >= 1000,并额外预留发布、线路降级和突发拨号余量。未完成真实 ASR/LLM/TTS、SIP/RTP 和供应商压测前,不承诺固定机器数或规格。 - 单 EIP+NAT 不再作为备选方案;当前及后续生产计划不设计、不实现、不验收该架构,不得以通用 SNAT 替代多 EIP 直连。
- 调度器只分配有完整资源租约的 Cell:供应商并发/CPS、Cell媒体端口、ASR/LLM/TTS配额、出口健康和节点容量必须同时满足;租约过期或心跳失效时停止新任务,活动通话不自动接管。
- RabbitMQ 只负责可靠传输,不作为活动通话唯一状态源;命令/结果采用持久化、发布确认、手动确认和幂等事件。业务状态、调度租约和 outbox 需要可靠持久化;重复投递不能造成重复拨号或重复业务结果。
- 1000 路容量必须同时验证 RTP 包率/带宽、RTP 端口对数量、连接数/文件描述符、NAT/conntrack、AI 首包及持续延迟、MQ 堆积、OSS 上传速度和供应商错误率。当前 RTP
10000–10800仅为基线,绝不是 1000 路容量保证。
多租户队列与公平调度(用户已确认,运行代码待实现)
- SaaS 按可信
tenant_key向租户独立 RabbitMQ 命令队列 PUSH,呼出应用调度器负责租户间公平调度;不再用所有租户共享的执行 FIFO,不增加 HTTP 拨号入口。业务任务/重试决策仍属于 SaaS。 - 默认建议活跃且可调度租户等权轮询,差异化权重需按业务规则确认;每轮有界取数,租户额度耗尽或线路不可用时跳过。按租户及全局限制预取、未 ACK 和已持久化待发起窗口,不能先消费到无界内存 FIFO;重启恢复也必须公平。
- 租户并发/CPS 配额跨所有 Cell、调度实例汇总;并发覆盖预留、拨号、振铃、接通及待对账占用,CPS 包括 FALLBACK。实际发起同时满足租户额度、供应商、Cell/出口和 AI 完整资源租约。多实例须协调调度所有权和原子额度,不能各自发放一份;未知活动通话不能仅因租约到期直接释放占用。
- 平台负责队列创建、精确绑定、权限和安全停用/清理;
tenant_key是 SaaS 产生的业务数据,命令、队列路由及后续 MQ 回调均原样使用,不做清洗、编码或业务格式限制;必须校验正文值与队列/路由绑定精确一致。最终用户不直接连接 broker,不允许任意指定其他租户路由。命令重试/死信恢复回原租户调度域,不绕过配额。 - 每租户设置发布速率、队列消息数/字节和待执行窗口上限,并有全局 broker 水位保护。队列满明确拒绝发布,不丢弃队头旧命令;SaaS 持久保留未确认发布记录,使用原执行标识有限重试。独立队列不代表独享 broker 资源或无限积压。
- 公平调度分配新执行机会,不为公平挂断已接通电话;资源满需等待释放。固定开始时限必须另确认覆盖线路/AI/Cell 的保底容量或受限借用策略,不能仅用轮询宣称保证。
- 本轮不改变事件结果队列为一租户一队列。资源统一使用
agent-call命名空间;命令 exchange 使用 direct,命令 routing key 为agent-call.tenant.{tenant_key}.call.execute,事件 routing key 为agent-call.{event_type}。轮转/预取、配额、保留与等待指标待 G0 冻结;须验收大租户积压下小租户公平、多实例配额不超额、背压不丢消息及租户路由安全。
其它环境前置
- 本地:Go 1.26、Python 3.11+、Node、Docker Engine/Compose;云操作另需
aliyunCLI 和北京区域权限。 - 云创建权限至少涉及 ECS Describe/RunInstances、VPC DescribeEipAddresses/AssociateEipAddress;已有 VSwitch、安全组、镜像和 SSH KeyPair。不得自动开放全部端口。
- Asterisk:镜像固定 digest;已提供的 SIP 参数见上节,其余供应商/备用地址及接入规则仍待补充。ARI 默认仅回环访问;跨机器使用管理网和受控 TLS。RTP、防火墙、NAT、编解码必须真机验证。诊断阶段的 UDP 放行必须按供应商 SIP/SDP 媒体源 IP 限定,禁止
0.0.0.0/0;第一组实测 183 SDP 的媒体源为61.132.228.245,仅可作为临时诊断源,验证后应收窄或移除。 - ASR Web:服务访问令牌、百炼/火山凭据;默认仅宿主机回环暴露。远程麦克风需要 HTTPS,或通过 SSH 隧道访问 localhost;不要求用户关闭浏览器安全机制。
- 业务对接仍需 RabbitMQ VHost/队列/ACL、用户发布的消息契约、OSS 上传与 OSS ID 规范。测试台音频/识别输出不是已接入 SaaS 的 MQ 结果。
- LLM/TTS:供应商、协议、模型、参数、取消/打断与音频契约均待用户新规范;不得静默调用旧实现或宣称完整对话已验证。
参考资源
- https://git.ipao.vip/rogee/sip-research :Asterisk 调研和 Mock 底座;不能把历史测试结果当成本环境验收。
- https://git.ipao.vip/rogee/voice_test :仅借用 ASR 协议代码;本项目访问控制、Web页面和生命周期独立实现。
- 最终实施入口为
docs/最终开发部署监控与验收计划_v1.0.md;主契约docs/SaaS交互_OpenAPI与MQ契约规划_v0.1.md(路径保留,正文v1.0)。旧一期计划保留WBS/AT和历史估算,旧交付文档作实现细则;当前已存在服务的运行步骤仍见docs/部署接入_运行说明.md,不能把未来产物当成已实现。
验证与交付
- 管理平台独立验证:在
management/backend/的 Go 模块执行go test -race ./...、go vet ./...与格式化检查;前端按自身锁文件及实际 package scripts 检查/测试/构建,入口记录于management/README.md。以下其它项目测试不作为管理平台默认前置,仅改动对应项目时执行。 - Python:
python3 -m unittest discover -s tests -v。 - Go:
cd services/asr-web && go test -race ./...;改动后执行格式化与静态检查。 - PCM:
node --test tests/test_pcm.cjs;Shell:bash -n deploy/asterisk.sh。 - 不用真实云账号运行自动创建测试;使用可注入的 CLI runner 测试请求/恢复逻辑。
- 实际部署、真实 ASR、SIP、MQ/OSS、LLM/TTS测试必须分别报告,模拟测试通过不代表生产验收通过。