- 1Extraer
- 2Normalizar
- 3Revisar
Receta
Documento de ejemploExtracción estructurada
Información extraída del documento mediante OCR e IA.
En esta página
EN BREVE
Un pipeline documental que transforma recetas médicas en datos estructurados y listos para revisión sin ocultar la incertidumbre.
Mi contribución
Arquitectura del pipeline · extracción estructurada · validación · migración de n8n a Python · RAG · diseño human-in-the-loop.
Datos clave
Decisiones de ingeniería
Mantener visible la incertidumbre
Usar confianza, alternativas y caminos de revisión en vez de presentar una extracción estructurada como una respuesta segura.
Preservar el workflow visual antes de migrar
Llevar el flujo validado en n8n a FastAPI, LangGraph y Pydantic sin descartar sus reglas de negocio y bifurcaciones.
Entregar el documento al modelo
Hacer que la imagen o el PDF sean una entrada multimodal real para reproducir la etapa de lectura documental esperada.
Recuperar desde catálogos controlados
Usar candidatos respaldados por CSV para normalización y clasificación, manteniendo las opciones de fuente revisables y reemplazables.
Evolución del proyecto
- Workflow en n8n
- Extracción estructurada y validación
- Migración a API en Python
- Caminos de revisión humana
- Catálogos CSV y RAG
Leer no alcanza
En Argentina, muchas recetas médicas todavía son manuscritas. Nombres, números de credencial, diagnósticos, fechas, indicaciones y medicamentos pueden convivir en un mismo documento, entre abreviaturas y caligrafías ambiguas. Un OCR convencional puede devolver fragmentos de texto, pero no puede determinar si interpretó correctamente un medicamento, si el resultado tiene coherencia clínica o si los datos extraídos son suficientemente confiables para continuar.
Este trabajo suele resolverse mediante revisión administrativa: una persona lee el documento, identifica los campos relevantes, los transcribe en otro sistema y decide cómo proceder cuando algo no es claro. Por eso, el proyecto cambió de dirección: dejó de ser únicamente un experimento de OCR y pasó a buscar la automatización de un flujo humano de procesamiento documental. El objetivo no era eliminar el criterio de las personas, sino reducir la transcripción repetitiva y dirigir la atención humana según el riesgo.
Las lecturas ambiguas y las recetas con medicamentos de alto costo se derivaban a una persona. Las recetas de menor prioridad y costo podían continuar sin intervención humana cuando la confianza del OCR superaba el umbral requerido; una extracción con baja confianza igualmente activaba el reprocesamiento o la revisión. El desafío pasó a ser diseñar ese recorrido conservando la receta original como evidencia y transformando su contenido en un contrato estructurado e inspeccionable.
Del workflow visual a un servicio mantenible
Trabajé sobre la arquitectura del pipeline, el contrato de datos y sus tres implementaciones sucesivas. El workflow inicial en n8n funcionaba correctamente y permitió diseñar y validar rápidamente la lógica de negocio. La migración a Python no fue una corrección de ese primer paso: fue la forma de convertirlo en el MVP, con mayor control sobre el código, los contratos y las pruebas.
La versión con FastAPI y LangGraph mantuvo las decisiones del workflow original —validar, extraer, normalizar, clasificar, decidir y consolidar— y las hizo explícitas como nodos y transiciones. Swagger funcionó como interfaz técnica, Pydantic definió límites verificables entre etapas y la integración con Gemini quedó aislada detrás de un cliente. En una tercera etapa incorporé recuperación sobre catálogos CSV para apoyar la normalización y la clasificación con candidatos controlados.
Tres etapas del sistema
1. Workflow en n8n
La primera versión implementó el recorrido completo como un flujo visual: ingreso por webhook, validación documental, OCR, normalización, clasificación, bifurcaciones y respuesta estructurada. En la primera demo con el cliente, n8n permitió ejecutar el proceso en vivo y recorrerlo nodo por nodo, mostrando cómo cambiaba el documento en cada etapa antes de consolidar el flujo en Python. Esa demostración visual convirtió requisitos todavía cambiantes en algo concreto: las etapas, excepciones y campos de salida podían discutirse y ajustarse directamente sobre un proceso funcionando.
2. MVP en Python
El flujo se migró a FastAPI, LangGraph y Pydantic para ganar modularidad, tipado, manejo de errores y capacidad de prueba, preservando el comportamiento definido en n8n.
3. CSV y RAG
La tercera implementación agregó recuperación sobre catálogos controlados. El sistema buscaba candidatos relevantes antes de normalizar medicamentos o asignar la jerarquía de tipo, subtipo y práctica.
Un pipeline con puntos de control
Arquitectura simplificada
El documento avanza como estado tipado. Cada etapa produce información inspeccionable y la validación decide si el flujo puede continuar.
Ingreso
Recibir imagen o PDF junto con metadata opcional del paciente y su afiliación.
Validación documental
Comprobar que el archivo sea procesable y corresponda al tipo esperado.
Visión y extracción
Enviar el archivo real al modelo multimodal y mapear la lectura a un schema.
Normalización
Corregir candidatos de medicamentos usando receta, diagnóstico y especialidad como contexto.
Clasificación y control
Asignar categorías y evaluar consistencia, confianza y necesidad de reintento.
Enrutamiento por riesgo
Continuar automáticamente los casos confiables y de menor costo; derivar las recetas ambiguas, de baja confianza o alto costo a revisión humana.
El contrato de salida también es producto
La extracción se diseñó alrededor de campos como validez de la receta, credencial, paciente, obra social, diagnóstico, fecha, área médica, prescripción completa y lista de medicamentos. Los datos ausentes debían permanecer nulos: completar silenciosamente un campo era peor que reconocer que no estaba disponible.
La normalización agregaba otra capa de evidencia por medicamento: texto original, corrección propuesta, concentración, frecuencia, candidatos alternativos, correspondencia con el diagnóstico, confianza seleccionada y una acción sugerida. Así, un consumidor podía distinguir entre un dato leído, una hipótesis normalizada y un caso todavía incierto.
El contexto se convierte en evidencia
- Decisión
- Calcular la confianza a partir del documento completo, combinando la calidad del OCR con metadata del paciente y señales contextuales de la receta.
- Motivo
- Los detalles que rodean una lectura dudosa pueden ayudar a desambiguarla. Los datos conocidos del paciente permiten contrastar la identidad extraída, mientras que la institución emisora, el diagnóstico y la especialidad aportan indicios sobre el medicamento. Por ejemplo, el encabezado de una clínica oftalmológica vuelve más plausible un medicamento relacionado con el cuidado ocular que otro candidato no relacionado pero con un nombre manuscrito similar.
- Compromiso
- El contexto es evidencia de apoyo, no una prueba. Una clínica puede cubrir varias especialidades, la metadata puede estar incompleta y un medicamento plausible igualmente puede estar mal leído. Estas señales pueden ajustar la confianza, pero no deben imponerse sobre evidencia contradictoria del documento.
- Resultado
- El puntaje de confianza refleja la concordancia entre calidad del OCR, datos del paciente, contexto clínico y candidatos del catálogo. Las señales débiles o contradictorias reducen la confianza y acercan la receta al reprocesamiento o la revisión humana.
El archivo debía llegar al modelo
- Decisión
- Tratar la imagen o el PDF como entrada multimodal real, no como un adjunto reducido a nombre y metadata.
- Motivo
- Una primera integración podía leer los bytes en FastAPI pero luego construir el prompt solo con el nombre del archivo y el contexto textual. Eso mantenía el endpoint funcionando sin reproducir el OCR original: el modelo nunca veía el documento.
- Compromiso
- Enviar contenido multimodal exige validar MIME, tamaño, multipart y límites del proveedor. También vuelve más importante registrar errores sin conservar información médica sensible.
- Resultado
- La arquitectura dejó explícito el transporte del binario hasta Gemini Vision y separó los problemas de carga, inferencia y parsing para poder probarlos de forma independiente.
Diseñar para la incertidumbre
Conservar la lectura original
Mantener el texto detectado junto con cualquier corrección propuesta para no borrar la evidencia del OCR.
Usar contexto clínico
Contrastar el medicamento con la metadata del paciente, la prescripción completa, el diagnóstico, el área médica y la institución emisora antes de seleccionar una normalización.
Medir consistencia
Exponer confianza, alternativas y correspondencia con el diagnóstico en lugar de devolver una única respuesta opaca.
Elegir una acción
Continuar automáticamente las recetas confiables, de menor prioridad o costo; reprocesar cuando la confianza del OCR es insuficiente; o solicitar revisión humana ante ambigüedad y medicamentos de alto costo.
Tercera etapa: catálogo controlado
- Decisión
- Incorporar recuperación sobre catálogos CSV curados para apoyar la normalización y la clasificación.
- Motivo
- Depender solo del conocimiento paramétrico del modelo limitaba la trazabilidad. La tercera versión recuperaba candidatos de medicamento o de una jerarquía tipo, subtipo y práctica; el modelo elegía y estructuraba la respuesta usando ese conjunto acotado.
- Compromiso
- La recuperación agrega versionado del catálogo, búsqueda semántica y criterios de ranking. A cambio, las opciones pueden rastrearse hasta una fuente administrada y actualizarse sin reentrenar el modelo.
- Resultado
- La separación entre OCR, normalización, recuperación y validación permitió sumar RAG sin reemplazar la API ni el grafo completo. El catálogo pasó a funcionar como una fuente controlada de candidatos dentro del pipeline; el caso no afirma por eso que la solución haya alcanzado validación productiva.
Una superficie técnica pequeña
El prototipo expuso un endpoint de carga para ejecutar el grafo, un health check y la especificación OpenAPI generada por FastAPI. Swagger permitió probar el recorrido con documentos y metadata sin construir antes una interfaz específica.
El manejo de errores diferenció fallas del modelo, respuestas no parseables, problemas de multipart y excepciones internas. Ese detalle convirtió un error 500 genérico en información accionable durante la integración, sin confundir que el servidor estuviera disponible con que el pipeline completo hubiese sido validado.
Resultado del prototipo
El trabajo produjo tres versiones conectadas del sistema: un workflow funcional en n8n para definir y probar el recorrido, un MVP modular en Python con API y documentación interactiva, y una etapa posterior con CSV/RAG para recuperar candidatos desde fuentes controladas.
El caso no publica métricas de precisión ni presenta el sistema como productivo porque todavía faltan resultados revisados sobre un conjunto representativo. Su valor está en mostrar cómo una automatización visual válida pudo convertirse en un servicio verificable y luego incorporar recuperación sin rehacer el pipeline desde cero.
Aprendizajes
En procesamiento documental, una respuesta estructurada no es sinónimo de una respuesta correcta. Los schemas mejoran el contrato; la confianza, los candidatos y la revisión humana mejoran la decisión.
La migración también mostró que copiar nodos uno a uno no es suficiente. La paridad real depende de preservar el binario, las bifurcaciones, los reintentos y la semántica de cada campo. La siguiente etapa natural sería construir un dataset anonimizado, evaluar por campo y por tipo de documento, y recién entonces ajustar umbrales o afirmar calidad operativa.