feat: add Google Serper search tool alongside Jina MCP

- Add langchain-community dependency for GoogleSerperAPIWrapper
- Add serper_api_key to config with default key
- Create app/tools/serper.py with async serper_search tool
- Register "serper" key in tools/__init__.py (independent from "search"/Jina MCP)
- Add tool title and input/output summaries in chat.py
- Set SERPER_API_KEY on Azure App Service (Operation resource group)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gongzhiyong
2026-04-09 21:11:22 +08:00
co-authored by Claude Sonnet 4.6
parent 707f6bce4b
commit ac843da725
5 changed files with 32 additions and 0 deletions
+6
View File
@@ -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)} 条搜索结果"
+3
View File
@@ -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"
+3
View File
@@ -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],
}
+19
View File
@@ -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}"
+1
View File
@@ -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