RAG系统怎么搭建?老金手把手教你从0到1构建企业知识库

8次阅读
没有评论

一、 开场:一个让我彻夜难眠的问题

大家好,我是老金。

上周有个客户找到我,问了一个让我头疼的问题:

“老金,我们公司有20年的技术文档、产品手册、客服话术,加起来几百万字。能不能做个AI,让员工直接问问题,AI自动从这些文档里找答案?”

我当时的第一反应是:这不就是RAG吗?

但当我真正深入这个需求后,我发现——

RAG系统,远没有网上那些”5分钟搭建RAG”教程说的那么简单。

今天这篇文章,我想把我在这个项目中踩过的坑、积累的经验,系统地分享出来。

目标是:让你看完这篇文章,真的能从0到1搭建一套生产级的RAG系统。

二、 什么是RAG?为什么需要RAG?

2.1 RAG的核心概念

RAG = Retrieval-Augmented Generation,检索增强生成。

说白了就是:先检索,再生成

传统的大模型(如GPT-4)有两个致命问题:

  1. 知识有截止日期:GPT-4的知识库截止到2023年,2024年发生的事它不知道
  2. 没有你的私有数据:公司的内部文档、产品信息,GPT-4从来没见过

RAG的解决方案是:

  1. 把你的私有文档切成小块,存入向量数据库
  2. 用户提问时,先从向量数据库检索相关内容
  3. 把检索到的内容作为”上下文”,喂给大模型
  4. 大模型基于这些上下文,生成准确的回答

2.2 RAG vs 微调 vs 长上下文

很多团队会纠结:我是用RAG,还是微调模型,还是等长上下文模型成熟?

我的建议:

方案 适用场景 成本 时效性
RAG 知识频繁更新、需要引用来源 实时
微调 特定任务、知识相对稳定 更新慢
长上下文 文档量小(<10万字) 高(Token费) 实时

对于企业知识库这种场景,RAG是最佳选择。

三、 RAG系统的核心架构

一个完整的RAG系统,包含以下模块:

用户提问 → Embedding → 向量检索 → 重排序 → 上下文构建 → LLM生成 → 回答
            ↑
        文档入库流程:
        文档 → 分块 → Embedding → 向量数据库

让我逐一拆解每个环节的技术选型和踩坑经验。

四、 第一步:文档处理与分块

4.1 分块策略的选择

这是RAG系统最容易被忽视的环节,但直接影响检索质量。

常见的分块策略:

  • 固定长度分块:每512个token一块(最简单,但效果一般)
  • 语义分块:按段落、章节分割(效果好,但需要解析文档结构)
  • 滑动窗口:有重叠的分块(解决信息被切断的问题)
  • 父文档检索:小块检索,大块返回(LangChain推荐方案)

4.2 我的踩坑经验

在客户项目中,我一开始用固定长度分块,结果:

  • 一段完整的技术说明被切成了两块
  • 检索时只找到了前半部分,答案不完整

后来我改用语义分块 + 滑动窗口

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter( chunk_size=500, # 每块500字符 chunk_overlap=100, # 重叠100字符 separators=["nn", "n", "。", "!", "?", ";", ",", " ", ""] )

chunks = text_splitter.split_text(document)

效果提升明显:检索准确率从65%提升到82%。

五、 第二步:Embedding模型选择

Embedding模型的选择,直接影响检索质量。

5.1 主流Embedding模型对比

模型 维度 中文效果 成本
OpenAI text-embedding-3-small 1536 中等 $0.02/1M tokens
OpenAI text-embedding-3-large 3072 较好 $0.13/1M tokens
BGE-large-zh 1024 优秀 免费(开源)
M3E-large 1024 优秀 免费(开源)

5.2 我的推荐

中文场景,首选BGE系列。

原因:

  1. 中文效果好,在C-MTEB榜单上名列前茅
  2. 开源免费,无Token成本
  3. 可以本地部署,数据不出域
from sentence_transformers import SentenceTransformer

加载BGE模型

model = SentenceTransformer('BAAI/bge-large-zh-v1.5')

生成向量

embeddings = model.encode(chunks)

六、 第三步:向量数据库选型

6.1 主流向量数据库对比

数据库 适用场景 优点 缺点
Chroma 原型开发、小规模 轻量、易上手 性能有限
Milvus 生产环境、大规模 高性能、分布式 部署复杂
Weaviate 企业级、混合检索 支持多种检索 资源占用大
Pinecone SaaS、快速上线 全托管 贵、数据出境

6.2 我的选择

对于客户项目,我选择了Milvus

  • 数据量大(百万级文档)
  • 需要高性能(QPS > 1000)
  • 要求数据不出域
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType

连接Milvus

connections.connect("default", host="localhost", port="19530")

创建集合

fields = [ FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True), FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1024), FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=2000), FieldSchema(name="metadata", dtype=DataType.JSON) ] schema = CollectionSchema(fields, "knowledge_base") collection = Collection("docs", schema)

创建向量索引

index_params = { "metric_type": "COSINE", "index_type": "IVF_FLAT", "params": {"nlist": 1024} } collection.create_index("embedding", index_params)

七、 第四步:检索与重排序

7.1 为什么需要重排序?

向量检索是语义相似,不等于问题相关

举个例子:

  • 用户问:”如何处理客户投诉?”
  • 向量检索返回了10条结果,其中第1条是”客户投诉的常见类型”,第8条才是”客户投诉处理流程”

这时候,就需要重排序模型来重新打分

7.2 重排序模型选择

推荐使用BGE-Reranker

from sentence_transformers import CrossEncoder

加载重排序模型

reranker = CrossEncoder('BAAI/bge-reranker-large')

对检索结果重排序

query = "如何处理客户投诉?" candidates = [doc1, doc2, doc3, ...] # 向量检索返回的文档

计算相关性分数

scores = reranker.predict([(query, doc) for doc in candidates])

按分数排序

ranked_results = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)

7.3 混合检索

更高级的做法是向量检索 + 关键词检索混合:

  • 向量检索:语义匹配,召回率高
  • 关键词检索:精确匹配,准确率高

两者结合,效果最佳。

八、 第五步:Prompt设计与上下文构建

8.1 Prompt模板

一个标准的RAG Prompt:

你是一个专业的企业知识库助手。请根据以下上下文回答用户问题。

上下文: {context}

用户问题: {question}

要求:

  1. 只基于上下文回答,不要编造信息
  2. 如果上下文中没有相关信息,请明确告知用户
  3. 回答要简洁、准确、有条理
  4. 如果引用上下文内容,请标注来源

8.2 上下文构建策略

核心问题:上下文窗口有限,如何选择最相关的文档?

我的策略:

  1. 检索Top 20文档
  2. 重排序后取Top 5
  3. 按相关性分数加权组合
  4. 总Token数控制在3000以内

九、 完整代码示例

from langchain.vectorstores import Milvus
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import CrossEncoderReranker

1. 初始化Embedding模型

embeddings = HuggingFaceEmbeddings( model_name="BAAI/bge-large-zh-v1.5" )

2. 连接向量数据库

vectorstore = Milvus( embedding_function=embeddings, collection_name="knowledge_base", connection_args={"host": "localhost", "port": "19530"} )

3. 创建检索器

base_retriever = vectorstore.as_retriever( search_kwargs={"k": 20} # 检索Top 20 )

4. 添加重排序

reranker = CrossEncoderReranker( model_name="BAAI/bge-reranker-large", top_n=5 # 重排序后取Top 5 ) retriever = ContextualCompressionRetriever( base_compressor=reranker, base_retriever=base_retriever )

5. 构建RAG链

from langchain.chains import RetrievalQA from langchain.llms import OpenAI

qa_chain = RetrievalQA.from_chain_type( llm=OpenAI(temperature=0), retriever=retriever, return_source_documents=True )

6. 提问

result = qa_chain({"query": "客户投诉的标准处理流程是什么?"}) print(result["result"]) print(result["source_documents"])

十、 生产环境优化建议

10.1 性能优化

  • 向量索引优化:使用HNSW索引,检索速度提升10倍
  • 缓存机制:相同问题缓存答案,减少LLM调用
  • 批处理:Embedding批量计算,提升吞吐量

10.2 质量优化

  • 文档清洗:去除无关内容、格式化
  • 分块调优:根据文档类型选择最佳分块策略
  • 评估体系:建立RAG评估指标(准确率、召回率、相关性)

10.3 运维监控

  • 检索延迟监控:P99 < 200ms
  • 答案质量监控:用户满意度 > 85%
  • 成本监控:Token消耗告警

十一、 写在最后

RAG系统搭建,不是简单的”调API”,而是一个需要精细调优的系统工程

从文档处理、Embedding选择、向量数据库、重排序、Prompt设计——每个环节都有坑。

但一旦搭建好,它的价值是巨大的:

  • 员工再也不用在几十万字的文档里大海捞针
  • 新员工入职,AI就是最耐心的老师
  • 知识沉淀,变成企业的核心竞争力

如果你也在搭建RAG系统,欢迎在评论区分享你的经验或问题。

我是技术老金,我们下期见!


📌 往期精彩回顾

正文完
 0
技术老金
版权声明:本站原创文章,由 技术老金 于2026-03-26发表,共计4855字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)