run.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/env python3
  2. """
  3. agent67v2/run.py — Lambda v2 多智能体个人助理 🐑
  4. =================================================
  5. v2 架构: 协调者 + 5个专业微代理
  6. 协调者: 轻量级 ReAct, 只做任务分析和分派
  7. 微代理: code / shell / web / memory / system
  8. 三大改进:
  9. 1. 拆分: 42工具 → 5个微代理, 每个代理工具少 → 响应快
  10. 2. 复用: 每个微代理注册为 Skill, 可被任何编排器调用
  11. 3. 懒加载: ToolSearch 元工具按需发现, 首次响应快 2-3x
  12. 用法:
  13. python run.py # 使用 Claude Code (默认)
  14. python run.py --api # 使用 API Key
  15. python run.py --model opus # 指定模型
  16. python run.py --verbose # 详细模式
  17. """
  18. from __future__ import annotations
  19. import argparse
  20. import os
  21. import sys
  22. from pathlib import Path
  23. # 路径设置
  24. PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
  25. AGENT_DIR = Path(__file__).resolve().parent
  26. sys.path.insert(0, str(PROJECT_ROOT))
  27. sys.path.insert(0, str(AGENT_DIR.parent))
  28. BANNER = """
  29. ╔═══════════════════════════════════════════════════╗
  30. ║ 🐑 lambda v2 — 多智能体协作版个人助手 ║
  31. ║ ║
  32. ║ 架构: Coordinator + 5 Micro-Agents ║
  33. ║ ┌──────────┐ ║
  34. ║ │Coordinator│─→ code-agent (文件/代码/Git) ║
  35. ║ │ (分析+ │─→ shell-agent (终端命令) ║
  36. ║ │ 分派) │─→ web-agent (搜索/知识库) ║
  37. ║ │ │─→ memory-agent (记忆/任务) ║
  38. ║ │ │─→ system-agent (系统控制) ║
  39. ║ └──────────┘ ║
  40. ║ ║
  41. ║ 命令: trace | stats | history | exit ║
  42. ╚═══════════════════════════════════════════════════╝
  43. """
  44. def main():
  45. parser = argparse.ArgumentParser(description="🐑 lambda v2 — 多智能体个人助理")
  46. parser.add_argument("--api", action="store_true",
  47. help="使用 API Key 模式")
  48. parser.add_argument("--ollama", action="store_true",
  49. help="使用 Ollama 本地模型")
  50. parser.add_argument("--model", type=str, default=None,
  51. help="指定模型 (默认: 自动检测)")
  52. parser.add_argument("--verbose", action="store_true",
  53. help="详细模式")
  54. args = parser.parse_args()
  55. print(BANNER)
  56. # 检测后端 (与 agent67 一致的优先级)
  57. try:
  58. from agent67.core.config import detect_backend, BACKEND_OLLAMA
  59. model, use_api, backend = detect_backend()
  60. except ImportError:
  61. import shutil
  62. if shutil.which("claude"):
  63. model, use_api, backend = "sonnet", False, "claude_code"
  64. print("✅ 使用 Claude Code Max Plan (无需 API Key)")
  65. elif os.environ.get("ANTHROPIC_API_KEY"):
  66. model, use_api, backend = "claude-sonnet-4-20250514", True, "api"
  67. print("✅ 使用 Anthropic API")
  68. else:
  69. model, use_api, backend = args.model or "sonnet", args.api, ""
  70. print("⚠️ 未检测到 LLM 后端,将使用标准 Lam")
  71. if args.ollama:
  72. backend = "ollama"
  73. model = args.model or "qwen2.5:7b"
  74. use_api = False
  75. elif args.api:
  76. use_api = True
  77. backend = "api"
  78. if args.model:
  79. model = args.model
  80. # 创建协调者
  81. from agent67v2.core.coordinator import CoordinatorAssistant
  82. print(" 🔄 初始化微代理注册表...")
  83. assistant = CoordinatorAssistant(
  84. model=model or "sonnet",
  85. use_api=use_api,
  86. backend=backend,
  87. verbose=args.verbose,
  88. )
  89. print(" ✅ 5 个微代理已就绪\n")
  90. while True:
  91. try:
  92. user_input = input("You: ").strip()
  93. except (EOFError, KeyboardInterrupt):
  94. print("\n👋 lambda v2 下线了,再见!")
  95. break
  96. if not user_input:
  97. continue
  98. if user_input.lower() in ("exit", "quit", "bye", "再见"):
  99. print("👋 lambda v2 下线了,祝你有美好的一天!")
  100. break
  101. if user_input.lower() == "trace":
  102. assistant.print_trace()
  103. continue
  104. if user_input.lower() == "stats":
  105. assistant.print_stats()
  106. continue
  107. if user_input.lower() == "history":
  108. print("\n📜 对话历史:")
  109. for entry in assistant.conversation_history:
  110. print(f" [{entry['role']}] {entry['content'][:100]}")
  111. print()
  112. continue
  113. if user_input.lower() == "skills":
  114. from lambdagent.skills import SkillRegistry
  115. registry = SkillRegistry()
  116. print(f"\n📦 已注册技能 ({len(registry)} 个):")
  117. for name in registry.list_all():
  118. skill = registry.get(name)
  119. print(f" • {name}: {skill.description}")
  120. print(f" tags: {skill.tags}")
  121. print(f" stats: {skill.stats}")
  122. print()
  123. continue
  124. print()
  125. response = assistant.chat(user_input)
  126. is_streaming = hasattr(assistant.brain, 'stream') and assistant.brain.stream
  127. if not is_streaming:
  128. print(f"🐑 lambda v2: {response}")
  129. print()
  130. if __name__ == "__main__":
  131. main()