A validação e correção da Document AI usam a Common Expression Language (CEL) para permitir a validação e manipulação flexíveis de dados nos fluxos de trabalho de processamento de documentos. A Document AI oferece um conjunto de funções personalizadas, macros e modificações comportamentais adaptadas para dados de entidades de documentos.
Acessar entidades em uma expressão CEL
Todas as expressões são avaliadas em relação a uma variável raiz chamada doc, que consiste em entidades, que são frases ou propriedades pertencentes ao documento. Essas entidades seguem de perto a estrutura das entidades do documento extraído.
Embora uma entidade extraída contenha muitas propriedades, apenas três delas estão disponíveis para avaliação da CEL.
mention_text: texto extraído bruto, como presente em uma entidade extraída. O padrão é uma string vazia.normalized_value: texto de menção normalizado, conforme presente em uma entidade extraída. O padrão é nulo. Leia mais sobre normalização.bounding_poly: um objeto especial que contém uma representação do posicionamento da entidade extraída no documento e usado para verificações de alinhamento. O padrão é nulo.
Modelo de dados
A estrutura exata de uma entidade extraída no mapa doc depende de dois fatores. O primeiro é se a estrutura é um valor concreto, como um número ou texto simples, ou se é um objeto complexo. O segundo fator é se o tipo de ocorrência é único ou múltiplo. Para mais informações, consulte OccurrenceType.
Um recurso principal do modelo de dados de validação é que qualquer entidade definida no esquema, mas não extraída do documento, é preenchida automaticamente com valores padrão. Esse design permite pular a maioria das verificações de nulo explícitas nas expressões CEL, simplificando significativamente as expressões de validação. Você só precisa escrever explicitamente verificações de nulo para garantir que uma entidade selecionada foi extraída.
Exemplos de entidades folha
As seções a seguir descrevem como acessar as entidades em uma entidade folha, que é uma sem entidades filhas aninhadas. As entidades folha contêm um valor diretamente.
Entidade folha com uma única ocorrência
Esse é o caso mais básico, usando OccurrenceType de OPTIONAL_ONCE ou REQUIRED_ONCE. A entidade é representada como um objeto que contém as três propriedades padrão.
Um exemplo de como acessar esses valores é doc.invoice_date.normalized_value.
Ele tem a seguinte estrutura:
"invoice_date": {
"mention_text": "1",
"normalized_value": 1.0,
"bounding_poly": bounding_poly_object
}
E o valor padrão:
"invoice_date": {
"mention_text": "",
"normalized_value": null,
"bounding_poly": null
}
Entidade folha com várias ocorrências
Esse caso se aplica a entidades folha que podem ocorrer várias vezes e ter um OccurrenceType de OPTIONAL_MULTIPLE ou REQUIRED_MULTIPLE. Por exemplo, em uma lista de datas de vencimento de pagamento, ela é representada como um objeto em que cada propriedade contém uma lista dos valores correspondentes de todas as ocorrências. Assim, propriedades como mention_text, normalized_value e bounding_poly podem ter várias entidades.
Um exemplo de como acessar esses valores é doc.payment_due_dates.normalized_value[0].
Ele tem a seguinte estrutura:
"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 o valor padrão:
"payment_due_dates": {
"mention_text": [],
"normalized_value": []
"bounding_poly": []
}
Entidades aninhadas
Uma entidade aninhada é um contêiner para outras entidades, que são seus "filhos".
Entidade aninhada com uma ocorrência
Se uma entidade aninhada ocorrer apenas uma vez, por exemplo, um único receiver_address, ela será representada como um objeto em que as chaves são os nomes das entidades filhas.
Um exemplo de como acessar esses valores é doc.receiver_address.city.mention_text.
Ele tem a seguinte estrutura:
"receiver_address": {
"street": {
"mention_text": "123 Main St",
"normalized_value": "123 Main St",
"bounding_poly": bounding_poly_object
}
}
E o valor padrão:
"receiver_address": {
"street": {
"mention_text": "",
"normalized_value": null,
"bounding_poly": null
}
}
Entidade aninhada com várias ocorrências
Quando uma entidade aninhada pode ocorrer várias vezes, ela é representada como uma lista de objetos. Cada objeto na lista representa uma instância completa da entidade aninhada e contém os filhos dela.
Um exemplo de como acessar esses valores é doc.line_items[1].description.normalized_value.
Ele tem a seguinte estrutura:
"line_items": [
{
"description": { "mention_text": "Product A", ... },
"quantity": { "mention_text": "2", ... }
},
{
"description": { "mention_text": "Service B", ... },
"quantity": { "mention_text": "5", ... }
}
]
E o valor padrão:
"line_items": []
Tabela de conversão de valor normalizado
Esta tabela mostra como o tipo de dados da entidade de esquema selecionada é traduzido para o tipo de dados normalized_value da CEL.
| Tipo de dados do esquema | Tipo de dados da CEL |
|---|---|
| Moeda, endereço | string |
| Number, Money | double |
| Data/hora | proto.Timestamp |
| Caixa de seleção, Assinatura | bool
|
| Texto simples | N/A |
Exemplos de expressões
Confira alguns exemplos de expressões 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)
Confira outros exemplos de lógica CEL que você pode usar.
// 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 != "")
Mudanças no comportamento
O dialeto CEL da Document AI modifica alguns comportamentos padrão para se adequar melhor aos casos de uso de processamento de documentos.
Igualdade baseada em épsilon
Para resolver a falta de um tipo decimal na CEL e considerar imprecisões comuns de ponto flutuante em dados financeiros e numéricos, os operadores de igualdade (==) e desigualdade (!=) são modificados para tipos numéricos (double, int). Em vez de igualdade exata, eles usam uma comparação baseada em epsilon com uma tolerância de 1e-2 (0,01).
Por exemplo, considere um total_amount com um valor normalizado de 100.005.
Com a expressão doc.total_amount.normalized_value == 100.0, o resultado é true porque abs(100.005 - 100.0) é menor que 0.01. A CEL padrão retornaria false.
Para a expressão doc.total_amount.normalized_value == 100.02, o resultado é false. Isso acontece porque abs(100.005 - 100.02) é maior que 0.01.
Restrições da função de string
As funções padrão de manipulação de strings da CEL só podem operar na propriedade mention_text de uma entidade. Essa restrição garante que as regras de validação sejam aplicadas de maneira consistente à string de texto literal conforme ela aparece no documento.
As funções afetadas são:
contains()endsWith()startsWith()matches()
Confira um exemplo válido:
// Checks if the extracted currency symbol is a dollar sign.
doc.total_amount.mention_text.startsWith("$")
Confira um exemplo de comando inválido:
// 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.")
Outras funções
Esta seção descreve funções globais e de membro não padrão disponíveis no ambiente de avaliação da CEL da Document AI.
Função de soma
### sum()
Calcula a soma de uma lista de elementos numéricos. Ele pode ser chamado em listas de números inteiros ou de ponto flutuante. Valores nulos na lista são ignorados. Se a lista contiver elementos não numéricos, a função vai gerar um erro.
Assinatura: <list>.sum()
Confira um exemplo que soma o valor normalizado de vários itens de linha.
// Calculates the sum of all line item amounts.
doc.line_item_amounts.normalized_value.sum()
Função OR
### or()
Retorna o valor original se ele não for nulo. Caso contrário, retorna o segundo argumento (padrão).
Assinatura: <value>.or(<;default_value>)
Por exemplo, é possível usar esse recurso para fornecer um valor padrão quando um campo opcional estiver faltando.
// 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
Verificar a função de alinhamento vertical da lista
### checkVerticalAlignment()
Retorna true se todos os objetos bounding_poly estiverem alinhados verticalmente a um grau especificado pela tolerância. Caso contrário, retorna um erro descrevendo quais entidades estão desalinhadas.
A tolerância é um argumento opcional que especifica a sobreposição de um polígono delimitador com o melhor polígono delimitador alinhado selecionado automaticamente. "0" significa que os polígonos delimitadores não se cruzam, e "1" significa que eles são idênticos.
Assinatura: checkVerticalAlignment([<;bounding_poly>,...],tolerance=0.8)
Por exemplo, você pode usar isso para manter todas as entidades extraídas em uma única coluna.
// Make sure that all extracted quantities are in the same column
checkVerticalAlignment(doc.line_items.map(li,li.quantity.bounding_poly))
Verificar a função de alinhamento horizontal
### checkHorizontalAlignment()
Retorna true se todos os objetos bounding_poly estiverem alinhados horizontalmente a um grau especificado pela tolerância. Caso contrário, retorna um erro descrevendo quais entidades estão desalinhadas.
A tolerância é um argumento opcional que especifica a sobreposição de um polígono delimitador com o melhor polígono delimitador alinhado selecionado automaticamente. O significado de 0 é que os polígonos delimitadores não se cruzam, e 1 significa que eles são idênticos.
Assinatura: checkHorizontalAlignment([<;bounding_poly>,...],tolerance=0.6)
Por exemplo, você pode usar isso para manter todas as entidades extraídas em uma única linha.
// 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)))
Outras macros
Esta seção descreve as macros não padrão disponíveis no ambiente de avaliação da CEL da Document AI.
Para mais informações sobre macros, consulte Definição de linguagem: macros.
Reduzir macro
### reduce()
Use a macro reduce para realizar operações cumulativas em uma lista.
Assinatura: <list>.reduce(<;iterator_name>, <;accumulator_name>, <;initial_value>, <;loop_expression>)
iterator_name: um nome de variável para o elemento que está sendo processado em cada iteração.accumulator_name: um nome de variável para o valor que acumula o resultado.initial_value: o valor inicial do acumulador.loop_expression: uma expressão que define como o acumulador é atualizado em cada etapa.
Confira um exemplo de uso de 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()
Bibliotecas de extensão CEL
Além dos recursos personalizados, as seguintes bibliotecas de extensão CEL padrão estão disponíveis.
- Listas: oferece funções para manipulação de listas:
range, distinct, flatten, reverse, sort, slice. Para mais informações, consulte Listas. - Matemática: oferece funções matemáticas estendidas, como
math.greatest, math.least, math.abs. Para mais informações, consulte Matemática.
A seguir
Saiba mais sobre processadores pré-treinados.