人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载本指南围绕 TEN 开源仓库中的 voice-assistant-sip-plivo 示例 展开完整讲解如何用 Plivo SIP 集成实现支持入站自动接听与出站主动呼叫的实时语音 AI 助手覆盖环境变量配置、property.json图编排、REST API 调用、WebSocket 媒体流桥接STT → LLM → TTS 全链路以及 ngrok 本地联调与 Docker 发布。读完本文你将掌握一套可直接运行的电话语音助手参考实现并理解其底层音频转换与事件驱动原理。核心能力概览该示例是一个基于 Plivo SIP 的电话语音助手具备以下三大能力与 README 描述一致入站呼叫处理自动接听来电并对通话中的实时语音进行识别驱动 AI 对话出站呼叫管理通过 RESTful API 发起、查询、停止外呼电话实时语音交互完整的语音对话流水线包含 STT语音转文字→ LLM大模型推理→ TTS文字转语音处理。从目录结构看该示例由四部分构成源码均在仓库ai_agents/agents/examples/voice-assistant-sip-plivo/下目录/文件作用server/独立的 Plivo 配置服务器FastAPI负责进程管理与健康检查tenapp/TEN 应用本体property.json定义语音助手图graphtenapp/ten_packages/extension/main_python/核心扩展main_pythonPlivo 呼叫服务器、Agent 事件循环、音频转发frontend/Next.js 前端呼叫状态、外呼表单、入站弹窗架构与关键调用链路组件角色配置服务器与呼叫服务器的分工仓库中存在两个 FastAPI 服务职责不同容易混淆server/plivo_server.py中的PlivoServer注释明确说明它只负责配置与健康检查所有呼叫逻辑由 tenapp 应用处理见 plivo_server.py。它会以子进程方式拉起tenapp调用./scripts/start.sh并通过监控线程在 tenapp 退出时同步关闭自己实现进程生命周期绑定plivo_server.py。tenapp/ten_packages/extension/main_python/server.py中的PlivoCallServer真正承载呼叫业务——REST API、Plivo webhook 应答 XML、WebSocket 媒体流全部在同一个端口默认 9000上提供server.py。PlivoCallServer在 TEN 扩展的on_init阶段被MainControlExtension._start_server()以 asyncio 后台任务启动并将扩展实例回填为extension_instance引用用于后续把音频帧转发进 TEN 框架extension.py。入站通话的完整链路从源码server.py的handle_answer_webhook与websocket_endpoint可以还原入站流程Plivo 收到来电后向公网地址/webhook/answer发送 webhookGET/POST 均可服务端用plivoxml.ResponseElement拼装应答 XML返回Stream bidirectionaltrue元素指向wss://公网地址/media并声明content_typeaudio/x-mulaw;rate8000server.pyPlivo 建立 WebSocket 连接后先收到{type: connected}确认帧随后 Plivo 推送start/media/stop三类事件start事件携带streamId与callId服务端据此注册active_call_sessions[call_uuid]会话并保存 WebSocket 与 stream_id同时回调扩展的on_websocket_connected触发问候语 TTSserver.pymedia事件携带 base64 编码的 μ-law 音频经_forward_audio_to_ten解码转换后封装为AudioFrame发送给 TEN 图中的streamid_adapter扩展见 property.json 的 audio_frame 连接随后进入 STT 扩展。出站呼叫的完整链路出站流程由POST /api/call触发server.py客户端提交{phone_number: ..., message: ...}服务端用 PlivoRestClient发起calls.create携带from_PLIVO_FROM_NUMBER、to_、answer_url与hangup_url应答后以request_uuid作为call_uuid注册会话返回 JSON对方接听后Plivo 回调answer_url后续流程与入站一致。音频格式转换μ-law ↔ PCM 的双向桥接Plivo 使用 μ-law 8kHz 编码而 TEN 框架内 STT/TTS 走 PCM 16kHz因此extension.py实现了双向转换上行用户语音进框架_forward_audio_to_ten用audioop.ulaw2lin将 μ-law 解码为 16-bit PCM构造AudioFrame设置sample_rate8000、单声道、每样本 2 字节并指定stream_id属性extension.py下行TTS 音频出到电话send_audio_to_plivo先将 16kHz PCM 用_downsample_audio16k→8k 采用隔样本抽取其他比率走audioop.ratecv降采样再用audioop.lin2ulaw编码为 μ-law最后以 Plivo 的playAudio事件、audio/x-mulaw;rate8000类型通过 WebSocket 下发extension.py。下行音频的来源是 TEN 图的on_audio_frame回调MainControlExtension收到名为pcm_frame的帧后遍历所有活跃通话的 WebSocket 逐个下发extension.py。事件驱动的 Agent 循环main_python扩展内部封装了一个事件驱动 Agentagent/agent.py维护_asr_queue与_llm_queue两个 asyncio 队列及对应消费者任务通过on(event_type, handler)注册回调。MainControlExtension在on_init中扫描自身带_agent_event_type装饰器的方法并自动注册extension.py。核心事件处理逻辑包括ASR 结果收到asr_result后若为 final 或文本超 2 字符则触发_interrupt()清空句段、flush_llm、发送tts_flush与flush命令打断正在生成的语音final 结果进入 LLM 队列extension.pyLLM 流式响应非 final 的 message 增量按句子切分parse_sentences即时送 TTS 实现边说边出final 时把剩余句段补齐extension.py工具注册ToolRegisterEvent将天气等工具注册给 LLM对应WEATHERAPI_API_KEY。LLM 执行器LLMExecagent/llm_exec.py通过输入队列消费请求维护上下文与工具注册表支持流式响应回调。前置准备环境变量必填环境变量变量说明PLIVO_AUTH_IDPlivo Auth ID必填来自 Plivo 控制台PLIVO_AUTH_TOKENPlivo Auth Token必填PLIVO_FROM_NUMBERPlivo 电话号码用作外呼主叫号码必填PLIVO_PUBLIC_SERVER_URL公网服务器地址必填。Plivo 通过它发送 webhook 并建立 WebSocket 音频流。本地调试可用 ngrok 将本地端口映射为公网域名DEEPGRAM_API_KEYDeepgram API Key必填用于语音识别 STTOPENAI_API_KEYOpenAI API Key必填用于大模型ELEVENLABS_TTS_KEYElevenLabs API Key必填用于语音合成 TTS可选环境变量变量说明OPENAI_MODELOpenAI 模型名可选默认使用已配置的模型OPENAI_PROXY_URLOpenAI API 代理地址可选WEATHERAPI_API_KEY天气工具所需的 Weather API Key可选对应图中的weatherapi_tool_python扩展NGROK_AUTHTOKENngrok 本地开发认证令牌可选此外从 server.py 的main()可知还存在两个协议开关变量变量默认值说明PLIVO_USE_HTTPStruewebhook 使用 HTTPStrue或 HTTPfalsePLIVO_USE_WSStrue媒体流使用 WSStrue或 WSfalse这两个开关由MainControlConfigconfig.py解析用于在server.py中拼接https/wss前缀的 webhook 与媒体流 URL。本地 ngrok 场景下服务端实际以 HTTP 运行、由 ngrok 承担 SSL 终结见 server.py 的注释与逻辑。部署与运行1. 配置 .env在.env文件中填写Taskfile.yml通过dotenv: [../../../.env]自动加载# Plivo呼叫处理必填 PLIVO_AUTH_IDyour_plivo_auth_id_here PLIVO_AUTH_TOKENyour_plivo_auth_token_here PLIVO_FROM_NUMBER1234567890 PLIVO_PUBLIC_SERVER_URLhttps://your-domain.com # Deepgram语音识别必填 DEEPGRAM_API_KEYyour_deepgram_api_key_here # OpenAI大模型必填 OPENAI_API_KEYyour_openai_api_key_here OPENAI_MODELgpt-4 OPENAI_PROXY_URLyour_proxy_url_here # ElevenLabs语音合成必填 ELEVENLABS_TTS_KEYyour_elevenlabs_api_key_here # 可选 WEATHERAPI_API_KEYyour_weather_api_key_here NGROK_AUTHTOKENyour_ngrok_auth_token_here2. 安装依赖cd agents/examples/voice-assistant-sip-plivo task install该命令安装 Python 依赖与前端组件。从 Taskfile.yml 可以看到它依次执行tman install安装 tenapp 依赖、./scripts/install_python_deps.sh安装 tenapp 的 Python 依赖、bun install --verbose安装前端依赖。3. 安装 ngrok本地开发用本地开发需要 ngrok 将本地服务暴露到公网。可参照官方仓库安装# 使用官方仓库安装 ngrok curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | gpg --dearmor /etc/apt/trusted.gpg.d/ngrok.gpg echo deb https://ngrok-agent.s3.amazonaws.com buster main /etc/apt/sources.list.d/ngrok.list apt-get update apt-get install -y ngrok也可以直接从 ngrok 官网下载。注意需要注册免费的 ngrok 账号并从 ngrok dashboard 获取 auth token。4. 启动语音助手cd agents/examples/voice-assistant-sip-plivo task run语音助手将以全部能力启动。task run会并行拉起四个任务Taskfile.ymlrun-gd-servertman designer启动 TMAN Designer端口 49483run-frontendbun run dev启动前端run-api-serverpython3 main.py --tenapp-dir ../tenapp启动独立 Plivo 服务器默认端口 8080负责拉起 tenapprun-ngrok./start-with-ngrok.sh启动公网隧道。5. 访问应用服务地址前端http://localhost:3000API 服务器http://localhost:9000TMAN Designerhttp://localhost:49483配置详解property.json 中的语音助手图语音助手的核心配置位于tenapp/property.jsonproperty.json它定义了一个名为voice_assistant的预定义图auto_start: true。仓库实际配置比 README 示例更完整包含connections数据流定义完整内容如下{ ten: { predefined_graphs: [ { name: voice_assistant, auto_start: true, graph: { nodes: [ { type: extension, name: stt, addon: deepgram_asr_python, extension_group: stt, property: { sample_rate: 8000, params: { api_key: ${env:DEEPGRAM_API_KEY}, language: en-US } } }, { type: extension, name: llm, addon: openai_llm2_python, extension_group: chatgpt, property: { max_memory_length: 10, base_url: https://api.openai.com/v1, api_key: ${env:OPENAI_API_KEY}, frequency_penalty: 0.9, model: ${env:OPENAI_MODEL}, max_tokens: 512, prompt: , proxy_url: ${env:OPENAI_PROXY_URL|}, greeting: TEN Agent connected. How can I help you today? } }, { type: extension, name: tts, addon: elevenlabs_tts2_python, extension_group: tts, property: { params: { key: ${env:ELEVENLABS_TTS_KEY}, model_id: eleven_multilingual_v2, voice_id: pNInz6obpgDQGcFmaJgB, output_format: pcm_16000 }, dump_path: ./, dump: false } }, { type: extension, name: main_control, addon: main_python, extension_group: control, property: { greeting: Hello, I am your AI assistant., plivo_auth_id: ${env:PLIVO_AUTH_ID}, plivo_auth_token: ${env:PLIVO_AUTH_TOKEN}, plivo_from_number: ${env:PLIVO_FROM_NUMBER}, plivo_server_port: 9000, plivo_public_server_url: ${env:PLIVO_PUBLIC_SERVER_URL}, plivo_use_https: true, plivo_use_wss: true } }, { type: extension, name: message_collector, addon: message_collector2, extension_group: transcriber, property: {} }, { type: extension, name: weatherapi_tool_python, addon: weatherapi_tool_python, extension_group: default, property: { api_key: ${env:WEATHERAPI_API_KEY|} } }, { type: extension, name: streamid_adapter, addon: streamid_adapter, property: {} } ], connections: [ { extension: streamid_adapter, audio_frame: [ { name: pcm_frame, dest: [{ extension: stt }] } ] }, { extension: stt, data: [ { name: asr_result, dest: [{ extension: main_control }] } ] }, { extension: main_control, audio_frame: [ { name: pcm_frame, dest: [{ extension: streamid_adapter }] } ] }, { extension: tts, audio_frame: [ { name: pcm_frame, dest: [{ extension: main_control }] } ] } ] } } ], log: { handlers: [ { matchers: [{ level: info }], formatter: { type: plain, colored: true }, emitter: { type: console, config: { stream: stdout } } } ] } } }各节点参数说明sttdeepgram_asr_pythonsample_rate: 8000与 Plivo 的 μ-law 8kHz 采样率保持一致确保上行音频无需重采样即可识别params.api_key通过${env:DEEPGRAM_API_KEY}从环境变量注入params.language: en-US识别语言。llmopenai_llm2_pythonbase_urlOpenAI API 端点api_key、model、proxy_url均支持环境变量注入${env:OPENAI_PROXY_URL|}中|表示空默认值max_tokens: 512单次生成上限frequency_penalty: 0.9降低重复max_memory_length: 10上下文记忆轮数greeting连接建立时的问候文案。ttselevenlabs_tts2_pythonparams.key${env:ELEVENLABS_TTS_KEY}params.model_id: eleven_multilingual_v2多语言模型params.voice_id音色 IDparams.output_format: pcm_16000输出 16kHz PCM供main_control降采样为 8kHz 后下发 Plivodump_path/dump是否导出音频文件默认关闭。main_controlmain_python即本示例的核心扩展属性与 config.py 中的MainControlConfig字段一一对应属性类型默认值说明greetingstringHello, I am your AI assistant.通话接通后 WebSocket 建立时发送的问候语经on_websocket_connected触发 TTS见 extension.pyplivo_auth_idstring空Plivo Auth ID必填plivo_auth_tokenstring空Plivo Auth Token必填plivo_from_numberstring空Plivo 外呼主叫号码必填plivo_server_portint9000HTTP API 与 WebSocket 共用端口plivo_public_server_urlstring空公网地址不含协议如your-domain.com:9000同时用于媒体流与 webhookplivo_use_httpsbooltruewebhook 是否走 HTTPSplivo_use_wssbooltrue媒体流是否走 WSSmessage_collector / weatherapi_tool_python / streamid_adapter分别负责消息收集transcript 透传、天气工具与音频帧流 id 适配。connections 的数据流解读图中的音频与数据流向非常清晰与extension.py中的转发逻辑相互印证streamid_adapter → sttpcm_frame用户语音帧进入 STTstt → main_controlasr_result识别文本交给主控扩展main_control → streamid_adapterpcm_frame主控扩展回传的帧经适配器转交 STT对应_forward_audio_to_ten中AudioFrame的dests设置见 extension.pytts → main_controlpcm_frameTTS 生成的语音帧进入主控扩展由on_audio_frame下发到每个活跃通话的 WebSocket。REST API 与 Webhook端点一览PlivoCallServer在同一端口9000上同时提供 REST API 与 WebSocket方法与路径说明POST /api/call创建新的外呼电话GET /api/calls列出所有活跃通话GET /api/call/{call_uuid}查询单个通话信息DELETE /api/call/{call_uuid}停止并删除通话调用 Plivocalls.delete挂断POST /webhook/answerPlivo 应答回调返回 XML启动双向媒体流POST /webhook/statusPlivo 状态回调更新通话状态GET /health健康检查返回status、active_calls、server_time另外还有两个辅助端点GET /api/config返回服务器配置、媒体流 URL 与 webhook URL依据plivo_public_server_url与协议开关动态拼接见 server.py独立配置服务器同样提供/health与/api/config。创建外呼curl -X POST http://localhost:9000/api/call \ -H Content-Type: application/json \ -d { phone_number: 1234567890, message: Hello from AI assistant! }响应示例来自 server.py{ success: true, call_uuid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, status: initiated, phone_number: 1234567890, message: Hello from AI assistant! }注意发起外呼时plivo_public_server_url必填否则接口返回 400见 server.py。查询通话信息curl http://localhost:9000/api/call/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx返回call_uuid、status、phone_number、message、created_at、ended_at等字段会话不存在时返回 404。列出所有通话curl http://localhost:9000/api/calls返回active_calls数量与callsuuid 列表。停止通话curl -X DELETE http://localhost:9000/api/call/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxWebSocket 媒体流协议/media端点接收 Plivo 推送的 JSON 消息server.py{event: start, start: {streamId: ..., callId: ...}, streamId: ...}媒体流开始注册通话会话并绑定 WebSocket随后触发问候语 TTS{event: media, media: {payload: base64 μ-law 音频, track: inbound}, streamId: ...}上行音频转发进 TEN 框架{event: stop}媒体流结束下行音频使用{event: playAudio, media: {contentType: audio/x-mulaw;rate8000, payload: base64}}消息格式extension.py。本地开发ngrok 隧道本地开发时直接运行仓库提供的脚本即可将本地 9000 端口暴露为公网./start-with-ngrok.sh该脚本start-with-ngrok.sh会检查 ngrok 是否安装、NGROK_AUTHTOKEN是否设置未设置仅告警以前台方式运行ngrok start --configngrok.yml --logstdout plivo-server启动支持 WebSocket 的隧道日志写入/tmp/ngrok.log。ngrok.ymlngrok.yml中的隧道定义为proto: http、addr: 9000、inspect: false并可配置自定义子域名。启动后把 ngrok 分配的公网域名填入PLIVO_PUBLIC_SERVER_URL环境变量即可完成联调闭环。发布为 Docker 镜像注意以下命令需要在任何 Docker 容器之外执行。构建镜像cd ai_agents docker build -f agents/examples/voice-assistant-sip-plivo/Dockerfile -t voice-assistant-sip-plivo-app .运行docker run --rm -it --env-file .env -p 9000:9000 -p 3000:3000 voice-assistant-sip-plivo-app访问前端http://localhost:3000API 服务器http://localhost:9000定制化替换 STT / LLM / TTS该语音助手采用模块化设计STT、LLM、TTS 模块都可以替换为其他服务商。通过 TMAN Designerhttp://localhost:49483即task run中的run-gd-server任务可视化编辑property.json中的图更换stt节点的addon与params、调整llm节点的模型与提示词、更换tts节点的音色与输出格式即可无需改动main_python扩展代码。与 Twilio 方案的关键差异该仓库还提供了 Twilio 版的 voice-assistant-sip-twilio 示例两者在协议层面对照如下方面TwilioPlivo认证Account SID Auth TokenAuth ID Auth TokenXML 响应TwiMLVoiceResponsePlivo XMLplivoxml.ResponseElement媒体流元素ConnectStreamStream bidirectionaltrue呼叫 IDcall_sidcall_uuid流 IDstreamSidstreamId音频格式μ-law 8kHzμ-law 8kHz相同进一步阅读示例 READMEvoice-assistant-sip-plivo/README.md呼叫服务器实现tenapp/ten_packages/extension/main_python/server.py扩展与音频桥接实现tenapp/ten_packages/extension/main_python/extension.py配置模型tenapp/ten_packages/extension/main_python/config.py独立配置服务器server/plivo_server.py图定义tenapp/property.json任务编排Taskfile.yml前端实现frontend/README.md其他 SIP 示例Twilio 版 voice-assistant-sip-twilio、Telnyx 版 voice-assistant-sip-telnyx赞分享人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载相关推荐基于 TEN-framework 构建支持 Telnyx SIP 入站/出站呼叫的实时语音助手基于 TEN framework 构建支持 Telnyx SIP 入站/出站呼叫的实时语音助手 本文是一份针对 TEN framework 开源仓库中 voic人工智能AI Agent多模态语音AI 应用TEN Framework Telnyx SIP 语音助手扩展main_python深度解析入站/出站通话与 STT → LLM → TTS 全链路实现TEN Framework Telnyx SIP 语音助手扩展main_python深度解析入站/出站通话与 STT → LLM → TTS 全链路实现人工智能AI Agent多模态语音AI 应用Cal.diy 与 Synthflow 语音 AI 集成指南用 AI 电话助手把入站通话变成实时预约Cal.diy 与 Synthflow 语音 AI 集成指南用 AI 电话助手把入站通话变成实时预约 本指南围绕 cal.diy 仓库中 Synthflow后端前端企业应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考