RAG 技术原理、工程实践与安全设计

1. RAG 解决什么问题

大语言模型的参数存储了训练过程中获得的知识与能力,但企业内部文档经常变化,且包含不能直接公开的内容。将每份新文档用于微调,成本高、更新慢,也难以彻底处理撤权和删除。RAG 的思路是:知识保留在外部数据源中,模型在回答时检索相关资料,将授权的片段放入上下文,再生成答案。

它通常不修改模型权重。RAG 也不是一个独立模型,而是一套覆盖数据处理、搜索、权限控制与生成的应用架构。

架构分成两条流水线:入库时构建知识索引,查询时检索并生成答案。检索命中的是内容相关性,不代表用户有读取权限;后者必须由可信的业务或检索服务执行。

9fc12a2b-eb18-4c3d-9c96-a703157b059f

2. 文档入库:解析、切片、索引

2.1 不同格式是否都要先转成 Markdown?

不必。实际系统通常先把多种文件解析成统一的中间结构(Intermediate Representation),描述标题、段落、表格、图片、坐标及阅读顺序。Markdown 可用于导出和后续处理,但复杂文档更适合保留结构化 JSON 与原图。

输入 解析重点 常见难点
DOCX 样式、标题层级、段落、嵌入图片与表格 人工加粗代替标题样式、浮动图片
PDF 文本块、版面、页码、坐标和阅读顺序 双栏、跨页表格、扫描件、页眉页脚
HTML DOM 结构、标题、正文、图片说明 导航、广告、隐藏文本等噪声
Markdown 标题、列表、代码块和链接 非标准格式、超长章节
Excel 工作表、行列、表头、公式结果 跨表关系、合并单元格、缺乏自然段落

一个可用的中间结构至少包括 doc_id / block_type / text / heading_path / page / bbox / source / version / ACL。它既服务检索,又服务来源追溯和权限继承。

2.2 为什么会切出不合理的 Chunk?

这里要区分两个故障层次。解析错误是内容识别错误,例如将 PDF 左右栏交叉读取、把标题识别成正文;切片错误是已识别的内容被错误组合,例如固定每 500 Token 截断,导致两章合并或一个完整流程被拆散。

优先采用 Layout-aware Parsing + Hierarchical Chunking(版面感知解析 + 层次化切片):

  1. 先识别标题、段落、表格、图注、阅读顺序;去除重复页眉页脚。
  2. 以章节、标题与语义边界为第一层,尽量不跨独立章节拼接。
  3. 对过长章节再按 Token 数切分;可从 300–800 Token、适量 overlap 做实验,而非作为固定标准。
  4. Chunk 附带父级标题路径(例如“人事制度 > 薪酬管理 > 调薪审批”),必要时采用“小块检索、大块回填”。
  5. 表格以表头与相关行绑定的方式切分,不要把列名与数据分离;代码、公式和流程按其自然单元处理。

诊断顺序:先看原文和解析结果是否一致,再检查切片边界,最后调整 Top-K 和重排序。 如果双栏顺序已经错乱,仅调 Chunk Size 无法修复。

2.3 图文混排如何处理?

纯文本 RAG 往往丢失架构图、流程图、截图里的关键信息。较完整的方案是:提取图片并保存其 image_id、page、bbox、caption、heading_path,使用 OCR 识别图片文字,必要时用视觉语言模型(VLM)描述流程关系或图表含义,然后将图片与前后段落、图注、所属章节建立关联。

例如,一张“用户 → 身份验证 → 权限检查 → 数据库”的图,可以同时保存原图、图注、OCR 文本、VLM 生成的摘要、邻近段落引用。查询命中时可返回文字片段与图片引用;要求精确解释图表时,再把原图提供给支持视觉输入的模型。VLM 描述可能漏掉箭头或细节,所以不应完全替代原图。

2.4 向量索引、召回与排序

每个 Chunk 会由 Embedding 模型映射为一组数值向量,用于语义近邻搜索。数据库可以采用 HNSW 等近似最近邻索引;同时使用关键词倒排索引(如 BM25)补足人名、编号、产品名和精确术语。

查询时的常见链路是:

验证身份 → 限定授权数据集 → 问题向量化 → 向量与关键词混合召回 → Reranker 重排序 → 组装经授权的上下文 → LLM 回答。

这里有两个容易混淆的词:Indexing(建索引)在文档入库时发生,Ranking(结果排序)在用户查询时发生。入库时不会提前知道某片段对未来所有问题的相关性排名。

3. 常见工程问题与调优思路

症状 优先排查 解决方向
标题、正文混淆 解析器的结构识别结果 使用版面分析、标题层级与人工校对
双栏、跨页顺序错乱 PDF 阅读顺序及坐标 更换版面解析模型、按区域重排
片段跨章节 Chunk 边界规则 层次化切片,禁止无意义跨章节合并
表格回答缺列名 表格结构与 Chunk 保留表头、合并单元格关系及源表引用
图片信息检索不到 图片是否入库、是否建立文字关联 OCR + 图注 + VLM + 原图回溯
关键词精确匹配差 只用了向量检索 采用 BM25 + 向量混合检索
检索命中但回答不准 Rerank、上下文组装、提示词 评估召回与生成两个环节,增加来源引用
撤权后仍召回旧内容 ACL 副本、索引更新、缓存 查询时有效授权、同步失效、清理派生数据

工程上应保留 原文 → 解析块 → Chunk → 索引记录 → 查询结果 → 答案 的可追溯链路。评估不要只看“回答似乎正确”,还要检查召回率、Top-K 命中率、引用准确性、越权返回率与撤权生效时延。

4. 如何选择 RAG 工具与部署方式

RAG 不是只能二选一:完全自建或完全购买。实际方案常把开源应用平台 + 自建检索服务 + 云端模型 API组合使用。

模式 代表方案 自己需要承担什么 适合场景
开源平台、自托管 RAGFlow、Dify 部署运维、身份集成、安全配置、补充 ACL 快速 PoC、内部知识应用
框架自建 LlamaIndex、LangChain + Milvus/pgvector 解析、索引、检索、权限、观测与更新全链路 深度定制与复杂多租户业务
商业闭源 RAG SaaS Vectara 等 数据治理、身份/权限映射、厂商安全评估 追求交付速度、减少运维
云厂商托管 Amazon Bedrock Knowledge Bases、Azure AI Search、阿里云百炼 IAM、数据地域、检索授权、云资源与费用治理 已有对应云平台基础设施

选型不应只比较模型回答效果,更要看六项能力:复杂文档解析、Chunk 可观测与可编辑、混合检索与 Rerank、文档级 ACL、撤权和删除同步、审计与接口安全。尤其要核实:平台所谓“知识库私有”究竟只限制控制台管理操作,还是对所有检索 API 真正实施了用户级授权。

针对学习:可先用 RAGFlow 观察 PDF 解析/Chunk,然后用 Dify 组装应用,最后用自建最小检索接口验证 ACL;针对生产:以组织既有身份体系、敏感数据要求和隔离等级来选型。

5. RAG 的安全边界:相关性不是访问权

RAG 的核心信任边界,是把外部可写材料转为模型上下文,以及把业务身份转为搜索和工具调用权限。Embedding 表示的是语义相关性,无法证明租户身份、文档所有权或访问授权。

5.1 多租户必须每个租户一套知识库吗?

不一定。常见三种形态:

方案 实现 优点与代价
共享索引 + tenant_id 过滤 同一索引中按可信租户字段过滤 成本低,但严格依赖过滤表达式与应用授权
共享基础设施 + 独立 Namespace/Collection 每租户独立逻辑检索空间 隔离更清晰,仍需验证检索路由和凭据
每租户独立实例 独立数据库、密钥、网络和运维边界 更强故障隔离,但成本和运维开销高

多租户隔离之外,还需租户内部文档级 ACL。例如租户 A 的普通员工也不应读取 A 租户 HR 专用文件。Chunk 必须继承原始文档的 tenant_id、allow_roles、owner、version 等元数据。

授权条件应由服务端根据登录态获取,而不能相信客户端自行填写的 tenant_id。更稳妥的执行逻辑是:

# 伪代码:说明安全语义,不是具体向量库 API
identity = verify_session(request)
allowed_scope = authz.resolve(identity)   # 租户、角色、文件 ACL
results = search_index.query(
    embedding=embed(request.question),
    scope=allowed_scope,                  # 服务端生成,不能由前端覆盖
)
results = [c for c in results if authz.can_read(identity, c.doc_id)]
context = build_context(results)
answer = llm.generate(request.question, context)

实际实现优先使用检索引擎的可信原生 ACL 或查询时过滤,并防止检索条件被字符串拼接注入。上例的二次校验是纵深防御:即使某条路径返回了非法候选,也不能把它放入 LLM 上下文。不能先把所有租户文档交给模型,再要求它“不要泄露”。

5.2 撤权、删除为何会失效?

原始文件系统与 RAG 索引通常独立存储。比如“薪酬表.xlsx”原来允许 HR 和财务读取;管理员将其改成仅 HR 可读,但旧 Chunk 上仍保存 allow_roles=[HR,Finance],而检索服务只相信旧索引,于是财务员工仍可能从 RAG 读取该表。

这叫 Stale ACL(权限元数据过期)。另一类是删除原文件后,解析文本、Chunk、向量库 Payload、缓存、摘要、历史回答仍留有副本。须区分两者:撤权不一定要求删除向量,但要求查询时立即阻止无权访问;彻底删除则还涉及数据生命周期与派生副本清理。

建议采用:权威权限源 + 变更事件驱动失效 + 查询时有效授权 + 定期对账。可按文档维护 auth_version / index_version / disabled,撤权时先使资源在查询路径上不可访问,再异步更新索引和缓存。系统无法确认权限时默认拒绝(fail closed),并验证撤权后的检索、缓存和直接文档 ID 查询。

5.3 其他常见风险

  • RAG/知识投毒:攻击者污染检索内容,让答案引用虚假事实;若文本诱导模型调用工具,还可能变成间接 Prompt Injection。
  • 跨租户缓存污染:缓存键未纳入租户与权限上下文,使 A 用户命中 B 用户的检索结果或答案。
  • 检索过滤注入:用户可控参数拼入数据库过滤表达式,突破 tenant_id / resource_id 限制。
  • URL 摄取 SSRF:RAG 的网页抓取或 URL 导入功能可被滥用,读取服务器可达的内部接口。
  • 敏感信息进入日志或第三方服务:Embedding、OCR、VLM 和 LLM API 都可能接触文档内容,须逐一检查处理方、地域、留存与访问策略。

6. 公开安全案例:从具体漏洞理解根因

以下是官方安全公告披露的漏洞,不等于已经确认发生了大规模真实客户数据泄露。

案例一:Open WebUI 未授权 RAG 文档检索——CVE-2026-44560

原始安全公告:GHSA-h36f-rqpx-j5wx

受影响版本为 ≤ 0.8.12,修复版本为 0.9.0。部分 RAG 来源解析路径在向量查询前没有检查文件或知识库的读取权限。公告指出,已登录攻击者如果知道目标资源的文件 ID 或知识库 ID,便可能通过相关路径检索私有内容;共享权限撤销后,已知 ID 仍可能被滥用。根因是接口路径间的授权不一致,而不是向量模型“破解”了权限。

案例二:Open WebUI + Milvus 多租户过滤绕过——CVE-2026-54019

原始安全公告:GHSA-p5cp-r7rg-qpxc

受影响版本为 ≤ 0.9.5,修复版本为 0.9.6,前提是启用 Milvus multitenancy 模式。系统将用户可控的集合名用于构造 resource_id 过滤表达式,但未安全转义,导致特制集合名能够改变过滤逻辑,进而读到其他用户的私有知识片段。根因是授权条件被当成可拼接的搜索语句,形成过滤表达式注入。

案例三:Open WebUI RAG 文件覆盖——GHSA-jjp7-g2jw-wh3j

原始安全公告:GHSA-jjp7-g2jw-wh3j

受影响版本为 ≤ 0.8.5,修复版本为 0.8.6。一个用于批量处理文件的接口缺少文件所有权校验,已登录用户知道目标文件 ID 后可覆盖本不应修改的文件内容;污染内容会进入 RAG 知识链路,影响其他用户得到的答案。它主要是完整性/知识投毒风险,不应与前两例的机密性/越权读取混为一谈。

三个案例分别说明:漏做授权、过滤条件注入、写入接口越权,都可能沿着 RAG 链路放大影响。完整评估不能只测聊天界面,还要覆盖直接检索、按 ID 查询、文件处理、文档共享和撤权后的所有路径。

7. 一套可落地的 RAG 安全检查框架

建议按数据生命周期设计控制,而不是只在 Prompt 中写“不要泄露”。

环节 关键控制 应验证的失败条件
接入与解析 文件类型限制、恶意内容检查、OCR/模型数据出站控制 未授权文件入库、隐私文档发往不允许的外部解析器
切片与索引 原文 ACL 继承、租户标识、来源与版本关联 Chunk 丢失权限标签或混入其他租户
检索与排序 服务端身份、文档 ACL、可信过滤、防注入 跨角色/跨租户文档 ID 出现在候选或上下文
生成与工具 低信任文档不得升级为指令;工具执行点独立授权 恶意文档诱导越权查询或外发
权限变化 实时失效、ACL 同步、缓存治理 撤权后仍能召回或按 ID 读取
删除与审计 索引/缓存/派生数据清理、可追溯日志 删除后仍有可访问正文,缺少访问证据

最小验证集:准备租户 A/B、普通员工/HR 三类身份、公开/HR/跨租户三类文档;分别测试正常召回、越权请求、恶意文档、撤权后即时重查和缓存重查。每个测试至少记录 actor、tenant、doc_id、chunk_id、权限版本、实际结果、判定依据。

8. 核心结论

RAG 的技术核心是把文档转换为可检索的、带来源和元数据的知识片段,而不是简单地“把 PDF 转成向量”。其效果高度依赖文档解析、合理切片、混合检索与重排序。

RAG 的安全核心则是:知识内容可以不可信,检索相关性不等于访问权;必须在可信服务中完成身份鉴别、授权判断和派生数据生命周期治理。 多租户不必强制每租户一套物理知识库,但无论共享索引还是独立实例,都不能省略文档级权限校验和撤权验证。

posted @ 2026-10-26 16:28  Momoko-X  阅读(18)  评论(0)    收藏  举报