合同比较
HPDFContractCompare 比较两份已加载 PDF 文档的语义文本和行几何,对齐段落,并返回可审计的插入、删除、替换和移动记录
措辞和条款审查用这个 helper;页面、对象和渲染层面的差异请用 THPDFDocComparison
比较已加载的合同
uses HPDFDoc, HPDFTypes, HPDFContractCompare;
Options := HPDFDefaultContractCompareOptions;
Options.Granularity := ccgWord;
BeforePDF.LoadFromFile('contract-before.pdf');
AfterPDF.LoadFromFile('contract-after.pdf');
if HPDFCompareContracts(BeforePDF, AfterPDF, Options, Report, Token) then
begin
HTML := HPDFContractReviewHTML(Report, 'Services agreement review',
8388608, Token);
HPDFSaveContractAnnotatedPDF('contract-before.pdf',
'contract-before-review.pdf', Report, ccsBefore, Token);
HPDFSaveContractAnnotatedPDF('contract-after.pdf',
'contract-after-review.pdf', Report, ccsAfter, Token);
end;
返回的 HTML 用 UTF-8 保存;比较函数返回 false 时,检查 Report.Status 和 Report.Note
段落对齐与变更
- 语义行按页面、分栏、列表或标题边界以及可配置的基线间距分组,行间空白会被规范化
- 完全相同的段落先配对,正文中重复出现的相同条款保留出现顺序和次数
- 发生变化的段落按可配置的 multiset 词相似度评分匹配,与所选的差异粒度无关
- 配对段落的最长递增序列用于识别重排,插入和删除造成的普通索引位移不会被误报为移动
- 匹配后发生变化的段落用有界的 token 对齐返回插入、删除或替换记录,两侧都携带完整段落上下文
- 词模式把标点与词分开;句模式以句号、叹号或问号后接空白或段落结尾作为切分点
- 句子边界是纯词法判断,可能把缩写或编号条款标签切断,因此精确的法律措辞审查默认使用词模式
JoinPageContinuations会保守地把一页底部附近未写完的段落与下一页顶部附近的普通段落拼接起来,调用方也可以关闭这个布局启发式
页面与几何引用
PageIndex 和 ParagraphIndex 从零开始计数,CharacterStart 是空白规范化后段落内从 1 开始的 UTF-16 位置
整段插入或删除缺失的一侧,其页面与段落索引为 -1;匹配段落内部的 token 插入或删除在对侧保留零长度位置
每个矩形携带自己的页面索引,覆盖 PDF user space 中相交的一条语义行;跨页段落可以在多个页面上拥有矩形
位置描述的是行级覆盖而非精确的字符四边形,因此带批注的 PDF 可能为了几处相互独立的词变更高亮同一行
排除重复出现的页面装饰与样板文字
默认设置会排除在每个输入至少两个不同页面的顶部或底部 54 点范围内重复出现的匹配语义行,并对页边数字做规范化,让重复的页码能够互相匹配
前后两份文档各自独立过滤,正文中的重复内容无论出现多少次都仍可参与比较
Options.IgnoreRepeatedHeadersFooters := False;
Options.NormalizeMarginDigits := False;
Options.HeaderMarginPoints := 40;
Options.FooterMarginPoints := 35;
SetLength(Options.ExcludedLineTexts, 1);
Options.ExcludedLineTexts[0] :=
'The parties shall maintain an accurate register of approved subcontractors.';
ExcludedLineTexts 按空白规范化后的字面相等移除整条语义行,遵循 IgnoreCase,绝不解释正则表达式或子串模式
边距与排除项要谨慎选择,因为被排除的重复页边行里如果包含日期或其他合同文字,这些内容就不会进入措辞审查
预算与取消
| 选项 | 默认值 | 范围 |
|---|---|---|
MaxPages | 500 | 每份文档 |
MaxParagraphs | 4000 | 每份文档(排除之后) |
MaxSemanticLines | 50000 | 快照与排除之前的语义行总数 |
MaxCharacters | 2000000 | 排除之前提取的行文本总量 |
MaxTokens | 200000 | 词 token 总量(句模式下还包括句子 token) |
MaxDifferences | 10000 | 返回的记录数(含移动) |
MaxAlignmentCells | 2000000 | 变更段落 token 矩阵的累计规模 |
MaxWorkUnits | 50000000 | 提取记账与对齐工作量 |
触碰预算上限返回 ccsBudgetExceeded,被取消返回 ccsCancelled;部分发现会保留下来供诊断,并在 HTML 中标记为不完整
取消检查发生在每次页面提取之间以及库自身的对齐循环全程,底层的单页语义提取器仍是同步的
ccsInvalidInput 表示文档缺失、枚举序数非法或选项非法;ccsExtractionFailed 表示页面没有可提取文本或语义提取失败
没有可提取文本的页面要先做 OCR 或显式删除空白页才能参与比较;ccsComplete 只证明本次文本比较完成
审查产物
HPDFContractReviewHTML 返回一份独立文档,包含转义后的标题、消息、文本、完整段落上下文、变更类型和两侧来源位置,默认输出上限为 8388608 个 UTF-16 字符
输出超过配置上限时,HTML 导出器抛出 EHPDFContractCompareBudget;取消令牌触发时抛出 EHPDFOperationCancelled
HPDFSaveContractAnnotatedPDF 要求报告已完成,会加载单独的源文档,并在添加高亮和编号审查批注之前校验每个语义页面快照(含精确行几何)
源路径与输出路径必须不同;选择 ccsBefore 或 ccsAfter,需要把整段删除和插入放在一起审查时,把两个版本都导出
在 Windows 上会检查源与输出文件的文件标识,拒绝硬链接等源文件别名
PDF 导出器会禁用 AutoLaunch,保持输入文档和源文件不变,并在加载前、页面与变更之间以及保存前检查取消
这个 helper 只比较提取出的措辞和布局引用,不会推断法律含义、识别扫描文本,也不会为修订的法律效力背书
相关 API
HPDFCompareContracts · THPDFContractCompareOptions · THPDFContractCompareReport · HPDFContractReviewHTML · HPDFSaveContractAnnotatedPDF