某天,一家律师事务所来了一位“高材生”——AI法律助手。它伶牙俐齿,你问什么都能答,但合伙人很快发现问题:它引用的法条,有一半是凭空编的;它推荐的诉讼策略,可能早在三年前就被新司法解释推翻了。这就是大模型的“幻觉”。 解决办法,是给它配一位“图书管理员”:这位管理员管理着一个不断更新的法规库,每次AI回答问题之前,管理员先帮它找出最相关的法律条文和判例,AI再“看着资料”组织回答,并在每句话后面标注出处。 这套“先查资料、再写答案”的机制,就是检索增强(Retrieval-Augmented Generation,RAG)。它不是让AI背更多的书,而是让它学会“查书”。在这篇文章里,我们会用“实习生+图书管理员”的故事,从问题背景、核心架构、向量化、检索策略、上下文管理、引用溯源、评测指标到持续优化,完整拆解如何用RAG打造一个“句句有依据、条条可溯源”的法律AI系统。

岗位关联

对AI从业者而言,RAG是把大模型从“demo玩具”推向“生产工具”的关键能力:掌握它,意味着你能构建出可解释、可追溯、可持续优化的企业级AI应用——这正是法律、金融、医疗等严肃场景最稀缺的技能。

目录
  1. 可视化演示
  2. 问题背景:爱编答案的实习生
  3. 核心架构:配合默契的双人组
  4. 向量化索引:给书架编目录
  5. 检索策略:管理员找书的诀窍
  6. 上下文管理:桌上放不下的案卷
  7. 引用溯源:给每句话附出处
  8. 评测指标:合伙人的抽查表
  9. 持续优化:越用越聪明的系统
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

问题背景:爱编答案的实习生

某家律师事务所新来了一个名校毕业的实习生(大模型),非常聪明,口才极好。你问他“合同违约了怎么办”,他能滔滔不绝讲上几分钟,引经据典、条理清晰。可律师合伙人拿去一核对,发现他引用的“法条”有一半根本不存在——编号是错的,条款内容是编的。这就是大模型典型的“幻觉”:模型会根据训练时学到的语言模式,流畅地编造看似合理、实则无据的答案。

大模型的本质是“预测下一个词”,它追求的是语言流畅和逻辑自洽,而不是事实正确。训练数据有截止日期,新颁布的法律它根本没见过。法律问答最怕两件事:一是事实错误,二是没有依据。如果当事人照着幻觉答案去打官司,后果不堪设想。此外,大模型的知识都“锁”在参数里,无法告诉你“这句话是从哪条法律来的”,更做不到随时更新。

于是有了检索增强生成(RAG):在模型回答前,先从外部知识库中检索相关法律条文和判例,让模型“看着资料回答问题”。外部知识库可以随时更新,从源头补上知识的“保质期”,也让回答变得有据可查。

解决之道,是给这位实习生配一位图书管理员——先查资料,再开口。这就是接下来要讲的检索增强。

幻觉率=包含无依据陈述的回答数总回答数\displaystyle \text{幻觉率} = \frac{\text{包含无依据陈述的回答数}}{\text{总回答数}}
幻觉率衡量AI回答中“查无实据”的比例,RAG的核心目标就是把这个比率压到最低。
  1. 分子(无依据回答)统计在所有测试回答中,包含“无依据陈述”——也就是知识库里找不到支持证据的句子——的回答有多少条。
    包含无依据陈述的回答数\text{包含无依据陈述的回答数}
  2. 分母(总回答数)统计全部测试回答的总数量,作为衡量基数。
    总回答数\text{总回答数}
  3. 比率(幻觉率)两者相除得到幻觉率,取值范围是 0 到 1,越接近 0 说明回答越可靠。
    幻觉率∈[0,1]\text{幻觉率} \in [0, 1]

核心架构:配合默契的双人组

律所终于给实习生配了一位图书管理员。管理员手里有一套卡片目录(索引),知道每本案卷放在哪个书架;他会根据实习生的提问,迅速挑出最相关的几本案卷(检索);最后把案卷摊开放在实习生桌上,让他照着写备忘录(生成)。这套“管理员找书、实习生写报告”的分工,就是RAG的缩影。

RAG架构正是这个协作流程的工程化,由四个模块组成。索引构建模块把法规库、判例库切块并向量化,存进向量数据库,相当于给书架编目录;检索模块根据用户问题召回候选文档,相当于管理员按提问找书;融合模块把候选文档与用户问题拼装成提示词,相当于把案卷摆上桌;生成模块让大模型基于上下文输出回答,相当于实习生照着案卷写备忘录。

四个模块像流水线一样串联:每个环节的输出都是下一环节的输入。值得注意的是,法律场景对“融合”的要求更高——不能简单地把文档拼在一起,还要在提示词中明确“只能依据检索材料回答”“不得添加材料之外的法条”,用指令约束模型的发挥空间。

图书管理员和实习生这套组合,分工明确:管理员负责“找得对”,实习生负责“说得好”。任何一方掉链子,最终答案都会出问题——所以接下来的每一节,都是在打磨这两个角色的能力。

Answer∼PLLM(⋅∣Query,R1,…,RK)\displaystyle \text{Answer} \sim P_{\text{LLM}}(\cdot \mid \text{Query}, R_1, \dots, R_K)
这个公式表示:模型的回答从“给定问题和K篇检索文档条件下的概率分布”中采样得到,检索文档是生成答案的“事实地基”。
  1. 条件(Query 与 R_i)Query 是用户原始问题,$R_1,\dots,R_K$ 是检索器召回的相关文档块,它们共同作为生成的条件。
    Query,  R1,…,RK\text{Query}, \; R_1, \dots, R_K
  2. 条件概率分布$P_{\text{LLM}}(\cdot \mid \cdots)$ 表示大模型在给定条件下,对下一个词的概率分布——条件越充分、越准确,分布就越“收敛”到正确答案附近。
    PLLM(⋅∣Query,R1,…,RK)P_{\text{LLM}}(\cdot \mid \text{Query}, R_1, \dots, R_K)
  3. 采样生成Answer 是从这个分布中采样得到的完整回答,它既依赖模型本身的语言能力,也依赖检索条件的质量。
    Answer∼PLLM\text{Answer} \sim P_{\text{LLM}}

向量化索引:给书架编目录

图书管理员之所以能在几十万本案卷中瞬间找到目标,靠的是每本书的书脊编号和卡片目录。文档也面临同样的问题:要让计算机“找到”它,就得先把它变成计算机能计算的形态——向量。所谓向量,就是一段文本被嵌入模型“翻译”成一串几百维的数字坐标,例如“合同违约”和“未按约履行义务”这两段字面不同的话,翻译成坐标后距离会很近。

文本本身不能直接做数学运算,所以需要一个“翻译官”——嵌入模型(Embedding Model)。它把一段文本映射成高维向量,语义相近的文本,向量之间的距离也近。法律场景中,“违约金过低”和“赔偿数额不合理”这类同义表述,靠字面匹配找不到,但向量能感知语义相似。

工程落地分三步:先把文档按语义切成块——切得太大会把不相干的内容绑在一起,切得太小会切断完整法条;再用嵌入模型把每块转成向量;最后存入向量数据库。向量数据库用HNSW等索引结构支持高效的近似最近邻搜索,而衡量两块文本远近的常用工具,是余弦相似度。

有了编号目录,管理员的查找效率从“挨个翻书”提升到“直达目标”。向量化就是把法律文本“编码”成计算机能快速定位的编号——但光有编号还不够,还要知道怎么找,这就轮到检索策略登场了。

sim(A,B)=∑i=1nAiBi∑i=1nAi2⋅∑i=1nBi2\displaystyle \text{sim}(\mathbf{A}, \mathbf{B}) = \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \cdot \sqrt{\sum_{i=1}^{n} B_i^2}}
余弦相似度把两个向量的“夹角”换算成 0 到 1 之间的分数,分数越高,两段文字的语义越接近,是向量检索的基础打分公式。
  1. 向量点积(分子)将向量 A 和 B 的每一维相乘再求和,结果越大说明两个向量在各维度上越“同向”。
    A⋅B=∑i=1nAiBi\mathbf{A} \cdot \mathbf{B} = \sum_{i=1}^{n} A_i B_i
  2. 向量模长(分母)先对每个向量的所有维度求平方和,再开根号,得到向量的“长度”,用于归一化。
    ∥A∥=∑i=1nAi2\|\mathbf{A}\| = \sqrt{\sum_{i=1}^{n} A_i^2}
  3. 余弦值(相似度)点积除以两个模长的乘积,把结果限制在 $[-1, 1]$。文本向量通常落在 $[0, 1]$,越接近 1 越相似。
    sim(A,B)∈[−1,1]\text{sim}(\mathbf{A}, \mathbf{B}) \in [-1, 1]

检索策略:管理员找书的诀窍

管理员接到问题后,不会把整个图书馆都搬过来,而是先快速筛掉明显无关的书,再按相关度排序,只拿最相关的那几本。这个“筛掉—排序—精选”的过程就是检索策略。对文档而言,“相关度”不能凭感觉,要算出来。

打分方式主要有两类。一类是向量检索,用上一节的余弦相似度找语义相近的文本;另一类是关键词检索,用BM25这类算法看字面匹配程度。法律文本有个特点:术语极其严谨——“违约金”就是“违约金”,字面匹配很可靠;但同一概念又有多种表述——“解除合同”和“终止劳动关系”,字面不同,语义一样。单一方法容易漏,于是有了混合检索。

混合检索(Hybrid Search)把向量得分和BM25得分加权融合,兼得语义与字面之利。更精细的方案再叠加重排序(Rerank):先用轻量级检索召回几十个候选,再用更重的模型精排,最后只取前几个。K值的选择是门艺术——太小漏掉关键判例,太大会把噪声带进来。法律场景通常 K 取 3~5 个片段,既保证覆盖,又不让模型“看花眼”。

管理员的找书诀窍,既看“内容对不对路”(向量语义),也看“关键词对不对”(BM25),还要二次精筛(重排序)。最终挑出来的那几本,才是实习生真正需要的案卷。但案卷挑好了,怎么摆上桌也有讲究。

Score(D,Q)=∑qi∈QIDF(qi)⋅f(qi,D)(k1+1)f(qi,D)+k1(1−b+b∣D∣avgdl)\displaystyle \text{Score}(D, Q) = \sum_{q_i \in Q} \text{IDF}(q_i) \cdot \frac{f(q_i, D)(k_1+1)}{f(q_i, D) + k_1(1-b+b\frac{|D|}{\text{avgdl}})}
BM25 是关键词检索的经典打分公式:同时考虑词的稀有程度、在文档中出现的次数,以及文档长度,给每个候选文档打出相关度分数。
  1. IDF(词的稀有度)$q_i$ 是查询里的一个词,$\text{IDF}(q_i)$ 表示这个词在全库中有多“稀有”——“违约金”比“的”稀有,权重就高。
    IDF(qi)=log⁡N−df(qi)+0.5df(qi)+0.5\text{IDF}(q_i) = \log \frac{N - df(q_i) + 0.5}{df(q_i) + 0.5}
  2. 词频饱和(分子缩放)$f(q_i, D)$ 是词在文档中的出现次数,得分随次数增长但越来越慢,避免“提到一百次就比提一次好一百倍”。
    f(qi,D)(k1+1)f(qi,D)+k1\frac{f(q_i,D)(k_1+1)}{f(q_i,D)+k_1}
  3. 长度归一化$|D|/\text{avgdl}$ 用文档长度除以平均长度,防止长文档因为篇幅大而天然高分;$b$ 控制归一化的强弱。
    b⋅∣D∣avgdlb \cdot \frac{|D|}{\text{avgdl}}

上下文管理:桌上放不下的案卷

管理员找书再准,实习生的办公桌(上下文窗口)也就那么大。如果搬来五十本案卷,别说看,桌子都塌了。这时管理员要学会做减法:按相关度留几本,太长的先压一压,顺序排好再上桌。大模型面临的正是同样的限制。

大模型的上下文窗口是有限的 token 预算。所谓 token,可以粗略理解为“词元”,模型每处理一个 token 都要消耗算力,窗口装不下就报错。检索结果、系统指令、用户问题都要占用空间。法律场景一个问题常常召回几十个候选块,如果全塞进去,既超限,又会稀释模型对重点内容的注意力——就像桌上堆了五十本书,实习生反而找不到最关键的那一页。

常用策略包括:动态截断——按相关性从高到低取到预算上限,放不下的果断舍弃;摘要压缩——用模型把长文档浓缩成要点,牺牲细节换容量;分层布局——系统指令放最前,检索证据居中,用户问题垫后,让模型按顺序读取。提示词模板要划分三个区域:约束区(“只能依据检索材料回答,不得编造”)、证据区(候选块)、问题区(用户原问)。

桌面管理得清爽,实习生才能专注在关键案卷上。上下文管理看似不起眼,却直接决定模型“看没看见、看了多少”关键证据。现在实习生终于有书可看了,但合伙人又提出了新要求:每句话都要说出处。

∑i=1Ktokens(Ri)+tokens(I)+tokens(Q)≤L窗口\displaystyle \sum_{i=1}^{K} \text{tokens}(R_i) + \text{tokens}(I) + \text{tokens}(Q) \leq L_{\text{窗口}}
这条公式是上下文管理的“预算线”:K 个检索块的 token 数,加上指令和问题的 token 数,总和不能超过上下文窗口上限。
  1. 检索块预算(证据区)$K$ 个检索块各自的 token 数之和,是上下文里最占空间的“变量”,也是管理的主要对象。
    ∑i=1Ktokens(Ri)\sum_{i=1}^{K} \text{tokens}(R_i)
  2. 固定开销(指令与问题)指令模板 $I$ 和用户问题 $Q$ 占用的 token 基本固定,必须先预留出来。
    tokens(I)+tokens(Q)\text{tokens}(I) + \text{tokens}(Q)
  3. 窗口上限约束三者总和不能超过窗口上限 $L_{\text{窗口}}$,一旦超限就要裁掉低相关度的检索块,或对长块做摘要压缩。
    ≤L窗口\leq L_{\text{窗口}}

引用溯源:给每句话附出处

实习生被合伙人训了一次后学乖了:每写一个结论,就在旁边标上“这个观点出自《民法典》第577条”。合伙人核对时,顺着编号一翻就能验证——这就是引用溯源。它把“我的回答有依据”从一句空话,变成了可操作的动作。

RAG 虽然让模型基于检索材料生成,但模型在生成过程中仍可能自行发挥,偏离原文。引用溯源机制要求模型在输出时标注引用编号,每个编号对应知识库中的具体原文段落。这样用户看到的不是孤零零的一个结论,而是“结论 + 证据链”。

实现上,提示词中会明确要求模型以 [n] 形式标注引用来源,同时系统把检索块的原始 ID 映射到最终输出。返回答案时附带证据列表:来源名称、条文编号、原文节选。法律场景还要求引用定位到具体条款级别,方便法务和当事人核验。更进一步,可以用覆盖率来评估可信度——看看整个回答里有多少比例的句子带有引用支撑。

把“出处”写进每句话后,实习生的每一条结论都经得起合伙人随手抽查。引用溯源把“信任”变成了可验证的工程机制。但合伙人还想知道另一件事:这套系统整体到底靠不靠谱?这就需要有评测指标来把关。

覆盖率=∑s∈SI[有引用(s)]∣S∣\displaystyle \text{覆盖率} = \frac{\sum_{s \in S} \mathbb{I}[\text{有引用}(s)]}{|S|}
引用覆盖率衡量回答中“有据可查”的句子占比:覆盖率越高,说明回答的可追溯性和可信度越好。
  1. 句子集合把回答切分为句子集合 $S$,$|S|$ 是总句数,作为评估的基数。
    S={s1,s2,…,sn}S = \{s_1, s_2, \dots, s_n\}
  2. 指示函数$\mathbb{I}[\text{有引用}(s)]$ 是个“开关”——当句子 $s$ 带有引用标注时取 1,否则取 0。
    I[有引用(s)]∈{0,1}\mathbb{I}[\text{有引用}(s)] \in \{0, 1\}
  3. 覆盖率把所有指示函数值加起来除以总句数,得到 $[0,1]$ 之间的比例,衡量整个回答的证据完整度。
    覆盖率∈[0,1]\text{覆盖率} \in [0, 1]

评测指标:合伙人的抽查表

合伙人不会只听实习生自己说“我进步了”,而是定期抽查:一百个问题,答对了多少?每个回答有没有引用支撑?检索器能不能找到正确答案?这些数字,就是评测指标。没有数据支撑的“我觉得变好了”,在严肃场景里一文不值。

RAG 系统需要评测两个环节。检索端看“找得准不准”:命中率(Hit Rate)是检索结果里包含正确答案的查询占比,召回率(Recall)是正确文档被召回的比例,MRR(平均倒数排名)则关注正确答案排得靠不靠前。生成端看“说得对不对”:答案正确率需要人工或强模型标注,忠实度(Faithfulness)判断生成内容是否被检索材料支持,可以用NLI(自然语言推理)模型自动打分。

法律场景下,评测集的构建是关键——通常由执业律师标注一批“问题—标准答案—关联法条”三元组。命中率只回答“检索器有没有找到对的资料”,忠识度回答“模型有没有老老实实照着资料说”,两者一起看才能发现短板:如果命中率低,问题出在检索器;如果命中率高但忠识度低,问题出在生成环节。

有了评测这把“标尺”,实习生和管理员是否真的在进步不再靠嘴说,而是靠数据说话。评测也是持续优化的起点——没有标尺,优化就是盲人摸象。

命中率=检索结果中包含正确答案的查询数Qtotal\displaystyle \text{命中率} = \frac{\text{检索结果中包含正确答案的查询数}}{Q_{\text{total}}}
命中率是最直观的检索指标:在一批测试问题里,有多少比例的问题,其检索结果的前 K 条中出现了人工标注的正确文档。
  1. 分子(命中查询数)在评测集里,统计有多少条查询的 Top-K 检索结果中包含人工标注的正确文档。
    检索结果中包含正确答案的查询数\text{检索结果中包含正确答案的查询数}
  2. 分母(总查询数)$Q_{\text{total}}$ 是评测集里全部人工标注问题的数量。
    QtotalQ_{\text{total}}
  3. 比率(命中率)两者相除得到命中率,越接近 1 说明检索器越可靠,但还要配合召回率和生成端指标一起评估。
    命中率∈[0,1]\text{命中率} \in [0, 1]

持续优化:越用越聪明的系统

图书管理员每周都会做三件事:新法规颁布了,赶紧买新书入库;上周实习生答错的题,周末复盘;发现某类案子总是找不到,就调整书架分类。这就是持续优化。RAG 系统上线不是终点,而是起点——法律知识在更新,用户问法在变化,系统必须跟着进化。

持续优化需要三个闭环。数据更新:定期把新法规、新判例切块、向量化,增量写入知识库。法律场景里这条尤其关键——沿用已废止的法条回答用户,比不用 RAG 危害还大。反馈闭环:把用户的负面反馈收集起来,例如“这条回答没有引用”“检索到的判例与问题无关”,打标后补充到评测集里,倒逼检索端和生成端共同改进。

场景适配:针对不同法律子领域做调参——合同纠纷的 K 值、劳动仲裁的切块大小、知产问题的重排序模型,都不能一套参数打天下。每次改动都跑一遍评测集,用分数差判断是否回滚。持续优化没有终点,因为法律的演进和用户需求的变化也不会停。

就像图书管理员会根据工作反馈不断调整书架,持续优化让 RAG 系统在真实业务中越用越顺手。法律条文会变,用户问题会变,系统的知识库和策略也要跟着变——这才是生产级 AI 系统该有的样子。

增益=Score(新版本)−Score(旧版本)\displaystyle \text{增益} = \text{Score}(\text{新版本}) - \text{Score}(\text{旧版本})
优化增益是“新版本评测得分减去旧版本得分”:大于 0 说明优化有效,小于 0 说明改错了方向,需要回滚。
  1. 旧版本基准优化前系统的综合评测得分,这是对比的基准线。
    Score(旧版本)\text{Score}(\text{旧版本})
  2. 新版本结果优化后系统的综合评测得分,反映数据更新、反馈闭环和调参带来的变化。
    Score(新版本)\text{Score}(\text{新版本})
  3. 增益判断两者相减,结果大于 0 说明优化有效;小于 0 则要回滚或换策略。
    增益>0⇒优化有效\text{增益} > 0 \Rightarrow \text{优化有效}

AI 应用场景

法律咨询平台智能问答

阶段:检索 + 生成(核心 RAG 流程)

解决的问题:公民咨询“房租合同没到期能退租吗?”传统平台靠人工律师回复,成本高、响应慢。接入 RAG 后,系统先从民法库检索租赁合同相关条文,再生成带引用的答复,用户可一键查看法条原文,大幅降低咨询门槛和律所人力成本。

具体案例:某在线法律咨询平台接入 RAG,知识库收录民法典、司法解释及数万条判例。用户提问“押金被房东扣了怎么办”,系统检索到民法典第577条等条款,生成三步维权指引,每条指引都附条文编号。上线三个月,平台咨询服务量提升 40%,用户对“有法条依据”的回答满意度提升 28%。

企业合同风险审查

阶段:索引构建 + 检索 + 生成

解决的问题:法务审查合同时,需要比对相似判例来判断条款风险。传统做法依赖个人经验,检索效率低、覆盖面有限。RAG 把历史合同与判例建成索引,法务输入合同条款,系统返回相似判例和裁判观点,并标注高风险条款。

具体案例:某企业法务部用 RAG 系统审查供应商合同,系统检索到三份“违约金过高被法院调整”的相似判例,自动在合同第 8 条旁标注风险提示并给出修改建议。法务复核效率提升 60%,同类风险条款的遗漏率下降 45%。

新法规生效后的知识库更新

阶段:数据更新 + 端到端评估

解决的问题:法律法规频繁更新,人工跟踪效率低、容易遗漏。RAG 系统通过持续更新索引把新法规纳入知识库,并用评测集验证模型能否依据新法规正确作答,确保对外咨询服务永远基于现行有效法律。

具体案例:某司法行政机关部署 RAG 系统,在新《公司法》施行后 72 小时内完成知识库更新与评测:新旧条款对照问答全部重测,确保系统回答的是最新法条而非旧版内容,避免了因知识过时导致的错误咨询。

Python 演示

python76 行
# -*- coding: utf-8 -*-"""简易检索增强问答: 面向法律小知识库的 RAG 流程演示"""import math # 模拟法律知识库 (实际场景中来自法规库与判例库)LAW_DOCS = [    "民法典第五百七十七条: 当事人一方不履行合同义务或者履行合同义务不符合约定的, 应当承担继续履行、采取补救措施或者赔偿损失等违约责任。",    "民法典第五百零九条: 当事人应当按照约定全面履行自己的义务。当事人应当遵循诚信原则, 根据合同的性质、目的和交易习惯履行通知、协助、保密等义务。",    "劳动合同法第三十九条: 劳动者严重违反用人单位规章制度的, 用人单位可以解除劳动合同。",    "劳动合同法第四十七条: 经济补偿按劳动者在本单位工作的年限, 每满一年支付一个月工资的标准向劳动者支付。",    "民法典第一百八十八条: 向人民法院请求保护民事权利的诉讼时效期间为三年。",] def tokenize(text):    """简易分词: 将常用分隔符替换为空格后切分"""    for sep in ",。:、;()":        text = text.replace(sep, " ")    return [w for w in text.split() if w] def build_index(docs):    """构建倒排索引: 词 -> 文档ID列表"""    index = {}    doc_tokens = []    for doc_id, doc in enumerate(docs):        tokens = tokenize(doc)        doc_tokens.append(tokens)        for word in set(tokens):            index.setdefault(word, []).append(doc_id)    return index, doc_tokens def bm25_scores(query, doc_tokens, avg_dl, N):    """计算查询与每个文档的BM25得分"""    q_tokens = set(tokenize(query))    df = {w: sum(1 for t in doc_tokens if w in t) for w in q_tokens}    scores = []    for tokens in doc_tokens:        dl = len(tokens)        score = 0.0        for word in q_tokens:            tf = tokens.count(word)            if tf == 0:                continue            idf = math.log(1 + (N - df[word] + 0.5) / (df[word] + 0.5))            score += idf * (tf * 2.5) / (tf + 1.5 * (1 - 0.75 + 0.75 * dl / avg_dl))        scores.append(score)    return scores def retrieve(query, index, doc_tokens, top_k=2):    """检索: 返回Top-K相关文档及其得分"""    N = len(doc_tokens)    avg_dl = sum(len(t) for t in doc_tokens) / N    scores = bm25_scores(query, doc_tokens, avg_dl, N)    ranked = sorted(range(N), key=lambda i: scores[i], reverse=True)    return [(LAW_DOCS[i], scores[i]) for i in ranked[:top_k]] def generate_answer(query, evidence):    """生成: 把检索结果拼接为带引用的回答"""    lines = ["【问题】" + query, "", "【依据】"]    for idx, (doc, _) in enumerate(evidence, 1):        lines.append(f"[{idx}] {doc}")    lines.append("")    lines.append("【结论】以上条文可作为初步参考, 具体案件请咨询执业律师。")    return "\n".join(lines) def main():    # 1. 构建索引    index, doc_tokens = build_index(LAW_DOCS)    # 2. 检索    query = "员工严重违纪, 公司可以解除劳动合同吗?"    evidence = retrieve(query, index, doc_tokens, top_k=2)    # 3. 生成    answer = generate_answer(query, evidence)    print(answer) if __name__ == "__main__":    main()
目的:演示一个迷你 RAG 流程——先为法律条文构建倒排索引,再用 BM25 检索出最相关的 Top-K 条文,最后拼装成带引用的回答,帮助理解“检索增强”的核心机制。
  1. index.setdefault(word, []).append(doc_id)为每个词维护一个文档列表,构建倒排索引,相当于给书架编卡片目录
  2. df = {w: sum(1 for t in doc_tokens if w in t) for w in q_tokens}统计查询中的每个词出现在多少篇文档中,用于计算稀有度
  3. idf = math.log(1 + (N - df[word] + 0.5) / (df[word] + 0.5))逆文档频率:越稀有的术语权重越高,“的”这类常见词权重趋近于零
  4. score += idf * (tf * 2.5) / (tf + 1.5 * (1 - 0.75 + 0.75 * dl / avg_dl))BM25 打分核心:词频越丰富得分越高,但增长会饱和,防止“刷屏”假象
  5. ranked = sorted(range(N), key=lambda i: scores[i], reverse=True)按分数对文档排序并取前 K 个,这就是“Top-K 遴选”
  6. lines.append(f"[{idx}] {doc}")给每条依据加编号,形成引用溯源,让回答“有据可查”

常见误区

误区我以为 RAG 就是把文档丢进向量数据库,然后调 API 查一下就完事了。向量检索是核心技术,其他都不重要。

正解向量检索只是 RAG 的“前半场”。完整的 RAG 还包含文档切块、融合策略、提示词编排、引用溯源和评测反馈。就像图书管理员不只是会翻卡片目录,还得会挑书、排顺序、写摘要。单有向量库,生成的回答依然可能超范围发挥。

为何常见:因为向量检索是 RAG 里最有“黑科技感”的部分,教程和开源工具都重点展示它,容易让人误以为它是全部。

误区我担心 K 值设太小会漏掉关键判例,所以把 Top-K 设成 20 甚至更多,把所有候选都塞给模型。

正解上下文窗口有限,塞得越多,每个证据分到的注意力越少,噪声还可能把正确答案“淹没”。这就像桌上堆了五十本案例书,实习生反而找不到最关键的一页。K 值要根据知识块大小和窗口容量动态调整,法律场景通常 3~5 个高质量片段效果最好。

为何常见:直觉上“信息越多越保险”,忽略了模型的注意力是一种有限资源。

误区我以为接入 RAG 之后,模型就永远不会胡说八道了,幻觉问题被彻底解决。

正解RAG 大幅降低幻觉,但不能根除:如果检索到的材料本身不相关,模型可能对着不相关材料“硬编”答案;如果知识库没有覆盖该问题,模型仍可能凭训练记忆作答。引用溯源和忠实度评测就是用来兜底的两道防线。

为何常见:RAG 走红后宣传很多,让人以为它是“幻觉的万能解药”,但工程上没有银弹。

误区我把法规库一次性索引完,就认为系统可以永久运行,不需要再更新。

正解法律在变、判例在增,知识库必须做增量更新,评测集也要跟着扩充。否则系统会一直引用已废止的旧法条,比不用 RAG 危害还大。新法实施后 72 小时内完成索引更新,是法律 AI 的基本运维纪律。

为何常见:把 RAG 当成“一次性项目”,忽略了持续运维的数据更新环节。

误区我觉得只要检索器命中率足够高,模型生成的回答就一定是准的,所以只优化检索模块。

正解检索准只代表“找到了对的材料”,模型是否忠诚地使用这些材料是另一回事——它可能忽略材料、按自己的偏好作答,甚至把材料理解歪。生成阶段还要做上下文编排、约束指令和忠实度评测。两块都要抓,缺一不可。

为何常见:拆开看模块时容易只见树木不见森林,忘了端到端的最终评价标准是“用户是否拿到了准确可用的回答”。

面试题

Q1. RAG 的中文全称是?

单选题 · easy

  • A.检索增强生成← 正确答案
  • B.递归自动生成
  • C.随机访问图
  • D.关系代理网关

答案:A。RAG 全称 Retrieval-Augmented Generation,即“检索增强生成”。核心是先检索相关知识再生成回答,像图书管理员先找书再让实习生写答案。B、C、D 都与“检索+生成”的组合无关,是干扰项。

Q2. RAG 主要解决大模型在法律场景中的哪个痛点?

单选题 · easy

  • A.训练速度异常缓慢
  • B.幻觉与知识信息过时← 正确答案
  • C.推理部署成本过高
  • D.多模态交互能力弱

答案:B。大模型依赖训练数据,存在知识截止日期并可能编造不存在的“法条”,这就是幻觉。RAG 通过外部知识库补充实时信息并约束生成。虽然 RAG 也能间接影响成本或多模态,但核心解决的是知识可靠性问题。

Q3. 下列哪个模块不属于 RAG 的核心架构组合?

单选题 · easy

  • A.索引构建模块
  • B.向量检索模块
  • C.协同推荐系统← 正确答案
  • D.融合生成模块

答案:C。RAG 四件套是索引构建、检索、融合、生成。协同推荐系统是推荐领域的技术,与 RAG 的“检索知识再生成”没有直接关系,属于典型的无关干扰项。

Q4. 向量检索中衡量两段文本语义相似度最常用的指标是?

单选题 · mid

  • A.字符串编辑距离
  • B.向量余弦相似度← 正确答案
  • C.哈希碰撞次数
  • D.单词出现频率

答案:B。嵌入模型把文本变成向量,余弦相似度衡量两向量夹角,越接近 1 语义越接近。编辑距离衡量字符层面的差异而非语义;哈希碰撞和单词频率都不描述“语义距离”。

Q5. 上下文窗口管理正确的做法有哪些?

多选题 · mid

  • A.检索结果全部塞入
  • B.动态截断压缩处理← 正确答案
  • C.摘要压缩核心要点← 正确答案
  • D.删除查询指令信息

答案:BC。窗口容量有限,A 会超限并引入噪声;D 删除查询指令会让模型失去作答目标。正确做法是按相关性动态截断(B),或把长文档压缩成摘要(C),确保窗口内是高价值证据。

Q6. 引用溯源机制的核心作用是什么?

单选题 · mid

  • A.减少用户查询延迟
  • B.让回答有据可查← 正确答案
  • C.压缩模型参数量
  • D.替代人工审核过程

答案:B。引用溯源给回答中的关键结论标注来源编号并映射到知识库原文,方便核验和合规审计。它不直接影响延迟,不压缩参数,也无法完全替代人工审核,但能极大降低审核成本。

Q7. BM25 检索算法属于哪一类检索方式?

单选题 · mid

  • A.稠密向量检索
  • B.关键词稀疏检索← 正确答案
  • C.图结构知识检索
  • D.生成式综合检索

答案:B。BM25 基于词频和逆文档频率打分,属于经典的关键词(稀疏)检索。它与基于嵌入向量的稠密检索互补,法律场景常把两者组成混合检索。

Q8. 混合检索(Hybrid Search)组合了哪些技术的优势?

多选题 · hard

  • A.向量语义相似检索← 正确答案
  • B.关键词精确匹配检索← 正确答案
  • C.深度学习文本生成
  • D.物体检测与识别

答案:AB。混合检索 = 向量检索(抓语义相近)+ 关键词检索(抓字面精确匹配)。法律文本中,同义表述靠语义检索,法条编号等专有名词靠关键词精确匹配,两者加权融合。C 是生成技术,D 是视觉技术,均与检索无关。

Q9. RAG 评测中,“检索结果包含正确答案的查询比例”代表哪个指标?

单选题 · mid

  • A.检索命中率指标← 正确答案
  • B.生成忠实度指标
  • C.文本流畅度指标
  • D.请求延迟时间

答案:A。命中率 = 包含正确答案的查询数 ÷ 总查询数,衡量检索器在 Top-K 中能否找到正确文档。忠实度衡量生成内容是否被检索材料支持;流畅度是文本质感;延迟是性能指标,四个指标分别覆盖不同环节。

Q10. 持续优化 RAG 系统的有效手段包括哪些?

多选题 · hard

  • A.定期更新知识库索引← 正确答案
  • B.建立用户反馈闭环← 正确答案
  • C.按场景调整检索参数← 正确答案
  • D.永久固定提示词模板

答案:ABC。A 保证知识不过时;B 让负面反馈进入评测集并驱动改进;C 针对不同法律领域调 K 值、切块大小等超参。D“永久固定”与优化理念矛盾——提示词模板也需要随评测结果迭代测试。