Java 知识库检索验收:权限、版本与删除回放
知识库返回了“正确格式”的文本,不代表引用来自当前用户有权访问的最新文档。这里把检索前的过滤单独拿出来验证:先确定租户和文档最新状态,再检查删除标记与角色,最后检索。
在自己电脑上运行
解压后,在文件所在目录执行:
java --version
java --source 21 RagEvidenceLab.java results.json需要 JDK 21 或更新版本,不需要 Maven、第三方 Java 包和模型账号。results.json 是你这次运行的实际输出;下面的结果来自本站构建时执行的同一份源码。
看清对照实现漏了什么
语料包含 A、B 两个租户的年假规则、HR 限定文档、一份带删除标记的 VPN 文档和普通工单说明,全部是教学合成数据。
对照实现直接在全部文档和版本中按词项查找,遇到相同分数取前一条。它可能返回 A 的旧年假规则,也可能把 HR 文档放入普通员工的上下文。
修正实现分成三个独立步骤:
测试身份的租户
→ 按文档ID选择最新版本(保留删除状态)
→ 排除已删除、无权访问的文档
→ 词项匹配与原文摘录
→ 保存答案、引用来源和上下文文档ID顺序很重要:如果先排除已删除的记录,再找最新版本,就可能重新选中已经被删除的旧版;如果先排除当前角色不可见的版本,也可能回退到旧的公开版本。
这次实际运行的结果
本次 Java 运行:21.0.12;合成场景 7 项。缺少过滤的对照实现通过 3 项,修正实现通过 7 项。
这些是下面七个固定场景的回放结果,用于检查代码行为,不表示真实 RAG 的准确率。
| 用例 | 检查内容 | 对照来源 | 修正来源 | 修正结果 |
|---|---|---|---|---|
| C01 | 当前文档版本 | A/leave/v1 | A/leave/v2 | 通过 |
| C02 | 租户隔离 | A/leave/v1 | B/leave/v1 | 通过 |
| C03 | 普通员工不能检索HR资料 | A/salary/v1 | NONE | 通过 |
| C04 | 删除标记覆盖旧文档 | A/vpn/v1 | NONE | 通过 |
| C05 | 没有证据时停止 | NONE | NONE | 通过 |
| C06 | 授权HR可检索HR资料 | A/salary/v1 | A/salary/v1 | 通过 |
| C07 | 普通工单查询 | A/ticket/v1 | A/ticket/v1 | 通过 |
JSON 中保留运行时间、Java 版本、源码 SHA-256,以及每题的查询、身份、期望引用、对照结果和修正结果。可以用源码包复跑,对照自己的结果。
选一个失败场景追到代码
C03 使用普通员工身份查询“薪酬”。对照实现能找到 A/salary/v1,说明仅在回答之后隐藏文本已经太晚:敏感片段先进入了上下文。
修正实现的 currentVisibleDocs 在检索之前排除无权限文档,C03 得到 NONE 和“没有可用证据”。程序不仅比对最终答案,也逐一检查进入上下文的文档是否属于当前可见集合。
接下来怎样扩展
- 新增一个“公开文档改为 HR 限定”的版本,验证不会回退到旧公开版。
- 把演示身份改为服务端认证后的身份,阻止客户端自行选择角色和租户。
- 接入向量库时核对过滤是否真的生效,再加入无答案、错引用、模型超时与提示注入用例。
当前匹配器采用确定性词项匹配,答案是原文摘录;它没有向量检索、模型生成、真正的身份认证和线上负载。实验用于检查检索边界,不能代表完整 RAG 的质量。
需要按同样口径记录自己的项目,可以使用验收表填写样例和空白资料。
