每日新闻 / 2026-06-15

RAG 搭建教程:从文档向量化到上下文注入,构建可生产部署的完整管道

XycAi
RAG 搭建教程:从文档向量化到上下文注入,构建可生产部署的完整管道

很多人第一次搭 RAG 系统,卡在"跑通了但效果差"的阶段——召回的文档不对,模型答非所问,或者一放到生产环境就崩。这篇文章把一个完整的 RAG 搭建教程拆成四个关键环节,每个环节给出具体参数和取舍逻辑,目标是搭出能实际上线的管道,而不是 demo。

Chunking:切错了,后面全白费

文档切分是整条链路里最被低估的步骤。chunk 切得太大,embedding 语义模糊;切得太小,上下文碎片化,检索出来的片段没有足够信息让模型回答。

**固定长度切分(Fixed-size chunking)**适合结构化不强的长文本,推荐 chunk size 设 512 token,overlap 设 64~128 token。overlap 的作用是防止关键信息恰好落在两个 chunk 的边界被截断。

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=512,
    chunk_overlap=128,
    length_function=len,
)
chunks = splitter.split_text(raw_text)

**语义切分(Semantic chunking)**更适合技术文档或有明确段落结构的内容:按标题层级、段落边界切分,同一语义单元不被拆散。代价是实现复杂度高一些,适合文档质量稳定的场景。

实际工程里的建议:先用固定切分跑基线,评估召回质量后再决定是否引入语义切分。不要一上来就过度工程化。


向量化:Embedding 模型的选型与部署

Embedding 是把 chunk 映射到高维向量空间,检索时计算 query 和 chunk 向量的余弦相似度。

主流选择:

模型 维度 适用场景 接入方式
text-embedding-3-large 3072 英文/多语言高精度 OpenAI API
text-embedding-3-small 1536 成本敏感场景 OpenAI API
BAAI/bge-m3 1024 中文强,支持离线 HuggingFace / 本地部署

对于中文文档,bge-m3 的效果通常比 OpenAI 的通用 embedding 更稳定,且可以本地部署,规避数据出境合规风险。

向量存储选 QdrantWeaviate 都可以。如果是快速原型,FAISS + 内存索引也够用,但不支持实时更新。生产环境推荐 Qdrant,支持 payload 过滤、持久化和水平扩展。

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams

client = QdrantClient(url="http://localhost:6333")
client.create_collection(
    collection_name="docs",
    vectors_config=VectorParams(size=1024, distance=Distance.COSINE),
)

检索 + 重排序:两阶段让召回质量上一个台阶

单靠向量检索(ANN 近似近邻搜索)召回 top-k,精度往往不够。原因是 embedding 空间对语义的压缩是有损的,尤其遇到专业术语或短查询时,相似度排名靠前的 chunk 未必是最相关的。

标准做法是两阶段检索

  1. 粗检索:用向量检索捞出 top-20~50 个候选 chunk
  2. 精排(Reranking):用 Cross-Encoder 模型对 query 和每个候选 chunk 做精细打分,取 top-3~5 送入上下文
from sentence_transformers import CrossEncoder

reranker = CrossEncoder("BAAI/bge-reranker-v2-m3")
pairs = [(query, chunk) for chunk in candidates]
scores = reranker.predict(pairs)

# 取 top-5
ranked = sorted(zip(scores, candidates), reverse=True)[:5]
final_chunks = [chunk for _, chunk in ranked]

bge-reranker-v2-m3 在中文场景下表现稳定,推理延迟在 GPU 上约 50~100ms(批量 20 条),CPU 部署约 300~500ms,可以接受。

**Hybrid Search(混合检索)**是另一个值得加的优化:把向量检索和 BM25 关键词检索的结果用 RRF(Reciprocal Rank Fusion)融合。关键词检索对精确匹配(产品型号、人名、代码片段)的召回更稳,两者互补。


上下文注入与 Prompt 工程

检索完成后,把 final_chunks 组装进 prompt,这一步的细节决定最终生成质量。

上下文注入的几个工程细节

system_prompt = """你是一个文档问答助手。
只根据以下提供的文档内容回答问题。
如果文档中没有足够信息,请直接说"文档中未找到相关内容",不要猜测。"""

context = "\n\n".join([
    f"[来源: {meta['source']}]\n{chunk}"
    for chunk, meta in final_chunks
])

user_prompt = f"文档内容:\n{context}\n\n问题:{query}"

调用模型时,Claude Sonnet 4.6 和 GPT-5.4 在长上下文理解和指令遵循上都表现稳定,适合生产场景。温度建议设 0~0.2,确保回答可复现。


生产部署的几个关键检查项

RAG 管道跑通之后,上生产前需要过几个检查点:

延迟预算:端到端 P95 延迟目标控制在 3s 以内。向量检索通常 <50ms,reranking 约 100~500ms,LLM 生成是大头(1~2s)。如果 reranking 拖慢响应,可以异步预计算或缩减候选数量。

索引更新策略:文档更新时,增量 upsert 而不是全量重建。Qdrant 支持按 document_id 做向量更新,配合文档 hash 做变更检测,可以做到分钟级同步。

评估体系:上线前跑一轮离线评估,核心指标看 Recall@5(top-5 是否包含正确 chunk)和 Answer Faithfulness(生成答案是否有幻觉)。用 RAGAS 框架可以快速建起评估流水线。

监控:生产中记录每条 query 的检索结果 ID 和 rerank 分数,方便排查召回失败的 case。


搭完这条管道之后,你会发现 API 调用成本是持续运营的主要变量——尤其是 embedding 批量写入和 LLM 生成这两块。我自己用 XycAi 词元平台(https://www.xyc.ai)接入主力模型,GPT-5.4 和 Claude Sonnet 4.6 的价格低至官方价 1.4 折起,OpenAI 兼容接口,换一行 base_url 就能切换,Claude Code 和 Codex 也支持直连。对于要跑大量文档写入或多租户 RAG 服务的项目,成本差距相当可观,感兴趣可以看看。

一个 API 接入 200+ 全球 AI 模型

GPT · Claude · Gemini 官方模型低至 1.4 折起,持大模型算法备案号,CN2 直连低至 5ms,可开全球合规发票。

立即体验 XycAi →