当前位置: 首页 > news >正文

RAG实现思路流程

上传接口

阶段一:前端分片与“指纹”识别(Gateway)

在处理 GB 级别的文档时,传统的单文件上传会导致连接超时或内存崩溃。

  • 预处理(MD5 计算):前端利用spark-md5预先扫描文件,生成FileMD5。这是文件的“身份证号”,用于实现秒传(如果后端已存该 MD5,直接返回成功)。
  • 物理切片(Slicing):利用 JavaScript 的Blob.slice()将大文件切割为固定大小(如 5MB)的Chunks
  • 并发上传:前端同时发起多个uploadChunk请求,携带chunkIndexfileMd5

阶段二:后端接入与可靠性保障(Warehouse)

后端不仅要收数据,还要做精密的状态管理。

  • 二级校验(Redis + MySQL)
    • Redis:作为高性能计数器,记录已到达的分片编号,实现高并发下的快速判重
    • MySQL:持久化文件元数据(文件名、总大小、上传者、组织权限)。
  • 断点续传逻辑:如果上传中断,用户下次上传同一 MD5 文件时,后端通过查询 Redis/MySQL 返回已收到的chunkIndex,前端从断点处继续发送。
  • 云端合并(MinIO):当所有分片到齐,后端调用 MinIO 的composeObject接口进行服务端合并,避免将几十 GB 的数据拉回应用服务器内存。

阶段三:任务调度与异步解耦(Assembly Line)

文件存入 MinIO 只是开始,真正的“重型加工”必须异步化。

  • 任务下发(Kafka):后端合并完成后,立即向 Kafka 发送一条包含fileMd5objectUrl事务消息
  • 削峰平谷:Kafka 充当了缓冲池。即便用户瞬间上传了 1000 份文档,后台的Consumer(消费者)也会按照自身算力(CPU/内存情况)有序地领取任务,防止系统宕机。
  • 存算分离:Web 服务器只负责“收货”,解析任务交给专门的“加工服务器”。

阶段四:文档解析与语义切片(Alchemy)

这是 RAG 系统区分于传统网盘的关键点,目标是将非结构化数据转化为“AI 易读”的格式。

  • 流式下载与解析:Consumer 收到消息后,从 MinIO 拉取流式数据,利用Apache Tika等工具提取纯文本。
    • 注意:避免将大文件一次性加载进内存,应使用磁盘临时目录作为缓冲区。
  • 语义切片(Chunking):将提取的长文本切分为小段(如 500-800 Token)。
    • 重叠度(Overlap):相邻切片需保留 10%~20% 的重复内容,确保语义在切断处不丢失。
    • 语义边界:优先按段落、标题、句号进行物理切割。

阶段五:向量化与知识入库(Indexing)

将文字转化为数字,存入搜索引擎。

  • Embedding 向量化:将每一个 Chunk 喂给 Embedding 模型(如 OpenAItext-embedding-3或本地模型),得到一串固定长度的高维浮点数组
  • 索引构建(Elasticsearch)
    • [原始文本, 向量数组, 元数据]存入 ES。
    • ES 底层利用HNSW 算法构建导航图索引,实现毫秒级的语义近似搜索
  • 状态闭环:全部入库完成后,更新 MySQL 中的文件状态为SUCCESS,用户此时即可在界面上看到“文档已就绪”。

Mysql,Redis,Elasticsearch,minIO如何协同工作保证一致性?

系统通过 MySQL 中的status字段强制约束各组件的动作。

状态语义潜在冲突 / 异常情况解决策略 (自愈机制)
0: INIT任务初始化,未开始上传孤儿分片:MinIO 存在该 MD5 文件夹,但 MySQL 仅停留在 INIT。定时任务清理:扫描 MinIO 临时目录,若 MySQL 记录为 INIT 且超时,物理删除 MinIO 数据。
1: UPLOADING分片上传中计数不一致:前端重试导致 Redis 计数 > 实际分片数,或分片丢失导致无法合并。幂等计数:Redis 记录已上传的chunkIndex集合而非单纯累加;定时任务检查超时未完成的任务。
2: MERGING合并触发中并发合并:两个请求同时发现分片到齐,触发两次 MinIO 合并请求。分布式锁 + 状态前置检查:使用 RedisSETNX锁定fileMd5;执行合并前必须确认状态仍为 UPLOADING,合并开始瞬间更新为 MERGING。
3: PROCESSING任务已发 Kafka,解析中丢失任务:MySQL 状态为 PROCESSING,但 Kafka 消费失败或消费者宕机。超时重推:定时任务扫描超过 30 分钟仍处于 PROCESSING 的记录,重新投入 Kafka 队列(补偿机制)。
4: SUCCESSES 索引完成数据残留:MySQL 已成功,但 MinIO 临时分片未清理,占用空间。后置清理:状态改为 SUCCESS 后,触发异步删除 MinIO 临时分片;若失败,由垃圾回收 Job 兜底。
5: FAILED处理失败脏数据堆积:ES 中存了部分向量,MinIO 存在合并后的文件。物理抹除:状态转为 FAILED 时,根据fileMd5同步删除 ES 相关索引及 MinIO 物理文件。
1. 逆向校对策略 (Backward Reconciliation)
  • 原则:MinIO/Redis/ES 的数据必须在 MySQL 中找到“合法身份”。
  • 执行:定时任务(Reconciliation Job)以存储侧(MinIO/ES)为基准扫描。
    • 如果MinIO 有文件MySQL 无记录/状态为 INIT→\rightarrow物理删除MinIO 文件。
    • 如果ES 有向量MySQL 状态非 SUCCESS→\rightarrow物理删除ES 向量。
2. 状态原子性与可见性
  • 先写库,后动作:在调用 MinIO 合并或发送 Kafka 消息前,必须先在数据库中完成状态变更。
  • CAS (Compare And Swap):更新状态时使用 SQL:UPDATE file_table SET status = 2 WHERE file_md5 = 'xxx' AND status = 1。利用数据库行锁防止并发冲突。
3. 消费者幂等性
  • 冲突:Kafka 消息重复消费导致重复解析。
  • 解决:ES 写入使用fileMd5_chunkIndex作为文档 ID。无论解析多少次,ES 始终执行Overwrite(覆盖)而非Append(追加),保证最终向量数据的一致性。


混合检索接口

阶段一:权限画像与查询语义化

在检索开始前,系统首先确定“谁在搜”以及“搜什么”。

  • 语义向量化:利用 Embedding 模型将原始提问(Query)转化为高维向量。
  • 文本分析与提取:利用分词器将整个句子切分为词组
  • 双路准备:此时系统手中同时持有查询向量(用于语义搜索)和原始关键词(用于文本搜索)。

阶段二:向量召回与强过滤

这是检索的“漏斗”入口,核心是语义找近邻,权限做隔离

  • 向量召回 (KNN):在向量空间中寻找语义最接近的 topN 个片段。这解决了“意思相近但词不同”的问题。
  • 硬性权限过滤 (Filter):这是一个“一票否决”环节。系统强制要求结果必须满足:是我的文档OR是公开文档OR是我组织的文档。不满足条件的片段即使语义再接近也会被剔除。

阶段三:关键词召回与分数融合

向量检索虽然聪明,但有时会产生语义幻觉(词不达意)。本阶段通过重排纠偏。

  • 关键词二次打分:对召回的候选片段进行传统的文本频率算法(BM25)打分。
  • 分数加权融合
    • 给语义分(向量)分配权重。
    • 给关键词匹配分(文本)分配权重。
  • 逻辑目标:确保那些既符合语义,又含有精确关键词的片段能够排在最前面。

阶段四:结果装配与元数据溯源

将 ES 检索到的“数字碎块”还原为用户可读的结构化信息。由于向量数据库(ES)主要负责高性能检索,并不适合存储频繁变动或详尽的业务属性,因此需要此阶段进行“数据对账”。

  • 数据映射:利用 ES 检索结果中的fileMd5回查MySQL。将哈希值还原为真实的文件名称。这实现了存算分离:即使文件在数据库中改名,也无需重新计算向量。
  • 属性补全:将 ES 中的权限 ID(如userId,orgTag)转换为可读的业务标签(如上传者姓名、所属部门)。这为前端展示提供依据,也为大模型(LLM)提供准确的引用出处(Citation)。
  • (如果是模型对话功能)片段截取:对文本进行清洗(去乱码/换行)并按需截断。确保提供给大模型的上下文(Context)既精炼高质,有效节省 Token 消耗并提升回答准确度。

阶段五:功能分流与生成增强

根据用户的业务需求,决定最终数据的去向

  • 判断当前请求类型。若为搜索功能,则直接将阶段四封装好的结构化列表返回给前端,展示带权限的文件片段。
  • 上下文拼接:若为模型对话,则将多个检索片段按相关性顺序进行文本串联,形成增强知识背景。
  • 提示词增强 (RAG):将拼接好的背景知识与用户原始提问填入预设的Prompt 模板,调用大模型(LLM)接口,并将生成的回复以SSE 流式(Streaming)或 WebSocket实时推送到前端。

http://www.jsqmd.com/news/557003/

相关文章:

  • 手把手教你用XSS平台复现BUU靶场第一课(附可用的免费平台推荐)
  • 2026年全国护肤代工行业十大排行:祛痘去闭口产品OEM加工/敏感肌修护产品OEM加工企业深度解析,以科技护肤为引领布局广东佛山等地区 - 十大品牌榜
  • MVCC 与事务隔离:MySQL 如何实现“读不阻塞写”?
  • YimMenu全面使用指南:从功能探索到安全应用的完整路径
  • 当因果图遇到混淆变量:手把手教你用PAG(部分祖先图)解读真实世界数据
  • Druid连接池minIdle和maxActive参数详解:如何避免连接池耗尽问题
  • 基于PLC的间歇反应釜智能温控系统设计与实践【附仿真代码】
  • 创新二维码生成利器:theqrmodule模块实战指南
  • ARKit数字人开发指南:如何用苹果52个BlendShape权重实现自然表情动画
  • 在C++中,什么是类的友元函数,如何使用?
  • 从零到一:用HarmonyOS和ArkTS开发一个宠物社交App(附数据库设计)
  • 聊天记录丢失?用WeChatMsg构建个人数据护城河,让数字资产永久归属自己
  • Windows持久化核心战术:系统服务植入实战教程
  • 给CFD新手的建议:从Python环境到OpenFOAM cavity案例,我的第一个完整模拟踩坑记录
  • Ubuntu 22.04 镜像源切换实战:从备份到极速更新的保姆级指南
  • python vue大学生足球队俱乐部管理系统
  • FanControl:Windows系统终极风扇控制软件完整使用指南
  • YOLOv11涨点改进| Arxiv 2026 | 独家创新首发、注意力改进篇| 引入InfSA无限自注意力模块,使注意力图更聚焦、全局建模更强,含多种改进,助力小目标检测、图像分割、图像分类高效涨点
  • LabelImg终极指南:快速掌握免费图像标注工具的使用技巧
  • 4大维度重塑音乐体验:面向发烧友的foobar2000增强方案
  • 【动静障碍物】基于JPS算法(改进A)全局路径规划与DWA动态窗口局部避障的机器人自主导航混合控制算法附Matlab代码
  • Windows应急响应实战:玄机靶场vulntarget-j-02后门排查全记录(附NTLM哈希爆破脚本)
  • 揭秘AI写教材:低查重技巧与高效工具的完美结合
  • 从API调试到文件加密:Python GMSSL的SM4算法在5个真实场景下的应用代码
  • 20251202马思钊3.23实验课报告
  • 使用Java实现支付宝支付接口的完整对接教程
  • BAAI/bge-m3从零部署:WebUI可视化工具,快速实现语义匹配验证
  • Windows powershell view huge file via command
  • 突破安卓权限壁垒:LAMDA自动化框架的跨设备流媒体解析技术全解
  • python+vue电影推荐系统python协同过滤