Donut para boletas peruanas

Modelo experimental de extracción estructurada, sin OCR explícito, para imágenes de boletas peruanas. Es una adaptación de bajo recurso de naver-clova-ix/donut-base-finetuned-cord-v2, no un modelo entrenado desde cero.

El modelo recibe una imagen completa y genera una representación que DonutProcessor.token2json convierte al siguiente esquema:

{
  "empresa": "",
  "ruc": "",
  "fecha": "",
  "nro_comprobante": "",
  "menu": [
    {
      "nm": "",
      "price": ""
    }
  ],
  "sub_total": "",
  "igv": "",
  "total": ""
}

Uso previsto

Este checkpoint está pensado para investigación, demostraciones y prototipos supervisados sobre boletas impresas peruanas en español. Puede servir como punto de partida para nuevas evaluaciones o fine-tuning con datos propios.

No debe utilizarse sin revisión humana para contabilidad, tributación, auditoría, pagos, cumplimiento normativo ni otras decisiones de alto impacto. Tampoco es un extractor universal de comprobantes: no fue validado para facturas, documentos manuscritos, documentos de otros países o imágenes fuera del dominio de entrenamiento.

Uso con Transformers

El checkpoint fue exportado con transformers==5.12.1 y se verificó localmente con transformers==5.15.0. Se recomienda cargar el modelo directamente en lugar de usar pipeline, porque requiere el prompt de tarea específico.

pip install "transformers==5.15.0" "torch>=2.4,<3" "pillow>=10"
from PIL import Image
import torch
from transformers import DonutProcessor, VisionEncoderDecoderModel

model_id = "eng-aesr/donut-boletas-peru"
task_prompt = "<s_receipt_peru>"

processor = DonutProcessor.from_pretrained(model_id)
model = VisionEncoderDecoderModel.from_pretrained(model_id)

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device).eval()

image = Image.open("boleta.jpg").convert("RGB")
pixel_values = processor(image, return_tensors="pt").pixel_values.to(device)
decoder_input_ids = processor.tokenizer(
    task_prompt,
    add_special_tokens=False,
    return_tensors="pt",
).input_ids.to(device)

generation_config = model.generation_config
generation_config.max_length = 768
generation_config.num_beams = 1
generation_config.pad_token_id = processor.tokenizer.pad_token_id
generation_config.eos_token_id = processor.tokenizer.eos_token_id

unk_token_id = processor.tokenizer.unk_token_id
bad_words_ids = [[unk_token_id]] if unk_token_id is not None else None

with torch.inference_mode():
    output_ids = model.generate(
        pixel_values,
        decoder_input_ids=decoder_input_ids,
        generation_config=generation_config,
        bad_words_ids=bad_words_ids,
    )

sequence = processor.batch_decode(output_ids, skip_special_tokens=False)[0]
for token in (
    task_prompt,
    processor.tokenizer.eos_token,
    processor.tokenizer.pad_token,
):
    if token:
        sequence = sequence.replace(token, "")

result = processor.token2json(sequence.strip())
print(result)

Nunca envíes documentos sensibles a servicios de terceros sin una base legal y controles de privacidad adecuados. Para documentos confidenciales, ejecuta el modelo en infraestructura controlada.

Detalles del modelo

Propiedad Valor
Arquitectura VisionEncoderDecoderModel (encoder Donut-Swin + decoder mBART)
Checkpoint base inmediato naver-clova-ix/donut-base-finetuned-cord-v2
Parámetros 201,133,176
Prompt de tarea <s_receipt_peru>
Resolución del procesador 1280 × 960 píxeles
Longitud máxima de generación 768 tokens
Formato de pesos SafeTensors
SHA-256 de los pesos 27330e48fda6bf3f4ac117b28afc2ae354a039dbae179eb29bfc72b829ea960a

Datos y entrenamiento

La adaptación utilizó un dataset privado de 140 boletas peruanas anotadas. El dataset y sus imágenes no se distribuyen con este modelo.

El checkpoint base inmediato ya había sido ajustado sobre CORD v2 por sus autores upstream. La etapa descrita aquí corresponde únicamente a la adaptación posterior al dominio peruano.

  • Entrenamiento: 100 documentos originales. Se aplicaron tres variantes visuales suaves únicamente a este split (blur, noise y rotate), dando 400 registros de entrenamiento pero conservando 100 fuentes independientes.
  • Validación: 20 documentos reales, sin augmentation; se usaron para seleccionar el checkpoint.
  • Test: 20 documentos reales, sin augmentation y sin uso durante la selección.
  • Split: por identificador de documento (source_id), no por empresa o plantilla visual.

Configuración principal de fine-tuning:

Hiperparámetro Valor
Learning rate 1e-5
Batch size por dispositivo 2
Gradient accumulation 1
Gradient clipping 1.0
Épocas máximas 30
Épocas ejecutadas 10
Early stopping paciencia 4
Seed 2022
Selección menor eval_loss

El mejor checkpoint fue el step 1200 (época 6), con eval_loss = 1.1445. La ejecución usó Python 3.12.13 y Transformers 5.12.1.

Evaluación

Las métricas se calcularon una sola vez sobre el test privado congelado de 20 documentos. Por el tamaño del test, cada error equivale a 5 puntos porcentuales; los resultados se presentan con conteo y porcentaje.

Métrica Resultado
JSON parseable 15/20 (75.0%)
Ocho claves de nivel superior presentes 10/20 (50.0%)
Esquema estricto válido (claves y tipos) 4/20 (20.0%)
Normalized edit distance promedio 0.4297
total exacto 14/20 (70.0%)
sub_total exacto 10/20 (50.0%)
fecha exacta 9/20 (45.0%)
ruc exacto 8/20 (40.0%)
igv exacto 8/20 (40.0%)
nro_comprobante exacto 5/20 (25.0%)
empresa exacta 4/20 (20.0%)
empresa Token-F1 promedio 0.3229
Cantidad de ítems correcta 10.0%
Precio de ítems correcto 16.7%
Nombre de ítems Token-F1 promedio 0.1004
Menú exacto 0/20 (0.0%)

Estos números describen este test concreto y no deben interpretarse como una estimación robusta del rendimiento sobre todas las boletas peruanas. No se calcularon intervalos de confianza.

Esquema estricto válido es una auditoría posterior de claves y tipos sobre las mismas predicciones guardadas. El evaluador original solo comprobaba la presencia de las ocho claves. Además, las métricas registradas de menu están sesgadas a la baja porque el evaluador original trataba como lista vacía el objeto que token2json produce para algunos menús de un solo ítem. Se conservan aquí por trazabilidad; no se publican métricas corregidas hasta repetir formalmente la evaluación.

Limitaciones y riesgos

  • El dataset es pequeño y puede no representar la diversidad de comercios, impresoras, cámaras, iluminación y diseños presentes en Perú.
  • El split evita duplicar el mismo documento entre conjuntos, pero no garantiza separación por empresa o plantilla; puede existir similitud visual entre splits.
  • El modelo produce una salida no parseable en 25% del test. Solo 50% incluye las ocho claves de nivel superior y 20% satisface la auditoría estricta de claves y tipos.
  • La extracción de listas es especialmente débil: el menú exacto fue 0% en el test registrado.
  • Cuando hay un solo ítem, menu puede generarse como un objeto en vez de una lista. Los consumidores deben preservar la salida cruda, validar tipos y tratar esta normalización explícitamente.
  • Puede confundir total, subtotal e IGV; copiar texto incorrectamente; omitir campos; o generar valores que no aparecen en la imagen.
  • No devuelve una probabilidad calibrada que permita aceptar automáticamente una predicción.
  • Los documentos pueden contener identificadores comerciales o personales. Aunque el dataset no se publica, un modelo generativo puede memorizar fragmentos; no debe asumirse que sus salidas están libres de información sensible.

Toda salida debe validarse estructuralmente y contrastarse con la imagen original antes de utilizarla.

Licencia y atribución

El checkpoint base se publica con licencia MIT. Esta adaptación se distribuye bajo la misma licencia; consulta LICENSE. La licencia del modelo no concede derechos sobre las imágenes o documentos que cada usuario procese.

DONUT: OCR-free Document Understanding Transformer fue presentado en:

@article{kim2021donut,
  title={OCR-free Document Understanding Transformer},
  author={Kim, Geewook and Hong, Teakgyu and Yim, Moonbin and Park, Jinyoung and Yim, Jinyeong and Hwang, Wonseok and Yun, Sangdoo and Han, Dongyoon and Park, Seunghyun},
  journal={arXiv preprint arXiv:2111.15664},
  year={2021}
}

Contacto

Responsable del repositorio: eng-aesr.

Downloads last month
21
Safetensors
Model size
0.2B params
Tensor type
I64
·
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for eng-aesr/donut-boletas-peru

Finetuned
(37)
this model

Paper for eng-aesr/donut-boletas-peru

Evaluation results