run.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. """
  2. 浏览器调研示例
  3. 使用 Agent 模式 + 浏览器工具进行网络调研
  4. """
  5. import os
  6. import sys
  7. import asyncio
  8. from pathlib import Path
  9. # 添加项目根目录到 Python 路径
  10. sys.path.insert(0, str(Path(__file__).parent.parent.parent))
  11. from dotenv import load_dotenv
  12. load_dotenv()
  13. from agent.llm.prompts import SimplePrompt
  14. from agent.core.runner import AgentRunner
  15. from agent.execution import (
  16. FileSystemTraceStore,
  17. Trace,
  18. Message,
  19. )
  20. from agent.llm import create_openrouter_llm_call
  21. async def main():
  22. # 路径配置
  23. base_dir = Path(__file__).parent
  24. project_root = base_dir.parent.parent
  25. prompt_path = base_dir / "test.prompt"
  26. output_dir = base_dir / "output"
  27. output_dir.mkdir(exist_ok=True)
  28. # Skills 目录(可选:用户自定义 skills)
  29. # 注意:内置 skills(agent/skills/core.md)会自动加载
  30. skills_dir = None # 或者指定自定义 skills 目录,如: project_root / "skills"
  31. print("=" * 60)
  32. print("浏览器调研任务 (Agent 模式)")
  33. print("=" * 60)
  34. print()
  35. # 1. 加载 prompt
  36. print("1. 加载 prompt...")
  37. prompt = SimplePrompt(prompt_path)
  38. # 提取配置
  39. system_prompt = prompt._messages.get("system", "")
  40. user_task = prompt._messages.get("user", "")
  41. model_name = prompt.config.get('model', 'gemini-2.5-flash')
  42. temperature = float(prompt.config.get('temperature', 0.3))
  43. print(f" - 任务: {user_task[:80]}...")
  44. print(f" - 模型: {model_name}")
  45. # 2. 构建消息
  46. print("2. 构建任务消息...")
  47. messages = prompt.build_messages()
  48. # 3. 创建 Agent Runner(配置 skills 和浏览器工具)
  49. print("3. 创建 Agent Runner...")
  50. print(f" - Skills 目录: {skills_dir}")
  51. print(f" - 模型: {model_name} (via OpenRouter)")
  52. # 使用 OpenRouter 的 Gemini 模型
  53. runner = AgentRunner(
  54. trace_store=FileSystemTraceStore(base_path=".trace"),
  55. llm_call=create_openrouter_llm_call(model=f"google/{model_name}"),
  56. skills_dir=skills_dir,
  57. debug=True # 启用 debug,输出到 .trace/
  58. )
  59. # 4. Agent 模式执行
  60. print(f"4. 启动 Agent 模式...")
  61. print()
  62. final_response = ""
  63. current_trace_id = None
  64. async for item in runner.run(
  65. task=user_task,
  66. messages=messages,
  67. system_prompt=system_prompt,
  68. model=f"google/{model_name}",
  69. temperature=temperature,
  70. max_iterations=20, # 调研任务可能需要更多迭代
  71. ):
  72. # 处理 Trace 对象(整体状态变化)
  73. if isinstance(item, Trace):
  74. current_trace_id = item.trace_id
  75. if item.status == "running":
  76. print(f"[Trace] 开始: {item.trace_id[:8]}")
  77. elif item.status == "completed":
  78. print(f"[Trace] 完成")
  79. print(f" - Total messages: {item.total_messages}")
  80. print(f" - Total tokens: {item.total_tokens}")
  81. print(f" - Total cost: ${item.total_cost:.4f}")
  82. elif item.status == "failed":
  83. print(f"[Trace] 失败: {item.error_message}")
  84. # 处理 Message 对象(执行过程)
  85. elif isinstance(item, Message):
  86. if item.role == "assistant":
  87. content = item.content
  88. if isinstance(content, dict):
  89. text = content.get("text", "")
  90. tool_calls = content.get("tool_calls")
  91. if text and not tool_calls:
  92. # 纯文本回复(最终响应)
  93. final_response = text
  94. print(f"[Response] Agent 完成")
  95. elif text:
  96. print(f"[Assistant] {text[:100]}...")
  97. if tool_calls:
  98. for tc in tool_calls:
  99. tool_name = tc.get("function", {}).get("name", "unknown")
  100. print(f"[Tool Call] {tool_name}")
  101. elif item.role == "tool":
  102. content = item.content
  103. if isinstance(content, dict):
  104. tool_name = content.get("tool_name", "unknown")
  105. print(f"[Tool Result] {tool_name}")
  106. if item.description:
  107. desc = item.description[:80] if len(item.description) > 80 else item.description
  108. print(f" {desc}...")
  109. # 5. 输出结果
  110. print()
  111. print("=" * 60)
  112. print("Agent 响应:")
  113. print("=" * 60)
  114. print(final_response)
  115. print("=" * 60)
  116. print()
  117. # 6. 保存结果
  118. output_file = output_dir / "research_result.txt"
  119. with open(output_file, 'w', encoding='utf-8') as f:
  120. f.write(final_response)
  121. print(f"✓ 结果已保存到: {output_file}")
  122. print()
  123. # 提示使用 API 可视化
  124. print("=" * 60)
  125. print("可视化 Step Tree:")
  126. print("=" * 60)
  127. print("1. 启动 API Server:")
  128. print(" python3 api_server.py")
  129. print()
  130. print("2. 浏览器访问:")
  131. print(" http://localhost:8000/api/traces")
  132. print()
  133. print(f"3. Trace ID: {current_trace_id}")
  134. print("=" * 60)
  135. if __name__ == "__main__":
  136. asyncio.run(main())