Skip to main content
Glama
FireWizard-V9

self_rag_mcp

Motor de Recuperación Self-RAG

Sistema de Generación Aumentada por Recuperación Auto-Reflexiva construido con LangGraph, Qdrant y expuesto como un servidor MCP (Model Context Protocol) sobre transporte SSE.

A diferencia de los pipelines RAG estándar que recuperan y generan a ciegas, Self-RAG hace que el LLM sea un participante activo en su propio control de calidad: decide si recuperar, califica lo recuperado, verifica lo generado y reintenta cuando la respuesta no es lo suficientemente buena.


Tabla de Contenidos


Related MCP server: mcp-rag-agent

¿Qué es Self-RAG?

El RAG estándar tiene un problema fundamental: siempre recupera (incluso cuando no es necesario), nunca verifica si los documentos recuperados son relevantes y nunca comprueba si la respuesta generada está realmente fundamentada en esos documentos.

Self-RAG (introducido en el artículo Self-RAG: Learning to Retrieve, Generate, and Critique Through Self-Reflection) resuelve esto insertando pasos de reflexión en cada etapa:

Etapa

RAG Estándar

Self-RAG

Decisión de recuperación

Siempre recupera

El LLM decide si la recuperación es necesaria

Filtrado de documentos

Usa todos los documentos recuperados

El LLM califica cada documento por relevancia

Generación

Genera una vez

Genera, luego verifica la fundamentación

Calidad de la respuesta

Sin verificación

El LLM califica la utilidad, reintenta si es necesario

Esta implementación utiliza LangGraph para modelar el flujo Self-RAG como un grafo dirigido con estado y aristas condicionales, permitiendo enrutamiento dinámico, bucles de reintento y trazabilidad completa del estado.


Resumen de Arquitectura

┌─────────────────────────────────────────────────────────────────┐
│                        MCP Client (SSE)                         │
│                    rich interactive terminal                     │
└──────────────────────────┬──────────────────────────────────────┘
                           │ SSE  http://127.0.0.1:8000/sse
┌──────────────────────────▼──────────────────────────────────────┐
│                      MCP Server (SSE)                           │
│              MCPServer  ·  3 tools exposed                      │
│         rag_answer  ·  retrieve  ·  server_health               │
└──────────┬──────────────────────────────┬───────────────────────┘
           │                              │
┌──────────▼──────────┐       ┌───────────▼──────────────────────┐
│   Self-RAG Graph    │       │       Hybrid Retriever           │
│   (LangGraph)       │       │                                  │
│                     │       │  1. Qdrant Hybrid Search         │
│  retrieval_decision │       │     Dense (OpenAI embeddings)    │
│  retrieve           │       │     Sparse (BM25 / FastEmbed)    │
│  relevance_grader   │       │     Fusion: RRF                  │
│  context_builder    │       │                                  │
│  generator          │       │  2. MMR Diversity Reranking      │
│  support_grader     │       │                                  │
│  usefulness_grader  │       │  3. FlashRank Cross-Encoder      │
│                     │       │     (ms-marco-MiniLM-L-12-v2)    │
└──────────┬──────────┘       │                                  │
           │                  │  4. Parent Document Expansion    │
           │                  └───────────────┬──────────────────┘
           │                                  │
┌──────────▼──────────────────▼──────────────────────────────────┐
│                         Qdrant                                  │
│                                                                 │
│   self_rag_documents  (child chunks  · dense + sparse)         │
│   self_rag_parents    (parent chunks · dense only)             │
└─────────────────────────────────────────────────────────────────┘

Flujo del Grafo Self-RAG

flowchart TD
    START([START]) --> RD[retrieval_decision]

    RD -->|should_retrieve = true| RET[retrieve]
    RD -->|should_retrieve = false| GEN[generator]

    RET --> REL[relevance_grader]
    REL --> CTX[context_builder]
    CTX --> GEN

    GEN --> SUP[support_grader]

    SUP -->|fully_supported\npartially_supported| USE[usefulness_grader]
    SUP -->|not_supported\n& retry_count < max_retries| INC1[increment_retry]
    SUP -->|not_supported\n& retry_count >= max_retries| USE

    INC1 --> GEN

    USE -->|useful| END([END])
    USE -->|not_useful\n& retry_count >= max_retries| END
    USE -->|not_useful\n& retry_count < max_retries| INC2[increment_retry_for_retrieval]

    INC2 --> RET

    style START fill:#2d6a4f,color:#fff
    style END fill:#2d6a4f,color:#fff
    style RD fill:#1d3557,color:#fff
    style RET fill:#457b9d,color:#fff
    style REL fill:#457b9d,color:#fff
    style CTX fill:#457b9d,color:#fff
    style GEN fill:#e63946,color:#fff
    style SUP fill:#f4a261,color:#000
    style USE fill:#f4a261,color:#000
    style INC1 fill:#6d6875,color:#fff
    style INC2 fill:#6d6875,color:#fff

Referencia de Nodos

retrieval_decision

El punto de entrada del grafo. El LLM analiza la pregunta del usuario y decide si la recuperación de conocimiento externo es realmente necesaria.

  • Consultas conversacionales ("Hola", "¿Cuánto es 2+2?") → omitir recuperación, ir directamente a generator

  • Consultas factuales / de dominio → proceder a retrieve

Utiliza salida estructurada: RetrievalDecision { thought: str, answer: "YES" | "NO" }


retrieve

Ejecuta el Pipeline de Recuperación Híbrida completo contra Qdrant:

  1. Búsqueda Híbrida — combina vectores densos (OpenAI text-embedding-3-small) y dispersos (BM25 vía FastEmbed), fusionados en el servidor con Fusión de Rango Recíproco (RRF)

  2. MMR — Reordenamiento de Relevancia Marginal Máxima para diversidad (evita devolver fragmentos casi duplicados)

  3. FlashRank — reordenador de codificador cruzado ONNX ligero (ms-marco-MiniLM-L-12-v2) para la puntuación final de relevancia

  4. Expansión Parental — los fragmentos hijos se recuperan para precisión, pero el fragmento padre completo se devuelve al LLM para un contexto más rico


relevance_grader

Filtra los documentos recuperados. Cada documento es calificado individualmente por el LLM contra la pregunta.

  • Documentos calificados como YES → se mantienen como relevant_documents

  • Documentos calificados como NO → se descartan

Utiliza salida estructurada: RelevanceGrade { thought: str, answer: "YES" | "NO" }


context_builder

Formatea los documentos relevantes en un bloque de contexto XML estructurado optimizado para la atención del LLM:

<context>
  <document index="1">
    <metadata>Source: hr.pdf | Relevance Score: 0.9821</metadata>
    <content>
      Human Resource Management (HRM) refers to...
    </content>
  </document>
</context>

generator

El LLM genera una respuesta utilizando solo los hechos del bloque de contexto. El prompt instruye explícitamente al modelo a no usar conocimiento externo y a citar los índices de los documentos ([Doc 1]).


support_grader

Verifica que la respuesta generada esté fundamentada en el contexto. Realiza una auditoría afirmación por afirmación.

Devuelve uno de:

  • fully_supported — cada afirmación está respaldada por el contexto

  • partially_supported — algunas afirmaciones están fundamentadas, otras no

  • not_supported — la respuesta contiene alucinaciones o contradice el contexto

Utiliza salida estructurada: SupportGrade { thought: str, label: "fully_supported" | "partially_supported" | "not_supported" }


usefulness_grader

Evalúa si la respuesta realmente resuelve la pregunta del usuario — incluso si está fundamentada, podría ser evasiva o incompleta.

Devuelve uno de:

  • useful — la respuesta satisface directamente la consulta

  • not_useful — la respuesta está fuera de tema, es incompleta o evasiva

Utiliza salida estructurada: UsefulnessGrade { thought: str, label: "useful" | "not_useful" }


increment_retry / increment_retry_for_retrieval

Nodos de contabilidad que incrementan retry_count en el estado del grafo antes de volver a generator o retrieve respectivamente.


Lógica de Enrutamiento

Router

Condición

Siguiente Nodo

route_after_retrieval_decision

should_retrieve = True

retrieve

should_retrieve = False

generator

route_after_support

fully_supported o partially_supported

usefulness_grader

not_supported y retry_count < max_retries

increment_retrygenerator

not_supported y retry_count >= max_retries

usefulness_grader

route_after_usefulness

useful

END

not_useful y retry_count < max_retries

increment_retry_for_retrievalretrieve

not_useful y retry_count >= max_retries

END


Pipeline de Recuperación

Query
  │
  ▼
Qdrant Hybrid Search (Dense + BM25 + RRF)   k=20 candidates
  │
  ▼
MMR Diversity Reranking                      k=15 diverse docs
  │
  ▼
FlashRank Cross-Encoder                      top_k=4 final docs
  │
  ▼
Parent Document Expansion                    fetch full parent chunks
  │
  ▼
List[Document] → relevance_grader

¿Por qué este embudo de múltiples etapas?

  • La búsqueda híbrida (densa + dispersa) ofrece mejor recall que cualquiera de las dos por separado — la densa captura coincidencias semánticas, BM25 captura coincidencias exactas de palabras clave

  • MMR evita que el LLM vea 4 fragmentos casi idénticos — fuerza la diversidad

  • FlashRank (ONNX int8 cuantizado) ofrece calidad de codificador cruzado en ~0.1s frente a ~19s de un CrossEncoder PyTorch completo

  • La expansión parental significa que la precisión de la recuperación proviene de fragmentos hijos pequeños, pero el LLM recibe el contexto completo circundante


Pipeline de Ingestión

Los documentos se dividen en una jerarquía de fragmentos padre-hijo:

PDF Document
  │
  ├── Parent Chunk 1  (1200 chars, overlap=0)  → stored in self_rag_parents
  │     ├── Child Chunk 1a  (600 chars, overlap=150)  → stored in self_rag_documents
  │     ├── Child Chunk 1b
  │     └── Child Chunk 1c
  │
  ├── Parent Chunk 2
  │     ├── Child Chunk 2a
  │     └── Child Chunk 2b
  ...
  • Fragmentos hijos se indexan con vectores densos y dispersos para precisión en la búsqueda híbrida

  • Fragmentos padres se almacenan solo con vectores densos, utilizados para la expansión de contexto después de la recuperación

  • Los UUID son deterministas (UUID5) para que la re-ingestión sea idempotente


Servidor y Cliente MCP

El sistema se expone como un servidor MCP sobre transporte SSE, lo que lo hace compatible con cualquier cliente MCP (Claude Desktop, clientes personalizados, etc.).

Herramientas

Herramienta

Descripción

rag_answer

Ejecuta el grafo Self-RAG completo — decisión de recuperación → recuperar → calificar → generar → verificar → reintentar

retrieve

Recuperación híbrida cruda solamente, sin generación ni calificación

server_health

Devuelve el estado operativo de los componentes de recuperación y reordenamiento

Cliente Interactivo

Se incluye un cliente de terminal enriquecido con una interfaz basada en menús:

╭─────────────────────────────────╮
│ Self-RAG MCP Interactive Client │
│ Connected via SSE Transport     │
╰─────────────────────────────────╯

[1] 💬 Ask Question     (rag_answer)
[2] 🔍 Raw Search       (retrieve)
[3] 🏥 System Health    (server_health)
[4] 📋 List Tools
[0] 🚪 Exit

Estructura del Proyecto

self_rag_retrieval/
├── src/self_rag/
│   ├── clients/
│   │   ├── llm.py              # LiteLLM chat model + OpenAI embeddings (cached)
│   │   └── qdrant.py           # Qdrant client singleton
│   ├── core/
│   │   └── config.py           # Pydantic settings from .env
│   ├── graph/
│   │   ├── engine.py           # Compiled graph singleton (lru_cache)
│   │   ├── routes.py           # Conditional edge routing functions
│   │   └── workflow.py         # LangGraph StateGraph definition
│   ├── ingestion/
│   │   ├── chunker.py          # Parent-child chunk splitting
│   │   ├── indexer.py          # Qdrant collection management
│   │   ├── loaders.py          # PDF loader
│   │   └── pipeline.py         # Ingestion orchestration
│   ├── mcp/
│   │   ├── server.py           # MCPServer with 3 tools + startup warmup
│   │   ├── mcp_client.py       # Rich interactive terminal client
│   │   └── tools.py            # Tool implementations (answer, retrieve, health)
│   ├── models/
│   │   ├── graph_state.py      # LangGraph TypedDict state
│   │   └── schemas.py          # Pydantic structured output schemas
│   ├── nodes/
│   │   ├── context_builder.py  # XML context formatter
│   │   ├── generator.py        # LLM answer generation
│   │   ├── relevance_grader.py # Per-document relevance grading
│   │   ├── retrieval_decision.py # Retrieval necessity classifier
│   │   ├── retrieve.py         # Retrieval node
│   │   ├── support_grader.py   # Hallucination / grounding checker
│   │   └── usefulness_grader.py # Answer quality checker
│   ├── prompts/
│   │   ├── generation.py
│   │   ├── relevance.py
│   │   ├── retrieval.py
│   │   ├── support.py
│   │   └── usefulness.py
│   ├── retrieval/
│   │   ├── mmr.py              # Maximal Marginal Relevance
│   │   ├── reranker.py         # FlashRank ONNX cross-encoder
│   │   ├── retriever.py        # HybridRetriever orchestrator (cached)
│   │   └── vector_store.py     # Qdrant vector store (dense + sparse, cached)
│   └── services/
│       └── rag_service.py      # Business layer wrapping the graph
├── scripts/
│   └── ingest.py               # CLI ingestion script
├── tests/
│   ├── test_mcp_server.py
│   ├── test_mcp_tools.py
│   └── test_routes.py
├── docker-compose.yaml
├── pyproject.toml
└── .env

Configuración e Instalación

Requisitos previos

  • Python 3.12+

  • Gestor de paquetes uv

  • Docker (para Qdrant)

  • Clave API de OpenRouter

1. Clonar e instalar dependencias

git clone <repo-url>
cd self_rag_retrieval
uv sync

2. Configurar el entorno

cp .env.example .env

Editar .env:

OPENROUTER_API_KEY=sk-or-v1-...

CHAT_MODEL=openrouter/openai/gpt-4.1-mini
EMBEDDING_MODEL=openai/text-embedding-3-small

QDRANT_URL=http://localhost:6333
QDRANT_COLLECTION=self_rag_documents
QDRANT_PARENT_COLLECTION=self_rag_parents

DATA_DIR=src/self_rag/data

3. Iniciar Qdrant

docker compose up -d

4. Añadir tus documentos

Coloca archivos PDF en src/self_rag/data/.

5. Ingerir documentos

# First time
uv run python scripts/ingest.py

# Full rebuild (wipes existing collections)
uv run python scripts/ingest.py --reset

Configuración

Todos los ajustes están en .env y son validados por Pydantic. Parámetros clave:

Variable

Default

Descripción

CHAT_MODEL

openrouter/openai/gpt-4.1-mini

LLM para todos los nodos de calificación y generación

EMBEDDING_MODEL

openai/text-embedding-3-small

Modelo de embeddings densos

CHUNK_SIZE

600

Tamaño de fragmento hijo (caracteres)

CHUNK_OVERLAP

150

Solapamiento de fragmentos hijos

PARENT_CHUNK_SIZE

1200

Tamaño de fragmento padre (caracteres)

RETRIEVAL_K_INITIAL

20

Pool de candidatos de búsqueda híbrida

RETRIEVAL_K_MMR

15

Documentos después del filtro de diversidad MMR

RETRIEVAL_K_RERANK

4

Documentos finales después de FlashRank

MAX_RETRIES

3

Máximo de bucles de reintento Self-RAG

LLM_TEMPERATURE

0.0

Temperatura del LLM (0 = determinista)


Ejecución del Sistema

Terminal 1 — Iniciar el servidor MCP

uv run python src/self_rag/mcp/server.py

El servidor calienta todos los modelos antes de aceptar conexiones:

INFO  Warming up retriever...
INFO  Warming up reranker...
INFO  Warming up graph...
INFO  Warmup complete — server ready.
INFO  Uvicorn running on http://127.0.0.1:8000

Terminal 2 — Iniciar el cliente interactivo

uv run python src/self_rag/mcp/mcp_client.py

Preguntas de ejemplo (dominio de RRHH)

What is Human Resource Management and what are its main objectives?
What are the nine broad areas of HRM activities identified by ASTD?
What is the difference between training and organizational development?
How does compensation and benefits management work in HRM?
What is the role of HRM in the new millennium?
What is the significance of HR planning in an organization?
Explain the scope of HRM and what it covers in an employee's working life.

Ejecución de Pruebas

uv run pytest tests/ -v
tests/test_routes.py::test_retrieval_decision_retrieve          PASSED
tests/test_routes.py::test_retrieval_decision_skip              PASSED
tests/test_routes.py::test_support_fully_supported_...          PASSED
tests/test_routes.py::test_support_not_supported_retries...     PASSED
tests/test_routes.py::test_usefulness_useful_ends               PASSED
...
24 passed

Cobertura de pruebas:

  • test_routes.py — todas las ramas de enrutamiento (decisión de recuperación, calificación de soporte, calificación de utilidad)

  • test_mcp_tools.py — funciones de herramientas con Qdrant/LLM simulados (entrada vacía, limitación, excepciones, salud)

  • test_mcp_server.py — tipo de servidor, registro de herramientas, descripciones de herramientas


Stack Tecnológico

Componente

Tecnología

Orquestación de grafos

LangGraph

Enrutamiento de LLM

LiteLLM vía OpenRouter

LLM

OpenAI GPT-4.1-mini (vía OpenRouter)

Embeddings

OpenAI text-embedding-3-small (vía OpenRouter)

Base de datos vectorial

Qdrant

Embeddings dispersos

FastEmbed BM25

Reordenador

FlashRank ms-marco-MiniLM-L-12-v2 (ONNX int8)

Marco MCP

MCP Python SDK v2

Configuración

Pydantic Settings

Interfaz de terminal

Rich

Gestor de paquetes

uv

Tiempo de ejecución

Python 3.12

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Adaptive Retrieval-Augmented Self-Refinement MCP Server — a closed-loop system that lets LLMs iteratively verify and correct their own claims using uncertainty-guided retrieval.
    11
    1
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Exposes a Retrieval-Augmented Generation pipeline as MCP tools, allowing users to index documents and query them through any MCP-compatible client like Claude or IDEs.

View all related MCP servers

Related MCP Connectors

  • AI Reasoning Cache & Consensus Layer with 11 MCP tools via Streamable HTTP.

  • MCP server exposing the Backtest360 engine API as tools for AI agents.

  • MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/FireWizard-V9/self_rag_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server