13 KiB
Crie um Chat com Dashboard utilizando Oracle Autonomous Database SELECT AI
1. Introdução
Este tutorial cria uma interface web simples (chat + cards com gráficos e tabelas) transformando perguntas em linguagem natural (pt-BR) em SQL automaticamente, usando o SELECT AI do Autonomous Database. É ideal para cenários como Pronto-Socorro (ER), vendas, logística etc., quando usuários de negócio querem insights imediatos sem escrever SQL.
Como funciona:
- O Flask serve uma página com um campo de pergunta e um histórico de respostas (cada resposta pode ter SQL gerado, tabela e gráfico Chart.js).
- Ao enviar a pergunta, o backend chama
SELECT AI 'sua pergunta' FROM <tabela/view>— quem gera e executa o SQL é o SELECT AI dentro do banco. - O app formata os resultados, tenta inferir o tipo de gráfico e permite exportar tudo para PDF (html2canvas + jsPDF, no navegador) e Excel (duas opções: no navegador com XlsxPopulate ou no servidor com
openpyxl).
Tecnologias principais:
- Oracle Autonomous Database 23ai com SELECT AI e DBMS_CLOUD_AI (perfis de LLM)
- Python + Flask + python-oracledb (Thin) com mTLS (wallet)
- Front-end: Chart.js, html2canvas + jsPDF e XlsxPopulate (via CDN)
2. Pré-requisitos
Oracle Cloud
- Um Autonomous Database (Serverless) em 23ai (ou com SELECT AI disponível).
- Saída de rede do ADB para acessar o serviço OCI Generative AI.
- Permissões para usar DBMS_CLOUD / DBMS_CLOUD_AI e criar perfis de IA.
- Modelo/Região do OCI Generative AI habilitados (ex.:
cohere.command-r-08-2024emus-chicago-1).
Uma VM Linux para hospedagem da página Web (app Flask)
- Python 3.10+ (recomendado).
- Pacotes:
flask,oracledb,openpyxl,pillow. - Wallet do ADB (ZIP baixado do console).
3. Entendendo o código (trecho a trecho)
O código-fonte pode ser baixado aqui: app_select_ai.py
Conexão e sessão com perfil de IA
- Lê config (wallet, alias TNS, usuário/senha).
- Define
TNS_ADMIN. session_callbackativa o perfil de IA (garante SELECT AI pronto em cada sessão).
run_select_ai
- Monta a sentença
SELECT AI 'pergunta' FROM <tabela>. - Executa e retorna SQL gerado, headers/rows e usuário/perfil ativos.
build_chart e format_table
build_chart: heurísticas para inferir gráfico (pizza, barras, linha).format_table: limita registros e devolve{headers, rows}.
Front-end (PAGE)
- Chart.js desenha gráficos; toolbar alterna tipos.
- Exportar PDF: usa html2canvas + jsPDF.
- Exportar Excel: cliente (XlsxPopulate) ou servidor (openpyxl).
Histórico (session)
- Mantém últimos 10 cards em
timeline.
4. SELECT AI no Autonomous Database
- Permite NL→SQL direto no banco.
- Configuração feita via Perfis de IA (
DBMS_CLOUD_AI.CREATE_PROFILE). - Perfis incluem provider, modelo, region, credential e lista de objetos (tables/views).
- Comandos auxiliares:
showsql,explain,narrateetc.
5. Instalação e implantação
5.1. Criar usuário e permissionamento como ADMIN
Execute estes comandos como ADMIN no Autonomous Database:
CREATE USER MEU_USUARIO IDENTIFIED BY "SenhaForte123";
ALTER USER MEU_USUARIO QUOTA UNLIMITED ON DATA;
GRANT CREATE SESSION TO MEU_USUARIO;
GRANT CREATE TABLE, CREATE VIEW, CREATE SEQUENCE TO MEU_USUARIO;
GRANT SELECT ON ADMIN.DATASET_ED_ADMISSION TO MEU_USUARIO;
GRANT EXECUTE ON DBMS_CLOUD TO MEU_USUARIO;
GRANT EXECUTE ON DBMS_CLOUD_AI TO MEU_USUARIO;
5.2 Escolher o método de autenticação do SELECT AI
Há duas opções. Escolha uma opção (A ou B) conforme necessidade:
Opção A — Resource Principal (RP) (recomendada no ADB)
Sem armazenar chave no banco; usa a identidade do serviço ADB.
BEGIN
DBMS_CLOUD_ADMIN.ENABLE_PRINCIPAL_AUTH(provider => 'OCI'); -- habilita provedor OCI no ADB
END;
/
BEGIN
DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL(); -- ativa RP no banco
END;
/
BEGIN
DBMS_CLOUD_ADMIN.ENABLE_PRINCIPAL_AUTH( -- permite o schema usar RP
provider => 'OCI',
username => 'MEU_USUARIO'
);
END;
/
Opção B — Credencial com API Key
Armazena uma credencial (OCID do usuário IAM + chave privada).
Substitua username e password pelos seus valores (OCID e chave/PEM).
BEGIN
DBMS_CLOUD.CREATE_CREDENTIAL(
credential_name => 'OCI_GENAI_CRED',
username => 'ocid1.user.oc1..aaaa...vx', -- OCID do usuário IAM
password => 'SUA_CHAVE_PRIVADA_OU_CONTEUDO' -- chave/PEM
);
END;
/
5.3 Criar o(s) Perfil(is) de IA (SELECT AI)
O perfil define provedor, região, credencial/RP, quais objetos o LLM pode usar e (opcionalmente) o modelo.
Exemplo 1 — Perfil com Resource Principal
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
'OCI_GENAI',
'{
"provider": "OCI",
"credential_name": "OCI$RESOURCE_PRINCIPAL",
"object_list": [ { "owner": "ADMIN" } ],
"model": "cohere.command-r-08-2024",
"oci_runtimetype": "COHERE",
"temperature": "0.4"
}'
);
END;
/
Exemplo 2 — Perfil principal da aplicação (com Credencial)
Inclui explicitamente os objetos que o SELECT AI pode usar:
BEGIN
DBMS_CLOUD_AI.CREATE_PROFILE(
profile_name => 'OCI_GENERATIVE_AI_PROFILE',
attributes =>
'{
"provider":"OCI",
"region":"us-chicago-1",
"credential_name":"OCI$RESOURCE_PRINCIPAL",
"object_list":[
{"owner":"ADMIN","name":"DATASET_ED_ADMISSION"},
{"owner":"MEU_USUARIO","name":"NLU_ED_ADMISSION"}
],
"model":"cohere.command-r-08-2024"
}'
);
END;
/
Nota: 💡 Dica: se preferir, você pode omitir "model" e deixar o ADB usar o modelo padrão da região/provedor.
Nota: 🔒 Segurança: liste somente os objetos necessários em object_list.
5.4 Ativar o perfil e torná-lo ativo na sessão
BEGIN
DBMS_CLOUD_AI.ENABLE_PROFILE('OCI_GENERATIVE_AI_PROFILE');
END;
/
EXEC DBMS_CLOUD_AI.SET_PROFILE('OCI_GENERATIVE_AI_PROFILE');
SELECT DBMS_CLOUD_AI.GET_PROFILE() AS active_after FROM dual;
IMPORTANTE: É necessário executar este comando abaixo antes de cada consulta SELECT AI:
CALL DBMS_CLOUD_AI.SET_PROFILE('OCI_GENERATIVE_AI_PROFILE');
5.5 Enriquecer o vocabulário
Enriquecer o vocabulário com COMMENT ON na tabela gerada no tutorial: Hospital Risk Admission Prediction with Machine Learning
Comentários ajudam o LLM a entender o domínio (descrições de tabelas/colunas).
COMMENT ON TABLE DATASET_ED_ADMISSION IS
'Tabela de pacientes do pronto-socorro / ER patients admission table';
COMMENT ON COLUMN DATASET_ED_ADMISSION.subject_id IS
'Patient ID / ID do paciente (unique identifier)';
COMMENT ON COLUMN DATASET_ED_ADMISSION.hadm_id IS
'Hospital admission ID / ID da internação hospitalar (NULL if not admitted)';
COMMENT ON COLUMN DATASET_ED_ADMISSION.stay_id IS
'ER stay ID / ID da estadia no pronto-socorro';
COMMENT ON COLUMN DATASET_ED_ADMISSION.intime IS
'ER entry timestamp / Data-hora de entrada no pronto-socorro (use EXTRACT(MONTH) for month filter)';
COMMENT ON COLUMN DATASET_ED_ADMISSION.outtime IS
'ER discharge timestamp / Data-hora de saída do pronto-socorro';
COMMENT ON COLUMN DATASET_ED_ADMISSION.gender IS
'Gender (M/F) / Sexo (M/F)';
COMMENT ON COLUMN DATASET_ED_ADMISSION.race IS
'Race/Ethnicity / Raça ou etnia do paciente';
COMMENT ON COLUMN DATASET_ED_ADMISSION.arrival_transport IS
'Arrival transport mode (ambulance, walk) / Forma de chegada (ambulância, caminhada)';
COMMENT ON COLUMN DATASET_ED_ADMISSION.disposition IS
'Disposition after ER (ADMITTED, HOME, etc.) / Destino após atendimento';
COMMENT ON COLUMN DATASET_ED_ADMISSION.admitted_from_ed IS
'Hospitalized from ER (1=yes, 0=no) / Internado a partir do pronto-socorro';
COMMENT ON COLUMN DATASET_ED_ADMISSION.temperature IS
'Body temperature (Celsius) / Temperatura corporal';
COMMENT ON COLUMN DATASET_ED_ADMISSION.heartrate IS
'Heart rate (bpm) / Frequência cardíaca';
COMMENT ON COLUMN DATASET_ED_ADMISSION.resprate IS
'Respiratory rate (breaths/min) / Frequência respiratória';
COMMENT ON COLUMN DATASET_ED_ADMISSION.o2sat IS
'Oxygen saturation (SpO2) / Saturação de oxigênio';
COMMENT ON COLUMN DATASET_ED_ADMISSION.sbp IS
'Systolic blood pressure / Pressão arterial sistólica';
COMMENT ON COLUMN DATASET_ED_ADMISSION.dbp IS
'Diastolic blood pressure / Pressão arterial diastólica';
COMMENT ON COLUMN DATASET_ED_ADMISSION.n_diagnosis IS
'Number of diagnoses / Número de diagnósticos registrados';
COMMENT ON COLUMN DATASET_ED_ADMISSION.split IS
'Data split flag (train, val, test) / Particionamento dos dados';
5.6 Criar uma view para NL com nomes claros
Esta view, mais amigável, facilitará a LLM do banco de dados a entender mais facilmente os campos.
Vista no schema atual (quando estiver em ADMIN):
CREATE OR REPLACE VIEW MEU_USUARIO.NLU_ED_ADMISSION AS
SELECT
subject_id AS patient_id,
hadm_id AS admission_id,
stay_id AS er_stay_id,
intime AS er_entry_time,
outtime AS er_exit_time,
gender, race, arrival_transport, disposition,
admitted_from_ed AS admitted,
temperature, heartrate, resprate, o2sat, sbp, dbp,
n_diagnosis, split,
EXTRACT(MONTH FROM intime) AS month_num,
EXTRACT(YEAR FROM intime) AS year_num
FROM ADMIN.DATASET_ED_ADMISSION;
E uma view equivalente no schema do usuário (recomendado para consumo pelo app):
-- execute no MESMO schema usado pelo SELECT AI (ex.: MEU_USUARIO)
CREATE OR REPLACE VIEW MEU_USUARIO.NLU_ED_ADMISSION AS
SELECT
subject_id AS patient_id,
hadm_id AS admission_id,
stay_id AS er_stay_id,
intime AS er_entry_time,
outtime AS er_exit_time,
gender, race, arrival_transport, disposition,
admitted_from_ed AS admitted, -- 1/0
temperature, heartrate, resprate, o2sat, sbp, dbp,
n_diagnosis, split,
EXTRACT(MONTH FROM intime) AS month_num,
EXTRACT(YEAR FROM intime) AS year_num
FROM ADMIN.DATASET_ED_ADMISSION;
COMMENT ON TABLE MEU_USUARIO.NLU_ED_ADMISSION IS 'ER admissions with friendly names for NL queries / Tabela para NL';
COMMENT ON COLUMN NLU_ED_ADMISSION.patient_id IS 'Patient ID / ID do paciente';
COMMENT ON COLUMN NLU_ED_ADMISSION.admitted IS 'Hospitalized from ER (1=yes, 0=no) / Internado a partir do PS';
COMMENT ON COLUMN NLU_ED_ADMISSION.er_entry_time IS 'ER entry timestamp / Entrada no PS';
COMMENT ON COLUMN NLU_ED_ADMISSION.month_num IS 'Month number (1..12)';
COMMENT ON COLUMN NLU_ED_ADMISSION.year_num IS 'Year';
Por que? Nomes como patient_id, admitted, month_num facilitam a tradução NL→SQL e evitam ambiguidade.
Valide o SELECT AI, executando os comandos abaixo numa mesma sessão:
Testar direto no SQL
BEGIN
EXEC DBMS_CLOUD_AI.SET_PROFILE('OCI_GENERATIVE_AI_PROFILE');
SELECT AI 'quantos pacientes no hospital' FROM MEU_USUARIO.NLU_ED_ADMISSION;
END;
5.7 Preparar o app Flask
Configure o arquivo config com os dados da Wallet do Autonomous Database:
{
"WALLET_PATH": "/caminho/Wallet_ADB",
"DB_ALIAS": "oradb_high",
"USERNAME": "MEU_USUARIO",
"PASSWORD": "SenhaForte123"
}
Baixar o arquivo requirements.txt. Instalar dependências:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
6. Testar a aplicação
Rodar o app app_select_ai.py:
python app_select_ai.py
# abre http://localhost:5001
Acessando a aplicação
Abra http://localhost:5001 e faça perguntas como:
- “comparar risco de internacao de pacientes”
- “quantos pacientes chegaram no hospital”
- “mostrar pacientes e suas pressoes arteriais acima de 120 80”
Exportar resultados
- PDF: botão “Exportar PDF”.
- Excel: botão “Exportar Excel” (via servidor).
Reference
- Install OCI-CLI
- Download Wallet Database Connection File
- About SELECT AI
- Hospital Risk Admission Prediction with Machine Learning
Acknowledgments
- Author - Cristiano Hoshikawa (Oracle LAD A-Team Solution Engineer)



