Sistema de comunicação por voz em tempo real para operadores de equipamentos pesados de mineração, utilizando reconhecimento de fala offline, NLU com Rasa e geração de resposta via LLM local (Ollama).
- Visão Geral
- Arquitetura do Sistema
- Fluxo de Comunicação (Tópicos ROS 2)
- Pré-requisitos
- Instalação
- Configuração do Rasa
- Execução
- Intenções Suportadas
- Estrutura dos Arquivos
- Variáveis e Parâmetros Configuráveis
- Troubleshooting
O CCO-IA é um sistema embarcado de assistência inteligente à operação de caminhões de mineração. Ele funciona como uma Central de Comando Operacional (CCO) virtual, capaz de:
- Escutar o motorista via rádio (PTT — Push-to-Talk)
- Reconhecer a fala offline, sem conexão com internet
- Classificar a intenção e extrair entidades relevantes (local, componente, carga, etc.)
- Gerar uma resposta natural e profissional via LLM local
- Falar a resposta ao motorista usando síntese de voz neural offline
Todo o processamento ocorre 100% localmente, sem nenhuma dependência de serviços em nuvem.
[Microfone / Rádio PTT]
│
▼
┌─────────────┐ /fala_reconhecida ┌─────────────┐
│ No_Vosk.py │ ──────────────────────────▶│ No_Rasa.py │
│ (Vosk STT) │ │ (Rasa NLU) │
└─────────────┘ └─────────────┘
│
/resposta_rasa (JSON NLU)
│
▼
┌──────────────────┐
│ No_LLM.py │
│ (Ollama / LLama) │
└──────────────────┘
│
/resposta_bot (sentenças)
│
▼
┌──────────────────┐
│ No_Fala.py │
│ (Silero TTS) │
└──────────────────┘
│
▼
[Alto-falante]
O sistema é composto por 4 nós ROS 2 independentes que se comunicam exclusivamente via tópicos:
| Nó | Arquivo | Função |
|---|---|---|
vosk_node |
No_Vosk.py |
Reconhecimento de voz (Speech-to-Text) com controle PTT |
rasa_node |
No_Rasa.py |
Classificação de intenção e extração de entidades (NLU) |
llm_node |
No_LLM.py |
Geração de resposta contextualizada via Ollama (streaming) |
fala_node |
No_Fala.py |
Síntese de voz neural offline (Text-to-Speech) |
| Tópico | Tipo | Publicado por | Consumido por | Conteúdo |
|---|---|---|---|---|
/botao_acionado |
Int8 |
Hardware externo | vosk_node |
1 = PTT pressionado, 0 = solto |
/fala_reconhecida |
String |
vosk_node |
rasa_node |
Texto transcrito da fala |
/resposta_rasa |
String |
rasa_node |
llm_node |
JSON com intenção, confiança e entidades |
/resposta_bot |
String |
llm_node |
fala_node |
JSON com sentenças geradas (streaming) |
{
"texto_original": "temperatura do motor muito alta",
"intencao": "informar_problema_mecanico",
"confianca": 0.9731,
"entidades": [
{ "entidade": "componente", "valor": "motor" }
]
}{
"respostas": ["A oficina foi notificada sobre o superaquecimento do motor."],
"streaming": false
}- Ubuntu 24.04 (testado)
- ROS 2 Jazzy
O projeto usa dois intérpretes Python distintos por incompatibilidade de dependências:
| Ambiente | Versão | Usado por |
|---|---|---|
| venv Rasa | Python 3.10 | servidor Rasa NLU |
| Sistema / ROS 2 | Python 3.12 | No_Rasa.py, No_Vosk.py, No_LLM.py, No_Fala.py |
O Rasa e suas dependências (spaCy, TensorFlow) exigem Python 3.10. Os demais nós rodam no Python 3.12 do sistema junto ao ROS 2.
| Componente | Ambiente | Instalação |
|---|---|---|
| Vosk (STT) | Python 3.12 | pip install vosk + baixar modelo (ver abaixo) |
| Rasa (NLU) | Python 3.10 (venv) | pip install rasa |
| spaCy (pipeline Rasa) | Python 3.10 (venv) | pip install spacy && python -m spacy download pt_core_news_sm |
| Ollama (LLM) | Python 3.12 | Instale em ollama.com e rode ollama pull llama3.2:1b |
| Silero TTS | Python 3.12 | Baixado automaticamente pelo PyTorch Hub na primeira execução |
cd ~/ros2_ws/src
git clone <url-do-repositorio> cco_ia
cd ~/ros2_ws
colcon build --packages-select cco_ia
source install/setup.bashEssas dependências são para os nós Vosk, LLM e Fala:
pip3.12 install torch torchaudio sounddevice vosk requests ollama# Crie e ative o venv
python3.10 -m venv ~/rasa_env
source ~/rasa_env/bin/activate
# Instale o Rasa e o modelo de linguagem
pip install rasa
pip install spacy
python -m spacy download pt_core_news_sm
deactivatecd ~/ros2_ws/src/cco_ia
wget https://alphacephei.com/vosk/models/vosk-model-small-pt-0.3.zip
unzip vosk-model-small-pt-0.3.zip# Instale o Ollama (seguir instruções em ollama.com)
ollama pull llama3.2:1bOs arquivos de configuração Rasa estão na raiz do projeto:
| Arquivo | Propósito |
|---|---|
config.yml |
Pipeline NLU (spaCy + DIET + FallbackClassifier com threshold 0.8) |
domain.yml |
Intenções, entidades e slots reconhecidos |
nlu.yml |
Exemplos de treinamento para cada intenção |
endpoints.yml |
Endpoints externos (action server, tracker store) |
credentials.yml |
Canais de comunicação do Rasa |
O Rasa deve ser executado sempre dentro do venv Python 3.10:
cd ~/ros2_ws/src/cco_ia
# Ative o ambiente virtual do Rasa
source ~/rasa_env/bin/activate
# Treinar o modelo (necessário após qualquer alteração no nlu.yml)
rasa train
# Iniciar o servidor NLU na porta 5005
rasa run --enable-api --port 5005
# Deixe este terminal aberto — o servidor precisa ficar rodandoO nó
No_Rasa.pyconsome a API REST emhttp://localhost:5005/model/parse.
cd ~/cco_ia
source rasa_env/bin/activate
rasa run --enable-apiDeixe este terminal aberto. O servidor precisa ficar rodando enquanto os nós estiverem ativos.
cd ~/cco_ia
source /opt/ros/jazzy/setup.bash
python3 No_Vosk.py &
python3 No_Rasa.py &
python3 No_LLM.py &
python3 No_Fala.py &
waitO
&executa cada nó em background. Owaitmantém o terminal aberto e aguarda todos os processos. Para encerrar tudo, pressioneCtrl+C.
Ou utilize um arquivo launch para subir tudo de uma vez:
# launch/cco_ia.launch.py
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(package='cco_ia', executable='vosk_node'),
Node(package='cco_ia', executable='rasa_node'),
Node(package='cco_ia', executable='llm_node'),
Node(package='cco_ia', executable='fala_node'),
])ros2 launch cco_ia cco_ia.launch.pyO modelo Rasa foi treinado para reconhecer as seguintes intenções do motorista:
| Intenção | Exemplos de fala | Ação da CCO |
|---|---|---|
saudacao_radio |
"QAP", "CCO na escuta?", "rádio teste" | Confirma presença na escuta |
confirmar_entendimento |
"copiado", "afirmativo", "entendido central" | Acusa recebimento |
informar_emergencia |
"emergência emergência", "tombamento na rampa" | Ordena parada e protocolo de segurança |
informar_emergencia_incendio |
"fogo no motor", "princípio de incêndio" | Protocolo de combate a incêndio |
solicitar_basculamento |
"permissão para bascular no britador 1" | Autoriza deslocamento ao ponto de descarga |
solicitar_carregamento |
"vazio, indo para a escavadeira 5" | Informa destino de carga |
informar_falha_critica |
"perdi o freio", "falha na direção" | Ordena parada imediata |
informar_problema_mecanico |
"pneu dianteiro furou", "temperatura do motor alta" | Notifica equipe de manutenção |
informar_status_operacional |
"caminhão cheio", "iniciando turno" | Registra status |
solicitar_ultrapassagem |
"posso passar o caminhão parado?" | Autoriza ou nega ultrapassagem |
informar_condicao_via |
"excesso de poeira, visibilidade ruim" | Registra condição da via |
| Entidade | Exemplos |
|---|---|
local |
britador 1, escavadeira 5, frente de lavra, pilha de estéril |
componente |
motor, pneu, suspensão, bateria, filtro de combustível |
carga |
minério, carvão |
status_carga |
cheio, vazio |
veiculo |
caminhão, motoniveladora, veículo leve |
cco_ia/
├── No_Vosk.py # Nó STT — Vosk com controle PTT agressivo
├── No_Rasa.py # Nó NLU — cliente da API Rasa
├── No_LLM.py # Nó LLM — streaming via Ollama
├── No_Fala.py # Nó TTS — Silero neural offline
├── config.yml # Pipeline de NLU do Rasa
├── domain.yml # Domínio: intenções, entidades, slots
├── endpoints.yml # Endpoints externos Rasa
├── credentials.yml # Canais do Rasa
├── README.md
└── data/
└── nlu.yml # Dados de treinamento NLU
| Variável | Padrão | Descrição |
|---|---|---|
_SAMPLE_RATE |
16000 |
Taxa de amostragem do microfone (Hz) |
_BLOCK_SIZE |
4000 |
Tamanho do bloco de áudio por callback |
| Variável | Padrão | Descrição |
|---|---|---|
URL_NLU |
http://localhost:5005/model/parse |
Endpoint da API Rasa NLU |
TIMEOUT_S |
5 |
Timeout das requisições HTTP (segundos) |
| Variável | Padrão | Descrição |
|---|---|---|
MODELO_LLM |
llama3.2:1b |
Modelo Ollama utilizado |
MAX_HISTORICO |
2 |
Turnos de histórico de conversa mantidos |
| Variável | Padrão | Descrição |
|---|---|---|
ARQUIVO_AUDIO |
/home/giovanna/Downloads/IA/piper_voices/fala.wav |
Caminho para salvar o .wav gerado |
CONFIANCA_MINIMA |
0.70 |
Confiança mínima do NLU para sintetizar fala |
| Parâmetro | Valor | Descrição |
|---|---|---|
FallbackClassifier.threshold |
0.8 |
Confiança mínima para aceitar uma intenção |
DIETClassifier.epochs |
100 |
Épocas de treinamento do classificador |
Rasa não responde / timeout
Verifique se o servidor Rasa está rodando:
curl http://localhost:5005/status
Vosk não reconhece fala
Confirme que o diretório
vosk-model-small-pt-0.3/existe no diretório de trabalho onde o nó é executado.
Silero não carrega o modelo
Na primeira execução, o modelo é baixado pelo PyTorch Hub (~60 MB). Certifique-se de ter acesso à internet nessa etapa. Nas execuções seguintes funciona offline (cache em
~/.cache/torch/hub).
Nenhum áudio no alto-falante
Verifique o dispositivo de saída padrão com
python -c "import sounddevice as sd; print(sd.query_devices())"e ajuste conforme necessário.
LLM lento na primeira resposta
O Ollama carrega o modelo na primeira chamada. Use
keep_alive=-1(já configurado) para manter o modelo em memória e eliminar esse delay nas próximas interações.
Este projeto foi desenvolvido para uso interno em operações de mineração. Consulte a equipe responsável para informações sobre licenciamento e distribuição.