news 2026/9/7 15:13:29

合同做 RAG,为什么不能直接按 Token 切?

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
合同做 RAG,为什么不能直接按 Token 切?

合同做 RAG,为什么不能直接按 Token 切?

用 RAG 查合同,有一种错误特别麻烦。

用户问:

「我们的赔偿责任上限是多少?」

系统很快回答:

最高不超过过去 12 个月支付的服务费。

单看这句话没问题。

但回到原合同继续往后看,后面可能还紧跟着重大过失、知识产权侵权、违反保密义务等例外。前面的“上限”找到了,但决定这个上限什么时候不适用的内容没有一起回来。

模型未必在胡编。

它只是拿到了一个不完整的 chunk。

这也是我们在做企业级 AI 知识库「有谷大脑」时,为什么会把合同类文档从普通文档里单独拆出来处理。

合同和一般文章不同。很多条款的含义并不只在当前这一段里,还依赖父条款、Definitions、例外条款、交叉引用,甚至附件。

所以在有谷大脑里,合同不会直接走“抽文本 → 固定 Token 切割”这条路径,而是先做文档识别和结构解析,恢复条款层级之后,再生成候选 chunk。


一、固定 Token 切割,为什么容易把合同切坏?

很多 RAG 项目一开始都会用固定长度切割,比如每个 chunk 控制在几百 tokens,再保留一点 overlap。

实现简单,也很通用。

但合同里最麻烦的是:法律语义经常刚好跨过切割点。

比如:

12.4 Limitation of Liability 甲方对乙方承担的最大赔偿责任,不超过乙方在过去 12 个月内实际支付的服务费,但以下情况除外: (a) 因甲方故意或重大过失导致的损失; (b) 第三方知识产权侵权; (c) 违反保密义务造成的损失。

如果切割点落在“但以下情况除外”前后,就可能变成:

Chunk A: 最大赔偿责任不超过过去 12 个月内实际支付的服务费。

以及:

Chunk B: 但以下情况除外: (a) 故意或重大过失…… (b) 知识产权侵权……

用户搜“赔偿责任上限”,Chunk A 往往更容易被召回。

模型回答“12 个月服务费”也很自然。

问题是,它看到的本来就只有半条规则。

Overlap 可以缓解一部分情况,但解决不了这个根本问题,因为切割依据仍然是长度,而不是条款完整性。

合同里还有几类类似的问题。

Definitions 和正文可能断开。

比如合同开头定义:

“服务”是指甲方根据本协议及附件 A 向乙方提供的软件服务、 技术支持服务及相关升级服务。 “用户数据”是指乙方或其授权用户通过平台上传、存储、 生成或处理的数据。

后面的正文会反复使用“服务”“用户数据”“保密信息”这些词。

在合同里,这些不是普通词,而是已经被定义过的术语。

如果用户问:

服务终止后,用户数据怎么处理?

检索可能把终止条款找出来了,却没有把“用户数据”的定义带回来。

这时候正文虽然没切坏,上下文依然不完整。

交叉引用也可能悬空。

合同里大量存在:

如 Section 9.3(a) 所述……

或者:

具体服务等级见附件 B。

如果当前 chunk 只有“见附件 B”,但系统不知道附件 B 跟它有什么关系,那么这个引用其实是悬空的。

子条款也可能失去父级语义。

比如:

1.1 未经甲方书面同意,乙方不得: (a) 将前述权利转让给任何第三方; (b) 对服务进行转售;

如果只检索到:

(a) 将前述权利转让给任何第三方。

“前述权利”是什么已经丢了。

所以合同 Chunking 真正要保护的,不只是某一段文字,而是条款之间原本存在的结构关系。


二、合同本身,其实已经告诉我们应该怎么切

合同和普通长文本有一个很大的区别:它通常有非常明确的层级结构。

英文合同常见:

Article I Section 1.01 (a) (i) (ii)

中文合同常见:

第一条 第一款 (一) (二)

或者:

1. 1.1 1.1.1 1.1.2

这些编号不是普通排版,它们本身就是合同提供的结构信号。

所以处理合同的时候,与其先问:

这一段有多少 Token?

不如先回答:

这一段到底属于哪一条?

在有谷大脑里,合同进入知识库后,会先尝试识别ArticleSection1.11.1(a)第 N 条这类编号结构,恢复条款层级,再决定哪些节点适合作为候选 chunk。


三、有谷大脑怎么做合同条款级 Chunking?

前面这些问题,本质上都指向同一件事:合同不能只按文本长度切,还得把原来的条款结构和引用关系保留下来。

在有谷大脑的合同解析链路里,大致会经历:

合同识别 → 条款结构解析 → 生成候选 clause chunk → 补充 Definitions / 父级 / 引用关系 → 超预算条款继续细分

也就是说,Token 预算还在,但它不负责决定“第一刀从哪里切”。

它只是限制一个 chunk 最终能有多大。

图 1:有谷大脑合同条款级 Chunking 架构——先恢复合同层级,再分别处理定义索引、叶子条款和交叉引用,检索阶段根据命中结果按需展开上下文。

比如:

Section 12. Limitation of Liability │ ├─ 12.1 General Cap │ ├─ 12.2 Exceptions │ ├─ 12.2(a) Gross negligence │ ├─ 12.2(b) IP infringement │ └─ 12.2(c) Confidentiality breach │ └─ 12.3 Mutual cap

这里Section 12是父节点,12.2下面还有子条款。

真正适合作为候选 chunk 的,通常是:

12.1 12.2(a) 12.2(b) 12.2(c) 12.3

而不是从某个 Token 位置切一刀,把12.1的后半段和12.2的前半段塞进同一个 chunk。

如果某个条款本身特别长,再优先沿子条款、编号列表、自然段继续拆。

只有前面这些语义边界都不够用时,才退到长度边界。

所以这里并不是不用 Token,而是把 Token 从“切割依据”变成了“长度约束”。


四、切成条款还不够,关系也要一起保存

只把合同按照 Section 和 Clause 切开,还没有结束。

有些条款单独看依然不完整,所以还需要把它和父级、定义、引用对象之间的关系一起保存下来。

祖先路径

比如检索命中了:

12.2(a) Gross negligence

如果只拿这一句,信息还是不够。

所以条款 chunk 会带上自己的结构路径,比如:

{"path":"Section 12 > 12.2 > 12.2(a)","level":3}

这样系统知道它属于:

Section 12 → 12.2 Exceptions → 12.2(a)

一方面模型能拿到必要的父级语义,另一方面最终回答也更容易回到具体条款,而不是只说“根据知识库内容”。

对合同场景来说,来源路径本身就是很重要的信息。

Definitions

定义块识别出来以后,可以转成结构化记录:

{"term":"Customer Data","definition":"..."}

然后单独建立定义索引。

当查询里出现合同已经定义过的术语时,系统可以把对应定义一起补进 Context。

比如:

Customer Data 在合同终止后多久删除?

实际可能需要的上下文是:

Customer Data 的定义 + 合同终止条款 + 数据删除 / 返还条款

而不是只期待向量检索刚好把 Definitions 那一页搜回来。

交叉引用

比如:

{"path":"Section 12.1","text":"……不超过过去12个月内乙方已实际支付的服务费(如第9.3(a)条所定义)……","cross_references":["Section 9.3(a)"]}

这样Section 12.1Section 9.3(a)之间就有明确关系。

但检索到12.1时,并不一定每次都要把9.3(a)也塞进 Context。

用户只是问:

责任上限是多少?

当前条款可能已经够用。

如果继续问:

这里的“过去 12 个月服务费”具体怎么算?

再沿着cross_references9.3(a)拉进来。

这种按需展开,比把整个引用链一次性全塞进去更稳。合同的交叉引用有时很多,上下文越多不代表回答越好。

附件

企业合同里,真正重要的数字经常不在正文。

比如主协议只写:

具体服务等级见附件 B。

附件 B 才写:

Availability SLA:99.9% P1 故障响应时间:30 分钟

如果附件被当成一份完全无关的文档,用户问:

这份合同的 SLA 是多少?

主合同很可能只返回一句“见附件 B”。

所以附件除了自己要切对,还要保留和主协议的关联。

价格、SLA、API 限额、服务范围、数据处理要求,这些内容都很常见。


五、怎么判断一份文档该不该走合同解析?

企业知识库里不会只有合同,所以入库时还要先决定走哪条解析路径。

有谷目前会结合几类信号来判断。

比如文件名:

合同协议NDASLA服务条款License Agreement

再看结构上有没有高密度的:

1.11.1(a)SectionArticle第一条第一款

以及正文里:

甲方乙方违约赔偿本协议

这类词的分布。

单看一个信号都不够稳,组合起来会更可靠。

对于置信度低的文档,保留回退到通用文档解析的路径,而不是强行按合同切。

因为普通报告如果被误切成大量细碎的“条款”,一样会影响检索效果。


六、条款级 Chunking 和固定 Token,到底差在哪?

放在一起看会更直观:

对比项固定 Token Chunking合同条款级 Chunking
切割依据Token 长度条款结构和语义边界
条款完整性可能从中间切开优先保留完整条款
父子关系容易丢失保留祖先路径
Definitions当普通文本检索单独提取和索引
交叉引用容易悬空保存引用关系
附件可能和正文割裂保留主协议关联
超长条款到长度继续切优先沿子条款、段落拆
来源定位文本片段Section / Clause 路径

所以这里并不是说合同不能使用 Token。

更准确地说:

Token 应该是长度约束,而不应该成为唯一的切割依据。

固定 Token 关心的是“这一段有多长”。

条款级 Chunking 更关心的是“这一段到底属于哪一条,以及和哪些内容有关”。


七、合同 RAG 做得对不对,可以直接这样测

比起“帮我总结这份合同”,下面几类问题更容易暴露底层 Chunking 有没有真的做好。

责任上限

赔偿责任上限是多少?有哪些例外?

看责任上限和 Exceptions 有没有被拆开。

定义术语

合同里的“保密信息”具体指什么?

看 Definitions 能不能正确关联回来。

跨条款问题

延迟付款超过 30 天,会触发哪些后果?

这类问题通常不只依赖一个条款,可能同时涉及付款、违约、暂停服务甚至终止。

附件问题

SLA 是多少?P1 故障多久响应?

看附件和主协议有没有断开。

来源追溯

这个结论具体来自合同哪一条?

如果最后只能回答“根据知识库内容”,对合同场景来说还不太够。

至少应该尽可能回到具体的 Section / Clause,让用户能打开原合同核对。

这几类问题,比“帮我总结一下合同”更容易看出底层 Chunking 到底有没有做好。


八、最后:合同 RAG 最怕的不是没搜到,而是只搜到半条规则

做合同 RAG,模型能力当然重要,但不少错误其实在模型回答之前就已经埋下了。

如果入库时把责任上限和例外切开,把 Definitions 和正文断开,把Section 9.3(a)变成一个无法展开的引用,那么后面换 Embedding、调召回参数,甚至换更大的模型,都很难把这些结构关系完整补回来。

所以在有谷大脑里,合同类文档会单独走结构化解析链路:

先恢复合同层级,再做条款级 Chunking,同时保留 Definitions、父子路径、交叉引用和附件关系。

我们更关注的是:检索回来的上下文是不是完整,以及答案能不能回到原合同核对。

除了合同,有谷大脑也在针对 Excel、Word、PDF、PPT 等不同类型的企业文档做对应的解析和 Chunking。

前面已经拆过 Excel,后面还会继续写:

  • PDF 里的复杂表格怎么进知识库?
  • 几百页的 Word 制度文件怎么保留章节层级?
  • 为什么 RAG 明明检索到了,模型还是会答错?
  • 多版本文档并存时,怎么避免引用旧版本?

如果你也在做企业知识库、RAG、合同智能问答或企业 AI 落地,可以关注后续更新。

如果想进一步了解这些能力在产品里的实际应用,可以体验:

有谷大脑:https://brain.yogu.pro

合同 RAG 最怕的不是没搜到,而是只搜到了半条规则。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 5:45:50

信创动环监控品牌技术体系剖析与实施方案

信创动环监控品牌的市场背景分析 随着数字化和智能化时代的到来,动环监控系统逐渐成为数据中心及商业建筑的核心组成部分。“信创动环监控品牌”在此背景下崭露头角,其技术不光满足了市场对安全可靠监测的需求,同时也符合绿色节能的发展趋势。…

作者头像 李华
网站建设 2026/9/1 5:48:30

密度脊与SCMS算法:从统计理论到无监督结构提取实践

做无监督学习相关项目时,我们习惯把聚类理解成“找密度最高的点”,却经常忽略另一类结构:很多真实数据并不是聚集在一堆团块里,而是沿着一条条“山脊线”展开。比如城市道路分析、图像骨架提取、天文光谱映射、单细胞发育轨迹推断…

作者头像 李华
网站建设 2026/9/1 5:45:08

Alexa语音设备开发为何离不开参考设计?硬件、认证与量产全解析

1. 从零做语音设备到底难在哪——为什么厂商都在等参考设计 做智能硬件这些年,我见过太多团队死在同一道坎上:硬件画板两个月,声学打样一个月,结果卡在Alexa认证上折腾了半年。你说它难吗?单看每个环节都不算登天难&am…

作者头像 李华
网站建设 2026/9/1 10:17:29

蓝桥杯国赛“赢球票”博弈题解析:动态规划与区间DP实战

1. 项目概述:从“赢球票”看蓝桥杯国赛的实战思维 “赢球票”是第七届蓝桥杯软件类国赛(Java组)的一道经典题目。乍一看标题,你可能会联想到某种游戏或概率问题,但它的本质是一道考察 动态规划 和 博弈论思想 的算…

作者头像 李华
网站建设 2026/9/1 10:18:43

宝塔Linux面板配置环境 + 创建站点

一、安装----#### (1)进入宝塔官网 https://www.bt.cn/new/index.html#### (2)点击“ 立即免费安装 ”,选择 Centos安装脚本#### (3)进入 ssh 输入以下命令安装宝塔 yum install -y wget &&…

作者头像 李华