ragfastapiqdrantopenaiadropen-sourcepython

Abri DocuQuery como OSS — RAG con FastAPI y Qdrant, sin pretender que era perfecto

Tenia cinco repos privados en mi org de GitHub. Cada uno con descripcion bonita: “RAG production”, “multi-tenant LLM gateway”, “agent orchestration con LangGraph”. Cuando los abri por dentro, tres tenian un README de una linea y nada mas.

Hoy hice publico uno de los dos que si tenian codigo. Se llama DocuQuery.

Que es

Una plataforma RAG: subis PDFs, se trocean, se vectorizan, y respondes preguntas en lenguaje natural con citas a la fuente.

Stack:

Repo: github.com/GeosData/llm-rag-platform

La decision tecnica que escribi como ADR

El call menos obvio fue Qdrant en vez de pgvector. Ya tenia Postgres en el stack. pgvector hubiera sido cero infra nueva.

Termine eligiendo Qdrant por dos razones:

  1. Aislamiento del blast radius. Los queries RAG corren a tasa mucho mayor que el CRUD. Una recompactacion del indice o un burst de busquedas no deberia tumbar el resto de la API. Engine separado mantiene el daño contenido.
  2. Headroom de latencia. A 1M de vectores, p95 ~30ms en Qdrant me deja espacio para reranking, hybrid search, multi-vector. pgvector funciona, pero cada optimizacion gasta presupuesto de Postgres que otras tablas tambien necesitan.

Acepte el costo operativo: un container mas, otro storyboard de backup, otro health check.

El ADR completo esta en el repo: docs/adr/0001-vector-store-qdrant-vs-pgvector.md. Incluye la condicion para revisar la decision si el proyecto crece.

Lo que aprendi escribiendolo

Tenia el trade-off “intuitivo” en la cabeza desde hace meses. Cuando me sente a redactar el ADR, dos cosas pasaron:

Naval lo dice mejor que yo: si no podes escribirlo, no lo entendes. Lo confirme una vez mas.

Lo que no esta perfecto y deje publico igual

Antes de hoy el repo tenia el stack y el codigo, pero:

Tenia dos opciones: pulir tres semanas en privado y subir cuando estuviera “listo”, o publicar con lo justo y mejorar en commits visibles.

Eleji la segunda. Lo que agregue antes de flipear publico:

Coverage subio de 0% a 25% global, con services/chunker.py y services/rag.py en 100%. Hay services/ingest.py, services/embeddings.py y los handlers de API todavia sin cubrir. Esos vienen en commits proximos.

[B-ROLL: terminal con output pytest -v mostrando 8 passed]

No es buen ejemplo de “ship perfecto”. Es buen ejemplo de ship visible, mejorar visible. Un recruiter o un peer puede ver el repo hoy, ver los proximos commits, y leer la trayectoria. No puede leer una trayectoria que existe solo en mi maquina.

La leccion meta

La razon real por la que tenia repos privados con descripciones aspiracionales era simple: scaffold sin ship me hacia sentir que estaba avanzando sin exponerme al juicio de que el repo estuviera “incompleto”.

Es self-deception barato. Te genera la sensacion de portfolio sin el costo del feedback.

La regla que me puse para los proximos 90 dias:

Repo privado con descripcion ambiciosa pero sin codigo = falsa pieza de portfolio. O lo construyo y lo abro, o le pongo “Roadmap-only, no code yet” en la descripcion, o lo borro.

Tres de mis cinco repos privados caen en esa categoria. Decision pendiente sobre que hacer con cada uno.

Que sigue

DocuQuery hoy es alpha funcional. Los proximos commits que tengo apuntados:

Todo eso publico desde el primer commit.

Si te interesa el codigo o tenes feedback, el repo esta en github.com/GeosData/llm-rag-platform. Issues abiertos.

Volver al blog