用於文件驗證的 CEL 方言

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

在 CEL 運算式中存取實體

所有運算式都會根據名為 doc 的根變數進行評估,這個變數包含屬於文件的片語或屬性的實體。這些實體與所擷取文件的實體結構密切相關。

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

  • mention_text:擷取實體中顯示的原始擷取文字。預設為空字串。
  • normalized_value:擷取實體中出現的正規化提及文字。預設為空值。請參閱正規化一文瞭解詳情。
  • bounding_poly:特殊物件,包含文件中擷取實體位置的表示法,用於對齊檢查。預設為空值。

資料模型

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

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

葉節點實體範例

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

單一出現次數的葉節點實體

這是最基本的情況,使用 OccurrenceTypeOPTIONAL_ONCEREQUIRED_ONCE。實體會以包含三個標準屬性的物件表示。

存取這些值的範例如下: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
  }

多次出現的葉節點實體

這個情況適用於可能多次出現的葉節點實體,且具有 OccurrenceTypeOPTIONAL_MULTIPLEREQUIRED_MULTIPLE。舉例來說,在付款期限清單中,這會以「物件」表示,每個屬性會保留所有出現次數的對應「清單」值。因此,mention_textnormalized_valuebounding_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 中缺少十進位型別的問題,並考量財務和數值資料中常見的浮點數不準確問題,我們修改了數值型別 (doubleint) 的等號 (==) 和不等號 (!=) 運算子。這些運算子不再使用精確等號,而是採用以 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()

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

簽名: <list>.sum()

以下範例會加總多個委刊項的標準化值。

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

或函式

### 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 擴充程式庫。

  • 清單:提供清單操控函式:range, distinct, flatten, reverse, sort, slice。詳情請參閱「清單」。
  • 數學:提供擴充數學函式,例如 math.greatest, math.least, math.abs。詳情請參閱「數學」。

後續步驟

瞭解預先訓練的處理器