You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
416 lines
12 KiB
Markdown
416 lines
12 KiB
Markdown
# AI Orquestrador
|
|
|
|
Orquestrador conversacional para operacao automotiva, focado em combinar:
|
|
- interpretacao semantica via Vertex AI
|
|
- execucao deterministica de tools de negocio
|
|
- normalizacao tecnica na aplicacao
|
|
- atendimento pelo Telegram como canal principal
|
|
|
|
## Proposta
|
|
|
|
A ideia central do sistema e:
|
|
- o usuario conversa em linguagem natural
|
|
- o modelo entende intencao, contexto e proximo passo
|
|
- a aplicacao protege regras, normaliza dados e executa tools de negocio
|
|
- a resposta final volta ao usuario no canal de atendimento
|
|
|
|
Hoje o projeto esta mais proximo de um orquestrador conversacional do que de uma API tradicional. O FastAPI continua no repositorio como apoio legado e operacional, mas o fluxo principal roda no satelite do Telegram.
|
|
|
|
## Estado Atual
|
|
|
|
O dominio atual cobre tres frentes principais:
|
|
- vendas
|
|
- revisao e pos-venda
|
|
- aluguel de veiculos
|
|
|
|
Capacidades de negocio ja implementadas:
|
|
- consultar estoque de veiculos
|
|
- validar cliente para compra
|
|
- avaliar veiculo para troca
|
|
- criar pedido
|
|
- listar pedidos
|
|
- cancelar pedido
|
|
- agendar revisao
|
|
- listar agendamentos de revisao
|
|
- cancelar agendamento de revisao
|
|
- remarcar revisao
|
|
- consultar frota de aluguel
|
|
- abrir locacao
|
|
- registrar pagamento de aluguel
|
|
- registrar multa de aluguel
|
|
- registrar devolucao de aluguel
|
|
- responder consultas informativas sobre o aluguel atual, como contrato, placa, diaria, pagamento e data de devolucao
|
|
|
|
Capacidades conversacionais ja tratadas:
|
|
- multiplos pedidos na mesma mensagem
|
|
- fila de pedidos pendentes
|
|
- escolha explicita de qual assunto iniciar primeiro
|
|
- refinamento implicito de uma opcao ja detectada
|
|
- troca de contexto entre dominios
|
|
- coleta incremental de campos
|
|
- reaproveitamento de contexto temporario
|
|
- reidratacao do ultimo contrato de locacao quando o estado em memoria nao existe mais
|
|
- confirmacao antes de mudar de assunto em fluxos abertos
|
|
- sugestao de horario alternativo em conflito de agenda
|
|
- retries defensivos no envio de respostas ao Telegram
|
|
|
|
## Arquitetura Atual
|
|
|
|
| Componente | Tecnologia | Papel atual |
|
|
| --- | --- | --- |
|
|
| LLM | Vertex AI / Gemini | interpretacao e apoio a decisao |
|
|
| Orquestracao | Python | coordena contexto, fluxo, tools e resposta |
|
|
| Metadados de tools | MySQL | catalogo das tools disponiveis |
|
|
| Dados mock de negocio | MySQL | veiculos, clientes, usuarios, pedidos, revisoes e locacoes |
|
|
| Estado conversacional | Redis ou memoria | rascunhos, fila, snapshots e contexto temporario |
|
|
| Canal | Telegram Bot API | atendimento principal via long polling |
|
|
| Containerizacao | Docker Compose | ambiente local e deploy simples |
|
|
|
|
## Fluxo Principal
|
|
|
|
Fluxo principal do atendimento pelo Telegram:
|
|
|
|
1. O usuario envia uma mensagem ao bot.
|
|
2. O `TelegramSatelliteService` identifica ou cria o usuario interno.
|
|
3. O `OrquestradorService` recupera contexto, fila e fluxos abertos.
|
|
4. O sistema tenta resolver atalhos deterministas antes de consultar o LLM, como continuidade de fluxo, selecao pendente, pagamento de aluguel e consulta do contrato atual.
|
|
5. O `MessagePlanner` e o Vertex ajudam a estruturar o turno quando necessario.
|
|
6. A tool e executada com validacoes e normalizacoes deterministicas.
|
|
7. O sistema persiste a trilha do turno e devolve a resposta ao usuario no Telegram.
|
|
|
|
Importante:
|
|
- a trilha de turnos fica registrada em `conversation_turns` para auditoria operacional;
|
|
- o estado de trabalho pode ficar em memoria ou Redis;
|
|
- em producao com Telegram, o backend esperado para estado conversacional e Redis;
|
|
- o bootstrap de banco e seed e uma rotina separada do servico principal.
|
|
|
|
## Estrutura do Projeto
|
|
|
|
```text
|
|
app/
|
|
main.py
|
|
api/
|
|
schemas.py
|
|
core/
|
|
settings.py
|
|
time_utils.py
|
|
db/
|
|
bootstrap.py
|
|
database.py
|
|
init_db.py
|
|
mock_database.py
|
|
mock_models.py
|
|
mock_seed.py
|
|
tool_seed.py
|
|
models/
|
|
tool.py
|
|
integrations/
|
|
telegram_satellite_service.py
|
|
models/
|
|
tool_model.py
|
|
repositories/
|
|
tool_repository.py
|
|
user_repository.py
|
|
services/
|
|
ai/
|
|
llm_service.py
|
|
domain/
|
|
credit_service.py
|
|
inventory_service.py
|
|
order_service.py
|
|
rental_service.py
|
|
review_service.py
|
|
flows/
|
|
flow_state_support.py
|
|
order_flow.py
|
|
order_flow_support.py
|
|
rental_flow.py
|
|
rental_flow_support.py
|
|
review_flow.py
|
|
review_flow_support.py
|
|
orchestration/
|
|
conversation_history_service.py
|
|
conversation_policy.py
|
|
conversation_state_repository.py
|
|
conversation_state_store.py
|
|
entity_normalizer.py
|
|
message_planner.py
|
|
orchestrator_context_manager.py
|
|
orchestrator_execution_manager.py
|
|
orquestrador_service.py
|
|
prompt_builders.py
|
|
redis_state_repository.py
|
|
response_formatter.py
|
|
sensitive_data.py
|
|
state_repository_factory.py
|
|
tool_executor.py
|
|
turn_decision.py
|
|
tools/
|
|
handlers.py
|
|
tool_registry.py
|
|
user/
|
|
mock_customer_service.py
|
|
user_service.py
|
|
scripts/
|
|
list_integration_deliveries.py
|
|
list_integration_routes.py
|
|
process_integration_deliveries.py
|
|
upsert_integration_route.py
|
|
stress_smoke.py
|
|
tests/
|
|
...
|
|
```
|
|
|
|
## Tools Disponiveis
|
|
|
|
As definicoes padrao ficam em [app/db/tool_seed.py](app/db/tool_seed.py):
|
|
|
|
| Tool | Finalidade |
|
|
| --- | --- |
|
|
| `consultar_estoque` | consulta veiculos por preco, categoria e ordenacao |
|
|
| `validar_cliente_venda` | valida elegibilidade de compra por CPF e valor |
|
|
| `avaliar_veiculo_troca` | estima valor de troca do veiculo do cliente |
|
|
| `realizar_pedido` | cria pedido de compra |
|
|
| `listar_pedidos` | lista pedidos do usuario |
|
|
| `cancelar_pedido` | cancela pedido existente |
|
|
| `agendar_revisao` | agenda revisao com calculo de valor |
|
|
| `listar_agendamentos_revisao` | lista revisoes do usuario |
|
|
| `cancelar_agendamento_revisao` | cancela revisao por protocolo |
|
|
| `editar_data_revisao` | remarca revisao existente |
|
|
| `consultar_frota_aluguel` | lista frota disponivel para locacao |
|
|
| `abrir_locacao_aluguel` | abre contrato de locacao |
|
|
| `registrar_pagamento_aluguel` | registra pagamento vinculado ao contrato |
|
|
| `registrar_multa_aluguel` | registra multa vinculada ao contrato |
|
|
| `registrar_devolucao_aluguel` | encerra locacao e calcula valor final |
|
|
| `limpar_contexto_conversa` | zera contexto e fila |
|
|
| `continuar_proximo_pedido` | retoma o proximo item da fila |
|
|
| `descartar_pedidos_pendentes` | limpa apenas a fila pendente |
|
|
| `cancelar_fluxo_atual` | encerra apenas o fluxo atual |
|
|
|
|
## Banco e Bootstrap
|
|
|
|
O projeto usa duas conexoes MySQL:
|
|
- banco de tools
|
|
- banco mock de negocio
|
|
|
|
O bootstrap e uma rotina dedicada e explicita:
|
|
- [app/db/bootstrap.py](app/db/bootstrap.py)
|
|
- [app/db/init_db.py](app/db/init_db.py) como alias legado de compatibilidade
|
|
|
|
Importante:
|
|
- o container principal nao executa bootstrap automaticamente;
|
|
- o app HTTP legado nao executa bootstrap no startup;
|
|
- schema e seed devem ser preparados de forma explicita quando necessario.
|
|
|
|
## Execucao Local
|
|
|
|
### Sem Docker
|
|
|
|
1. Configure as variaveis de ambiente com base em `.env.example`, `.env.local` ou `.env.prod`, conforme o ambiente.
|
|
2. Rode bootstrap quando precisar preparar schema e seeds:
|
|
|
|
```bash
|
|
python -m app.db.bootstrap
|
|
```
|
|
|
|
Alias legado ainda aceito:
|
|
|
|
```bash
|
|
python -m app.db.init_db
|
|
```
|
|
|
|
3. Inicie o satelite do Telegram:
|
|
|
|
```bash
|
|
python -m app.integrations.telegram_satellite_service
|
|
```
|
|
|
|
Se estiver usando um arquivo dedicado, como `.env.local`, voce pode executar com `python-dotenv`:
|
|
|
|
```bash
|
|
python -m dotenv -f .env.local run -- python -m app.db.bootstrap
|
|
python -m dotenv -f .env.local run -- python -m app.integrations.telegram_satellite_service
|
|
```
|
|
|
|
O app HTTP legado continua disponivel quando necessario:
|
|
|
|
```bash
|
|
python -m uvicorn app.main:app --reload
|
|
```
|
|
|
|
### Com Docker Compose
|
|
|
|
O compose atual sobe:
|
|
- `mysql`
|
|
- `redis`
|
|
- `telegram`
|
|
- `bootstrap` como rotina opcional e dedicada via profile
|
|
|
|
Preparar banco e seed:
|
|
|
|
```bash
|
|
docker compose --profile bootstrap run --rm bootstrap
|
|
```
|
|
|
|
Subida completa do atendimento:
|
|
|
|
```bash
|
|
docker compose up --build
|
|
```
|
|
|
|
Somente infraestrutura:
|
|
|
|
```bash
|
|
docker compose up mysql redis
|
|
```
|
|
|
|
## Variaveis de Ambiente
|
|
|
|
Principais variaveis:
|
|
|
|
### Vertex AI
|
|
|
|
- `GOOGLE_PROJECT_ID`
|
|
- `GOOGLE_LOCATION`
|
|
- `VERTEX_MODEL_NAME`
|
|
|
|
### Banco de tools
|
|
|
|
- `DB_HOST`
|
|
- `DB_PORT`
|
|
- `DB_USER`
|
|
- `DB_PASSWORD`
|
|
- `DB_NAME`
|
|
- `DB_CLOUD_SQL_CONNECTION_NAME`
|
|
|
|
### Banco mock
|
|
|
|
- `MOCK_DB_HOST`
|
|
- `MOCK_DB_PORT`
|
|
- `MOCK_DB_USER`
|
|
- `MOCK_DB_PASSWORD`
|
|
- `MOCK_DB_NAME`
|
|
- `MOCK_DB_CLOUD_SQL_CONNECTION_NAME`
|
|
- `MOCK_SEED_ENABLED`
|
|
- `AUTO_SEED_TOOLS`
|
|
- `AUTO_SEED_MOCK`
|
|
|
|
### Telegram
|
|
|
|
- `TELEGRAM_BOT_TOKEN`
|
|
- `TELEGRAM_POLLING_TIMEOUT`
|
|
- `TELEGRAM_REQUEST_TIMEOUT`
|
|
|
|
### Estado conversacional
|
|
|
|
- `CONVERSATION_STATE_BACKEND` (`memory` ou `redis`)
|
|
- `CONVERSATION_STATE_TTL_MINUTES`
|
|
- `REDIS_URL`
|
|
- `REDIS_KEY_PREFIX`
|
|
- `REDIS_SOCKET_TIMEOUT_SECONDS`
|
|
|
|
### Integracoes externas
|
|
|
|
- `INTEGRATIONS_ENABLED`
|
|
- `INTEGRATION_SYNC_DELIVERY_ENABLED`
|
|
- `BREVO_API_KEY`
|
|
- `BREVO_BASE_URL`
|
|
- `BREVO_SENDER_EMAIL`
|
|
- `BREVO_SENDER_NAME`
|
|
- `BREVO_REQUEST_TIMEOUT_SECONDS`
|
|
|
|
### Ambiente
|
|
|
|
- `ENVIRONMENT`
|
|
- `DEBUG`
|
|
|
|
Observacoes:
|
|
- para producao com Telegram, use `CONVERSATION_STATE_BACKEND=redis`;
|
|
- `memory` e util para desenvolvimento local e alguns smoke tests;
|
|
- evite valores nao booleanos em `DEBUG`.
|
|
|
|
## Docker
|
|
|
|
O [Dockerfile](Dockerfile) sobe apenas o servico principal do projeto:
|
|
|
|
```bash
|
|
python -m app.integrations.telegram_satellite_service
|
|
```
|
|
|
|
O bootstrap fica separado e pode ser executado quando necessario com:
|
|
|
|
```bash
|
|
python -m app.db.bootstrap
|
|
```
|
|
|
|
Isso evita que um restart do container recrie schema ou rode seed de forma implicita.
|
|
|
|
## Testes e Stress
|
|
|
|
Suite automatizada:
|
|
|
|
```bash
|
|
python -m unittest discover -s tests -v
|
|
```
|
|
|
|
Se o ambiente local tiver `DEBUG` com valor invalido, force antes da execucao:
|
|
|
|
```bash
|
|
DEBUG=false python -m unittest discover -s tests -v
|
|
```
|
|
|
|
Stress smoke local para estado, ciclos de pedido e corrida de reserva:
|
|
|
|
```bash
|
|
python scripts/stress_smoke.py --backend memory --state-iterations 200 --order-cycles 30 --race-attempts 8 --user-base 995000 --cpf 11144477735
|
|
```
|
|
|
|
Se voce estiver usando um arquivo de ambiente dedicado:
|
|
|
|
```bash
|
|
python -m dotenv -f .env.local run -- python scripts/stress_smoke.py --backend memory --state-iterations 200 --order-cycles 30 --race-attempts 8 --user-base 995000 --cpf 11144477735
|
|
```
|
|
|
|
Operacao basica do outbox de integracoes:
|
|
|
|
```bash
|
|
python scripts/upsert_integration_route.py --event order.created --recipient ops@empresa.com
|
|
python scripts/list_integration_routes.py --enabled
|
|
python scripts/list_integration_deliveries.py --status failed --limit 20
|
|
python scripts/process_integration_deliveries.py --status failed --limit 20
|
|
```
|
|
|
|
Exemplo de configuracao mais completa da rota Brevo:
|
|
|
|
```bash
|
|
python scripts/upsert_integration_route.py --event order.created --recipient ops@empresa.com --sender-email noreply@empresa.com --sender-name Operacoes --reply-to-email atendimento@empresa.com --reply-to-name Atendimento --cc financeiro@empresa.com --tag pedidos --tag operacao --header X-Canal=orquestrador
|
|
```
|
|
|
|
Campos aceitos no `provider_config` da rota: `sender`, `reply_to`, `cc`, `bcc`, `tags`, `headers` e `html_content`.
|
|
Para casos mais avancados, o script tambem aceita `--provider-config-json` com um objeto JSON.
|
|
|
|
## Deploy
|
|
|
|
O deploy de servidor fica documentado em [DEPLOY_SERVIDOR.md](DEPLOY_SERVIDOR.md).
|
|
|
|
No modelo atual:
|
|
- o servico `orquestrador` do `systemd` executa o `telegram_satellite_service`;
|
|
- o bootstrap pode ser rodado manualmente ou por uma unit separada;
|
|
- em producao, Redis deve estar disponivel para o estado conversacional.
|
|
|
|
## Arquivos Uteis
|
|
|
|
- [TEST_CASES.md](TEST_CASES.md)
|
|
- [DEPLOY_SERVIDOR.md](DEPLOY_SERVIDOR.md)
|
|
- [.env.example](.env.example)
|
|
- [scripts/stress_smoke.py](scripts/stress_smoke.py)
|
|
|
|
## Proximos Passos Naturais
|
|
|
|
Os proximos ganhos mais valiosos para o projeto sao:
|
|
- introduzir migracoes de banco de dados
|
|
- ampliar observabilidade por turno, tool e canal
|
|
- evoluir a trilha de auditoria e consultas operacionais
|
|
- criar uma camada de avaliacao semantica e replay de conversas
|
|
- integrar o orquestrador com sistemas reais de operacao
|