La convalida e la correzione di Document AI sfruttano il Common Expression Language (CEL) per consentire la manipolazione e la convalida flessibili dei dati all'interno dei workflow di elaborazione dei documenti. Document AI offre un insieme di funzioni personalizzate, macro e modifiche comportamentali personalizzate per i dati delle entità dei documenti.
Accedere alle entità nell'espressione CEL
Tutte le espressioni vengono valutate in base a una variabile radice denominata doc, che è costituita da entità che sono frasi o proprietà appartenenti al documento. Queste entità seguono da vicino la struttura delle entità del documento estratto.
Sebbene un'entità estratta contenga molte proprietà, solo tre sono disponibili per la valutazione CEL.
mention_text: testo estratto non elaborato presente in un'entità estratta. Il valore predefinito è una stringa vuota.normalized_value: testo della menzione normalizzato presente in un'entità estratta. Il valore predefinito è null. Scopri di più sulla normalizzazione.bounding_poly: un oggetto speciale contenente una rappresentazione del posizionamento dell'entità estratta nel documento e utilizzato per i controlli di allineamento. Il valore predefinito è null.
Modello dei dati
La struttura esatta di un'entità estratta all'interno della mappa doc dipende da due fattori. Il primo è se la sua struttura è un valore concreto, ad esempio un numero
o un testo normale, o se è un oggetto complesso. Il secondo fattore è se il tipo di occorrenza è singolo o multiplo. Per saperne di più, consulta OccurrenceType.
Una caratteristica fondamentale del modello dei dati di convalida è che qualsiasi entità definita nello schema, ma non estratta dal documento, viene compilata automaticamente con i valori predefiniti. Questo design ti consente di saltare la maggior parte dei controlli null espliciti nelle espressioni CEL, semplificando notevolmente le espressioni di convalida. Devi solo scrivere esplicitamente i controlli null per assicurarti che un'entità selezionata sia stata estratta.
Esempi di casi di entità foglia
Le sezioni seguenti descrivono come accedere alle entità in un'entità foglia, ovvero un'entità senza entità secondarie nidificate. Le entità foglia contengono direttamente un valore.
Entità foglia con una singola occorrenza
Questo è il caso più semplice, in cui si utilizza OccurrenceType di OPTIONAL_ONCE o
REQUIRED_ONCE. L'entità è rappresentata come un oggetto contenente le tre
proprietà standard.
Un esempio di come accedere a questi valori è doc.invoice_date.normalized_value.
Ha la struttura:
"invoice_date": {
"mention_text": "1",
"normalized_value": 1.0,
"bounding_poly": bounding_poly_object
}
E il valore predefinito:
"invoice_date": {
"mention_text": "",
"normalized_value": null,
"bounding_poly": null
}
Entità foglia con più occorrenze
Questo caso si applica alle entità foglia che possono verificarsi più volte e hanno un
OccurrenceType di OPTIONAL_MULTIPLE o REQUIRED_MULTIPLE. Ad esempio, in un
elenco di date di scadenza dei pagamenti, è rappresentato come un oggetto in cui ogni proprietà
contiene un elenco dei valori corrispondenti di tutte le occorrenze. Pertanto, proprietà
come mention_text, normalized_value e bounding_poly potrebbero avere più
entità.
Un esempio di come accedere a questi valori è doc.payment_due_dates.normalized_value[0].
Ha la struttura:
"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]
}
E il valore predefinito:
"payment_due_dates": {
"mention_text": [],
"normalized_value": []
"bounding_poly": []
}
Entità nidificate
Un'entità nidificata è un contenitore per altre entità, che sono i suoi "elementi secondari".
Entità nidificata con una occorrenza
Se un'entità nidificata si verifica una sola volta, ad esempio un singolo receiver_address,
viene rappresentata come un oggetto in cui le chiavi sono i nomi delle entità secondarie.
Un esempio di come accedere a questi valori è doc.receiver_address.city.mention_text.
Ha la struttura:
"receiver_address": {
"street": {
"mention_text": "123 Main St",
"normalized_value": "123 Main St",
"bounding_poly": bounding_poly_object
}
}
E il valore predefinito:
"receiver_address": {
"street": {
"mention_text": "",
"normalized_value": null,
"bounding_poly": null
}
}
Entità nidificata con più occorrenze
Quando un'entità nidificata può verificarsi più volte, viene rappresentata come un elenco di oggetti. Ogni oggetto dell'elenco rappresenta un'istanza completa dell'entità nidificata e contiene i relativi elementi secondari.
Un esempio di come accedere a questi valori è doc.line_items[1].description.normalized_value.
Ha la struttura:
"line_items": [
{
"description": { "mention_text": "Product A", ... },
"quantity": { "mention_text": "2", ... }
},
{
"description": { "mention_text": "Service B", ... },
"quantity": { "mention_text": "5", ... }
}
]
E il valore predefinito:
"line_items": []
Tabella di conversione del valore normalizzato
Questa tabella mostra come il tipo di dati dell'entità dello schema selezionato viene convertito nel tipo di dati CEL
normalized_value.
| Tipo di dati dello schema | Tipo di dati CEL |
|---|---|
| Valuta, indirizzo | string |
| Numero, Denaro | double |
| Data/ora | proto.Timestamp |
| Casella di controllo, Firma | bool
|
| Testo normale | N/D |
Espressioni di esempio
Ecco alcune espressioni CEL di esempio.
// 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)
Ecco altri esempi di logica CEL che puoi utilizzare.
// 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 != "")
Modifiche al comportamento
Il dialetto CEL di Document AI modifica alcuni comportamenti standard per adattarsi meglio ai casi d'uso di elaborazione dei documenti.
Eguaglianza basata su epsilon
Per risolvere il problema della mancanza del tipo decimale in CEL e tenere conto delle comuni imprecisioni in virgola mobile nei dati finanziari e numerici, gli operatori di uguaglianza (==) e disuguaglianza (!=) vengono modificati per i tipi numerici (double, int). Invece dell'uguaglianza esatta, utilizzano un confronto basato su epsilon con una tolleranza di 1e-2 (0,01).
Ad esempio, considera un total_amount con un valore normalizzato di 100.005.
Con l'espressione doc.total_amount.normalized_value == 100.0, il risultato è
true. Questo perché abs(100.005 - 100.0) è inferiore a 0.01. L'espressione CEL standard
restituirebbe false.
Per l'espressione doc.total_amount.normalized_value == 100.02 il risultato è
false. Questo perché abs(100.005 - 100.02) è maggiore di 0.01.
Limitazioni delle funzioni di stringa
Le funzioni standard di manipolazione delle stringhe CEL sono limitate al funzionamento solo sulla proprietà mention_text di un'entità. Questa limitazione garantisce che le regole di convalida
vengano applicate in modo coerente alla stringa di testo letterale così come appare nel
documento.
Le funzioni interessate sono:
contains()endsWith()startsWith()matches()
Ecco un esempio valido:
// Checks if the extracted currency symbol is a dollar sign.
doc.total_amount.mention_text.startsWith("$")
Ecco un esempio di comando non valido:
// 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.")
Funzioni aggiuntive
Questa sezione descrive le funzioni globali e membro non standard disponibili nell'ambiente di valutazione CEL di Document AI.
Funzione Somma
### sum()
Calcola la somma di un elenco di elementi numerici. Può essere chiamato su elenchi di numeri interi o doppi. Tieni presente che i valori null nell'elenco vengono ignorati. Se l'elenco contiene elementi non numerici, la funzione attiverà un errore.
Firma: <list>.sum()
Ecco un esempio che riassume il valore normalizzato di diversi elementi pubblicitari.
// Calculates the sum of all line item amounts.
doc.line_item_amounts.normalized_value.sum()
Funzione OR
### or()
Restituisce il valore originale se non è nullo; altrimenti, restituisce il secondo argomento (predefinito).
Firma: <value>.or(<;default_value>)
Ad esempio, puoi utilizzarlo per fornire un valore predefinito quando un campo facoltativo potrebbe essere mancante.
// 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
Controllare la funzione di allineamento verticale dell'elenco
### checkVerticalAlignment()
Restituisce true se tutti gli oggetti bounding_poly sono allineati verticalmente a un grado specificato dalla tolleranza. In caso contrario, restituisce un errore che descrive quali
entità non sono allineate.
La tolleranza è un argomento facoltativo che specifica la sovrapposizione di un bounding poly con il bounding poly con il migliore allineamento selezionato automaticamente. Il valore 0 indica che i bounding poly non si intersecano, mentre il valore 1 indica che i bounding poly sono identici.
Firma: checkVerticalAlignment([<;bounding_poly>,...],tolerance=0.8)
Ad esempio, puoi utilizzare questa opzione per mantenere tutte le entità estratte all'interno di una singola colonna.
// Make sure that all extracted quantities are in the same column
checkVerticalAlignment(doc.line_items.map(li,li.quantity.bounding_poly))
Controlla la funzione di allineamento orizzontale
### checkHorizontalAlignment()
Restituisce true se tutti gli oggetti bounding_poly sono allineati orizzontalmente a un grado specificato dalla tolleranza. In caso contrario, restituisce un errore che descrive quali
entità non sono allineate.
La tolleranza è un argomento facoltativo che specifica la sovrapposizione di un bounding poly con il bounding poly con il miglior allineamento selezionato automaticamente. Il significato di 0 è che i poligoni di delimitazione non si intersecano, mentre 1 significa che sono identici.
Firma: checkHorizontalAlignment([<;bounding_poly>,...],tolerance=0.6)
Ad esempio, puoi utilizzarlo per mantenere tutte le entità estratte all'interno di una singola riga.
// 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)))
Macro aggiuntive
Questa sezione descrive le macro non standard disponibili nell'ambiente di valutazione CEL di Document AI.
Per saperne di più sulle macro, consulta Definizione del linguaggio: macro.
Riduci macro
### reduce()
Utilizza la macro reduce per eseguire operazioni cumulative su un elenco.
Firma: <list>.reduce(<;iterator_name>, <;accumulator_name>, <;initial_value>, <;loop_expression>)
iterator_name: il nome di una variabile per l'elemento in fase di elaborazione in ogni iterazione.accumulator_name: il nome di una variabile per il valore che accumula il risultato.initial_value: il valore iniziale dell'accumulatore.loop_expression: un'espressione che definisce come viene aggiornato l'accumulatore in ogni passaggio.
Ecco un esempio di utilizzo delle macro:
// 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()
Librerie di estensioni CEL
Oltre alle funzionalità personalizzate, sono disponibili le seguenti librerie di estensioni CEL standard.
- Elenchi: fornisce funzioni per la manipolazione degli elenchi:
range, distinct, flatten, reverse, sort, slice. Per saperne di più, consulta Elenchi. - Matematica: fornisce funzioni matematiche estese come
math.greatest, math.least, math.abs. Per saperne di più, consulta Matematica.
Passaggi successivi
Scopri di più sui processori preaddestrati.