摘要 法规知识库真正要回答的,不是“哪里提到了相关段落”,而是“给定一种情形,该用哪一条”。前者是找相关,后者是对号入座:一条条文对谁、在何时、何种情形下适用,全由一组条件决定,时间只是其中一种。本文考察一个开源 RAG 平台,确认它的数据模型只有“文档—分块—向量”,条文的身份、条件与治理状态都无处安放,检索也不接受时间这个条件。据此提出一种补偿设计:平台只承担语义召回,条文的身份、条件与治理在平台之外持有;条件能由程序判定的就判定,判不出的就标出来交人,不把未定之事当作已定。这条路不省总人力,换的是架构上的不侵入与单次核对的减负。设计最薄弱的环节仍是条文切分,它的错误形态沉默,内容比对无法发现,只能以条文身份为校验对象。所据为对该平台源码与接口的一次考察及小规模实践,样本有限,结论限于同类平台与同类文件。
关键词 法规知识库;检索增强生成;条件匹配;条文身份;人机分工
一、引言
1.1 问题的提出
把一套规定放进去、用人话问出来,看着是同一个动作,其实有两种要法。一种是找相关:问“关于这件事的规定有哪些”,要的是一堆相关的段落,允许模糊、允许多给。另一种是对号入座:问“这间厂排污超标该按哪条罚”,要的是唯一的一条,而且这一条当下有效。人资、环保、税务、市场监管、法律——凡是按规则办事的领域,要的都是第二种。
此处“唯一”指判定的确定性:每次查询给出的结果集一致,且其中每一条都有明确的适用依据,不指结果条数。竞合、层级并存、新旧法衔接时,结果集可能含多条,但每一条为什么在这里、为什么不适用别的条,都是确定的。
再往前一步,两种要法的分界有一条判据:当知识的基本单元是“给定一组条件,决定该适用哪些规范”时,找相关就不够。医疗诊断、财务审计、工程验收都是这个结构,法规只是其中一例;该用哪种数据模型,取决于单元的形状,与领域无关。
这两种要法落到系统上,是数据模型的差别,不是检索算法的差别。找相关,靠文档与分块,按相似度召回;对号入座,靠条文与条件,拿事实去对条件,相似度只能先用来找出候选。
开源 RAG 平台部署成本低,界面与权限也基本齐备,于是“直接拿来当法规知识库”成为一种自然选择。本文关心的是:这条路径在哪里会断,断口能否用配置弥补,若不能,应在平台之外补什么。
1.2 对象与方法
考察对象为一个开源的知识管理框架(WeKnora,MIT 许可,考察时版本 0.8.3),技术构成为 Go 后端、Vue 前端与一个独立的文档解析服务。方法有三:阅读其检索、分块、知识入库相关源码;调用其 HTTP 接口进行实际读写;在其上导入六部公务员管理相关法规,观察入库结果与检索输出。取样落在公务员管理,只为观察方便,本文的设计思想不限于这一个领域。
材料的限度需在开头说明。本文没有做对照实验,没有多样本统计;六部法规、一百七十二个分块、两次检索观察,只能支撑“现象存在”与“成因可定位”,不足以支撑任何关于效果的量化结论。文中部分判断属推断,凡涉推断处多以“提示”“可理解为”“本文推断”标出,但并非逐句标注。
1.3 范围与安排
第二节报告考察所见的四处不匹配,说明为何它们不属配置问题,并交代三条现成路线各自为何不合用:买库、自建、形式化标准。第三节回到需求侧,给出法规知识库应具备的结构。第四节提出补偿设计与其分工界线,范围限于第一类知识的身份、条件、治理与检索输出;优先级关系与第二、三类知识的处理不在本文设计之内。第五节讨论该设计最薄弱处、追溯能力、与图谱及路由两类路线的关系、以及局限。第六节收束。接口契约、表结构、队列划分、轨迹与上线门槛这类工程细节,另见配套的《实施备忘》,正文不展开。
二、平台能力的考察
2.1 检索里没有条件的位置
检索入口的参数只有查询文本、查询向量、知识库标识、知识标识、标签标识、排除项、返回条数与相似度阈值,没有一项是“条件”。时间是最常被用到、也最明显缺席的一种:一部法规修订后,旧条文仍留在库里,检索不带时间,新旧条文一起进入候选,谁前谁后由相似度决定,而相似度高不等于当时有效。
分块一级虽有修订记录,记的是修订序号与编辑时间,不是生效区间。编辑时间回答“这条什么时候被改过”,不回答“这条从什么时候开始算数”。两者不能互相替代:一次录入性编辑不改变条文的效力起点,一次实质修订却同时改变旧条文的终点与新条文的起点。
2.2 字段挂不上,分支更判不出
对号入座需要每一条先有身份(属于哪份文件、第几条),再挂上字段(生效日期、位阶、审核状态)。考察所见,平台在文档一级有用户可自撰的元数据,可存任意键值;到了分块一级,更新入口只接受正文与启用状态,不接受附加信息。
这里要把两种字段分开,否则后面几处论断都会失准。一种是条级静态属性:生效日期、位阶、审核状态,一条一个值,与问的是谁无关。另一种是条内分支:同一条文对不同的人给出不同的答案,答哪一支取决于当事人的情形。
先说前一种。现在的向量库大多支持元数据预过滤,字段一旦挂在块上,按条级属性把不合格的条文挡在候选之外,在存储层是做得到的。这套能力到不了本平台的检索入口——入口那几个参数里没有一个是过滤条件——但即便补上入口,另有更难的一层在下面。难点只在挂不上去:硬塞进正文,违反“原文不可改写”;只存文档一级,同一文件里不同条文的生效日期就分不开——而这正是法规最常见的形态,一份修正案往往只改其中数条。对这类字段,平台的欠缺是缺字段位,不是缺机制,补起来是加列与改入口的事。
后一种连机制都无从谈起。条内分支不是条文的属性,而是条文内部的岔口:同一件事,对不同的人给不同答案。要把它压成条级字段,就得先替所有情形选定一个答案,压完这一条只剩半条意思。例如某条对改革前参加工作的人定一个年龄、对改革后参加工作的人另定一个,两个值都在这一条里,“这条的年龄”填进哪个字段都是错的。对这类条件,平台最多把整条筛进或筛出,答不出该走哪一支。
筛与判的分界就在这里:筛回答“该不该进候选”,判回答“进去之后走哪一支”。前者可以靠字段,字段能挂上的那部分,平台做得到;后者只能拿当事人的情形逐项对照条文里的限定语,这件事,平台没有位置。
2.3 切分不由条文决定,身份无从建立
平台的分块策略按字数与标点切分,配父块与子块两级;内置的中文识别只认“章、节、部分、篇”,不认“条、款、项”。
后果在入库结果里直接可见:有的块装下完整一条、还捎上下一条的开头,有的长条被截成两段。前者让条与块的对应不再唯一,后者切断了一条的上下文。
更麻烦的是它的错误沉默。块里仍是原文,字数、标点、文字都对,任何以“内容是否被改动”为标准的检查都通过,错的只是边界。
2.4 治理没有位置
平台在知识条目上有处理状态,取值待处理、处理中、已完成、失败。这是解析流水线的状态,回答“这份文件解析完没有”,不是“这条内容准不准用”。
对号入座还要求两条治理判断:这条内容有没有经人确认,以及它是否与既有条目冲突。前者决定能不能进默认检索,后者决定要不要挂起。这两件事,平台里都没有对应位置。
2.5 为何不属配置问题
这四点容易被当成“没调好”。区分标准一条:修复它要不要动接口契约、索引结构或表列。
加时间条件,要改接口契约、各检索引擎适配层、索引结构;按条切分,要新增策略并配套识别规则;条文级字段没处放,因为分块表的列里没有它;治理状态没处放,因为状态字段已被解析流程占用。四项都指向同一层:平台把知识组织成“文档—分块—向量”,而法规要的是“条文—条件”。前者能做“找相关”,后者才谈得上“对号入座”。
由共同成因可推断,同类平台大概率同样受限,因为它们共享同一范式;但本文未对其它平台作接口与表结构考察,此推断不作结论依据。眼下可行的替代两类:买商业法规数据库,条文结构、时效标注、版本比对现成,代价是封闭[1];或自建,代价是成本。此外还有一条更早的路,按既有标准把条文形式化,单列于下。
2.6 第三条现成路线:形式化标准
除了买库与自建,还有一条走得更早的路:按既有标准把法规形式化。Akoma Ntoso[2] 与 ELI[3] 规定条文如何标记与标识;LegalRuleML[4]、Catala[5] 与 Solon[6] 规定法律源如何建模、规则如何写成可执行式,判定交给规则引擎。这条路有成熟工具与实施案例,不该略过。
它对闭合的分支确实管用。同一条“改革前参加工作的六十岁、之后六十五岁”,写成两条规则,引擎算得出来,且每次结果一样。本文不否认这一点,也不主张形式化不适用于条内分支。准确的表述是:形式化适用于分支闭合的情形,本文的场景以裁量为主。
它与本文隔着的不是能力,是两条前提。其一,规则必须闭合,谓词要能落到可计算的值上。而公务员、环保、税务这类领域里,“情节严重”“确有必要”“影响较大”是常见写法,且往往正是争点所在。把这类谓词强行闭合,等于替制定机关补写标准——给“情节严重”配一个金额门槛,这个门槛法条里没有,是写规则的人定的。退一步改成参数可配,判断也没有消失,只是从运行时挪到了配置时,仍要有人担这个责。其二,规则要有人写:每部法规、每次修订都要有人重写或改规则,写错的后果也由人担。
还有一层差别在错误现形的时点。形式化的差错出现在写规则的时候,能编译、能测试、能被人看见;本文这一路的差错出现在运行时,条件提取偏了、映射没对上,系统自己不会报警,只有使用方发现结论不对才知道。两条路的差别因此不在一贵一贱,而在同一个投入落在哪个环节、在什么时刻暴露。选哪条,取决于该领域条款的闭合程度与修订频率,本文不认为有普适答案。
还有一处须说清。本文的身份设计借鉴了标记标准中身份与位置分离的思路,却不采用完整的标记体系。理由不在平台约束——权威副本在平台之外,平台解不解析标记与本设计无关——而在成本:完整标记要人工逐条标注,每部法规、每次修订都要重标;本文场景又以裁量为主,用不到那样细的结构。不采用完整体系,不等于拒绝它们的局部能力:标记标准可为权威副本提供持久标识,法律源建模可为条间关系提供本体参考,版本分层可让双时态追溯分得更细。本文与这些标准是分工,不是替代;能吸收多少,取决于建库时肯投入多少标注。
三、需求侧:法规知识库要什么
3.1 定位
法规知识库应是一个只读的规则供给服务:使用方给出一个对象、一件事和一个时点,它返回适用的条文及其依据,合规判断由使用方自己做。它不判断责任,不编排流程,也不替使用方决定一件事该由机器判定还是转人工。
这个定位带来两条边界。其一,它给的是依据,不是结论,因此不自行撰写解释性文字。其二,它的输出必须能回溯到条文本身,因此不能以“大意如此”的形式交付。
3.2 三类知识
实践中需要供给的知识不止一类,来源与治理方式也不同。
第一类是权威规则,来源是导入的正式法规文本。结构化程度最高,治理最严,写入须经审批,且只能标记失效、不能删除或改写,因为已经下发过的文件可能已被引用。
第二类是会话沉淀的临时约束,来源是办理过程中用户对 Agent 的纠正或补充。它的共同特征是事后产生:用户在使用之前并不知道 Agent 会表现成什么样,看到输出才发现哪里不对。这类知识结构轻、写入快,但与正式条文冲突时不得自行裁决,只能报出冲突并交由使用方去问用户。
第三类是工具与字典的使用指引,服务于“办这类事该调哪个工具、参数从哪来、用哪张表互译”。它既非法规也非约束,而是操作层配置,出错代价高,故其变更宜走轻量确认。
三者物理隔离,共享同一查询入口,以类型分流。
第一类的身份键取“文号 + 定位符”,库内另以文件名为展示标识。定位符随文件种类不同:法规类取条号,纪要类取专题序号。之所以不另立版本号,是因为正式文件本身已带文号与施行日期,再添一套编号反增负担。文件名可重名、可改动,故只作展示;遇到重名以文号消歧。
3.3 一条条文,四件事
一条条文进入知识库,系统须能回答四件事:它是哪一条,它讲什么,它对谁、在何时、何种情形下适用,它现在能不能用。前两件决定找不找得到,第三件决定该不该用,第四件决定敢不敢用。
它是哪一条,是身份。文件一级记名称、制定机关、文号、位阶、性质;条文一级记章、节、条、款、项的层级路径。层级路径按文件种类分,法规走章、节、条、款、项,纪要走专题、编号、标题。二者不可混用:纪要没有条号,硬套章条款项只能编造一个假条号,身份随即失真。
它讲什么,是内容。原文一个字不改,照存。任何概括、转述都放在原文之外,不取代原文。
它对谁、在何时、何种情形下适用,是条件,也是本设计的核心。时间——何时生效、何时失效——是条件中最常见的一种,却不是特殊的一种:对哪类人适用、在何种行为下起作用、在哪个辖区有效,与它同列。判断一条规适不适用,就是拿使用方提供的事实去对条件:对得上的,给出条文;对不上的,说明哪条条件不满足;对不了的——条件模糊、指代不明、事实缺失——就标出来交人,不装作已经判定。
条件项自身也要有形状,否则程序无从比对。一项条件至少写清六件事:字段名、类型、取值或范围、单位、原文依据、以及怎样算成立。类型不外乎时间、主体、行为、地域与引用另一条几类。若条件项只是一段自由文本,比对仍要回到理解,4.2 那条界线就落空。前四件事同时是事实侧要填的东西:条件声明它需要什么,事实提供现在有什么,两侧用同一个字段名对齐。
满足、不满足、无法判定三者的边界也要写明:事实齐备且落在取值之内,判满足或不满足;事实缺项或取值域未覆盖,判无法判定,不判不满足。同层之内多个条件取并列,须同时成立;分支之间择一;但书成立则排除本条。执行次序是范围、分支、但书,不可颠倒。
比对用的事实从哪来,也得交代。使用方说的是一件事,程序要的是字段值,中间隔着一次结构化。本文约定:比对所用的事实字段由使用方提供,或经使用方确认后进入;未经确认的抽取结果不作比对输入。事实缺项不按“条件不满足”处理,那是替使用方做了他没做过的判断;另立一档“待补事实”,条文仍留在候选里,并说明缺什么。条件侧靠原文依据兜住,事实侧靠回显确认兜住,两侧各有兜法,都不让未定之事进入确定性环节。
条件不是一张平面清单。真实条文常分三层:先是适用范围,这条对谁、在哪个辖区、管什么事;再是分支,在范围之内按不同情形给出不同答案;最后是但书,把某一情形整体移出本条管辖。三层次序不能颠倒。范围不满足,分支不必看;分支选定了,还要再查有没有但书把它推开。把三层压成一堆并列条件,比对时会把不适用的情形算进分支,也会漏掉被但书排除的情形。三层之中只有分支分出结果,范围与但书都只做排除。
分支与但书最易混。判据看该分句把当事人往哪儿送:往本条之内的另一个后果送,是分支;往本条之外送,是但书。“违法行为轻微并及时纠正,没有造成危害后果的,不予处罚”是分支,当事人仍在本条管辖内,只是后果从罚变为不罚。“本法另有规定的除外”“不适用前款规定”是但书,它把人推出去,本条对他不产生任何后果,得另找依据。
移送型分句最易误判。“构成犯罪的,依法追究刑事责任”送往条外,却没有“不再”“不予”“免予”这类排除词,本条的行政处罚照旧,故归分支;只有带了排除词、把本条后果抹掉的,才归但书,如“已追究刑事责任的,不再给予行政处罚”。两者都往条外送,差别在后果有没有被取消。
分清这两者不只是分类癖。分支选错,输出的是“本条适用、后果不对”;但书漏掉,输出的是“本条适用、而本条本不管他”,后者错得更硬——使用方会拿一条根本不适用于他的规定去办事。
这一判据随定位符的粒度而变。本文的定位符到条不到款,款在条内,故“适用本条第二款”仍属条内转交,按分支处理;若日后把定位符下探到款,这类转交就要改按但书算,因为被转出的那一款对当事人已不再给出后果。
跨条的例外不放进条件。一条规定“本条不适用于第某条所列情形”,这是两条之间的关系,按优先关系处理,与本节的治理一段、4.4 节的第三步同在一处。条件模型管条内,适用关系管条间,两边都不勉强。
条件模型覆盖的是“构成要件到法律后果”这一型条文,其余三类须另说。程序性规范有条件也有后果,只是后果为程序义务而非适用判定,仍可按条件模型处理,后果字段填“应当”“不得”“可以”及对应义务。定义性条文自身不参与比对,它是别的条文比对时的解释依据;入库后条件表留空,在关系表里标“被引用”,比对涉及被定义概念时沿关系取定义。授权性规范没有后果,不参与比对,但须进库接受治理,以保证引用它的条文能追到有效依据。承认这条边界不削弱本文的论点:条件模型管给定条件、确定后果的那一部分,其余或作引用对象、或只走治理,不强行纳入比对。
它现在能不能用,是治理。审核状态分已解析、自审通过、冲突待确认、已批准,只有已批准进入默认检索。两条条文都满足条件、又给出相反结论时,需要比谁优先——上位、特别、新[4],比出来落成一条“优先”关系,只给优先级,不删除被覆盖的那条,历史时点仍须能调到。
四件事各有检查:身份查路径是否断裂、原文是否被改动;内容查原文与权威副本是否一致;条件查能判的判了没有、判不了的标了没有;治理查状态流转是否合法、冲突是否报出。任一件查不过,该条挂起,不进入治理流转。
图 1
,四件事:前三件并列,治理横切其上
四、分层补偿的设计
4.1 两份副本与身份归属
设计的第一条不是给平台加功能,而是缩小它的职责:只让它存一份检索副本,负责“找相关”——按语义找出可能沾边的条文。
这里先交代一件事,否则后文会自相矛盾。原文在系统里存在两份(图 2):一份在平台内,供召回用,它怎么切分无关紧要;一份在平台外,是权威副本,条文怎么切、身份是什么、条件有哪些,都在那里定。平台的切分结果不当身份用,所以它切错了只会少召回几条,不会改变任何一条的身份——该条在权威副本里是第几条,不因平台把两条并成一块而含糊。
两份副本之间必须有一条映射,否则外围拿回一个块,不知道它说的是哪一条。这一步不靠平台的块编号:编号随切分策略生成,重切一次就全变,拿它当身份,等于把地基交给最不稳的那一环。也不靠模型回头再读一遍条号:模型会读错,而且错得没有声响。
可行的办法是文本锚定:拿块的正文去权威副本的条文原文里比对,落在哪一条的原文里,就定位到哪一条。这条办法之所以成立,是因为块切得再糙,里面的字仍是原文,仍是某一条原文的一段子串——切分改变的是边界,不改变文字。
比对之前要先做标准化,否则同一条文在两份副本里会因为空白符、换行、全半角、标点样式不同而合不上。清洗规则对双方一致:去掉空白与换行,统一全半角,统一引号与标点,数字与括号一律取半角。原文本身不动,标准化只在比对时用的临时串上做。
标准化之后仍可能因解析器丢字、扫描件讹字而断在中间,所以匹配要留退路:先试子串包含,不中取最长公共子串,再不就上 N 元组重合度(N-gram)或编辑距离(Levenshtein),相似度过一个较高的阈值才算命中。低于阈值的块标为定位失败,不猜。这条退路只影响召回:定位失败无非少一条候选;只要身份不从块编号来,切错、认错都不会把一条文的身份记到别的条文头上。
定位失败的块不进交付内容,只进修复队列。它或许真与某条相关,但身份未定,按本文的立场,宁可少给,不可给错。使用方看到的是一个状态(见 4.4),不是一段没有出处归属的文字。
由此,第二节那几处缺陷(条件没位置、字段没处挂、切分不由条文)到了输出端都不再起作用,剩下的只有一个影响面:召回率。
一句话分工:平台负责“找相关”,外围负责“对号入座”。找得全不全只影响省不省事,对得上对不上由外围说了算。
图 2 两份副本与身份归属:平台内那份只供召回,身份在外围确定
4.2 判断与确定的界线
若把外围全交给模型,同一个问题问两次可能得到两个答案,这与“对号入座”要的唯一性直接冲突。所以外围内部还要再划一次:需要判断的交给模型,必须每次都一样的交给程序。
属于判断的有三件(图 3):条文边界划在哪里、适用条件从哪里提取、这几条里该给哪几条。属于确定的有四件:存储、条件比对、按身份取原文、按固定格式拼装。后四件不含理解成分,全是比对与查询。
界线一句话:同一个问题问两次,程序给的答案一样,模型给的不一定;凡要求一样的,归程序。落到条件这一层,这条界线可以说得更具体:条件提取归模型,条件比对归程序。提取要读限定语、要看上下文、要在没有明说时判断有没有隐含前提,这是理解,两次结果略有出入是常态;比对是拿当事人的情形逐项对照已经写下来的条件,对得上、对不上、还缺条件、或判不了,落到哪一档都是确定的。前者靠原文依据与人审兜住,后者必须每次一样——否则同一个人问两次得到两个答案,唯一性就没了。
图 3 写入与读取两条链路:蓝底为需要判断、交 Agent 的环节,灰底交程序
4.3 两个 Agent
写入侧负责把一份文件变成条目。输入是一条条文与文件级上下文,输出是这条文的身份、条件,以及每一项在原文中的依据。依据不是“为什么这么填”的解释,而是从该条原文里剪下的句子;剪下的句子在原文里找不到,这一项就不成立。
这条规则能挡掉“无出处的编造”——模型能编出通顺的理由,编不出原文里根本没有的句子。但它挡不掉误判:一段原文确实在,却不足以支撑这个条件,这种情形仍要人来判。
多分支条文另有一道结构校验。两个分支若看起来都能套用,多半不是法条含歧义,而是提取时漏了区分两方的限定语:把“改革前参加工作的”抽掉,两支就都成了无条件,谁都匹配得上。所以先看文本结构:分界符、平行句式里“……的”那个槽位、两支相隔的远近,都能判出“这里本该有区分”,这一步由程序做,不需理解语义。判出之后才让模型定向看那个槽位,仍答不出的交人。把这一步放在写入侧,是不让提取缺陷流到运行时冒充法理歧义;一个没有依据句的条件,连标“裁量未定”的资格都没有。
读取侧负责在语义召回出来的候选里,挑出值得进“对号入座”的几条。它只做选择,不做生成,输出定位符清单,每条附一句选它的理由,理由只限对原文限定语的定位或摘录,不得超出原文用词另作解释。
两者共同的约束只有一条:都不许碰原文。前者不许改写,后者不许转述。差别在失败的形态:前者错了,错在身份或条件,条目还能审、能改;后者错了,错在选漏或选错,下游一旦采用,错就外流。所以后者必须留痕,让人能复核。
4.4 检索次序与输出契约
条目建好之后,检索不是一步到位,而是分三步,共用同一个身份键。
第一步按条件过滤,建在身份与治理上:生效期、审核状态、位阶、业务标识、作用域。它先把失效的、未审核的、位阶不符的条目排除掉。这一步不用向量,结果是确定的、可复现的——这就是“对号入座”里的硬门槛。
第二步按语义召回,建在原文上,只做候选发现,不做最终裁决。这就是“找相关”。
第三步查优先级关系,纯图结构:一条义务性规定,沿边能找到挂在它下面的例外;一条被修订的条文,沿边能找到现行版本;一条禁止性规定,沿边能找到例外出口。
次序是先对号、后找相关。用户给了定位符的,直接命中,不打标;只给语义的,一律打标“需人工核对”,不与精确命中混排——这个分级本身就是防“看着很像”的第一道闸,精确命中的和猜出来的,下游必须区别对待。
对外交付的每条结果含六项:文件名、定位符、原文、条件判定(含生效区间)、命中方式(定位命中或语义召回)、治理状态。原文与字段一律取自权威副本,不回平台取,理由见 4.1。条件判定一项还须标出确定性,分四档:已判定、裁量未定、待补事实、但书未验证。四档不可同形呈现,否则使用方分不清哪一条可以当依据。最后一档单列,是因为但书缺事实时,既不能说它成立而排除本条,也不能说它不成立而照常适用;两句话都是替使用方做了他没做过的判断,系统只能说走到这一步、最后一步判不了。
检索状态分五种,不可合并:正常、没找到、命中但未定位、服务坏了、有冲突。服务故障与“库里确实没有”是两回事,混成一个空结果返回,使用方就无法判断该重试还是换一条路。“命中但未定位”指语义召回到了片段,而该片段未能对上任何一条权威条文,原因见 4.1。这一状态只描述系统当下的能力边界,不描述法律内容:它说明库里有相关文字、暂时不能用,不能被读作“存在这样一条规定”。有此一档,使用方才不会把“暂不可用”当成“没有规定”。
两种状态不能随意相乘,否则组合数一大半没有意义。三条规则收住:检索状态不是“正常”时,条件判定不适用;为“正常”时,条件判定取最不利的一档,序为待补事实、裁量未定、已判定;“有冲突”独立于条件判定,两条各自带各档,另加冲突说明。提取存疑不出现在这条链上,它应在入库时被拦下,若出现在输出里,说明治理流转有漏洞。
4.5 治理落在程序一侧
审核状态由程序控制,模型无权变更。状态只许前进、不许跳级;遇冲突停于“冲突待确认”,不进不退。模型填完身份与条件,条目落于“已解析”;人工抽查通过,方至“自审通过”;只有“已批准”进入默认检索。
抽查所依赖的正是前述依据。人不必重读全文,只需判断一句话能否支撑一条身份或一个条件。这一安排意在把人工投入从通读收窄为核对,但能否实际减轻负担,本文未作测量。
条文本身写得好不好、模型读得对不对,是两件事,不能压成一个标签。前者是语义品质,取清晰或裁量未定:条文本身用了“情节严重”“确有必要”这类无法闭合的谓词,标裁量未定是如实反映法理现状,属合法状态,放行并标注,比对落到该支时按 4.4 的确定性一项提示使用方自行判断。后者是提取品质,取已确认或提取存疑:模型没能从原文里找到条件,或所剪的依据句不足以支撑所填内容,这是写入侧的缺陷,不属合法状态,须退回重填或交人工。两列正交,四格都合法。“清晰而提取存疑”是其中一格,说的是条文没问题、模型读漏了,责任不在条文;若一批条目里这一格占比偏高,说明提取这一步没过关,不能拿“裁量多”来解释。
文件一级也要有状态。检索端的开销按次计,建库端的开销按份计,后者更重,也更容易被漏算。一份文件导入后若存在定位失败的块,整份退出默认检索,落文件级状态,进修复队列。部署决策只有这一条,不按条文放行,也不按块放行——失败的块恰恰不知道自己属于哪一条,拿它承载什么来定轻重,等于用未知判未知。
修复环节另有一套便利,与上不上线无关。失败块前后相邻的两块若都定位到同一条文,且这两块在原文中首尾相接,修复者便可据夹逼判出该块归属,免去逐块辨认。它救得了长条内部的孤立失败——一条分作数块,其中一块因丢字、插图、页眉而未匹配上,前后两块干净且同属一条;救不了边界错乱,那种情形下前后块本身就不对,夹逼的前提不成立,而边界错乱恰是定位失败的高发形态。所以这只是修复工的省力处,不是部署的分支。
工单里的缺口不靠失败块反推,而由条号序列校验给出:权威副本从第五条直接跳到第七条,缺的是第六条。使用方看到的是“该文件暂不可用”,看不到条目级缺口——文件既整份不上线,逐条披露也没有对象。质量过低、连条号都断不齐的扫描件,不走自动建库,先人工数字化,否则修复队列会积压到不可运营。
五、讨论
5.1 最薄弱处在切分
一种常见的预期是:模型填写条件最不可靠。本文的观察相反,最薄弱处在切分。
法规文本的条号写法并不统一,“第六条”“第 6 条”“第六 条”并存;条文之下还有“(一)(二)”这样的项,以及“1.”这样的目,加之排版导致的断行,规则识别难免遗漏。漏认一条,其后条号整体错位。
麻烦在于此类错误的隐蔽性。切错位置所切出的文字仍是原文,以“内容是否被改动”为标准的检查全部通过。因此校验的对象不能是字,必须是身份:每一段属于第几条、条号是否连续、段内是否混入其他条号。三事相符,位置才对。
由此可以补一条与“原文不可改写”并列的原则:身份不可错位。两条原则的检查方式不同,不可互相代替——前者比字,后者比身份,而比字在切分环节形同虚设。
这里要说明 4.1 节那层映射的边界。文本锚定能把平台的切分错误挡在身份之外:块对原文匹配,切歪了顶多定位失败。但这条办法的立足点是权威副本自己的条号无误。条号若在建库时认错,锚定反而会把块稳稳地记到错的那一条上,错得整齐,事后查不出来。映射层因此不算切分问题的解,它只是把切分的后果挡在身份之外,代价是把责任集中到建库这一环。
条号校验本身也有够不着的地方。连续性检查能发现跳号、重号这类局部错位,发现不了整体偏移:首条认错一位,其后全部顺延,序列照样连续,前面所说三事相符的校验也全过,错得干干净净。想靠文件自身的外部特征兜底,例如目录所载条数、附则所称条数,并不总有著落——不少文件没有目录,附则也不载条数。更可行的一道是让两条互不依赖的链路各认一次条号,再比偏移量:整齐的错误只能由另一处独立的整齐来打破,两边偏移一旦不等,问题当场现形。这道校验止于报警,不止于定位——偏移不等只说明至少一方有错,指不出错在哪一条,定位仍要回到原文由人逐条核。它的用处不在修,在于把一处原本沉默的错误变成可检测的异常;检出来之后的处置与全文一致,交人。校验本身也要成本,值不值得,取决于文件的重要性。
5.2 追溯要三层
治理要求“正式规定只标失效、不删除”,这一条不是流程习惯,是存储约束,理由是追溯必须成立。追溯本身分三层,缺一层就不完整。
检索溯源:每条结果能说明它是怎么被找到的,并定位到条文一级。缺了这一层,使用方分不清一条依据是定位命中还是语义猜中。
版本溯源:旧版本退出默认检索,但能显式调取,任何时点都能重建当时的文本。缺了这一层,“当时有效”就无从验证。版本的划分参照书目领域对作品与版本的分层[7],此处只借它把层次分清,不搬它整套模型。
变更溯源:每次写入与审核都记下谁做的、什么时候、改前改后是什么,不可抵赖。缺了这一层,条件被改过也看不出来。
三层对应两条时间轴:版本溯源管“有效时间”,问的是某个时点什么有效;变更溯源管“系统时间”,问的是某个时点库里记录了什么。这两条轴必须分开存[8]——混在一起,答案给出时可能对,事后却解释不清。三层合起来,才撑得起“对号入座”这一要求。只做最后一层(记日志)而缺前两层,是常见的不完整做法。
5.3 与图谱路线、Agent 路由的关系
另有两类做法常被拿来与本文比较:把条文建成知识图谱,以及让 Agent 先查目录再查正文。二者与本文不冲突,因为解决的不是同一件事。
图谱的长处在表达与寻址。一条规定对哪类主体适用,可落成一条事实边;上位下位、修订被修订、原则与例外,这些关系沿边走比查表顺。但“眼前这个具体事实该落进条内哪一支”,图本身不给答案:要么事先把条件写成规则由引擎算,要么让模型当场读原文判。前者的贡献在规则,后者的贡献在模型,图谱在两种情形下都只到寻址为止。表达是静态的边,判定是动态的比对,两件事不能互相顶替。
模型当场判这一支,本文不用它承担比对,理由与 4.2 相同:同一个事实问两次可能给出两支,而比对要的是每次一样。它可以参与提取,不能承担判定。
Agent 路由同理。它改的是找的方式:多轮、可回溯、先定位文件再进正文,召回通常更全。但寻址完成之后,“这条对眼前这个事实适不适用”仍要有人做。路由本身还与唯一性有张力:同一个人问两次,路由可能给出不同的候选集;本文的读取侧只做一次选择并留痕,正是把这段不确定性收在可复核的范围内。二者可以叠加,叠加时本文那一层的位置不变:图谱与路由把“找”做得更好,本文补的是“找完之后怎么判”。
5.4 局限与未决
局限有六。其一,样本极小,六部法规、一百七十二个分块、两次检索观察,只能说明现象存在,不能说明其普遍程度;不同来源、不同排版的法规,切分难度差异可能很大。其二,效果未经验证。低成本的做法是有的:从已建条目里取一批可闭合的条件,时间、身份、年限一类,构造若干当事人事实,由人给出应适用的条与款,再跑程序比对,看一致率与不一致项的成因——漏召、前提判断错、分支选错,还是裁量带来的人机分歧。裁量条款不纳入一致率,其标准答案本不唯一。这一步本文未做,故上述优劣均为原理推得。其三,身份与条件的填写准确性未被系统评估,依据可回溯能挡住无出处的编造,挡不住误判。其四,本文的设计范围限于第一类知识的身份、条件、治理与检索输出,优先级关系如何建立、第二与第三类知识如何组织,均未涉及。其五,成本未算。本设计的“轻”指架构侵入性低、不要求规则闭合、不要求替换平台,不指总投入低;模型逐条提取、人工核对、映射表与修复队列的维护,都是持续开销,且随文件数增长。这笔账本文未算,只指出它落在哪,见 2.6 末段。其六,修复环节的负荷未估。夹逼只在长条内部孤立失败时可用,触发率可推断偏低,修复工单的吞吐因而主要取决于人工数字化的能力;本文未测,也未估算一份文件从退出到重新上线的平均耗时。
验证方案的指标还须先定义。一致,指程序给出的适用条文集合与人工答案相同,且每一条的条件判定档位相同;只给出同一条却把裁量未定判成已判定,不算一致。不一致按四类归因:漏召、范围条件判错、分支选错、裁量分歧。裁量条款不计入一致率,但另有考核:系统是否如实标出裁量未定、依据句是否指向那个无法闭合的谓词,这两条可逐项核对,不依赖标准答案唯一。
未决的问题有五。一是治理的操作细则:抽查比例、检查不过如何处置、人工修改的入口、文件级要不要设状态,均未定。二是身份与版本的边界:身份键要不要带时点、一次修正后其余条文要不要跟着复制成新版本,存疑未定。三是冲突由谁判定:程序只报“条件重叠、后果相反”的嫌疑,定夺归人;但临时约束与正式条文“是否构成冲突”由谁判,仍未定。四是平台那层是否保留语义召回,取决于实际规模。五是“已公布、未施行”要不要单列为一个状态,现设计默认时间条件落在过去,对此未作处理。
此外还有三个更靠前的取舍,本文未展开,因其不属工程层面而属设计取向。一是单位问题:条文是否作为唯一单位,还是文件与条文两级并存。二是治理形态:靠流程推动,还是靠标记加留痕。三是结构的长法:一次建全,还是先以一份法规长出骨架再扩。这三项一旦定下,前文的若干设计细节随之改变,故不宜在细节上先行结论,留待后续讨论。
六、结论
法规知识库与通用文档库要的不是一回事:前者要“对号入座”,后者要“找相关”。用通用 RAG 平台直接承载,会在身份、条件、治理三处撞上结构性的墙,切分这一关更是地基。这些限制的成因在数据组织方式,非参数可调;更换同类平台能否消除,本文未作横向考察,仅据共同范式推断大概率不能。
可行的路径是把平台缩成“找相关”——只存检索副本、做语义召回;把身份、条件、治理搬到外围,做“对号入座”。外围内部再划一条线:条件提取交模型,条件比对交程序,算不了的标出来交人,不把未定之事当作已定。
这条路不便宜,也不轻。它降低的是单次核对的认知负荷,从通读全文收窄为判断一句话能否支撑一个条件;不降低的是总投入,条目数随文件数增长,每次修订还要重提取。换来的也不是省人工,是把不可控的全量阅读变成可计件、可排期、可分工的逐项核对,加上不要求规则闭合、不要求替换平台、不把裁量硬行闭合这三点。
设计中最要防的不是模型,是切分。切分错了形态沉默,内容比对查不出来,只能拿条文身份去验。
这套设计能不能交付,有两条当场可验的判据:每条输出能追到原文依据句,追不到就不输出;同一输入两次比对,结果一样。准确率一类统计量是上线之后持续监控的运营指标,不作上线门槛——用它当门槛,系统会一直卡在还差几个百分点上。
材料说明 本文所据材料为:对该平台源码与接口的考察记录;在其上导入六部公务员管理相关法规(合计一百七十二个分块)的入库结果;两次检索的完整输出;以及本项目前期关于需求与结构的讨论记录。未列出所导入法规的名称与文号。凡属作者推断之处,已尽量以限定语标出,未作为观察结果陈述。
参考文献
[1] 北大法宝[EB/OL]. www.pkulaw.com.
[2] OASIS. Akoma Ntoso Version 2.0[S]. 2026.
[3] Council of the European Union. European Legislation Identifier (ELI)[EB/OL]. eur-lex.europa.eu/eli.
[4] OASIS. LegalRuleML Version 1.0[S]. 2018.
[5] Merigoux D, Chataing N, Protzenko J. Catala: A Programming Language for the Law[J]. Proceedings of the ACM on Programming Languages, 2021, 5(ICFP): 77:1-77:29.
[6] Koniaris M, Papastefanatos G, Anagnostopoulos I. Solon: A Holistic Approach for Modelling, Managing and Mining Legal Sources[J]. Algorithms, 2018, 11(12): 196.
[7] IFLA Study Group on the Functional Requirements for Bibliographic Records. Functional Requirements for Bibliographic Records: Final Report[M]. München: K.G. Saur, 1998.
[8] Snodgrass R T. Developing Time-Oriented Database Applications in SQL[M]. San Francisco: Morgan Kaufmann Publishers, 1999.