TEN-framework X OceanBase PowerMem 打造个性化智能体语音助手
本教程介绍如何通过 OceanBase PowerMem 结合 TEN-framework 打造一款带记忆的智能体语音助手。在集成了 TEN 强大的“实时多模态”能力基础上,还展现了“个性化”对话体验与长期记忆感知的独特优势。
有关 OceanBase PowerMem 的详细信息,可参考 GitHub - oceanbase/powermem。
为什么需要记忆?
Agent 需要记忆能力,是因为记忆是实现个性化、连续性互动和深度共情的核心基础。没有记忆,这些 Agent 就像“金鱼记忆”一样,每次交互都从零开始,无法建立真正有意义的关系或提供高效服务。
维持对话的连贯性和上下文理解
问题:如果 Agent 不记得用户之前说过什么,每次对话都会显得割裂、重复甚至令人沮丧。 例子:
- 用户:“我最近压力很大,工作快撑不住了。”
- 几天后再次说:“还是老样子,项目没结束。”
- 如果 Agent 记得之前的对话,可以说:“上次你说项目压力大,现在还在持续吗?有没有好一点?”
- 如果没有记忆,Agent 可能会问:“你最近有什么压力?”——显得冷漠且重复。
记忆让对话有延续感,像是“真正关心你的人”。
建立情感连接与信任
情感陪伴的本质是“被理解”和“被记住”。人类在关系中重视“对方记得我的事”。
心理学研究表明:被记住细节(如喜好、经历、情绪)会显著增强亲密感和信任。 例子:
- “你上次说你喜欢喝抹茶拿铁,今天要不要来点轻松的话题放松一下?”
- 这种细节回忆会让用户感到被关注,提升情感价值。
记忆 = 被重视的信号 → 增强用户依恋和使用黏性。
实现个性化服务与预测需求
助手类 Agent 需要根据用户习惯主动提供帮助。 例子:
- 用户每周五晚上都会问:“明天天气怎么样?”
- 有记忆的 Agent 可以主动提醒:“周五快到了,需要我帮你查周末天气吗?”
- 或者记住用户讨厌会议太多,自动建议:“下周日程太满,要我帮你调整吗?”
记忆让 Agent 从“被动响应”升级为“主动关怀”。
避免重复提问,提升用户体验
没有记忆的 Agent 会反复问相同问题(如“你叫什么名字?”“你住哪里?”),让人烦躁。 有长期记忆的 Agent 可以:
- 记住用户的姓名、偏好、重要事件(生日、纪念日)
- 在合适时机表达关心:“明天是你生日,准备怎么庆祝?”
减少认知负担,让用户感觉更自然、更人性化。
支持长期目标追踪与成长陪伴
情感陪伴或健康类助手常涉及长期目标(如减压、戒烟、学习)。 记忆能力可用来:
- 跟踪进展:“这周你记录了3次情绪低落,比上周少了2次,有进步!”
- 提供鼓励:“你说过想坚持写日记,今天写了吗?”
形成“成长伙伴”角色,而非一次性工具。
集成 OceanBase PowerMem:我们做了什么?
用户画像记忆模块(User Memory Module)
在 OceanBase PowerMem v0.2.0 版本中,我们全新推出了 用户画像记忆模块(User Memory Module),迈出构建更智能、更个性化的智能体助手的关键一步。用户画像记忆模块能够自动分析用户对话内容,提取并持久化用户画像(User Profile)。
**用户画像:**描述用户的当前状态与特征,包括使用偏好、角色身份、操作习惯、业务需求等关键属性,支持动态更新与长期存储,实现“记住你是谁”。
能力价值
通过引入用户画像记忆,Agent 实现了从“无状态响应”到“有记忆服务”的跃迁,具备以下能力升级:
- 上下文感知的智能理解:结合历史画像与行为轨迹,更准确识别用户真实意图;
- 个性化推荐与主动服务:基于用户习惯,智能推荐常用命令、优化建议或高频功能入口;
- 跨会话连续性体验:打破“每次对话从零开始”的局限,实现多轮次、跨时间的连贯交互;
- 支撑高阶智能场景:为后续的智能运维、自助诊断、个性化 SQL 优化等高级功能提供数据基础,助力打造真正懂用户的数据库助手。
智能记忆保存策略
为保障性能与一致性,我们设计了高效协调的记忆持久化机制:
| 策略 | 规则 | 可配置 项 |
|---|---|---|
| 基于对话轮次 | 每 N 轮对话后自动触发保存 | memory_save_interval_turns(默认 5) |
| 基于空闲超时 | 连续 N 秒无交互后自动保存 | memory_idle_timeout_seconds(默认 30) |
两种策略协同工作,通过去重判断避免重复写入;同时采用计数器同步机制,防止并发更新导致的竞态条件,确保数据一致性与系统稳定性。
个性化问候生成
为了让用户感受到“被记住”的温暖体验,我们在首次加入时引入了 个性化欢迎问候 功能,让每一次接入都更有温度。
工作流程
- 获取记忆摘要:从 PowerMem 中检索用户的历史对话概要;
- 生成定制问候:将记忆信息填入提示词模板,调用 LLM 生成 2–3 句自然语言问候语;
- 多语言适配:根据用户地区信息自动选择对应语言(如中文、英文等);
- 语音输出:生成完成后推送至 TTS 引擎进行播报。
技术亮点
- 异 步非阻塞:全程异步处理,不影响用户正常接入流程。
- 10 秒超时保护:防止 LLM 响应延迟影响整体体验。
- 状态隔离机制:使用独立标志位,避免与常规对话混淆。
- 优雅降级:当无历史记忆或生成失败时,自动回退至通用欢迎语,保障可用性。
快速上手
准备工作
-
登录 https://console.agora.io/ 创建 project 获取
App ID和Primary Certificate。提示agora 会提供一定免费额度,超过用量可能产生费用,请在继续前,访问其官网或查阅相关文档,确认并接受其收费标准。如不同意,请勿继续操作。
-
准备好 openai 兼容的模型服务 API KEY。
提示openai 兼容的模型服务 API KEY 需要您跳转至第三方平台完成。此操作将遵循第三方平台的收费规则,并可能产生相应费用。请在继续前,访问其官网或查阅相关文档,确认并接受其收费标准。如不同意,请勿继续操作。
-
安装 seekdb 服务器模式,有关 seekdb 服务器模式的部署,请参见 通过 yum install 部署 seekdb。
-
已安装完成 Docker。
-
Docker build 可能会超时,请提前配置好 Docker 国内镜像或者代理。
部署服务
-
克隆仓库 ten-framework 。
git clone https://github.com/TEN-framework/ten-framework
cd ten-framework/ai_agents/
cp .env.example .env -
在
.env文件中,修改相关的环境变量(以 Agora + QWen 配置为例):vim .env需要修改及新增的变量如下:
# ============================================================= #
# 以下为需要修改的变量
# ============================================================= #
# Agora
# 登录 https://console.agora.io/ 创建 project 获取
AGORA_APP_ID={需要填写}
AGORA_APP_CERTIFICATE={需要填写}
# LLM
# 此处以百炼举例,可以用任何兼容 openai 的大模型服务
OPENAI_API_BASE=https://dashscope.aliyuncs.com/compatible-mode/v1
OPENAI_API_KEY={需要填写}
OPENAI_MODEL=qwen3-max
# ============================================================= #
# 以下为新增的变量
# ============================================================= #
# Database
DATABASE_PROVIDER=oceanbase
OCEANBASE_HOST=127.0.0.1
OCEANBASE_PORT=2881
OCEANBASE_USER=root
OCEANBASE_PASSWORD=
OCEANBASE_DATABASE=test
OCEANBASE_COLLECTION=memories
# LLM Provider (for PowerMem)
LLM_PROVIDER=qwen
LLM_API_KEY={需要填写}
LLM_MODEL=qwen3-max
# Embedding Provider (for PowerMem)
EMBEDDING_PROVIDER=qwen
EMBEDDING_API_KEY={需要填写}
EMBEDDING_MODEL=text-embedding-v4
EMBEDDING_DIMS=1536 -
修改
property.json。rm -rf agents/examples/voice-assistant-with-PowerMem/tenapp/property.json
vi agents/examples/voice-assistant-with-PowerMem/tenapp/property.json将以下内容粘贴进去:
{
"ten": {
"predefined_graphs": [
{
"name": "voice_assistant",
"auto_start": true,
"graph": {
"nodes": [
{
"type": "extension",
"name": "agora_rtc",
"addon": "agora_rtc",
"extension_group": "default",
"property": {
"app_id": "${env:AGORA_APP_ID}",
"app_certificate": "${env:AGORA_APP_CERTIFICATE|}",
"channel": "ten_agent_test",
"stream_id": 1234,
"remote_stream_id": 123,
"subscribe_audio": true,
"publish_audio": true,
"publish_data": true,
"enable_agora_asr": false,
"agora_asr_vendor_name": "microsoft",
"agora_asr_language": "en-US",
"agora_asr_vendor_key": "${env:AZURE_STT_KEY|}",
"agora_asr_vendor_region": "${env:AZURE_STT_REGION|}",
"agora_asr_session_control_file_path": "session_control.conf"
}
},
{
"type": "extension",
"name": "stt",
"addon": "aliyun_asr_bigmodel_python",
"extension_group": "stt",
"property": {
"params": {
"api_key": "${env:OPENAI_API_KEY|}",
"language": "zh-CN",
"language_hints": [
"zh"
]
}
}
},
{
"type": "extension",
"name": "llm",
"addon": "openai_llm2_python",
"extension_group": "chatgpt",
"property": {
"base_url": "${env:OPENAI_API_BASE}",
"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?",
"max_memory_length": 10
}
},
{
"type": "extension",
"name": "tts",
"addon": "cosy_tts_python",
"extension_group": "tts",
"property": {
"params": {
"api_key": "${env:OPENAI_API_KEY|}",
"model": "cosyvoice-v3-plus",
"sample_rate": 16000,
"voice": "longanyang"
}
}
},
{
"type": "extension",
"name": "main_control",
"addon": "main_python",
"extension_group": "control",
"property": {
"greeting": "Hello! I'm your AI assistant with memory. I can remember our previous conversations to provide more personalized help.",
"agent_id": "voice_assistant_agent",
"user_id": "user",
"enable_memorization": true,
"enable_user_memory": true,
"memory_save_interval_turns": 5,
"memory_idle_timeout_seconds": 30.0,
"powermem_config": {
"vector_store": {
"provider": "oceanbase",
"config": {
"collection_name": "${env:OCEANBASE_COLLECTION}",
"host": "${env:OCEANBASE_HOST}",
"port": "${env:OCEANBASE_PORT}",
"user": "${env:OCEANBASE_USER}",
"password": "${env:OCEANBASE_PASSWORD}",
"db_name": "${env:OCEANBASE_DATABASE}"
}
},
"llm": {
"provider": "${env:LLM_PROVIDER}",
"config": {
"api_key": "${env:LLM_API_KEY}",
"model": "${env:LLM_MODEL}"
}
},
"embedder": {
"provider": "${env:EMBEDDING_PROVIDER}",
"config": {
"api_key": "${env:EMBEDDING_API_KEY}",
"model": "${env:EMBEDDING_MODEL}",
"embedding_dims": "${env:EMBEDDING_DIMS}"
}
}
}
}
},
{
"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": "main_control",
"cmd": [
{
"names": [
"on_user_joined",
"on_user_left"
],
"source": [
{
"extension": "agora_rtc"
}
]
},
{
"names": [
"tool_register"
],
"source": [
{
"extension": "weatherapi_tool_python"
}
]
}
],
"data": [
{
"name": "asr_result",
"source": [
{
"extension": "stt"
}
]
}
]
},
{
"extension": "agora_rtc",
"audio_frame": [
{
"name": "pcm_frame",
"dest": [
{
"extension": "streamid_adapter"
}
]
},
{
"name": "pcm_frame",
"source": [
{
"extension": "tts"
}
]
}
],
"data": [
{
"name": "data",
"source": [
{
"extension": "message_collector"
}
]
}
]
},
{
"extension": "streamid_adapter",
"audio_frame": [
{
"name": "pcm_frame",
"dest": [
{
"extension": "stt"
}
]
}
]
}
]
}
}
],
"log": {
"handlers": [
{
"matchers": [
{
"level": "info"
}
],
"formatter": {
"type": "plain",
"colored": true
},
"emitter": {
"type": "console",
"config": {
"stream": "stdout"
}
}
}
]
}
}
} -
构建容器。
修改
property.json后,构建容器。# 构建镜像,如无变更只需要构建一次
docker build -f agents/examples/voice-assistant-with-PowerMem/Dockerfile -t voice-assistant-with-powermem:latest . -
启动容器。
# 启动容器
docker run -it --env-file .env -p 3000:3000 voice-assistant-with-powermem:latest -
与 Agent 语音沟通。
等待启动完成,即可在浏览器中打开
http://127.0.0.1:3000,如 果使用远程服务器则访问对应的 3000 端口的 http 服务即可,可以看到如下页面,点击右上角Select Graph选择voice_assistent,并点击Connent,即可与 Agent 语音沟通了。提示与 Agent 语音沟通需要授予麦克风权限。

总结
记忆,让 AI 从"工具"到"伙伴"的跨越。
我们常把 AI 助手看作信息查询工具,但真正的智能体不应止于“回答问题”,而应致力于“理解人”。实现这一点的核心转折,正是记忆——它让交互脱离原子化的片段,开始具备时间的维度与情感的深度。
本次将 OceanBase PowerMem 融入 TEN-framework 的实践,本质上是一次对“AI 人格化”的探 索。我们不再追求一个完美但冰冷的应答机器,而是尝试构建一个能感知用户轨迹、积累认知、并据此演化行为的服务主体。
这一转变带来的不仅是体验升级,更是范式迁移:
- 从响应到共鸣:记忆使语言不再是即时刺激的反射,而是历史经验的回响;
- 从通用到专属:同一个助手,在不同用户面前逐渐长成不同的“性格”;
- 从孤立任务到持续陪伴:服务目标从“完成这一次对话”转向“支持你长期的成长或需求”。
更重要的是,这套机制的设计为未来留出了演进空间——当记忆可存储、可检索、可推理时,AI 就有了自我修正和主动建模用户的能力基础。今天的个性化问候只是起点,明天可能是一个会提醒你情绪波动趋势、预判操作意图、甚至在你未言明时已准备妥当的伙伴。
因此,这项工作的意义不在于“加了个记忆模块”,而在于确立了一个原则:
智能体的价值,不在于它知道多少,而在于它为你记住了多少。
这不仅改变了人机关系的本质,也为下一代 AI 系统定义了新的衡量标准——不是准确率多高,而是是否“值得被依赖”。