test_goal_model.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. """
  2. 测试重构后的 Goal 模型功能
  3. 测试内容:
  4. 1. Goal 模型的新字段(evaluation 相关)
  5. 2. 序列化和反序列化(to_dict/from_dict)
  6. 3. 向后兼容性(加载旧数据)
  7. """
  8. import asyncio
  9. import sys
  10. from pathlib import Path
  11. from datetime import datetime
  12. # 添加项目根目录到 Python 路径
  13. sys.path.insert(0, str(Path(__file__).parent.parent))
  14. from agent.models.goal import Goal, GoalTree, GoalStats
  15. def test_goal_new_fields():
  16. """测试 Goal 模型的新字段"""
  17. print("=" * 80)
  18. print("测试 1: Goal 模型新字段")
  19. print("=" * 80)
  20. print()
  21. # 创建带有 evaluation 字段的 Goal
  22. goal = Goal(
  23. id="1",
  24. description="实现用户登录功能",
  25. type="agent_call",
  26. agent_call_mode="evaluation",
  27. target_goal_id="3",
  28. evaluation_input={
  29. "goal_description": "实现用户登录功能",
  30. "actual_result": "已实现登录接口和前端页面",
  31. "context": {"files": ["login.py", "login.html"]}
  32. },
  33. evaluation_result={
  34. "passed": True,
  35. "reason": "功能完整,符合要求",
  36. "suggestions": []
  37. },
  38. completed_at=datetime.now()
  39. )
  40. print("1. 创建的 Goal 对象:")
  41. print(f" ID: {goal.id}")
  42. print(f" 描述: {goal.description}")
  43. print(f" 类型: {goal.type}")
  44. print(f" 模式: {goal.agent_call_mode}")
  45. print(f" 目标 Goal ID: {goal.target_goal_id}")
  46. print(f" 评估输入: {goal.evaluation_input}")
  47. print(f" 评估结果: {goal.evaluation_result}")
  48. print(f" 完成时间: {goal.completed_at}")
  49. print()
  50. print("=" * 80)
  51. print("✅ 新字段测试完成")
  52. print("=" * 80)
  53. def test_goal_serialization():
  54. """测试 Goal 的序列化和反序列化"""
  55. print("\n" + "=" * 80)
  56. print("测试 2: Goal 序列化和反序列化")
  57. print("=" * 80)
  58. print()
  59. # 创建 Goal
  60. original_goal = Goal(
  61. id="1",
  62. description="测试目标",
  63. reason="测试序列化",
  64. type="agent_call",
  65. agent_call_mode="evaluation",
  66. target_goal_id="2",
  67. evaluation_input={"actual_result": "测试结果"},
  68. evaluation_result={"passed": True, "reason": "测试通过"},
  69. completed_at=datetime.now()
  70. )
  71. print("1. 原始 Goal:")
  72. print(f" {original_goal}")
  73. print()
  74. # 序列化
  75. print("2. 序列化为字典:")
  76. goal_dict = original_goal.to_dict()
  77. print(f" ID: {goal_dict['id']}")
  78. print(f" 描述: {goal_dict['description']}")
  79. print(f" target_goal_id: {goal_dict.get('target_goal_id')}")
  80. print(f" evaluation_input: {goal_dict.get('evaluation_input')}")
  81. print(f" evaluation_result: {goal_dict.get('evaluation_result')}")
  82. print(f" completed_at: {goal_dict.get('completed_at')}")
  83. print()
  84. # 反序列化
  85. print("3. 从字典反序列化:")
  86. restored_goal = Goal.from_dict(goal_dict)
  87. print(f" ID: {restored_goal.id}")
  88. print(f" 描述: {restored_goal.description}")
  89. print(f" target_goal_id: {restored_goal.target_goal_id}")
  90. print(f" evaluation_input: {restored_goal.evaluation_input}")
  91. print(f" evaluation_result: {restored_goal.evaluation_result}")
  92. print(f" completed_at: {restored_goal.completed_at}")
  93. print()
  94. # 验证一致性
  95. print("4. 验证序列化前后一致性:")
  96. assert restored_goal.id == original_goal.id
  97. assert restored_goal.description == original_goal.description
  98. assert restored_goal.target_goal_id == original_goal.target_goal_id
  99. assert restored_goal.evaluation_input == original_goal.evaluation_input
  100. assert restored_goal.evaluation_result == original_goal.evaluation_result
  101. print(" ✅ 所有字段一致")
  102. print()
  103. print("=" * 80)
  104. print("✅ 序列化测试完成")
  105. print("=" * 80)
  106. def test_backward_compatibility():
  107. """测试向后兼容性(加载旧数据)"""
  108. print("\n" + "=" * 80)
  109. print("测试 3: 向后兼容性")
  110. print("=" * 80)
  111. print()
  112. # 模拟旧版本的 Goal 数据(没有新字段)
  113. old_goal_dict = {
  114. "id": "1",
  115. "description": "旧版本的目标",
  116. "reason": "测试兼容性",
  117. "parent_id": None,
  118. "type": "normal",
  119. "status": "pending",
  120. "summary": None,
  121. "sub_trace_ids": None,
  122. "agent_call_mode": None,
  123. "sub_trace_metadata": None,
  124. "self_stats": {
  125. "message_count": 0,
  126. "total_tokens": 0,
  127. "total_cost": 0.0,
  128. "preview": None
  129. },
  130. "cumulative_stats": {
  131. "message_count": 0,
  132. "total_tokens": 0,
  133. "total_cost": 0.0,
  134. "preview": None
  135. },
  136. "created_at": "2026-02-07T10:00:00"
  137. # 注意:没有 target_goal_id, evaluation_input, evaluation_result, completed_at
  138. }
  139. print("1. 旧版本的 Goal 数据(缺少新字段):")
  140. print(f" {old_goal_dict}")
  141. print()
  142. # 尝试加载旧数据
  143. print("2. 从旧数据加载 Goal:")
  144. try:
  145. goal = Goal.from_dict(old_goal_dict)
  146. print(f" ✅ 成功加载")
  147. print(f" ID: {goal.id}")
  148. print(f" 描述: {goal.description}")
  149. print(f" target_goal_id: {goal.target_goal_id} (应该是 None)")
  150. print(f" evaluation_input: {goal.evaluation_input} (应该是 None)")
  151. print(f" evaluation_result: {goal.evaluation_result} (应该是 None)")
  152. print(f" completed_at: {goal.completed_at} (应该是 None)")
  153. print()
  154. # 验证新字段为 None
  155. assert goal.target_goal_id is None
  156. assert goal.evaluation_input is None
  157. assert goal.evaluation_result is None
  158. assert goal.completed_at is None
  159. print(" ✅ 新字段默认值正确(None)")
  160. print()
  161. except Exception as e:
  162. print(f" ❌ 加载失败: {e}")
  163. import traceback
  164. traceback.print_exc()
  165. print("=" * 80)
  166. print("✅ 向后兼容性测试完成")
  167. print("=" * 80)
  168. def test_goal_tree_serialization():
  169. """测试 GoalTree 的序列化"""
  170. print("\n" + "=" * 80)
  171. print("测试 4: GoalTree 序列化")
  172. print("=" * 80)
  173. print()
  174. # 创建 GoalTree
  175. tree = GoalTree(mission="测试任务")
  176. # 添加目标
  177. goals = tree.add_goals(
  178. ["目标1", "目标2", "目标3"],
  179. reasons=["理由1", "理由2", "理由3"]
  180. )
  181. # 为第一个目标添加子目标
  182. tree.add_goals(
  183. ["子目标1.1", "子目标1.2"],
  184. parent_id=goals[0].id
  185. )
  186. # 设置一个目标为 evaluation 类型
  187. goals[0].type = "agent_call"
  188. goals[0].agent_call_mode = "evaluation"
  189. goals[0].target_goal_id = goals[1].id
  190. goals[0].evaluation_input = {"actual_result": "测试"}
  191. goals[0].evaluation_result = {"passed": True}
  192. print("1. 创建的 GoalTree:")
  193. print(tree.to_prompt())
  194. print()
  195. # 序列化
  196. print("2. 序列化 GoalTree:")
  197. tree_dict = tree.to_dict()
  198. print(f" Mission: {tree_dict['mission']}")
  199. print(f" Goals 数量: {len(tree_dict['goals'])}")
  200. print(f" Current ID: {tree_dict['current_id']}")
  201. print()
  202. # 反序列化
  203. print("3. 从字典恢复 GoalTree:")
  204. restored_tree = GoalTree.from_dict(tree_dict)
  205. print(f" Mission: {restored_tree.mission}")
  206. print(f" Goals 数量: {len(restored_tree.goals)}")
  207. print(f" Current ID: {restored_tree.current_id}")
  208. print()
  209. # 验证 evaluation 字段
  210. print("4. 验证 evaluation 字段:")
  211. restored_goal = restored_tree.find(goals[0].id)
  212. print(f" target_goal_id: {restored_goal.target_goal_id}")
  213. print(f" evaluation_input: {restored_goal.evaluation_input}")
  214. print(f" evaluation_result: {restored_goal.evaluation_result}")
  215. print()
  216. assert restored_goal.target_goal_id == goals[1].id
  217. assert restored_goal.evaluation_input == {"actual_result": "测试"}
  218. assert restored_goal.evaluation_result == {"passed": True}
  219. print(" ✅ evaluation 字段正确")
  220. print()
  221. print("=" * 80)
  222. print("✅ GoalTree 序列化测试完成")
  223. print("=" * 80)
  224. def test_agent_call_mode_values():
  225. """测试 agent_call_mode 的所有可能值"""
  226. print("\n" + "=" * 80)
  227. print("测试 5: agent_call_mode 的值")
  228. print("=" * 80)
  229. print()
  230. modes = ["explore", "delegate", "sequential", "evaluation"]
  231. print("1. 测试所有 agent_call_mode 值:")
  232. for mode in modes:
  233. goal = Goal(
  234. id=f"goal-{mode}",
  235. description=f"测试 {mode} 模式",
  236. type="agent_call",
  237. agent_call_mode=mode
  238. )
  239. print(f" ✅ {mode}: {goal.agent_call_mode}")
  240. print()
  241. # 序列化和反序列化
  242. print("2. 测试序列化和反序列化:")
  243. for mode in modes:
  244. goal = Goal(
  245. id=f"goal-{mode}",
  246. description=f"测试 {mode} 模式",
  247. type="agent_call",
  248. agent_call_mode=mode
  249. )
  250. goal_dict = goal.to_dict()
  251. restored_goal = Goal.from_dict(goal_dict)
  252. assert restored_goal.agent_call_mode == mode
  253. print(f" ✅ {mode}: 序列化前后一致")
  254. print()
  255. print("=" * 80)
  256. print("✅ agent_call_mode 测试完成")
  257. print("=" * 80)
  258. def main():
  259. """运行所有测试"""
  260. print("\n" + "🧪" * 40)
  261. print("Goal 模型功能测试")
  262. print("🧪" * 40 + "\n")
  263. try:
  264. test_goal_new_fields()
  265. test_goal_serialization()
  266. test_backward_compatibility()
  267. test_goal_tree_serialization()
  268. test_agent_call_mode_values()
  269. print("\n" + "=" * 80)
  270. print("🎉 所有测试完成!")
  271. print("=" * 80)
  272. except Exception as e:
  273. print(f"\n❌ 测试失败: {e}")
  274. import traceback
  275. traceback.print_exc()
  276. if __name__ == "__main__":
  277. main()