Hacki
All BUIDLs

About the project

Qué construí

Un agente de IA que concilia una factura contra su orden de compra —lee ambos documentos a partir de una foto, y te dice si coinciden— corriendo 100% en mi propia máquina, sin mandar nada a ninguna nube.

Cómo funciona

  1. Subís una imagen de la factura y una de la orden de compra.
  2. Un modelo multimodal chico (SmolVLM2, 500M parámetros, vía @qvac/sdk) lee cada documento por separado.
  3. En vez de pedirle "devolveme JSON" en texto libre, fuerzo al modelo a llamar a una herramienta con un esquema fijo (Zod). Si no la llama, o los datos no cumplen el esquema, lo trato como fallo de lectura — nunca como excusa para inventar un número.
  4. La comparación entre los dos documentos (proveedor, número de orden de compra referenciada, moneda, monto total con 1% de tolerancia, ítems) la hace código determinístico plano, no el modelo. El modelo lee; el veredicto lo calcula JS auditable.
  5. El mismo modelo redacta una explicación en un párrafo, pero a partir de la lista de discrepancias que el código ya calculó — no tiene permiso de inventar comparaciones nuevas.
  6. Si algún campo salió con confianza baja o no se pudo leer, se marca explícitamente en pantalla en vez de ocultarlo.

Arquitectura

  • `/engine`: servidor Node local que carga el modelo y hace toda la inferencia con @qvac/sdk. Esto es lo único que tiene que correr en la máquina del usuario.
  • `/web`: interfaz estática (HTML/CSS/JS sin build), deployable en Vercel. No hace ningún cómputo de IA — solo le habla a localhost:8787, donde vive el motor.

Separé el proyecto así a propósito: la consigna exige que toda la inferencia corra en el dispositivo del usuario, y @qvac/sdk solo corre nativo sobre Node/Bare/Expo (no existe versión de navegador). Esta arquitectura me deja tener una interfaz prolija sin romper esa regla.

Capacidades de QVAC usadas

  • Multimodal completion (completion() con attachments) para leer las imágenes.
  • Tool calling como mecanismo de salida estructurada confiable, con validación Zod.
  • Modelo: SMOLVLM2_500M_MULTIMODAL_Q8_0 + MMPROJ_SMOLVLM2_500M_MULTIMODAL_Q8_0.

Qué no hice (y por qué)

  • OCR dedicado: elegí ir directo con el VLM para tener menos modelos que cargar y una demo más rápida.
  • Soporte de PDF: por ahora solo acepto imágenes, porque no confirmé que completion() acepte PDF directamente en attachments.