tools.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. from dotenv import load_dotenv
  2. # 加载 .env 文件中的环境变量
  3. load_dotenv()
  4. import os
  5. from serpapi import SerpApiClient
  6. from typing import Dict, Any
  7. def search(query: str) -> str:
  8. """
  9. 一个基于SerpApi的实战网页搜索引擎工具。
  10. 它会智能地解析搜索结果,优先返回直接答案或知识图谱信息。
  11. """
  12. print(f"🔍 正在执行 [SerpApi] 网页搜索: {query}")
  13. try:
  14. api_key = os.getenv("SERPAPI_API_KEY")
  15. if not api_key:
  16. return "错误:SERPAPI_API_KEY 未在 .env 文件中配置。"
  17. params = {
  18. "engine": "google",
  19. "q": query,
  20. "api_key": api_key,
  21. "gl": "cn", # 国家代码
  22. "hl": "zh-cn", # 语言代码
  23. }
  24. client = SerpApiClient(params)
  25. results = client.get_dict()
  26. # 智能解析:优先寻找最直接的答案
  27. if "answer_box_list" in results:
  28. return "\n".join(results["answer_box_list"])
  29. if "answer_box" in results and "answer" in results["answer_box"]:
  30. return results["answer_box"]["answer"]
  31. if "knowledge_graph" in results and "description" in results["knowledge_graph"]:
  32. return results["knowledge_graph"]["description"]
  33. if "organic_results" in results and results["organic_results"]:
  34. # 如果没有直接答案,则返回前三个有机结果的摘要
  35. snippets = [
  36. f"[{i+1}] {res.get('title', '')}\n{res.get('snippet', '')}"
  37. for i, res in enumerate(results["organic_results"][:3])
  38. ]
  39. return "\n\n".join(snippets)
  40. return f"对不起,没有找到关于 '{query}' 的信息。"
  41. except Exception as e:
  42. return f"搜索时发生错误: {e}"
  43. from typing import Dict, Any
  44. class ToolExecutor:
  45. """
  46. 一个工具执行器,负责管理和执行工具。
  47. """
  48. def __init__(self):
  49. self.tools: Dict[str, Dict[str, Any]] = {}
  50. def registerTool(self, name: str, description: str, func: callable):
  51. """
  52. 向工具箱中注册一个新工具。
  53. """
  54. if name in self.tools:
  55. print(f"警告:工具 '{name}' 已存在,将被覆盖。")
  56. self.tools[name] = {"description": description, "func": func}
  57. print(f"工具 '{name}' 已注册。")
  58. def getTool(self, name: str) -> callable:
  59. """
  60. 根据名称获取一个工具的执行函数。
  61. """
  62. return self.tools.get(name, {}).get("func")
  63. def getAvailableTools(self) -> str:
  64. """
  65. 获取所有可用工具的格式化描述字符串。
  66. """
  67. return "\n".join([
  68. f"- {name}: {info['description']}"
  69. for name, info in self.tools.items()
  70. ])
  71. # --- 工具初始化与使用示例 ---
  72. if __name__ == '__main__':
  73. # 1. 初始化工具执行器
  74. toolExecutor = ToolExecutor()
  75. # 2. 注册我们的实战搜索工具
  76. search_description = "一个网页搜索引擎。当你需要回答关于时事、事实以及在你的知识库中找不到的信息时,应使用此工具。"
  77. toolExecutor.registerTool("Search", search_description, search)
  78. # 3. 打印可用的工具
  79. print("\n--- 可用的工具 ---")
  80. print(toolExecutor.getAvailableTools())
  81. # 4. 智能体的Action调用,这次我们问一个实时性的问题
  82. print("\n--- 执行 Action: Search['英伟达最新的GPU型号是什么'] ---")
  83. tool_name = "Search"
  84. tool_input = "英伟达最新的GPU型号是什么"
  85. tool_function = toolExecutor.getTool(tool_name)
  86. if tool_function:
  87. observation = tool_function(tool_input)
  88. print("--- 观察 (Observation) ---")
  89. print(observation)
  90. else:
  91. print(f"错误:未找到名为 '{tool_name}' 的工具。")