> For the complete documentation index, see [llms.txt](https://public-intelligence.gitbook.io/taina-agente-ia-ogtic/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://public-intelligence.gitbook.io/taina-agente-ia-ogtic/empezando-con-taina/installation.md).

# Instalación paso a paso

Esta guía te acompañará paso a paso para instalar y poner en marcha a Taína Agente IA en un servidor de producción. Al finalizar, tendrás el agente funcionando y listo para atender ciudadanos.

## Antes de comenzar

Asegúrate de haber completado estos pasos previos:

* [x] Servidor con Ubuntu 22.04+ y Docker instalado → [Preparación del servidor](/taina-agente-ia-ogtic/empezando-con-taina/prerrequisitos.md)
* [x] Credenciales de servicios obtenidas → [Variables de entorno](/taina-agente-ia-ogtic/empezando-con-taina/configuracion-entorno.md)

## Paso 1 – Clonar el repositorio

Conéctate a tu servidor y clona el repositorio de Taína:

```bash
git clone <url-del-repositorio> taina_ogtic
cd taina_ogtic
```

> Sustituye `<url-del-repositorio>` por la URL real del repositorio Git proporcionada por la OGTIC.

Verifica la estructura del proyecto:

```bash
ls -la
```

Deberías ver al menos estos directorios y archivos:

```
taina_ogtic/
├── docker-compose.yml              # Composición de servicios Docker
└── backend/                        # Código fuente del agente
    ├── Dockerfile                  # Imagen Docker (Python 3.11)
    ├── .env.example                # Plantilla de variables de entorno
    ├── requirements.txt            # Dependencias Python
    ├── setup_databases.sh          # ★ Script maestro de ingesta
    ├── google_bucket_config.json.example  # Plantilla credenciales GCP
    │
    ├── src/                        # ─── Código fuente principal ───
    │   ├── main.py                 # Punto de entrada del agente (LiveKit worker)
    │   ├── tools.py                # 8 herramientas del catálogo de servicios
    │   ├── prompts.py              # System prompt y contexto del LLM
    │   ├── ingest.py               # Pipeline de ingesta JSON → ChromaDB
    │   ├── embeddings/             # Embeddings con Google Gemini
    │   │   └── gemini_embedding.py
    │   ├── vectors/                # Cliente ChromaDB
    │   │   └── chroma_vector.py
    │   ├── qa/                     # Generación QA y catálogo
    │   │   ├── catalog.py          # Escanea data/chunks/ → catálogo
    │   │   ├── generator.py        # Genera pares pregunta-respuesta
    │   │   └── build_qa_index.py   # Construye colección QA
    │   ├── utils/                  # Utilidades
    │   │   ├── doc_loader.py       # Carga y valida documentos JSON
    │   │   ├── doc_split.py        # Splitting de documentos
    │   │   ├── logger.py           # Sistema de logging
    │   │   └── rate_limiter.py     # Rate limiting para APIs
    │   └── handlers/               # Manejadores de errores
    │       └── error_handler.py
    │
    ├── scripts/                    # ─── Scripts de automatización ───
    │   └── auth_get_token.sh       # Obtiene token JWT del Catálogo
    │
    ├── preprocessing/              # ─── Pipeline de datos ───
    │   ├── fetch_service.sh        # Descarga servicio de la API
    │   ├── process_service.py      # Limpia HTML, genera chunks RAG
    │   ├── run_pipeline.sh         # Pipeline completo por servicio
    │   ├── batch_process.sh        # Procesamiento en lote
    │   └── setup_pipeline.sh       # Instalación de dependencias
    │
    ├── data/                       # ─── Datos ───
    │   ├── chunks/                 # Archivos *_rag_documents.json
    │   ├── QA/                     # Pares pregunta-respuesta (generados)
    │   └── service_ids.txt         # IDs de servicios a descargar
    │
    ├── storage/                    # ─── Persistencia (auto-generado) ───
    │   ├── chroma/                 # Colección principal ChromaDB
    │   └── chroma_qa/              # Colección QA ChromaDB
    │
    └── logs/                       # Logs del agente (rotados)
```

## Paso 2 – Configurar las variables de entorno

Copia la plantilla de variables de entorno y edítala con tus credenciales reales:

```bash
cp backend/.env.example backend/.env
```

Edita el archivo con tu editor preferido:

```bash
nano backend/.env
```

Completa **como mínimo** estas variables obligatorias:

```ini
# LiveKit (comunicación en tiempo real)
LIVEKIT_URL=wss://tu-proyecto.livekit.cloud
LIVEKIT_API_KEY=tu_api_key
LIVEKIT_API_SECRET=tu_api_secret

# Google Gemini (inteligencia artificial)
GOOGLE_API_KEY=tu_google_api_key

# Deepgram (voz a texto)
DEEPGRAM_API_KEY=tu_deepgram_api_key

# ElevenLabs (texto a voz)
ELEVEN_API_KEY=tu_eleven_api_key
ELEVENLABS_API_KEY=tu_eleven_api_key
ELEVENLABS_VOICE_ID=tu_voice_id

# Cartesia (STT alternativo)
CARTESIA_API_KEY=tu_cartesia_api_key
```

> Para la referencia completa de cada variable, consulta la [guía de variables de entorno](/taina-agente-ia-ogtic/empezando-con-taina/configuracion-entorno.md).

Guarda y cierra el archivo (`Ctrl+O`, `Enter`, `Ctrl+X` en nano).

## Paso 3 – Colocar las credenciales de Google Cloud

El sistema almacena logs de Egress y archivos de LiveKit en un Bucket seguro de GCP. Necesitas crear un archivo de credenciales de Service Account:

**Si ya tienes el archivo JSON:**

```bash
# Copia tu archivo de Service Account a backend/
cp /ruta/a/tu/credencial.json backend/google_bucket_config.json
```

**Si necesitas crearlo desde cero:**

1. En [Google Cloud Console](https://console.cloud.google.com/), crea un proyecto (o usa uno existente)
2. Ve a **IAM** → **Service Accounts** → **Create Service Account**
3. Asigna el rol **Storage Object Admin**
4. En la Service Account creada, ve a **Keys** → **Add Key** → **JSON**
5. Descarga el archivo JSON y guárdalo como `google_bucket_config.json` en `backend/`

> Usa `backend/google_bucket_config.json.example` como referencia del formato esperado.

### 3.1 Verificar que no falte nada crítico

Antes de continuar, ejecuta este script para confirmar que todas las credenciales están en su lugar:

```bash
python3 << 'VERIFY'
import os
from dotenv import load_dotenv
load_dotenv('backend/.env')

required_keys = [
    'LIVEKIT_URL', 'LIVEKIT_API_KEY', 'LIVEKIT_API_SECRET',
    'GOOGLE_API_KEY', 'DEEPGRAM_API_KEY',
    'ELEVENLABS_API_KEY', 'ELEVENLABS_VOICE_ID',
    'API_USERNAME'
]

print('Verificando variables de entorno...')
all_set = True

for key in required_keys:
    value = os.getenv(key)
    ok = value and not value.startswith('your_') and not value.startswith('YOUR_')
    icon = '+' if ok else 'X'
    label = 'CONFIGURADA' if ok else 'FALTA'
    print(f'  [{icon}] {key}: {label}')
    if not ok:
        all_set = False

if os.path.exists('backend/google_bucket_config.json'):
    print('  [+] google_bucket_config.json: ENCONTRADO')
else:
    print('  [X] google_bucket_config.json: NO ENCONTRADO')
    all_set = False

if all_set:
    print('\nTodo configurado correctamente!')
else:
    print('\nFaltan claves o archivos. Corrige antes de avanzar.')
VERIFY
```

Todas las líneas deben mostrar ✅. Si alguna muestra ❌, revisa la [guía de variables de entorno](/taina-agente-ia-ogtic/empezando-con-taina/configuracion-entorno.md).

## Paso 4 – Ingesta de datos y construcción de inteligencia (ChromaDB)

Antes de levantar el contenedor Docker, necesitamos poblar la memoria vectorial de Taína.

> **¿Por qué antes de Docker?** El script `setup_databases.sh` ejecuta Python directamente en el servidor (crea su propio `.venv`). Docker Compose monta las carpetas `data/` y `storage/` como volúmenes, así que cuando el contenedor arranque, ya encontrará toda la inteligencia construida y lista para usar.

***

### Opción A: Ingesta automática desde la API oficial (Recomendado)

Este script se conecta a la API del Catálogo de Servicios del Estado Dominicano, se autentica con las credenciales del `.env`, descarga todos los servicios registrados en `data/service_ids.txt`, crea los bloques RAG optimizados y construye toda la inteligencia estructurada de Taína.

```bash
cd backend/
./setup_databases.sh --env produccion --build-qa
```

> **¿Qué hace internamente?**
>
> 1. Crea un entorno virtual Python (`.venv`) e instala dependencias
> 2. Lee las credenciales `API_USERNAME` y `API_PASSWORD` del `.env`
> 3. Obtiene un token JWT de la API usando `scripts/auth_get_token.sh`
> 4. Descarga cada servicio listado en `data/service_ids.txt`
> 5. Limpia el HTML y genera archivos `*_rag_documents.json` en `data/chunks/`
> 6. Ejecuta la ingesta vectorial en `storage/chroma/` (colección `servicios`)
> 7. Con `--build-qa`, genera pares pregunta-respuesta y construye `storage/chroma_qa/`

**Opciones disponibles:**

| Flag                       | Descripción                                                       |
| -------------------------- | ----------------------------------------------------------------- |
| `--env staging`            | Usa la API del entorno de pruebas (staging)                       |
| `--env produccion`         | Usa la API del entorno de producción                              |
| `--build-qa`               | Genera la colección QA complementaria                             |
| `--services "163 245 707"` | Procesa solo los IDs indicados (en vez de leer `service_ids.txt`) |

**Ejemplo con servicios específicos:**

```bash
./setup_databases.sh --env staging --services "163 245 707" --build-qa
```

> **Requisitos previos:** Las credenciales de la API (`API_USERNAME`, `API_PASSWORD`) deben estar configuradas en tu `backend/.env`. Estas credenciales serán proporcionadas por la OGTIC de forma privada. Consulta los endpoints en el [Manual de Integración API](https://docs.digital.gob.do/books/manual-de-integracion-api).

***

### Opción B: Ingesta manual / Offline (Paso a paso)

Si no tienes acceso a la API o quieres usar tus propios datos preprocesados, el sistema requiere una nomenclatura específica para su indexación inteligente:

**1. Coloca tus archivos en `backend/data/chunks/`:**

```bash
ls backend/data/chunks/
# Deberías ver archivos con patrón: {service_id}_rag_documents.json
# Ejemplo:
#   120_rag_documents.json
#   163_rag_documents.json
#   707_rag_documents.json
```

> **IMPORTANTE:** Tus archivos JSON **deben** tener el sufijo `*_rag_documents.json`. Este es el patrón que el sistema escanea automáticamente (ver `src/qa/catalog.py`).

**2. Ejecuta la ingesta manual:**

```bash
cd backend/
./setup_databases.sh --json-dir data/chunks --build-qa
```

> Sin `--env`, el script no intentará descargar servicios de la API. Solo procesará los archivos ya existentes en `data/chunks/`.

***

Independientemente de la opción elegida, el proceso tomará unos minutos dependiendo de la cantidad de servicios y la velocidad de tu conexión. Al finalizar exitosamente verás:

```
==> Ingestando documentos en storage/chroma (colección 'servicios')
==> Generando archivos QA desde chunks/ hacia data/QA/
==> Construyendo índice QA en storage/chroma_qa (colección 'servicios_qa')
==> Setup completado
Bases: storage/chroma (servicios), storage/chroma_qa (servicios_qa)
```

**Verifica que las bases se crearon en el servidor:**

```bash
ls -la storage/chroma/
ls -la storage/chroma_qa/
```

> Regresa a la raíz del proyecto antes de continuar: `cd ..`

## Paso 5 – Construir y levantar el contenedor Docker

Ahora que la base de conocimiento está construida, levantamos el contenedor. Docker montará automáticamente las carpetas `data/` y `storage/` que acabamos de poblar.

Desde la raíz del proyecto, ejecuta:

```bash
docker compose up -d --build
```

**¿Qué hace este comando?**

| Parte            | Significado                                                         |
| ---------------- | ------------------------------------------------------------------- |
| `docker compose` | Usa Docker Compose para orquestar servicios                         |
| `up`             | Levanta (inicia) los contenedores definidos en `docker-compose.yml` |
| `-d`             | En segundo plano (*detached*), libera la terminal                   |
| `--build`        | Reconstruye la imagen Docker antes de iniciar                       |

La primera ejecución descarga la imagen base de Python 3.11, instala las dependencias y descarga los modelos de IA locales (Silero VAD, Multilingual Turn Detector). **Esto puede tomar de 5 a 15 minutos** dependiendo de la velocidad de tu servidor.

Verifica que el contenedor esté corriendo:

```bash
docker compose ps
```

Deberías ver:

```
NAME             IMAGE                    STATUS          PORTS
taina_backend    taina_ogtic-taina-...    Up X minutes    0.0.0.0:8080->8080/tcp
```

El estado debe ser **Up**.

## Paso 6 – Verificar la instalación

### 6.1 Ver los logs del agente

```bash
docker compose logs -f taina-backend
```

Deberías ver una salida similar a:

```
============================================================
INICIANDO TAÍNA ASSISTANT - MODO PRODUCCIÓN v2.0
============================================================
[Worker Identity] Proceso marcado como worker-12345
Iniciando precalentamiento del proceso
Cargando modelo VAD...
Modelo VAD cargado exitosamente
Precalentamiento completado exitosamente en 2.34s
```

> Presiona `Ctrl+C` para dejar de ver los logs (el servicio sigue corriendo en segundo plano).

### 6.2 Verificar las colecciones de ChromaDB

```bash
docker compose exec taina-backend python3 -c "
import asyncio
from src.vectors.chroma_vector import get_chroma_load
from src.embeddings.gemini_embedding import get_google_embeddings

async def verify_chromadb():
    try:
        embeddings = get_google_embeddings()
        retriever = get_chroma_load(embeddings, 'storage/chroma', 'servicios')
        results = retriever.invoke('test')
        print(f'✅ ChromaDB Chunks: {len(results)} documentos encontrados')

        qa_retriever = get_chroma_load(embeddings, 'storage/chroma_qa', 'servicios_qa')
        qa_results = qa_retriever.invoke('test')
        print(f'✅ ChromaDB QA: {len(qa_results)} documentos encontrados')

    except Exception as e:
        print(f'❌ Error verificando ChromaDB: {e}')

asyncio.run(verify_chromadb())
"
```

### 6.3 Verificar las herramientas del sistema

```bash
docker compose exec taina-backend python3 -c "
import asyncio
from src.tools import health_check, list_services

async def test_system():
    try:
        health = await health_check()
        print(f'✅ Health Check: {health}')

        services = await list_services(limit=3)
        print(f'✅ Herramientas: {services}')

    except Exception as e:
        print(f'❌ Error en herramientas: {e}')

asyncio.run(test_system())
"
```

### 6.4 Verificar las variables de entorno

```bash
docker compose exec taina-backend python3 -c "
import os
from dotenv import load_dotenv
load_dotenv()

required = [
    'LIVEKIT_URL', 'LIVEKIT_API_KEY', 'LIVEKIT_API_SECRET',
    'GOOGLE_API_KEY', 'DEEPGRAM_API_KEY',
    'ELEVENLABS_API_KEY', 'ELEVENLABS_VOICE_ID'
]

print('Variables de entorno:')
for var in required:
    value = os.getenv(var)
    status = '✅' if value and len(value) > 5 else '❌'
    print(f'  {status} {var}')
"
```

Todas las variables deben mostrar ✅.

> Si alguna verificación falla, consulta la sección de [Solución de problemas](#solución-de-problemas) más abajo.

## Paso 7 – Probar el agente

### Opción 1: LiveKit Playground (recomendado)

1. Abre [LiveKit Playground](https://playground.livekit.io/) en tu navegador
2. Ingresa tu `LIVEKIT_URL` como Server URL
3. Genera un token con tu `LIVEKIT_API_KEY` y `LIVEKIT_API_SECRET`
4. Conéctate a una sala
5. El agente Taína se conectará automáticamente
6. Habla en español: *"Hola, ¿qué servicios tienes disponibles?"*

### Opción 2: Verificar herramientas del catálogo

```bash
docker compose exec taina-backend python3 -c "
import asyncio
from src.tools import list_services

async def test():
    result = await list_services(limit=3)
    print('Servicios encontrados:', result)

asyncio.run(test())
"
```

***

## Comandos esenciales de operación

Una vez que Taína está funcionando, estos son los comandos que usarás día a día:

| Acción                         | Comando                                  |
| ------------------------------ | ---------------------------------------- |
| Iniciar Taína                  | `docker compose up -d`                   |
| Detener Taína                  | `docker compose down`                    |
| Reiniciar Taína                | `docker compose restart`                 |
| Ver logs en tiempo real        | `docker compose logs -f taina-backend`   |
| Ver estado del contenedor      | `docker compose ps`                      |
| Reconstruir después de cambios | `docker compose up -d --build`           |
| Entrar al contenedor           | `docker compose exec taina-backend bash` |
| Ver consumo de recursos        | `docker stats taina_backend`             |

***

## Solución de problemas

### El contenedor no arranca

```bash
# Ver logs detallados
docker compose logs taina-backend

# Errores comunes:
# - "API key not found" → Verifica tu archivo .env
# - "port already in use" → Otro servicio usa el puerto 8080
# - "no space left on device" → Libera espacio en disco
```

### Error: "ChromaDB collection not found"

Esto significa que la base de conocimiento no se ha construido. Verifica que existan archivos en `data/chunks/`:

```bash
ls backend/data/chunks/*.json
```

### Error: "LIVEKIT\_URL not configured"

```bash
# Verifica que el .env esté correctamente configurado
cat backend/.env | grep LIVEKIT

# Reconstruye el contenedor para cargar los cambios
docker compose up -d --build
```

### El agente no responde en LiveKit Playground

1. Verifica que el contenedor esté corriendo: `docker compose ps`
2. Verifica que el puerto 8080 esté abierto: `ss -tlnp | grep 8080`
3. Revisa los logs: `docker compose logs -f taina-backend`

### Limpiar y empezar de cero

```bash
# Detener y eliminar todo
docker compose down --volumes --rmi all

# Reconstruir desde cero
docker compose up -d --build
```

***

## Actualizar Taína

Cuando haya una nueva versión del código:

```bash
# 1. Actualizar el código
git pull origin main

# 2. Reconstruir y reiniciar
docker compose up -d --build
```

Si la actualización incluye cambios en la base de conocimiento, vuelve a ejecutar la ingesta:

```bash
cd backend/
./setup_databases.sh --json-dir data/chunks --build-qa
```

***

## Configuración para desarrollo

Si estás desarrollando o modificando Taína, puedes usar estas variables para un entorno de desarrollo más detallado:

```ini
# En backend/.env (ajustes para desarrollo)
ENV=development
LOG_LEVEL=DEBUG
ENABLE_HEALTH_CHECKS=true
MAX_RETRY_ATTEMPTS=1
```

Para ejecutar sin Docker (desarrollo local con hot reload):

```bash
cd backend/
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

# Ejecutar el agente
python3 -m src.main

# Con logging detallado
python3 -m src.main --log-level DEBUG
```

***

## Configuración para producción

Para despliegues en producción, ajusta estas variables para mayor estabilidad:

```ini
# En backend/.env (ajustes para producción)
ENV=production
ENABLE_HEALTH_CHECKS=true
ENABLE_AUTO_RECOVERY=true

# Optimizaciones de memoria
MAX_MEMORY_MB=4000
WARNING_MEMORY_MB=3000
WORKER_PROCESSES=4

# Timeouts más amplios para redes lentas
STT_TIMEOUT=15
LLM_TIMEOUT=20
TTS_TIMEOUT=25
```

> Para la referencia completa de todas las variables operativas (memoria, timeouts, rate limiting, ChromaDB, logging, feature toggles), consulta la [guía de variables de entorno](https://public-intelligence.gitbook.io/taina-agente-ia-ogtic/empezando-con-taina/pages/MjqfPJPfoR9N7IiVzNrE#configuración-operativa).

***

## Arquitectura Docker

El archivo `docker-compose.yml` en la raíz del proyecto define la configuración del servicio:

```yaml
services:
  taina-backend:
    build:
      context: ./backend
      dockerfile: Dockerfile
    container_name: taina_backend
    restart: unless-stopped
    env_file:
      - ./backend/.env
    ports:
      - "8080:8080"
    volumes:
      - ./backend/data:/app/data         # Base de conocimiento
      - ./backend/storage:/app/storage   # ChromaDB persistido
      - ./backend/logs:/app/logs         # Logs del agente
    environment:
      - ENV=production
      - HOST=0.0.0.0
      - PORT=8080
```

### Volúmenes montados

| Volumen local      | Dentro del contenedor | Propósito                                |
| ------------------ | --------------------- | ---------------------------------------- |
| `backend/data/`    | `/app/data/`          | Archivos JSON de la base de conocimiento |
| `backend/storage/` | `/app/storage/`       | Persistencia de ChromaDB                 |
| `backend/logs/`    | `/app/logs/`          | Logs del agente                          |

> Los volúmenes permiten que los datos persistan aunque el contenedor se reinicie o se reconstruya.

***

## Próximos pasos

* [Guía rápida](/taina-agente-ia-ogtic/empezando-con-taina/quick-start.md) – Resumen ejecutivo para verificar el sistema
* [Operación diaria](/taina-agente-ia-ogtic/operacion-y-monitoreo/despliegue.md) – Comandos de monitoreo y mantenimiento
* [Herramientas del catálogo](/taina-agente-ia-ogtic/referencias-tecnicas/api/tools.md) – Documentación de las herramientas del agente
* [Integraciones](/taina-agente-ia-ogtic/referencias-tecnicas/integrations.md) – Detalles de cada servicio integrado

***

## Recursos adicionales

* [Docker Documentation](https://docs.docker.com/)
* [LiveKit Playground](https://playground.livekit.io/)
* [Google Gemini API](https://ai.google.dev/docs)
* [Deepgram API](https://developers.deepgram.com/)
* [ElevenLabs API](https://docs.elevenlabs.io/)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://public-intelligence.gitbook.io/taina-agente-ia-ogtic/empezando-con-taina/installation.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
