RAG 入门实战:给大模型外挂一个知识库

举报
yd_237615889 发表于 2026/09/07 15:31:44 2026/09/07
【摘要】 RAG 入门实战:给大模型外挂一个知识库大模型很能说,但它有两个先天缺陷:知识有截止日期(训练之后发生的事一无所知),以及会一本正经地编造(行话叫"幻觉")。问它"咱们公司年假几天",它只会礼貌地胡说八道。微调能注入知识吗?能,但代价高、更新慢——知识库每周都在变,总不能每周重训一次模型。RAG(Retrieval-Augmented Generation,检索增强生成)给出了更聪明的解法:...

RAG 入门实战:给大模型外挂一个知识库

大模型很能说,但它有两个先天缺陷:知识有截止日期(训练之后发生的事一无所知),以及会一本正经地编造(行话叫"幻觉")。问它"咱们公司年假几天",它只会礼貌地胡说八道。

微调能注入知识吗?能,但代价高、更新慢——知识库每周都在变,总不能每周重训一次模型。RAG(Retrieval-Augmented Generation,检索增强生成)给出了更聪明的解法:回答之前,先去你的知识库里把相关资料查出来,塞进提示词,让模型"看着资料答题"。知识更新只需要改库,不用动模型。

这篇把 RAG 从原理到落地讲一遍:流程、切片、向量检索、生成细节、评估方法和最常见的坑。

一、什么场景值得上 RAG

·         企业知识库问答:员工手册、制度、产品文档

·         客服机器人:基于工单和 FAQ 回答

·         文档助手:"帮我在这 200 页规格书里找 XX 参数"

·         代码库问答:基于仓库文档回答实现问题

共同特征:答案存在于你私有的资料里,且资料的更新频率高于重训模型的频率。反过来,如果只是想让模型学会某种输出风格或领域话术,微调更合适;如果只是一次性的长文档问答,直接塞长上下文也行。

维度

RAG

微调

长上下文直塞

知识更新

改库即生效

要重新训练

每次对话都要带全量

成本

低到中

高

token 费用高

可溯源

好,答案能标注出处

差

一般

适合

知识频繁变化、要求出处

学风格、格式、领域语言

一次性长文档

 

二、RAG 的完整流程:先建索引,再查再答

RAG 分两个阶段。离线索引把资料变成可检索的形态;在线检索生成在每次提问时发生。

离线索引(做一次,随文档更新增量做)

·         文档加载与清洗:PDF、Word、网页、数据库记录转成纯文本。这一步的解析质量决定整个系统的上限——扫描件要 OCR,PDF 里的表格要专门处理

·         切片(Chunking):长文档切成几百字的小段,每段是检索的最小单位

·         向量化(Embedding):用 embedding 模型把每个切片变成一个高维向量——语义相近的文本,向量距离就近

·         入库:向量、原文、元数据(来源、时间、部门)一起存进向量库

在线检索生成(每次提问都走一遍)

·         问题向量化:用户的提问同样被转成向量

·         检索:在向量库里找距离最近的 top-k 个切片,混合检索再加关键词一路

·         重排:用交叉编码器把最相关的切片精排到最前面

·         生成:把命中的切片拼进提示词,让模型"看着资料回答",并要求标注引用

一句话记住本质:RAG = 搜索引擎 + 带资料开卷考试。检索质量决定下限,生成环节决定上限。

三、切片:被低估的第一决定因素

大多数 RAG 效果差,问题不在模型,而在切片切得不好。四种常见策略:

策略

做法

适合

固定长度

每 N 个 token 切一刀

快速基线

递归切分

优先按段落切,超长再按句子回退

通用默认,主流框架的缺省做法

按结构切

按标题层级、Markdown 节、表格行切

手册、wiki 等结构规整的文档

语义切分

相邻句子向量突变处下刀

质量优先、不怕成本

 

常见经验值:切片大小 500–1000 token,相邻切片保留 10%–15% 的重叠(overlap),避免答案正好被切在边界上。两个原则比数字更重要:

·         一片一个话题:一段讲年假、一段讲考勤,别混在一起

·         切片自含上下文:检索命中后它是独立给模型看的,"如上文所述"这种切片就是废片——可以在每个切片前拼上它所属的标题路径

四、Embedding 与向量库:怎么存、怎么查

Embedding 模型把文本映射成语义空间里的一个点:"年假天数"和"休假多少天"两个切片字面不同,向量却很近。检索就是"在所有点里找离问题最近的 k 个"。

选型速查:

向量库

形态

适合

FAISS

本地库

原型、研究

Chroma

嵌入式

小项目、快速验证

pgvector

PostgreSQL 扩展

已有 PG,向量数据和业务数据同居

Qdrant

独立服务/托管

生产环境,运维省心

Milvus

分布式服务

亿级向量、大规模生产

 

选 embedding 模型看三件事:主要语言(中文效果差异很大,主流选择如 BGE 系列)、效果与维度(MTEB 之类的榜单可以参考,但务必用自己的数据实测)、成本与私有化要求。注意:换 embedding 模型等于换了一套坐标系,全库必须重新向量化——所以一开始就别拍脑袋。

五、检索环节:别只做"向量最近邻"

纯向量检索有个盲区:产品型号、报错码、人名这类精确词,向量相似度反而不敏感。生产级 RAG 通常做混合检索:向量检索(管语义)+ 关键词检索(BM25,管字面),两路结果合并。再加一道重排(rerank):先用便宜的手段召回 top 20–50,再用交叉编码器精排出 top 3–5。"先广撒网再精排"是当前的主流架构,BGE-reranker、Cohere Rerank 都是这个位置上的常用件。

检索端还有两个实用开关:

·         元数据过滤:按部门、时间、文档类型先过滤再检索——"2024 年之后的通知"这类问题全靠它

·         查询改写:用户问法千奇百怪,先让模型把问题改写、展开成适合检索的形式;多轮对话里还要把"那第二种呢"这种指代补全

六、生成环节:模板里必须有的三句话

拼提示词不是把检索结果一股脑塞进去。模板里这三句话能挡掉一大半事故:

·         只依据资料回答:资料里没有的,明确说"资料中没有提到",不许编

·         标注引用:每个结论注明来自哪条切片,方便人工核对

·         冲突要摆出来:新旧制度在资料里打架时,把冲突说清楚,而不是随机选一个

另外,别把 top-20 全塞进去:上下文越长,模型对每段的注意力越稀薄,中间部分还容易被忽略。精选 3–5 段、按相关性排序,效果通常好于大水漫灌。

七、评估:别凭感觉调参

RAG 系统最容易死于"开发者自己试了十个问题,感觉还行"。至少建一个几十条的小评测集:问题 + 标准答案 + 出处。两层指标分开看:

·         检索层:该命中的切片有没有进 top-k(召回率)、最好的切片排多前(MRR)。检索不对,生成必错——大部分调优应该先做在检索端

·         生成层:答案是否忠实于检索到的资料(忠实度)、是否切题(答案相关性)。RAGAS 这类框架能自动化打分,但人工抽查永远不可替代

调优顺序固定:先修解析和切片 → 再修检索(混合检索、重排、过滤)→ 最后调提示词和生成参数。跳过前两步直接改提示词,是新手最常见的无效努力。

八、五个常见坑

1. PDF 解析想当然。 扫描件没有文本层、双栏排版被按顺序读串、表格变成乱码——解析质量不行,后面全白搭。复杂 PDF 用版面分析工具,表格单独处理。

2. 表格被切碎。 表格拦腰切断后,每半张表都检索不准。整张表作为一个切片,或转成 Markdown/键值对再切。

3. 只用向量检索。 报错码、产品型号这类精确词,纯向量几乎必挂。上混合检索。

4. 没有元数据。 "最新的""我们部门的"这类过滤全靠元数据。索引时就把时间、部门、版本存进去。

5. 上线即不管。 文档下线了索引还在,回答引用一年前的旧制度。给索引加更新和失效机制,评测集留着做回归。

九、最小可用代码骨架(示意)

用 Chroma 加任意 embedding 与大模型 API,几十行搭出骨架:

# 索引阶段(示意代码)

import chromadb

 

client = chromadb.PersistentClient(path="./kb")

col = client.get_or_create_collection("docs")

 

for doc in load_documents("./handbook"):       # 文档加载与清洗

    for i, chunk in split_chunks(doc.text):    # 切片

        col.add(

            ids=[f"{doc.name}:{i}"],

            documents=[chunk],

            metadatas=[{"source": doc.name}],  # 元数据

        )

 

# 检索生成阶段(示意代码)

question = "入职满一年有几天年假?"

hits = col.query(query_texts=[question], n_results=5)

 

context = "\n---\n".join(hits["documents"][0])

prompt = f"""仅依据以下资料回答问题;资料不足以回答时,明确说"资料中没有提到"。

 

资料:

{context}

 

问题:{question}

回答(注明引用的资料编号):"""

# 把 prompt 交给任意大模型 API 即可

load_documents、split_chunks 是留给你的两个函数,也是整篇最值得花时间的两个函数。生产环境要换掉的部分:embedding 调用、持久化向量库、混合检索与重排、自动化评测——骨架不变。

速查卡

环节

关键决策

解析

扫描件 OCR、表格专门处理

切片

500–1000 token、10% 重叠、一片一话题

向量化

按主要语言选模型,用自己的数据实测

检索

混合检索 + 重排 + 元数据过滤

生成

精选 3–5 段、要求引用、答不出就说不知道

评估

小评测集 + 检索/生成两层指标,先修检索端

 

写在最后

RAG 的迷人之处在于它把"让模型变聪明"变成了一个普通工程问题:解析、切片、检索、生成,每一层都能单独测量、单独改进。第一版不用追求完美——一个"解析干净 + 递归切片 + 向量检索 + 引用出处"的朴素系统,跑通评测集之后再逐层升级。

从把你们团队 wiki 里的前十篇文档索引进 Chroma 开始吧。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。