Bot inteligente de búsqueda multi-fuente con IA. Busca en Slack, Redmine y Google Drive usando RAG (Retrieval-Augmented Generation), búsqueda híbrida (semántica + keywords), y OpenAI Function Calling para respuestas conversacionales.
# 1. Configurar variables de entorno (crear archivo .env)
# 2. Cargar variables
set -a && source .env && set +a
# 3. Indexar contenido
detector index # Indexar Slack
detector index-redmine # Indexar Redmine (opcional)
detector index-gdrive # Indexar Google Drive (opcional)
# 4. Iniciar el bot
python -m detector.bot.example_app- 🔍 Búsqueda multi-fuente - Slack mensajes + Redmine issues + Google Drive docs en una sola consulta
- 🎯 Búsqueda híbrida - Combina búsqueda semántica con keywords exactos
- 🧠 Conversación inteligente - El LLM decide en qué fuente buscar
- 💬 Historial de conversación - Recuerda el contexto entre mensajes del mismo usuario
- 🔒 Sanitización de credenciales - Redacta automáticamente API keys, tokens y passwords
- 📚 Indexación automática - Indexa Slack, Redmine y Google Drive
- 📄 Soporte Google Drive - Indexa Google Docs y archivos .docx con chunking inteligente
┌─────────────────────────────────────────────────────────────┐
│ Slack (Usuario) │
│ DMs / Menciones / Slash Commands │
└──────────────────────────┬──────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Bot Handler │
│ (OpenAI Function Calling) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ Historial │ │ LLM decide │ │ Tools disponibles: │ │
│ │ por usuario │ │ qué hacer │ │ • search_slack │ │
│ └─────────────┘ └─────────────┘ │ • search_redmine │ │
│ │ • search_gdrive │ │
│ │ • search_all │ │
│ │ • get_thread │ │
│ │ • list_channels │ │
│ └─────────────────────┘ │
└──────────────────────────┬──────────────────────────────────┘
│
┌────────┬─────────┼─────────┬────────┬────────┐
▼ ▼ ▼ ▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Vector │ │Sanitizer │ │ Slack │ │ Redmine │ │ G.Drive │ │ LLM │
│ Store │ │(Credenc.)│ │ Client │ │ Client │ │ Client │ │ (OpenAI) │
│(ChromaDB)│ └──────────┘ │ (API) │ │ (API) │ │ (API) │ └──────────┘
└────┬─────┘ └──────────┘ └──────────┘ └──────────┘
│
├──────────────────────┬─────────────────────┐
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Slack Mensajes │ │ Redmine Issues │ │ Google Drive │
│(chunks+embeds) │ │(chunks+embeds) │ │ Documents │
└────────────────┘ └────────────────┘ └────────────────┘
- Python 3.11+
- API Key de OpenAI
- Slack App con estos permisos (Bot Token Scopes):
| Scope | Descripción |
|---|---|
channels:history |
Leer historial de canales públicos |
channels:read |
Listar canales públicos |
groups:history |
Leer historial de canales privados |
groups:read |
Listar canales privados |
chat:write |
Enviar mensajes |
commands |
Slash commands |
users:read |
Información de usuarios |
app_mentions:read |
Recibir menciones |
im:history |
Leer DMs |
im:read |
Ver DMs |
- Abrir el proyecto en VS Code/Cursor
- Instalar la extensión "Dev Containers"
Ctrl+Shift+P→ "Dev Containers: Reopen in Container"
cd Detector
# Crear entorno virtual
python -m venv venv
source venv/bin/activate # Linux/Mac
# Instalar dependencias
pip install -e ".[dev]"
pip install slack-bolt
# Crear archivo .env (ver sección Configuración)# ══════════════════════════════════════════════════════════
# Slack (obligatorio)
# ══════════════════════════════════════════════════════════
SLACK_BOT_TOKEN=xoxb-tu-token
SLACK_APP_TOKEN=xapp-tu-token
SLACK_SIGNING_SECRET=tu-signing-secret
# ══════════════════════════════════════════════════════════
# OpenAI (obligatorio)
# ══════════════════════════════════════════════════════════
OPENAI_API_KEY=sk-tu-key
# LLM
LLM_PROVIDER=openai
LLM_MODEL=gpt-4o-mini
EMBEDDING_MODEL=text-embedding-3-small
# ══════════════════════════════════════════════════════════
# Redmine (opcional)
# ══════════════════════════════════════════════════════════
REDMINE_URL=https://redmine.tu-empresa.com
REDMINE_API_KEY=tu-api-key-de-redmine
REDMINE_PROJECT=nombre-proyecto # Identificador del proyecto
REDMINE_INDEX_CLOSED_ONLY=true # Solo indexar issues cerrados
# ══════════════════════════════════════════════════════════
# Google Drive (opcional)
# ══════════════════════════════════════════════════════════
GDRIVE_CREDENTIALS_FILE=/ruta/a/service-account.json
GDRIVE_FOLDER_ID=1ABC123xyz # ID de la carpeta raíz
GDRIVE_INCLUDE_SUBFOLDERS=true # Incluir subcarpetas
# ══════════════════════════════════════════════════════════
# ChromaDB
# ══════════════════════════════════════════════════════════
CHROMA_PERSIST_DIR=/ruta/a/data/chroma
# ══════════════════════════════════════════════════════════
# Indexador Slack
# ══════════════════════════════════════════════════════════
INDEX_CHANNELS=general,engineering,support
INDEX_DAYS_BACK=365- Ir a api.slack.com/apps → Create New App
- Agregar los Bot Token Scopes listados arriba
- Habilitar Socket Mode (genera el
SLACK_APP_TOKEN) - En App Home, activar "Messages Tab" para permitir DMs
- Instalar la app en el workspace
- Invitar el bot a los canales:
/invite @nombre-del-bot
- Ir a Google Cloud Console
- Crear un proyecto o seleccionar uno existente
- Habilitar la Google Drive API
- Crear una Service Account:
- IAM & Admin → Service Accounts → Create
- Descargar el archivo JSON de credenciales
- Compartir la carpeta de Drive con el email de la Service Account:
mi-service-account@proyecto.iam.gserviceaccount.com- Con permisos de Lector
- Obtener el ID de la carpeta de la URL:
https://drive.google.com/drive/folders/1ABC123xyz └─────────┘ Este es el GDRIVE_FOLDER_ID
# Cargar variables de entorno
set -a && source .env && set +a
# ═══ Slack ═══
# Indexar canales configurados
detector index
# Indexar canal específico
detector index --channels "tecnologia-testing" --days 30
# Reindexar desde cero
detector index --reindex
# ═══ Redmine ═══
# Indexar issues del proyecto configurado
detector index-redmine
# Indexar proyecto específico
detector index-redmine --project "mi-proyecto"
# ═══ Google Drive ═══
# Indexar documentos de la carpeta configurada
detector index-gdrive
# Indexar carpeta específica
detector index-gdrive --folder "1ABC123xyz"
# ═══ Todas las fuentes ═══
# Indexar Slack, Redmine y Google Drive de una vez
detector index-all# Estado de Slack
detector status
# Estado de Redmine
detector status-redmine
# Estado de Google Drive
detector status-gdrive# Cargar variables y ejecutar
set -a && source .env && set +a && python -m detector.bot.example_app| Método | Ejemplo |
|---|---|
| DM | Abrir el bot en Slack y escribir directamente |
| Mención | @bot ¿qué errores hubo de VOII? |
| Slash | /buscar problemas de performance |
| Canales | /canales - lista canales indexados |
| Limpiar | /limpiar - reinicia el historial |
Usuario: Hola
Bot: ¡Hola! ¿En qué puedo ayudarte?
Usuario: ¿Qué errores se reportaron del proyecto VOII?
Bot: Encontré información en ambas fuentes:
📬 Slack (3 resultados):
1. Error de conexión reportado por Juan en #desarrollo...
🎫 Redmine (2 issues):
1. Issue #1234 - Error timeout en API...
Usuario: ¿Cómo se resolvió el issue #1234?
Bot: El issue #1234 se resolvió aumentando el timeout de conexión
a 30 segundos. Lo cerró María el 15/01.
URL: https://redmine.example.com/issues/1234
Usuario: ¿Hay documentación sobre el proceso de deployment?
Bot: Sí, encontré un documento en Google Drive:
📄 "Manual de Deployment v2"
Describe el proceso de CI/CD y los comandos necesarios...
URL: https://docs.google.com/document/d/xyz
Usuario: ¿Quién mencionó algo sobre eso en Slack?
Bot: Juan comentó en #desarrollo que ya se había aplicado el fix...
[Permalink al mensaje]
Usuario: Dame más detalles de ese hilo
Bot: [Obtiene el contexto completo del hilo de Slack]
El bot automáticamente redacta información sensible:
| Tipo | Ejemplo → Resultado |
|---|---|
| API Keys | sk-abc123... → [API_KEY_REDACTED] |
| Slack Tokens | xoxb-123... → [SLACK_TOKEN_REDACTED] |
| JWT | eyJhbG... → [JWT_TOKEN_REDACTED] |
| Passwords | password=secret → password=[PASSWORD_REDACTED] |
| URLs con creds | https://user:pass@... → [URL_WITH_CREDS_REDACTED] |
Detector/
├── src/detector/
│ ├── bot/ # Bot de Slack
│ │ ├── handler.py # Handler con Function Calling
│ │ └── example_app.py
│ ├── indexer/ # Indexación
│ │ ├── slack_sync.py # Indexador de Slack
│ │ ├── redmine_sync.py # Indexador de Redmine
│ │ └── gdrive_sync.py # Indexador de Google Drive
│ ├── tools/ # Herramientas de búsqueda
│ │ ├── search.py # Búsqueda Slack
│ │ ├── search_redmine.py # Búsqueda Redmine
│ │ ├── search_gdrive.py # Búsqueda Google Drive
│ │ └── search_all.py # Búsqueda unificada
│ ├── llm/ # Cliente LLM
│ ├── slack_client/ # Cliente API de Slack
│ ├── redmine_client/ # Cliente API de Redmine
│ ├── gdrive_client/ # Cliente API de Google Drive
│ ├── vector_store/ # ChromaDB
│ ├── sanitizer.py # Redacción de credenciales
│ └── config.py # Configuración
├── scripts/
│ └── scheduled_index.sh # Indexación programada
├── .env # Variables de entorno
└── pyproject.toml
Los datos indexados se guardan en ChromaDB (local, gratuito):
data/chroma/ # Base de datos vectorial
No es necesario reindexar cada vez que se inicia el bot. Solo reindexar cuando:
- Se quieran incluir mensajes/issues nuevos
- Se cambien los canales o proyectos
# Hacer el script ejecutable
chmod +x scripts/scheduled_index.sh
# Abrir crontab para edición
crontab -e
# Agregar esta línea (ejecuta cada semana, domingos a las 3am)
0 3 * * 0 /ruta/a/Detector/scripts/scheduled_index.sh >> /ruta/a/logs/index.log 2>&1- El bot debe estar invitado al canal:
/invite @nombre-del-bot - Para canales privados, se necesitan los scopes
groups:readygroups:history
- Agregar el scope faltante en api.slack.com/apps
- Reinstalar la app en el workspace
- Verificar que "Messages Tab" esté activado en App Home
- Agregar scopes
im:readeim:history
- Usar comillas:
"VOII"para forzar búsqueda exacta - Verificar que los mensajes estén indexados:
detector status
- Verificar que la Service Account tenga acceso a la carpeta
- La carpeta debe estar compartida con el email de la Service Account
- Solo se indexan Google Docs y archivos .docx (no PDFs, Sheets, etc.)
MIT