ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

施工企业制度文档问答:权限与多版本管理的实现

施工企业制度文档问答:权限与多版本管理的实现

施工企业做制度文档问答,难点不在“能不能问答”,而在“能不能管住权限、分清版本、保证答的是现行有效内容”。本文按模块拆解一套可落地的实现思路。

一、制度文档问答的技术难点

施工企业的制度文档有几个鲜明特点:文档数量多、版本更新频繁、权限边界严格、格式不统一。

由此带来三个核心问题:

  1. 权限问题:不同分公司、不同岗位能看的制度不同,问答系统不能越权返回;
  2. 版本问题:同一制度可能有多个历史版本,必须只召回现行有效版本;
  3. 准确性问题:制度条款表述严谨,切片一旦丢失上下文,容易答偏。

这三个问题决定了系统不能只是"文档切片 + 向量检索"这么简单,需要在切片、权限、版本、召回几个环节分别设计。

整体架构可以概括为下面这条链路:

制度文档入库

结构化切片与清洗

写入元数据(权限/版本/状态)

向量库索引

用户提问

构造权限与状态过滤条件

语义召回 + 关键词补充

重排与出处校验

生成带出处的答案

置信度低则提示人工核实

二、文档切片与清洗

制度文档通常是结构化的,按“章—条—款”组织,切片应当尊重这种结构,而不是按固定长度硬切。

推荐的做法:

  • 以“条”为最小切片单位,保留所属章、制度名称作为上下文元数据;
  • 每个切片附带结构化字段: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}where=build_permission_filter(user)results=vector_store.query(query_embeddings=[query_vector],# 用户问题的向量where=where,# 权限与状态过滤条件top_k=10# 候选切片数量)

这样写的好处是:权限判断完全下沉到检索层,召回结果天然只包含用户有权查看且现行有效的条款,后续重排和生成阶段无需再做二次过滤。

如果系统承载在协同办公平台上,还可以直接继承平台的组织架构和权限体系,避免单独维护一套账号权限,权限变更也能自动同步。

四、多版本管理

制度会修订,旧版本不能一删了之,有时还要追溯“当时按哪版执行”,但日常问答必须只答现行版本。

实现上可以这样设计:

  • 同一制度用稳定的doc_id关联所有版本,每个版本有独立的version和effective_date;
  • 用status标识active(现行)、archived(归档)、draft(草稿);
  • 向量库默认只对active切片建立可检索索引,归档版本默认不参与召回;
  • 需要追溯历史时,再走专门的历史版本查询入口。

版本生效时,把旧版本批量置为archived、新版本置为active,是一次原子化的状态切换,避免出现新旧版本同时被召回的情况。

版本状态切换可以表示为:

审核通过并生效

新版本生效

draft

active

archived

五、召回与重排

在前面几个模块的基础上,召回链路可以这样组织:

  1. 用用户信息构造权限与状态过滤条件;
  2. 在过滤后的切片集合里做向量召回,取候选若干条;
  3. 结合关键词匹配(制度名称、条款号)做补充,避免专有词召回不准;
  4. 重排时优先保留条款完整、出处明确、版本最新的切片;
  5. 生成答案时附上制度名称、条款号和版本,作为出处。

召回与重排的完整链路:

是

否

用户提问

权限与状态过滤

向量召回候选切片

关键词补充召回

重排:条款完整/出处明确/版本最新

置信度是否足够

生成答案并附出处

提示请人工核实

对于无依据或检索置信度低的问题,系统应明确提示“请人工核实”,而不是强行拼凑答案。这一条在制度问答里尤其重要,因为错误的制度解释可能直接误导执行。

本文为技术科普

返回列表