models.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. """
  2. Tool Models - 工具系统核心数据模型
  3. 定义:
  4. 1. ToolResult: 工具执行结果(支持双层记忆管理)
  5. 2. ToolContext: 工具执行上下文(依赖注入)
  6. """
  7. from dataclasses import dataclass, field
  8. from typing import Any, Dict, List, Optional, Protocol
  9. @dataclass
  10. class ToolResult:
  11. """
  12. 工具执行结果
  13. 支持双层记忆管理(参考 Browser-Use 的 ActionResult):
  14. - output: 主要输出,可能很长,可以配置只给 LLM 看一次
  15. - long_term_memory: 简短摘要,永久保存在对话历史中
  16. 这种设计避免了大量临时内容占用 context。
  17. """
  18. # 主要输出(临时内容)
  19. title: str # 简短标题,用于展示
  20. output: str # 主要输出内容
  21. # 记忆管理
  22. long_term_memory: Optional[str] = None # 永久记忆(简短摘要)
  23. include_output_only_once: bool = False # output 是否只给 LLM 看一次
  24. # 元数据
  25. metadata: Dict[str, Any] = field(default_factory=dict)
  26. # 状态标志
  27. truncated: bool = False # 输出是否被截断
  28. error: Optional[str] = None # 错误信息(如果执行失败)
  29. # 附件支持(用于浏览器自动化等场景)
  30. attachments: List[str] = field(default_factory=list) # 文件路径列表
  31. images: List[Dict[str, Any]] = field(default_factory=list) # 图片列表
  32. def to_llm_message(self, first_time: bool = True) -> str:
  33. """
  34. 转换为给 LLM 的消息
  35. Args:
  36. first_time: 是否第一次展示(影响 include_output_only_once 的行为)
  37. Returns:
  38. 给 LLM 的消息字符串
  39. """
  40. # 如果有错误,优先返回错误
  41. if self.error:
  42. return f"Error: {self.error}"
  43. # 构建消息
  44. parts = []
  45. # 标题
  46. if self.title:
  47. parts.append(f"# {self.title}")
  48. # 主要输出
  49. if first_time or not self.include_output_only_once:
  50. if self.output:
  51. parts.append(self.output)
  52. if self.truncated:
  53. parts.append("(Output truncated)")
  54. # 长期记忆(永远包含)
  55. if self.long_term_memory:
  56. parts.append(f"\nSummary: {self.long_term_memory}")
  57. # 附件信息
  58. if self.attachments:
  59. parts.append(f"\nAttachments: {', '.join(self.attachments)}")
  60. return "\n\n".join(parts)
  61. class ToolContext(Protocol):
  62. """
  63. 工具执行上下文(依赖注入)
  64. 工具函数可以声明需要哪些上下文字段,框架自动注入。
  65. 使用 Protocol 允许不同实现提供不同的上下文字段。
  66. """
  67. # 基础字段(所有工具都可用)
  68. trace_id: str
  69. step_id: str
  70. uid: Optional[str]
  71. # 浏览器相关(Browser-Use 集成)
  72. browser_session: Optional[Any] # BrowserSession 实例
  73. page_url: Optional[str] # 当前页面 URL
  74. file_system: Optional[Any] # FileSystem 实例
  75. sensitive_data: Optional[Dict[str, Any]] # 敏感数据字典
  76. # 其他可扩展字段
  77. context: Optional[Dict[str, Any]] # 额外上下文数据
  78. @dataclass
  79. class ToolContextImpl:
  80. """ToolContext 的默认实现"""
  81. # 基础字段
  82. trace_id: str
  83. step_id: str
  84. uid: Optional[str] = None
  85. # 浏览器相关
  86. browser_session: Optional[Any] = None
  87. page_url: Optional[str] = None
  88. file_system: Optional[Any] = None
  89. sensitive_data: Optional[Dict[str, Any]] = None
  90. # 额外上下文
  91. context: Optional[Dict[str, Any]] = None