Saltar al contenidoIván Gómez Dell’Osa

Iván Gómez Dell’Osa

Full Stack Developer

Los proyectos, en video
Lista de proyectos

Proyecto propio · 2026 · IA aplicada · RAG

Ask Leonardo da Vinci

Leonardo da Vinci dejó más de 7.500 páginas escritas. Por primera vez, un software las utiliza para conversar con él sin inventar respuestas. Una red neuronal encuentra, entre 1.565 pasajes de sus cuadernos, los que responden cada pregunta, y el sistema comprueba que cada cita exista en el original.

«Actúa como si fueras…» es uno de los pedidos más comunes que recibe una inteligencia artificial. Cuando se le pide ser alguien, el modelo asegura que puede, pero inventa respuestas, cambia la forma de expresarse de esa persona y opina sobre temas que nunca se planteó. Para no inventar necesitaría muchísimo contexto de esa persona: sus pensamientos, sus experiencias, lo que se preguntó alguna vez. Leonardo lo dejó escrito. Durante toda su vida llenó cuadernos, una transfusión mental a papel: anatomía, óptica, pintura, máquinas, fábulas y hasta sus listas de compras. Sus expresiones, sus respuestas y sus opiniones no hace falta inventarlas: las escribió él.

El sitio recibe al visitante en el taller de Leonardo, sentado frente a él: se le hace una pregunta y responde en primera persona, con las fuentes a la vista. Lo que aparece entre comillas sale tal cual de sus cuadernos. Para quien no sabe qué preguntarle, la Pregunta asistida ofrece un mapa de 22 secciones y 396 temas, y cada uno se convierte en pregunta con un clic. Lo que no está en sus cuadernos no se inventa: el sitio lo aclara. Todo en español y en inglés, con una biblioteca 3D, un museo virtual 3D y un espacio vectorial que muestra cómo funciona por dentro.

Corre sobre un pipeline RAG escrito desde cero, sin frameworks como LangChain o LlamaIndex, para que cada paso se pueda controlar y medir por separado. La pregunta se vuelve vector en el propio navegador; si ningún pasaje se le parece lo suficiente, el sistema se abstiene sin llamar al modelo. Si hay material, una búsqueda híbrida elige tres pasajes, Gemini responde con ellos delante y el código verifica cada cita.

0 de 187

citas inventadas. Con el mismo modelo y las mismas preguntas, una IA actuando como Leonardo inventa el 96,9% (156 de 161).

Stack

  • Next.js
  • React
  • TypeScript
  • Three.js
  • RAG
  • Transformers.js
  • Gemini API
  • Python

La diferencia se mide

Citas atribuidas a Leonardo que no existen en sus cuadernos

Modelo de lenguaje actuando como Leonardo

96,9%156 de 161 citas

Ask Leonardo da Vinci

0%0 de 187 citas

Mismo modelo, mismo prompt y las mismas 120 preguntas. Cada cita se buscó en el texto completo, en los dos idiomas.

También se midióResultado
Preguntas con respuesta en los cuadernos que el sistema rechazó por error0, en 170 preguntas de prueba
Temas de los cuadernos que el buscador encuentra en los dos idiomas94%
Las dos corridas del gráfico, con cada respuesta completa, están publicadas en evals/out/.

Preguntarle a Leonardo

El códice: el mapa de temas a la izquierda y una respuesta de Leonardo con una cita textual y sus fuentes.
  • Respuestas con fuentes. Leonardo responde en primera persona a partir de los pasajes recuperados, con las fuentes debajo y el enlace a cada pasaje en Project Gutenberg.
  • Citas textuales. Todo lo que aparece entre comillas sale tal cual de sus cuadernos. Si una cita no coincide con el original, no se muestra como cita.
  • Pregunta asistida. ¿Qué se le pregunta a uno de los hombres más brillantes de la historia? Escribió sobre tantas cosas que hasta puede intimidar. Por eso hay un mapa de 22 secciones y 396 temas sobre los que sí escribió, más seis preguntas sugeridas: se elige un tema y con un clic se convierte en pregunta. Quien no está acostumbrado a la IA puede concentrarse en leer las respuestas en vez de armar un prompt.
  • Lo que no pudo escribir. Hay cosas que Leonardo, lógicamente, no dejó en sus cuadernos, como su propia muerte, y datos que no solía anotar sobre sí mismo («¿qué día naciste?», «¿quién fue tu maestro?»). Ahí el sitio lo aclara y muestra el fragmento exacto de Wikipedia, con su atribución, fuera de su voz.
  • Lo que se perdió. Con los siglos, parte de sus cuadernos se perdió. ¿La Mona Lisa? Sus manuscritos nunca la mencionan, y el sitio muestra la nota del editor que lo confirma. Queda el misterio, pero no se inventa.
  • Bilingüe. Todo el sitio, incluidas las respuestas de Leonardo, está completo en español y en inglés.

Biblioteca 3D

La estantería de la biblioteca, con el volumen de Anatomía fuera del estante.
Un volumen abierto mientras se pasa una hoja, con la lupa sobre una lámina.

Cinco volúmenes con 27 láminas de Leonardo. Los tomos salen del estante, las hojas se pasan con el pliegue de un libro real y, en escritorio, una lupa permite leer la escritura de cerca.

Museo virtual 3D

La sala del museo con La Gioconda y La Última Cena, el avatar del visitante y la ficha de la obra.

Una sala que se recorre caminando, también desde el teléfono, con nueve de sus obras y la ficha de cada una.

Espacio vectorial

Sección encendida…

1.402 pasajes · 22 secciones · 384 → 3 dimensiones

Es la sección «Cómo funciona» del sitio. Le muestra al visitante los pasajes convertidos en vectores y cómo una pregunta encuentra los suyos. Está en una web para público general a propósito: la validez técnica del sistema es lo que respalda cada respuesta de Leonardo.

No es una animación ilustrativa. Son los vectores reales del proyecto: los 1.402 pasajes que consulta el sistema, ubicados por su red neuronal y llevados de 384 dimensiones a 3 para poder verlos. Al encender una sección se entiende la cercanía: para la red neuronal, los pasajes que hablan de lo mismo tienden a quedar juntos.

Arquitectura

La idea fue el punto de partida, no el resultado. Hubo que medir y elegir modelos, calibrar la búsqueda semántica, dejar que hable sólo Leonardo (y no su editor), limitar la prosa que los modelos de IA tienden a inventar y comprobar que cada cita exista en los cuadernos. El texto que consulta el sistema es la edición que Jean Paul Richter transcribió y tradujo en 1888, hoy de dominio público.

Qué pasa con cada pregunta
  1. Preguntaembedding en el navegadorSe vuelve vector en el dispositivo de quien pregunta, sin API.
  2. Casos curadoscapa 0Lo que se sabe que no está en los cuadernos: abstención con la evidencia citada.
  3. Umbral de similitudcapa 1Si ningún pasaje se le parece lo suficiente, se abstiene sin llamar al modelo.
  4. Recuperación híbridacoseno + BM25 · RRFElige los tres pasajes que van a sostener la respuesta.
  5. Generacióncapa 2 · GeminiEl modelo responde, o se abstiene, con los pasajes delante.
  6. Verificacióncapa 3 · códigoCada cita se compara con el pasaje original.
  7. Respuestacon sus fuentesEn la voz de Leonardo, con los pasajes a la vista.

En dos de los pasos el sistema puede abstenerse antes de llamar al modelo: prefiere decir que los cuadernos no tratan un tema antes que inventar una respuesta.

  • El coseno decide y la fusión sólo ordena. Un ranking siempre tiene un primer puesto, exista o no material pertinente; lo que determina si hay respuesta es la similitud contra un umbral calibrado.
  • Un índice y un umbral por idioma. Con un umbral compartido, la exactitud del filtro caía de 88,4% a 70,5%.
  • Embeddings en el navegador. La consulta se vectoriza en el dispositivo del usuario: sin costo por consulta y sin una cuota que se pueda agotar.
  • Sin servidor persistente ni base de datos vectorial. El índice es un binario int8 versionado en Git, BM25 está precomputado y las secciones 3D se cargan sólo cuando alguien las visita.

Stack

CapaTecnología
FrontendNext.js 16 (App Router), React 19, TypeScript, Three.js
Embeddingsmultilingual-e5-small (384 dimensiones, int8) · Transformers.js en el navegador
RecuperaciónCoseno denso + BM25 precomputado, fusión RRF
GeneraciónGemini 3.1 Flash-Lite, con GPT-OSS 120B en Groq como respaldo
IngestaPython: parseo de la edición de Gutenberg, separación de voces, chunking, embeddings y calibración
Evaluación170 preguntas en 8 categorías · juez automático validado contra etiquetado humano
SeguridadCloudflare Turnstile, límite por IP hasheada y presupuesto diario global
Hosting y CIVercel · GitHub Actions

Proyecto propio · 2026 · Datos · ETL

Datos Pauta Oficial

La primera y única base unificada de pauta oficial argentina: 540.413 órdenes de publicidad de Nación, CABA, PBA y Santa Fe (2003–2025), con montos deflactados por IPC. Se consulta desde el sitio con una tabla explorable, rankings y el buscador «Cuánto recibió» (por proveedor, medio o grupo mediático), con la metodología publicada.

Antes, esos datos estaban dispersos en portales, planillas y PDF de cada jurisdicción, sin una forma unificada y sencilla de acceder a ellos ni de compararlos. El ETL en Python incluye un dataset de PBA 2020–2024 reconstruido a partir de más de 500 resoluciones en PDF, datos que no existen en ningún portal de datos abiertos.

Arquitectura sin backend: la base SQLite (~173 MB) se aloja en Cloudflare R2 y el navegador consulta únicamente los bytes necesarios mediante HTTP Range Requests.

540.413

órdenes de publicidad unificadas, de cuatro jurisdiccionesNación · CABA · PBA · Santa Fe · 2003–2025

Stack

  • Python
  • ETL
  • SQLite
  • Astro
  • React
  • TypeScript
  • Cloudflare R2/Pages

PBA, reconstruida desde PDF

La Provincia de Buenos Aires no publica sus órdenes de publicidad de 2020 a 2024 en datasets abiertos: la información estaba en resoluciones individuales en PDF. Un script fue extrayendo los datos resolución por resolución (más de 500) para reconstruir el detalle de cada orden: proveedor, medio, monto y expediente. Ese tramo es un dataset propio del proyecto.

Cobertura

Cobertura de la base, por jurisdicción
CABA209.877CABA: 2003–2024, 209.877 órdenes.
Santa Fe61.187Santa Fe: 2008–2023, 61.187 órdenes.
Nación225.367Nación: 2009–2022, 225.367 órdenes.
PBA43.982PBA: 2020–2025, 43.982 órdenes.

PBA 2020–2024 · Reconstruido de más de 500 resoluciones en PDF

540.413 órdenes en total, 2003–2025

JurisdicciónPeríodoÓrdenes
Nación2009–2022225.367
CABA2003–2024209.877
Santa Fe2008–202361.187
PBA2020–202543.982
Total2003–2025540.413
Los huecos de cobertura se muestran de forma explícita en la web: nunca se presentan agregados que puedan engañar por cobertura incompleta.

Arquitectura

El proyecto corre sin backend ni servidores: la base SQLite completa (~173 MB) vive en Cloudflare R2 partida en bloques, y el navegador consulta sólo los bytes que necesita mediante HTTP Range Requests, gracias a sql.js-httpvfs.

De la fuente oficial al navegador
  1. Fuentes oficialesCSV · Excel · PDFCada jurisdicción publica a su manera.
  2. ExtracciónPythonUn extractor por jurisdicción.
  3. Unificaciónunificar.py · validar.pyUn solo CSV canónico y validado: 8 columnas, 540.413 filas.
  4. Base de datosbuild_db.py · SQLiteMontos deflactados por IPC (INDEC) y cachés precomputados.
  5. AlmacenamientoCloudflare R2La base, partida en bloques de 20 MiB.
  6. Consultasql.js-httpvfsSQL desde el navegador, que pide sólo los bloques que necesita.
  7. SitioAstro · React · Cloudflare PagesEstático, con islas de React: sin backend ni servidores.

Funcionalidades

  • Tabla explorable de 540 mil órdenes. Filtros cruzados por jurisdicción y año, agrupación por proveedor o medio con filas expandibles. El estado inicial viene precomputado en el HTML, y la base se abre recién cuando el usuario interactúa. El dato que se muestra es el crudo exacto de la fuente oficial.
  • «Cuánto recibió». Buscador por proveedor, medio o grupo mediático; el modo grupo consolida las razones sociales de cada holding según el Media Ownership Monitor Argentina, con fuente citada. Genera una imagen de 1080 × 1080 para compartir, con Canvas puro, y enlaces que restauran la búsqueda.
  • Rankings de proveedores, medios y grupos por jurisdicción y año, servidos desde caches precomputados en el build.
  • Metodología pública: fuentes, criterios de deflactación y de normalización documentados en el sitio.
La portada de Datos Pauta Oficial: 540.413 pautas asignadas, 15.688 medios, 6.481 proveedores y 4 jurisdicciones.
La portada de Datos Pauta Oficial en un teléfono.

Decisiones de datos

  • Montos deflactados, no nominales. Todo está en pesos constantes (IPC INDEC): comparar la pauta de 2009 con la de 2024 en pesos nominales no tiene sentido en Argentina.
  • El dato exacto, aun a costa de la comodidad. La tabla muestra cada orden tal como figura en la fuente oficial, sin corregir ni agrupar nombres, aunque eso la haga menos cómoda de leer: un mismo proveedor puede aparecer escrito de varias formas. Los rankings y «Cuánto recibió» sólo unifican variantes de escritura de una misma razón social, con un listado curado de forma conservadora; la consolidación por grupo mediático es una opción aparte, con su fuente citada.
  • Honestidad sobre los huecos. Cada limitación de la fuente (filas sin fecha, períodos parciales) se documenta en vez de ocultarse.
  • Postura informativa: sin denuncia ni opinión.

Stack

CapaTecnología
ETLPython: extractores por jurisdicción, unificación y validación
Base de datosSQLite estática, consultada desde el navegador con sql.js-httpvfs
FrameworkAstro 6 (salida estática) + React 19 (islas)
LenguajeTypeScript
BúsquedaMiniSearch (índice en el cliente)
HostingCloudflare Pages + Cloudflare R2
DeflactaciónIPC INDEC, montos en pesos constantes

Freelance · dic. 2025 – jun. 2026 · Full stack

SeViVe

Aplicación de reservas y gestión para un estudio de pilates, en producción con más de 200 usuarios. Los alumnos reservan sus clases desde el celular y la administración gestiona el estudio desde su panel. API REST en Python/FastAPI y PostgreSQL.

La desarrollé como único programador para un estudio de Canning, Buenos Aires (franquicia), desde la definición de requisitos con el cliente hasta la puesta en producción. Finalizado el desarrollo, continúo a cargo del soporte, la administración del servidor y las actualizaciones solicitadas por el cliente.

Reservas con control de concurrencia para evitar sobrerreservas, créditos con vencimiento, turnos fijos con reserva automática, toma de asistencia y calendario con feriados configurables. Las cuentas que crea la administración se unifican automáticamente con la del alumno cuando se registra (por DNI), preservando historial, créditos y turnos.

Se instala como PWA en cualquier dispositivo, con una guía paso a paso pensada para usuarios no técnicos.

+200

usuarios

Stack

  • Flutter
  • Python
  • FastAPI
  • PostgreSQL
  • Firebase
  • Docker
  • Nginx

Qué resuelve

El objetivo: una aplicación fácil de usar, que permita delegar y ordenar la gestión del estudio, y que al mismo tiempo impida que un alumno rompa el orden del negocio.

  • Reservas con control de concurrencia. El backend valida cupos, créditos y horarios en cada reserva: dos alumnos no pueden quedarse con el mismo último lugar.
  • Turnos fijos y clases recurrentes. La administración crea una clase una vez y el sistema genera las instancias semanales respetando los feriados; los abonos se reservan solos cada semana.
  • Créditos con vencimiento, descontados automáticamente con cada reserva, y cancelación con política de sanciones por aviso tardío o ausencia.
  • Fusión de cuentas por DNI. La administración puede cargar alumnos que todavía no tienen la aplicación, para que los cupos y las estadísticas sean reales. Cuando ese alumno se registra con su DNI, las dos cuentas se unifican y conserva turnos fijos, créditos e historial.
  • Asistencia. La administración la toma desde la agenda del día, y el calendario mensual guarda cada clase dictada con su ocupación y su asistencia.
  • Panel de administración: historial por alumno, bloqueo de usuarios con cancelación de sus reservas futuras, pausa general de las reservas y feriados que se cargan desde la aplicación, sin un nuevo despliegue.
  • Comunicación: novedades con notificaciones push y feedback después de cada clase, con aviso por email a la administración ante una respuesta negativa.
  • Apto médico: carga de PDF o imagen, con compresión automática.
  • Rifa mensual entre alumnos activos, ponderada por asistencia, para incentivar la constancia.
  • Instalación sin tienda de aplicaciones. Es una PWA: se instala desde el navegador en el teléfono, la tablet o la computadora, con una guía paso a paso pensada para usuarios no técnicos.

Arquitectura

Cómo está armada
App Flutter (PWA)alumnos · administración
VPS · Docker Compose
Nginx
FastAPIasync
PostgreSQLasyncpg · Alembic
FirebaseGoogle · Storage · push (FCM)
  • Reservas con control de concurrencia
  • Créditos con vencimiento
  • Turnos fijos con reserva automática
  • Fusión de cuentas por DNI

Una sola aplicación en Flutter (Riverpod, Freezed, GoRouter) para alumnos y administración, servida como PWA. El inicio de sesión es el de Google, mediante Firebase, y el backend verifica esa identidad en cada pedido.

Nginx recibe el tráfico por HTTPS, limita los pedidos por dirección IP y sirve la aplicación y los archivos subidos. Detrás, la API asíncrona en FastAPI (SQLModel, asyncpg) trabaja sobre PostgreSQL 16, con los cambios de estructura versionados en Alembic. Las notificaciones push salen por Firebase Cloud Messaging.

Todo corre en tres contenedores de Docker Compose (base de datos, API y Nginx) en un VPS que administro: despliegue con un script que aplica las migraciones, backups y resolución de fallas.

Stack

CapaTecnología
AppFlutter 3, Riverpod, Freezed, GoRouter, Dio · instalable como PWA
BackendPython, FastAPI (async), SQLModel, asyncpg
Base de datosPostgreSQL 16, Alembic
AutenticaciónFirebase Authentication (Google)
Archivos y avisosFirebase Storage, Firebase Cloud Messaging
InfraestructuraDocker Compose, Nginx, VPS en Hetzner

Proyecto propio · 2026 · IA · Automatización

Inversiones en Argentina

Automatiza con IA el seguimiento de las inversiones privadas en Argentina. Identifica las inversiones reales, descarta duplicados y publica los resultados en la web y en un canal de Telegram.

La información estaba dispersa en noticias, cuentas de X y registros oficiales, y cada inversión aparece repetida en muchos medios, escrita de formas distintas. Un flujo programado en GitHub Actions reúne esas fuentes y suma una búsqueda en Google con Gemini y Search Grounding.

Un sistema de capas decide qué llega a publicarse: Gemini estructura cada mención, reglas deterministas y Jev (TypeSafe) separan las inversiones reales de lo que no lo es, y pgvector recupera los registros parecidos. El mismo proyecto, contado por dos medios, puede leerse muy distinto, y dos proyectos distintos de la misma región pueden parecer casi idénticos: por eso la similitud sólo sugiere candidatos, y la decisión la toman reglas de identidad y un modelo de decisión (Jev). API en FastAPI y frontend en Next.js con render en servidor, sobre Vercel.

Stack

  • Python
  • FastAPI
  • Gemini
  • Jev (TypeSafe)
  • PostgreSQL/pgvector
  • GitHub Actions
  • Next.js

El flujo de cada corrida

Qué llega a publicarse
  1. FuentesX · RSS · RIGICuentas especializadas, medios por rubro y el registro oficial.
  2. FiltrodeterministaSaca el ruido: menos tokens y decisiones más simples después.
  3. ExtracciónGemini + GroundingCada mención pasa a datos estructurados.
  4. ValidaciónreglasFuera deuda, préstamos, compraventa de acciones y lanzamientos.
  5. JuicioJev (TypeSafe)¿Es una inversión privada concreta?
  6. Deduplicaciónpgvector + identidadLa similitud recupera; la identidad decide.
  7. Publicaciónweb · TelegramSólo lo nuevo, sin intervención.

Cada capa descarta algo y le deja a la siguiente menos ruido y menos margen de error. Sin Jev, el flujo funciona igual sobre sus capas deterministas.

  • Recolección. Cuentas especializadas de X (API de Apify), medios de distintos rubros por RSS, paginados hasta cubrir la ventana completa, y el registro oficial del RIGI (el régimen de incentivo a las grandes inversiones) de forma incremental: se guarda una huella de cada proyecto y sólo se reenvían los nuevos o los que cambiaron.
  • Filtro de relevancia. Un filtro determinista descarta el ruido estructural de los feeds antes de que llegue a Gemini. No sólo ahorra tokens: los pasos siguientes reciben menos material irrelevante, y sus decisiones son más simples y con menos margen de error. Prioriza no perder: ante la duda deja pasar, porque descartar de más significa perder una inversión real.
  • Extracción con Gemini y Search Grounding. El material recolectado entra como primera fuente y Gemini busca en Google noticias del período como segunda, con foco en los rubros que las fuentes propias cubren poco. Devuelve cada inversión como JSON estructurado.
  • Validación. Una red determinista descarta lo que no es una inversión productiva nueva: emisiones de deuda, préstamos, constituciones de sociedades, compraventa de acciones, contratos ganados por proveedores y lanzamientos de productos.
  • Juicio semántico con Jev. Un modelo que devuelve decisiones tipadas con probabilidad calibrada, en lugar de texto, responde si cada registro es una inversión privada concreta.
  • Deduplicación. El embedding recupera los candidatos más parecidos; la decisión la toman reglas de identidad y Jev, respondiendo si dos registros describen el mismo proyecto.
  • Publicación y parte de estado. Lo nuevo se guarda y se publica a la vez en la web y en Telegram. Cada corrida termina informando el estado de cada fuente, y falla si alguna que debería responder no trajo nada.

Por qué la similitud recupera pero no decide. Sobre un corpus temáticamente estrecho, el espacio vectorial se comprime. Dos proyectos distintos del mismo rubro y la misma región pueden parecerse tanto como el mismo proyecto contado por dos medios, y no hay un umbral que separe esos dos casos.

Funcionalidades

La portada de inversionesargentina.com.ar: la bandera, el buscador y la cronología de inversiones.
  • Cronología interactiva ordenada por fecha de anuncio, con el estado de cada inversión (confirmada, anunciada o en evaluación), montos legibles (USD 40M, USD 1.2B), provincia y empleos cuando están disponibles.
  • Búsqueda en tiempo real sobre empresa, descripción y ubicación, sin importar las tildes: «Neuquen» encuentra las inversiones de Neuquén.
  • Indexable: la primera página se renderiza en el servidor, con datos estructurados (JSON-LD), sitemap.xml y robots.txt.
  • API REST en FastAPI con documentación automática.

Stack

CapaTecnología
AutomatizaciónGitHub Actions (cada 72 horas)
FuentesApify (X), RSS de medios, registro oficial del RIGI
IA generativaGemini 2.5 Flash con Google Search Grounding
Juicio semánticoJev (TypeSafe)
Embeddingsgemini-embedding (768 dimensiones)
Base de datosPostgreSQL (Neon) con pgvector y unaccent
APIPython, FastAPI (async), Mangum, sobre Vercel
FrontendNext.js 16 con render en servidor, TypeScript, Tailwind CSS, Framer Motion
PublicaciónTelegram Bot API

Proyecto propio · 2026 · Visión por computador

FaceHunt 2

Sistema de reconocimiento facial con IA y deep learning que, a partir de una foto, localiza cada aparición de una persona en horas de video, incluso de perfil, parcialmente cubierta o en baja resolución.

Procesa todo en local con aceleración por GPU, sin enviar datos a la nube. Es una aplicación de escritorio que devuelve los intervalos de tiempo exactos, con miniatura, mini-clip y acceso directo a cada momento, para un archivo local o un video de YouTube. Aplicable a seguridad, investigación y análisis de video.

Reconocimiento facial con InsightFace (ArcFace, embeddings de 512 dimensiones) sobre ONNX Runtime, con aceleración por GPU según el hardware disponible y seguimiento entre cuadros. Es la reconstrucción integral de la primera versión, FaceHunt (2025): de TensorFlow en CPU a ONNX Runtime con GPU.

7 s

para encontrar una aparición de un segundo en un video de 70 segundos

Stack

  • Python
  • InsightFace
  • ArcFace
  • ONNX Runtime
  • FastAPI
  • pywebview
  • pytest

Qué hace

Se cargan una o varias fotos de la persona y un video (archivo local o URL de YouTube). La aplicación devuelve los rangos de tiempo exactos en los que aparece, cada uno con una miniatura del rostro, un mini-clip animado del momento y un salto directo, más una línea de tiempo del video completo en la que se puede hacer clic.

Cómo funciona una búsqueda

  • Referencia. Se validan las fotos y se calcula un embedding de 512 dimensiones por rostro; con varias fotos se promedian, para una identificación más estable.
  • Video. Se valida el archivo o la URL (YouTube se descarga con yt-dlp).
  • Análisis en segundo plano. Un hilo productor lee los cuadros y otro los analiza: detección con SCRFD, comparación por coseno contra la referencia y seguimiento de cada rostro entre cuadros.
  • Progreso en vivo. El avance, el tiempo restante y las coincidencias llegan por Server-Sent Events, y la búsqueda se puede cancelar en cualquier momento.
  • Resultados. Las coincidencias se agrupan en rangos, cada uno con su miniatura, su mini-clip y su enlace.
La interfaz de FaceHunt 2 en el primer paso: subir la foto de referencia.
La interfaz corre en una ventana nativa (pywebview) sobre un servidor FastAPI local.

Características

  • 100% local y privado. Las fotos y los videos nunca salen del equipo: no hay servidor en línea ni subida a la nube.
  • Reconocimiento facial actual. InsightFace antelopev2 (SCRFD-10G + ArcFace ResNet100 entrenado en Glint360K, embeddings de 512 dimensiones) sobre ONNX Runtime, con flip-TTA para no perder apariciones.
  • Aceleración por GPU automática. Elige el mejor proveedor disponible (CUDA, DirectML o CPU): funciona con placas NVIDIA, AMD e Intel en Windows.
  • Seguimiento temporal. Agrupa los rostros en tracklets entre cuadros y compara contra el embedding agregado, lo que recupera apariciones en cuadros degradados (de perfil, tapadas o en baja resolución).
  • Dos modos: rápido (2 cuadros por segundo) y exhaustivo (5 cuadros por segundo y rostros más chicos).
  • Ejecutable de un clic para Windows, con tests de la lógica pura en pytest.

De FaceHunt a FaceHunt 2

FaceHunt (2025)FaceHunt 2 (2026)
MotorTensorFlow en CPUONNX Runtime con GPU (CUDA, DirectML o CPU)
ModeloFaceNet, 128 dimensionesArcFace ResNet100, 512 dimensiones
ResultadoMarcas de tiempo sueltasRangos con miniatura, mini-clip y línea de tiempo
UsoInterfaz web: demo en Hugging Face Spaces o imagen de DockerAplicación de escritorio de un clic, sin servidor ni nube

Stack

CapaTecnología
ReconocimientoInsightFace (SCRFD + ArcFace), ONNX Runtime
VideoOpenCV, yt-dlp
BackendPython, FastAPI, Server-Sent Events
InterfazHTML, CSS y JavaScript sin build, en una ventana pywebview
Pruebas y empaquetadopytest, PyInstaller, instalador para Windows

Primera versión

La interfaz web de la primera versión de FaceHunt, en el paso de carga de la foto de referencia.

FaceHunt 2025

Reconocimiento facial en video con deep learning: DeepFace (FaceNet) con dos modos de análisis (alta precisión con RetinaFace, equilibrado con MTCNN), extracción de cuadros por lotes con OpenCV y descarga de YouTube con yt-dlp. Empezó como aplicación de escritorio en Tkinter y sumó una API en FastAPI con interfaz web por pasos. Se publicó como demo web en Hugging Face Spaces y como imagen en Docker Hub, y corre en Windows, macOS y Linux.

  • Python
  • DeepFace
  • FaceNet
  • RetinaFace
  • FastAPI
  • Docker
  • Hugging Face Spaces

Proyecto propio · 2026 · Extensión de Chrome

MementoLife

Extensión de Chrome publicada en la Chrome Web Store que reemplaza la pestaña nueva por una grilla con las semanas de la vida, calculada a partir de la fecha de nacimiento.

Tema claro, oscuro o del sistema, interfaz completa en 6 idiomas y una efeméride histórica para cada día del año. Ninguna conexión de red y un solo permiso (storage): la fecha de nacimiento se guarda sólo en el equipo.

TypeScript, sin frameworks ni bundler: ESM nativo compilado con tsc. Tests unitarios y de snapshots con Vitest, pruebas de extremo a extremo con Playwright sobre la extensión empaquetada y CI con GitHub Actions.

3 trazados

SVG para dibujar 4.160 semanas, en lugar de un elemento por semana. El renderizado baja de 10,00 ms a 1,30 ms.

Stack

  • TypeScript
  • Manifest V3
  • SVG
  • Vitest
  • Playwright
  • GitHub Actions

Qué hace

Cada punto es una semana. Las vividas se dibujan llenas, las que faltan apenas insinuadas, y un anillo marca la semana actual. La esperanza de vida se ajusta entre 20 y 100 años, y cada día muestra una efeméride histórica distinta, en los 6 idiomas, que se puede desactivar.

La grilla, en vivo

Una vida de 80 años, semana por semana
—semana — de 4.160

La grilla de esta página se dibuja con la misma técnica que la extensión: tres trazados SVG acumulados (pasado, futuro y anillo) en lugar de un elemento por celda. En la extensión, eso evita 4.160 elementos y baja el renderizado de 10,00 ms a 1,30 ms, medido contra la alternativa de un elemento por semana.

Capturas

MementoLife en tema oscuro: el porcentaje de vida, la semana actual y la grilla de puntos.
MementoLife en tema claro.
La página de opciones: fecha de nacimiento, esperanza de vida, tema e idioma.
La efeméride del día debajo del porcentaje.

Privacidad

  • Ninguna conexión de red.
  • Un solo permiso: storage.
  • La fecha de nacimiento se guarda en chrome.storage.local, nunca en sync: no viaja por la cuenta de Google.

Stack

CapaTecnología
LenguajeTypeScript
EjecuciónSin framework ni bundler: ESM nativo, tsc como único paso de build
RenderSVG generado por un núcleo puro: sin DOM, sin chrome.*, la fecha entra como parámetro
PruebasVitest (unitarios y snapshots) + Playwright (extremo a extremo sobre el paquete real)
EmpaquetadoManifest V3, un solo permiso, sin service worker
CIGitHub Actions en cada push

Historia del proyecto

MementoLife empezó como una aplicación de Android que ponía la grilla en la pantalla de bloqueo. Funcionaba, pero MIUI y One UI ignoran en silencio los intentos de actualizar sólo la pantalla de bloqueo (setBitmap(..., FLAG_LOCK) no falla: no hace nada). En vez de romper una decisión de diseño del proyecto, se cambió de plataforma.

Rugidos Fiestas Tandil · 2023 – actualidad · Sitio web comercial

Rugidos Fiestas

Sitio comercial de una empresa de eventos, mobile first y optimizado para búsquedas locales.

Diseñé, desarrollé y mantengo el sitio web comercial de la empresa, en producción. La versión actual está hecha con Next.js, TypeScript, Tailwind CSS y Framer Motion, con diseño UX/UI propio.

Los efectos pesados se desactivan en teléfonos para sostener la fluidez del scroll, el feed de Instagram y las reseñas son contenido local en lugar de widgets externos, y los datos estructurados ayudan en las búsquedas locales.

95 / 100

de rendimiento en Lighthouse con el perfil móvil, sobre el sitio en producción (99 en escritorio)Mediana de 3 corridas · septiembre de 2026

Stack

  • Next.js
  • TypeScript
  • Tailwind CSS
  • Framer Motion
  • Lenis
  • shadcn/ui
  • Vercel

El sitio

El sitio es el canal comercial de Rugidos Fiestas Tandil, una PyME de eventos infantiles: tiene que mostrar el salón, los servicios y los extras, y llevar al visitante a una consulta por WhatsApp. Por eso se diseñó primero para el teléfono.

La sección «¿Por qué elegirnos?»: los contadores de años y eventos y las tarjetas de atención, propuestas, espacio y experiencia.
El sitio en un teléfono.

Secciones y funcionalidades

  • Nuestro espacio: galería con lightbox navegable con teclado y una grilla con las características del salón.
  • Academia de Estrellas: en escritorio, una máscara radial que sigue al cursor revela el look «superstar» debajo del casual; en teléfonos, un comparador antes/después que se arrastra con el dedo.
  • Detección real de hover (hover: hover y pointer: fine) en lugar de un corte por ancho, para no romper la experiencia en tablets táctiles.
  • Reseñas: resumen de Google Reviews y marquesinas con pausa manual, sin depender de widgets.
  • Contacto: un botón de WhatsApp que abre la conversación con el mensaje ya escrito, la dirección del salón con su mapa de Google, las redes y una selección de publicaciones de Instagram.

Rendimiento

LighthouseMóvilEscritorio
Rendimiento9599
Accesibilidad9696
Buenas prácticas100100
SEO100100
LCP2,9 s0,8 s
CLS00
Lighthouse 12 sobre el sitio en producción, mediana de 3 corridas por perfil (septiembre de 2026).
  • Parallax, efecto 3D de las tarjetas, vidrio esmerilado y animaciones de entrada se desactivan en teléfonos, para que el contenido llegue antes y el scroll se mantenga fluido en equipos de gama media.
  • El logo pasó de PNG (127 KB) a WebP (7 KB), y el recurso crítico del hero se pide con prioridad alta.
  • Las fotos del salón y de los extras se procesaron en lote con Sharp: de ~15,6 MB a ~1,8 MB.
  • El feed de Instagram y las reseñas de Google se sirven como contenido local: sin dependencias externas ni saltos de diseño mientras cargan.
Las tarjetas de servicios y la sección violeta con cumpleaños, capacidad y precio congelado.

Stack

CapaTecnología
FrameworkNext.js (App Router), TypeScript
Estilos y componentesTailwind CSS, shadcn/ui, Radix UI, Lucide
MovimientoFramer Motion, Lenis (sólo en escritorio)
DeployVercel, Vercel Analytics

Primera versión

La portada del sitio de 2023: fondo rosa, el león de Rugidos y los enlaces a redes.

RugidosWebSite 2023 2023 – 2026

En producción desde 2023 hasta ser reemplazada por la versión actual. HTML, CSS y JavaScript sin frameworks, con deploy automático a cPanel. Desarrollada sin asistencia de IA.

  • HTML5
  • CSS3
  • JavaScript

Rugidos Fiestas Tandil · 2025 · Aplicación de escritorio

FreeMagicMirror

Aplicación de fotomatón táctil en uso en el salón de Rugidos, distribuida como ejecutable portable para Windows.

Captura con cuenta regresiva animada, editor multitáctil con dibujo libre y stickers que se escalan y rotan con los dedos, y guardado automático en una galería local. Pensada para chicos: videos animados, transiciones suaves y controles grandes.

Python, Kivy y OpenCV. Un panel de administración oculto (cinco toques en una esquina) permite elegir cámara, orientación y monitor, y la aplicación corre en modo kiosco, a pantalla completa y sin bordes.

Stack

  • Python
  • Kivy
  • OpenCV
  • PyInstaller
  • Docker

El recorrido en pantalla

Las pantallas de la aplicación, en orden
  • Inicio: un video en loop invita a tocar la pantalla.
  • Pose: una animación sugiere poses para la foto.
  • Cuenta regresiva y captura desde la cámara.
  • Editor: dibujo libre con cinco colores, stickers que se escalan, rotan y mueven con varios dedos, y deshacer.
  • Guardado en una galería local, con numeración incremental.

Decisiones técnicas

  • La cámara se inicializa después de los videos, a 10 cuadros por segundo, para que la reproducción no se trabe.
  • Videos decodificados con FFPyPlayer, integrado en Kivy, y exportación del lienzo completo (foto, dibujos y stickers) a PNG.
  • Panel de administración oculto: detección de cámaras con OpenCV, orientación vertical u horizontal con ajuste de la ventana, y elección del monitor de salida.
  • Rutas que detectan si la aplicación corre empaquetada con PyInstaller, para que el ejecutable encuentre sus recursos al copiarlo a otro equipo.

Distribución

Ejecutable portable (.exe) para Windows, sin dependencias externas, publicado en los Releases del repositorio, e imagen en Docker Hub para Linux.

Iván Gómez Dell’Osa

Sobre mí

Desarrollo productos de software completos, desde el diseño hasta la puesta en producción, con foco en backend e inteligencia artificial aplicada. Tengo experiencia en proyectos de principio a fin, propios y freelance, con clientes y usuarios reales, con Python, React y Next.js, PostgreSQL y APIs REST.

Sobre la base que me da la carrera de Ingeniería de Sistemas (lógica de programación, análisis matemático y diseño de algoritmos), trabajo de forma autodidacta con tecnologías actuales, que aplico en proyectos propios con el código publicado. Lo combino con la gestión operativa de una PyME, donde sumo conocimientos de administración de empresas, producto y manejo de equipos.

Domino la IA aplicada al trabajo y a soluciones de producto: forma parte de mi proceso de desarrollo y de los productos que construyo. Las decisiones de producto, diseño y arquitectura son propias.

Ubicación
Argentina · Trabajo remoto
Idiomas
Español (nativo) · Inglés (B2)
Ciudadanía
Argentina e italiana (pasaporte de la UE)
Formación
Ingeniería de Sistemas · UNICEN · 2022 – actualidad
Certificación
Scrum Fundamentals Certified (SFC) · VMEdu · 2024

Experiencia

  1. Rugidos Fiestas Tandil

    PyME de eventos · Tandil, Argentina

    • Desarrollador de Softwaresep. 2023 – actualidad
    • Responsable de Operacionessep. 2019 – actualidad
    • Diseñé, desarrollé y mantengo el sitio web comercial de la empresa, en producción: primera versión en 2023 y rediseño integral en 2026, con diseño UX/UI propio.
    • Desarrollé FreeMagicMirror, una aplicación de fotomatón táctil que se usa en eventos.
    • Gestiono la operación diaria: organización de los eventos, optimización de procesos internos y mejoras del modelo de servicio, parte de ellas implementadas con software propio.

    Rugidos FiestasFreeMagicMirror

  2. SeViVe

    Estudio de pilates (franquicia) · Canning, Buenos Aires

    • Desarrollador Full Stack Freelancedic. 2025 – jun. 2026
    • Desarrollé como único programador una aplicación de reservas y gestión con más de 200 usuarios, desde la definición de requisitos con el cliente hasta la puesta en producción: reservas con control de concurrencia, créditos con vencimiento, turnos fijos y panel de administración.
    • Finalizado el desarrollo, continúo a cargo del soporte, la administración del servidor y las actualizaciones solicitadas por el cliente.

    SeViVe

  3. Navkok Security Group SRL

    Empresa de seguridad privada · Argentina

    • Desarrollador Web Freelancemar. 2026 – abr. 2026
    • Rediseñé el sitio institucional, desde la venta del proyecto hasta su finalización: arquitectura de información, diseño UX/UI, textos institucionales y contenido multimedia producido con herramientas de IA.

    Navkok Security Group