☰
砼智 工程企业知识库搭建:法规条款RAG召回优化的几个实践
2026/10/22 7:26:46 网站建设 项目流程

工程企业做内部知识库,最典型的场景是法规、标准、定额、制度的检索问答。这类文档结构特殊、对“出处”要求极高,通用 RAG 直接套用往往效果不好。本文整理几个在工程条款类知识库上比较有效的召回优化实践。

TL;DR

  • 按条切片,保留结构路径与元数据,不拆散条款;
  • 混合检索,关键词权重不低于 0.5,精确命中编号;
  • 重排 + 上下文回填 + 版本过滤,提升召回质量;
  • 回答必带出处,无依据时明确拒答,不硬编造;
  • 评估分开看:检索质量与答案质量各自独立衡量。

一、先解决切片:工程文档不能按固定长度切

工程文档(规范、标准、法规)有明显的层级结构:章、节、条、款,而且强条、术语、表格往往不能被拆开。

实践要点:

  • 按"条"为最小切片单位,保留条号与原文,不把一个完整条款切成两半;
  • 每个切片附带完整的结构路径,如"某施工质量验收规范 > 第 6 章 > 6.2 > 6.2.3";
  • 表格、公式作为独立切片,保留表头,避免只检索到孤立单元格;
  • 切片同时保留"原文"与"元数据"(规范编号、版本号、发布/实施日期、是否强条)。

固定长度切分会把条款和它的上下文割裂,导致召回时语义不完整。一个典型的切片结构:

{"doc_id":"gb-xxxx-2014","path":"第6章 > 6.2 > 6.2.3","clause_no":"6.2.3","text":"条款原文……","is_mandatory":false,"version":"2014","effective_date":"2015-01-01"}

二、检索:向量与关键词混合,工程条款更吃关键词

纯向量检索在工程场景有两个问题:一是条款里大量专业术语、强条编号、数字(如 “30 万方” “C30”),向量容易模糊;二是用户常直接按编号或精确表述查询。

因此采用混合检索:

  • 一路用 Embedding 做语义召回,覆盖“意思相近但表述不同”的问法;
  • 一路用关键词(BM25/倒排)匹配条款号、术语、规范编号、数字;
  • 两路结果按归一化分数加权融合,再进入重排。

经验上,工程条款检索里关键词通道的权重不应设得过低,很多“按编号查”“查强条”的问题,命中高度依赖精确匹配。

下面给出一个混合检索的 Python 示例,演示向量检索与 BM25 关键词检索如何并行召回、再按归一化分数加权融合:

importnumpyasnpfromrank_bm25importBM25Okapidefnormalize(scores:list[float])->list[float]:"""Min-Max 归一化,把分数压到 [0, 1],便于两路加权融合。"""arr=np.array(scores,dtype=float)ifarr.max()==arr.min():returnnp.zeros_like(arr).tolist()return((arr-arr.min())/(arr.max()-arr.min())).tolist()defhybrid_search(query:str,chunks:list[str],embed_fn,top_k:int=5,w_vec:float=0.4,w_bm25:float=0.6)->list[tuple[int,float]]:""" 混合检索:向量召回 + BM25 关键词召回,按权重加权融合。 :param query: 用户问题,如 "C30 混凝土强度等级要求" :param chunks: 切片列表(每个元素是条款原文) :param embed_fn: 返回 query 与各切片向量的函数,输出 shape 为 (n_chunks,) :param top_k: 最终返回的候选条数 :param w_vec: 向量通道权重 :param w_bm25: 关键词通道权重(工程条款建议不低于 0.5) """# 1) 向量通道:语义召回vec_scores=embed_fn(query,chunks)# 余弦相似度等,越大越相关vec_norm=normalize(vec_scores)# 2) 关键词通道:BM25 精确匹配条款号、术语、规范编号tokenized=[c.split()forcinchunks]bm25=BM25Okapi(tokenized)bm25_scores=bm25.get_scores(query.split())bm25_norm=normalize(bm25_scores)# 3) 加权融合,取 Top-Kfused=[w_vec*v+w_bm25*kforv,kinzip(vec_norm,bm25_norm)]ranked=sorted(enumerate(fused),key=lambdax:x[1],reverse=True)[:top_k]returnranked# 运行结果说明:# 对 "按 6.2.3 条查混凝土强度" 这类问题,BM25 通道能精确命中条款号,# 融合后该切片分数显著高于仅靠语义相似度的结果;# 对 "强度不够怎么办" 这类口语化问法,向量通道负责兜住语义相近的条款。# 实际工程中建议 w_bm25 取 0.5~0.7,避免精确编号被语义噪声稀释。

运行结果说明:对“按 6.2.3 条查混凝土强度”这类问题,BM25 通道能精确命中条款号,融合后该切片分数显著高于仅靠语义相似度的结果;对“强度不够怎么办”这类口语化问法,向量通道负责兜住语义相近的条款。实际工程中建议w_bm25取 0.5~0.7,避免精确编号被语义噪声稀释。

下面是混合检索的整体流程:

用户问题

向量召回
Embedding 语义相似度

关键词召回
BM25 精确匹配条款号/术语

Min-Max 归一化

加权融合
w_vec * 向量分 + w_bm25 * 关键词分

Top-K 候选切片

进入重排与上下文回填

三、召回优化:重排、过滤与上下文回填

初筛拿到候选切片后,需要进一步处理:

  1. 重排(rerank):用交叉编码器对问题和候选切片做相关性重排,比单纯向量相似度更准,能把"看起来相似但实际不是一回事"的条款压下去;
  2. 上下文回填:检索到某个条款时,把它的上一条、下一条以及所属小节的定义一并补入,避免条款里的代词、引用(“应符合本规范第 X 条”)悬空;
  3. 版本与时效过滤:按"现行有效"过滤,过期或作废的版本默认不参与召回,或明确标注"已废止";
  4. 强条与普通条款区分:涉及强制性条文的问题,优先返回强条并显著标注。

整体召回优化链路如下:

初筛候选切片

重排
交叉编码器相关性排序

上下文回填
补入上/下一条与定义

版本与时效过滤
剔除过期/作废版本

强条优先标注

进入生成环节

四、出处标注与无依据兜底

工程领域最忌讳“AI 凭空说”,因此生成环节有两条硬约束:

  • 回答必带出处:每一条结论都要能回溯到具体规范编号、条款号和版本,最好在回答中直接给出;
  • 无依据不硬答:检索分数低于阈值、或没有可靠来源时,不编造结论,而是明确提示“未检索到可靠依据,请人工核实”。

可以在提示词中约束模型只依据给定上下文作答,并用引用标记(如脚注编号)把结论与切片绑定,便于追溯。

五、评估:召回与答案要分开看

工程知识库的效果不能只看“答得顺不顺”,建议分开评估:

评估项关注指标说明
检索质量Recall@K、MRR正确条款是否在候选里、排第几
重排质量NDCG、命中前 3 比例目标条款是否被提到前面
答案质量引用准确率、出处完整率结论是否忠实、出处是否对得上
兜底能力无依据拒答率无来源时是否如实拒答
时效准确性现行版本命中率是否误用过期条款

评估集要覆盖不同问法:按编号查、按术语查、按场景描述查,以及查不到的问题,最后一类专门用来检验兜底是否生效。

工程企业的知识库建设不是一次性工程,文档版本更新、召回参数、重排策略都需要随业务迭代持续调优。

最后说两句

本文为技术科普,不构成任何商业建议。文中的参数与权重仅为通用经验,实际取值需要结合具体文档规模和评估集做实验确定。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询