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 函数
### 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 扩展库。
- Lists:提供用于列表操作的函数:
range, distinct, flatten, reverse, sort, slice。如需了解详情,请参阅列表。 - Math:提供扩展的数学函数,例如
math.greatest, math.least, math.abs。如需了解详情,请参阅数学。
后续步骤
了解接地。