跳转到主内容

构建你自己的 AI IVR 语音智能体

使用本地模型构建电话智能体:连接语音、处理更正并确认动作。包含可复制的编程提示词与实验测量图表,帮助你完善对话流程并理解等待时间。

AI IVR 示意架构:呼叫、聆听、理解、确认和响应。
TechKili
分享这篇文章:
本文目录

一通电话、一段对话、一项明确的任务。将电话系统与你的本地 AI 模型连接起来,构建一个能够听取诉求、追问缺失信息,并在来电者确认后准备请求的助手。

设想你拨打支持服务电话,说:“我想报告一台设备的问题。”助手询问具体设备,接受更正,并在继续之前复述信息。对话由此成为应用的输入,而应用可以围绕你自己的服务来设计。

AI IVR 智能体将交互式语音应答、语音识别、语言理解与语音合成结合起来。你可以用这种模式收集请求、读取经过授权的信息,或为后续人工处理准备资料。关键在于用明确的流程连接各个组件。

本文依次介绍如何选择第一项任务、将通话连接到模型、控制确认流程并测量等待时间。内容参考了使用 Asterisk、Pi 和 Qwen 的实验实现,同时提供用于构建智能体的编程提示词,以及帮助判断优化方向的图表。

本文假设模型已经在本地运行。 目标是构建一个能收集并确认测试请求的原型,随后再设计与管理应用的连接。本文讲解架构和应用规则,并不提供配置完成的电话系统或可直接投产的部署方案。

1. 选择智能体能够完成的任务

先明确一通电话应该完成什么。在本文的示例中,结果是一份由来电者确认的提案,包含类别、受影响对象和问题描述。

决策 原型示例
能做什么 准备一份通用问题报告
需要什么信息 类别、受影响对象和描述
应该问什么 下一个尚未填写的必填字段
何时可以继续 来电者确认当前版本的摘要后
怎样算完成 返回提案,并说明尚未提交
如何求助 提供明确的人工协助选项

这份简短的约定让你在接入电话之前就能测试逻辑。用文本输入请求,检查缺失字段,再加入一次更正。如果这条路径不成立,语音只会增加排查变量。

以后要接入真实查询或写入操作时,应为智能体所需的具体操作定义适配器。身份验证、权限检查和结果核验属于这一集成层的职责。

2. 划分组件:电话、语音与智能体逻辑

分开各项职责,才能分别检查。

组件 职责 边界
Asterisk 通话信令、音频传输与播放 不决定请求中的业务数据
Qwen3-ASR-1.7B 将语音转换为文字 转写结果不能代替标识符校验
Pi 与配置为 Qwen3.8-27B-NVFP4 的模型 提取意图、字段以及对确认回答的理解 不授予操作权限,也不控制通话
状态机 收集字段、校验转换、确认、更正和结束 只允许应用定义的动作
业务适配器 准备提案或读取已授权的信息 准备提案不等于真实写入
Qwen3-TTS 与预制语音 合成可变回答,复用固定消息 说出结果不能证明操作已经发生

这些模型说明的是我们测试时采用的组合,并不是你的智能体必须使用的组件。你可以选择接口兼容的其他本地 ASR、语言和 TTS 模型,但接入前应检查输入格式、输出契约和能力。下文的测量不能证明这些替代模型的性能。

这些名称用于说明所审阅的配置;结果既不是模型之间的比较,也没有单独测量模型权重的性能。Qwen 分别提供了语音识别语音合成文档。Pi提供智能体运行环境,具体限制则由应用代码实施。

来电者 → Asterisk → 语音活动检测 → ASR → 文字
                                          ↓
                                   Pi + 语言模型
                                          ↓
                                     意图与字段
                                          ↓
                                        状态机
                                     ↙        ↘
                                 追问/更正    确认信息
                                     ↑        ↓
                                     └─ 回答 ← 适配器
                                           ↓
                                  预制语音或 TTS → 来电者

在这一集成模式中,Pi 接收状态和用户发言,返回范围受限的结构。它没有通用文件、命令行或浏览工具。下一步问什么、何时允许执行操作,都由程序决定。

给模型写指令不能代替应用规则。技能说明可以描述流程,但规则仍须由应用强制执行。在所审阅的解释器中,自动加载技能已关闭,系统使用专用指令和结构化输出工具。

3. 将通话接入对话循环

基本逻辑确定后,再把它接入通话。在所审阅的架构中,Asterisk 负责电话部分,应用通过 WebSocket 通道交换音频。集成过程如下:

  1. 每通电话建立独立会话。 保存各自的字段、状态和当前修订号。每位来电者都需要独立上下文。

  2. 等待音频就绪。 来电进入系统和媒体连接可用是两个事件。通道能够接收音频后,再播放问候语。

  3. 检测一次发言并转写。 语音活动检测负责划定发给 ASR 的音频。将识别文字连同当前问题和状态交给解释器。

  4. 把结果转换为状态变化。 Pi 返回意图和字段;状态机决定继续收集信息、更正信息还是请求确认。

  5. 播放回答并继续聆听。 固定问题使用预制语音,可变内容使用 TTS。挂断后取消待处理工作和定时器。

用已知输入分别排查每个连接:先验证音频转文字,再验证文字转字段,最后验证文字转语音。三个阶段正常后,再与通话管理器集成。独立的阶段耗时有助于定位等待,而不会把所有延迟都归因于语言模型。

4. 设计允许更正的对话

以下对话是虚构示例,与测量数据背后的业务用途无关。设备 A 和 B 仅用于说明设计,不重现任何通话,也不对应真实组织、行业或地点。

助手: 我是自动助手。您想报告什么问题?

来电者: 我想报告一台设备的问题。

助手: 哪台设备受到了影响?

来电者: 示例设备 A。开机后没有反应。

助手: 我将准备一份问题报告:示例设备 A 开机后没有反应。信息正确吗?

来电者: 不对,我说的是示例设备 B。

助手: 已将受影响对象改为示例设备 B。您确认这些信息吗?

来电者: 是的,正确。

助手: 测试请求已准备好,尚未提交到管理系统。

更正必须使先前的确认失效。“是”只对当前摘要有效;沉默也不能视为同意。如果必填信息缺失,应用需要继续追问。

真正创建记录的集成必须先核实后端结果,再宣告创建成功,并提供由该系统返回的编号。本文的提案准备测试没有证明真实写入已经完成。保持这一区别,才能避免把流畅对话变成错误承诺。

查询也遵循同样的原则。助手说明授权读取返回的内容。模型不能补出并不存在的解决日期,也不能仅凭对方知道一个编号就授予访问权限。

5. 复制提示词,构建你自己的智能体

如果语音识别、语言模型和语音合成已经在本地运行,可以让编程 LLM 构建连接它们的应用。任务应明确规定对话、每通电话的状态,以及采取动作的条件。

将方括号中的内容替换为你的服务信息,再把下面的提示词交给编程助手。不要填写密码或个人数据。不了解的字段可以暂留,让助手在实现相应连接前先澄清。

请担任专注于语音智能体的软件工程师,为我的项目编写 IVR 智能体。
我需要可运行、可验证的应用,而不只是一份说明。

起点
我已经有三个模型服务在本地运行:
- ASR:[URL、模型、协议、输入音频格式及响应格式]。
- LLM:[URL、模型、协议及结构化输出支持情况]。
- TTS:[URL、模型、声音、响应格式及音频采样率]。
身份验证所用的环境变量名称为:
[变量名,不填写秘密值]。
不要安装、下载、训练或启动模型。
直接调用现有服务,不增加中间层,也不设计基础设施或部署方案。

我的智能体
- 任务:[智能体必须能够完成的事项]。
- 对话语言:[语言]。
- 必填字段:[字段及校验规则]。
- 允许动作:[封闭的操作清单]。
- 求助方式:[无法完成任务时应提供的选择]。
如果需要默认起点,请使用通用问题报告,包含类别、受影响对象和描述。
测试数据必须虚构,不涉及真实组织、行业或地点。

项目环境
遵循已有仓库的语言和约定。
如果是新项目,使用 Node.js 与 TypeScript。
若 Pi 与我的 LLM 端点兼容,用它作为受限的解释器。
先检查兼容性,不要杜撰 SDK 函数、方法或支持能力。
如果缺少必需的 API 信息,请向我索取接口契约或不含敏感数据的响应样例。
与此同时,继续实现不依赖这些信息的模块。

智能体逻辑
1. 分离会话、状态机、解释器、语音和动作模块。
   每通电话独立保存字段、有限历史、定时器和待处理任务。
2. LLM 只返回意图、字段和解释提案。依据模式校验输出。
   不向它提供通用命令行、文件或网络请求工具。
3. 应用决定下一步:收集信息、澄清、展示摘要、确认或取消。
   只问缺失内容,不编造值,也不凭推测补齐不确定字段。
4. 将明确确认绑定到来电者实际听到的那一版摘要。
   更正会使确认失效,必须重新展示摘要。
   沉默和过期确认都不能授权操作。
5. 从模拟适配器开始:返回提案并说明尚未提交。
   定义用于未来真实动作的接口,包含校验、授权与幂等性。
   没有接口契约时,不连接真实业务服务。
6. 只有相关操作确认成功后才宣告成功。
   若结果不确定,明确说明,并避免自动重复写入。

语音与电话循环
- 连接输入音频、发言检测、ASR、解释器、状态机和 TTS 回答。
- 按服务实际支持的格式转换音频,不擅自假定编解码器或采样率。
- 收到静音时以及音频块停止到达时,都应能结束一次发言。
- 用户打断时,停止排队音频,尽可能取消处理,丢弃过期结果。
- 复用固定语音,不把含来电者数据的回答放入共享语音目录。
- 等待时间、澄清次数和通话时长上限应可配置。
  结束时释放会话并取消其全部任务。
- 为已经可用的 Asterisk 实例准备适配器:
  [连接契约和配置变量名称]。
  播放问候语之前先等待音频通道就绪。
  如果连接不可用,保留模拟传输,并说明真实电话连接尚待验证。
- 若已配置人工协助,区分转接尝试、接听和音频连通。
  不编造转接目标,也不因发起转接就把它标记为完成。

交付与验证
交付清晰的模块、完整文件、不含秘密的环境变量配置,
以及说明如何连接本地服务运行智能体的 README。
先实现文本流程,再实现语音,最后实现电话适配器。

包含以下测试:字段缺失、更正、过期确认、沉默、打断、模型故障、
动作结果不确定,以及会话之间的隔离。

分别测量 ASR、解释器、动作和 TTS 耗时。
有真实通话时,还要测量从发言结束到有效回答首次可听见的时间。
不要把生成音频当成已经播放音频。
默认不在日志中记录录音、转写、凭据或个人数据。

运行环境允许的检查,并说明实际运行了哪些。
区分模拟服务、真实本地模型和真实电话连接。
不编造延迟数字、成功结果或通过的测试。

提示词要求构建的是智能体本身:模型已经存在,通过其接口访问。你可以调整任务和字段,同时保留确认、隔离和动作控制原则。生成的代码在接听电话之前,仍须经过审阅并连接你的服务进行测试。

6. 让智能体会聆听、等待和处理打断

1. 提前准备不会变化的语音

问候语、菜单和固定问题可以在来电前生成。参考模式加载固定语音目录,并检查文本对应关系与文件完整性。包含可变数据的回答则走另一条路径。

这样就不需要在通话中生成这些固定消息。这是设计属性,不是已经测得的秒数节省:该测试没有对问候语进行 A/B 对比。包含个人数据的音频不能进入共享目录。

2. 检测“没有到达的静音”

如果传输在停顿时停止发送数据包,只等待静音采样可能使对话轮次一直不结束。所审阅的检测器结合了采样分析与针对音频块缺失的定时器。

分别测试“收到静音块的停顿”和“完全没有音频块的停顿”。两者都必须有明确的处理结果。

3. 用户打断时取消过期工作

打断(barge-in)不仅是调低音量。还需要清空排队音频,尽可能取消处理,并丢弃已经被后续发言替代的结果。

Asterisk 的 WebSocket 驱动文档提供了用于丢弃排队音频的 FLUSH_MEDIA 命令。应用还必须判断哪一代工作仍然有效。Asterisk 文档

例如,用户在旧回答生成期间更正了对象标识符,旧回答不能在推理结束后再次播放。修订计数器和取消信号可以落实这一规则。

4. 明确求助选项

流程保留按键选项和请求人工协助的方式。用完澄清机会后提供帮助,不能等同于已经完成转接。

拨打目标只能证明尝试了转接。成功需要验证有人接听且音频连通。本文的内存测试没有验证人工转接,因此不把它算作已完成的结果。

5. 区分告知等待与真正加快回答

简短的等待提示可以让来电者知道通话仍然有效。预制问题能减少对即时推理的依赖。但这些决定都不会消除可变回答所需的处理时间。

把“首次可听见的提示”和“首次有用的回答”分开,才能避免优化一个不能代表来电者真实需要的指标。

7. 测量响应时间,用数据决定改进

流程正常后,记录每一阶段的耗时并核对保留的数据。下面的实验测量说明如何把测试结果转化为智能体的改进方向。

测试了什么,哪些没有测试

图表范围。 2026 年 9 月 17 日评估了两个脚本中的十二次合成来电者发言。模型是真实服务,电话传输与测试持久化由内存实现替代。这不是十二通真人电话,也不是负载测试。

评估器使用项目中的通话管理器、语音检测、识别客户端和解释器,以 20 毫秒 PCM 帧输入合成音频。模型和查询集成是真实的,而电话传输和测试存储使用内存实现。

两个脚本分别有四次和八次发言。审阅后的样本包含十三个识别片段:十二个完成,一个因被替代而取消。耗时图表纳入十二个完成片段,并明确排除已取消片段。对于被分段的轮次,展示的是完成片段,不是全部尝试的总耗时。

我们从客户端测量 ASR 请求与 Pi 解释阶段的耗时,其中可能包含传输、排队和服务处理。它们既不是纯 GPU 时间,也不是从用户说完到听见回答的完整等待时间。

该样本没有完整测量 TTS、首次可听见回答、抖动、丢包、能耗、单通电话成本或并发,也没有涵盖不同口音的真人群体。我们不用估算填补这些缺失指标。

执行报告没有充分记录硬件、负载和服务器的实际配置。因此,我们不把数字归因于特定 GPU 或上下文上限,也不将其描述为硬件比较。

等待时间积累在哪里

十二个合成对话轮次中客户端测得的语音识别与理解耗时。图表标注为中文。
TechKili

图 1:客户端分阶段测量。各条柱线独立,不相加作为总延迟。样本量小、顺序执行,每轮纳入一个完成片段。

阶段 完成的观测数 中位数 最小值 最大值
语音识别 12 8.17 秒 4.82 秒 14.71 秒
Pi 与 LLM 解释 12 3.93 秒 2.66 秒 11.37 秒

识别阶段的中位耗时更高,但部分轮次的解释耗时也很突出。后续优化应分别测量音频长度、排队、处理、请求长度和生成过程。

我们不把 p95 作为能够代表整个服务的指标。两个脚本、十二次观测虽然可以计算分位数,但作为运营信号非常薄弱。完整分布、中位数和范围更适合说明实际看到的情况。

我们也不宣称相对初次测试提升了某个百分比。审阅期间调整了分段处理与音频验证方式,两次执行不能视为受控的速度对比。

用实时因子理解 ASR 耗时

实时因子(RTF)等于识别请求耗时除以提交音频的时长:

RTF = ASR 请求耗时 / 音频片段时长

RTF 为 1 表示请求耗时等于片段时长。这是计算参照,不能单独判断整段对话是否流畅。

音频时长与识别耗时的关系;十二次观测的实时因子均大于一。图表标注为中文。
TechKili

图 2:十二个已完成请求的 RTF 中位数为 3.37。提交片段时长为 1.22 至 4.98 秒。分母采用实际 ASR 输入时长,而非剪辑后的对话音频时长。

所有片段的识别耗时都超过了自身时长。这为当前路径指出了优先排查方向,但不能证明模型在任意服务器上都具有同样性能,也不能推断 GPU 可以处理多少并发通话。

分别检查对话与识别

十二个轮次中十个通过转写阈值,十一个保留关键术语,十二个通过功能检查。图表标注为中文。
TechKili

图 3:逐轮检查。各项标准用于同一个样本,不是相互独立的生产可靠性百分比。

十二次发言中有十次满足评估器的词错误率阈值,即 WER ≤ 20%。十一次保留了脚本要求的关键术语。十二次都通过了解释字段、对话状态、回答内容、确认和音频技术有效性检查。

WER 通过统计替换、遗漏和插入,将转写文本与参考文本比较。本次评估规范化了大小写、重音符号以及部分数字表达。因此,不能直接与采用其他规范化方式或其他语料的基准比较。

某个轮次可能未通过文本匹配,却仍保留了足够上下文到达预期状态。这解释了完成流程与通过全部标准的区别,但不意味着识别错误无关紧要。即使其余对话正常,识别错误的标识符或编号仍可能需要重述。

输出语音也经过自动回转写。审阅验证器后,十二个轮次的回答均落在规定阈值内。验证使用的是同一语音识别系统:这不是独立的人工听评,也不能证明每个专有名称都发音准确

两个场景的严格总体结果仍为未通过。语言模型评审认为对话合理,不能覆盖这一结果。不同信号回答的是不同问题。

8. 面向来电者开放前,验证完整路径

要在其他项目复用这一方法,先定义范围有限的流程、必填字段、允许动作和可核验的结果,再编写涵盖确认、更正、沉默、打断、取消和后端故障的脚本。

  1. 对测试进行版本管理。 固定代码、模型、参数、音频与规范化方式。记录服务器实际生效的配置,而不只是预期配置。

  2. 分别测量各阶段。 记录 ASR、解释器、适配器、TTS 和播放的起止时间,同时保留取消和错误。

  3. 保留失败。 明确说明后,可以将取消请求排除在完成请求的耗时分布之外;不能把它从总体记录中抹掉。

  4. 检查数据与动作。 对照字段、有效确认、已执行操作和播报结果。保存提案不等于创建真实请求。

  5. 进入真实电话测试。 在真人、噪声和 SIP/RTP 传输条件下重复测量,从发言结束计时到有效回答首次可听见。

  6. 逐步提高负载。 在预先确定的限制下测量并发时的分布、错误和队列。共享模型不能意味着共享通话状态。

图表只展示耗时、音频时长和质量检查,不包含录音、识别文本、地址、记录编号、会话标识符或内部基础设施。

第一个智能体:实用任务与明确的下一步

这一模式适合探索可重复任务的产品价值,例如准备通用问题报告、查询已授权的状态信息,或在人工接手前收集资料。商业吸引力在于减少这些步骤的交互阻力;当前样本还没有量化人员成本节省、满意度或弃呼率下降。

对于考虑自建或采购的团队,我会要求三项演示:更正使旧确认失效、故障时不宣告不存在的成功,以及在预期负载下完整测量等待时间。

第一版可以只做一项任务:收集字段、接受更正、返回已确认的提案。随后加入经过授权的读取、连接真实动作,并测试完整电话路径。每一步都增加一项可验证的能力,再逐步扩大服务范围。

你会让第一个电话智能体做什么:收集请求、查询状态,还是为人工接手准备信息?