Skip to main content
Glama
fellgar246
by fellgar246
README.md
# FAQ RAG Chatbot — PeopleForce HR SaaS

Sistema de chatbot inteligente de soporte para FAQs basado en **Retrieval-Augmented Generation (RAG)**. Procesa un documento de preguntas frecuentes de una empresa HR SaaS, lo indexa en una base de datos vectorial y responde preguntas de usuarios recuperando los fragmentos más relevantes del documento para generar respuestas precisas con un LLM. Esto elimina la necesidad de búsquedas manuales y reduce la carga del equipo de soporte al cliente.

---

## Arquitectura RAG

```
┌──────────────────────────────────────────────────────────────────┐
│                    PIPELINE DE INDEXACIÓN                        │
│                                                                  │
│  faq_document.txt ──► Chunking ──► Embeddings ──► ChromaDB      │
│                     (300 chars,   (text-embedding   (persistente │
│                      50 overlap)   -3-small)         local)      │
└──────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────┐
│                    PIPELINE DE CONSULTA                          │
│                                                                  │
│  Pregunta ──► Embedding ──► k-NN Search ──► Contexto ──► LLM    │
│  del usuario   de query     (coseno,        (top-k       (gpt-4o │
│                              ChromaDB)       chunks)      -mini)  │
│                                                     │            │
│                                                     ▼            │
│                                              JSON Response       │
│                                        { user_question,          │
│                                          system_answer,          │
│                                          chunks_related }        │
└──────────────────────────────────────────────────────────────────┘
```

---

## Instalación

### 1. Clonar el repositorio

```bash
git clone <repo-url>
cd kunz-mcp-project
```

### 2. Crear entorno virtual e instalar dependencias

```bash
python -m venv .venv
source .venv/bin/activate   # macOS/Linux
# .venv\Scripts\activate    # Windows

pip install -r requirements.txt
```

### 3. Configurar API Key

```bash
cp .env.example .env
# Edita .env y agrega tu clave de OpenAI:
# OPENAI_API_KEY=sk-...
```

---

## Uso

### Ejecutar el pipeline de indexación

```bash
python src/build_index.py
```

Esto carga `data/faq_document.txt`, lo divide en chunks, genera embeddings y los almacena en ChromaDB (`data/chroma_db/`).

### Ejecutar una consulta

```bash
python src/query.py "¿Cuántos días de vacaciones me corresponden?"
```

Salida JSON de ejemplo:

```json
{
  "user_question": "¿Cuántos días de vacaciones me corresponden?",
  "system_answer": "Todos los colaboradores de tiempo completo tienen derecho a 15 días hábiles de vacaciones al año a partir de su primer aniversario. Con más de 3 años de antigüedad, se reciben 20 días hábiles, y con más de 7 años, 25 días hábiles.",
  "chunks_related": [
    {
      "text": "¿Cuántos días de vacaciones me corresponden?...",
      "metadata": {
        "chunk_index": 1,
        "total_chunks": 30,
        "source": "faq_document.txt"
      }
    }
  ]
}
```

### Ejecutar el agente evaluador (Bonus)

```bash
python src/evaluator.py
```

Evalúa las respuestas en `outputs/sample_queries.json` y devuelve un puntaje 0-10 con justificación.

---

## Servidor MCP (Model Context Protocol)

El proyecto incluye `src/mcp_server.py`, que expone el pipeline RAG como un servidor **MCP** para que agentes de IA (Claude Desktop, Cursor, VS Code con Copilot, etc.) puedan invocar las herramientas directamente.

### Tools disponibles

| Tool | Descripción |
|---|---|
| `ask_hr_faq(question)` | Pipeline RAG completo: busca en ChromaDB y genera respuesta con GPT-4o-mini |
| `evaluate_rag_response(user_question, system_answer, chunks_related)` | Evalúa la calidad de una respuesta RAG (puntaje 0-10 con justificación) |
| `rebuild_index()` | Reindexar el documento FAQ en ChromaDB (útil tras actualizar el FAQ) |

### Prerequisito

Asegúrate de haber construido el índice antes de levantar el servidor:

```bash
python src/build_index.py
```

### Opción A — Ejecutar directamente (modo stdio)

```bash
python src/mcp_server.py
```

Esto lanza el servidor en modo `stdio`, compatible con cualquier cliente MCP.

### Opción B — Ejecutar con MCP CLI

```bash
mcp run src/mcp_server.py
```

### Opción C — Integrar con Claude Desktop

Edita el archivo de configuración de Claude Desktop:

- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "hr-faq-rag": {
      "command": "python",
      "args": ["/ruta/absoluta/a/kunz-mcp-project/src/mcp_server.py"],
      "env": {
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}
```

Reinicia Claude Desktop. El servidor aparecerá como herramienta disponible en el chat.

### Opción D — Integrar con Cursor o VS Code

Agrega en la configuración MCP del editor (`.cursor/mcp.json` o `settings.json`):

```json
{
  "mcpServers": {
    "hr-faq-rag": {
      "command": "python",
      "args": ["src/mcp_server.py"]
    }
  }
}
```

> **Nota**: el servidor lee `OPENAI_API_KEY` desde el archivo `.env` del proyecto; si el editor no hereda el entorno, pásala explícitamente en el bloque `"env"` como se muestra en la Opción C.

---

## Estructura del proyecto

```
kunz-mcp-project/
├── README.md               # Documentación del proyecto
├── requirements.txt        # Dependencias con versiones
├── .env.example            # Plantilla de variables de entorno
├── config.yaml             # Configuración del modelo, embeddings y RAG
├── data/
│   └── faq_document.txt    # Documento FAQ fuente (≥1000 palabras)
├── src/
│   ├── __init__.py
│   ├── build_index.py      # Pipeline de indexación (load → chunk → embed → store)
│   ├── query.py            # Pipeline de consulta (search → generate → JSON)
│   ├── evaluator.py        # Agente evaluador de calidad (bonus)
│   ├── mcp_server.py       # Servidor MCP (expone los tools vía FastMCP)
│   └── shared/
│       ├── __init__.py
│       ├── config_loader.py  # Carga config.yaml + .env
│       └── logger.py         # Logger con Rich (colores y formato)
└── outputs/
    └── sample_queries.json   # ≥3 ejemplos de consulta-respuesta
```

---

## Decisiones técnicas

### Estrategia de chunking

Se usa **`RecursiveCharacterTextSplitter`** con `chunk_size=300` y `chunk_overlap=50`.

- **¿Por qué recursivo?** Los separadores jerárquicos (`\n\n` → `\n` → `.` → ` `) preservan los límites semánticos naturales del texto (secciones, párrafos, oraciones), produciendo chunks más coherentes que un corte por tamaño fijo.
- **¿Por qué 300 caracteres?** Genera chunks de ~75-125 tokens, dentro del rango requerido de 50-500 tokens. Chunks más pequeños mejoran la precisión de la búsqueda vectorial al reducir el ruido semántico.
- **¿Por qué 50 de overlap?** El solapamiento asegura continuidad de contexto entre chunks adyacentes, evitando que información relevante quede cortada en un límite.

### Método de búsqueda vectorial

Se usa **k-NN (k-Nearest Neighbors) con similitud coseno** sobre el índice HNSW de ChromaDB.

- **¿Por qué k-NN?** Es el método más directo y predecible para búsqueda de vectores similares. ChromaDB optimiza internamente con HNSW (Hierarchical Navigable Small World) para búsquedas sub-lineales.
- **¿Por qué coseno?** La similitud coseno mide la dirección semántica de los vectores, no su magnitud. Es ideal para embeddings de texto normalizados como los de OpenAI (`text-embedding-3-small`), donde vectores con significado similar apuntan en la misma dirección.
- **Top-k = 3** retorna entre 2-5 chunks por consulta, suficientes para dar contexto sin introducir ruido.

### Beneficios de RAG

- **Actualización sin re-training**: Basta con actualizar el documento fuente y re-indexar, sin necesidad de fine-tuning costoso del LLM.
- **Transparencia**: Cada respuesta incluye los chunks utilizados (`chunks_related`), permitiendo verificar la fuente de información.
- **Atribución**: Los metadatos de cada chunk (`source`, `chunk_index`) habilitan la trazabilidad completa de la respuesta.

---

## Configuración

El archivo `config.yaml` centraliza todos los parámetros:

| Parámetro | Valor | Descripción |
|-----------|-------|-------------|
| `model.name` | `gpt-4o-mini` | Modelo LLM para generación |
| `model.temperature` | `0.3` | Baja temperatura para respuestas consistentes |
| `embedding.model` | `text-embedding-3-small` | Modelo de embeddings (1536 dims) |
| `rag.chunk_size` | `300` | Tamaño máximo de chunk en caracteres |
| `rag.chunk_overlap` | `50` | Solapamiento entre chunks |
| `rag.top_k` | `3` | Chunks a recuperar por consulta |
| `rag.collection` | `faq_hr_saas` | Nombre de la colección en ChromaDB |