RAG(检索增强生成)是当前大模型开发中解决幻觉问题的主流方案。通过将外部知识库与大语言模型结合,RAG让AI模型在生成回答前先检索相关文档,显著提升事实准确性。本文拆解RAG系统的完整搭建流程,涵盖向量数据库选型、Embedding模型配置、检索策略优化和Prompt工程调优。
RAG系统架构与核心组件
一个完整的RAG系统包含三个核心模块:文档处理与向量化、语义检索、生成回答。文档处理阶段将原始文本切分为chunk,通过Embedding模型转为向量存入向量数据库。检索阶段将用户查询同样向量化,在数据库中计算相似度召回相关chunk。生成阶段将召回内容拼入Prompt,交由大模型生成最终回答。
关键技术决策点在于:向量数据库的选择、chunk切分策略、Embedding模型质量、检索top-k值、以及Prompt模板设计。每个环节都直接影响最终回答质量。
向量数据库选型对比:Milvus vs Chroma vs Weaviate
向量数据库是RAG的存储底座。三款主流方案各有适用场景:
Milvus适合大规模生产环境,支持十亿级向量检索,分布式架构可水平扩展。部署成本较高,适合企业级应用。Chroma轻量易用,单机即可运行,适合中小型项目和原型验证。Weaviate内置GraphQL接口,支持混合检索(向量+关键词),适合需要复杂查询的场景。
以下以Milvus为例演示向量存储与检索的核心代码:
from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection
# 连接Milvus
connections.connect(host="localhost", port="19530")
# 定义Collection结构
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536),
FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=2048),
FieldSchema(name="source", dtype=DataType.VARCHAR, max_length=256)
]
schema = CollectionSchema(fields, "RAG知识库")
collection = Collection("rag_knowledge", schema)
# 创建IVF索引
collection.create_index(
field_name="embedding",
index_params={
"index_type": "IVF_FLAT",
"metric_type": "COSINE",
"params": {"nlist": 1024}
}
)
# 插入向量数据
collection.insert([
[i for i in range(len(embeddings))],
embeddings,
text_chunks,
sources
])
collection.load()
# 语义检索
search_params = {"metric_type": "COSINE", "params": {"nprobe": 16}}
results = collection.search(
data=[query_embedding],
anns_field="embedding",
param=search_params,
limit=5,
output_fields=["text", "source"]
)
文档切分策略对检索质量的影响
chunk切分是RAG中容易被忽视但至关重要的环节。切分粒度过粗,单个chunk包含过多信息,检索时噪声大;切分过细,上下文断裂,语义信息丢失。
实际工程中推荐以下策略:
固定长度切分(512-1024 token)配合重叠窗口(50-100 token),保证chunk间语义连续性。按段落或标题切分,保持文档结构完整性。对于代码、表格等结构化内容,使用专门的解析器而非简单文本切分。
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=64,
separators=["\n\n", "\n", "。", "!", "?", ";", " ", ""],
length_function=len
)
chunks = text_splitter.split_text(document_text)
print(f"切分结果: {len(chunks)}个chunk")
for i, chunk in enumerate(chunks[:3]):
print(f" Chunk {i}: {len(chunk)}字符, 预览: {chunk[:80]}...")
Embedding模型选择与部署
Embedding质量直接决定检索准确性。OpenAI的text-embedding-3-small性价比高,1024维向量即可满足大部分场景。开源方案中BGE-large-zh-v1.5在中文场景表现优异,可在本地GPU部署。
部署本地Embedding服务时,使用HuggingFace Transformers加载模型并封装为API:
from sentence_transformers import SentenceTransformer
import torch
# 加载BGE中文模型
model = SentenceTransformer('BAAI/bge-large-zh-v1.5', device='cuda')
# 批量生成向量
texts = ["人工智能模型部署方案", "数据库性能优化方法"]
embeddings = model.encode(texts, normalize_embeddings=True)
print(f"向量维度: {embeddings.shape}") # (2, 1024)
print(f"余弦相似度: {torch.cosine_similarity(
torch.tensor(embeddings[0]),
torch.tensor(embeddings[1]), dim=0
)}")
检索策略优化:从纯向量检索到混合检索
纯向量检索在处理专有名词、代码标识符等场景时效果有限。混合检索结合BM25关键词匹配和向量语义检索,通过加权融合提升召回率。
from rank_bm25 import BM25Okapi
import numpy as np
# BM25检索
tokenized_corpus = [doc.split() for doc in text_chunks]
bm25 = BM25Okapi(tokenized_corpus)
bm25_scores = bm25.get_scores(query.split())
# 向量检索
vector_scores = cosine_similarity(query_embedding, doc_embeddings)
# 加权融合
alpha = 0.5
final_scores = alpha * normalize(vector_scores) + (1 - alpha) * normalize(bm25_scores)
top_k = 5
top_indices = np.argsort(final_scores)[-top_k:][::-1]
retrieved_chunks = [text_chunks[i] for i in top_indices]
Prompt工程:如何将检索结果送入大模型
检索到的chunk需要合理组装到Prompt中。核心原则:明确告诉模型只能基于提供的上下文回答,无法回答时承认不确定性。
prompt_template = '''你是一个技术问答助手。请严格根据以下参考资料回答问题。
如果参考资料中没有相关信息,请明确回答"根据现有资料无法回答该问题",不要编造内容。
参考资料:
{context}
问题:{question}
回答:'''
context_text = "\n\n---\n\n".join([
f"[来源: {chunk.metadata.get('source', '未知')}\n内容: {chunk.page_content}]"
for chunk in retrieved_chunks
])
final_prompt = prompt_template.format(context=context_text, question=user_question)
response = llm.generate(final_prompt)
Prompt设计中有几个实操要点:context部分加入来源标记,便于追溯信息出处;使用分隔符清晰区分参考资料和问题;设定role-play约束模型行为;在system message中定义输出格式要求。
RAG评估指标与调优方向
评估RAG系统需要从检索和生成两个维度衡量。检索质量看召回率(Recall@k)和精确率(Precision@k),通过人工标注的query-doc对计算。生成质量看答案准确率、相关性、完整性,可通过LLM自动评估或人工评分。
常见调优方向:增大top-k值提升召回但有噪声风险,需要rerank模型做二次排序;引入query改写扩展检索意图;对长文档构建层次化索引,先检索摘要再检索细节段落。
RAG系统的搭建不是一次性工作,需要持续迭代优化。从文档切分策略到检索融合权重,每个参数都需根据实际数据特点调整。核心思路是建立评估闭环:修改参数-评估效果-迭代优化,用数据驱动决策而非凭感觉调参。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/rag-jian-suo-zeng-qiang-sheng-cheng-shi-zhan-cong-xiang/