From 97673fe67be18e9cbb845c990f866abe632eaca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Hugo=20Belorio=20Sim=C3=A3o?= Date: Mon, 23 Feb 2026 15:56:39 -0300 Subject: [PATCH] feat: Adicionando scripts de setup e testes --- TEST_CASES.md | 152 ++++++++++++++++++++++++++++ app/db/init_db.py | 28 ++++++ setup-database.sh | 59 +++++++++++ setup-gcp.sh | 245 ++++++++++++++++++++++++++++++++++++++++++++++ test-local.sh | 76 ++++++++++++++ 5 files changed, 560 insertions(+) create mode 100644 TEST_CASES.md create mode 100644 app/db/init_db.py create mode 100644 setup-database.sh create mode 100644 setup-gcp.sh create mode 100644 test-local.sh diff --git a/TEST_CASES.md b/TEST_CASES.md new file mode 100644 index 0000000..69b38a4 --- /dev/null +++ b/TEST_CASES.md @@ -0,0 +1,152 @@ +# Test Cases para o Orquestrador + +## Testes Manuais + +### Setup + +```bash +# Terminal 1: Iniciar servidor +uvicorn app.main:app --reload + +# Terminal 2: Rodar testes +bash test-local.sh http://localhost:8000 +``` + +Ou com Docker Compose: + +```bash +docker-compose up +bash test-local.sh http://localhost:8000 +``` + +## Casos de Teste + +### 1. Chat Simples (Sem Tool) + +```bash +curl -X POST http://localhost:8000/chat \ + -H "Content-Type: application/json" \ + -d '{ + "message": "Olá, como você funciona?", + "user_id": "user-123" + }' +``` + +**Esperado**: Resposta direta do modelo, sem chamada de tool + +--- + +### 2. Consultar Estoque + +```bash +curl -X POST http://localhost:8000/chat \ + -H "Content-Type: application/json" \ + -d '{ + "message": "Quero um carro de até 50000 reais", + "user_id": "user-123" + }' +``` + +**Esperado**: Modelo chama `consultar_estoque` com `preco_max=50000` + +--- + +### 3. Validar Cliente Venda + +```bash +curl -X POST http://localhost:8000/chat \ + -H "Content-Type: application/json" \ + -d '{ + "message": "Meu CPF é 12345678900. Posso financiar um carro de 45000 reais?", + "user_id": "user-123" + }' +``` + +**Esperado**: Modelo chama `validar_cliente_venda` + +--- + +### 4. Avaliar Veículo para Troca + +```bash +curl -X POST http://localhost:8000/chat \ + -H "Content-Type: application/json" \ + -d '{ + "message": "Tenho um Toyota Corolla 2015 com 120000 km para dar de entrada. Quanto vale?", + "user_id": "user-123" + }' +``` + +**Esperado**: Modelo chama `avaliar_veiculo_troca` + +--- + +### 5. Agendar Revisão + +```bash +curl -X POST http://localhost:8000/chat \ + -H "Content-Type: application/json" \ + -d '{ + "message": "Quero agendar uma revisão para meu carro com placa ABC1234 no dia 25 de fevereiro às 10 da manhã", + "user_id": "user-123" + }' +``` + +**Esperado**: Modelo chama `agendar_revisao` + +--- + +### 6. Cancelar Pedido + +```bash +curl -X POST http://localhost:8000/chat \ + -H "Content-Type: application/json" \ + -d '{ + "message": "Gostaria de cancelar meu pedido número 12345 porque mudei de ideia", + "user_id": "user-123" + }' +``` + +**Esperado**: Modelo chama `cancelar_pedido` + +--- + +## Swagger UI + +Acesse: http://localhost:8000/docs + +Todos os endpoints estão documentados lá para testar interativamente. + +## Checklist de Testes + +- [ ] Chat simples sem tool funciona +- [ ] Consultar estoque retorna veículos +- [ ] Validar cliente retorna aprovação/rejeição +- [ ] Avaliar veículo retorna valor estimado +- [ ] Agendar revisão retorna agendamento +- [ ] Cancelar pedido retorna cancelamento +- [ ] Modelo é assertivo (chama tools quando apropriado) +- [ ] Modelo não chama tools desnecessariamente +- [ ] Respostas são formatadas corretamente +- [ ] Sem erros 500 na API + +## Debugging + +### Ver logs detalhados + +```bash +# Terminal com logs +uvicorn app.main:app --reload --log-level debug +``` + +### Testar Mockaroo direto + +```bash +curl -X POST http://localhost:8000/mock/consultar-estoque \ + -H "Content-Type: application/json" \ + -d '{"preco_max": 50000}' +``` + +### Ver resposta do Vertex AI + +Adicione console.log nos handlers para ver o que o Vertex retorna. diff --git a/app/db/init_db.py b/app/db/init_db.py new file mode 100644 index 0000000..29337da --- /dev/null +++ b/app/db/init_db.py @@ -0,0 +1,28 @@ +""" +Inicialização de banco de dados +Cria tabelas e faz seed dos dados iniciais +""" + +from app.db.database import Base, engine +from app.db.models import Tool +from app.db.tool_seed import get_tools_definitions, seed_tools + + +def init_db(): + """Cria todas as tabelas e faz o seed dos dados iniciais""" + print("📊 Inicializando banco de dados...") + + # Cria todas as tabelas + print("🔨 Criando tabelas...") + Base.metadata.create_all(bind=engine) + + # Seed das tools + print("📥 Populando tools iniciais...") + seed_tools() + + print("✅ Banco de dados inicializado com sucesso!") + + +if __name__ == "__main__": + init_db() + diff --git a/setup-database.sh b/setup-database.sh new file mode 100644 index 0000000..46839eb --- /dev/null +++ b/setup-database.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +# Script para setup inicial no Google Cloud SQL +# Uso: ./setup-database.sh + +set -e + +PROJECT_ID=${1:-seu-projeto-id} +INSTANCE_NAME=${2:-orquestrador-db} +REGION=${3:-us-central1} +DB_NAME="orquestrador" +DB_USER="postgres" + +echo "📊 Criando instância Cloud SQL PostgreSQL" +echo "📦 Projeto: $PROJECT_ID" +echo "🏢 Instância: $INSTANCE_NAME" +echo "🌍 Região: $REGION" + +# Habilitar SQL Admin API +echo "📡 Habilitando Cloud SQL Admin API..." +gcloud services enable sqladmin.googleapis.com + +# Criar instância PostgreSQL +echo "🔨 Criando instância PostgreSQL..." +gcloud sql instances create $INSTANCE_NAME \ + --project=$PROJECT_ID \ + --database-version=POSTGRES_15 \ + --region=$REGION \ + --tier=db-f1-micro \ + --availability-type=ZONAL \ + --backup-start-time=03:00 \ + --enable-bin-log \ + --no-assign-ip + +# Criar banco de dados +echo "🗄️ Criando banco de dados..." +gcloud sql databases create $DB_NAME \ + --instance=$INSTANCE_NAME \ + --project=$PROJECT_ID + +# Criar usuário +echo "👤 Criando usuário de banco de dados..." +gcloud sql users create $DB_USER \ + --instance=$INSTANCE_NAME \ + --project=$PROJECT_ID + +echo "" +echo "✅ Setup do banco de dados concluído!" +echo "" +echo "📋 Configurações do Cloud SQL:" +echo "🏢 Instância: $INSTANCE_NAME" +echo "📦 Banco: $DB_NAME" +echo "👤 Usuário: $DB_USER" +echo "" +echo "próximos passos:" +echo "1. Defina a senha do usuário postgres no Cloud Console" +echo "2. Configure a connection string:" +echo " postgresql://$DB_USER:SENHA@/cloudsql/$PROJECT_ID:$REGION:$INSTANCE_NAME/$DB_NAME" + diff --git a/setup-gcp.sh b/setup-gcp.sh new file mode 100644 index 0000000..0e1e656 --- /dev/null +++ b/setup-gcp.sh @@ -0,0 +1,245 @@ +#!/bin/bash + +# Script interativo para setup no Google Cloud +# Execute: bash setup-gcp.sh + +set -e + +echo "╔══════════════════════════════════════════════════════════╗" +echo "║ 🚀 Setup Google Cloud para Orquestrador MVP ║" +echo "╚══════════════════════════════════════════════════════════╝" +echo "" + +# Cores para output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Função para perguntar +ask() { + local prompt="$1" + local default="$2" + local input + + read -p "$prompt [$default]: " input + echo "${input:-$default}" +} + +# Função para sucesso +success() { + echo -e "${GREEN}✅ $1${NC}" +} + +# Função para erro +error() { + echo -e "${RED}❌ $1${NC}" + exit 1 +} + +# Função para info +info() { + echo -e "${BLUE}ℹ️ $1${NC}" +} + +# Função para aviso +warning() { + echo -e "${YELLOW}⚠️ $1${NC}" +} + +# ============================================================================ +# STEP 1: Verificar pré-requisitos +# ============================================================================ + +echo "" +echo "📋 STEP 1: Verificando pré-requisitos..." +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# Verificar gcloud +if ! command -v gcloud &> /dev/null; then + error "Google Cloud SDK não instalado. Acesse: https://cloud.google.com/sdk/docs/install" +fi +success "Google Cloud SDK instalado" + +# Verificar autenticação +if ! gcloud auth list --filter=status:ACTIVE --format="value(account)" | grep -q "@"; then + warning "Você não está autenticado no Google Cloud" + info "Executando: gcloud auth login" + gcloud auth login +fi +success "Autenticado no Google Cloud" + +echo "" + +# ============================================================================ +# STEP 2: Definir ou escolher projeto +# ============================================================================ + +echo "" +echo "📦 STEP 2: Configurar Projeto Google Cloud..." +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +# Listar projetos existentes +echo "" +info "Seus projetos atuais:" +gcloud projects list --format="table(projectId,name)" | head -10 + +echo "" +PROJECT_ID=$(ask "Digite seu PROJECT_ID (ex: orquestrador-mvp)" "orquestrador-mvp") + +# Verificar se projeto existe +if gcloud projects describe "$PROJECT_ID" &> /dev/null; then + success "Projeto '$PROJECT_ID' encontrado" +else + warning "Projeto '$PROJECT_ID' não existe. Criando..." + gcloud projects create "$PROJECT_ID" --name="Orquestrador MVP" + success "Projeto criado" +fi + +# Configurar como padrão +gcloud config set project "$PROJECT_ID" +success "Projeto configurado como padrão" + +echo "" + +# ============================================================================ +# STEP 3: Habilitar APIs +# ============================================================================ + +echo "" +echo "🔧 STEP 3: Habilitando APIs necessárias..." +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +info "Habilitando: Cloud Run, Vertex AI, Cloud Build, Cloud SQL..." +gcloud services enable \ + run.googleapis.com \ + aiplatform.googleapis.com \ + cloudbuild.googleapis.com \ + sqladmin.googleapis.com \ + cloudresourcemanager.googleapis.com \ + --quiet + +success "APIs habilitadas" + +echo "" + +# ============================================================================ +# STEP 4: Configurar Cloud SQL +# ============================================================================ + +echo "" +echo "🗄️ STEP 4: Configurar Banco de Dados (Cloud SQL)..." +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +DB_INSTANCE_NAME="orquestrador-db" +REGION="us-central1" + +# Verificar se instância existe +if gcloud sql instances describe "$DB_INSTANCE_NAME" --region="$REGION" &> /dev/null; then + success "Instância Cloud SQL já existe" +else + warning "Criando instância Cloud SQL PostgreSQL..." + warning "Isso pode levar 2-3 minutos..." + + gcloud sql instances create "$DB_INSTANCE_NAME" \ + --database-version=POSTGRES_15 \ + --region="$REGION" \ + --tier=db-f1-micro \ + --no-assign-ip \ + --quiet + + success "Instância Cloud SQL criada" +fi + +# Criar banco de dados +if gcloud sql databases describe orquestrador --instance="$DB_INSTANCE_NAME" &> /dev/null; then + success "Banco de dados já existe" +else + info "Criando banco de dados 'orquestrador'..." + gcloud sql databases create orquestrador \ + --instance="$DB_INSTANCE_NAME" \ + --quiet + success "Banco de dados criado" +fi + +# Definir senha +echo "" +read -s -p "Defina uma senha segura para o usuário 'postgres': " DB_PASSWORD +echo "" + +gcloud sql users set-password postgres \ + --instance="$DB_INSTANCE_NAME" \ + --password="$DB_PASSWORD" \ + --quiet + +success "Senha do usuário postgres definida" + +echo "" + +# ============================================================================ +# STEP 5: Configurar variáveis de ambiente +# ============================================================================ + +echo "" +echo "🔐 STEP 5: Configurar Variáveis de Ambiente..." +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" + +MOCKAROO_API_KEY=$(ask "Cole sua API Key do Mockaroo (https://www.mockaroo.com)" "") + +if [ -z "$MOCKAROO_API_KEY" ]; then + error "API Key do Mockaroo é obrigatória" +fi + +# Criar arquivo .env.prod +cat > .env.prod << EOF +GOOGLE_PROJECT_ID=$PROJECT_ID +GOOGLE_LOCATION=$REGION +DB_HOST=/cloudsql/$PROJECT_ID:$REGION:$DB_INSTANCE_NAME +DB_PORT=5432 +DB_USER=postgres +DB_PASSWORD=$DB_PASSWORD +DB_NAME=orquestrador +MOCKAROO_API_KEY=$MOCKAROO_API_KEY +MOCKAROO_BASE_URL=https://my.api.mockaroo.com +USE_MOCKAROO_WRITES=false +EOF + +success "Arquivo .env.prod criado" +warning "O arquivo .env.prod contém senhas. Nunca commite!" + +echo "" + +# ============================================================================ +# STEP 6: Resumo +# ============================================================================ + +echo "" +echo "╔══════════════════════════════════════════════════════════╗" +echo "║ ✅ Setup Completo! ║" +echo "╚══════════════════════════════════════════════════════════╝" +echo "" +echo "📋 Configuração Resumida:" +echo " Projeto: $PROJECT_ID" +echo " Banco de dados: orquestrador-db ($REGION)" +echo " Usuário: postgres" +echo " Banco: orquestrador" +echo "" +echo "🚀 Próximos passos:" +echo "" +echo " 1. Teste a aplicação localmente (opcional):" +echo " docker-compose up" +echo " bash test-local.sh http://localhost:8000" +echo "" +echo " 2. Faça o deploy no Google Cloud:" +echo " bash deploy.sh $PROJECT_ID $REGION" +echo "" +echo " 3. Pegue a URL do seu serviço:" +echo " gcloud run services describe orquestrador --region=$REGION --format='value(status.url)'" +echo "" +echo "💡 Dicas:" +echo " - Docs: cat README.md" +echo " - Troubleshooting: cat TROUBLESHOOTING.md" +echo " - Deploy Simples: cat DEPLOY_SIMPLES.md" +echo "" + diff --git a/test-local.sh b/test-local.sh new file mode 100644 index 0000000..ee5ce0d --- /dev/null +++ b/test-local.sh @@ -0,0 +1,76 @@ +#!/bin/bash + +# Script de testes locais +# Testa a API antes de fazer deploy + +set -e + +API_URL=${1:-http://localhost:8000} + +echo "🧪 Iniciando testes da API" +echo "🎯 URL: $API_URL" +echo "" + +# Função para teste HTTP +test_endpoint() { + local method=$1 + local endpoint=$2 + local data=$3 + local description=$4 + + echo "📝 Teste: $description" + echo " $method $endpoint" + + if [ -z "$data" ]; then + curl -s -X $method "$API_URL$endpoint" \ + -H "Content-Type: application/json" | jq . || echo "❌ Erro" + else + echo " Dados: $data" + curl -s -X $method "$API_URL$endpoint" \ + -H "Content-Type: application/json" \ + -d "$data" | jq . || echo "❌ Erro" + fi + echo "" +} + +# Teste 1: Health check (Swagger) +echo "═══════════════════════════════════════════════════════════" +test_endpoint "GET" "/docs" "" "Documentação Swagger" + +# Teste 2: Chat simples +echo "═══════════════════════════════════════════════════════════" +test_endpoint "POST" "/chat" \ + '{"message":"Olá, tudo bem?","user_id":"test-user-1"}' \ + "Chat simples (sem tool)" + +# Teste 3: Chat com ferramenta - Consultar Estoque +echo "═══════════════════════════════════════════════════════════" +test_endpoint "POST" "/chat" \ + '{"message":"Quero um carro de até 50000 reais que seja sedan","user_id":"test-user-2"}' \ + "Chat com tool - Consultar Estoque" + +# Teste 4: Chat com ferramenta - Validar Cliente +echo "═══════════════════════════════════════════════════════════" +test_endpoint "POST" "/chat" \ + '{"message":"Meu CPF é 12345678900 e quero financiar um carro de 45000 reais, posso?","user_id":"test-user-3"}' \ + "Chat com tool - Validar Cliente Venda" + +# Teste 5: Chat com ferramenta - Avaliar Veículo +echo "═══════════════════════════════════════════════════════════" +test_endpoint "POST" "/chat" \ + '{"message":"Tenho um Toyota Corolla 2015 com 120000 km, quanto vale para troca?","user_id":"test-user-4"}' \ + "Chat com tool - Avaliar Veículo Troca" + +# Teste 6: Mockaroo direto +echo "═══════════════════════════════════════════════════════════" +test_endpoint "POST" "/mock/consultar-estoque" \ + '{"preco_max":50000,"categoria":"Sedan"}' \ + "Endpoint direto - Consultar Estoque" + +echo "✅ Testes concluídos!" +echo "" +echo "💡 Dicas:" +echo " - Para testes mais detalhados, visite: $API_URL/docs" +echo " - Para ver os logs: tail -f app.log" +echo " - Para reiniciar: Ctrl+C e execute novamente" +