
摘要:企业 RAG 不加权限,答得越准越危险。
1. 为什么这个话题值得单独写
很多 AI 应用的第一版都很快:接模型、写 Prompt、加接口、前端页面能问答,Demo 就算完成。可一旦放到真实业务里,问题会立刻变复杂。用户不会只问概念题,他们会把真实任务丢给系统:让它查资料、看日志、读告警、调用接口、生成建议,甚至希望它自动完成一部分操作。
不同部门、项目、租户的文档进入同一套向量库,如果检索时不带权限过滤,用户可能问到自己无权查看的资料。更麻烦的是,模型回答后如果没有引用溯源,连越权来源都查不出来。
这类问题单靠“换一个更强模型”解决不了。模型能力决定上限,但工程边界决定系统能不能上线。Java 后端原本就要处理权限、审计、日志、事务、并发、限流、降级和数据隔离。AI 接进来以后,这些能力不会消失,反而更重要。因为大模型不是普通函数,它可能输出不稳定,可能把资料理解错,也可能把用户一句模糊请求扩展成真实动作。
所以这篇文章的重点不是追新词,而是回答一个更实际的问题:RAG 知识库要不要加权限多租户、文档隔离、引用溯源一次讲清 这件事放进一个 Spring Boot 或企业后端系统里,到底应该怎么设计?
2. 一句话先讲清楚
企业 RAG 不加权限,答得越准越危险。
如果用工程语言翻译,就是下面这张表:
把 AI 能力看成“后端链路里的一环”,很多问题就清楚了。模型可以参与决策,但不应该成为唯一边界;模型可以生成建议,但系统必须决定能不能执行;模型可以组织答案,但后端要校验格式、权限和风险。
3. 真实业务场景拆解
拿企业内部系统举例,用户的真实问题通常不是“请解释一下概念”,而是这种带上下文、带业务后果的问题:
这个告警为什么触发? 这段日志看起来哪里异常? 这份知识库资料和当前现象是否匹配? 能不能帮我生成下一步排查步骤? 这个操作是否需要人工确认? 如果资料不足,系统应该直接回答还是追问?
如果后端没有边界,模型很容易给出“看起来完整”的回答。但完整不等于可靠。真正的系统至少要回答这几个问题:
这也是我建议你写这类文章时多放“真实场景”的原因。概念文章很多,但能把概念放进工单、告警、知识库、Dify、Spring Boot 调用链里拆的人不多。
4. 架构上应该怎么分层
一个最小但能上线的设计,不要让 Controller 直接调用模型。建议至少拆成下面几层:
mermaid flowchart TD A[Controller/API] --> B[Application Service] B --> C[AI Gateway] C --> D[Context Builder] C --> E[Policy Guard] C --> F[Model Client] C --> G[Tool/RAG Adapter] D --> H[Prompt + Context] E --> I[权限/限流/审批] F --> J[模型响应] G --> K[外部资料或工具结果] J --> L[Parser + Validator] K --> L L --> M[业务结果]
这张图的核心不是多加几层,而是把职责拆清楚:
这个拆法很适合 Java 后端,因为它和我们熟悉的网关、服务层、适配器、校验器很接近。
5. Java 后端最小建模方式
可以先从请求对象开始:
java public record RetrievalScope( String requestId, String userId, String question, String scene, Map<String, Object> context ) {}
响应不要只放一个字符串。至少要带状态、风险、引用和错误码:
java public record AiResult( boolean success, String answer, String riskLevel, List<String> citations, String errorCode ) {}
如果涉及工具调用、RAG 或 Agent 步骤,还要记录过程:
java public record AiTraceStep( String requestId, int stepIndex, String stepName, String inputSummary, String outputSummary, long latencyMs ) {}
核心调用可以保持很简单:
java public AiResult handle(RetrievalScope request) { policyGuard.check(request.userId(), request.scene()); String context = contextBuilder.build(request); String raw = modelClient.call(context); AiResult result = outputParser.parse(raw); return validator.validate(result); }
这段代码没有复杂框架,但它把几件事固定住了:权限先于模型,Prompt 集中组装,输出必须解析,结果必须校验。
6. 正确做法和错误做法对比

这里最关键的是:不要把 Prompt 当成安全边界。Prompt 可以提醒模型,但不能代替权限系统、参数校验、风险策略和审计日志。凡是涉及数据读取、工具执行、生产动作、成本消耗的地方,都要回到后端代码里判断。
7. 关键流程图
这类能力的请求链路可以简化成下面这样:
`mermaid flowchart LR S1[文档入库打标签] S2[建立 ACL] S1 --> S2 S3[用户请求带身份] S2 --> S3 S4[检索前过滤] S3 --> S4 S5[返回带引用] S4 --> S5 S6[记录 trace] S5 --> S6
`
这条链路里,每一步都应该留下最小日志。日志不是为了好看,而是为了出错后能回答三个问题:模型当时看到了什么?它为什么这样输出?下一次怎么避免?
建议日志字段至少包含:
8. 上线前检查清单
发布前可以直接按这个清单过一遍:
是否多租户隔离 是否按文档授权 是否有引用溯源 是否能审计召回 是否有 requestId 和完整调用日志 是否记录模型、Prompt 版本和上下文来源 是否设置超时、重试、限流和熔断 是否支持降级或人工接管 是否有固定评测样本做回归
这些检查项看起来普通,但它们决定 AI 应用是 Demo 还是生产系统。
9. 可以继续扩展的方向
如果第一版已经跑通,后续可以继续补这些能力:
不要一开始就做大平台。第一版先把主链路、日志、权限、校验跑通,再逐步补齐。
深度实战补充:把 RAG 权限和多租户 放进真实项目里
上面讲的是主链路,但真正写项目时,最容易出问题的往往不是第一天的接入,而是第二周、第三周开始出现的边界问题。不同部门、租户、项目的文档进入同一套向量库,如果检索前不做权限过滤,模型可能引用用户无权查看的资料。 这类场景看起来像一个 AI 功能,其实拆开以后至少包含用户身份、业务参数、上下文来源、模型调用、后端校验、日志审计和人工兜底几个环节。
我建议把它当成一个普通后端能力来做,而不是当成一段 Prompt。普通后端能力意味着:输入要校验,权限要判断,过程要留痕,失败要分类,输出要稳定,线上要能灰度。AI 只是其中一个处理节点,不应该绕过这些工程规则。
企业 RAG 不加权限,答得越准越危险。权限不能靠模型判断,必须在检索层和元数据层处理。 这也是很多 AI 项目 Demo 和生产差距最大的地方。Demo 只要看起来能答,生产系统要能解释为什么这么答、基于什么资料答、是否有权限答、失败后怎么恢复。尤其是企业内部系统,用户问的问题往往和业务数据、内部文档、生产操作有关,不能只看模型回答是否流畅。
可以直接落地的设计拆分
这个拆分并不复杂,但能避免所有逻辑堆在一个 sk() 方法里。很多项目后期难维护,就是因为一开始为了快,把 Prompt、RAG 检索、工具调用、日志、权限全写在同一个 Service 里。等需求一多,任何改动都会影响整条链路。
更贴近 Java 项目的代码组织
`java @RestController @RequestMapping(“/api/ai”) public class AiController { private final AiApplicationService aiApplicationService;
@PostMapping("/run")public AiResult run(@RequestBodyAiRequest request) {return aiApplicationService.run(request);}
} `
java @Service public class AiApplicationService { public AiResult run(AiRequest request) { policyGuard.check(request.userId(), request.scene()); AiContext context = contextBuilder.build(request); String raw = aiGateway.call(context); AiResult result = outputParser.parse(raw); return resultValidator.validate(result, context); } }
这段代码没有炫技,但边界是清楚的。以后要替换模型,只改 iGateway;要调整上下文,只改 contextBuilder;要加强安全,只改 policyGuard;要排查线上问题,就查 requestId 对应的 trace。
最容易被忽略的几个字段
如果只能先做一件事,我会先做日志和 trace。没有 trace,任何 AI 问题最后都会变成“感觉模型不稳定”。有 trace,至少能判断问题发生在输入、检索、工具、模型、解析还是后处理。
结合 CSDN 文章写法的建议
这篇文章发布时,不要只把概念讲完,可以加一个“我在后端项目里会怎么拆”的小节。读者真正关心的不是名词定义,而是自己项目遇到类似问题时该怎么动手。你可以把 tenantId、ACL、metadata filter、citation trace 这些点做成一张表,再配一张架构图,文章可读性会比纯文字强很多。
另外,代码不要堆太多完整工程。CSDN 文章里最合适的是小而完整的片段:一个请求对象、一个 service 方法、一个日志字段表、一个上线检查清单。读者看完能记住结构,而不是被大量无关代码淹没。
再补一个真实排查视角:上线后怎么判断它有没有做好
很多文章写到架构图就结束了,但真实项目上线后,最需要的是一套排查方法。判断 RAG 权限和多租户 有没有做好,不是看 Demo 回答是否顺滑,而是看它在异常情况下是否还能被定位和控制。
RAG 权限文章一定要讲“答对也是事故”。如果用户无权看某份文档,模型基于它回答得再准确,也是越权泄露。
我一般会从四个角度检查。
第一,看输入是否干净。用户输入里有没有缺少必要参数?有没有超长文本?有没有明显越权意图?有没有把上一轮上下文误带进这一轮?如果输入阶段不处理,后面模型回答再漂亮也可能是建立在错误前提上。
第二,看上下文是否可追踪。凡是进入模型的资料、历史、工具返回,都应该能在日志里找到来源。尤其是 RAG 和工具调用场景,必须能看到 docId、chunkId、toolName、toolArgs、toolResultSummary。否则用户问“你为什么这么说”,系统只能回答不出来。
第三,看输出是否可执行。AI 返回一段自然语言不等于任务完成。后端要判断它是否满足格式要求,是否包含必要字段,是否引用了资料,是否触发高风险规则,是否需要人工确认。如果要进入业务流程,最好先转成结构化结果,再由业务代码继续处理。
第四,看失败是否可恢复。模型超时怎么办?知识库没召回怎么办?工具返回空怎么办?JSON 解析失败怎么办?用户权限不足怎么办?这些失败都不应该用一个“系统异常”糊过去,而应该有明确错误码和降级方案。
10. 总结
企业 RAG 不加权限,答得越准越危险。
真正能落地的 AI 应用,最后一定会回到工程问题:输入是否可信,过程是否可观测,输出是否可校验,失败是否可降级,风险是否可控制。
夜雨聆风