BISHENG 知识空间 AI 问答检索权限过滤(F029):双层 view_file 过滤架构与落地实现
BISHENG 知识空间 AI 问答检索权限过滤F029双层 view_file 过滤架构与落地实现【免费下载链接】bishengBISHENG is an open LLM devops platform for next generation Enterprise AI applications. Powerful and comprehensive features include: GenAI workflow, RAG, Agent, Unified model management, Evaluation, SFT, Dataset Management, Enterprise-level System Management, Observability and more.项目地址: https://gitcode.com/GitHub_Trending/bi/bisheng导读本文围绕 BISHENG v2.6.0 特性F029-knowledge-qa-permission-filter知识空间 AI 问答 - 检索权限过滤展开讲解其如何解决列表 UI 看不到的文件却能被 AI 问答检索到这一越权读取风险。文中以 spec.md 与 tasks.md 为骨架结合仓库真实源码完整呈现双层过滤架构AD-01/02/03/08、KnowledgeFileVisibilityService的实现细节、可配置参数、四大问答入口整空间 / 文件夹 / 文件预览 / 首页与工作台多 KB与角标溯源接口的改造以及 Test-First 测试策略与 E2E 回归清单。读完本文你将掌握 BISHENG 如何在不新增 OpenFGA 关系、不新增数据库表的前提下用索引层粗滤 结果层精滤保证 AI 问答可见性与列表 UI 可见性严格一致。1. 背景AI 问答为什么成为越权读取的入口知识空间内用户可能对某个空间有view_space权限但只对其中部分文件有view_file权限。改造前知识空间 AI 问答的检索链路KnowledgeSpaceChatService、工作台WorkStationService.queryChunksFromDB只做空间级鉴权检索召回出的 chunk 没有按文件级权限过滤导致普通用户在空间页发起问答回答引用的文件名、来源、预览链接可能暴露无权文件历史会话的角标溯源citation resolve接口在用户失去view_file后仍返回结构化字段构成新的越权读取路径首页 / 工作台多 KB 检索以kb_id_whitelistcheck_authFalse跳过 per-KB 鉴权可被构造请求绕过下拉框。该特性被定义为P0 优先级必须在 v2.6.0 关闭这条越权路径。1.1 范围边界本期纳入 / 排除本期纳入知识空间 AI 助手的 4 个问答入口整空间 / 文件夹 / 文件预览 / 首页 工作台多 KB 检索 新版角标溯源接口POST /api/v1/citations/resolve批量、GET /api/v1/citations/{citation_id}单条。本期明确排除工作流KNOWLEDGE_RETRIEVER节点workflow/nodes/knowledge_retriever/——涉及流程节点执行上下文中的运行用户身份问题留待后续 feature对外 RPC/api/v2/filelib/retrieve——当前以默认 operator身份运行而非真实终端用户需先定义代用户检索协议OpenFGA 模型变更——不引入新的view_fileReBAC 关系复用现有can_read与view_filepermission_idchunk 元数据 ACL 索引化超大规模方案——单空间单用户可见文件 10 万时所需的索引层 ACL 字段方案不在本期本期通过双层过滤 检索次数封顶在 10 万规模内提供可接受性能。2. 核心设计双层过滤架构AD-01 / AD-02 / AD-03 / AD-082.1 语义对齐基线AD-01为什么不能只用单一权限架构决策 AD-01 在三个选项中选择了双层过滤选 C方案问题A仅用 ReBACcan_read会导致列表看不到但问答能查到越权B仅用 fine-grainedview_file10 万规模冷启动需要对每个文件单独 OpenFGA tuple 读取单空间一次性解析耗时不可接受C双层选can_read在 Milvus/ES 端把候选缩到至少有 ReBAC 读权限的文件一次list_objects Redis 缓存再在召回结果的 unique file_id一般规模 ≤ 30 个上跑 fine-grainedview_file解析保证最终送进 LLM 的 chunks必然满足列表 UI 可见性这一设计的目标不变量INV-7登记在 release-contract.md 表 2知识空间内容的AI 问答可检索可见性必须是列表 UI 可见性的子集即对任意(user, space, file)若用户在列表 UI 中不可见该fileview_file ∉ effective_permissions则任何 AI 问答入口都不得让该file的 chunk / 文件名 / 来源出现在模型上下文、回答引用、角标溯源/api/v1/citations/resolve响应的结构化字段中。2.2 索引层过滤策略AD-02自适应 IN / NOT-IN / 不过滤以可见集合大小K与空间内主版本文件总数N为决策依据K ≤ 5000→IN(可见集合)N − K ≤ 5000→NOT IN(排除集合)排除集合 非主版本 ∪ 不可见二者均 5000 → 不下推索引过滤仅靠扩大候选 结果层精滤。设计理由ESterms默认上限 65536Milvus 长表达式解析在 ≤ 5000 内表现稳定自适应让 95% 业务走快路径极端规模有兜底。阈值 5000 写为可配置常量KnowledgeQAFilterConf.index_filter_threshold。2.3 结果层扩展策略AD-03最多 2 次检索首轮按top_k × initial_multiplier默认 3召回若过滤后 top_k且首轮命中文件数 0进行至多 1 次扩张到top_k × expansion_multiplier仍不足则返回已有结果可少于top_k不存在凑齐 top_k 的无限扩张。该策略保证最坏情况下也只是 2 次 Milvus 2 次精滤批量调用单次问答额外延迟 ≤ 400ms可观测可控。2.4 结果层精滤并发与缓存AD-08复用列表 UI 已验证的_build_child_permission_context含tuple_cache 同一 semaphore 8 并发上限与_CHILD_PERMISSION_CHECK_CONCURRENCY默认一致空间维度的权限上下文在结果集少≤ 30 个 file_id时近乎一次性构建。3. 核心服务源码解析KnowledgeFileVisibilityService新增服务文件位于 knowledge_file_visibility_service.py集中可见文件集合的解析避免逻辑散落在 chat service 各处。它由 FastAPI 依赖工厂knowledge/api/dependencies.py 中的get_knowledge_file_visibility_service构造构造函数注入request: Request, login_user: UserPayload。3.1IndexFilter索引层过滤产物dataclass class IndexFilter: Index-layer filter to be injected into Milvus / ES search_kwargs. strategy: str # in | notin | none | empty milvus_expr: str | None None es_filter: list | None None accessible_size: int 0 excluded_ids: list[int] field(default_factorylist) property def is_empty(self) - bool: return self.strategy empty四种策略语义源码 docstring 明确定义in——document_id in [visible ids]适用于小可见集notin——document_id not in [excluded ids]适用于几乎全可见none—— 不过滤要么是 admin 调用者要么两侧规模都过大由结果层精滤兜底empty—— 用户在该空间可见文件数为 0调用方必须直接跳过检索。3.2is_space_visible(space_id) - boolAC-11non-throwing 版本复用KnowledgeSpaceService._require_permission_id(knowledge_space, space_id, view_space)的判定逻辑捕获SpacePermissionDeniedError错误码 18040复用不新增返回False。admin 用户由底层PermissionService短路返回True。该方法是首页 / 工作台多 KB 检索无view_space的 KB 静默跳过AC-11的判定来源。3.3build_index_prefilter(space_id, candidate_file_ids) - IndexFilterAD-02 策略决策的核心实现关键逻辑如下源码级调PermissionService.list_accessible_ids(user_id, can_read, knowledge_file, login_user)拿到用户租户级可读文件集admin 返回None拉取该空间主版本 file_id 集合排除非主版本复用version_repo.find_non_primary_file_ids_by_knowledge_ids计算交集K accessible_ids ∩ candidate (∩ space_files if candidateNone)按阈值选策略并返回IndexFilter。源码中一个值得注意的细节是业务范围的正确性优先candidate_file_ids文件夹 / tag 业务范围没有结果层兜底post_filter_visible_files只强制view_file因此只要传入了 candidate就必须下推到索引层不能走 admin 或两侧过大的none短路——大 IN 列表优于泄漏到范围之外。3.4post_filter_visible_files(space_id, file_ids) - Set[int]结果层精滤保证最终送 LLM 前必经admin → 返回输入集合短路空输入 → 在构建权限上下文前短路一次性_build_child_permission_context(space_id)拿共享 binding / tuple_cache / membership 上下文semaphorefine_grained_concurrency默认 8并发跑_get_child_item_effective_permission_ids保留view_file ∈ effective的 file_id。源码 docstring 特别强调委托调用应用了 per-item lineage walkfile → 祖先文件夹 → space、nearest_binding_winsTrue语义文件级 revoke 优先于空间成员默认、membership 默认权限与 public-space viewer 默认——若缺少这些参数早期版本会返回所有 binding 的并集让被 revoke 的文件泄漏过滤这正是用户报告的 bug。测试 test_knowledge_file_visibility_service.py 中的test_post_filter_visible_files_regression_revoke_overrides_membership即该回归场景的验证。4. 配置参数KnowledgeQAFilterConf配置块定义于 core/config/settings.py挂在Settings.knowledge_qa_filtersettings.py第 740 行顶层为可选块YAML 缺省时按默认值。class KnowledgeQAFilterConf(BaseModel): Knowledge space AI QA retrieval permission filter (F029). index_filter_threshold: int Field( default5000, ge1, descriptionAD-02 threshold. ...当可见或排除文件数 ≤ 该值走 IN / NOT-IN否则仅后过滤, ) retrieval_initial_multiplier: int Field( default3, ge1, descriptionAD-03 first attempt. 首轮召回 top_k * 该倍数, ) retrieval_expansion_multiplier: int Field( default6, ge1, descriptionAD-03 capped expansion. 不足 top_k 时单次重试召回 top_k * 该倍数不再扩张, ) fine_grained_concurrency: int Field( default8, ge1, le64, descriptionAD-08 concurrency. 结果层 view_file 解析的 semaphore 并发上限, ) model_validator(modeafter) def validate(self): if self.retrieval_expansion_multiplier self.retrieval_initial_multiplier: raise ValueError(retrieval_expansion_multiplier must be retrieval_initial_multiplier) return self参数速查表参数默认值约束作用关联决策index_filter_threshold5000 1索引层 IN / NOT-IN 切换阈值AD-02AC-23/24/25retrieval_initial_multiplier3 1首轮召回倍数AD-03retrieval_expansion_multiplier6 initial单次扩张召回倍数扩张后封顶AD-03AC-26fine_grained_concurrency81..64结果层精滤并发AD-08实现偏差提示spec.md 中retrieval_expansion_multiplier写的是默认 10而实际提交到源码的默认值是6。源码注释说明改为 6 是为了控制重试搜索成本base_k100 时 k600且 Milvus wrapper 会提高 ef 覆盖该 k 值。这也是 tasks.md「实际偏差记录」一节建议登记的内容。5. 四个问答入口的改造5.1 整空间 / 文件夹问答KnowledgeSpaceChatServiceknowledge_space_chat_service.py 的改造要点将_build_folder_search_kwargs拆为_compute_candidate_file_ids(knowledge_id, folder_id, tags)保留原 candidate 计算逻辑 调build_index_prefilter新增_retrieve_and_filter(space, query, candidate, max_content) - List[Document]对应 spec §7.4 五步流程chat_folder替换原milvus_kwargs/es_kwargs构造为_retrieve_and_filter调用space_rag将retriever_tool.ainvoke调用迁入_retrieve_and_filter移除原 retriever_tool 直接拼接逻辑保留 prompt LLM 调用chat_single_file在space_rag之前增加防御性post_filter_visible_files({file_id})一次已通过门禁的请求应必中不中则记 WARN 并返回空避免越权_render_rag_response从space_rag中抽出供chat_folder复用不变的 prompt 流式路径。_retrieve_and_filter的关键实现源码第 480-566 行先build_index_prefilter若index_filter.is_empty则直接返回空并写一条strategyempty的结构化日志对(initial_multiplier, expansion_multiplier)二元组循环每轮以base_k × multiplier构造 Milvus/ES search_kwargsbase_k100ef110注入milvus_expr/es_filter调用KnowledgeRetrieverTool.ainvoke(query)后抽 unique file_id走post_filter_visible_files得view_file子集过滤 chunks一旦某轮 survivors 非空立即 breakAD-03 封顶 2 次尝试每轮结束写一条结构化日志AC-27 字段。5.2 首页 / 工作台多 KB 检索WorkStationService.queryChunksFromDBworkstation_service.py 按 spec §7.2b 逐项落地Stage 1AC-11进入循环前对space_bucket的每个 kb_id 调is_space_visible(kb_id)不通过则continue INFO 日志skipped_kb_id%s reasonno_view_space源码第 1017-1031 行。该 KB 静默跳过、不抛错、不阻塞其他 KB、不出现在kb_succeed列表Stage 2索引层粗滤构造MultiRetriever的search_kwargs时注入build_index_prefilter(kb_id, None)的产物与chat_folder路径一致。不做显式预检测用户在该 KB 是否有可见文件——若accessible_ids与 KB 文件集交集为空Milvus / ES 查询自然返回 0 chunksAC-12Stage 3结果层精滤per_kb_tool.ainvoke返回后对kb_docs走post_filter_visible_files(kb_id, unique_file_ids)过滤后空则不进入finally_docs/ 不计入kb_succeed源码第 1085 行沿用 AD-03 检索循环上限首轮 ×3 / 扩张 ×10多 KB 间不互相补量org_bucketlegacyknowledge_library路径完全不改AC-14check_authFalse不动与本特性正交。5.3 角标溯源CitationResolveServicecitiy_resolve_service.py 的改造删除_has_file_access静态方法旧 RBACRoleAccessDaoAccessType.KNOWLEDGE空间级判定是 arch-guard RULE-8 VIOLATION及其对from bisheng.database.models.role_access import AccessType的导入新增_permitted_file_ids(items, login_user)login_user is None匿名返回None表示不过滤AC-20 保持现状否则按(knowledgeId, documentId)分组对每个 knowledgeId 调post_filter_visible_files扁平合并为允许集合_apply_tier_filterweb 类型 citation 永远通过AC-19per_userRAG citation 在文件不满足view_file时整条剔除sharedRAG citationtoggle-OFF 的知识空间来源保留、其整文件 URL 在 enrich 阶段再门控匿名时全保留resolve_citations批量先过滤再走原_enrich_item并发流程resolve_citation单条RAG 类型且无权 → 抛NotFoundErrorAC-18与citation 不存在语义一致web 类型不受影响_enrich_rag_item内旧的has_access login_user is None or ...整段删除——精滤已在上层完成进入这里的 item 必然通过view_file或匿名URL/bbox 无条件填充。5.4 不修改的端点明确排除knowledge/api/endpoints/qa.py/qa/chunk、/qa/keyword是历史角标溯源接口本期不动待后续统一下线open_endpoints/api/endpoints/filelib.py与citation.py的 v2 RPC默认 operator 身份本期不动AD-06workflow/nodes/knowledge_retriever/工作流节点检索路径AD-06。6. API 契约与错误码所有端点继续走UserPayload Depends(UserPayload.get_login_user)QA 端点新增依赖响应包装沿用UnifiedResponseModel[T]。无外部契约变化前端契约透明。MethodPath变更POST/api/v1/knowledge/space/{space_id}/chat/file/{file_id}内部新增结果层精滤防御性确认POST/api/v1/knowledge/space/{space_id}/chat/folder内部接入双层过滤folder_id0 即整空间POST工作台search_kb工具无独立 HTTP 端点queryChunksFromDB内部按view_file过滤无view_space的 KB 静默跳过POST/api/v1/citations/resolveService 内_has_file_access改造为文件级view_file精滤无权 citation 整条剔除GET/api/v1/citations/{citation_id}单条无权返回NotFoundErrorPOST/api/v1/qa/chunk/GET/api/v1/qa/keyword历史接口不修改待下线错误码表不新增错误码HTTP StatusCode场景关联 AC200body18040SpacePermissionDeniedError复用无view_space/view_folder/view_fileAC-01, AC-05, AC-08200body—有view_*但可见集合为空resolve 时 items 全被过滤AC-03, AC-12, AC-17200body现有NotFoundError码单条 citation 无view_file与citation 不存在语义一致AC-18请求 / 响应示例spec §6/citations/resolve部分 citation 无权AC-16 整条剔除请求POST /api/v1/citations/resolve { citationIds: [cit_A_visible, cit_B_invisible, cit_C_visible] }响应cit_B_invisible对应的文件用户无view_file整条不返回{ status_code: 200, status_message: SUCCESS, data: { items: [ { citationId: cit_A_visible, type: rag, sourcePayload: { knowledgeId: 5, knowledgeName: Q1 报告库, documentId: 1234, documentName: report-Q1.pdf, snippet: ..., previewUrl: ..., downloadUrl: ..., items: [{ itemId: ..., bbox: ... }] } }, { citationId: cit_C_visible, type: rag, sourcePayload: { ...: ... } } ] } }chat_folder流式响应source_documents[*].file_id必为当前用户view_file子集AD-01 结果层精滤保证可能为空数组AC-03 触发但模型仍按 prompt 给出回答。7. 验收标准AC全景7.1 整空间 / 文件夹 / 文件预览问答ID场景预期AC-01无view_space调整空间问答返回 18040不进入检索不写 RecallChunk不消耗 LLM 配额AC-02有view_space、部分文件有view_file检索仅命中可见的主版本文件source_documents[*].file_id是当前view_file子集AC-03有view_space但空间内无任何view_file文件空文档集模型按 prompt 回答如未找到相关内容HTTP 200 不报错AC-04问答后管理员收回部分view_file立即追问第二轮用最新权限缓存 TTL ≤ 10s 或invalidate_user已触发被收回文件不再进入上下文AC-05无view_folder调文件夹问答返回 18040不进入检索AC-06有view_folder检索范围 文件夹子树下可见主版本文件无view_folder的子文件夹分支被剔除与列表 UI 对齐AC-07view_foldertags过滤检索范围 子树可见集 ∩ tag 文件集交集为空按 AC-03 行为AC-08无view_file调单文件问答URL 直构造返回 18040不进入检索AC-09有view_file检索限定document_id file_id沿用version_filter行为与原有逻辑等价7.2 首页 / 工作台多 KBID场景预期AC-10拉取 KB 下拉框mine/managed/joined/department 4 端点本特性不改 4 端点行为现有服务层已按can_read membership 过滤E2E 回归验证AC-11某 KB 无view_space构造请求绕过下拉框静默跳过不抛错不阻塞不出现在kb_succeedINFO 日志skipped_kb_idX reasonno_view_spaceAC-12KB 有view_space但无任何view_file文件Stage 2/3 自然产出 0 docs不进入finally_docs/kb_succeed日志输出 AC-27 字段AC-13KB 内部分可见每 KB 走双层过滤跨 KB 合并按max_total_docs100截断不变AC-14选择org_bucketlegacyknowledge_library不修改org_bucket路径行为变更历史登记差异7.3 角标溯源ID场景预期AC-15所有 RAG 文件均满足view_fileitems结构与现状一致downloadUrl/previewUrl/bbox照常填充AC-16部分 RAG citation 已无view_file整条剔除无权 citationdocumentName / knowledgeId / snippet / chunk 文本均不返回web 类型不受影响AC-17全部无权items返回空数组[]HTTP 200AC-18单条 RAG citation 无权返回NotFoundError不返回任何文件元数据AC-19web类型 citation本期不修改_enrich_web_item行为AC-20匿名调用方share linklogin_user is None保持现状不引入新鉴权7.4 实时性 / 性能 / 可观测ID场景预期AC-21管理员 authorize / revoke同步触发PermissionCache.invalidate_user(user_id)下一轮问答即用新权限AC-22缓存未及时失效TTL 上限 10s最迟 10s 内自动收敛AC-23≤ 5000 可见文件、热缓存权限过滤新增耗时 ≤ 80ms不含 LLM / Milvus / ESAC-24≤ 5000 可见文件、冷缓存OpenFGA list_objects新增耗时 ≤ 500msAC-25≤ 100000 可见文件、热缓存新增耗时 ≤ 200ms走 NOT-IN 或后过滤路径AC-26任意场景检索循环次数 ≤ 2不存在无限扩张AC-27任意场景结构化日志含strategyin\|notin\|postfilter、accessible_ids_size、prefilter_candidate_size、retrieval_attempts、post_filter_dropped_count8. Test-First 测试策略与测试覆盖tasks.md 采用后端 Test-First务实版先写测试红再写实现绿。新测试统一放在test/module/之下复用 conftest.py 现有 fixturesmock_openfga、mock_redis、async_db_session、tenant_context等OpenFGA 通过mock_openfga桩Milvus / ES 不在单元测试中真起用 monkeypatch 替换 retriever 工具最外层ainvoke返回固定 docs。8.1 三个新增测试文件测试文件任务数量覆盖 ACtest_knowledge_file_visibility_service.pyT00217 testsAC-11 / AC-23 / AC-24 / AC-25 部分test_knowledge_space_chat_service_visibility.pyT0047 testsAC-01 ~ AC-09 / AC-26 / AC-27test_query_chunks_visibility.py新建test/workstation/目录T0068 tests4 主场景AC-11 ~ AC-14test_citation_resolve_visibility.py新建test/citation/目录T0089 tests7 主场景AC-15 ~ AC-208.2 关键测试场景示例test_build_index_prefilter_*系列K0 → strategyemptyK10 → strategyin 且milvus_exprdocument_id in [..]、es_filter含termsN−K ≤ 5000 → strategynotin两侧均 5000 → strategynoneadmin → strategynone传入 candidate 时 admin 仍受业务范围约束test_build_index_prefilter_admin_still_scopes_to_candidate大 candidate 永不下沉为 nonetest_build_index_prefilter_large_candidate_never_falls_to_none。test_post_filter_visible_files_*系列仅保留view_file ∈ effective的 file_idadmin 返回全部空输入短路50 个并发 file_id 验证 semaphore 限流不死锁回归用例验证revoke 覆盖 membership 默认。test_retrieve_and_filter_*系列empty策略直接跳过 retriever 调用首轮即满足 top_k精滤砍掉部分封顶 2 次尝试test_retrieve_and_filter_capped_at_two_attempts扩张第二轮成功用caplog验证permission_filter结构化字段齐全test_retrieve_and_filter_logs_structured_fields。test_chat_single_file_logs_view_file_passed_debug验证单文件问答通过门禁后的 DEBUG 日志。Citation 测试全可见原样返回含 URL/bbox部分不可见整条剔除web 不受影响全不可见 items 空数组单条无权抛NotFoundErrorweb 类型不走view_file匿名跳过精滤admin 短路。9. 前端改动仅 i18n 文案无组件 / 路由 / store后端变更对前端契约透明唯一需要联调的是无可见内容提示文案Platformpublic/locales/{en-US,zh-Hans,ja}/knowledge.json 补knowledge.qa.noVisibleContentClientsrc/locales/{en,zh-Hans,ja}/translation.json 补同名语义 key。三语文案语言文案中文未在你有权访问的内容中找到相关信息英文No relevant content found in resources accessible to you日文アクセス権限のあるリソースに該当する内容が見つかりませんでした不涉及新增组件、新增路由、新增 store。整空间 / 文件夹 / 单文件问答响应 schema 不变角标溯源面板items数组变短时按数组渲染无需特殊处理单条无权返回NotFoundError时前端复用现有该来源已不可访问提示。10. E2E 回归清单与性能验证tasks.md T012 定义的全链路回归场景e2e-report.md 模板待人工执行KB 下拉框回归AC-10以view_space不全的测试账号登录确认GET /api/v1/knowledge/space/{mine,managed,joined,department}仅返回有view_space的空间整空间问答AC-02 / AC-06部分文件可见账号触发问答截图source_documents仅含可见 file_id 的 chunk首页 / 工作台问答AC-11/12/13选 3 个 KB1 个无 view_space、1 个无可见 view_file、1 个有可见 file仅最后一个 KB 出现在回答 citation 列表角标溯源AC-15/16/17历史会话引用 N 个文件管理员收回一半文件的view_file重开会话展开 citation 面板确认无权 citation 整条不出现单条 citationAC-18直接GET /api/v1/citations/{无权 citation_id}返回NotFoundError匿名调用AC-20share link 公开访问触发 citation resolve行为不变实时失效AC-21/22关键场景账号 A 对 F1 有view_file→ 问答确认 F1 出现 → 管理员调PermissionService.revoke→ 10s 内追问验证 F1 消失grep 后端日志确认accessible_ids_size前后两轮变化证明list_accessible_ids已重算结构化日志AC-27grep 日志permission_filter行确认 5 个字段齐全性能 sanityAC-23/24单空间 5000 可见文件账号整空间问答warmup ≤ 80ms、冷启动 ≤ 500ms10 万规模AC-25环境不可达则在报告标注未验证 留待 stagingarch-guard 校验运行bash scripts/arch-guard.sh确认CitationResolveService的 RULE-8 VIOLATION 已消除。11. 实现偏差记录与后续演进tasks.md 末尾保留「实际偏差记录」章节实现完成后登记与 spec.md 的偏差。本文可确认的一处偏差是retrieval_expansion_multiplier默认值由 spec 的 10 调整为源码的 6为控制重试搜索成本且 Milvus wrapper 会提高 ef 覆盖。建议后续执行 E2E 时在报告中同步记录该调整对 AC-26 的影响。后续演进方向本期明确不支持详见 spec §3 边界情况工作流 KNOWLEDGE_RETRIEVER 节点的检索权限过滤需要先定义运行身份语义对外 RPC/api/v2/filelib/retrieve的代用户检索协议on_behalf_of_user_id或新鉴权方式单用户单空间 10 万可见文件的低延迟保证chunk 元数据 ACL group 字段方案/api/v1/qa/chunk与/api/v1/qa/keyword历史接口的统一下线匿名调用方 citations 接口的鉴权专项share-link 场景。相关文档特性规格spec.md任务拆分tasks.md版本契约与 INV-7release-contract.md权限体系参考10-permission-rbac.md描述 v2.5 之前旧 RBAC 模型仅作历史背景【免费下载链接】bishengBISHENG is an open LLM devops platform for next generation Enterprise AI applications. Powerful and comprehensive features include: GenAI workflow, RAG, Agent, Unified model management, Evaluation, SFT, Dataset Management, Enterprise-level System Management, Observability and more.项目地址: https://gitcode.com/GitHub_Trending/bi/bisheng创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考