memory.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. """
  2. Memory 数据模型
  3. Experience: 经验规则(条件 + 规则 + 证据)
  4. Skill: 技能(从经验归纳的高层知识)
  5. """
  6. from dataclasses import dataclass, field
  7. from datetime import datetime
  8. from typing import Dict, Any, List, Optional, Literal
  9. import uuid
  10. @dataclass
  11. class Experience:
  12. """
  13. 经验规则
  14. 从执行过程或人工反馈中提取的规则,格式:
  15. - condition: 什么情况下适用
  16. - rule: 应该怎么做
  17. - evidence: 证据(step_ids)
  18. """
  19. exp_id: str
  20. scope: str # "agent:{type}" 或 "user:{uid}"
  21. # 核心三元组
  22. condition: str
  23. rule: str
  24. evidence: List[str] = field(default_factory=list) # step_ids
  25. # 元数据
  26. source: Literal["execution", "feedback", "manual"] = "feedback"
  27. confidence: float = 0.5
  28. usage_count: int = 0
  29. success_rate: float = 0.0
  30. # 时间
  31. created_at: datetime = field(default_factory=datetime.now)
  32. updated_at: datetime = field(default_factory=datetime.now)
  33. @classmethod
  34. def create(
  35. cls,
  36. scope: str,
  37. condition: str,
  38. rule: str,
  39. evidence: List[str] = None,
  40. source: Literal["execution", "feedback", "manual"] = "feedback",
  41. confidence: float = 0.5,
  42. ) -> "Experience":
  43. """创建新的 Experience"""
  44. now = datetime.now()
  45. return cls(
  46. exp_id=str(uuid.uuid4()),
  47. scope=scope,
  48. condition=condition,
  49. rule=rule,
  50. evidence=evidence or [],
  51. source=source,
  52. confidence=confidence,
  53. created_at=now,
  54. updated_at=now,
  55. )
  56. def to_dict(self) -> Dict[str, Any]:
  57. """转换为字典"""
  58. return {
  59. "exp_id": self.exp_id,
  60. "scope": self.scope,
  61. "condition": self.condition,
  62. "rule": self.rule,
  63. "evidence": self.evidence,
  64. "source": self.source,
  65. "confidence": self.confidence,
  66. "usage_count": self.usage_count,
  67. "success_rate": self.success_rate,
  68. "created_at": self.created_at.isoformat() if self.created_at else None,
  69. "updated_at": self.updated_at.isoformat() if self.updated_at else None,
  70. }
  71. def to_prompt_text(self) -> str:
  72. """转换为可注入 Prompt 的文本"""
  73. return f"当 {self.condition} 时,{self.rule}"
  74. @dataclass
  75. class Skill:
  76. """
  77. 技能 - 从经验归纳的高层知识
  78. 技能可以形成层次结构(通过 parent_id)
  79. """
  80. skill_id: str
  81. scope: str # "agent:{type}" 或 "user:{uid}"
  82. name: str
  83. description: str
  84. category: str # 分类,如 "search", "reasoning", "writing"
  85. # 层次结构
  86. parent_id: Optional[str] = None
  87. # 内容
  88. guidelines: List[str] = field(default_factory=list)
  89. derived_from: List[str] = field(default_factory=list) # experience_ids
  90. # 版本
  91. version: int = 1
  92. # 时间
  93. created_at: datetime = field(default_factory=datetime.now)
  94. updated_at: datetime = field(default_factory=datetime.now)
  95. @classmethod
  96. def create(
  97. cls,
  98. scope: str,
  99. name: str,
  100. description: str,
  101. category: str = "general",
  102. guidelines: List[str] = None,
  103. derived_from: List[str] = None,
  104. parent_id: Optional[str] = None,
  105. ) -> "Skill":
  106. """创建新的 Skill"""
  107. now = datetime.now()
  108. return cls(
  109. skill_id=str(uuid.uuid4()),
  110. scope=scope,
  111. name=name,
  112. description=description,
  113. category=category,
  114. parent_id=parent_id,
  115. guidelines=guidelines or [],
  116. derived_from=derived_from or [],
  117. created_at=now,
  118. updated_at=now,
  119. )
  120. def to_dict(self) -> Dict[str, Any]:
  121. """转换为字典"""
  122. return {
  123. "skill_id": self.skill_id,
  124. "scope": self.scope,
  125. "name": self.name,
  126. "description": self.description,
  127. "category": self.category,
  128. "parent_id": self.parent_id,
  129. "guidelines": self.guidelines,
  130. "derived_from": self.derived_from,
  131. "version": self.version,
  132. "created_at": self.created_at.isoformat() if self.created_at else None,
  133. "updated_at": self.updated_at.isoformat() if self.updated_at else None,
  134. }
  135. def to_prompt_text(self) -> str:
  136. """转换为可注入 Prompt 的文本"""
  137. lines = [f"### {self.name}", self.description]
  138. if self.guidelines:
  139. lines.append("指导原则:")
  140. for g in self.guidelines:
  141. lines.append(f"- {g}")
  142. return "\n".join(lines)