Ir al contenido

IDP — Ground

Tipo: idp-ground  ·  Paquete: IDP Activities v1.20.4  ·  Salida: object

Desde: v1.1.0

Coge lo que devolvió AI — Extract y busca cada valor de vuelta en el documento. De ahí salen tres cosas: la caja donde está, una confianza medida (no la que el modelo diga que tiene), y la decisión de qué campos tiene que mirar una persona. En el Designer en español aparece como IDP — Ubicar valores.

IDP — Extract ya la usa por dentro; úsala suelta si montas el pipeline a mano.

El esquema que hizo IDP — Build Schema le pidió al modelo, por cada campo, el valor, el texto literal del que sale y la línea donde aparece. Esta actividad busca ese literal entre las palabras del documento:

  • Lo encuentra → tiene caja, y la confianza es la del OCR de esas palabras.
  • No lo encuentra → el valor no se puede verificar. A revisión.

Un campo va a revisión si su confianza queda por debajo de su minConfidence, si no se pudo localizar o si el modelo no lo devolvió. Es un cálculo local: no llama a ningún servicio ni consume nada. El log resume cuántos campos se aceptaron y cuántos necesitan revisión.

ParámetroTipoPor defectoDescripción
documentDictionary—El documento de IDP — Load Document (o de IDP — Classify). Sus words son donde se localiza cada valor.
extractionDictionary | List—Lo que devolvió AI — Extract: una respuesta, o la lista de respuestas cuando la taxonomía se partió en lotes (aquí se juntan).
taxonomystring | Dictionary—La misma taxonomía con la que se construyó el esquema (ruta de .json u objeto). Su minConfidence por campo decide qué va a revisión.

Ninguno.

CampoTipoQué es
documentTypestringEl tipo de documento de la taxonomía.
needsReviewbooltrue si algún campo necesita revisión.
reviewFieldsListNombres de los campos que la necesitan.
valuesDictionaryNombre → valor. Para usar los datos directamente. Una tabla sale como lista de filas; una tabla sin filas, como lista vacía.
fieldsListUn objeto por campo, con todo el detalle.

Cada entrada de fields trae: name, type, value, valueRaw, grounded, confidence, needsReview, reason, page, x, y, width, height, rows y rowCount. reason explica en inglés por qué un campo va a revisión (por ejemplo, que el literal no aparece en el documento) y es null cuando no hace falta.

Un campo de tipo table trae sus filas en rows, y cada celda tiene exactamente la misma forma que un campo escalar — con su valor, su confianza, su caja y su motivo. En values, la tabla sale como una lista de filas limpias:

values["items"] = [
{ "descripcion": "Resma papel carta", "cantidad": 10, "valor": 185000 },
{ "descripcion": "Tóner negro", "cantidad": 2, "valor": 420000 }
]

La tabla necesita revisión si alguna de sus celdas la necesita. Si el modelo no devolvió la tabla, va a revisión; si la devolvió vacía, no.

Recorrer una tabla necesita un Foreach anidado:

Foreach items = res["fields"] itemVariable = campo
If condition = campo["type"] == "table"
Foreach items = campo["rows"] itemVariable = fila
Set Variable name = celda value = fila["valor"]
Log message = toString(celda["value"]) + " conf=" + toString(celda["confidence"])

Por qué la confianza no se le pregunta al modelo

Sección titulada «Por qué la confianza no se le pregunta al modelo»

Porque la confianza que un LLM se autoasigna no está calibrada: dice “0.95” con la misma soltura cuando acierta que cuando se lo inventa.

Aquí se mide algo comprobable: el literal está escrito en el documento o no lo está. Un valor que el modelo se inventó no aparece en ninguna parte, así que no se encuentra, así que va a revisión. Y de propina sale la caja para poder resaltarlo.

Por eso el esquema pide valueRaw aparte de value: value puede venir normalizado (2026-07-15) mientras el documento dice 15 de julio de 2026. El literal es el que ancla; el valor es el que usas.

  • Se compara ignorando espacios y mayúsculas: el OCR parte y junta palabras de forma impredecible, y dónde caen los espacios no debería invalidar un acierto. Un literal puede abarcar varias palabras y la caja las une.
  • Se conserva la puntuación: en un número de serie, un guion de más o de menos es una diferencia real que merece ir a revisión.
  • La confianza de una caja de varias palabras es la del eslabón más débil: si una palabra del número de serie se leyó regular, el número de serie se leyó regular.

Valores que se repiten — la cita por línea

Sección titulada «Valores que se repiten — la cita por línea»

Encontrar el literal prueba que existe, no que esa ocurrencia es la que dio el valor. Una fecha de emisión, una de vencimiento y una de entrega pueden ser idénticas: buscar el valor pelado casaría siempre con la primera, y la caja señalaría el dato equivocado.

La solución es no recuperar la posición a posteriori, sino que el modelo la cite al extraer. El documento le llega con cada línea numerada:

[11] Fecha de emisión: | 15/01/2024
[12] Fecha de vencimiento: | 15/01/2024
[13] Fecha de entrega: | 15/01/2024

Y por cada campo, además del valor, el modelo devuelve el número de línea de la que lo sacó. El grounding entonces no busca: va directo a la caja de esa línea, y dentro de ella acota al valor. La fecha de la línea 12 y la de la 13 dejan de colisionar porque el modelo dijo “12”, no “15/01/2024”. Es obtener la posición en el momento de leer, no adivinarla después — sin entrenar un modelo por formato.

  • El modelo cita una línea válida → la caja sale de ahí, directa y sin ambigüedad.
  • El valor no casa dentro de la línea citada (el modelo la citó regular, o el valor se normalizó) → se usa la caja de la línea entera: la línea correcta, con menos precisión.
  • El modelo no cita → se recae en buscar el literal por el texto; un valor repetido que no se puede distinguir así va a revisión, en vez de señalar uno al azar.

En una tabla, cada celda cita su propia línea, así que las filas repetidas caen cada una en su sitio sin depender del orden.

El pipeline completo a mano, para una taxonomía que cabe en un lote:

IDP — Load Document path = rutaDoc → output: doc
IDP — Build Schema taxonomy = asset("taxonomias/factura-proveedor.json") → output: esquemas
AI — Extract prompt = doc["text"]
schema = esquemas[0]
→ output: extraccion
IDP — Ground document = doc
extraction = extraccion
taxonomy = asset("taxonomias/factura-proveedor.json")
→ output: res
If condition = res["needsReview"]
Queue Add Item ...a la cola de validación humana

Recorrer los campos para pintar las cajas encima de la página renderizada:

Foreach items = res["fields"] itemVariable = campo
Log message = campo["name"] + " = " + toString(campo["value"]) + " (conf " + toString(campo["confidence"]) + ")"

Usar un valor concreto — hace falta un salto porque el motor no encadena índices:

Set Variable name = vals value = res["values"]
Log message = "Factura: " + toString(vals["numero"])
MensajeCausa y solución
'document' debe ser el objeto que devuelve IDP Load Document.document no es un objeto (por ejemplo, pasaste la ruta).
'document' no tiene 'words'. Pasa el objeto que devuelve IDP Load Document.El objeto no trae las palabras con posición.
'extraction' debe ser lo que devolvió AI Extract: una respuesta, o la lista de respuestas cuando la taxonomía se dividió en lotes.extraction no es un objeto ni una lista de objetos.
'taxonomy' es obligatorio. / La taxonomía debe declarar un 'documentType'. / …La taxonomía no es válida. Ver los errores de IDP — Build Schema.