快速回答
如何为 LangChain agent 提供网页搜索工具?
用 langchain_core.tools 中的 @tool 装饰一个 Python 函数,让它调用 https://serpcrypto.com/api/v1/search 并返回简短文本,然后在创建 agent 时将其传入 tools=[...]。使用 SerpCrypto 时,agent 每次搜索消耗 1 个积分,起价 US$0.30/千次搜索,失败的调用免费。积分使用加密货币支付,无需 KYC。
如何编写搜索工具?
LangChain 工具是一个带 docstring 的类型化函数。装饰器会把函数签名转成参数 schema,把 docstring 转成模型读取的描述,因此两者都值得用心。参数命名要贴合模型思考的方式:查询、国家、语言。
返回文本,而不是整个 JSON。五条包含标题、链接和摘要的结果足以让模型作答并引用来源,而且 token 数只有原始答案的一小部分。出错时返回简短消息而不是抛出异常,这样 agent 可以解释或重试。
"""A LangChain tool that searches Google through the SerpCrypto SERP API."""
import os
import requests
from langchain_core.tools import tool
API_URL = "https://serpcrypto.com/api/v1/search"
@tool
def google_search(query: str, gl: str = "us", hl: str = "en") -> str:
"""Search Google for current information. Returns the top results with title, link and snippet.
Args:
query: the search query, as a person would type it.
gl: two-letter country code of the results, for example us, gb or de.
hl: language code, for example en, de or pt-BR.
"""
r = requests.get(
API_URL,
params={"q": query, "gl": gl, "hl": hl},
headers={"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]},
timeout=90,
)
if r.status_code != 200:
return f"Search failed with HTTP {r.status_code}."
results = r.json().get("organic_results", [])[:5]
return "\n\n".join(f"{x['title']}\n{x['link']}\n{x.get('snippet', '')}" for x in results) or "No results."如何让 agent 决定何时搜索?
将工具传给 create_agent(LangChain 1.0 起可用)。模型会读取描述,在问题需要最新事实时调用工具。将 AGENT_MODEL 设为你的账户支持的模型字符串,例如 openai: 或 anthropic: 后跟模型名称;任何支持工具调用的 chat 模型都可用。
系统提示词和代码同样重要。要求 agent 仅针对比其训练数据更新的信息进行搜索,并引用链接,可以让回答有据可依,并限制付费搜索的次数。
"""An agent that decides when to search (LangChain 1.0 or later)."""
import os
from langchain.agents import create_agent
from search_tool import google_search
agent = create_agent(
model=os.environ["AGENT_MODEL"], # a provider:model string, such as one of your OpenAI or Anthropic models
tools=[google_search],
system_prompt="Answer with current facts. Use google_search when you need information newer than your training data, and cite the links you used.",
)
result = agent.invoke({"messages": [{"role": "user", "content": "What changed in Google's search results pages this year?"}]})
print(result["messages"][-1].content)如何用 LlamaIndex 实现同样的功能?
编写一个带类型提示和 docstring 的普通函数,然后用 FunctionTool.from_defaults 包装它。LlamaIndex 会像 LangChain 一样读取名称、类型提示和 docstring 来构建工具 schema。将该工具添加到任何接受工具列表的 LlamaIndex agent 中。
"""The same search as a LlamaIndex FunctionTool."""
import os
import requests
from llama_index.core.tools import FunctionTool
def google_search(query: str, gl: str = "us", hl: str = "en") -> str:
"""Search Google for current information and return the top results with title, link and snippet."""
r = requests.get(
"https://serpcrypto.com/api/v1/search",
params={"q": query, "gl": gl, "hl": hl},
headers={"Authorization": "Bearer " + os.environ["SERPCRYPTO_API_KEY"]},
timeout=90,
)
r.raise_for_status()
results = r.json().get("organic_results", [])[:5]
return "\n\n".join(f"{x['title']}\n{x['link']}\n{x.get('snippet', '')}" for x in results)
search_tool = FunctionTool.from_defaults(fn=google_search)
# Pass search_tool in the tools list of your LlamaIndex agent.工具应该返回 JSON 还是文本?
大多数情况下返回文本。模型对简短、带标签的文本读取效果很好,而且比嵌套 JSON 消耗更少的 token。只有当链的后续步骤需要解析它时才返回 JSON,例如用于存储排名。
在输出中保留链接。它们让模型能够引用来源,也让你事后能核查答案依赖了哪些页面。
如何在 agent 中控制搜索成本?
每次成功的工具调用就是 1 个积分。三个习惯可以保持低消耗:在系统提示词中告诉模型何时不要搜索,在 agent 循环中限制每次运行的调用次数,并在自己的代码中缓存常见问题的答案。
100,000 次搜索 的积分包售价 US$56.25,且 预付的搜索积分永不过期:未使用的查询会一直留在你的账户中,直到你使用它们,所以清淡的月份不会浪费任何东西。
LangChain 常见问题
这是官方的 LangChain 集成吗?
不是。它是基于 LangChain 公开的 @tool 装饰器构建的小型自定义工具。由于是你自己的代码,你可以更改输出格式、添加 location 或 engine 等参数,或为 Google News 添加第二个工具。
工具可以搜索特定城市吗?
可以。添加一个 location 参数并在 params 中传入,格式为 City, Region, Country。格式和示例见位置。
失败的搜索需要 agent 付费吗?
不需要。1 积分 = 1 次成功的查询请求,可在任意支持的引擎上返回一页结果。失败的请求不计费。遇到超时或临时错误的工具调用不消耗积分。
哪些模型可以使用此工具?
任何在 LangChain 或 LlamaIndex 中支持工具调用的 chat 模型。工具本身只发送 HTTPS 请求,因此不依赖模型提供商。