检索增强生成(RAG)已成为AI应用的标准架构,但传统RAG存在一个根本性局限:它依赖预先准备的静态知识库,无法获取实时、动态的信息。当用户询问"今天的股市走势"或"最新的AI政策"时,传统RAG无能为力。本文将展示如何通过集成SERP API和Reader API,构建能够动态获取最新知识的高级RAG系统。
传统RAG的局限性
标准RAG架构
典型的RAG系统包含:
-
知识准备阶段
- 收集文档
- 分块(Chunking)
- 向量化(Embedding)
- 存入向量数据库
-
查询阶段
- 用户提问
- 问题向量化
- 向量检索
- 将检索结果作为上下文输入LLM
- 生成答案
三大局限
时效性问题:知识库的内容是固定的,截止于最后一次更新。如果某个重要信息在之后发生变化,系统无法感知。
覆盖面问题:不可能将互联网上所有信息都放入知识库。很多长尾查询、新兴话题,知识库中根本不存在相关内容。
维护成本问题:保持知识库的时效性需要持续的数据采集、清洗、更新。对于快速变化的领域(如新闻、金融),这个成本很高。
高级RAG:混合架构
解决方案是构建混合架构:静态知识库 + 动态互联网检索。
核心设计思想
内外结合:
- 内部知识库:存储相对稳定、专有的知识(如公司文档、产品手册)
- 外部互联网:通过SERP API动态获取最新、开放的信息
智能路由:
- 系统判断查询类型
- 稳定知识 → 查询知识库
- 实时信息 → 调用SERP API
- 综合任务 → 同时使用两者
深度融合:
- 将搜索结果与知识库内容一起输入LLM
- LLM综合内外部信息生成答案
架构图
用户查询
↓
查询分析器
↓
┌─────┴─────┐
↓ ↓
内部检索 外部检索
(向量DB) (SERP API)
↓ ↓
└─────┬─────┘
↓
内容提取
(Reader API)
↓
结果融合
↓
LLM生成
↓
答案
详细实现步骤
步骤1:查询分析与路由
首先,判断查询需要哪些信息源。
from typing import Literal, List
from pydantic import BaseModel
class QueryAnalysis(BaseModel):
query_type: Literal["internal", "external", "hybrid"]
needs_realtime: bool
search_queries: List[str] # 如果需要外部检索,生成搜索查询
def analyze_query(user_query: str) -> QueryAnalysis:
"""
使用LLM分析查询,决定检索策略
"""
analysis_prompt = f"""
分析以下用户查询,判断需要哪些信息源:
查询:{user_query}
请输出JSON格式的分析结果:
- query_type: "internal"(仅需内部知识)/ "external"(仅需外部信息)/ "hybrid"(两者都需要)
- needs_realtime: true/false(是否需要最新、实时的信息)
- search_queries: 如果需要外部检索,列出1-3个搜索查询
示例:
查询:"公司的休假政策是什么?"
输出:{{"query_type": "internal", "needs_realtime": false, "search_queries": []}}
查询:"今天苹果公司的股价是多少?"
输出:{{"query_type": "external", "needs_realtime": true, "search_queries": ["苹果股价实时行情"]}}
查询:"分析特斯拉的最新财报,结合我们公司的产品定位,评估合作机会"
输出:{{"query_type": "hybrid", "needs_realtime": true, "search_queries": ["特斯拉2024Q3财报", "特斯拉供应链战略"]}}
"""
response = llm.generate(analysis_prompt, response_format=QueryAnalysis)
return response
步骤2:内部知识检索
传统的向量检索:
from langchain.vectorstores import Pinecone
from langchain.embeddings import OpenAIEmbeddings
def search_internal(query: str, top_k: int = 5) -> List[Document]:
"""
从内部向量数据库检索
"""
embeddings = OpenAIEmbeddings()
vectorstore = Pinecone.from_existing_index("company-knowledge", embeddings)
docs = vectorstore.similarity_search(query, k=top_k)
return docs
步骤3:外部信息检索
调用SERP API搜索,然后用Reader API提取内容:
import requests
def search_external(queries: List[str], num_results_per_query: int = 5) -> List[Document]:
"""
使用SERP API搜索外部信息
"""
all_results = []
for query in queries:
# 调用SearchCans SERP API
response = requests.get(
"https://searchcans.youxikuang.cn/api/search",
headers={"Authorization": f"Bearer {SERP_API_KEY}"},
params={"q": query, "num": num_results_per_query}
)
results = response.json().get("organic_results", [])
all_results.extend(results)
return all_results
def extract_content(urls: List[str]) -> List[Document]:
"""
使用Reader API提取网页内容
"""
documents = []
for url in urls:
response = requests.get(
"https://searchcans.youxikuang.cn/api/url",
headers={"Authorization": f"Bearer {READER_API_KEY}"},
params={"url": url}
)
content = response.json().get("content", "")
doc = Document(page_content=content, metadata={"source": url})
documents.append(doc)
return documents
步骤4:结果融合与排序
将内外部检索结果融合,并重新排序:
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CohereRerank
def fuse_and_rerank(internal_docs: List[Document],
external_docs: List[Document],
query: str) -> List[Document]:
"""
融合内外部检索结果,并使用reranker重新排序
"""
all_docs = internal_docs + external_docs
# 使用Reranker模型对文档重新排序
compressor = CohereRerank(model="rerank-english-v2.0")
reranked_docs = compressor.compress_documents(all_docs, query)
# 取top 5
return reranked_docs[:5]
关于Reranking的详细讲解,参考RAG重排序最佳实践。
步骤5:生成答案
将融合后的内容输入LLM:
def generate_answer(query: str, context_docs: List[Document]) -> str:
"""
基于检索到的内容生成答案
"""
context = "\n\n".join([
f"来源:{doc.metadata.get('source', 'internal')}\n{doc.page_content}"
for doc in context_docs
])
prompt = f"""
基于以下信息回答用户的问题。如果信息不足,诚实说明。
背景信息:
{context}
用户问题:{query}
请提供详细、准确的答案,并标注关键信息的来源。
"""
answer = llm.generate(prompt)
return answer
完整流程整合
def advanced_rag(user_query: str) -> str:
"""
高级RAG完整流程
"""
# 1. 分析查询
analysis = analyze_query(user_query)
# 2. 内部检索
internal_docs = []
if analysis.query_type in ["internal", "hybrid"]:
internal_docs = search_internal(user_query)
# 3. 外部检索
external_docs = []
if analysis.query_type in ["external", "hybrid"]:
search_results = search_external(analysis.search_queries)
# 选择最相关的URL
top_urls = [r["link"] for r in search_results[:5]]
external_docs = extract_content(top_urls)
# 4. 融合与排序
final_docs = fuse_and_rerank(internal_docs, external_docs, user_query)
# 5. 生成答案
answer = generate_answer(user_query, final_docs)
return answer
优化策略
1. 智能缓存
对于热门查询或短时间内的重复查询,使用缓存避免重复的API调用:
from functools import lru_cache
import hashlib
@lru_cache(maxsize=1000)
def cached_search(query: str, ttl_hours: int = 24):
"""
带缓存的搜索,避免重复调用
"""
return search_external([query])
# 或使用Redis等支持TTL的缓存
2. 并行处理
内部检索和外部检索可以并行执行:
import asyncio
async def parallel_retrieval(query: str, analysis: QueryAnalysis):
"""
并行执行内外部检索
"""
tasks = []
if analysis.query_type in ["internal", "hybrid"]:
tasks.append(asyncio.to_thread(search_internal, query))
if analysis.query_type in ["external", "hybrid"]:
tasks.append(asyncio.to_thread(search_external, analysis.search_queries))
results = await asyncio.gather(*tasks)
return results
3. 渐进式加载
先返回快速答案(基于snippet),再提供深度答案(基于完整内容):
def quick_answer(query: str, search_results: List[dict]) -> str:
"""
基于搜索结果的snippet快速生成答案
"""
snippets = "\n".join([r["snippet"] for r in search_results[:3]])
prompt = f"基于以下摘要快速回答:{snippets}\n\n问题:{query}"
return llm.generate(prompt)
def deep_answer(query: str, full_contents: List[Document]) -> str:
"""
基于完整内容生成详细答案
"""
# ... 完整的RAG流程
4. 成本控制
监控和限制API调用:
class APIBudgetManager:
def __init__(self, daily_limit: int):
self.daily_limit = daily_limit
self.used_today = 0
def can_call_api(self) -> bool:
return self.used_today < self.daily_limit
def record_call(self):
self.used_today += 1
def should_use_cache_only(self) -> bool:
# 如果接近限额,只使用缓存
return self.used_today > self.daily_limit * 0.9
5. 质量评估
评估检索到的内容的质量和相关性:
def assess_relevance(doc: Document, query: str) -> float:
"""
评估文档与查询的相关性得分
"""
prompt = f"""
评估以下文档与查询的相关性,给出0-1的分数:
查询:{query}
文档摘要:{doc.page_content[:500]}
只输出数字分数。
"""
score = float(llm.generate(prompt))
return score
def filter_low_quality(docs: List[Document], query: str, threshold: float = 0.6):
"""
过滤低相关性的文档
"""
scored_docs = [(doc, assess_relevance(doc, query)) for doc in docs]
return [doc for doc, score in scored_docs if score >= threshold]
实战案例
案例1:金融分析助手
某金融公司构建了混合RAG系统,用于分析师查询:
内部知识库:
- 公司的研究报告
- 内部数据库和模型
外部检索:
- 实时股价和财报(通过SERP API)
- 最新新闻和分析
- 监管公告
典型查询:"分析腾讯最新财报,结合我们的评级模型,给出投资建议"
系统行为:
- 查询分析:识别为混合查询
- 内部检索:获取公司对腾讯的历史评级和模型
- 外部检索:搜索"腾讯2024Q3财报",提取完整财报内容
- 融合分析:结合财报数据和内部模型,生成投资建议
价值:分析师的研究时间从4小时缩短至30分钟,同时保证了信息的时效性和分析的一致性。
案例2:客户支持系统
某SaaS公司的客服AI:
内部知识库:
- 产品文档
- 常见问题FAQ
- 历史工单
外部检索:
- 产品更新日志(官方博客)
- 社区讨论
- 第三方评测
典型查询:"新版本的API限流策略是什么?"
系统行为:
- 内部检索:查找产品文档中的限流说明
- 外部检索:搜索官方博客的最新更新公告
- 融合答案:如果外部找到更新信息,以外部为准,并注明"根据最新公告(链接),限流策略已更新为…"
价值:即使内部文档未及时更新,系统也能提供最新信息,客服答案准确率从85%提升至95%。
案例3:学术研究助手
某大学的AI研究助手:
内部知识库:
- 学校图书馆的论文数据库
- 课程资料
外部检索:
- arXiv最新论文
- Google Scholar
- 学术新闻
典型查询:"多模态大模型的最新进展是什么?"
系统行为:
- 内部检索:查找本地已有的相关论文
- 外部检索:搜索arXiv最近3个月的论文
- 深度阅读:提取5篇最相关论文的摘要和结论
- 综合报告:生成包含最新进展、关键技术、代表性论文的综述
价值:学生和研究者能快速了解领域前沿,文献综述时间从1周缩短至1天。
挑战与应对
挑战1:信息冲突
内外部信息可能存在矛盾。
应对:
- 优先级策略:明确哪个来源更权威
- 时效性优先:对于动态信息,外部新信息优先
- 明确标注:告诉用户信息来源和可能的矛盾
挑战2:外部内容质量
互联网上的信息质量参差不齐。
应对:
- 来源白名单:优先检索权威网站
- 质量过滤:使用relevance scoring过滤低质量内容
- 多源验证:关键信息从多个来源验证
挑战3:成本控制
频繁的SERP和Reader API调用会产生成本。
应对:
- 智能缓存:减少重复调用
- 渐进加载:先snippet后全文
- 预算管理:设置每日调用上限
详细的成本优化策略参考LLM成本优化指南。
未来演进
高级RAG正在向以下方向发展:
多模态融合:不仅检索文本,还包括图片、视频、音频。
主动更新:系统主动监控关键主题,自动更新知识库。
个性化检索:根据用户的角色、历史,定制检索策略。
解释性增强:不仅给出答案,更解释推理过程,让用户理解AI是如何得出结论的。
构建高级RAG系统,是迈向真正智能的AI应用的关键一步。那些能够有效融合内外部知识,动态获取最新信息的系统,将在实际应用中展现出巨大优势。
相关资源
RAG技术:
API集成:
- SERP API入门 – 搜索API
- SERP+Reader组合 – 黄金搭档
- AI Agent集成 – 集成指南
实战应用:
SearchCans提供高性价比的Bing搜索API和Reader API服务,专为AI Agent和开发者打造。立即体验 →