Saltar a contenido

RAG Hub — Infraestructura

Visión general

                    ┌─────────────────────────┐
                    │    FastAPI RAG Hub      │
                    │   (puerto 8000)         │
                    │                         │
                    │  GET  /health           │
                    │  GET  /models           │
                    │  GET  /collections      │
                    │  POST /query/{col}      │
                    │  POST /v1/chat/complet  │
                    │  POST /responses        │
                    └──────┬──────────┬───────┘
                           │          │
              ┌────────────┘          └────────────┐
              ▼                                     ▼
     ┌─────────────────┐                  ┌─────────────────┐
     │     Ollama      │                  │     Qdrant      │
     │  localhost:11434│                  │  localhost:6333 │
     │                 │                  │                 │
     │ mxbai-embed-lrg │                  │ smallcountry    │ ← 1024d
     │ deepseek-r1:8b  │                  │ (futuras...)    │
     └─────────────────┘                  └─────────────────┘
              │                                  │
              └──────────────────┬───────────────┘
                      ┌─────────────────────┐
                      │   Consumidores       │
                      │                      │
                      │ • Hermes Agent       │
                      │ • AnythingLLM        │
                      │   (Docker, vía Resp.)│
                      │ • Bot Telegram       │
                      └──────────────────────┘

Servicios

Servicio Puerto Estado Cómo se gestiona
RAG Hub API 8000 🟢 systemd user systemctl --user {start,stop,restart} rag-hub.service
Auto-indexer 🟢 systemd user systemctl --user {start,stop,restart} rag-hub-indexer.service
Check integridad 🟢 timer noc. systemctl --user start rag-hub-integrity.service
Ollama 11434 🟢 Docker docker compose en ~/ai-stack/
Qdrant 6333 🟢 Docker Mismo compose
AnythingLLM 3002 🟢 Docker indep. Ver sección integración

Ubicación del proyecto

Ruta Contenido
~/ai-stack/rag-api/ Código fuente del Hub
~/ai-stack/rag-api/main.py FastAPI app (174 líneas)
~/ai-stack/rag-api/collection_config.py Config de colecciones (fuente de verdad)
~/ai-stack/rag-api/embedding_router.py Routing de embeddings
~/ai-stack/rag-api/auto_indexer.py Watchdog (inotify)
~/ai-stack/rag-api/check_integrity.py Verificación nocturna
~/ai-stack/rag-api/migrate_smallcountry.py Migración 768d → 1024d
~/.config/systemd/user/rag-hub.service Unit systemd API
~/.config/systemd/user/rag-hub-indexer.service Unit systemd indexer
~/.config/systemd/user/rag-hub-integrity.{service,timer} Unit systemd integridad
~/ai-stack/anythingllm_data/ Datos persistentes AnythingLLM (Docker volume)

Colecciones y embeddings

Colección Modelo Dim Origen Estado
smallcountry mxbai-embed-large 1024 Ollama 🟢 787 pts (migrada)
smallcountry_full nomic-embed-text 768 Ollama ⏳ Legacy (backup)

Migración de embedding

Los documentos fueron indexados originalmente con nomic-embed-text (768d). Para mejorar calidad en español se migró a mxbai-embed-large (1024d).

cd ~/ai-stack/rag-api && .venv/bin/python migrate_smallcountry.py

Resultado: 787 puntos migrados de 865 (78 omitidos por texto binario).

Systemd services

rag-hub.service (API server)

[Unit]
Description=RAG Hub API Server — FastAPI multi-embedding Qdrant
After=network-online.target

[Service]
Type=simple
Environment=PYTHONUNBUFFERED=1
WorkingDirectory=/home/tonatiuh/ai-stack/rag-api
ExecStart=/home/tonatiuh/ai-stack/rag-api/.venv/bin/python -u main.py
Restart=always
RestartSec=5

[Install]
WantedBy=default.target

rag-hub-indexer.service (auto-indexador watchdog)

Vigila ~/SmallCountry/ con inotify. Al crear o modificar un .md/.txt/.pdf, lo fragmenta, lo embediza con el modelo de la colección, y lo indexa en Qdrant.

rag-hub-integrity.timer (check nocturno)

Se ejecuta cada día a las 00:00. Verifica que todos los archivos en los directorios vigilados estén correctamente indexados. Si un archivo cambió (hash SHA256 diferente), lo re-indexa automáticamente.

systemctl --user list-timers | grep rag

Integración con AnythingLLM

La conexión se hace vía Responses API (OpenAI nuevo formato).

Configuración del contenedor Docker

docker run -d --name anythingllm \
  -p 3002:3001 \
  -v ~/ai-stack/anythingllm_data:/app/server/storage \
  -e STORAGE_DIR=/app/server/storage \
  -e OLLAMA_BASE_URL=http://host.docker.internal:11434 \
  -e QDRANT_ENDPOINT=http://host.docker.internal:6333 \
  -e OPENAI_BASE_URL=http://host.docker.internal:8000 \
  --add-host host.docker.internal:host-gateway \
  mintplexlabs/anythingllm:latest

Configuración en la UI

  1. Settings → LLM → OpenAI: API key dummy (sk-not-needed-local-rag-hub)
  2. Workspace → modelo: gpt-4o (el Hub lo redirige a smallcountry)
  3. El Hub expone GET /models para que AnythingLLM descubra modelos disponibles
  4. Las consultas se envían a POST /responses con formato Responses API

Formato Responses API

AnythingLLM envía las consultas en el nuevo formato OpenAI Responses API:

{
  "model": "gpt-4o",
  "input": [
    {"role": "system", "content": [{"type": "input_text", "text": "system prompt"}]},
    {"role": "user", "content": [{"type": "input_text", "text": "¿pregunta?"}]}
  ]
}

El RAG Hub aplanea recursivamente estos mensajes, embediza la query, busca en Qdrant y genera respuesta con deepseek-r1:8b.

Errores comunes y solución

Error Causa Solución
404 en /models Endpoint no implementado Añadir GET /models al Hub
400 en /responses Formato Responses API no soportado Añadir POST /responses con flatten recursivo
500 en responses content es lista de Aplanar item.content como lista, no string
host.docker.internal no resuelve Falta --add-host Añadir --add-host host.docker.internal:host-gateway

Modelos Ollama disponibles

Modelo Uso
mxbai-embed-large Embeddings (español, 1024d) — principal
nomic-embed-text Embeddings (fallback, 768d)
deepseek-r1:8b Generación de respuestas RAG
gemma4:e2b-it-q8_0 Chat general (AnythingLLM anterior)
qwen3-vl:8b Modelo multimodal (vision + texto)

Lo que NO se usa

  • LlamaIndex — routing manual es más simple
  • Cron — reemplazado por systemd timers (journald, Persistent=true)
  • APIs externas de embedding — todo 100% offline
  • OpenAI real — el Hub reemplaza la necesidad de API keys externas