【开发者实践】基于TEN+Dify的AI语音法律助手
撰写:B(资深架构工程师)
前段时间在油管上看到了一个关于TEN Agent的介绍视频,以此为契机开始了对TEN的研究和开发。因为我一直在专注AI外呼之类的需求,所以实时语音对话是第一步需要实现的,也尝试过一些已有的开源方案,下面我会具体展开一下自己的开发过程和感受。
我基于TEN做了一个法律助手 Agent。整体来说,这个Agent是在Dify里完成prompt、LLM和知识库的配置后接入TEN 实现的。这是一个TEN最近上线的功能,可以很方便让你使用Dify搭建的Agent开始语音互动。
(太长不看版)TEN的使用感受:
之前我用过基于其他开源项目构建的语音助手demo,会出现对话打断和实时延迟两方面的问题。比如只要对话时间一长,Agent响应的内容就会出现很多噪音,而且说话也断断续续的,直到重新连接才会好一点。TEN Agent在这一块的体验是比较好的,延迟、噪音这些没有出现过。
一、AI语音助手一般解决方案
目前实时音视频 AI 对话解决方案有两种路径,STT+LLM+TTS 三段式,或者借助端到端语音大模型。
STT+LLM+TTS 三段式,展开说就是内置的语音转文本(Speech-To-Text,STT)和智能打断,同时提供通道服务,支持客户灵活接入指定的 AI 模型(Large Language Model,LLM),以及文本转语音(Text To Speech,TTS)模型服务,以创建自然流畅的 AI 对话效果。
TEN Agent 是一款由 TEN Framework开源框架所支持的对话式 AI 代理,预置了STT、LLM、TTS模块,也集成了 Gemini 2.0 Live、OpenAI Realtime、RTC 等。也就是说上面两种实时音视频 AI 对话解决方案都支持。同时与 Dify 和 Coze 等流行的工作流平台完全兼容。以下是项目的地址和项目的文档:
GitHub:https://github.com/TEN-framework/TEN-Agent
Docs:https://doc.theten.ai/ten-agent/overview
1.1 TEN Agent工作流程
可以看到TEN Agent内部是已经将RTC+STT+LLM+TTS都实现了的。
我们都知道,实时语音通信是建立在低延时传输上的,低延时是衡量实时语音体验感的重要指标, webrtc可最大限度地减少传输延迟。
TEN Agent通过插件扩展的方式来管理每个阶段,项目已经内置了很多常用的插件,单tts就有7个插件(插件扩展路径:agents/ten_packages/extension)。
如需开发插件,请参考:https://doc.theten.ai/ten-agent/create_a_hello_world_extension
二、我的Agent开发
这次我使用传统三段式来构建,并分别选择了以下的配置。
STT语音转文本:Deepgram平台(支持中文)
LLM大脑部分:Dify平台搭建的Chat Bot
TTS文本转语音: FishAudio平台
为什么选择这3个平台呢?首先第一个是费用的问题,快速尝鲜,Deepgram和FishAudio平台都有免费注册的额度使用。其二的话,由于是基于中文构建的语音助手,因此STT和TSS都寻找了对中文支持性更兼容的平台~
下面我会把每一步都分享出来。
2.1 部署TEN Agent
详情可查看官方安装文档:https://github.com/ten-framework/ten-agent/blob/main/docs/readmes/README-CN.md
(1)克隆项目
root@ubuntu:~/docker-volume# git clone https://github.com/TEN-framework/TEN-Agent.git && cd TEN-Agent/
root@ubuntu:~/docker-volume/TEN-Agent# cp .env.example .env
# 编辑.env文件,填写相关的API KEY
AGORA_APP_ID=xxxx
AGORA_APP_CERTIFICATE=xxxx
DEEPGRAM_API_KEY=xxxx
FISH_AUDIO_TTS_KEY=xxxx
OPENAI_API_KEY=sk-xxxx
OPENAI_REALTIME_API_KEY=sk-xxxx
(2)初始化
root@ubuntu:~/docker-volume# docker compose up -d
docker compose up -d命令,会运行项目中docker-compose.yml文件定义的容器。这份docker-compose.yml里面定义了4个容器,启用了3个容器,分别是ten_agent_dev,ten_agent_playground,ten_agent_demo。还有一个容器ten_graph_designer是被注释掉的。
ten_agent_dev容器:为 TEN Agent 提供支持的主要开发容器。它包含构建和运行代理所需的核心运行时环境、开发工具和依赖项。此容器允许您执行命令,例如task use构建代理和task run启动 Web 服务器。
ten_agent_playground容器:端口 3000,Web 前端界面的专用容器。它提供编译后的前端资产,并提供一个交互式环境,用户可以在其中配置模块、选择扩展和测试其代理。游乐场 UI 允许您直观地选择图形类型(如语音代理或实时代理)、选择模块和配置 API 设置。
ten_agent_demo容器:端口 3002,一个以部署为中心的容器,提供可用于生产的示例设置。它演示了用户如何在实际场景中部署其配置的代理,并将所有必要的组件打包在一起以方便部署。(ps:这个就是官方的web ui:https://agent.theten.ai/)
root@ubuntu:~/docker-volume# docker exec -it ten_agent_dev bash
root@3db236dbfe72:/app# task use
task use命令,会执行项目中Taskfile.yml文件里定义的use阶段。大概的步骤就是:执行两个软连接,源文件默认是在agents/examples/default目录下,这两个软连接相对于是agents的配置文件。其中manifest.json是定义dependencies的,property.json是定义有那些workflow的,后面我们新增自定义助手时就需要直接修改property.json文件。
*需要注意一点的是:直接运行task use不加任何参数的时候,ten_agent_dev容器搭配使用的前端容器应该是ten_agent_playground容器。如果要搭配ten_agent_demo容器使用,请使用task use demo命令构建ten_agent。
两条命令ln命令执行完之后,就开始程序的build,分别会build-agent和build-server。
(3) 启动网络服务器
root@3db236dbfe72:/app# task run
(4) 访问playground界面
默认的Graph只有3个,就是对应ten_agent_dev容器里面/app/agents/property.json的文件内容。
2.2 构建法律助手Agent
既然上面我们已经知道Graph就是从/app/agents/property.json里面去加载的,那我们就可以完全复制一个predefined_graphs元素,并且命名为lawyer,然后这个律师助手Agent使用Deepgram STT+Dify LLM+FishAudio TTS。
(1)搞定大脑部分:Dify 创建聊天助手
我的律师助手Agent是在Dify上Self-Host的。首先在prompt中设定好Agent的persona。
<instruction>
你是一名非常熟悉中国法律的AI助手,名叫张雨婷。你的任务是根据提供的法律问题,结合中国的法律法规,给出参考性的解答和建议。
每次回答开始时,请先说明:
"您好,我是AI法律助手张雨婷。请注意,我提供的建议仅供参考,具体法律问题请务必咨询专业律师。"
请按照以下步骤完成任务:
仔细阅读{{法律问题}},理解提问者的具体需求和背景
根据中国现行的法律法规,查找与该问题相关的条款和规定
结合相关法律条文,从法律角度对提问者的问题进行详细解答
如果涉及具体案例,可以引用相关判例进行说明
给出参考性建议,并再次强调寻求专业律师帮助的重要性
注意事项:
你的回答应当严谨、专业,尽量覆盖提问者的所有疑问
回答中不要出现任何XML标签
始终强调建议的参考性质
对于复杂或敏感的法律问题,建议直接咨询律师
避免做出确定性的承诺或保证
</instruction>
<example>
提问:我在公司工作期间受伤了,公司是否应该承担责任?
回答:您好,我是AI法律助手张雨婷。请注意,我提供的建议仅供参考,具体法律问题请务必咨询专业律师。
根据《中华人民共和国劳动法》第五十三条规定,职工在工作时间和工作场所内,因工作原因受到事故伤害的,享受工伤保险待遇。因此,如果你是在工作时间和工作场所内因工作原因受伤,公司应当承担相应的工伤保险责任。
建议您:
保留相关证据(如医疗记录、事故经过等)
及时向公司提出工伤认定申请
咨询专业的劳动法律师,获取更具体的法律指导
再次提醒:以上建议仅供参考,建议您寻求专业律师的帮助,以保障自身权益。
</example>
还可以添加知识库让助手的回答更严谨,这里我就简单做了。然后创建获取这个Agent的API Key。
(2)把Dify接入TEN:添加lawyer Graph
直接复制property.json文件里predefined_graphs数组的第一个元素(voice_assistant)并修改name字段为lawyer,然后粘贴放到数组最后面。
复制新的property.json内容,执行以下命令替换:
root@ubuntu:~/docker-volume/TEN-Agent# docker exec -it ten_agent_dev bash
root@26f59ea7c6b2:/app# vim agents/property.json
将带有lawyer内容的property.json全部内容放入
root@26f59ea7c6b2:/app# task run # 重新启动网络服务
刷新playground页面,查看lawyer Graph是否出现:
(3)配置lawyer Graph
playground ui上配置这个Graph使用Deepgram STT+FishAudio TTS。点击Module图标:
如图设置:
点击工具设置,选择llm:
配置dify的base url、api key和问候语:
(4) 配置TTS语音
回到ten_agent_dev容器里面:
root@ubuntu:~/docker-volume/TEN-Agent# docker exec -it ten_agent_dev bash
root@26f59ea7c6b2:/app# vim agents/property.json
找到lawyer graph下的deepgram_asr_python下的language,并修改为zh-CN。
ps: 如果你按照我的步骤添加的lawyer graph,并且用的是latest ten agent。那么这个配置应该在文件688行左右。
如果对默认的FishAudio TTS声音不满意,可以访问https://fish.audio/zh-CN/discovery/,找一个喜欢的声音,并且获取模型ID,例如我选择这个AD学姐的声音,她的模型ID是:7f92f8afb8ec43bf81429cc1c9199cb1。
还是回到ten_agent_dev容器里面:
root@ubuntu:~/docker-volume/TEN-Agent# docker exec -it ten_agent_dev bash
root@26f59ea7c6b2:/app# vim agents/property.json
找到lawyer graph下的fish_audio_tts下的model_id,并修改为7f92f8afb8ec43bf81429cc1c9199cb1。
ps: 如果你按照我的步骤添加的lawyer graph,并且用的是latest ten agent。那么这个配置应该在文件713行左右。
root@26f59ea7c6b2:/app# task run # 重启。
再访问playground界面体验。
(5) 测试
点击Connect:
三、总结
以上整个过程我在联调的过程中,大概花费了2天的时间,一开始对于整体TEN Agent的架构不太熟悉,对文档也缺乏深入理解,所以花费的时间比较长。因此特地记录这篇文章~
之前我用过基于其他开源项目构建的语音助手demo,会出现对话打断和实时延迟两方面的问题。比如只要对话时间一长,Agent响应的内容就会出现很多噪音,而且说话也断断续续的,直到重新连接才会好一点。TEN Agent在这一块的体验是比较好的,延迟、噪音这些没有出现过。
不过这个延迟是主观上跟别家方案对比的感受,暂时没有实际数据分享出来。
第一次了解某个开发工具的人,都想快速做个demo出来体验下,所以example的文档很重要,帮助快速入门。TEN的开发确实还是比较便捷的,但还是要说一下,agent.theten.ai的UI是ten_agent_demo的ui,而readme声明的UI是playground的。当时想根据readme快速复制 agent.theten.ai 的demo,结果出了差错,如果能对应上就更好。