RPG-RAG / README.md
Yienvee's picture
Adding vLLM alternative to run local LLM insted of API
979f168
---
title: RPG-RAG
emoji: 🎲
colorFrom: purple
colorTo: blue
sdk: gradio
sdk_version: "6.9.0"
python_version: "3.12"
app_file: app.py
pinned: false
---
# RPG-RAG
Um kit pessoal para organizar **lore/campanhas de RPG** e usar **LLMs locais** pra ajudar durante e depois das sessões.
O repositório hoje tem 3 “pilares” principais:
1. **Session Helper (Tkinter)**: seleciona uma campanha, transcreve um áudio e gera um resumo via Ollama.
2. **UI protótipo (PyQt6)**: um menu básico para futuramente unir geração + pós-sessão.
3. **PDF reader (PyMuPDF)**: extrai texto de PDFs e detecta imagens (com placeholder para descrever as imagens).
> Status: o projeto está em desenvolvimento e algumas partes ainda são rascunhos (ex.: `src/brain.py`, `src/get_data.py`, geradores em `src/gen/`).
## Funcionalidades
- **Campanhas**: carrega campanhas em `Data/Campaings/campaings.json`.
- **Transcrição**: usa Whisper para transcrever arquivo de áudio (ex.: MP3).
- **Resumo**: usa um LLM via **Ollama** pra resumir a sessão.
- **Extração de PDF**: pega texto e imagens e salva imagens extraídas.
## Estrutura do projeto
- `Data/`
- `Campaings/`: campanhas e sessões
- `Ekalia/`: lore/mundo em `.txt` (obsidian-friendly)
- `Audios/`: exemplos de áudio
- `src/`
- `main.py`: app Tkinter (Session Helper)
- `main2.py`: protótipo PyQt6
- `ears/whisper.py`: transcrição e resumo
- `pdf_reader/pdf_agent.py`: extrator de PDF (texto + imagens)
- `brain.py`: experimentos com agentes/LLM (atenção: contém prompts inadequados e não representa o objetivo final)
- `get_data.py`: experimento para ler dados e jogar em dataframe (precisa de ajustes)
- `models/`: modelos locais (ex.: qwen)
## Pré-requisitos
- Python 3.10+ (recomendado)
- (Opcional) GPU/CUDA para Whisper acelerar — funciona em CPU também.
- **Ollama instalado e rodando** (para o resumo): https://ollama.com
## Instalação
Crie um ambiente virtual e instale dependências:
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
## Como rodar
### 1) Session Helper (Tkinter)
Abre uma UI simples para:
- listar campanhas
- selecionar campanha
- escolher um arquivo de áudio
- transcrever e gerar resumo
```bash
python src/main.py
```
**Observações**
- O arquivo de campanhas precisa existir em `Data/Campaings/campaings.json`.
- O resumo usa Ollama via LangChain. Ajuste o modelo em `src/ears/whisper.py` (variável `LLM_MODEL`).
### 2) Protótipo de UI (PyQt6)
Interface base com navegação de telas.
```bash
python src/main2.py
```
### 3) Extrator de PDF
Processa um PDF e salva imagens encontradas em `extracted_images/`.
```bash
python src/pdf_reader/pdf_agent.py
```
Por padrão o script tenta ler `DH.pdf` na raiz. Se não existir, edite `test_pdf_path` no final do arquivo.
## LLM Local com vLLM (opcional)
O projeto suporta rodar um LLM local via [vLLM](https://github.com/vllm-project/vllm)
como alternativa à API da Groq. Útil pra desenvolvimento offline, custos zero
e (futuramente) servir modelos fine-tuned.
### Por que um venv separado
vLLM tem requisitos rígidos de torch/CUDA que conflitam com Whisper e
`langchain-huggingface` no venv principal. A solução padrão é isolar o vLLM
em seu próprio ambiente — o projeto principal só conversa com ele via HTTP.
```
.venv/ ← venv principal (Whisper, FAISS, embeddings, gradio…)
.venv-vllm/ ← venv isolado, só com vllm + suas deps CUDA
```
### Setup (uma vez)
Pré-requisito: GPU NVIDIA com pelo menos 16GB VRAM (testado em RTX 5060 Ti).
```bash
uv venv .venv-vllm --python 3.12
uv pip install --python .venv-vllm/bin/python vllm --torch-backend=auto
```
A flag `--torch-backend=auto` deixa o uv detectar a versão do CUDA pelo
`nvidia-smi` e baixar o wheel compatível. Em GPUs Blackwell (RTX 50xx) com
driver recente isso é o stack CUDA 13.
### Subindo o servidor
```bash
python vllm/run_local.py
```
O script:
- Aponta pro binário em `.venv-vllm/bin/vllm`
- Configura `LD_LIBRARY_PATH` pra encontrar os `.so` de CUDA do venv isolado
- Sobe um servidor **OpenAI-compatible** em `http://localhost:8000/v1`
- Modelo padrão: `Qwen/Qwen2.5-7B-Instruct-AWQ` (4-bit, cabe folgado em 16GB)
Primeira execução baixa o modelo (~5GB) em `vllm/Models/` (ignorado pelo git).
### Usando no código
`src/llm/client.py` expõe três papéis (`Role`):
```python
from src.llm.client import get_llm, Role
llm = get_llm(Role.FAST) # → Groq llama-3.1-8b-instant (padrão)
llm = get_llm(Role.CREATIVE) # → Groq llama-3.3-70b-versatile
llm = get_llm(Role.LOCAL) # → vLLM local (Qwen2.5-7B-AWQ)
```
`Role.LOCAL` usa `ChatOpenAI` apontando pro endpoint local — não precisa de
nenhum SDK específico do vLLM.
### Variáveis de ambiente (opcionais)
Todas têm default sensato; só sobrescreva no `.env` se precisar mudar:
| Variável | Default | Para quê |
| --- | --- | --- |
| `VLLM_BASE_URL` | `http://localhost:8000/v1` | URL do servidor local |
| `VLLM_MODEL` | `Qwen/Qwen2.5-7B-Instruct-AWQ` | Modelo servido pelo vLLM |
| `VLLM_API_KEY` | `EMPTY` | Token (vLLM aceita qualquer string por padrão) |
### Smoke test
Com o servidor rodando em outro terminal:
```bash
python -m src.llm.client --local
```
Deve imprimir uma resposta do Qwen local. Sem `--local`, usa Groq (`Role.CREATIVE`)
— bom pra confirmar que o fallback continua funcionando.
---
## Notas importantes / TODOs
- `src/brain.py` contém experimentos com agentes e prompts de teste. Use como referência de experimentação, não como “produção”.
- `src/get_data.py` tem um bug (tenta imprimir `context['file_path']` mas a chave criada é `file name`).
- Os geradores em `src/gen/` estão vazios no momento.
- `src/main.py` tem um TODO antigo: “Trocar Tkinter por PySide6”. Hoje há um protótipo em PyQt6 (`main2.py`).
## Troubleshooting
### Whisper muito lento
- Em CPU, o Whisper (principalmente `large`) pode demorar bastante.
- Você pode trocar o modelo em `src/ears/whisper.py` (ex.: `base`, `small`, `medium`, `large`).
### Ollama não responde
- Garanta que o daemon do Ollama está rodando.
- Garanta que o modelo configurado em `LLM_MODEL` existe (ex.: `ollama pull deepseek-r1:latest`).
## Licença
Se você quiser, posso adicionar uma licença explícita (MIT/Apache-2.0/etc). Por enquanto, o repositório não declara licença aqui no README.