memory.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. """
  2. Memory 相关工具 —— 目前只包含 dream 操作(见 agent/docs/memory-plan.md 第四节)。
  3. dream 整理 Agent 身份的长期记忆:回顾最近 trace 的执行历史,
  4. 逐个 trace 做反思,再跨 trace 整合写回记忆文件。
  5. 设计要点:
  6. - 需要 config.memory(MemoryConfig)才可用;否则报错。
  7. - 不是 knowledge_save_pending 那样每 trace 都要用的日常工具 ——
  8. 所以放在独立 group "memory",通过 tool_groups 显式开启。
  9. """
  10. from __future__ import annotations
  11. import logging
  12. from typing import Optional
  13. from agent.tools import tool, ToolResult, ToolContext
  14. logger = logging.getLogger(__name__)
  15. @tool(groups=["memory"], hidden_params=["context"])
  16. async def dream(
  17. reflect_model: str = "",
  18. dream_model: str = "",
  19. context: Optional[ToolContext] = None,
  20. ) -> ToolResult:
  21. """整理长期记忆。回顾最近的执行历史,更新记忆文件。
  22. 本工具做两件事:
  23. 1. per-trace 反思:扫描未反思的 trace,为每个生成反思摘要
  24. 2. 跨 trace 整合:汇总未消化的反思 + 当前记忆,让 LLM 更新记忆文件
  25. 需要 RunConfig.memory(MemoryConfig)才可调用。
  26. Args:
  27. reflect_model: per-trace 反思用的模型(空则默认 gpt-4o-mini)
  28. dream_model: 跨 trace 整合用的模型(空则默认 gpt-4o)
  29. """
  30. runner = context.get("runner") if context else None
  31. if runner is None:
  32. return ToolResult(
  33. title="❌ dream 不可用",
  34. output="缺少 runner(需要从 AgentRunner 上下文调用)",
  35. error="runner not in context",
  36. )
  37. memory_config = getattr(runner, "_current_memory_config", None)
  38. if memory_config is None:
  39. return ToolResult(
  40. title="❌ dream 不可用",
  41. output="当前 Agent 未配置 MemoryConfig,不是 memory-bearing Agent",
  42. error="memory not configured",
  43. )
  44. if not runner.trace_store or not runner.llm_call:
  45. return ToolResult(
  46. title="❌ dream 不可用",
  47. output="runner 缺少 trace_store 或 llm_call",
  48. error="runner dependencies missing",
  49. )
  50. from agent.core.dream import run_dream
  51. report = await run_dream(
  52. store=runner.trace_store,
  53. llm_call=runner.llm_call,
  54. memory_config=memory_config,
  55. reflect_model=reflect_model or "gpt-4o-mini",
  56. dream_model=dream_model or "gpt-4o",
  57. )
  58. lines = []
  59. lines.append(f"per-trace 反思: {len(report.per_trace_summaries)} 条")
  60. if report.skipped_traces:
  61. lines.append(f"跳过: {len(report.skipped_traces)} 条 trace(日志详见 logger)")
  62. lines.append(f"消化 reflection: {report.consumed_reflection_count} 条")
  63. lines.append(f"更新记忆文件: {len(report.updated_files)} 个")
  64. for p in report.updated_files:
  65. lines.append(f" - {p}")
  66. if report.reasoning:
  67. lines.append(f"\n整合理由: {report.reasoning}")
  68. output = "\n".join(lines)
  69. return ToolResult(
  70. title="🧠 dream 完成",
  71. output=output,
  72. long_term_memory=f"dream: reflected={len(report.per_trace_summaries)}, "
  73. f"consumed={report.consumed_reflection_count}, "
  74. f"files_updated={len(report.updated_files)}",
  75. metadata={
  76. "per_trace_count": len(report.per_trace_summaries),
  77. "consumed": report.consumed_reflection_count,
  78. "updated_files": report.updated_files,
  79. },
  80. )