base_agent/tools/web_search.py

88 lines
2.9 KiB
Python
Raw Normal View History

2026-03-30 08:48:36 +00:00
"""
tools/web_search.py
2026-06-01 07:53:27 +00:00
网络搜索工具 google搜索
2026-03-30 08:48:36 +00:00
配置通过 settings.tools['web_search'] 读取
"""
2026-02-28 08:21:35 +00:00
2026-06-01 07:53:27 +00:00
from dataclasses import dataclass
from serpapi import SerpApiClient
2026-06-06 08:42:07 +00:00
from agent.config.settings import settings
from agent.tools.base_tool import BaseTool
from agent.utils.logger import get_logger
2026-03-30 08:48:36 +00:00
logger = get_logger("TOOL.WebSearch")
def _cfg(key: str, fallback=None):
return settings.tools['web_search'].get(key, fallback)
2026-02-28 08:21:35 +00:00
2026-03-30 08:48:36 +00:00
@dataclass
class SearchResult:
title: str
url: str
snippet: str
rank: int = 0
2026-02-28 08:21:35 +00:00
2026-03-30 08:48:36 +00:00
def __str__(self) -> str:
return f"[{self.rank}] {self.title}\n {self.url}\n {self.snippet}"
2026-04-15 08:20:22 +00:00
class Tool(BaseTool):
2026-02-28 08:21:35 +00:00
name = "web_search"
2026-03-30 08:48:36 +00:00
description = (
"在互联网上搜索信息,返回相关网页的标题、链接和摘要。"
"适用于需要实时信息、最新资讯或不确定的知识查询。"
)
2026-02-28 08:21:35 +00:00
parameters = {
2026-03-30 08:48:36 +00:00
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "搜索关键词或问题,例如: 'Python 3.12 新特性'",
2026-06-01 07:53:27 +00:00
}
2026-03-30 08:48:36 +00:00
},
"required": ["query"],
2026-02-28 08:21:35 +00:00
}
2026-06-01 07:53:27 +00:00
def execute(self, query: str = "", **_) -> str:
"""
一个基于SerpApi的实战网页搜索引擎工具
它会智能地解析搜索结果优先返回直接答案或知识图谱信息
"""
print(f"🔍 正在执行 [SerpApi] 网页搜索: {query}")
2026-03-30 08:48:36 +00:00
try:
2026-06-01 07:53:27 +00:00
api_key = _cfg("api_key")
if not api_key:
return "错误:ApiKey未配置。"
params = {
"engine": "google",
"q": query,
"api_key": api_key,
"gl": "cn", # 国家代码
"hl": "zh-cn", # 语言代码
}
client = SerpApiClient(params)
results = client.get_dict()
# 智能解析:优先寻找最直接的答案
if "answer_box_list" in results:
return "\n".join(results["answer_box_list"])
if "answer_box" in results and "answer" in results["answer_box"]:
return results["answer_box"]["answer"]
if "knowledge_graph" in results and "description" in results["knowledge_graph"]:
return results["knowledge_graph"]["description"]
if "organic_results" in results and results["organic_results"]:
# 如果没有直接答案,则返回前三个有机结果的摘要
snippets = [
f"[{i + 1}] {res.get('title', '')}\n{res.get('snippet', '')}"
for i, res in enumerate(results["organic_results"][:3])
]
return "\n\n".join(snippets)
return f"对不起,没有找到关于 '{query}' 的信息。"
2026-03-30 08:48:36 +00:00
except Exception as e:
2026-06-01 07:53:27 +00:00
return f"搜索时发生错误: {e}"