LLM 的知识有截止日期。通过 Tavily 搜索工具,Agent 能实时检索网页内容,让模型基于最新信息回答问题——"谁是 XX 的校长?""今天的股价是多少?"
所有 LLM 都有一个根本局限:训练数据有截止日期(Knowledge Cutoff)。GPT-4、DeepSeek、Claude——它们只知道训练集里的知识,无法知道训练后发生的新事件、新数据。
对于这类问题,单纯依赖 LLM 会得到可能过时或错误的答案。Web 搜索工具解决了这个问题——它让 Agent 能在推理时"出去查一下",把最新信息带回来。
Web 搜索工具本质上是实时 RAG(Retrieval-Augmented Generation)的一种形式:先检索(Retrieve)相关内容,再让模型基于检索结果生成(Generate)答案。区别在于:RAG 通常从私有知识库检索,Web 搜索从公开互联网检索。
Tavily 是一个为 LLM/Agent 场景优化的搜索服务,相比直接爬网页,它有几个关键优势:
| 特性 | Tavily | 自己爬网页 |
|---|---|---|
| 返回格式 | 干净的 JSON,包含 URL、标题、内容摘要 | 原始 HTML,需要解析和清洗 |
| 内容质量 | 智能筛选,过滤广告和无关内容 | 包含大量噪声 |
| 搜索深度 | 支持 basic 和 advanced 两档 |
需要自己实现深度搜索 |
| 集成难度 | 一行代码,直接返回 LLM 可用的内容 | 需要处理 robots.txt、限流、编码等问题 |
在 tavily.com 注册即可获取免费 API Key(有月度配额),将其设置为环境变量 TAVILY_API_KEY,TavilyClient 会自动读取。
from langchain.tools import tool
from typing import Dict, Any
from tavily import TavilyClient
tavily_client = TavilyClient() # 自动读取 TAVILY_API_KEY 环境变量
@tool("web_search", description="Search web")
def web_search(query: str) -> Dict[str, any]:
return tavily_client.search(query, search_depth="basic")
这个工具的关键参数:
query: str:搜索关键词。Agent 会根据用户的问题自动生成合适的查询词search_depth="basic":快速搜索(适合大多数场景);改为 "advanced" 会更深入但更慢results、query、answer 等字段上面代码里 description="Search web" 非常简短。在实际项目中,建议写得更详细,例如:"Search the web for real-time information. Use when you need current data, recent events, or facts that may have changed after your training cutoff." 这样模型能更准确地判断何时调用。
先建一个没有工具的普通 Agent,看它如何回答实时性问题:
agent_no_tools = create_agent(model=deepseek_model())
question = {
"role": "user",
"content": "Who is the principal of Birralee Primary School?"
}
response = agent_no_tools.invoke({"messages": question})
模型诚实地承认不知道——这是最好的情况。更糟糕的情况是模型自信地给出一个错误答案(幻觉)。
# 给 Agent 绑定 web_search 工具
agent = create_agent(
deepseek_model(),
tools=[web_search]
)
question = {
"role": "user",
"content": "Who is the principal of Birralee Primary School?"
}
response = agent.invoke({"messages": question})
print(response['messages'][-1].content)
模型这次调用了 web_search("Birralee Primary School principal"),从真实网页里找到了答案,而不是凭空编造。
agent = create_agent(
model=deepseek_model(),
tools=[web_search]
)
question = HumanMessage(content="Who is the current mayor of San Francisco?")
response = agent.invoke({"messages": [question]})
print(response['messages'][-1].content)
Tavily 返回的是 JSON 字符串,被封装为 ToolMessage.content。如果需要从搜索结果中提取具体信息,可以解析这个 JSON:
import json
# messages[2] 是 ToolMessage(工具执行结果)
content = response['messages'][2].content
data = json.loads(content) # 字符串 → dict
from pprint import pprint
pprint(data)
| 字段 | 含义 |
|---|---|
query |
实际执行的搜索查询词 |
results |
搜索结果列表,每项包含 url、title、content、score |
results[i].content |
网页摘要内容(已清洗,适合 LLM 阅读) |
results[i].score |
相关性评分(0-1),越高越相关 |
answer |
Tavily 自动生成的直接答案(并非总是有) |
response_time |
搜索耗时(秒) |
# 先独立测试 web_search,确认可以正常工作
web_results = web_search.invoke("Who is the current mayor of San Francisco?")
print(web_results['results'][0]['content']) # 第一条结果的内容
# 可以同时绑定多个工具
agent = create_agent(
model=deepseek_model(),
tools=[web_search, square_root, another_tool],
system_prompt="You have access to web search and math tools. Use them when needed."
)
使用 Web 搜索工具时要注意:
① 成本:Tavily 有 API 调用费用,高频调用需监控用量
② 延迟:网络搜索增加响应时间(通常 1-3 秒)
③信息质量:搜索结果可能包含错误或偏颇的网页内容,模型需要判断可信度
④ 无限循环风险:如果 system prompt 设计不当,模型可能无限搜索。LangGraph Agent 内置有最大步骤限制
TavilyClient() 自动读取 API Keysearch_depth="basic" 快速适用