Phase 4:补齐通用记忆闭环(验收 9/9 通过)
按 P1-Pipecat Flows Agent化与记忆改造交接.md 的 Phase 4 完成。 新增 p1/phase4_acceptance.py:跑真实服务端验 7 条,每条之间查数据库。 实测结果(2026-09-16) 1. "记住我不吃香菜" → confirmed 落库 ✅ 2. **新连接** "我不吃什么?" → "你不吃香菜。" ✅ 连接开始时加载档案生效 3. "我今天吃了香菜" → 不新增 confirmed,模型还追问了是否口味变了 ✅ 4. "其实我现在吃香菜了" → 同键仍只一条 confirmed,值已更新 ✅ 5. "忘掉我的饮食偏好" → 已删除 ✅ 6/7. 访客与跨用户隔离 → 由单测覆盖(客户端不支持切身份) 实现:会话开始时加载稳定档案 - load_stable_memories():取已确认、未过期记忆(身份未确认返回空) - _conversation_node 改用 build_system_prompt,与 legacy 共用同一套 人格与记忆注入格式;记忆进**同一条** system 消息,仍不用 role_message 修掉一个真实缺陷:Flows 路径误用了语音的 max_tokens - 症状:一句"忘掉我的饮食偏好",服务端日志 "Failed to parse function call arguments: {"query": "饮食"(JSON 被截断), 回复为空、记忆没删掉,且**没有任何报错** - 根因:Flows 路径沿用了语音的 max_tokens=200(为"回复要短"而设)。 原始 API 对照实测:max_tokens=200 时模型 finish=stop、根本不调工具; 600 时正常产生 tool_calls 且参数 JSON 完整 - 修法:新增 AgentConfig.max_tokens(AI_AGENT_MAX_TOKENS,默认 600), Flows 路径用它,语音路径仍用 200 新增 client/test_client.py 能力(为验收所需) - RTVIReplies:收服务端 RTVI 文本消息(bot-output / bot-transcription) - 打印 BOT_REPLY 供验收脚本断言 回归:test_agent_tools 45/45、test_flows_runtime 24/24、 test_memory 30/30、test_identity 19/19 服务器已改回 AI_AGENT_RUNTIME=legacy(改默认是 Phase 7 的事)
This commit is contained in:
+12
-11
@@ -78,7 +78,7 @@ from pipecat.workers.base_worker import WorkerParams
|
||||
|
||||
from app.agent.flows_runtime import (
|
||||
UserTextRecorder, build_flows_parts, initialize_conversation_node,
|
||||
make_flow_manager,
|
||||
load_stable_memories, make_flow_manager,
|
||||
)
|
||||
from app.config import AppConfig
|
||||
from app.engine import ConversationEngine, EventKind
|
||||
@@ -557,7 +557,8 @@ async def offer(request: SmallWebRTCRequest):
|
||||
aggregator.assistant(),
|
||||
transport.output(),
|
||||
])
|
||||
flows_objs = (llm, aggregator, ctx_factory, tool_schemas)
|
||||
flows_objs = (llm, aggregator, ctx_factory, tool_schemas,
|
||||
memory, identity)
|
||||
log.info("Agent 运行时: flows(文字路径),语音仍走 legacy")
|
||||
else:
|
||||
pipeline = Pipeline([transport.input(), engine_proc, transport.output()])
|
||||
@@ -636,18 +637,18 @@ async def offer(request: SmallWebRTCRequest):
|
||||
log.info("PipelineWorker 已结束")
|
||||
|
||||
if flows_objs is not None:
|
||||
llm, aggregator, ctx_factory, tool_schemas = flows_objs
|
||||
llm, aggregator, ctx_factory, tool_schemas, memory, identity = flows_objs
|
||||
flow = make_flow_manager(worker=task, llm=llm, aggregator=aggregator)
|
||||
identity = engine_proc._engine.identity if engine_proc._engine else None
|
||||
display_name = ""
|
||||
if identity is not None:
|
||||
display_name = getattr(identity.current(), "display_name", "") or ""
|
||||
# 方案 §四要求稳定档案"连接开始时加载",不等模型自己想起来查。
|
||||
# 身份未确认时返回空——访客拿不到任何私人记忆(Phase 4 验收第 6 条)。
|
||||
memories = await load_stable_memories(memory, identity)
|
||||
# **必须 await**:initialize 是协程但签名显示 -> None,
|
||||
# 漏 await 不报错,只是人格/任务/工具全部静默失效(Phase 1 栽过)。
|
||||
# 漏 await 不报错,只是人格/记忆/工具全部静默失效(Phase 1 栽过)。
|
||||
await initialize_conversation_node(
|
||||
flow, display_name=display_name, tool_schemas=tool_schemas,
|
||||
ctx_factory=ctx_factory)
|
||||
log.info("Flows 节点已初始化:工具 %d 个", len(tool_schemas))
|
||||
flow, identity_decision=identity.current(), memories=memories,
|
||||
tool_schemas=tool_schemas, ctx_factory=ctx_factory)
|
||||
log.info("Flows 节点已初始化:工具 %d 个,稳定记忆 %d 条",
|
||||
len(tool_schemas), len(memories))
|
||||
|
||||
bg = asyncio.create_task(_run_task())
|
||||
_bg_tasks.add(bg)
|
||||
|
||||
Reference in New Issue
Block a user