用於文件驗證的 CEL 方言

Document AI 驗證和修正功能採用通用運算式語言 (CEL),可在文件處理工作流程中彈性驗證及操控資料。Document AI 提供一組自訂函式、巨集和行為修改功能,專為文件實體資料量身打造。

存取 CEL 運算式中的實體

所有運算式都會根據名為 doc 的根變數進行評估,該變數由實體組成,這些實體是屬於文件的詞組或屬性。這些實體會嚴格遵循擷取文件的實體結構。

雖然擷取的實體包含許多屬性,但只有三個屬性可用於 CEL 評估。

  • mention_text:擷取實體中的原始擷取文字。預設為空白字串。
  • normalized_value:擷取實體中標準化的提及文字。預設值為空值。進一步瞭解正規化。
  • bounding_poly:特殊物件,包含擷取實體在文件中的位置表示法,用於對齊檢查。預設為空值。

資料模型

doc 對應中擷取實體的確切結構取決於兩個因素。首先是結構,也就是具體值 (例如數字或純文字) 或複雜物件。第二個因素是發生類型為單一或多個。詳情請參閱 OccurrenceType 的說明。

驗證資料模型的主要特徵是,系統會自動為結構定義中定義但未從文件擷取的任何實體填入預設值。這種設計可讓您略過 CEL 運算式中的大部分明確空值檢查,大幅簡化驗證運算式。您只需要明確編寫空值檢查,確保所選實體確實已擷取。

葉實體範例

以下各節說明如何存取葉實體中的實體,也就是沒有巢狀子實體的實體。葉實體會直接保留值。

出現一次的葉實體

這是最基本的情況,使用 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()

計算數值元素清單的總和。您可以在整數或雙精度浮點數清單上呼叫這個函式。請注意,系統會忽略清單中的空值。如果清單包含任何非數字元素,函式會觸發錯誤。

簽名:<list>.sum()

以下範例加總了多個委刊項的正規化值。

// Calculates the sum of all line item amounts.
doc.line_item_amounts.normalized_value.sum()

Or 函式

### or()

如果原始值不是空值,則傳回原始值;否則傳回第二個 (預設) 引數。

簽名:<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.greatest, math.least, math.abs 等擴充數學函式。詳情請參閱「數學」。

後續步驟

瞭解基準建立。