
人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载语音对话天然是瞬时的没有记忆的 Agent 每次会话都从零开始反复追问姓名、偏好和目标。本文以仓库中的 voice-assistant-with-PowerMem 示例为核心系统讲解如何在 TEN Framework 的语音 Agent 中接入 PowerMem 持久语义记忆——包括整体架构、检索与保存触发规则、配置参数以及main_python扩展的源码级实现。读完本文你将掌握用户画像个性化欢迎语 语义记忆注入 LLM 上下文 按轮次/空闲双机制落库的完整实战方案。为什么语音助手需要记忆语音对话天然是瞬时的。没有记忆每次会话都从零开始Agent 会反复询问基础信息姓名、偏好、目标。接入 PowerMem 后记忆让 Agent 能够跨会话保持连续性例如上次你说更喜欢简短回答不再重复提问基于已知偏好提供个性化体验解决含糊追问通过回忆此前上下文理解指代与隐含意图随时间积累偏好与事实不断沉淀体验越用越好。原文档的定位是讲清楚为什么要有记忆和记忆如何工作而非 API 参考细节本文延续这一主线并补充源码层面的佐证。架构概览PowerMem 插在控制层TEN 图负责把语音Agora RTC、ASR、LLM 和 TTS 串联起来PowerMem 则插在控制层负责记忆的检索与保存关键点main_python是整个 Agent 的编排者orchestrator。它决定何时检索记忆、如何把记忆注入 LLM 上下文以及何时把新对话保存回 PowerMem。图中的节点与连接关系可以在 tenapp/property.json 中看到完整定义agora_rtc、sttdeepgram_asr_python、llmopenai_llm2_python、ttselevenlabs_tts2_python、main_controlmain_python、message_collectormessage_collector2、weatherapi_tool_python与streamid_adapter共同构成voice_assistant预置图其中main_control作为asr_result数据流和on_user_joined/on_user_left/tool_register命令流的汇聚点。PowerMem 如何融入 TEN 工作流PowerMem 通过main_control扩展接入对应 extension.py 中的四个关键事件处理器触发时机行为源码位置用户加入on_user_joined从 PowerMem 获取用户画像生成个性化欢迎语_on_user_joinedextension.py#L128-L153ASR 最终结果on_asr_result用转写文本对 PowerMem 做语义检索把相关记忆注入 LLM 提示词_on_asr_resultextension.py#L163-L185LLM 最终响应on_llm_response按配置规则把新对话写入 PowerMem_on_llm_responseextension.py#L187-L256空闲超时 / 关闭on_stop保存尚未落库的对话_start_memory_idle_timer与on_stopextension.py#L261-L267所有这些行为都由 tenapp/property.json 中的powermem_config与enable_memorization驱动。从源码看记忆存储的初始化发生在on_init阶段extension.py#L88-L116当enable_memorization与powermem_config同时满足时根据enable_user_memory开关选择PowerMemSdkMemoryStore对应 PowerMem 的Memory还是PowerMemSdkUserMemoryStore对应 PowerMem 的UserMemory初始化失败时扩展会降级为无记忆模式继续运行而不是阻断整个 Agent。存储、检索与更新的数据是什么写入存储到 PowerMemmessages只保存 LLM 上下文中的 user/assistant 消息系统消息会被过滤。这一点在_memorize_conversationextension.py#L531-L569中有明确实现它直接从agent.llm_exec.get_context()读取上下文仅保留role in [user, assistant]且内容为字符串的消息user_id与agent_id用于按用户和按 Agent 隔离记忆写入时作为作用域参数传入memory_store.add()。读取从 PowerMem 检索相关记忆根据当前用户查询做语义检索_retrieve_related_memoryextension.py#L481-L529把检索结果格式化为Memorise:\n- ...列表文本用户画像用于欢迎语个性化来自UserMemory.profile()启用enable_user_memory时。PowerMemSdkUserMemoryStore.get_user_profilememory.py#L263-L309优先调用client.profile()若返回空则回退到以 User Profile 为查询词的语义搜索get_user_profile_by_query。更新随时间变化Agent 只负责追加新的对话轮次索引、向量化与排序全部由 PowerMem 内部处理Agent 侧不需要维护记忆的增量更新逻辑。单轮对话流程7 个步骤音频输入用户通过 Agora 频道说话ASRdeepgram_asr_python产出最终转写文本final transcript记忆检索main_python用转写文本查询 PowerMem 语义检索提示词增强相关记忆与用户问题一起注入 LLM 提示词LLM 响应LLM 在记忆感知的上下文中生成回答TTS 输出elevenlabs_tts2_python合成语音经 Agora 回传记忆保存按轮次或空闲超时规则把本轮对话写入 PowerMem。其中第 4 步的提示词增强在_on_asr_result中实现检索到相关记忆时用CONTEXT_MESSAGE_WITH_MEMORY_TEMPLATE拼装上下文消息再queue_llm_input否则直接透传用户文本。模板定义在 prompt.pyHeres what I remember from our past conversations that might be relevant: {related_memory} Now the user is asking: {user_query} Please respond naturally, as if youre continuing our conversation. Reference the memories when relevant, but keep it conversational and helpful.记忆生命周期与保存规则Agent 使用两个协同的保存触发器避免重复保存按轮次保存turn-based每memory_save_interval_turns轮保存一次默认 5空闲保存idle空闲memory_idle_timeout_seconds秒后保存默认 30 秒。伪流程原文档简化版on_final_llm_response: if turns_since_last_save interval: save_to_powermem() cancel_idle_timer() else: start_or_reset_idle_timer() on_idle_timeout: if unsaved_turns: save_to_powermem()源码实现比伪流程更细致值得展开轮次判定extension.py#L232-L248在 LLM 最终响应到达时用turn_id - last_memory_update_turn_id memory_save_interval_turns判定。触发保存时先更新计数器再异步创建保存任务asyncio.create_task(self._memorize_conversation())注释明确说明这是为了防止并发响应到达时触发多个保存任务产生竞态保存不阻塞 LLM 响应处理同时取消空闲定时器。空闲定时器extension.py#L372-L418asyncio.sleep(timeout_seconds)到期后检查turn_id last_memory_update_turn_id且未停止才执行保存任务被取消例如用户开始新一轮对话、轮次保存已触发、或扩展停止时不保存。定时器对当前任务引用做了比较避免旧任务清理新任务的竞态。关闭兜底extension.py#L261-L267on_stop中先取消空闲定时器、停止 Agent再调用一次_memorize_conversation()保证最后未落库的对话被保存。记忆如何随时间改变行为跨多个会话之后Agent 可以做到个性化欢迎欢迎回来你仍然喜欢简短回答吗——对应_generate_personalized_greetingextension.py#L420-L479获取用户画像摘要后用PERSONALIZED_GREETING_TEMPLATE构造提示词交给 LLM 生成 23 句欢迎语10 秒超时兜底回退到默认欢迎语推断意图你上周问过徒步路线这里有新的推荐——语义检索把历史任务带入当前上下文保持一致语气与工具使用习惯记忆用户反馈并在每次响应前注入。这一切之所以发生是因为相关记忆在每次响应前被注入 LLM 上下文。欢迎语模板同样位于 prompt.py它还会根据记忆中的用户地区信息用该地区最常用的语言生成欢迎语。main_control 配置详解原文档给出了main_control的注释配置{ name: main_control, addon: main_python, property: { 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: { ...: OceanBase/SeekDB settings }, llm: { ...: LLM for memory processing }, embedder: { ...: Embedding model for search } } } }仓库中真实的 tenapp/property.json 给出了main_control的完整配置含greeting与powermem_config的三段式细节。各字段的语义与默认值可在 config.pyPydantic 模型MainControlConfig与 manifest.json属性 schema 声明中交叉印证字段类型默认值说明greetingstringHello! Im your AI assistant with memory...默认欢迎语个性化欢迎语生成失败或没有记忆时回退使用user_idstringuser记忆作用域按人隔离agent_idstringvoice_assistant_agent记忆作用域按助手人格隔离enable_memorizationbooltrue总开关关闭后不初始化记忆存储enable_user_memorybooltruetrue用UserMemory含profile()画像false用Memorymemory_save_interval_turnsint325每 N 轮对话保存一次记忆memory_idle_timeout_secondsfloat6430.0空闲 N 秒后保存未落库对话powermem_configdict{}向量库、LLM、Embedding 三段配置配置提示原文档要点为每位真实用户设置不同的user_id可隔离每个人的记忆为不同助手人格设置不同的agent_id可隔离每个助手的记忆。powermem_config在 tenapp/property.json 中的真实形态如下全部通过环境变量注入支持${env:VAR}语法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} } } }环境变量与 PowerMem 配置.env在.env文件中设置以下环境变量原文档完整清单# Database DATABASE_PROVIDERoceanbase OCEANBASE_HOST127.0.0.1 OCEANBASE_PORT2881 OCEANBASE_USERroot OCEANBASE_PASSWORDpassword OCEANBASE_DATABASEoceanbase OCEANBASE_COLLECTIONmemories # LLM Provider (for PowerMem) LLM_PROVIDERqwen LLM_API_KEYyour_qwen_api_key LLM_MODELqwen-plus # Embedding Provider (for PowerMem) EMBEDDING_PROVIDERqwen EMBEDDING_API_KEYyour_qwen_api_key EMBEDDING_MODELtext-embedding-v4 EMBEDDING_DIMS1536需要说明的是数据库部分对应powermem_config.vector_storePowerMem 使用 OceanBase兼容 SeekDB作为向量库OCEANBASE_COLLECTION对应集合名默认memoriesOCEANBASE_DATABASE对应数据库名LLM 部分对应powermem_config.llm负责记忆的处理与摘要生成示例使用通义千问qwen-plusEmbedding 部分对应powermem_config.embedder负责把记忆文本向量化以支持语义检索示例使用text-embedding-v4EMBEDDING_DIMS1536需与所选模型输出维度一致注意区分两套密钥LLM_*供 PowerMem 记忆处理使用而对话 LLMopenai_llm2_python使用的是OPENAI_API_KEY/OPENAI_MODEL两者相互独立。快速开始1. 启动 SeekDB 服务OceanBase 向量库docker run -d \ --name seekdb \ -p 2881:2881 \ -p 2886:2886 \ -v ./data:/var/lib/oceanbase \ -e SEEKDB_DATABASEpowermem \ -e ROOT_PASSWORDpassword \ oceanbase/seekdb:latest2. 安装依赖task installtask install由 Taskfile.yml 定义它依次执行tman install安装 tenapp 依赖、./scripts/install_python_deps.sh安装 Python 扩展依赖、bun install安装前端依赖位于 playground以及 Go API Server 的构建go mod tidy go mod download go build -o bin/api main.go源码在 server。Taskfile 通过dotenv: [../../../.env]自动加载仓库根目录附近的.env文件。3. 运行集成 PowerMem 的语音助手task runtask run会并行拉起三个进程tman designerTMAN Designer 服务、bun run dev前端、./bin/api -tenapp_dir.../tenappAPI Server。4. 访问应用Frontend前端http://localhost:3000API Serverhttp://localhost:8080TMAN Designerhttp://localhost:49483关键文件索引tenapp/property.json — 图graph配置与 PowerMem 配置入口tenapp/ten_packages/extension/main_python/extension.py — 记忆检索与保存的核心逻辑tenapp/ten_packages/extension/main_python/memory.py — PowerMem 存储适配层MemoryStore抽象 PowerMemSdkMemoryStore/PowerMemSdkUserMemoryStore两个实现tenapp/ten_packages/extension/main_python/prompt.py — 记忆注入与欢迎语生成的提示词模板tenapp/ten_packages/extension/main_python/config.py —MainControlConfig配置模型字段默认值tenapp/ten_packages/extension/main_python/manifest.json — 扩展属性 schema 声明tenapp/ten_packages/extension/main_python/agent/agent.py — Agent 事件队列与 LLM 编排LLMExec上下文管理README.zh-CN.md — 本示例的中文版文档小结PowerMem 为语音 Agent 提供的不是简单的聊天记录而是一套检索增强的记忆系统main_python在 ASR 最终结果到达时做语义检索并把相关记忆注入 LLM 上下文在 LLM 响应后按轮次/空闲双机制异步落库在用户加入时基于画像生成个性化欢迎语并在关闭时兜底保存。理解这套编排层决定何时读写、存储层负责索引与排序的分工是把它迁移到自己的 TEN 语音 Agent 场景不同 STT/TTS/LLM 组合、多用户隔离、多助手人格的关键。赞分享人工智能AI Agent多模态语音AI 应用【免费下载链接】ten-frameworkOpen-source framework for conversational voice AI agents项目地址https://gitcode.com/TEN-framework/ten-framework点击查看免费下载相关推荐MINIX入门教程10个核心概念带你快速掌握微内核设计精髓MINIX入门教程10个核心概念带你快速掌握微内核设计精髓 欢迎来到MINIX微内核操作系统入门指南MINIX是一个经典的微内核操作系统由Andrew SMicrosoft Agent Framework 如何用 FileMemoryProvider 实现跨会话记忆Microsoft Agent Framework 如何用 FileMemoryProvider 实现跨会话记忆 你遇到的问题是用 Microsoft Ag人工智能AI Agent多智能体Agent 工作流ADK 跨会话记忆实战基于 Vertex AI Memory Bank 的 Agent 长期记忆实现与双目标部署ADK 跨会话记忆实战基于 Vertex AI Memory Bank 的 Agent 长期记忆实现与双目标部署 本指南以 core/python/cross示例工程上一篇GBrain 演进全览从 v0.1.0 到 v0.51.0.0 的版本脉络、核心能力与升级实践指南下一篇domain-driven-hexagon快速上手指南10分钟用NestJS跑通DDD六边形架构项目创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考