[简单理解]RAG知识库?

标准RAG基础全流程拆解(你写的这条链路是最经典朴素RAG)

手写的完整流程:

知识手册 → Embedding 分块编码 → 构建向量索引,向量 + 原始文档存入向量库 → 用户提问 → 向量召回 (捞取 Top‑10 候选片段) → 重排 Rerank (精选 Top‑3) → Prompt 拼接 (问题 + 3 份参考文档) 送入 LLM → 输出答案

一、逐环节详细解释

阶段 1:文档预处理(离线,一次性做完)

  1. 原始文档:PDF、Word、知识库手册、markdown 等

  2. 文档分块 Chunking

    ❗这里刚好用到刚刚聊的 固定 stride 滑动窗口切分

    把长文档切成一块块短片段chunk,参数:chunk_size(窗口大小window_size)chunk_overlap重叠长度stride = chunk_size‑overlap

    为什么需要重叠?防止一句话被一刀切成两个 chunk、语义断裂,就是你前面 PPT 里面 LLM 文本滑窗。

  3. Embedding

    每一个文本块chunk送入嵌入模型,转换成固定维度浮点向量,向量代表这段文字的语义

  4. 存入向量数据库

  • 存两份东西:chunk向量 + 原始文本 chunk、页码、来源文件名等元数据
  • 向量库会建立专门索引 (FAISS、HNSW 等),用来做高速相似度搜索

⚠️向量库不会丢掉原文!向量只是用来做检索的钥匙;最终给大模型的仍然是原始文字,不是向量。

阶段 2:用户在线问答(实时流程)

  1. 用户输入问题
  2. 问题 Embedding :把用户提问,用同一个 Embedding 模型转为查询向量
  3. 初筛召回 (Retrieval)
    在向量库里面,计算问题向量 和 全部文档块向量之间余弦相似度,返回相似度最高的 Top‑10 片段
  • 优点:速度极快,支持百万级文档
  • 缺点:粗筛,精度一般,容易出现语义相似但是文字事实无关的噪声
  1. 重排序 Rerank
    把刚刚召回出来的 10 条候选片段,丢进专门的重排模型 (Cross‑Encoder)
    重排模型同时看【用户问题 + 整条文档】做精细打分,重新排序,选出质量最高 Top‑3

召回:粗、快、广,宁多勿漏;重排:精、慢、准,做二次筛选

  1. Prompt 组装
    把用户问题、筛选好的 3 段参考上下文,拼接到提示词模板

    参考资料:
    【文档1】xxx
    【文档2】xxx
    【文档3】xxx
    根据上面材料回答问题:{用户提问}

  2. 送入大模型生成答案
    LLM 阅读参考文档,生成回答并且尽量引用知识库内容,减少幻觉。

二、流程图文字版

复制代码
【离线构建知识库】
原始文档 → 滑动窗口分块(stride+overlap) → embedding → (向量+原文)存入向量数据库

【在线问答】
用户提问 → 问题embedding →向量数据库相似度召回Top‑10 →Rerank重排筛选Top‑3 →构造提示词(问题+上下文) →大模型生成回答

三、每个环节常见坑点

步骤 最常见问题
分块 Chunking chunk 大小不合理,或者 overlap=0,完整句子被切开,关键信息被拆分到两个块(就是为什么要用带重叠 stride 滑窗)
Embedding 问题、文档使用不一样的 embedding 模型,向量不在同一个语义空间,召回完全错乱
向量召回 只靠余弦相似度,字面相近但是事实无关,召回很多无效内容,这一步就是为什么需要重排
Rerank 召回数量太少 (比如直接召回 top3),重排没有选择空间;召回太多则速度变慢
Prompt 拼接 上下文过长超过大模型上下文窗口上限,产生截断

四、和前面三个滑窗算法做联动回顾

  1. RAG 文档分块 = LLM 一维固定 stride 滑动窗口
  2. CNN stride:二维图像固定步长滑窗
  3. KMP:一维、内容驱动动态步长滑窗(精确字符串匹配 ,RAG 是语义相似度匹配,完全不一样)

补充区分:

KMP 是字面关键词精确查找 ;向量召回是模糊语义查找,哪怕用词不一样,只要意思接近就能找出来。

五、最简 Python 伪代码(逻辑版,不可直接运行,方便理解)

python 复制代码
#离线阶段
def build_knowledge_base(文档,chunk_size,overlap):
    chunks = sliding_window_split(文档,window_size=chunk_size,stride=chunk_size-overlap)
    for chunk in chunks:
        vec = embedding_model.encode(chunk)
        vector_db.insert(vector=vec,text=chunk)

#在线问答
def rag_answer(question):
    q_vec = embedding_model.encode(question)
    #向量召回 top10
    candidates = vector_db.search(q_vec,top_k=10)
    #重排取top3
    top3 = rerank_model.rerank(query=question,docs=candidates,top_k=3)
    #拼接prompt
    prompt = build_prompt(question,top3)
    answer = llm.chat(prompt)
    return answer

六、RAG核心三步可视化:分块、召回、重排

为直观理解RAG核心流程差异,以下通过可视化流程示意图+通俗解析,拆解分块、向量召回、重排三个关键环节的执行逻辑、数据变化和核心作用。

6.1 第一步:文档分块可视化(离线预处理)

核心规则:固定窗口大小+固定重叠长度,LLM滑动窗口切分,避免语义断裂

复制代码
原始完整长文档:【A B C D E F G H I J】
窗口大小chunk_size=4 | 重叠overlap=2 | 步长stride=2

分块过程:
Chunk1:【A B C D】
Chunk2:【C D E F】 (重叠2个字符:C D)
Chunk3:【E F G H】 (重叠2个字符:E F)
Chunk4:【G H I J】 (重叠2个字符:G H)

最终入库:4个文本块 + 对应4组语义向量

关键作用:将超长文档切割为大模型可处理的短片段,窗口重叠设计完美规避句子、关键信息被生硬切割的问题。

6.2 第二步:向量召回可视化(在线粗筛)

核心规则:语义相似度匹配,广撒网、宁多勿漏,粗筛Top10候选片段

复制代码
用户提问:【针对 C F H 相关知识点解答】
问题Embedding:生成提问语义向量Q

向量库匹配逻辑:
Q VS 所有Chunk向量 → 计算余弦相似度,从高到低排序
初筛结果(Top10):
✅Chunk2【C D E F】(高度相关)
✅Chunk3【E F G H】(高度相关)
✅Chunk1【A B C D】(部分相关)
❌Chunk5【xxx】(语义相近、事实无关噪声)
❌Chunk6【xxx】(低相关冗余内容)
......(共10条候选)

关键作用:依托向量数据库高速检索,快速过滤海量知识库内容,保留大概率相关片段,速度快、覆盖全,但存在少量噪声。

6.3 第三步:重排Rerank可视化(在线精筛)

核心规则:全文语义精细校验,去噪提纯、择优留存,精选Top3优质片段

复制代码
输入:召回阶段10条候选片段
重排模型逐一对齐【用户提问+完整文本块】精细打分

重排打分排序后:
1. Chunk2【C D E F】(匹配度98%,核心相关)
2. Chunk3【E F G H】(匹配度95%,核心相关)
3. Chunk1【A B C D】(匹配度82%,辅助相关)
--------- 以下全部淘汰 ---------
4. 噪声片段(匹配度45%,无关)
5. 冗余片段(匹配度30%,无效)
......

最终留存:Top3高质量文本块,送入LLM生成答案

关键作用:弥补向量召回的精度缺陷,剔除语义相似但事实无关的噪声,筛选出最贴合用户问题的核心上下文,提升回答准确率。

6.4 三步核心差异可视化总结

流程环节 核心特点 工作逻辑 核心目标
文档分块 离线、固定规则、无筛选 滑动窗口均匀切分,保留重叠语义 适配模型输入长度,保全文本语义
向量召回 在线、高速、粗筛选 向量语义相似度匹配,批量召回Top10 全覆盖、不遗漏有效信息
重排Rerank 在线、精细、精筛选 全文语义精准打分,过滤噪声留存Top3 提精度、降噪、优化上下文质量
html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RAG 完整流程动态可视化动画</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: "Microsoft Yahei", sans-serif;
        }

        body {
            background: #0f172a;
            color: #f1f5f9;
            padding: 40px 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
        }

        h1 {
            text-align: center;
            margin-bottom: 10px;
            color: #38bdf8;
            font-size: 28px;
        }

        .desc {
            text-align: center;
            color: #94a3b8;
            margin-bottom: 40px;
        }

        .stage-tip {
            text-align: center;
            font-size: 18px;
            color: #facc15;
            margin-bottom: 30px;
            height: 24px;
        }

        .flow-wrap {
            display: flex;
            flex-direction: column;
            gap: 24px;
        }

        .box {
            background: #1e293b;
            border-radius: 12px;
            padding: 20px;
            border: 1px solid #334155;
            transition: all 0.5s ease;
            opacity: 0.4;
            transform: translateY(10px);
        }

        .box.active {
            opacity: 1;
            transform: translateY(0);
            border-color: #38bdf8;
            box-shadow: 0 0 15px #38bdf840;
        }

        .box-title {
            font-size: 16px;
            color: #e2e8f0;
            margin-bottom: 12px;
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .box-title span {
            display: inline-block;
            width: 24px;
            height: 24px;
            line-height: 24px;
            text-align: center;
            border-radius: 50%;
            background: #38bdf8;
            color: #000;
            font-weight: bold;
            font-size: 14px;
        }

        .chunk-list {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
        }

        .chunk {
            padding: 8px 12px;
            background: #334155;
            border-radius: 6px;
            font-size: 14px;
            transition: all 0.4s ease;
        }

        .chunk.overlap {
            background: #22d3ee33;
            border: 1px solid #22d3ee;
        }

        .chunk.in-db {
            background: #10b98133;
            border: 1px solid #10b981;
        }

        .query-box {
            padding: 10px 14px;
            background: #facc1522;
            border: 1px solid #facc15;
            border-radius: 6px;
            color: #facc15;
            display: inline-block;
        }

        .ret-list .item {
            padding: 8px 12px;
            border-radius: 6px;
            font-size: 14px;
            margin-bottom: 8px;
            background: #334155;
            transition: all 0.4s ease;
        }

        .item.high {
            background: #10b98133;
            border: 1px solid #10b981;
        }

        .item.low {
            background: #ef444422;
            border: 1px solid #ef4444;
            opacity: 0.5;
        }

        .arrow {
            text-align: center;
            color: #38bdf8;
            font-size: 20px;
            margin: 4px 0;
            opacity: 0;
            transition: all 0.3s ease;
        }

        .arrow.show {
            opacity: 1;
        }

        .btn-wrap {
            text-align: center;
            margin-top: 40px;
        }

        button {
            padding: 12px 30px;
            font-size: 16px;
            border: none;
            border-radius: 8px;
            background: #38bdf8;
            color: #000;
            font-weight: bold;
            cursor: pointer;
            transition: 0.3s;
            margin: 0 8px;
        }

        button:hover {
            background: #0ea5e9;
        }

        button.reset {
            background: #64748b;
            color: #fff;
        }

        .answer-box {
            margin-top: 12px;
            padding: 14px;
            background: #a855f722;
            border: 1px solid #a855f7;
            border-radius: 8px;
            color: #e9d5ff;
            opacity: 0;
            transition: all 0.5s ease;
        }

        .answer-box.show {
            opacity: 1;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>RAG 完整流程动态可视化动画</h1>
        <p class="desc">离线分块入库 → 在线提问 → 向量召回Top10 → 重排Top3 → LLM 生成答案</p>
        <div class="stage-tip" id="stageTip">点击「开始播放」启动动画</div>

        <!-- 1.原始文档分块 -->
        <div class="box" id="box1">
            <div class="box-title"><span>1</span>文档滑动窗口分块(离线)</div>
            <p style="color:#94a3b8;font-size:14px;margin-bottom:10px;">窗口大小=4,重叠=2,步长=2,带重叠防语义断裂</p>
            <div class="chunk-list">
                <div class="chunk" id="c1">Chunk1: A B C D</div>
                <div class="chunk" id="c2">Chunk2: <span class="overlap">C D</span> E F</div>
                <div class="chunk" id="c3">Chunk3: <span class="overlap">E F</span> G H</div>
                <div class="chunk" id="c4">Chunk4: <span class="overlap">G H</span> I J</div>
            </div>
        </div>

        <div class="arrow" id="arr1">↓</div>

        <!-- 2.向量化入库 -->
        <div class="box" id="box2">
            <div class="box-title"><span>2</span>Embedding 向量化 + 向量数据库入库</div>
            <p style="color:#94a3b8;font-size:14px;margin-bottom:10px;">文本块转为语义向量,向量+原文存入向量库</p>
            <div class="chunk-list" id="dbList">
            </div>
        </div>

        <div class="arrow" id="arr2">↓</div>

        <!-- 3.用户提问 -->
        <div class="box" id="box3">
            <div class="box-title"><span>3</span>用户提问 + 问题 Embedding</div>
            <div class="query-box" id="queryText">问题:针对 C、F、H 相关知识点解答</div>
        </div>

        <div class="arrow" id="arr3">↓</div>

        <!-- 4.向量召回Top10 -->
        <div class="box" id="box4">
            <div class="box-title"><span>4</span>向量粗召回(Top10 广筛、宁多勿漏)</div>
            <p style="color:#94a3b8;font-size:14px;margin-bottom:10px;">余弦相似度匹配,批量召回,包含少量噪声</p>
            <div class="ret-list" id="retList">
                <div class="item" id="r1">Chunk2【C D E F】- 高度相关</div>
                <div class="item" id="r2">Chunk3【E F G H】- 高度相关</div>
                <div class="item" id="r3">Chunk1【A B C D】- 部分相关</div>
                <div class="item" id="r4">Chunk5【xxx】- 语义相近无关(噪声)</div>
                <div class="item" id="r5">Chunk6【xxx】- 低相关冗余</div>
            </div>
        </div>

        <div class="arrow" id="arr4">↓</div>

        <!-- 5.重排Top3 -->
        <div class="box" id="box5">
            <div class="box-title"><span>5</span>Rerank 重排精筛(留存 Top3 优质上下文)</div>
            <p style="color:#94a3b8;font-size:14px;margin-bottom:10px;">精细语义打分,过滤噪声,提纯上下文</p>
            <div class="ret-list" id="rerankList">
            </div>
        </div>

        <div class="arrow" id="arr5">↓</div>

        <!-- 6.LLM生成答案 -->
        <div class="box" id="box6">
            <div class="box-title"><span>6</span>Prompt 拼接 + LLM 生成最终答案</div>
            <div class="answer-box" id="answerBox">
                根据参考文档中 C、F、H 相关知识点:<br/><br/>
                1. C、D、E、F 模块核心知识点覆盖基础定义与使用规则;<br/>
                2. E、F、G、H 模块为拓展应用知识点,承接前文基础内容;<br/>
                3. 结合上下文可完整解答对应考点,无幻觉、答案贴合内部知识库。
            </div>
        </div>

        <div class="btn-wrap">
            <button id="playBtn">开始播放动画</button>
            <button class="reset" id="resetBtn">重置动画</button>
        </div>
    </div>

    <script>
        // 获取所有DOM
        const stageTip = document.getElementById('stageTip');
        const playBtn = document.getElementById('playBtn');
        const resetBtn = document.getElementById('resetBtn');

        const boxes = [
            document.getElementById('box1'),
            document.getElementById('box2'),
            document.getElementById('box3'),
            document.getElementById('box4'),
            document.getElementById('box5'),
            document.getElementById('box6')
        ];

        const arrows = [
            document.getElementById('arr1'),
            document.getElementById('arr2'),
            document.getElementById('arr3'),
            document.getElementById('arr4'),
            document.getElementById('arr5')
        ];

        const dbList = document.getElementById('dbList');
        const rerankList = document.getElementById('rerankList');
        const answerBox = document.getElementById('answerBox');

        // 重置所有状态
        function resetAll() {
            boxes.forEach(box => box.classList.remove('active'));
            arrows.forEach(arr => arr.classList.remove('show'));
            dbList.innerHTML = '';
            rerankList.innerHTML = '';
            answerBox.classList.remove('show');
            stageTip.innerText = '点击「开始播放」启动动画';
            // 重置召回列表样式
            document.querySelectorAll('.ret-list .item').forEach(item => {
                item.classList.remove('high','low');
            });
        }

        // 延时函数
        function sleep(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }

        // 动画主流程
        async function runAnimation() {
            resetAll();
            playBtn.disabled = true;

            // 1.分块
            stageTip.innerText = '步骤1:滑动窗口分块,生成带重叠文本块';
            boxes[0].classList.add('active');
            await sleep(1200);

            // 箭头1
            arrows[0].classList.add('show');
            await sleep(600);

            // 2.入库
            stageTip.innerText = '步骤2:文本Embedding,向量+原文存入向量数据库';
            boxes[1].classList.add('active');
            const chunksText = ['Chunk1: A B C D','Chunk2: C D E F','Chunk3: E F G H','Chunk4: G H I J'];
            for(let text of chunksText){
                let div = document.createElement('div');
                div.className = 'chunk in-db';
                div.innerText = text;
                dbList.appendChild(div);
                await sleep(300);
            }
            await sleep(1000);

            // 箭头2
            arrows[1].classList.add('show');
            await sleep(600);

            // 3.用户提问
            stageTip.innerText = '步骤3:用户提问,问题生成Embedding查询向量';
            boxes[2].classList.add('active');
            await sleep(1200);

            // 箭头3
            arrows[2].classList.add('show');
            await sleep(600);

            // 4.向量召回
            stageTip.innerText = '步骤4:向量数据库相似度召回,粗筛Top10(含噪声)';
            boxes[3].classList.add('active');
            // 标记高低质量
            document.getElementById('r1').classList.add('high');
            document.getElementById('r2').classList.add('high');
            document.getElementById('r3').classList.add('high');
            document.getElementById('r4').classList.add('low');
            document.getElementById('r5').classList.add('low');
            await sleep(1500);

            // 箭头4
            arrows[3].classList.add('show');
            await sleep(600);

            // 5.重排
            stageTip.innerText = '步骤5:Rerank重排降噪,精准筛选Top3优质上下文';
            boxes[4].classList.add('active');
            const top3 = [
                '1. Chunk2【C D E F】 匹配度98%',
                '2. Chunk3【E F G H】 匹配度95%',
                '3. Chunk1【A B C D】 匹配度82%'
            ];
            for(let text of top3){
                let div = document.createElement('div');
                div.className = 'item high';
                div.innerText = text;
                rerankList.appendChild(div);
                await sleep(400);
            }
            await sleep(1200);

            // 箭头5
            arrows[4].classList.add('show');
            await sleep(600);

            // 6.生成答案
            stageTip.innerText = '步骤6:拼接Prompt,LLM基于知识库生成答案,杜绝幻觉';
            boxes[5].classList.add('active');
            answerBox.classList.add('show');

            stageTip.innerText = '✅ RAG 全流程动画演示完毕!';
            playBtn.disabled = false;
        }

        // 绑定事件
        playBtn.addEventListener('click', runAnimation);
        resetBtn.addEventListener('click', resetAll);
    </script>
</body>
</html>
相关推荐
Ai-_Man5 小时前
希望大家能推荐一款软件,可以直接把文心生成的代码变流程图,提高办公效率
人工智能·ai·小程序·流程图
AI绘画哇哒哒10 小时前
【建议收藏!】35岁后端血泪忠告,这3类人别硬转Agent(过来人亲述)
java·人工智能·后端·ai·程序员·大模型·agent
QN1幻化引擎10 小时前
DalinX Phi 性能突破:跨层秩保持对齐与意识涌现度量的实证研究
人工智能·ai·架构·agi·asi
龙兵AI增长破局圈.赵老师讲成交11 小时前
只有把过程管好,结果才会出来。
大数据·人工智能·ai·创业创新
最强小杰11 小时前
gpt-5.6-sol 频繁报 503 怎么办?区分容量熔断和限速 429 的排查方法 + 可复用 retry wrapper
java·人工智能·gpt·ai
你是一个铁憨憨12 小时前
从 GIS 到 Spatial Agent:MCP 如何重新定义 GIS 的 AI 入口
arcgis·ai·agent·mcp·spatial
奇牙coding12317 小时前
gpt-5.6-luna 频繁 429 但 gpt-5.5 正常怎么办?不是配额问题,是 luna 独立的并发 session 限速桶
gpt·ai
安逸sgr17 小时前
AI 应用怎么评测?离线评测、人工评估和线上反馈如何结合?
人工智能·ai·大模型·agent·智能体
DS随心转插件18 小时前
Grok生成的html怎么导出——AI导出鸭:大模型结构化输出的“最后一公里”工程化解构
前端·人工智能·ai·html·豆包·deepseek·ai导出鸭