diff --git a/backend/app/api/chat.py b/backend/app/api/chat.py index 05b3ea7..bf9c0ce 100644 --- a/backend/app/api/chat.py +++ b/backend/app/api/chat.py @@ -230,6 +230,8 @@ _TOOL_TITLES: dict[str, str] = { "ticket_detail": "查询工单详情", "generate_document": "生成文档", "sandbox_run": "执行沙盒代码", + # Google Serper + "serper_search": "Google 搜索", # Jina MCP tools "search_web": "外部搜索", "read_url": "读取网页", @@ -262,6 +264,8 @@ def _summarize_input(tool_name: str, inp: dict | str) -> str: return f"第 {inp.get('page', 1)} 页,每页 {inp.get('page_size', 20)} 条" case "ticket_detail": return f"工单 ID:{inp.get('ticket_id', '')}" + case "serper_search": + return f"搜索:{str(inp.get('query', ''))[:50]}" case "search_web": return f"搜索:{str(inp.get('query', ''))[:50]}" case "read_url": @@ -294,6 +298,8 @@ def _summarize_output(tool_name: str, output: str) -> str: return f"返回 {m.group(1)} 条工单" if m else "工单列表已获取" case "ticket_detail": return "工单详情已获取" + case "serper_search": + return f"Google 搜索完成,{len(output.splitlines())} 行结果" case "search_web": count = output.count("##") return f"找到 {max(count, 1)} 条搜索结果" diff --git a/backend/app/config.py b/backend/app/config.py index 698e6d6..97ab8e3 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -44,6 +44,9 @@ class Settings(BaseSettings): # Jina AI (Search / Reader / Rerank) jina_api_key: str = "" + # Google Serper + serper_api_key: str = "499940576bc8a7211ac98a3f3b83a4826bb8105b" + # Redis redis_url: str = "rediss://:bY8ZNwyJX60UwN5NPqnl6HRODfTV0efkDAzCaF1PrOU=@oper.redis.cache.windows.net:6380" diff --git a/backend/app/tools/__init__.py b/backend/app/tools/__init__.py index 75234dc..d8939ff 100644 --- a/backend/app/tools/__init__.py +++ b/backend/app/tools/__init__.py @@ -4,14 +4,17 @@ from app.tools.kb import kb_search from app.tools.tickets import ticket_list, ticket_detail from app.tools.document import generate_document from app.tools.sandbox import sandbox_run +from app.tools.serper import serper_search # Mapping from frontend tool names to LangChain tool objects. # "search" is no longer here — it is handled via Jina MCP in chat.py. +# "serper" uses Google Serper REST API, independent from Jina MCP. _TOOL_MAP: dict[str, list] = { "knowledge": [kb_search], "tickets": [ticket_list, ticket_detail], "document": [generate_document], "sandbox": [sandbox_run], + "serper": [serper_search], } diff --git a/backend/app/tools/serper.py b/backend/app/tools/serper.py new file mode 100644 index 0000000..3f9d225 --- /dev/null +++ b/backend/app/tools/serper.py @@ -0,0 +1,19 @@ +"""Google Serper search tool via LangChain integration.""" + +from __future__ import annotations + +from langchain_community.utilities import GoogleSerperAPIWrapper +from langchain_core.tools import tool + +from app.config import settings + + +@tool +async def serper_search(query: str) -> str: + """Search the web using Google Serper API. Returns Google search results including snippets, links, and answer boxes.""" + try: + search = GoogleSerperAPIWrapper(serper_api_key=settings.serper_api_key) + result = await search.arun(query) + return result or "No results found." + except Exception as e: + return f"Serper search failed: {e}" diff --git a/backend/requirements.txt b/backend/requirements.txt index 0931846..7134326 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -17,3 +17,4 @@ azure-storage-blob>=12.20.0 azure-servicebus>=7.12.0 daytona>=0.6.0 langchain-mcp-adapters>=0.1.0 +langchain-community>=0.3.0