关于 rag-implementation
面向构建 RAG 应用的技能,指导开发者将外部知识接入 LLM,以生成有依据的回答。内容涵盖数据切分、向量检索、重排和效果评估。
主要功能
- 01设计语料与评估目标
- 02选择嵌入模型和向量库
- 03构建切分与检索流程
- 04采用混合检索和重排
- 05评估依据性并监控漂移
适用场景
- 01为内部文档构建问答系统
- 02创建提供最新事实的聊天机器人
- 03为文档助手添加来源引用
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ rmyndharis/ antigravity-skills --skill rag-implementation安装后在 Claude Code 中输入/rag-implementation确认已加载。
详细介绍
RAG 实现
掌握检索增强生成(RAG),构建基于外部知识源提供准确、有据可依回答的大模型应用。
适用场景
- 基于专有文档构建问答系统
- 创建能够提供最新、准确事实信息的聊天机器人
- 使用自然语言查询实现语义搜索
- 通过提供有据可依的回答减少幻觉
- 让大模型能够访问特定领域的知识
- 构建文档助手
- 创建带有来源引用的研究工具
不适用场景
- 只需要纯生成式写作,无需检索
- 数据集太小,不值得使用嵌入
- 无法安全存储或处理源数据
说明
- 明确语料库、更新频率和评估目标。
- 根据规模选择嵌入模型和向量存储。
- 构建包含重排序的摄取、分块和检索流程。
- 使用有据可依的问答指标进行评估,并监控偏移。
安全
- 对敏感数据进行脱敏,并实施访问控制。
- 如果受到限制,请勿在回答中暴露源文档。
核心组件
1. 向量数据库
用途:高效存储和检索文档嵌入
选项:
- Pinecone:托管式、可扩展、查询速度快
- Weaviate:开源、混合搜索
- Milvus:高性能、可本地部署
- Chroma:轻量、易用
- Qdrant:搜索快速,支持筛选
- FAISS:Meta 的库,可本地部署
2. 嵌入
用途:将文本转换为用于相似度搜索的数值向量
模型:
- text-embedding-ada-002(OpenAI):通用型,1536 维
- all-MiniLM-L6-v2(Sentence Transformers):快速、轻量
- e5-large-v2:高质量、多语言
- Instructor:针对任务提供指令
- bge-large-en-v1.5:SOTA 性能
3. 检索策略
方法:
- 稠密检索:通过嵌入计算语义相似度
- 稀疏检索:关键词匹配(BM25、TF-IDF)
- 混合搜索:结合稠密检索和稀疏检索
- 多查询:生成多个查询变体
- HyDE:生成假设文档
4. 重排序
用途:通过重新排列结果来提升检索质量
方法:
- Cross-Encoder:基于 BERT 的重排序
- Cohere Rerank:基于 API 的重排序
- 最大边际相关性(MMR):兼顾多样性和相关性
- 基于大模型:使用大模型评估相关性
快速入门
from langchain.document_loaders import DirectoryLoader
from langchain.text_splitters import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 1. Load documents
loader = DirectoryLoader('./docs', glob="**/*.txt")
documents = loader.load()
# 2. Split into chunks
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len
)
chunks = text_splitter.split_documents(documents)
# 3. Create embeddings and vector store
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings)
# 4. Create retrieval chain
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(),
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 4}),
return_source_documents=True
)
# 5. Query
result = qa_chain({"query": "What are the main features?"})
print(result['result'])
print(result['source_documents'])
高级 RAG 模式
模式 1:混合搜索
from langchain.retrievers import BM25Retriever, EnsembleRetriever
# Sparse retriever (BM25)
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 5
# Dense retriever (embeddings)
embedding_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# Combine with weights
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, embedding_retriever],
weights=[0.3, 0.7]
)
模式 2:多查询检索
from langchain.retrievers.multi_query import MultiQueryRetriever
# Generate multiple query perspectives
retriever = MultiQueryRetriever.from_llm(
retriever=vectorstore.as_retriever(),
llm=OpenAI()
)
# Single query → multiple variations → combined results
results = retriever.get_relevant_documents("What is the main topic?")
模式 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()
)
# Returns only relevant parts of documents
compressed_docs = compression_retriever.get_relevant_documents("query")
模式 4:父文档检索器
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
# Store for parent documents
store = InMemoryStore()
# Small chunks for retrieval, large chunks for context
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter
)
文档分块策略
递归字符文本拆分器
from langchain.text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
separators=["\n\n", "\n", " ", ""] # Try these in order
)
基于 Token 的拆分
from langchain.text_splitters import TokenTextSplitter
splitter = TokenTextSplitter(
chunk_size=512,
chunk_overlap=50
)
语义分块
from langchain.text_splitters import SemanticChunker
splitter = SemanticChunker(
embeddings=OpenAIEmbeddings(),
breakpoint_threshold_type="percentile"
)
Markdown 标题拆分器
from langchain.text_splitters import MarkdownHeaderTextSplitter
headers_to_split_on = [
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]
splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
向量存储配置
Pinecone
import pinecone
from langchain.vectorstores import Pinecone
pinecone.init(api_key="your-api-key", environment="us-west1-gcp")
index = pinecone.Index("your-index-name")
vectorstore = Pinecone(index, embeddings.embed_query, "text")
Weaviate
import weaviate
from langchain.vectorstores import Weaviate
client = weaviate.Client("http://localhost:8080")
vectorstore = Weaviate(client, "Document", "content", embeddings)
Chroma(本地)
from langchain.vectorstores import Chroma
vectorstore = Chroma(
collection_name="my_collection",
embedding_function=embeddings,
persist_directory="./chroma_db"
)
检索优化
1. 元数据筛选
# Add metadata during indexing
chunks_with_metadata = []
for i, chunk in enumerate(chunks):
chunk.metadata = {
"source": chunk.metadata.get("source"),
"page": i,
"category": determine_category(chunk.page_content)
}
chunks_with_metadata.append(chunk)
# Filter during retrieval
results = vectorstore.similarity_search(
"query",
filter={"category": "technical"},
k=5
)
2. 最大边际相关性
# Balance relevance with diversity
results = vectorstore.max_marginal_relevance_search(
"query",
k=5,
fetch_k=20, # Fetch 20, return top 5 diverse
lambda_mult=0.5 # 0=max diversity, 1=max relevance
)
3. 使用 Cross-Encoder 进行重排序
from sentence_transformers import CrossEncoder
reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
# Get initial results
candidates = vectorstore.similarity_search("query", k=20)
# Rerank
pairs = [[query, doc.page_content] for doc in candidates]
scores = reranker.predict(pairs)
# Sort by score and take top k
reranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)[:5]
RAG 提示词工程
上下文提示词
prompt_template = """Use the following context to answer the question. If you cannot answer based on the context, say "I don't have enough information."
Context:
{context}
Question: {question}
Answer:"""
包含引用
prompt_template = """Answer the question based on the context below. Include citations using [1], [2], etc.
Context:
{context}
Question: {question}
Answer (with citations):"""
包含置信度
prompt_template = """Answer the question using the context. Provide a confidence score (0-100%) for your answer.
Context:
{context}
Question: {question}
Answer:
Confidence:"""
评估指标
def evaluate_rag_system(qa_chain, test_cases):
metrics = {
'accuracy': [],
'retrieval_quality': [],
'groundedness': []
}
for test in test_cases:
result = qa_chain({"query": test['question']})
# Check if answer matches expected
accuracy = calculate_accuracy(result['result'], test['expected'])
metrics['accuracy'].append(accuracy)
# Check if relevant docs were retrieved
retrieval_quality = evaluate_retrieved_docs(
result['source_documents'],
test['relevant_docs']
)
metrics['retrieval_quality'].append(retrieval_quality)
# Check if answer is grounded in context
groundedness = check_groundedness(
result['result'],
result['source_documents']
)
metrics['groundedness'].append(groundedness)
return {k: sum(v)/len(v) for k, v in metrics.items()}
资源
- references/vector-databases.md:向量数据库详细对比
- references/embeddings.md:嵌入模型选择指南
- references/retrieval-strategies.md:高级检索技术
- references/reranking.md:重排序方法及其适用场景
- references/context-window.md:管理上下文限制
- assets/vector-store-config.yaml:配置模板
- assets/retriever-pipeline.py:完整的 RAG 流水线
- assets/embedding-models.md:模型对比和基准测试
最佳实践
- 分块大小:在上下文和具体程度之间取得平衡(500-1000 个 token)
- 重叠:使用 10-20% 的重叠,以保留边界处的上下文
- 元数据:包含来源、页面和时间戳,以便筛选和调试
- 混合搜索:结合语义搜索和关键词搜索,以获得最佳结果
- 重排序:使用交叉编码器改进排名靠前的结果
- 引用:始终返回来源文档,以提高透明度
- 评估:持续测试检索质量和回答准确性
- 监控:跟踪生产环境中的检索指标
常见问题
- 检索效果差:检查嵌入质量、分块大小和查询表述
- 结果不相关:添加元数据筛选、使用混合搜索并重新排序
- 信息缺失:确保文档已正确编入索引
- 查询缓慢:优化向量存储、使用缓存并减小 k 值
- 幻觉:改进 grounding 提示词,并添加验证步骤
评论
支持 Markdown