📚 RAG:给AI装上"图书馆"
"世界上有一种知识,AI本来不知道。但你给它一座图书馆,它就能装得像个博学家。这,就是RAG。"
📖 定义:什么是RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种让AI在回答问题之前,先从外部知识库中检索相关信息的技术。
想象一下考试:
- ❌ 闭卷考试(纯LLM):全靠记忆,记错了就答错
- ✅ 开卷考试(RAG):可以查资料,答案更准确
💡 一句话理解:RAG = AI的图书馆系统。它让AI先查资料再回答,告别"一本正经地胡说八道"。
⚙️ 为什么需要RAG?
LLM的三大痛点
- 知识截止:GPT-4的知识停在2024年,不知道最新事件
- 幻觉问题:AI会编造听起来像真的但其实是假的信息
- 私有知识:公司内部的文档、数据库,LLM本来不知道
RAG的解决方案
- ✅ 实时更新:知识库随时更新,AI永远用最新信息
- ✅ 有据可查:每个回答都能追溯到原文出处
- ✅ 私有化:可以接入企业内部文档和数据
🏗️ RAG架构:两大阶段
阶段一:Indexing(索引构建)
把知识装进"图书馆":
┌─────────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 原始文档 │ → │ 分块 │ → │ Embedding│ → │ 向量数据库│ │ (PDF/Word/ │ │ (Chunk) │ │ (向量化) │ │(存储) │ │ Web/...) │ └──────────┘ └──────────┘ └──────────┘ └─────────────┘
1. 文档加载(Load)
从各种来源加载文档:
from langchain.document_loaders import (
PyPDFLoader, # PDF文件
TextLoader, # 文本文件
WebBaseLoader, # 网页
NotionLoader # Notion文档
)
# 加载PDF
docs = PyPDFLoader("manual.pdf").load()
# 加载网页
docs = WebBaseLoader("https://docs.openclaw.ai").load()
2. 文档分块(Split)
把长文档切成适合处理的小块:
from langchain.text_splitter import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000, # 每块1000字符
chunk_overlap=200 # 重叠200字符(保持上下文)
)
chunks = splitter.split_documents(docs)
3. 向量化(Embed)
把文本变成向量(数字表示语义):
from langchain.embeddings import OpenAIEmbeddings embeddings = OpenAIEmbeddings() # "猫" → [0.12, -0.34, 0.56, ...] # 1536维向量 # "狗" → [0.15, -0.31, 0.52, ...] # 相似的向量
4. 存储(Store)
存入向量数据库:
from langchain.vectorstores import Chroma, FAISS, Pinecone
# 使用Chroma本地存储
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
阶段二:Retrieval(检索生成)
用户提问时的处理流程:
用户提问 → Embedding → 向量检索 → 取Top-K → 组装Prompt → LLM生成答案
(向量化) (相似度搜索) (相关文档) (增强上下文)
完整流程
# 1. 用户提问
question = "OpenClaw怎么配置多Agent?"
# 2. 向量化查询
query_vector = embeddings.embed_query(question)
# 3. 检索相似文档
relevant_docs = vectorstore.similarity_search(
query=question,
k=4 # 取最相似的4个文档块
)
# 4. 组装增强Prompt
context = "\n\n".join([doc.page_content for doc in relevant_docs])
augmented_prompt = f"""基于以下参考资料回答问题:
参考资料:
{context}
用户问题:{question}
请基于以上资料回答。如果资料中没有相关信息,请明确说明。"""
# 5. LLM生成答案
answer = llm.generate(augmented_prompt)
🚀 OpenClaw实战:RAG集成
场景:企业内部知识库助手
搭建一个能理解公司文档的AI助手:
Step 1:准备知识库
# 目录结构
knowledge_base/
├── products/ # 产品文档
│ ├── openclaw_guide.pdf
│ └── feature_list.md
├── faqs/ # 常见问题
│ └── common_issues.md
└── policies/ # 公司政策
└── refund_policy.pdf
Step 2:构建RAG Pipeline
# rag_builder.py
from langchain.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
class KnowledgeBase:
def __init__(self, docs_path="./knowledge_base"):
self.embeddings = OpenAIEmbeddings()
self.vectorstore = None
self.docs_path = docs_path
def build(self):
"""构建知识库索引"""
# 1. 加载文档
loader = DirectoryLoader(
self.docs_path,
glob="**/*.{pdf,md,txt}",
loader_cls=TextLoader
)
docs = loader.load()
# 2. 分块
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200
)
chunks = splitter.split_documents(docs)
# 3. 存入向量库
self.vectorstore = Chroma.from_documents(
chunks,
self.embeddings,
persist_directory="./kb_index"
)
self.vectorstore.persist()
print(f"✅ 知识库构建完成!共索引 {len(chunks)} 个文档块")
def query(self, question, k=4):
"""查询知识库"""
if not self.vectorstore:
self.vectorstore = Chroma(
persist_directory="./kb_index",
embedding_function=self.embeddings
)
results = self.vectorstore.similarity_search(question, k=k)
return results
# 使用
kb = KnowledgeBase()
kb.build() # 首次运行构建索引
Step 3:OpenClaw Agent配置
agents:
list:
- name: knowledge_assistant
system_prompt: |
你是公司的知识库助手。你会基于提供的参考资料回答用户问题。
回答规则:
1. 严格基于提供的参考资料回答
2. 如果资料中没有答案,明确说明"根据现有资料,我无法确定..."
3. 回答时标注信息来源
4. 保持专业、友好的语气
skills:
- rag_query # 自定义RAG查询技能
skills:
rag_query:
description: "查询知识库"
handler: |
from rag_builder import KnowledgeBase
kb = KnowledgeBase()
results = kb.query(query)
return format_results(results)
Step 4:使用示例
用户:"OpenClaw怎么配置MCP?"
Agent处理:
1. 调用 rag_query("OpenClaw怎么配置MCP")
2. 检索到相关文档片段
3. 组装Prompt并生成答案:
"根据《OpenClaw MCP集成指南》,配置MCP需要以下步骤:
1. 在config.yaml中添加mcp.servers配置...
2. 指定command和args参数...
3. 在Agent中启用mcp_servers...
[来源: openclaw_guide.pdf, 第12页]"
💡 高级RAG技巧
1. Hybrid Search(混合检索)
向量检索 + 关键词检索结合:
# 向量检索(语义相似)
vector_results = vectorstore.similarity_search(query, k=10)
# 关键词检索(精确匹配)
keyword_results = bm25_retriever.retrieve(query, k=10)
# 融合排序
final_results = reciprocal_rank_fusion(
vector_results,
keyword_results
)
2. Query重写
优化用户查询以提高检索质量:
# 原始查询:"它怎么配置?"
# 重写后:"OpenClaw MCP Server怎么配置?"
rewritten_query = llm.generate(f"""
将以下查询重写为更具体的搜索查询:
上下文:用户在问OpenClaw相关问题
查询:{query}
""")
3. 上下文压缩
检索到的文档太长,提取关键信息:
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=vectorstore.as_retriever()
)
4. 多跳检索
复杂问题需要多步检索:
# 问题:"OpenClaw MCP支持哪些数据库?" # Step 1: 检索MCP相关信息 # Step 2: 基于Step 1结果,检索数据库支持信息
🎯 RAG优化 checklist
- ☑️ 文档分块大小合适(通常500-1000字符)
- ☑️ 块之间有重叠(保持上下文连贯)
- ☑️ 使用高质量的Embedding模型
- ☑️ 定期更新知识库索引
- ☑️ 添加元数据(来源、日期等)
- ☑️ 实现重排序(Reranking)
- ☑️ 设置相似度阈值(过滤低质量结果)
- ☑️ 记录检索日志(用于优化)
"RAG的本质不是让AI变聪明,而是让AI知道'自己不知道什么',并学会查资料。这才是真正的智慧。"