id, title, type, domain, stack, tags, level, prerequisites, est_hours, related, week
| id |
title |
type |
domain |
stack |
tags |
level |
prerequisites |
est_hours |
related |
week |
| ai.rag.scenario.permission-aware-kb |
带权限的企业知识库问答:不同部门看到不同内容 |
scenario |
ai |
| rag |
| vector-db |
| elasticsearch |
| fastapi |
|
| 企业知识库 |
| 权限过滤 |
| 文档解析 |
| 混合检索 |
| 重排 |
| 拒答 |
| 增量更新 |
|
advanced |
|
3 |
| ai.rag.interview |
| ai.vector-db.scenario.multi-tenant-index |
| backend.elasticsearch.index |
|
|
带权限的企业知识库问答:不同部门看到不同内容
业务背景与问题
公司把员工手册、IT 指南、财务制度、各部门内部文档都导入知识库,做一个“制度问答助手”。试运行时发现:
- 研发同事问“A 级调薪幅度多少”,助手根据 HR 内部的薪酬文档给出了答案——越权;
- PDF 里的表格(差旅标准)被解析成一串数字,问“一线城市住宿标准”答错;
- 问“报错 0x80070005 怎么办”,检索不到包含这个错误码的文档;
- 制度更新后,新旧两个版本都被检索到,答案自相矛盾;
- 知识库里没有的问题(股票期权),助手也一本正经地回答。
约束
- 权限以现有的组织架构(部门、角色)为准,文档有“全员 / 指定部门 / 指定角色”三种可见范围。
- 文档格式:PDF(含表格、扫描件)、Word、Confluence 类网页。
- 答案必须给出引用来源,方便员工核对原文。
- 回答延迟目标:首字 2 秒以内(流式)。
方案设计
- 权限在检索阶段过滤:每个块带
acl(可见的部门 / 角色列表),检索时作为过滤条件,无权限的内容根本不进入提示词。不要“先检索再让模型别说”。
- 文档解析:PDF 先转结构化文本,表格转成 Markdown 表格整体作为一个块;扫描件走 OCR;去掉页眉页脚。解析结果抽样人工检查。
- 混合检索:向量检索负责语义,Elasticsearch(IK 等中文分词)负责错误码、编号等精确词;RRF 融合后用重排模型取前 5。
- 版本和增量更新:块带
doc_id 和 version;文档更新时按 doc_id 删除旧块再写入新块(或写入新版本后切换),避免新旧共存。
- 拒答:重排后最高分低于阈值直接拒答,给出“提交工单 / 联系 HR”入口。
- 评测和回归:评测集包含有权限 / 无权限 / 无答案 / 精确词 / 表格类问题,每次改动跑一遍。
关键代码
权限过滤和拒答的最小实现(完整代码 examples/mini-rag/mini_rag.py):
示例里验证了:HR 部门问调薪,命中薪酬制度;研发部门问同一个问题,薪酬制度不会出现在候选中(结果为空 → 拒答);问知识库中没有的“股票期权”→ 拒答。
真实向量库的过滤写法(以 Chroma 为例,where 条件;其他向量库语法不同,以官方文档为准):
取舍
| 选择 |
优点 |
缺点 |
| 检索时按 acl 过滤(本方案) |
安全,无权限内容不会进入模型 |
权限变化时要更新块的 acl |
| 按部门分别建索引 |
隔离彻底 |
跨部门文档要重复存储;部门多时管理困难 |
| 检索后再过滤 |
实现简单 |
top-k 被无权限内容占满后,有权限的内容反而召回不到 |
| 只靠提示词让模型不说 |
—— |
不可接受,模型可能泄露 |
| 向量库 + ES 两套存储 |
混合检索效果好 |
两边数据同步、一致性要处理 |
| 只用支持混合检索的单一引擎 |
运维简单 |
依赖具体产品的能力(ES、部分向量库已支持向量 + 关键词),以官方文档为准 |
易错点
- 权限只在前端或网关判断,检索层不过滤。
- 先取 top-5 再过滤权限:结果可能被过滤成空,实际上还有相关的有权限内容。先过滤再取 top-k。
- 用户换部门后缓存的答案仍可见:缓存 key 要包含权限维度,或不缓存敏感问答。
- 表格被拆成多块:一行数据和表头分离,数字失去含义。
- 文档删除 / 下线后向量库里还有残留。
- 日志里记录了完整的提示词(包含敏感文档内容),日志本身成为泄露渠道。
面试怎么讲
“企业知识库最大的问题是权限。我在每个块上带了 acl 元数据,检索阶段就过滤,无权限的内容不会进入提示词,而不是靠提示词让模型别说;检索用向量加 ES 的混合检索再重排,解决错误码这类精确查询;文档解析时把表格转成 Markdown 整体入库;文档按 doc_id 和版本增量更新;最高分低于阈值就拒答。评测集专门包含无权限和无答案的问题,每次改动都跑回归。”