在Google做LLM研究时,我们有一个主要问题:语言模型只知道它们训练时的数据。问GPT-4昨天发生的事,它一无所知。
现在大家都在构建的解决方案?将LLM连接到SERP API获取实时信息。
相关阅读:构建AI Agent | AI集成指南 | API文档
这篇文章解释它如何工作,并展示你自己构建的确切代码。
知识截止日期问题
每个LLM都有训练截止日期。GPT-4的知识止于2023年4月(基础模型)。问它:
"旧金山现在天气如何?"
它答不上来。信息不在它的训练数据中。
传统解决方案很笨拙:
- 微调模型(昂贵、慢)
- 维护一个巨大的最新知识库(工程噩梦)
- 接受局限性(糟糕的用户体验)
更好的解决方案:检索增强生成(RAG)
RAG是个高大上的术语,概念很简单:
- 用户问问题
- 搜索相关信息
- 将信息作为上下文喂给LLM
- LLM使用训练知识和新数据生成答案
搜索API让第2步变得简单。
基础架构
最简单的实现:
import requests
import openai
def answer_with_search(question):
"""使用LLM + 搜索API回答问题"""
# 步骤1:搜索相关信息
search_response = requests.post(
'https://searchcans.youxikuang.cn/api/search',
headers={'Authorization': f'Bearer {SEARCHCANS_KEY}'},
json={'s': question, 't': 'google', 'num': 5}
)
search_results = search_response.json()
# 步骤2:提取相关片段
context = "\n\n".join([
f"{result['title']}\n{result['snippet']}"
for result in search_results.get('organic_results', [])[:3]
])
# 步骤3:带上下文喂给LLM
prompt = f"""
使用提供的上下文回答以下问题。
来自最近搜索的上下文:
{context}
问题:{question}
回答:"""
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content
# 测试
answer = answer_with_search("OpenAI在2024年11月发生了什么?")
print(answer)
这出奇地有效。LLM现在可以访问搜索结果的当前信息。
生产级实现
基础版本有问题:
- 无错误处理
- 在无关上下文上浪费token
- 无来源归属
- 无法处理复杂查询
这是我们如何正确构建:
import requests
import openai
from typing import List, Dict
class AISearchAgent:
def __init__(self, search_api_key, openai_api_key):
self.search_key = search_api_key
self.openai_key = openai_api_key
openai.api_key = openai_api_key
def search(self, query: str, num_results: int = 5) -> List[Dict]:
"""执行搜索并返回结构化结果"""
try:
response = requests.post(
'https://searchcans.youxikuang.cn/api/search',
headers={'Authorization': f'Bearer {self.search_key}'},
json={'s': query, 't': 'google', 'num': num_results},
timeout=10
)
response.raise_for_status()
return response.json().get('organic_results', [])
except Exception as e:
print(f"搜索失败: {e}")
return []
def is_relevant(self, result: Dict, original_query: str) -> bool:
"""使用LLM检查搜索结果是否相关"""
prompt = f"""
查询:{original_query}
结果标题:{result['title']}
结果摘要:{result['snippet']}
这个结果与回答查询相关吗?
只回答"是"或"否"。
"""
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo", # 用便宜模型过滤
messages=[{"role": "user", "content": prompt}],
max_tokens=10
)
return "是" in response.choices[0].message.content
def answer_question(self, question: str) -> Dict:
"""带来源回答问题"""
# 搜索
results = self.search(question, num_results=10)
if not results:
return {
'answer': "我找不到相关信息来回答这个问题。",
'sources': []
}
# 过滤相关结果
relevant = [r for r in results if self.is_relevant(r, question)][:3]
# 构建上下文
context = "\n\n".join([
f"来源{i+1}:{r['title']}\n{r['snippet']}\n链接:{r['link']}"
for i, r in enumerate(relevant)
])
# 生成答案
prompt = f"""
使用以下来源回答问题。
使用[1]、[2]、[3]标记引用来源。
如果来源不包含答案,请说明。
来源:
{context}
问题:{question}
回答:"""
response = openai.ChatCompletion.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.3 # 更低温度以获得事实性回答
)
return {
'answer': response.choices[0].message.content,
'sources': [{'title': r['title'], 'url': r['link']}
for r in relevant]
}
# 使用
agent = AISearchAgent(
search_api_key="your_searchcans_key",
openai_api_key="your_openai_key"
)
result = agent.answer_question("谁赢得了2024年世界杯?")
print(result['answer'])
print("\n来源:")
for source in result['sources']:
print(f"- {source['title']}: {source['url']}")
这个版本:
- 使用便宜的LLM调用过滤无关结果
- 提供来源归属
- 优雅处理错误
- 为不同任务使用适当的模型
LangChain集成
如果你在用LangChain(你可能应该用),集成更简单:
from langchain.tools import Tool
from langchain.agents import initialize_agent, AgentType
from langchain.llms import OpenAI
import requests
def search_tool_func(query: str) -> str:
"""LangChain的搜索函数"""
response = requests.post(
'https://searchcans.youxikuang.cn/api/search',
headers={'Authorization': f'Bearer {API_KEY}'},
json={'s': query, 't': 'google'}
)
results = response.json().get('organic_results', [])[:3]
return "\n\n".join([
f"{r['title']}: {r['snippet']}"
for r in results
])
# 创建工具
search_tool = Tool(
name="网络搜索",
func=search_tool_func,
description="用于在互联网上查找最新信息"
)
# 初始化agent
llm = OpenAI(temperature=0)
agent = initialize_agent(
[search_tool],
llm,
agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
verbose=True
)
# 使用
result = agent.run("AI监管的最新发展是什么?")
print(result)
LangChain处理决策:何时搜索、如何解释结果、何时回应。
真实世界用例
1. 客服机器人
一家SaaS公司构建的支持机器人:
- 搜索他们的文档获取答案
- 降级到网络搜索处理一般问题
- 不确定时升级到人工
结果:60%的工单自动处理,平均4分钟解决时间。
2. 研究助手
学术研究人员使用AI + 搜索:
- 快速找相关论文
- 总结主题的当前研究
- 识别专家和机构
一个研究团队使用这种方法将文献综述时间从2周缩短到3天。
3. 新闻监控
一家对冲基金构建的AI agent:
- 监控投资组合公司的新闻
- 总结关键发展
- 对重大事件告警
系统每天处理10,000+篇文章,发送5-10个高优先级告警。
成本分析:实际花费
让我们计算每月10,000个用户查询的经济性:
搜索API成本:
- 10,000查询 × 每个1次搜索 = 10,000 API调用
- ¥3.4/1K = ¥34/月
OpenAI成本:
- 相关性过滤:10,000 × 3结果 × ¥0.007 = ¥210/月
- 答案生成:10,000 × ¥0.21 = ¥2,100/月
- OpenAI总计:¥2,310/月
总计:每月10,000增强查询¥2,344
对比维护自己的实时知识库:
- 网络爬虫基础设施:¥3,400/月
- 数据库:¥1,360/月
- 维护:20小时/月 × ¥680/小时 = ¥13,600/月
- 总计:¥18,360/月
API方案成本是DIY的13%,且无需维护。
高级模式
多步研究
对于复杂问题,使用多次搜索:
def deep_research(question: str) -> str:
"""复杂问题的多步研究"""
# 步骤1:识别子问题
sub_questions = decompose_question(question)
# 步骤2:研究每个子问题
sub_answers = []
for sq in sub_questions:
results = search(sq)
answer = synthesize_answer(sq, results)
sub_answers.append(answer)
# 步骤3:合并为最终答案
final_answer = synthesize_final(question, sub_answers)
return final_answer
这处理像"比较最近三任美国总统的经济政策"这样需要多个研究步骤的问题。
来源质量评分
不是所有搜索结果都同等可信:
def score_source_quality(url: str) -> float:
"""评估来源可靠性"""
trusted_domains = {
'人民网.cn': 0.95,
'xinhuanet.com': 0.95,
'cnki.net': 0.90,
'nature.com': 0.98,
# ... 更多域名
}
domain = url.split('/')[2]
return trusted_domains.get(domain, 0.5) # 默认:中等信任
# 在上下文构建中使用
weighted_results = sorted(
results,
key=lambda r: score_source_quality(r['link']),
reverse=True
)
这在发送给LLM的上下文中优先考虑权威来源。
重要的提示工程
提示质量决定输出质量。有效的做法:
糟糕的提示:
回答:{question}
上下文:{context}
好的提示:
你是一个有帮助的助手,准确回答问题。
仅使用提供的上下文回答。
如果上下文不包含答案,说"我没有足够信息。"
使用[1]、[2]、[3]标记引用来源。
上下文:
{context}
问题:{question}
回答:
好的提示:
- 设定明确的角色期望
- 将答案限制在提供的上下文
- 防止幻觉
- 请求来源归属
常见陷阱
陷阱1:发送过多上下文
GPT-4有8K token限制。如果你发送10篇完整文章作为上下文,会触及限制并截断重要信息。
解决方案:只发送摘要和标题。让LLM决定是否需要更多细节。
陷阱2:不处理搜索失败
搜索API可能失败或返回空结果。你的代码需要优雅降级。
解决方案:始终检查空结果并有降级响应。
陷阱3:信任一切
LLM会自信地呈现信息即使它是错的。
解决方案:始终显示来源,用户可以验证声明。
未来:自主Agent
下一个演进是AI agent:
- 决定何时搜索
- 选择搜索什么
- 确定是否需要更多信息
- 执行多步计划
我们正使用ReAct模式构建agent:
思考:我需要找关于AI监管的最新新闻
行动:搜索"AI监管 2024"
观察:[搜索结果]
思考:我找到了相关信息,让我综合它
行动:回应用户
这些agent在曾需要人类分析师的研究任务上表现得非常好。
今天开始行动
如果你想为AI应用添加搜索能力:
第1天:构建基础RAG系统(50行代码)
第2天:添加相关性过滤和错误处理
第3天:实现来源归属
第4天:用真实用户查询测试并迭代
别想太多。基础模式效果很好。你可以稍后优化。
关于作者:张艾米莉博士在斯坦福完成NLP博士学位,在Google Brain做LLM研究。她现在为公司构建AI产品提供咨询。
想为你的AI应用添加搜索能力?从1000次免费API调用开始构建第一个原型。