run.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. """
  2. 内容寻找 Agent
  3. 使用示例:
  4. python run.py
  5. """
  6. import asyncio
  7. import logging
  8. import sys
  9. import os
  10. from pathlib import Path
  11. sys.path.insert(0, str(Path(__file__).parent.parent.parent))
  12. from dotenv import load_dotenv
  13. load_dotenv()
  14. from agent import (
  15. AgentRunner,
  16. RunConfig,
  17. FileSystemTraceStore,
  18. Trace,
  19. Message,
  20. )
  21. from agent.llm import create_openrouter_llm_call
  22. from agent.llm.prompts import SimplePrompt
  23. # 导入工具(确保工具被注册)
  24. from tools import (
  25. douyin_search,
  26. douyin_user_videos,
  27. get_content_fans_portrait,
  28. get_account_fans_portrait,
  29. )
  30. # 配置日志
  31. log_dir = Path(__file__).parent / '.cache'
  32. log_dir.mkdir(exist_ok=True)
  33. logging.basicConfig(
  34. level=logging.INFO,
  35. format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
  36. handlers=[
  37. logging.FileHandler(log_dir / 'agent.log'),
  38. logging.StreamHandler()
  39. ]
  40. )
  41. logger = logging.getLogger(__name__)
  42. async def main():
  43. print("\n" + "=" * 60)
  44. print("内容寻找 Agent")
  45. print("=" * 60)
  46. print("开始执行...\n")
  47. # 加载 prompt
  48. prompt_path = Path(__file__).parent / "content_finder.prompt"
  49. prompt = SimplePrompt(prompt_path)
  50. # 构建消息
  51. messages = prompt.build_messages()
  52. # 初始化
  53. api_key = os.getenv("OPEN_ROUTER_API_KEY")
  54. if not api_key:
  55. raise ValueError("OPEN_ROUTER_API_KEY 未设置,请在 .env 文件中配置")
  56. model = os.getenv("MODEL", f"anthropic/claude-{prompt.config.get('model', 'sonnet-4.6')}")
  57. temperature = float(prompt.config.get("temperature", 0.3))
  58. max_iterations = int(os.getenv("MAX_ITERATIONS", "30"))
  59. trace_dir = os.getenv("TRACE_DIR", ".cache/traces")
  60. skills_dir = str(Path(__file__).parent / "skills")
  61. Path(trace_dir).mkdir(parents=True, exist_ok=True)
  62. store = FileSystemTraceStore(base_path=trace_dir)
  63. # 限制工具范围:只使用抖音相关的4个工具
  64. allowed_tools = [
  65. "douyin_search",
  66. "douyin_user_videos",
  67. "get_content_fans_portrait",
  68. "get_account_fans_portrait",
  69. ]
  70. runner = AgentRunner(
  71. llm_call=create_openrouter_llm_call(model=model),
  72. trace_store=store,
  73. skills_dir=skills_dir,
  74. )
  75. config = RunConfig(
  76. model=model,
  77. temperature=temperature,
  78. max_iterations=max_iterations,
  79. tools=allowed_tools, # 限制工具范围
  80. )
  81. # 执行
  82. try:
  83. async for item in runner.run(messages=messages, config=config):
  84. if isinstance(item, Trace):
  85. if item.status == "completed":
  86. print(f"\n[完成] trace_id={item.trace_id}")
  87. elif item.status == "failed":
  88. print(f"\n[失败] {item.error_message}")
  89. elif isinstance(item, Message):
  90. if item.role == "assistant":
  91. content = item.content
  92. if isinstance(content, dict):
  93. text = content.get("text", "")
  94. tool_calls = content.get("tool_calls")
  95. if text and not tool_calls:
  96. print(f"\n{text}")
  97. elif text:
  98. print(f"[思考] {text[:100]}..." if len(text) > 100 else f"[思考] {text}")
  99. if tool_calls:
  100. for tc in tool_calls:
  101. tool_name = tc.get("function", {}).get("name", "unknown")
  102. print(f"[工具] {tool_name}")
  103. elif isinstance(content, str) and content:
  104. print(f"\n{content}")
  105. elif item.role == "tool":
  106. content = item.content
  107. if isinstance(content, dict):
  108. tool_name = content.get("tool_name", "unknown")
  109. print(f"[结果] {tool_name} ✓")
  110. except KeyboardInterrupt:
  111. print("\n用户中断")
  112. except Exception as e:
  113. logger.error(f"执行失败: {e}", exc_info=True)
  114. print(f"\n执行失败: {e}")
  115. sys.exit(1)
  116. if __name__ == "__main__":
  117. asyncio.run(main())