File size: 5,682 Bytes
951a2fa
 
1a0b19c
 
 
951a2fa
1a0b19c
951a2fa
 
 
1a0b19c
 
 
 
 
 
72d747f
1a0b19c
 
72d747f
1a0b19c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72d747f
1a0b19c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72d747f
 
1a0b19c
 
 
 
 
 
 
72d747f
 
 
 
 
 
 
 
 
 
 
1a0b19c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
---
title: BotSpace
emoji: "🤖"
colorFrom: blue
colorTo: indigo
sdk: docker
app_port: 7860
pinned: false
---

# BotSpace

Bot para Discord com RAG (Retrieval-Augmented Generation) usando documentos jurídicos, indexação local com FAISS e geração de respostas via Hugging Face Inference API.

## Visão Geral

O projeto combina tres partes principais:

- Bot Discord (`!rag`, `!reindex` e resposta por menção)
- API FastAPI para saude, logs e reindexacao
- Pipeline de ingestão que baixa documentos, sanitiza arquivos, cria embeddings e publica artefatos de índice

## Funcionalidades

- Busca semântica local com `sentence-transformers` + `faiss-cpu`
- Reindex manual por comando no Discord ou endpoint HTTP
- Recarregamento automático do índice em runtime
- Sanitização de documentos (`.doc` -> `.docx`, remoção de formatos não suportados)
- Execução em Docker (compatível com Hugging Face Spaces)

## Arquitetura

```mermaid
flowchart LR
    A["Discord User"] --> B["Bot (discord.py)"]
    B --> C["LocalIndexRuntime (FAISS)"]
    C --> D["Artifacts locais (faiss.index/meta.json)"]
    B --> E["HF Inference API"]

    F["/reindex (FastAPI)"] --> G["ingest_job.py"]
    G --> H["Dataset de documentos (HF Hub)"]
    G --> I["Dataset de índice (HF Hub)"]
    G --> D
```

## Pré-requisitos

- Python 3.12+
- `uv` instalado
- Ambiente virtual (`.venv`) configurado
- Token de bot do Discord
- Token do Hugging Face com permissões para leitura/escrita nos repositórios usados

## Quick Start (Local)

1. Criar/ativar ambiente virtual e instalar dependências com `uv`:

```bash
uv venv
source .venv/bin/activate
uv pip install -r requirements.txt
```

2. Criar `.env` (ou exportar variáveis):

```bash
export DISCORD_TOKEN="..."
export REINDEX_API_TOKEN="..."
export HF_TOKEN="..."
export DOCS_REPO_ID="usuario/dataset-documentos"
export INDEX_REPO_ID="usuario/dataset-indice"
export DOCS_SUBDIR="docs_rag"
```

3. Executar:

```bash
python main.py
```

## Configuração

| Variável | Obrigatória | Default | Descrição |
|---|---|---|---|
| `DISCORD_TOKEN` | Sim | - | Token do bot Discord |
| `BOT_PREFIX` | Não | `!` | Prefixo de comandos |
| `REINDEX_API_TOKEN` | Nao | - | Se definido, exige Bearer token no `POST /reindex`; se ausente, aceita apenas localhost |
| `HF_TOKEN` | Sim | - | Token para Hugging Face Hub/Inference |
| `HF_TEXT_MODEL` | Não | `microsoft/Phi-3.5-mini-instruct` | Modelo de geração de texto |
| `HF_INFERENCE_URL` | Não | construído a partir de `HF_TEXT_MODEL` | URL da Inference API |
| `DOCS_REPO_ID` | Sim (ingestão) | - | Dataset fonte de documentos |
| `INDEX_REPO_ID` | Sim (ingestão) | - | Dataset destino dos artefatos de índice |
| `DOCS_SUBDIR` | Não | `docs_rag` | Subdiretório dos documentos no dataset |
| `EMBED_MODEL` | Não | `sentence-transformers/all-MiniLM-L6-v2` | Modelo de embeddings |
| `CHUNK_CHARS` | Não | `1200` | Tamanho de chunk |
| `CHUNK_OVERLAP` | Não | `200` | Sobreposição de chunks |
| `WORK_DIR` | Não | `/data/work` (app) / `/tmp/rag_job` (ingest) | Diretório de trabalho |
| `ARTIFACTS_PREFIX` | Não | `artifacts` | Prefixo de arquivos no dataset de índice |
| `RELOAD_POLL_SECONDS` | Não | `30` | Intervalo para detectar atualização do índice |
| `REINDEX_EVERY_SECONDS` | Não | `0` | Agendamento automático de reindex (0 desativa) |

## Uso

### Comandos do Bot

- `!rag <pergunta>`: responde com base nos trechos mais relevantes do índice
- `!reindex` (admin): dispara reindexação
- Menção ao bot: responde à pergunta presente na menção

### Endpoints HTTP

- `GET /health` -> `ok`
- `GET /logs` -> últimos logs da ingestão
- `POST /reindex` -> dispara ingestão
  - Se `REINDEX_API_TOKEN` estiver definido: requer `Authorization: Bearer <REINDEX_API_TOKEN>`
  - Se `REINDEX_API_TOKEN` nao estiver definido: apenas chamadas de `127.0.0.1`/`::1` sao aceitas

## Docker

Build e run local:

```bash
docker build -t botspace .
docker run --rm -p 7860:7860 \
  -e DISCORD_TOKEN="$DISCORD_TOKEN" \
  -e HF_TOKEN="$HF_TOKEN" \
  -e DOCS_REPO_ID="$DOCS_REPO_ID" \
  -e INDEX_REPO_ID="$INDEX_REPO_ID" \
  botspace
```

Com protecao por token (opcional):

```bash
docker run --rm -p 7860:7860 \
  -e DISCORD_TOKEN="$DISCORD_TOKEN" \
  -e REINDEX_API_TOKEN="$REINDEX_API_TOKEN" \
  -e HF_TOKEN="$HF_TOKEN" \
  -e DOCS_REPO_ID="$DOCS_REPO_ID" \
  -e INDEX_REPO_ID="$INDEX_REPO_ID" \
  botspace
```

## Estrutura do Projeto

```text
.
├── main.py                 # API FastAPI + scheduler + bootstrap do bot
├── bot_app.py              # Bot Discord e comandos
├── ingest_job.py           # Pipeline de ingestão e publicação do índice
├── index_local_runtime.py  # Carregamento/consulta local do índice
├── hf_client.py            # Cliente de inferência no HF
├── sanitize_docs.py        # Conversão/sanitização de documentos
├── prompts.py              # Prompt base para respostas
├── Dockerfile
└── docs_rag/               # Base documental local (quando aplicável)
```

## Troubleshooting

- Erro `HF_TOKEN nao definido`: exporte `HF_TOKEN` antes de iniciar.
- Erro `DISCORD_TOKEN nao definido`: verifique token do bot e permissões no servidor.
- `Indice nao existe ... Rode reindex primeiro.`: execute `!reindex` ou `POST /reindex`.
- Falha com `.doc`: garanta LibreOffice/`soffice` disponível (já incluso no Dockerfile).

## Contribuição

1. Crie uma branch para sua alteração.
2. Faça mudanças pequenas e testáveis.
3. Abra PR com contexto, impacto e forma de validação.

## Licença

Defina a licença do projeto (ex.: MIT) e adicione o arquivo `LICENSE` no repositório.