Document AI 验证和更正功能利用通用表达式语言 (CEL),可在文档处理工作流中灵活地验证和处理数据。Document AI 提供了一组针对文档实体数据量身定制的自定义函数、宏和行为修改。
在 CEL 表达式中访问实体
所有表达式都针对名为 doc 的根变量进行评估,该变量由属于文档的短语或属性组成的实体构成。这些实体与提取的文档的实体结构密切相关。
虽然提取的实体包含许多属性,但只有三个属性可用于 CEL 评估。
mention_text:提取的实体中显示的原始提取文本。默认值为空字符串。normalized_value:提取的实体中显示的标准化提及文本。默认值为 null。如需详细了解,请参阅标准化。bounding_poly:一种特殊对象,包含提取的实体在文档中的位置表示形式,用于进行对齐检查。默认值为 null。
数据模型
doc 映射中提取实体的确切结构取决于两个因素。第一种是其结构是具体值(例如数字或纯文本),还是复杂对象。第二个因素是其出现类型是单次还是多次。如需了解详情,请参阅 OccurrenceType。
验证数据模型的一项关键功能是,架构中定义的任何实体(但未从文档中提取)都会自动填充默认值。这种设计可让您在 CEL 表达式中跳过大多数显式 null 检查,从而显著简化验证表达式。您只需明确编写 null 检查,以确保所选实体确实已提取。
叶实体示例
以下部分介绍了如何访问叶实体(即没有嵌套子实体的实体)中的实体。叶实体直接保存值。
仅出现一次的叶实体
这是最基本的情况,使用 OPTIONAL_ONCE 或 REQUIRED_ONCE 的 OccurrenceType。实体表示为一个包含三个标准属性的对象。
访问这些值的示例为 doc.invoice_date.normalized_value。
其结构如下:
"invoice_date": {
"mention_text": "1",
"normalized_value": 1.0,
"bounding_poly": bounding_poly_object
}
默认值:
"invoice_date": {
"mention_text": "",
"normalized_value": null,
"bounding_poly": null
}
多次出现的叶实体
这种情况适用于可多次出现且 OccurrenceType 为 OPTIONAL_MULTIPLE 或 REQUIRED_MULTIPLE 的叶实体。例如,在付款截止日期列表中,它表示为一个对象,其中每个属性都包含所有出现次数的相应值的列表。因此,mention_text、normalized_value 和 bounding_poly 等属性可能具有多个实体。
访问这些值的示例为 doc.payment_due_dates.normalized_value[0]。
其结构如下:
"payment_due_dates": {
"mention_text": ["Mar 1, 2024", "Apr 1, 2024"],
"normalized_value": [null, proto.timestamp(2024-04-01)],
// Note: If a value is not normalized, it is stored as a null.
"bounding_poly": [bounding_poly_object,bounding_poly_object]
}
默认值:
"payment_due_dates": {
"mention_text": [],
"normalized_value": []
"bounding_poly": []
}
嵌套实体
嵌套实体是其他实体(即其“子实体”)的容器。
出现一次的嵌套实体
如果嵌套实体仅出现一次(例如单个 receiver_address),则表示为对象,其中键是其子实体的名称。
访问这些值的示例为 doc.receiver_address.city.mention_text。
其结构如下:
"receiver_address": {
"street": {
"mention_text": "123 Main St",
"normalized_value": "123 Main St",
"bounding_poly": bounding_poly_object
}
}
默认值:
"receiver_address": {
"street": {
"mention_text": "",
"normalized_value": null,
"bounding_poly": null
}
}
多次出现的嵌套实体
如果嵌套实体可以多次出现,则表示为对象列表。列表中的每个对象都表示嵌套实体的完整实例,并包含其子级。
访问这些值的示例为 doc.line_items[1].description.normalized_value。
其结构如下:
"line_items": [
{
"description": { "mention_text": "Product A", ... },
"quantity": { "mention_text": "2", ... }
},
{
"description": { "mention_text": "Service B", ... },
"quantity": { "mention_text": "5", ... }
}
]
默认值:
"line_items": []
归一化值转换表
下表显示了所选架构实体数据类型如何转换为 CEL normalized_value 数据类型。
| 架构数据类型 | CEL 数据类型 |
|---|---|
| 币种、地址 | string |
| 数字、金额 | double |
| 日期时间 | proto.Timestamp |
| 复选框,签名 | bool
|
| 纯文本 | 不适用 |
表达式示例
以下是一些 CEL 表达式示例。
// Leaf entity with a single occurrence: Get the invoice ID string
doc.invoice_id.normalized_value == "INV-12345"
// Leaf entity with multiple occurrences: Get the first payment term from the list
doc.payments.mention_text[0].matches('^\d+$')
// Nested entity with one occurrence: Access a child entity of a single nested entity
doc.receiver_address.name.normalized_value.star
tsWith("John")
// Nested entity with multiple occurrences: Access a child of a specific item in a list of nested entities
doc.line_items[1].description.normalized_value == "Premium Gadget"
// Advanced: Sum the total of all line items
doc.line_items.map(item, item.total.normalized_value).sum() == 275.0
// Advanced: Check if any line item has a quantity greater than 1
doc.line_items.exists(item, item.quantity.normalized_value > 1.0)
以下是您可以使用的其他 CEL 逻辑示例。
// Ensure due date is after invoice date
doc.due_date.normalized_value > doc.invoice_date.normalized_value
// Cross list validation: ensure that each employer_contribution
// has a corresponding employee deduction
doc.employer_contribution.size() == doc.employee_deduction.size() && lists.range(doc.employer_contribution.size()).all(i,doc.employee_deduction[i].current_amount.mention_text != "" && doc.employer_contribution[i].current_amount.mention_text != "")
行为变更
Document AI 的 CEL 方言修改了一些标准行为,以更好地适应文档处理使用情形。
基于 epsilon 的相等性
为了解决 CEL 中缺少小数类型的问题,并考虑到财务和数值数据中常见的浮点不精确性,我们针对数值类型(double、int)修改了等值 (==) 和不等值 (!=) 运算符。这些运算符不再使用精确等值,而是使用基于 epsilon 的比较,容差为 1e-2 (0.01)。
例如,假设某个 total_amount 的归一化值为 100.005。
对于表达式 doc.total_amount.normalized_value == 100.0,结果为 true。这是因为 abs(100.005 - 100.0) 小于 0.01。标准 CEL 会返回 false。
对于表达式 doc.total_amount.normalized_value == 100.02,结果为 false。这是因为 abs(100.005 - 100.02) 大于 0.01。
字符串函数限制
标准 CEL 字符串操作函数只能对实体的 mention_text 属性进行操作。此限制可确保验证规则始终应用于文档中显示的字面文本字符串。
受影响的函数包括:
contains()endsWith()startsWith()matches()
以下是一个有效示例:
// Checks if the extracted currency symbol is a dollar sign.
doc.total_amount.mention_text.startsWith("$")
以下是无效命令的示例:
// This will produce a validation error upon save because contains() is not
// being used on a .mention_text field.
doc.supplier_name.normalized_value.contains("Inc.")
其他功能
本部分介绍了 Document AI CEL 评估环境中提供的非标准全局函数和成员函数。
求和函数
### sum()
计算数值元素列表的总和。它可以针对整数或双精度浮点数列表调用。请注意,系统会忽略列表中的 null 值。如果列表包含任何非数字元素,该函数将触发错误。
签名: <list>.sum()
以下示例展示了如何汇总多个订单项的归一化价值。
// Calculates the sum of all line item amounts.
doc.line_item_amounts.normalized_value.sum()
OR 函数
### or()
如果原始值不为 null,则返回原始值;否则,返回第二个(默认)实参。
签名: <value>.or(<;default_value>)
例如,您可以使用它在可选字段可能缺失时提供默认值。
// If the tax amount is not found, use a default of 0.0 for calculation.
doc.tax_amount.normalized_value.or(0.0) > 5.0
检查列表垂直对齐函数
### checkVerticalAlignment()
如果所有 bounding_poly 对象在容差指定的范围内垂直对齐,则返回 true。否则,返回一条错误消息,说明哪些实体的对齐不正确。
容差是一个可选实参,用于指定边界多边形与自动选择的最佳对齐边界多边形的重叠程度,0 表示边界多边形不相交,1 表示边界多边形完全相同。
签名: checkVerticalAlignment([<;bounding_poly>,...],tolerance=0.8)
例如,您可以使用此参数来帮助将所有提取的实体保留在单个列中。
// Make sure that all extracted quantities are in the same column
checkVerticalAlignment(doc.line_items.map(li,li.quantity.bounding_poly))
检查水平对齐函数
### checkHorizontalAlignment()
如果所有 bounding_poly 对象在水平方向上对齐到容差指定的程度,则返回 true。否则,返回一条错误消息,说明哪些实体未对齐。
容差是一个可选实参,用于指定边界多边形与自动选择的最佳对齐边界多边形的重叠程度。0 表示边界多边形不相交,1 表示边界多边形完全相同。
签名: checkHorizontalAlignment([<;bounding_poly>,...],tolerance=0.6)
例如,您可以使用此参数来帮助将所有提取的实体保留在同一行中。
// For all line items make sure that each extracted line item's
// children are in the same row. For example, if line item has
// quantity and description properties, it makes sure they are in
// a single row for each respective line item.
doc.line_items.all(li, checkHorizontalAlignment(li.map(col,li[col].bounding_poly)))
其他宏
本部分介绍了 Document AI CEL 评估环境中提供的非标准宏。
如需详细了解宏,请参阅语言定义:宏。
减少宏
### reduce()
使用 reduce 宏对列表执行累积运算。
签名: <list>.reduce(<;iterator_name>, <;accumulator_name>, <;initial_value>, <;loop_expression>)
iterator_name:每次迭代中正在处理的元素的变量名称。accumulator_name:用于累积结果的值的变量名称。initial_value:累加器的初始值。loop_expression:一种表达式,用于定义在每个步骤中如何更新累加器。
以下是宏使用示例:
// Use reduce to sum up the quantities from all line items.
doc.line_items.reduce(item, running_total, 0.0, running_total + item.quantity.normalized_value)
// Result: 3.0
// Tip: this could also be done by concatenating map and sum:
doc.line_items.map(item,item.quantity.normalized_value).sum()
CEL 扩展库
除了自定义功能之外,以下标准 CEL 扩展库也可供使用。
- 列表:提供用于列表操作的函数:
range, distinct, flatten, reverse, sort, slice。如需了解详情,请参阅列表。 - 数学:提供扩展的数学函数,例如
math.greatest, math.least, math.abs。如需了解详情,请参阅数学。
后续步骤
了解预训练的处理器。