简单来说,RAG的使用可以简单的划为两个步骤:存储、检索、优化

1、存储

1.1上传之前:

文本处理——扫描件处理

文本解析——Apache Tika

1.2上传方式:

1.2.1分片上传:

固定长度分块——512token + 10% overlap(尽可能保证语义的完整度)/ 不加overlap(相同的内容被向量检索命中时,会召回包含该片段的多个切片,影响召回效率,可以分片之外维护一个 1MB 的父块,流式读进来防止 OOM,分片只承担向量召回,命中之后回溯到父块给大模型作为上下文)

语义分块——根据章节结构、段落、标点进行切割,并设置分块长度的上下界,避免过长或者过短。

1.2.2断点续传:

分片之后,基于**算法对分片进行计算,并在上传z中断时进行校验,从断开处及逆行续传;在上传完成时进行完整校验

1.3存储方式:

elastic search 同时支持关键词检索和向量检索:

针对关键词检索,以knowledge-base字段存储,存储结构为倒排索引;针对向量检索,以dense-vector字段存储,索引结构为HNSW,

不采用其他主流的向量库的原因:如milvus还需要搭配关键词库使用。

1.4存储过程:embedding

1.4.1对比不同的embedding模型:

Qwen3-Embedding:对中文文档的召回效果最好,32K 超长文档向量化,整本知识库切片检索精准,原生支持多维度;

Doubao-embedding:日常中文知识库、客服问答、企业文档检索稳定;上下文仅 4K,超长文档需要手动切片;小语种、代码能力弱于 Qwen;

Seed1.6-embedding:文本、图片、短视频映射到同一个向量空间,纯文本检索不如Qwen。

1.4.2采用2048维:

1.纬度越高,向量空间的表达能力越强,对长文本和专业术语的区分度增加;

2.对比1024和2048在es中的存储空间占用,单条向量占用仅增加8kb左右;

3.针对检索过程中可能增加的时间成本,维度的增加主要影响语义召回的速度,但本设计中以关键词召回为主导,BM25进行兜底,时间成本可控。

2、检索

2.1采用混合检索的方式:

向量检索+关键词检索——KNN + BM25的方案,实现找回结果“全”+“准”,单次召回响应耗时约80ms。

全:基于KNN进行向量召回,召回量为top K * 30,这一步骤基于es的原生接口knn-search;

准:在KNN召回范围内进行rescore,进行精确召回(准),召回量为top K,是召回的主导部分,对精确词的召回很敏感,避免语义召回“语义相近但答案错位”的情况。

Rescore基于BM25算法实现,BM25算法是在TF-IDF基础上增加了对词频增长速率的限制。TF-IDF的核心是TF(词频)、IDF(逆文档频率)、文档长度归一化,刺在当前文档里出现的频率越高,其权重越大;词在所有文档中出现的越普遍,权重应降低;文档越长,单个词的权重应该减低。

但是对于长文本而言,词频越高并不能代表重要性持续线性增长(不能因为长文本中单个词出现频率更高就认为这个词的重要性得分持续线性增长,应该适当调整增长速率),因此在BM25中加入k1作为系数限制增长速度。

2.2LLM:Deepseek chat

针对中文文档,输出质量高且价格较低

3、优化

3.1如何评估效果

检索顺序:检索阶段(召回率、准确率)、生成阶段(答案准确率、忠诚度

3.1.1检索阶段:

召回率:已召回的topk个文档中被标注的占全部标注文档比例;

准确率:已召回的的topk中有多少是真正被标注的;

MRR(平均倒数排名):第一个被召回的相关文档排在第几名;

召回冗余率:召回结果中重复的部分(否则会造成召回率高但答案准确率低)

3.1.2生成阶段:(这里在实际任务中怎么检测呢?)

答案准确率:生成答案与标准答案之间的差距;

忠诚度:答案中的事实声明有多少能在检索到的文档中找到依据

3.2问题定位:数据处理 + 召回 + 模型

3.2.1数据处理:

包括初始的数据清洗、分块方式、向量库更新策略;

3.2.2召回策略:

混合检索——语义/关键词召回的阈值、权重,采用什么算法

3.2.3模型:

基座模型的选择:deepseek chat

上下文窗口大小:滑动窗口、摘要机制

幻觉:在prompt中硬性规定“必须基于召回的切片进行回答,不允许无中生有“;设定向量召回的相似度阈值,如果都达不到阈值,返回差五结果而不是给出一个并不合理的回答。

3.3如何提升

3.3.1RAG架构选择

当前是基础RAG设计,关键词索引依赖于倒排索引,向量索引依赖于HNSW。在需要进行向量库更新时,每次都要遍历节点后更新,计算量十分大,基于此考虑更新RAG架构:

Graph RAG将知识库中的实体映射为图节点,将实体之间的关系映射为边,构建全局大图,自动聚类community,并生成对应摘要;查询时先星星向量检索(粗筛),之后通过多跳推理挖掘关联子图精召回,召回性能提高;但是community不支持增量更新,当需要更新知识库时,要重新构建整个图并针对全部的多层community生成新的摘要,计算成本极高;

Light RAG取消community强约束,在知识库更新时仅针对相关实体个关系做增量更新,而无需LLM完成community构建和生成相关摘要等重型任务。

3.3.2当前召回响应耗时

单个召回约80ms,该数据和知识库的数据量、recall K、文档命中范围相关

数据量:知识库存量越大,向量相似度计算、关键词匹配检索的计算开销同步上升,召回时延随之增加;

Recall K:增大召回条数 K 会提升向量排序、关键词结果合并过滤的计算量,但持续扩大 K 值对检索收益提升有限,需平衡时延开销与检索覆盖效果;

文档命中范围:若用户查询语义宽泛,会匹配大量候选分片,候选集膨胀直接抬高相似度打分与结果聚合耗时。

3.3.3 function calling SFT

基于通用模型的准确率可以达到70%,经过SFT(微调之后达到90%)。

通用模型的训练是泛化并没有针对具体场景进行深度训练,所以需要SFT。

  1. 构造种子问题——在线系统日志、专家编写
  2. 扩充问题——问题改写、扩展
  3. 利用Teacher模型生成轨迹,再用质量验证过滤——JSON格式是否可以被解析,轨迹步数是否合理
  4. 微调完成后验证增长是真实的

从种子数据里留出来的、没有参与训练的部分

泛化测试:训练集里没有或极少出现的场景

对抗测试:构造一些看起来需要调用工具 但实际上不需要的场景,避免无意义的调用

reference:沉默王二

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐