阅读文本 / Reading text
本文使用合成样本演示处理方法。代码已通过隔离环境中的示例检查;这不代表对所有真实文件或产品效果的保证。处理重要文件前,请保留原件,并按文中的边界与验收项复核。
提取结果只有一个
amount: 1200
,审校员仍得重新翻完整份文档。多保存页号和短原文片段,往往比再加一个小数位的“置信度”更有用:它让错误可以被定位,也让后续纠正有据可查。
证据对象应该能带人回到原文
下面采用从一开始的页码。若你的解析库从零开始,要在边界处转换,并在协议中注明。片段只保留与字段相关的短句,避免把整页敏感信息复制进日志、搜索索引或通知消息。
先校验形状,再校验对应关系
from jsonschema import Draft202012Validator
schema = {
"type": "object", "required": ["value", "evidence"],
"additionalProperties": False,
"properties": {
"value": {"type": "string"},
"evidence": {"type": "object", "additionalProperties": False,
"required": ["page", "quote"],
"properties": {"page": {"type": "integer", "minimum": 1},
"quote": {"type": "string", "minLength": 1}}}
}
}
v = Draft202012Validator(schema)
pages = ["Invoice total: USD 1200."]
record = {"value": "1200", "evidence": {"page": 1, "quote": "USD 1200"}}
assert v.is_valid(record)
def quote_exists(r):
if not v.is_valid(r):
return False
e = r["evidence"]
return e["page"] <= len(pages) and e["quote"] in pages[e["page"] - 1]
assert quote_exists(record)
fake = {"value": "9999", "evidence": {"page": 1, "quote": "USD 9999"}}
assert v.is_valid(fake)
assert not quote_exists(fake)
assert not quote_exists({"value": "1", "evidence": {"page": 9, "quote": "x"}})
这个合成例子故意构造了一条结构合法、证据不存在的记录。它说明 Schema 和来源比对不能互相替代。真实 PDF 可能存在断词、连字和空白差异,子串匹配只是最小演示,不能直接宣称为完整证据验证算法。
证据也要绑定文件版本
保存项
可以解决
不能保证
文件内容哈希
识别对应版本
上传者拥有文件权限
页号
缩小查找范围
页面没有重排
原文片段
快速核对文本
字段语义必然正确
坐标及坐标系
定位页面区域
OCR 结果已经准确
原文存在也可能引用错位置
一份文件里可能有多次出现的相同金额。即使片段存在,也要判断它是不是合计、税额或上期余额。进一步的验收可以检查字段标签、所在表格和邻近上下文;遇到多个候选,不应只拿第一个。
双语审校最需要可追溯性
把这类来源记录与
OmniDoc(产品入口)
的双语核对一起使用,审校可以从译文数字跳回源页确认含义。价值不在于让输出看起来更复杂,而在于让每一次纠正都能解释清楚,减少来回查找原件的时间。
参考:
JSON Schema 对象结构
。
- 1 -
更新于 2026-10-08