施工企业做制度文档问答难点不在“能不能问答”而在“能不能管住权限、分清版本、保证答的是现行有效内容”。本文按模块拆解一套可落地的实现思路。一、制度文档问答的技术难点施工企业的制度文档有几个鲜明特点文档数量多、版本更新频繁、权限边界严格、格式不统一。由此带来三个核心问题权限问题不同分公司、不同岗位能看的制度不同问答系统不能越权返回版本问题同一制度可能有多个历史版本必须只召回现行有效版本准确性问题制度条款表述严谨切片一旦丢失上下文容易答偏。这三个问题决定了系统不能只是文档切片 向量检索这么简单需要在切片、权限、版本、召回几个环节分别设计。整体架构可以概括为下面这条链路制度文档入库结构化切片与清洗写入元数据权限/版本/状态向量库索引用户提问构造权限与状态过滤条件语义召回 关键词补充重排与出处校验生成带出处的答案置信度低则提示人工核实二、文档切片与清洗制度文档通常是结构化的按“章—条—款”组织切片应当尊重这种结构而不是按固定长度硬切。推荐的做法以“条”为最小切片单位保留所属章、制度名称作为上下文元数据每个切片附带结构化字段doc_id、chapter、article_no、version、effective_date、status、dept_scope清洗时统一格式去除页眉页脚、修订痕迹、失效批注。一个切片的元数据示例{doc_id:REG-0021,title:项目成本管理办法,article_no:第13条,version:2026-03,effective_date:2026-03-01,status:active,dept_scope:[all]}按条款切片的好处是每条回答都能精确定位到“哪个制度、哪一条、哪个版本”天然带出处。切片流程可以进一步细化为原始制度文档去除页眉页脚/修订痕迹按章—条—款解析以条为最小切片附加 doc_id/article_no/version 等元数据写入向量库三种常见切片方案各有取舍横向对比如下对比维度固定长度切片按章切片按条切片上下文完整性较差容易在条款中间截断语义被割裂较好整章内容完整但单块偏大、噪声多较好以“条”为完整语义单元配合章名元数据可补足上下文出处精度低只能定位到文档级难以精确到条款中可定位到章但章内条款仍需二次定位高可精确定位到“哪个制度、哪一条、哪个版本”实现成本低按字符数或 token 数切分即可无需解析文档结构中需识别章标题层级对格式不规范的文档要做兼容较高需解析“章—条—款”结构并抽取条款号、版本等元数据适用场景结构松散、无固定层级的通用文档或快速验证原型以章为单位阅读、问题粒度较粗的场景制度、法规、合同等强结构化且要求可溯源的问答场景综合来看制度文档问答更适合以“按条切片”为主必要时用“按章切片”兜底固定长度切片只作为兜底或冷启动方案。三、权限模型设计权限要在检索阶段就过滤而不是检索完再筛否则既越权又浪费算力。常见的做法是把权限信息写进元数据在召回时作为过滤条件。权限维度过滤字段匹配方式组织范围org_scope命中用户所属分公司或 all岗位范围role_scope命中用户岗位或 all密级security_level用户密级 ≥ 文档密级文件状态status仅 active检索时先根据当前用户的组织、岗位、密级构造过滤条件再在符合权限的切片集合里做语义召回。这样能保证答案只会从用户本就有权看的内容里产生。权限过滤与召回的关系如下否是用户身份组织/岗位/密级构造过滤条件切片是否满足权限直接排除不参与召回进入语义召回候选集返回答案把上面的过滤逻辑落到代码里核心就是根据当前用户身份拼出一个向量库可用的 filter 条件。下面用 Python 伪代码演示以 Chroma / Milvus 这类支持元数据过滤的向量库为例写法做了简化defbuild_permission_filter(user): 根据当前用户身份构造向量库检索的 filter 条件。 user 结构示例 { org: 华东分公司, # 用户所属组织 role: 项目经理, # 用户岗位 security_level: 2, # 用户密级数值越大权限越高 } conditions[]# 1. 组织范围切片允许的组织里包含用户所属分公司或标记为 all全公司通用# 作用防止跨分公司越权比如华东的员工看不到华南的专项制度conditions.append({org_scope:{$in:[user[org],all]}})# 2. 岗位范围切片允许的岗位里包含用户岗位或标记为 all不限岗位# 作用区分管理层与执行层的可见范围如薪酬制度仅对 HR 与管理者开放conditions.append({role_scope:{$in:[user[role],all]}})# 3. 密级文档密级不得高于用户密级用户密级 文档密级# 作用控制涉密制度的可见性低密级用户无法召回高密级内容conditions.append({security_level:{$lte:user[security_level]}})# 4. 文件状态只召回现行有效版本# 作用避免把已归档或草稿版本当作有效制度返回保证答的是现行内容conditions.append({status:{$eq:active}})# 多个条件之间是 AND 关系必须同时满足才进入召回候选集return{$and:conditions}# 使用示例先构造过滤条件再在满足权限的切片集合里做语义召回user{org:华东分公司,role:项目经理,security_level:2}wherebuild_permission_filter(user)resultsvector_store.query(query_embeddings[query_vector],# 用户问题的向量wherewhere,# 权限与状态过滤条件top_k10# 候选切片数量)这样写的好处是权限判断完全下沉到检索层召回结果天然只包含用户有权查看且现行有效的条款后续重排和生成阶段无需再做二次过滤。如果系统承载在协同办公平台上还可以直接继承平台的组织架构和权限体系避免单独维护一套账号权限权限变更也能自动同步。四、多版本管理制度会修订旧版本不能一删了之有时还要追溯“当时按哪版执行”但日常问答必须只答现行版本。实现上可以这样设计同一制度用稳定的doc_id关联所有版本每个版本有独立的version和effective_date用status标识active现行、archived归档、draft草稿向量库默认只对active切片建立可检索索引归档版本默认不参与召回需要追溯历史时再走专门的历史版本查询入口。版本生效时把旧版本批量置为archived、新版本置为active是一次原子化的状态切换避免出现新旧版本同时被召回的情况。版本状态切换可以表示为审核通过并生效新版本生效draftactivearchived五、召回与重排在前面几个模块的基础上召回链路可以这样组织用用户信息构造权限与状态过滤条件在过滤后的切片集合里做向量召回取候选若干条结合关键词匹配制度名称、条款号做补充避免专有词召回不准重排时优先保留条款完整、出处明确、版本最新的切片生成答案时附上制度名称、条款号和版本作为出处。召回与重排的完整链路是否用户提问权限与状态过滤向量召回候选切片关键词补充召回重排条款完整/出处明确/版本最新置信度是否足够生成答案并附出处提示请人工核实对于无依据或检索置信度低的问题系统应明确提示“请人工核实”而不是强行拼凑答案。这一条在制度问答里尤其重要因为错误的制度解释可能直接误导执行。本文为技术科普