- docs/13-v2-perfis-carga.html: mapeamento completo coluna a coluna pra DL_TECH_CMDB_V2 (12 campos) e DL_TECH_VULNERABILIDADE_V3 (23 campos), conferido campo a campo contra um export real (Artefatos/ da V1_Cliente, só linhas AM...) em vez de suposição. - Correções encontradas na conferência: definition.patch_published e definition.vulnerability_published têm prefixo 'definition.' no export real (não estava assim documentado antes); flags booleanos confirmados como texto 'true'/'false' (Tenable) e 'Verdadeiro(a)'/'Falso(a)' (ServiceNow, mesma convenção já usada em SOX/COFRE/TENABLE/SIEM no capítulo 10). - RAW_JSON deliberadamente fora do escopo deste passo — Data Load só carrega colunas mapeadas, não a linha completa; população real de RAW_JSON depende da tabela de staging (próximo item do TASKS.md). - Nav (13 páginas) e pillnav do capítulo 12 atualizados. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1929 lines
105 KiB
HTML
1929 lines
105 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="pt-BR">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>ampmInsights · Passo a passo do banco de dados</title>
|
|
<meta name="description" content="Roteiro seção por seção do script 01_ampminsights_db_setup.sql.">
|
|
<link rel="stylesheet" href="assets/main.css">
|
|
</head>
|
|
<body>
|
|
<div class="layout">
|
|
<aside class="sidebar">
|
|
<div class="brand">
|
|
<span class="oracle">ORACLE</span>
|
|
<span class="name">ampmInsights</span>
|
|
</div>
|
|
<button class="menu-toggle" type="button">Menu ☰</button>
|
|
<div class="kicker">Documentação V2 · AM/PM</div>
|
|
<ul class="nav-list">
|
|
<li><a class="" href="index.html"><span class="step-no">1</span>Visão geral</a></li>
|
|
<li><a class="" href="02-arquitetura.html"><span class="step-no">2</span>Arquitetura</a></li>
|
|
<li><a class="" href="03-pre-requisitos-credenciais.html"><span class="step-no">3</span>Pré-requisitos & credenciais</a></li>
|
|
<li><a class="active" href="04-passo-a-passo-banco.html"><span class="step-no">4</span>Passo a passo: banco de dados</a></li>
|
|
<li><a class="" href="05-passo-a-passo-apex.html"><span class="step-no">5</span>Passo a passo: aplicação APEX</a></li>
|
|
<li><a class="" href="06-validacao-testes.html"><span class="step-no">6</span>Validação & testes</a></li>
|
|
<li><a class="" href="07-seguranca-boas-praticas.html"><span class="step-no">7</span>Segurança & boas práticas</a></li>
|
|
<li><a class="" href="08-glossario-roadmap.html"><span class="step-no">8</span>Glossário & roadmap</a></li>
|
|
<li><a class="" href="09-operacao-observabilidade.html"><span class="step-no">9</span>Operação & observabilidade</a></li>
|
|
<li><a class="" href="10-carga-cmdb-vulnerabilidades.html"><span class="step-no">10</span>Carga: CMDB & Vulnerabilidades</a></li>
|
|
<li><a class="" href="11-v2-evolucao-schema.html"><span class="step-no">11</span>v2.0.0 — Evolução de schema</a></li>
|
|
<li><a class="" href="12-v2-view-procedure.html"><span class="step-no">12</span>v2.0.0 — View & Procedure</a></li>
|
|
<li><a class="" href="13-v2-perfis-carga.html"><span class="step-no">13</span>v2.0.0 — Perfis de carga</a></li>
|
|
</ul>
|
|
<div class="sidebar-footer">
|
|
Vulnerability & Audit AI Insights<br>
|
|
Oracle AI Database 26ai · AI Vector Search<br>
|
|
Versão V1 · ambiente reprodutível do cliente
|
|
</div>
|
|
</aside>
|
|
<main class="content">
|
|
<p class="page-kicker">Script 1 de 2</p>
|
|
<h1>Passo a passo: banco de dados</h1>
|
|
<p class="lede">Guia de execução de sql/01_ampminsights_db_setup.sql, seção por seção, na ordem em que deve ser rodado.</p>
|
|
|
|
<p>Este roteiro acompanha <code>sql/01_ampminsights_db_setup.sql</code> seção por seção. Cada bloco
|
|
abaixo é o código <strong>completo</strong> daquela seção — use o botão <strong>Copiar</strong> e
|
|
cole direto no SQL Worksheet do Database Actions. Rode um bloco de cada vez, na ordem apresentada,
|
|
e confira que não houve erro antes de seguir para o próximo.</p>
|
|
|
|
<div class="callout info">
|
|
<div class="callout-title">Você só preenche valores uma vez</div>
|
|
<p>A partir da Seção 2, todo OCID, região, namespace e nome de bucket é digitado <strong>uma única
|
|
vez</strong>, na tabela de configuração. Os blocos seguintes (credencial, modelo ONNX, SELECT AI)
|
|
leem esses valores automaticamente — você não vai precisar colar o mesmo OCID de novo em nenhum
|
|
outro lugar deste arquivo.</p>
|
|
</div>
|
|
|
|
<h2>Seção 1 · Executar conectado como ADMIN do Autonomous Database</h2>
|
|
<p>Conecte como <strong>ADMIN</strong> do Autonomous Database (Database Actions → SQL,
|
|
logado como ADMIN). Este bloco cria o usuário/schema <code>AMPMINSIGHTS</code>, concede os
|
|
privilégios de AI Vector Search / DBMS_CLOUD / SELECT AI / credenciais / jobs, habilita ORDS e cria a
|
|
regra de rede (ACL) que autoriza o schema a chamar o OCI Generative AI.</p>
|
|
<div class="callout danger">
|
|
<div class="callout-title">Antes de copiar</div>
|
|
<p>Troque <code><SUBSTITUA_POR_UMA_SENHA_FORTE_SUA></code> por uma senha forte escolhida por
|
|
você (mínimo 12 caracteres, com maiúsculas, minúsculas, número e caractere especial) antes de colar
|
|
este bloco no Worksheet.</p>
|
|
</div>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 1 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">-- 1.1) Criar o schema/usuario da aplicacao.
|
|
-- Troque a senha abaixo por uma senha forte escolhida por voce ANTES de
|
|
-- rodar este comando (minimo 12 caracteres, com maiusculas, minusculas,
|
|
-- numero e caractere especial - regra padrao do Oracle Database).
|
|
CREATE USER AMPMINSIGHTS IDENTIFIED BY "<SUBSTITUA_POR_UMA_SENHA_FORTE_SUA>";
|
|
|
|
-- 1.2) Papeis basicos
|
|
GRANT CONNECT TO AMPMINSIGHTS;
|
|
GRANT RESOURCE TO AMPMINSIGHTS;
|
|
ALTER USER AMPMINSIGHTS DEFAULT ROLE CONNECT, RESOURCE;
|
|
|
|
-- 1.3) Habilitar REST (ORDS) para o schema e habilitar Data Sharing
|
|
BEGIN
|
|
ORDS_ADMIN.ENABLE_SCHEMA(
|
|
p_enabled => TRUE,
|
|
p_schema => 'AMPMINSIGHTS',
|
|
p_url_mapping_type => 'BASE_PATH',
|
|
p_url_mapping_pattern => 'ampminsights',
|
|
p_auto_rest_auth => TRUE
|
|
);
|
|
|
|
-- habilita o compartilhamento de dados usado por alguns recursos de AI/Vector
|
|
C##ADP$SERVICE.DBMS_SHARE.ENABLE_SCHEMA(
|
|
SCHEMA_NAME => 'AMPMINSIGHTS',
|
|
ENABLED => TRUE
|
|
);
|
|
COMMIT;
|
|
END;
|
|
/
|
|
|
|
-- 1.4) Quota de armazenamento no tablespace de dados
|
|
ALTER USER AMPMINSIGHTS QUOTA UNLIMITED ON "DATA";
|
|
|
|
-- 1.5) Privilegios usados pela aplicacao (AI Vector Search, DBMS_CLOUD,
|
|
-- SELECT AI, mineracao/embeddings, credenciais e jobs agendados)
|
|
GRANT EXECUTE ON dbms_vector_chain TO AMPMINSIGHTS;
|
|
GRANT EXECUTE ON dbms_cloud TO AMPMINSIGHTS;
|
|
GRANT EXECUTE ON dbms_cloud_ai TO AMPMINSIGHTS;
|
|
GRANT CONNECT TO AMPMINSIGHTS;
|
|
GRANT RESOURCE TO AMPMINSIGHTS;
|
|
GRANT CREATE MINING MODEL TO AMPMINSIGHTS;
|
|
GRANT CREATE CREDENTIAL TO AMPMINSIGHTS;
|
|
GRANT CREATE JOB TO AMPMINSIGHTS;
|
|
|
|
-- 1.6) Regras de rede (ACL) para o schema poder chamar o endpoint do OCI
|
|
-- Generative AI usado neste script (regiao us-chicago-1 por padrao - o
|
|
-- mesmo valor que vai para o parametro GENAI_REGION da SECAO 2, que
|
|
-- ainda nao existe neste ponto do script, por isso o host aqui e
|
|
-- digitado direto). Nem toda tenancy alcanca us-chicago-1 (ex.: algumas
|
|
-- tenancies com escopo regional restrito, como America Latina, podem
|
|
-- so alcancar sa-saopaulo-1) - se for o seu caso, troque o host abaixo
|
|
-- pela regiao que a sua tenancy alcanca, E use o mesmo valor no
|
|
-- parametro GENAI_REGION da SECAO 2 (repita este bloco para cada host
|
|
-- adicional que for necessario).
|
|
BEGIN
|
|
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
|
|
host => 'inference.generativeai.us-chicago-1.oci.oraclecloud.com',
|
|
lower_port => 443,
|
|
upper_port => 443,
|
|
ace => xs$ace_type(
|
|
privilege_list => xs$name_list('connect'),
|
|
principal_name => 'AMPMINSIGHTS',
|
|
principal_type => xs_acl.ptype_db
|
|
)
|
|
);
|
|
|
|
DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
|
|
host => 'inference.generativeai.us-chicago-1.oci.oraclecloud.com',
|
|
ace => xs$ace_type(
|
|
privilege_list => xs$name_list('resolve'),
|
|
principal_name => 'AMPMINSIGHTS',
|
|
principal_type => xs_acl.ptype_db
|
|
)
|
|
);
|
|
END;
|
|
/
|
|
|
|
-- 1.7) Conferir as regras de rede criadas
|
|
SELECT host, lower_port, upper_port, principal, privilege
|
|
FROM dba_host_aces
|
|
WHERE principal = 'AMPMINSIGHTS';
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
-- A partir daqui, conecte-se como o usuario AMPMINSIGHTS (nao mais como ADMIN)
|
|
--------------------------------------------------------------------------------
|
|
--
|
|
-- VALIDACAO (rode antes de continuar - erro mais comum deste script):
|
|
SELECT USER FROM DUAL;
|
|
-- Tem que retornar AMPMINSIGHTS. Se retornar ADMIN, voce ainda nao trocou de
|
|
-- usuario/sessao - troque agora, senao a SECAO 2 (e tudo depois) vai falhar
|
|
-- com ORA-00942 (table or view "ADMIN"."TB_26AI_TECH_PARAMS" does not exist).
|
|
-- No Database Actions/SQL Developer Web, trocar o "schema" num seletor do
|
|
-- Worksheet NAO basta - precisa fazer login de novo com o usuario/senha do
|
|
-- AMPMINSIGHTS.</code></pre>
|
|
</div>
|
|
<h2>Seção 2 · Tabela de configuracao (preencha os valores UMA UNICA VEZ aqui)</h2>
|
|
<p>Agora conecte como o usuário <strong>AMPMINSIGHTS</strong> que você acabou de criar (não mais
|
|
como ADMIN). Este bloco cria a <strong>tabela de configuração</strong> e insere, de uma vez, os 8
|
|
valores que os próximos blocos vão precisar. Veja em
|
|
<a href="03-pre-requisitos-credenciais.html">Pré-requisitos & credenciais</a> onde obter cada um.</p>
|
|
<div class="callout danger">
|
|
<div class="callout-title">Antes de copiar</div>
|
|
<p>Substitua os 8 marcadores <code><SUBSTITUA_...></code> pelos valores reais do seu ambiente
|
|
antes de colar. Depois de rodar, confira com o <code>SELECT</code> no final do bloco que nenhuma
|
|
linha ainda mostra um marcador.</p>
|
|
</div>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 2 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">--
|
|
-- Esta e a UNICA seção onde voce vai colar OCIDs, regiao, namespace e bucket.
|
|
-- Todos os blocos seguintes (credencial OCI, modelo ONNX, SELECT AI, e o job
|
|
-- de geracao de insights criado pela propria aplicacao APEX) leem os valores
|
|
-- DAQUI automaticamente - voce nao precisa colar o mesmo OCID de novo em
|
|
-- nenhum outro lugar deste arquivo nem do aplicativo APEX.
|
|
--
|
|
-- Onde obter cada valor: ver docs/03-pre-requisitos-credenciais.html.
|
|
--
|
|
CREATE TABLE "TB_26AI_TECH_PARAMS"
|
|
( "PARAM_NAME" VARCHAR2(100 CHAR) NOT NULL ENABLE,
|
|
"PARAM_VALUE" VARCHAR2(1000 CHAR) NOT NULL ENABLE,
|
|
"DESCRIPTION" VARCHAR2(4000),
|
|
CONSTRAINT "TB_26AI_TECH_PARAMS_PK" PRIMARY KEY ("PARAM_NAME")
|
|
USING INDEX ENABLE
|
|
);
|
|
|
|
COMMENT ON TABLE "TB_26AI_TECH_PARAMS" IS 'Tabela de configuracao central da aplicacao ampmInsights - preencher uma unica vez.';
|
|
|
|
-- Preencha os 8 marcadores abaixo e rode o bloco UMA VEZ.
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('EMBEDDING_CREDENTIAL', 'OCI_CRED',
|
|
'Nome da credencial que sera criada na SECAO 3. Nao precisa alterar este valor.');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('EMBEDDING_COMPARTMENT', '<SUBSTITUA_PELO_OCID_DO_COMPARTIMENTO_DO_BANCO>',
|
|
'OCID do compartimento OCI onde o Autonomous Database foi criado.');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('OCI_TENANCY_OCID', '<SUBSTITUA_PELO_OCID_DO_TENANCY>',
|
|
'OCID do tenancy OCI (campo "tenancy" da API key).');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('OCI_USER_OCID', '<SUBSTITUA_PELO_OCID_DO_USUARIO_OCI>',
|
|
'OCID do usuario OCI dono da API key (campo "user" da API key).');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('OCI_FINGERPRINT', '<SUBSTITUA_PELA_FINGERPRINT_DA_API_KEY>',
|
|
'Fingerprint da API key (campo "fingerprint" da API key).');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('OCI_REGION', '<SUBSTITUA_PELA_SUA_REGIAO>',
|
|
'Regiao OCI do seu tenancy, ex.: sa-saopaulo-1 (campo "region" da API key).');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('OS_NAMESPACE', '<SUBSTITUA_PELO_SEU_NAMESPACE_DE_OBJECT_STORAGE>',
|
|
'Namespace do Object Storage do seu tenancy (Console OCI > Storage > Buckets > "Namespace").');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('OS_BUCKET', '<SUBSTITUA_PELO_NOME_DO_BUCKET_QUE_VOCE_VAI_CRIAR>',
|
|
'Nome do bucket de Object Storage onde o modelo ONNX sera armazenado (ver SECAO 4).');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('AI_LOG_RETENTION_DAYS', '90',
|
|
'Dias de retencao do log de chamadas de IA/embeddings (TB_26AI_TECH_LOG) - ver docs/09-operacao-observabilidade.html para a query de purga.');
|
|
|
|
INSERT INTO TB_26AI_TECH_PARAMS (PARAM_NAME, PARAM_VALUE, DESCRIPTION) VALUES
|
|
('GENAI_REGION', 'us-chicago-1',
|
|
'Regiao do OCI Generative AI usada pelo RAG/insights/embeddings (SECAO 5+). Pode ser diferente da OCI_REGION (que e a regiao "de casa" do seu tenancy/bucket) - o Generative AI so roda em regioes especificas. Se a sua tenancy nao alcancar us-chicago-1 (comum em tenancies com escopo regional restrito, ex. America Latina), troque para uma regiao que a sua tenancy alcance (ex. sa-saopaulo-1) E repita a ACL da SECAO 1.6 para o novo host - confirme antes com "oci generative-ai model-collection list-models" ou o Console OCI que o modelo usado (meta.llama-4-maverick-17b-128e-instruct-fp8) ainda esta ativo para uso on-demand na regiao escolhida, ja que a disponibilidade de modelos varia por regiao e muda com o tempo.');
|
|
|
|
COMMIT;
|
|
|
|
-- Confira: nenhuma linha abaixo deve ainda mostrar um valor "<SUBSTITUA...>"
|
|
-- antes de voce seguir para a SECAO 3.
|
|
SELECT param_name, param_value, description FROM TB_26AI_TECH_PARAMS ORDER BY param_name;
|
|
|
|
-- VALIDACAO EXTRA: confere que cada OCID e do TIPO certo, nao so que foi
|
|
-- preenchido. Ja aconteceu de EMBEDDING_COMPARTMENT ser preenchido com o
|
|
-- OCID do proprio Autonomous Database (ocid1.autonomousdatabase...) em vez
|
|
-- do compartimento (ocid1.compartment...) - o valor "parece" um OCID valido
|
|
-- e passa despercebido, mas quebra silenciosamente mais tarde (Generative AI
|
|
-- retorna ORA-20404 "Object not found", dificil de associar a este campo).
|
|
SELECT param_name, param_value,
|
|
CASE
|
|
WHEN param_name = 'EMBEDDING_COMPARTMENT' AND param_value NOT LIKE 'ocid1.compartment.%'
|
|
THEN 'ERRO: deveria comecar com ocid1.compartment. - confira se nao colou o OCID do banco/Autonomous Database por engano'
|
|
WHEN param_name = 'OCI_TENANCY_OCID' AND param_value NOT LIKE 'ocid1.tenancy.%'
|
|
THEN 'ERRO: deveria comecar com ocid1.tenancy.'
|
|
WHEN param_name = 'OCI_USER_OCID' AND param_value NOT LIKE 'ocid1.user.%'
|
|
THEN 'ERRO: deveria comecar com ocid1.user.'
|
|
ELSE 'OK'
|
|
END AS validacao
|
|
FROM TB_26AI_TECH_PARAMS
|
|
WHERE param_name IN ('EMBEDDING_COMPARTMENT', 'OCI_TENANCY_OCID', 'OCI_USER_OCID');</code></pre>
|
|
</div>
|
|
<h2>Seção 3 · Credencial de acesso a OCI (Generative AI + Object Storage)</h2>
|
|
<p>Cria a credencial <code>OCI_CRED</code>, usada pelo banco para chamar o OCI Generative AI e o
|
|
Object Storage. O bloco já lê tenancy/usuário/compartimento/fingerprint da tabela de configuração da
|
|
Seção 2 — o único valor que você ainda precisa colar aqui é o conteúdo da <strong>chave privada</strong>
|
|
(.pem), porque ela nunca é guardada em texto puro em nenhuma tabela.</p>
|
|
<div class="callout danger">
|
|
<div class="callout-title">Antes de copiar</div>
|
|
<p>Substitua o marcador da chave privada pelo conteúdo completo do seu arquivo <code>.pem</code>
|
|
(incluindo as linhas <code>BEGIN/END PRIVATE KEY</code>). Depois de confirmar que a credencial foi
|
|
criada (consulta no final do bloco), você pode apagar o arquivo <code>.pem</code> do seu computador
|
|
com segurança.</p>
|
|
</div>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 3 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">--
|
|
-- Esta credencial (OCI_CRED) e o que permite o banco chamar o OCI Generative
|
|
-- AI (para gerar embeddings e texto/insights) e o OCI Object Storage (para
|
|
-- carregar o modelo ONNX). Ela usa autenticacao "API Signing Key" da OCI.
|
|
-- O bloco abaixo LE tenancy/usuario/compartimento/fingerprint automaticamente
|
|
-- da tabela de configuracao da SECAO 2 - voce so precisa colar a CHAVE
|
|
-- PRIVADA aqui (ela nao e guardada em nenhuma tabela; o proprio banco a
|
|
-- guarda de forma criptografada dentro da credencial).
|
|
--
|
|
-- PRE-REQUISITO (feito uma unica vez, no Console OCI, fora do banco):
|
|
-- Ver o passo a passo completo em docs/03-pre-requisitos-credenciais.html.
|
|
-- Resumo: Console OCI > usuario > User settings > API keys > Add API key >
|
|
-- Generate API key pair > Download private key > Add. Os 4 valores exibidos
|
|
-- (user, fingerprint, tenancy, region) vao para a SECAO 2 acima; a chave
|
|
-- privada baixada (.pem) vai direto no bloco abaixo.
|
|
--
|
|
-- IMPORTANTE (seguranca):
|
|
-- - A chave privada .pem equivale a uma senha: nao envie por e-mail/chat,
|
|
-- nao suba para repositorio de codigo, restrinja a politica IAM ao
|
|
-- minimo necessario e rotacione periodicamente.
|
|
-- - Depois de rodar este bloco, o arquivo .pem local pode ser removido
|
|
-- com seguranca - o banco guarda a chave de forma criptografada e ela
|
|
-- nao aparece em nenhuma consulta.
|
|
--
|
|
DECLARE
|
|
v_tenancy TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
v_user TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
v_compartment TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
v_fingerprint TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
jo JSON_OBJECT_T;
|
|
BEGIN
|
|
SELECT param_value INTO v_tenancy FROM TB_26AI_TECH_PARAMS WHERE param_name = 'OCI_TENANCY_OCID';
|
|
SELECT param_value INTO v_user FROM TB_26AI_TECH_PARAMS WHERE param_name = 'OCI_USER_OCID';
|
|
SELECT param_value INTO v_compartment FROM TB_26AI_TECH_PARAMS WHERE param_name = 'EMBEDDING_COMPARTMENT';
|
|
SELECT param_value INTO v_fingerprint FROM TB_26AI_TECH_PARAMS WHERE param_name = 'OCI_FINGERPRINT';
|
|
|
|
jo := JSON_OBJECT_T();
|
|
jo.put('user_ocid', v_user);
|
|
jo.put('tenancy_ocid', v_tenancy);
|
|
jo.put('compartment_ocid', v_compartment);
|
|
-- Cole aqui o conteudo COMPLETO do arquivo .pem baixado (incluindo as
|
|
-- linhas -----BEGIN PRIVATE KEY----- e -----END PRIVATE KEY-----, com as
|
|
-- quebras de linha originais). Este e o UNICO lugar de todo o pacote onde
|
|
-- a chave privada e digitada.
|
|
jo.put('private_key',
|
|
'<SUBSTITUA_PELO_CONTEUDO_COMPLETO_DA_CHAVE_PRIVADA_PEM_INCLUINDO_AS_LINHAS_BEGIN_E_END_E_AS_QUEBRAS_DE_LINHA_ORIGINAIS>');
|
|
jo.put('fingerprint', v_fingerprint);
|
|
|
|
DBMS_VECTOR_CHAIN.CREATE_CREDENTIAL(
|
|
credential_name => 'OCI_CRED',
|
|
params => JSON(jo.to_string));
|
|
END;
|
|
/
|
|
|
|
-- Conferir que a credencial foi criada (nao mostra a chave privada)
|
|
SELECT credential_name, username, comments
|
|
FROM user_credentials
|
|
WHERE credential_name = 'OCI_CRED';
|
|
|
|
-- VALIDACAO/LEMBRETE: esta credencial grava tenancy/user/compartment por
|
|
-- dentro, NO MOMENTO em que e criada. Se voce corrigir qualquer valor da
|
|
-- SECAO 2 (principalmente EMBEDDING_COMPARTMENT) DEPOIS de ja ter rodado
|
|
-- este bloco, a credencial antiga continua com o valor velho - corrigir a
|
|
-- tabela sozinho NAO conserta. Nesse caso, rode:
|
|
-- BEGIN DBMS_VECTOR_CHAIN.DROP_CREDENTIAL(credential_name => 'OCI_CRED'); END;
|
|
-- /
|
|
-- e este bloco de novo, nesta ordem.</code></pre>
|
|
</div>
|
|
<h2>Seção 4 · Modelo de embeddings ONNX</h2>
|
|
<p>Opcional — só necessária se você for usar embeddings de imagem/texto combinados (CLIP). O
|
|
fluxo padrão de texto do ampmInsights (embeddings de relatórios, RAG) não depende desta seção e pode
|
|
ser pulado.</p>
|
|
<p>O passo 4.1 é sobre <strong>obter um arquivo <code>.onnx</code> corretamente convertido</strong>
|
|
(veja a explicação logo abaixo do bloco de código sobre por que isso importa). Depois de ter esse
|
|
arquivo, criar seu bucket e subir o arquivo (passo 4.2, via Console OCI ou OCI CLI), o bloco de SQL
|
|
(passo 4.3) monta a URL sozinho a partir da tabela de configuração e carrega o modelo no banco.</p>
|
|
<div class="callout danger">
|
|
<div class="callout-title">Não baixe um .onnx "pronto" de qualquer lugar</div>
|
|
<p>Um export cru feito direto do PyTorch/HuggingFace normalmente falha no banco com
|
|
<code>ORA-54426</code>. A explicação completa do porquê, e o passo a passo pra gerar um arquivo
|
|
que funciona, estão logo após o bloco de código abaixo, em
|
|
<a href="#converter-onnx">Como converter seu próprio modelo ONNX</a>.</p>
|
|
</div>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 4 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">--
|
|
-- Esta secao carrega um modelo de embeddings do tipo imagem/texto (ONNX) para
|
|
-- casos de uso que combinem imagem e texto. O fluxo principal de texto do
|
|
-- ampmInsights (embeddings de relatorios, RAG, etc.) usa o modelo hospedado no
|
|
-- OCI Generative AI (cohere.embed-v4.0, chamado via DBMS_VECTOR_CHAIN na
|
|
-- SECAO 5) e NAO depende desta secao. Pule a SECAO 4 se voce so precisa do
|
|
-- fluxo de texto (a maioria dos casos).
|
|
--
|
|
-- ATENCAO - leia antes de rodar (evita o erro ORA-54426):
|
|
-- Um export .onnx "cru", feito direto do PyTorch/HuggingFace
|
|
-- (torch.onnx.export sem passar pelo pipeline da Oracle), normalmente sai
|
|
-- com DOIS eixos dinamicos nao vinculados no tensor de entrada (batch E
|
|
-- comprimento de sequencia). O ONNX Runtime embutido no Oracle AI Database
|
|
-- nao aceita esse formato e falha com ORA-54426 ao carregar o modelo.
|
|
-- O jeito certo de gerar o arquivo e usando o pacote OML4Py (classe
|
|
-- oml.utils.ONNXPipeline) da propria Oracle: ela tem um "template"
|
|
-- pre-configurado para o openai/clip-vit-large-patch14 que fixa o
|
|
-- comprimento de sequencia em 77 E embute o tokenizer dentro do proprio
|
|
-- grafo ONNX (via onnxruntime-extensions) - o modelo final fica com UM so
|
|
-- eixo dinamico (batch_size) e recebe texto puro como entrada. Passo a
|
|
-- passo completo (via Docker, ja que nao existe cliente OML4Py para macOS)
|
|
-- logo abaixo deste bloco, em "Como converter seu proprio modelo ONNX".
|
|
--
|
|
-- 4.1) Obtenha um arquivo CLIP_VIT_LARGE_PATCH14_TXT.onnx corretamente
|
|
-- convertido - siga o passo a passo logo abaixo. Nao existe hoje um
|
|
-- link publico "pronto para uso" para este arquivo: qualquer .onnx que
|
|
-- voce encontre por ai (incluindo exports antigos de PoCs) pode ser um
|
|
-- export cru e reproduzir o ORA-54426 descrito acima. Referencia oficial
|
|
-- da Oracle para o processo de conversao:
|
|
-- https://docs.oracle.com/en/database/oracle/oracle-database/26/vecse/convert-pretrained-models-onnx-model-end-end-instructions.html
|
|
--
|
|
-- 4.2) Crie um bucket no SEU Object Storage (o nome deve ser o mesmo que voce
|
|
-- colocou em OS_BUCKET na SECAO 2) e faca upload do arquivo convertido:
|
|
-- Console OCI > Storage > Buckets > Create Bucket
|
|
-- (ou via OCI CLI: oci os bucket create --name <valor-de-OS_BUCKET> --compartment-id <OCID-do-compartimento>)
|
|
-- Console OCI > abra o bucket > Upload > selecione o CLIP_VIT_LARGE_PATCH14_TXT.onnx
|
|
-- (ou via OCI CLI: oci os object put -bn <valor-de-OS_BUCKET> --file CLIP_VIT_LARGE_PATCH14_TXT.onnx)
|
|
--
|
|
-- 4.3) Carregue o modelo no banco. O bloco abaixo monta a URI sozinho, usando
|
|
-- OS_REGION/OS_NAMESPACE/OS_BUCKET da tabela de configuracao (SECAO 2) -
|
|
-- voce nao precisa editar nenhuma URL na mao.
|
|
--
|
|
DECLARE
|
|
v_region TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
v_namespace TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
v_bucket TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
v_uri VARCHAR2(1000);
|
|
BEGIN
|
|
SELECT param_value INTO v_region FROM TB_26AI_TECH_PARAMS WHERE param_name = 'OCI_REGION';
|
|
SELECT param_value INTO v_namespace FROM TB_26AI_TECH_PARAMS WHERE param_name = 'OS_NAMESPACE';
|
|
SELECT param_value INTO v_bucket FROM TB_26AI_TECH_PARAMS WHERE param_name = 'OS_BUCKET';
|
|
|
|
v_uri := 'https://objectstorage.' || v_region || '.oraclecloud.com/n/' || v_namespace || '/b/' || v_bucket || '/o/CLIP_VIT_LARGE_PATCH14_TXT.onnx';
|
|
|
|
DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD(
|
|
model_name => 'CLIP_VIT_LARGE_PATCH14_TXT',
|
|
credential => 'OCI_CRED',
|
|
uri => v_uri,
|
|
metadata => JSON('{
|
|
"function": "embedding",
|
|
"embeddingOutput": "embedding",
|
|
"input": {"input": ["DATA"]}
|
|
}')
|
|
);
|
|
END;
|
|
/
|
|
|
|
SELECT model_name, algorithm, mining_function
|
|
FROM user_mining_models
|
|
WHERE model_name = 'CLIP_VIT_LARGE_PATCH14_TXT';</code></pre>
|
|
</div>
|
|
|
|
<h2 id="converter-onnx">Como converter seu próprio modelo ONNX (e por que isso é necessário)</h2>
|
|
<p>Esta seção explica um problema que não é óbvio na primeira vez que alguém tenta carregar um
|
|
modelo ONNX de terceiros no Oracle AI Database, e mostra como gerar um arquivo que funciona.
|
|
Vale a leitura mesmo se você só pretende usar embeddings de texto (Seção 5), porque o mesmo
|
|
princípio vale pra qualquer modelo ONNX que você queira carregar no banco no futuro.</p>
|
|
|
|
<h3>O sintoma: ORA-54426</h3>
|
|
<p>Ao rodar <code>DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD</code> com um arquivo <code>.onnx</code> baixado
|
|
de um repositório qualquer (HuggingFace, GitHub, um export feito por outra pessoa), é comum o banco
|
|
recusar o modelo com um erro do tipo <code>ORA-54426</code> relacionado a eixo dinâmico não suportado
|
|
no tensor de entrada, mesmo que o arquivo abra normalmente em qualquer visualizador ONNX e pareça
|
|
válido.</p>
|
|
|
|
<h3>Por que acontece</h3>
|
|
<p>Um export "cru", feito chamando <code>torch.onnx.export</code> (ou o exportador equivalente do
|
|
HuggingFace <code>optimum</code>) diretamente, sem nenhum tratamento adicional, normalmente produz um
|
|
tensor de entrada com <strong>dois eixos dinâmicos não vinculados</strong>: o tamanho do lote
|
|
(<code>batch_size</code>) <em>e</em> o comprimento da sequência de tokens (<code>sequence_length</code>).
|
|
O mecanismo de ONNX Runtime embutido no Oracle AI Database exige que, no máximo, um eixo do tensor de
|
|
entrada seja dinâmico — os demais precisam ter um tamanho fixo conhecido em tempo de carga do modelo.
|
|
Um arquivo com dois eixos livres é rejeitado antes mesmo de rodar qualquer inferência.</p>
|
|
|
|
<h3>A ferramenta certa: OML4Py <code>ONNXPipeline</code></h3>
|
|
<p>A Oracle disponibiliza um pacote Python próprio, <strong>OML4Py</strong>, com uma classe utilitária
|
|
(<code>oml.utils.ONNXPipeline</code>) que já sabe converter uma lista de modelos populares do
|
|
HuggingFace (incluindo o <code>openai/clip-vit-large-patch14</code> usado nesta seção) no formato que o
|
|
banco espera. Para esse modelo especificamente, o pipeline usa um template chamado
|
|
<code>multimodal_clip</code> que faz duas coisas ao mesmo tempo:</p>
|
|
<ul>
|
|
<li>fixa o comprimento de sequência em 77 tokens (o limite do CLIP), eliminando o segundo eixo
|
|
dinâmico;</li>
|
|
<li>embute o tokenizer do CLIP <em>dentro do próprio grafo ONNX</em> (usando operadores customizados
|
|
da biblioteca <code>onnxruntime-extensions</code>, como o nó <code>CLIPTokenizer</code>), de forma que
|
|
o modelo final recebe <strong>texto puro (string)</strong> como entrada em vez de IDs de token já
|
|
tokenizados. Sobra só um eixo dinâmico — o tamanho do lote.</li>
|
|
</ul>
|
|
<p>Resultado prático: o <code>ONNXPipeline</code> não gera um, mas <strong>dois</strong> arquivos a
|
|
partir do mesmo modelo — um com sufixo <code>_txt</code> (a torre de texto, que é a que interessa pra
|
|
embeddings de relatórios/RAG) e um com sufixo <code>_img</code> (a torre de imagem). Use o <code>_txt</code>
|
|
no <code>LOAD_ONNX_MODEL_CLOUD</code> da Seção 4.3 acima.</p>
|
|
|
|
<div class="callout info">
|
|
<div class="callout-title">Não existe cliente OML4Py para macOS</div>
|
|
<p>O pacote OML4Py só tem build oficial para Linux. Em uma máquina macOS (como a usada neste
|
|
roteiro), a conversão precisa rodar dentro de um container Docker Linux
|
|
(<code>--platform=linux/amd64</code>). Os passos abaixo já contemplam isso.</p>
|
|
</div>
|
|
|
|
<h3>Passo a passo (via Docker)</h3>
|
|
<p>Pré-requisitos: Docker Desktop instalado, o wheel do cliente OML4Py baixado do site da Oracle
|
|
(variante Linux x86_64) e pelo menos ~15 GB de espaço em disco livres e ~10 GB de RAM alocados ao
|
|
Docker Desktop — ver aviso sobre recursos logo abaixo do passo a passo.</p>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">1 — criar a pasta de trabalho e o requirements.txt</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-bash">mkdir -p ~/oracle-onnx-convert/{tmp,hf-cache,pip-cache,out}
|
|
cd ~/oracle-onnx-convert
|
|
|
|
cat > requirements.txt <<'EOF'
|
|
--extra-index-url https://download.pytorch.org/whl/cpu
|
|
pandas==2.2.3
|
|
setuptools==80.8.0
|
|
scipy==1.14.1
|
|
matplotlib==3.10.0
|
|
oracledb==3.3.0
|
|
scikit-learn==1.6.1
|
|
numpy==2.1.0
|
|
pyarrow==19.0.0
|
|
onnxruntime==1.20.0
|
|
onnxruntime-extensions==0.14.0
|
|
onnx==1.18.0
|
|
torch==2.9.0
|
|
transformers==4.56.1
|
|
sentencepiece==0.2.1
|
|
EOF
|
|
|
|
# copie o .whl do OML4Py (baixado do site da Oracle) para esta pasta, ex.:
|
|
# oml-2.1.1-cp313-cp313-linux_x86_64.whl</code></pre>
|
|
</div>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">2 — subir o container com os mounts corretos</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-bash">cd ~/oracle-onnx-convert
|
|
docker run -d --platform=linux/amd64 --name onnx-convert \
|
|
-v "$PWD":/work \
|
|
-v "$PWD/tmp":/tmp \
|
|
-v "$PWD/hf-cache":/root/.cache/huggingface \
|
|
-v "$PWD/pip-cache":/root/.cache/pip \
|
|
-e TMPDIR=/tmp \
|
|
-w /work python:3.13-slim sleep infinity</code></pre>
|
|
</div>
|
|
<div class="callout warning">
|
|
<div class="callout-title">Por que montar /tmp e os caches</div>
|
|
<p>Em ambientes com "Enhanced Container Isolation" (comum em Docker Desktop com política
|
|
corporativa), o <code>/tmp</code> interno do container pode vir montado como somente-leitura, e a
|
|
etapa de quantização do <code>onnxruntime</code> precisa escrever arquivos temporários — sem esse
|
|
mount o processo falha com <code>Read-only file system</code>. Montar <code>hf-cache</code> e
|
|
<code>pip-cache</code> no host evita perder o download do modelo (~1,7 GB) e os pacotes Python
|
|
caso precise recriar o container.</p>
|
|
</div>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">3 — instalar dependências dentro do container</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-bash">docker exec onnx-convert bash -c "apt-get update -qq && apt-get install -y -qq build-essential"
|
|
docker exec onnx-convert bash -c "pip install --upgrade pip -q && pip install -r requirements.txt -q"
|
|
docker exec onnx-convert bash -c "pip install oml-*.whl -q"</code></pre>
|
|
</div>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">4 — rodar a conversão</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-bash">docker exec onnx-convert python3 -c "
|
|
from oml.utils import ONNXPipeline
|
|
import os
|
|
pipeline = ONNXPipeline(model_name='openai/clip-vit-large-patch14')
|
|
os.makedirs('/work/out', exist_ok=True)
|
|
pipeline.export2file('CLIP_VIT_LARGE_PATCH14', output_dir='/work/out')
|
|
print('EXPORT_DONE')
|
|
"</code></pre>
|
|
</div>
|
|
<p>Ao final, <code>~/oracle-onnx-convert/out/</code> vai ter dois arquivos:
|
|
<code>CLIP_VIT_LARGE_PATCH14_txt.onnx</code> (o que interessa) e
|
|
<code>CLIP_VIT_LARGE_PATCH14_img.onnx</code>.</p>
|
|
|
|
<div class="callout danger">
|
|
<div class="callout-title">Recursos: disco e memória</div>
|
|
<p>Essa conversão baixa o modelo completo (~1,7 GB), instala <code>torch</code>
|
|
(~800 MB) e faz tracing + quantização, que consomem RAM bem acima do tamanho do modelo em disco.
|
|
Rodando com pouco espaço livre, o Docker Desktop pode travar por completo; rodando com pouca
|
|
memória alocada ao Docker (o padrão costuma reservar ~metade da RAM da máquina), o processo é
|
|
morto pelo kernel com <code>exit code 137</code> (OOM kill) no meio do export. Antes de começar,
|
|
garanta pelo menos ~15 GB livres em disco e aumente a memória do Docker Desktop (Settings >
|
|
Resources > Memory) para 10–12 GB se sua máquina tiver 16 GB de RAM ou mais.</p>
|
|
</div>
|
|
|
|
<h3>Verificar o resultado antes de subir pro bucket</h3>
|
|
<p>Com o pacote <code>onnx</code> (<code>pip install onnx</code>, roda em qualquer SO, inclusive fora
|
|
do container) dá pra inspecionar o grafo gerado e confirmar que o eixo duplicado sumiu, sem precisar
|
|
de acesso ao banco:</p>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">verificação local</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-python">import onnx
|
|
m = onnx.load('CLIP_VIT_LARGE_PATCH14_txt.onnx')
|
|
for inp in m.graph.input:
|
|
dims = [d.dim_param or d.dim_value for d in inp.type.tensor_type.shape.dim]
|
|
print(inp.name, dims)
|
|
# esperado: input ['batch_size'] -> um so eixo dinamico, tipo string
|
|
# (elem_type 8 = STRING; o primeiro node do grafo deve ser um CLIPTokenizer)</code></pre>
|
|
</div>
|
|
<p>Se a saída mostrar <strong>dois</strong> eixos no input (ex.: <code>['batch_size',
|
|
'sequence_length']</code>), o arquivo ainda é um export cru e vai reproduzir o ORA-54426 — volte ao
|
|
passo 4 do Docker. Com um só eixo confirmado, siga para a Seção 4.2/4.3 acima (upload no bucket e
|
|
<code>LOAD_ONNX_MODEL_CLOUD</code>). Se o modelo já estava carregado no banco com o nome
|
|
<code>CLIP_VIT_LARGE_PATCH14_TXT</code>, rode <code>DBMS_VECTOR.DROP_ONNX_MODEL</code> antes de
|
|
carregar a versão nova (o mesmo nome de modelo não pode ser recarregado por cima).</p>
|
|
|
|
<h2>Seção 5 · Testes rapidos de sanidade (embedding, geracao de texto, SELECT AI)</h2>
|
|
<p>Três testes rápidos para confirmar que a credencial e a rede estão corretas antes de seguir
|
|
para as tabelas e o PL/SQL da aplicação: um teste de embedding, um teste de geração de texto e a
|
|
criação de um profile de SELECT AI (que já lê região e compartimento da tabela de configuração).</p>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 5 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">-- Rode os 3 blocos abaixo para confirmar que a credencial e a rede estao OK
|
|
-- antes de seguir para as tabelas e o PL/SQL da aplicacao.
|
|
|
|
-- 5.1) Teste de embedding (Cohere, via OCI Generative AI). A URL usa a
|
|
-- regiao configurada em GENAI_REGION (SECAO 2), nao um valor fixo.
|
|
SELECT VECTOR_SERIALIZE(
|
|
DBMS_VECTOR_CHAIN.UTL_TO_EMBEDDING(
|
|
TO_CLOB('Teste simples para gerar um embedding.'),
|
|
JSON('{
|
|
"provider": "ocigenai",
|
|
"credential_name": "OCI_CRED",
|
|
"url": "https://inference.generativeai.' || (SELECT param_value FROM TB_26AI_TECH_PARAMS WHERE param_name = 'GENAI_REGION') || '.oci.oraclecloud.com/20231130/actions/embedText",
|
|
"model": "cohere.embed-v4.0"
|
|
}')
|
|
)
|
|
RETURNING CLOB
|
|
) AS embedding
|
|
FROM dual;
|
|
|
|
-- 5.2) Teste de geracao de texto (Llama 4, via OCI Generative AI). Mesma
|
|
-- logica: a URL usa a regiao configurada em GENAI_REGION (SECAO 2).
|
|
SELECT DBMS_VECTOR_CHAIN.UTL_TO_GENERATE_TEXT(
|
|
TO_CLOB('Responda somente com a palavra: sucesso'),
|
|
JSON('{
|
|
"provider": "ocigenai",
|
|
"credential_name": "OCI_CRED",
|
|
"url": "https://inference.generativeai.' || (SELECT param_value FROM TB_26AI_TECH_PARAMS WHERE param_name = 'GENAI_REGION') || '.oci.oraclecloud.com/20231130/actions/chat",
|
|
"model": "meta.llama-4-maverick-17b-128e-instruct-fp8",
|
|
"chatRequest": {
|
|
"temperature": 0.1,
|
|
"topK": 1,
|
|
"maxTokens": 50
|
|
}
|
|
}')
|
|
) AS resposta
|
|
FROM dual;
|
|
|
|
-- 5.3) Teste de SELECT AI (perguntas em linguagem natural sobre as views/
|
|
-- tabelas do schema). O bloco abaixo le EMBEDDING_COMPARTMENT e
|
|
-- GENAI_REGION da tabela de configuracao (SECAO 2). As tabelas/view
|
|
-- referenciadas abaixo sao criadas na SECAO 6 - rode este bloco depois
|
|
-- de criar V_26AI_TECH e TB_26AI_TECH_CMDB.
|
|
--
|
|
-- IMPORTANTE: a regiao do OCI Generative AI abaixo vem do parametro
|
|
-- GENAI_REGION - NAO troque pelo valor de OCI_REGION da tabela de
|
|
-- configuracao (sao coisas diferentes de proposito, ver comentario da
|
|
-- SECAO 2). O Generative AI so roda em algumas regioes especificas da
|
|
-- OCI (nem toda regiao onde voce tem tenancy/bucket tem o servico);
|
|
-- usar a regiao "de casa" do tenancy aqui falha com ORA-20404 (Object
|
|
-- not found), porque o DBMS_CLOUD_AI nao consegue montar o endpoint
|
|
-- para uma regiao sem o servico.
|
|
DECLARE
|
|
v_compartment TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
v_genai_region TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
BEGIN
|
|
SELECT param_value INTO v_compartment FROM TB_26AI_TECH_PARAMS WHERE param_name = 'EMBEDDING_COMPARTMENT';
|
|
SELECT param_value INTO v_genai_region FROM TB_26AI_TECH_PARAMS WHERE param_name = 'GENAI_REGION';
|
|
|
|
DBMS_CLOUD_AI.CREATE_PROFILE(
|
|
profile_name => 'OCI_CRED2',
|
|
attributes => '{
|
|
"provider": "oci",
|
|
"credential_name": "OCI_CRED",
|
|
"region": "' || v_genai_region || '",
|
|
"model": "meta.llama-4-maverick-17b-128e-instruct-fp8",
|
|
"temperature": 0,
|
|
"comments": true,
|
|
"object_list": [
|
|
{"owner": "AMPMINSIGHTS", "name": "V_26AI_TECH"},
|
|
{"owner": "AMPMINSIGHTS", "name": "TB_26AI_TECH_CMDB"}
|
|
],
|
|
"enforce_object_list": "true"
|
|
}',
|
|
description => 'Profile ampmInsights para uso no SELECT AI (OCI Generative AI - Llama 4 Maverick). Compartimento: ' || v_compartment
|
|
);
|
|
END;
|
|
/
|
|
|
|
SELECT DBMS_CLOUD_AI.GENERATE(
|
|
prompt => 'Responda apenas: CONECTADO',
|
|
profile_name => 'OCI_CRED2',
|
|
action => 'chat'
|
|
) AS resposta
|
|
FROM dual;</code></pre>
|
|
</div><div class="callout warning">
|
|
<div class="callout-title">O passo mais importante</div>
|
|
<p><code>TB_26AI_TECH_PARAMS</code> (criada na Seção 2) guarda o nome da credencial e o OCID do
|
|
compartimento. Todo o PL/SQL da aplicação — e o job de processamento em lote criado pelo botão da
|
|
interface — lê esses valores dali. Se algo falhar mais adiante, confira primeiro se essa tabela
|
|
está com os valores reais preenchidos.</p>
|
|
</div>
|
|
<h2>Seção 6 · Tabelas, sequence, trigger e view da aplicacao</h2>
|
|
<p>Cria <code>TB_26AI_TECH_CHAT</code>, <code>TB_26AI_TECH_CMDB</code>, <code>TB_26AI_TECH_SYS</code>,
|
|
<code>TB_26AI_TECH_V2</code> (+ trigger/sequence de <code>ID_INSIGHT</code>), a tabela legada
|
|
<code>TB_26AI_TECH</code>, <code>TB_26AI_TECH_VECTOR</code> e a view <code>V_26AI_TECH</code>. Nomes
|
|
idênticos aos usados no export da aplicação APEX — não renomear estes objetos.</p>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 6 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">-- Os nomes de tabelas, view, sequence e trigger abaixo sao os MESMOS nomes
|
|
-- referenciados internamente pelo export da aplicacao APEX
|
|
-- (02_ampminsights_apex_app.sql). Nao renomeie estes objetos: a aplicacao
|
|
-- tem centenas de referencias diretas a estes nomes exatos.
|
|
|
|
CREATE TABLE "TB_26AI_TECH_CHAT"
|
|
( "USER_NAME" VARCHAR2(200) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador, papel ou atributo de usuario/controle de acesso associado a interacoes de chat do dominio tecnico.'),
|
|
"IS_OWN" VARCHAR2(6) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Indicador booleano de is own no registro de interacoes de chat do dominio tecnico.'),
|
|
"COMMENT_TEXT" CLOB ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Conteudo textual, documental ou binario associado a interacoes de chat do dominio tecnico; o nome da coluna indica o papel especifico no fluxo.'),
|
|
"COMMENT_DATE" DATE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Data, hora ou marco temporal associado ao registro de interacoes de chat do dominio tecnico.'),
|
|
"SESSION_ID" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador ou codigo de session no contexto de interacoes de chat do dominio tecnico.')
|
|
)
|
|
ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Armazena registros de interacoes de chat do dominio tecnico ("fale com os dados"); e classificada, pela nomenclatura e estrutura, como tabela operacional do dominio.');
|
|
|
|
CREATE TABLE "TB_26AI_TECH_CMDB"
|
|
( "ID" NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador unico do registro de itens de configuracao tecnica (CMDB); compoe a chave primaria da tabela. E coluna identity preenchida automaticamente pelo Oracle.'),
|
|
"NOME" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Nome ou titulo usado para identificar o registro de itens de configuracao tecnica (CMDB) em consultas e interfaces.'),
|
|
"EMPRESA" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo EMPRESA do registro de itens de configuracao tecnica (CMDB).'),
|
|
"CLASSE" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo de classificacao, versao, origem ou formato do registro de itens de configuracao tecnica (CMDB).'),
|
|
"AMBIENTE" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo AMBIENTE do registro de itens de configuracao tecnica (CMDB).'),
|
|
"STATUS_OPERACIONAL" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Indicador de estado ou de controle do registro de itens de configuracao tecnica (CMDB).'),
|
|
"DESCRIÇÃO" VARCHAR2(32767) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Texto descritivo, detalhe ou observacao associado a itens de configuracao tecnica (CMDB).'),
|
|
"SOX" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo SOX do registro de itens de configuracao tecnica (CMDB).'),
|
|
"COFRE" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo COFRE do registro de itens de configuracao tecnica (CMDB).'),
|
|
"ENDEREÇO_IP" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Endereco IP registrado no contexto de itens de configuracao tecnica (CMDB).'),
|
|
"SISTEMA_OPERACIONAL" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo SISTEMA_OPERACIONAL do registro de itens de configuracao tecnica (CMDB).'),
|
|
"TIPO_DE_REDE" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo TIPO_DE_REDE do registro de itens de configuracao tecnica (CMDB).'),
|
|
"É_VIRTUAL" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo E_VIRTUAL do registro de itens de configuracao tecnica (CMDB).'),
|
|
"CRITICIDADE" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo CRITICIDADE do registro de itens de configuracao tecnica (CMDB).'),
|
|
"INSTÂNCIAS_BANCOS" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo INSTANCIAS_BANCOS do registro de itens de configuracao tecnica (CMDB).'),
|
|
"APLICAÇÕES_RELACIONADAS" VARCHAR2(32767) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo APLICACOES_RELACIONADAS do registro de itens de configuracao tecnica (CMDB).'),
|
|
"JANELAS_DE_MANUTENÇÃO" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo JANELAS_DE_MANUTENCAO do registro de itens de configuracao tecnica (CMDB).'),
|
|
"ANALISTA_RESPONSAVEL" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo ANALISTA_RESPONSAVEL do registro de itens de configuracao tecnica (CMDB).'),
|
|
"ANALISTAS_RESPONSÁVEIS" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo ANALISTAS_RESPONSAVEIS do registro de itens de configuracao tecnica (CMDB).'),
|
|
"GERENCIADO_PELO_GRUPO" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo GERENCIADO_PELO_GRUPO do registro de itens de configuracao tecnica (CMDB).'),
|
|
"GRUPOS_RESPONSÁVEIS" VARCHAR2(32767) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo GRUPOS_RESPONSAVEIS do registro de itens de configuracao tecnica (CMDB).'),
|
|
"GRUPO_RESPONSÁVEL" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo GRUPO_RESPONSAVEL do registro de itens de configuracao tecnica (CMDB).'),
|
|
"EDR" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo EDR do registro de itens de configuracao tecnica (CMDB).'),
|
|
"TENABLE" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo TENABLE do registro de itens de configuracao tecnica (CMDB).'),
|
|
"SIEM" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo SIEM do registro de itens de configuracao tecnica (CMDB).'),
|
|
"APPLIANCE" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo APPLIANCE do registro de itens de configuracao tecnica (CMDB).'),
|
|
PRIMARY KEY ("ID")
|
|
USING INDEX ENABLE
|
|
)
|
|
ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Armazena registros de itens de configuracao tecnica (CMDB); e utilizada por VIEW V_26AI_TECH.');
|
|
|
|
CREATE TABLE "TB_26AI_TECH_SYS"
|
|
( "ID_1" NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador unico do registro de cadastro de sistemas tecnicos; compoe a chave primaria da tabela.'),
|
|
"ID" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador tecnico do registro de cadastro de sistemas tecnicos.'),
|
|
"TIMESTAMP" TIMESTAMP (9) WITH TIME ZONE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Data, hora ou marco temporal associado ao registro de cadastro de sistemas tecnicos.'),
|
|
"HOST" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo HOST do registro de cadastro de sistemas tecnicos.'),
|
|
"FACILITY" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo FACILITY do registro de cadastro de sistemas tecnicos.'),
|
|
"SEVERITY" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo SEVERITY do registro de cadastro de sistemas tecnicos.'),
|
|
"PROCESS" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo PROCESS do registro de cadastro de sistemas tecnicos.'),
|
|
"PID" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo PID do registro de cadastro de sistemas tecnicos.'),
|
|
"ORACLE_INSTANCE" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Atributo ORACLE_INSTANCE do registro de cadastro de sistemas tecnicos.'),
|
|
"MESSAGE" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Mensagem, diagnostico ou informacao de log associada ao processamento de cadastro de sistemas tecnicos.'),
|
|
"RAW_SYSLOG" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Mensagem, diagnostico ou informacao de log associada ao processamento de cadastro de sistemas tecnicos.'),
|
|
"INSIGHT_REPORT" CLOB ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Conteudo textual gerado por IA associado a cadastro de sistemas tecnicos.'),
|
|
"INSIGHT_JSON" CLOB ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Conteudo estruturado em JSON relacionado ao insight gerado por IA para cadastro de sistemas tecnicos.'),
|
|
PRIMARY KEY ("ID_1")
|
|
USING INDEX ENABLE
|
|
)
|
|
ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Armazena registros de cadastro de sistemas tecnicos (syslog); e utilizada por PROCEDURE PRC_26AI_TECH.');
|
|
|
|
CREATE SEQUENCE "SEQ_26AI_TECH" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE GLOBAL;
|
|
|
|
CREATE TABLE "TB_26AI_TECH_V2"
|
|
( "ID_1" NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador unico do registro de dados tecnicos (versao 2); compoe a chave primaria da tabela.'),
|
|
"AGE_IN_DAYS" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Idade em dias do achado, referenciada em VIEW V_26AI_TECH.'),
|
|
"ASSET_DISPLAY_IPV4_ADDRESS" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Endereco IPv4 do ativo, referenciado em VIEW V_26AI_TECH.'),
|
|
"ASSET_ID" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador do ativo, referenciado em VIEW V_26AI_TECH.'),
|
|
"ASSET_NAME" VARCHAR2(100) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Nome do ativo, referenciado em VIEW V_26AI_TECH.'),
|
|
"ASSET_TAGS" VARCHAR2(32767) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Tags do ativo, referenciadas em VIEW V_26AI_TECH.'),
|
|
"DEFINITION_EXPLOITABILITY_EASE" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Facilidade de exploracao da vulnerabilidade, referenciada em VIEW V_26AI_TECH.'),
|
|
"DEFINITION_FAMILY" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Familia da definicao de vulnerabilidade, referenciada em VIEW V_26AI_TECH.'),
|
|
"DEFINITION_ID" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador da definicao de vulnerabilidade, referenciado em VIEW V_26AI_TECH.'),
|
|
"DEFINITION_NAME" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Nome da definicao de vulnerabilidade, referenciado em VIEW V_26AI_TECH.'),
|
|
"DEFINITION_VPR_SCORE" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Score VPR (Vulnerability Priority Rating), referenciado em VIEW V_26AI_TECH.'),
|
|
"FIRST_OBSERVED" TIMESTAMP (9) WITH TIME ZONE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Data da primeira observacao, referenciada em VIEW V_26AI_TECH.'),
|
|
"ID" VARCHAR2(255) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador tecnico do achado, referenciado em VIEW V_26AI_TECH.'),
|
|
"LAST_SEEN" TIMESTAMP (9) WITH TIME ZONE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Data da ultima observacao, referenciada em VIEW V_26AI_TECH.'),
|
|
"OUTPUT" VARCHAR2(32767) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Saida/detalhe tecnico do scanner, referenciada em VIEW V_26AI_TECH.'),
|
|
"PROTOCOL" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Protocolo relacionado ao achado, referenciado em VIEW V_26AI_TECH.'),
|
|
"RESURFACED_DATE" TIMESTAMP (9) WITH TIME ZONE ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Data de ressurgimento do achado, referenciada em VIEW V_26AI_TECH.'),
|
|
"SEVERITY" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Severidade do achado, referenciada em VIEW V_26AI_TECH.'),
|
|
"STATE" VARCHAR2(50) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Estado do achado, referenciado em VIEW V_26AI_TECH.'),
|
|
"INSIGHT_REPORT" CLOB ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Relatorio de insight gerado por IA, referenciado em VIEW V_26AI_TECH.'),
|
|
"INSIGHT_JSON" CLOB ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Insight estruturado em JSON gerado por IA.'),
|
|
"ID_INSIGHT" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Identificador sequencial do insight, gerado pelo trigger BIU_TB_26AI_TECH_V2, referenciado em VIEW V_26AI_TECH.'),
|
|
PRIMARY KEY ("ID_1")
|
|
USING INDEX ENABLE
|
|
)
|
|
ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Armazena os achados de vulnerabilidade (principal fonte de dados tecnicos); e utilizada por PROCEDURE PRC_26AI_TECH e VIEW V_26AI_TECH.');
|
|
|
|
CREATE OR REPLACE EDITIONABLE TRIGGER "BIU_TB_26AI_TECH_V2"
|
|
BEFORE INSERT OR UPDATE
|
|
ON TB_26AI_TECH_V2
|
|
FOR EACH ROW
|
|
BEGIN
|
|
:new.ID_INSIGHT := SEQ_26AI_TECH.NEXTVAL;
|
|
END;
|
|
/
|
|
ALTER TRIGGER "BIU_TB_26AI_TECH_V2" ENABLE;
|
|
|
|
-- Tabela legada (mantida por compatibilidade: ainda e usada por uma pagina/
|
|
-- carga de dados mais antiga da aplicacao - "DL_TECH_VULNERABILIDADES").
|
|
CREATE TABLE "TB_26AI_TECH"
|
|
( "ID_1" NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE,
|
|
"AGE_IN_DAYS" NUMBER,
|
|
"ASSET_DISPLAY_IPV4_ADDRESS" VARCHAR2(255),
|
|
"ASSET_ID" VARCHAR2(255),
|
|
"ASSET_NAME" VARCHAR2(100),
|
|
"EMPRESA" VARCHAR2(50),
|
|
"AMBIENTE" VARCHAR2(50),
|
|
"STATUS" VARCHAR2(50),
|
|
"DESCRIÇÃO" VARCHAR2(32767),
|
|
"ASSET_OPERATING_SYSTEM" VARCHAR2(255),
|
|
"DEFINITION_EXPLOITABILITY_EASE" VARCHAR2(50),
|
|
"DEFINITION_FAMILY" VARCHAR2(255),
|
|
"DEFINITION_ID" NUMBER,
|
|
"DEFINITION_NAME" VARCHAR2(255),
|
|
"DEFINITION_VPR_SCORE" NUMBER,
|
|
"FIRST_OBSERVED" DATE,
|
|
"ID" VARCHAR2(255),
|
|
"LAST_SEEN" DATE,
|
|
"OUTPUT" VARCHAR2(32767),
|
|
"PROTOCOL" VARCHAR2(50),
|
|
"RESURFACED_DATE" DATE,
|
|
"SEVERITY" VARCHAR2(50),
|
|
"STATE" VARCHAR2(50),
|
|
"INSIGHT_REPORT" CLOB,
|
|
"INSIGHT_JSON" CLOB,
|
|
"ID_INSIGHT" NUMBER,
|
|
PRIMARY KEY ("ID_1")
|
|
USING INDEX ENABLE
|
|
);
|
|
|
|
CREATE TABLE "TB_26AI_TECH_VECTOR"
|
|
( "EMBED_ID" NUMBER ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Representacao vetorial (embedding) associada ao conteudo de embeddings de conhecimento tecnico, destinada a buscas por similaridade e fluxos de recuperacao aumentada (RAG).'),
|
|
"EMBED_DATA" CLOB ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Trecho de texto (chunk) que originou o vetor, referenciado em FUNCTION FNC_26AI_TECH_RAG.'),
|
|
"EMBED_VECTOR" VECTOR ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Vetor (embedding) do trecho, referenciado em FUNCTION FNC_26AI_TECH_RAG.'),
|
|
"TITULO" VARCHAR2(2000) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Titulo/identificacao do registro de embeddings de conhecimento tecnico.'),
|
|
"ID" VARCHAR2(200) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Referencia (rowid/id) do registro de origem do insight, referenciada em FUNCTION FNC_26AI_TECH_RAG.'),
|
|
"SOURCE_TYPE" VARCHAR2(3) ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Origem do dado vetorizado: VUL (vulnerabilidades) ou SYS (syslog).')
|
|
)
|
|
ANNOTATIONS("LLM_DESCRIPTION_PT_BR" 'Armazena os vetores (chunks) usados na busca semantica/RAG; e utilizada por FUNCTION FNC_26AI_TECH_RAG e PROCEDURE PRC_26AI_TECH.');
|
|
|
|
-- View consolidada usada pela aplicacao e pelo SELECT AI.
|
|
-- Observacao: as duas chamadas REPLACE() abaixo (colunas NOME/EMPRESA)
|
|
-- fazem parte da logica de negocio original do ambiente de origem e
|
|
-- generalizam nomes de marca especificos para "Company" em determinados
|
|
-- cenarios de apresentacao. Como este e o proprio ambiente da AM/PM, avalie
|
|
-- com o time de negocio se esse tratamento ainda faz sentido aqui ou se pode
|
|
-- ser removido (ver docs/07-seguranca-boas-praticas.html).
|
|
CREATE OR REPLACE FORCE EDITIONABLE VIEW "V_26AI_TECH" ("CID", "AGE_IN_DAYS", "ASSET_DISPLAY_IPV4_ADDRESS", "ASSET_ID", "ASSET_NAME", "ASSET_TAGS", "DEFINITION_EXPLOITABILITY_EASE", "DEFINITION_FAMILY", "DEFINITION_ID", "DEFINITION_NAME", "DEFINITION_VPR_SCORE", "FIRST_OBSERVED", "ID", "LAST_SEEN", "OUTPUT", "PROTOCOL", "RESURFACED_DATE", "SEVERITY", "STATE", "INSIGHT_REPORT", "ID_INSIGHT", "NOME", "EMPRESA", "CLASSE", "AMBIENTE", "STATUS_OPERACIONAL", "DESCRICAO", "SOX", "COFRE", "ENDERECO_IP", "SISTEMA_OPERACIONAL", "TIPO_DE_REDE", "IS_VIRTUAL", "CRITICIDADE", "INSTANCIAS_BANCOS", "APLICACOES_RELACIONADAS", "JANELAS_DE_MANUTENCAO", "ANALISTA_RESPONSAVEL", "ANALISTAS_RESPONSAVEIS", "GERENCIADO_PELO_GRUPO", "GRUPOS_RESPONSAVEIS", "GRUPO_RESPONSAVEL", "EDR", "TENABLE", "SIEM", "APPLIANCE") AS
|
|
SELECT
|
|
v.rowid cid,
|
|
v.AGE_IN_DAYS ,
|
|
v.ASSET_DISPLAY_IPV4_ADDRESS ,
|
|
v.ASSET_ID ,
|
|
v.ASSET_NAME ,
|
|
v.ASSET_TAGS ,
|
|
v.DEFINITION_EXPLOITABILITY_EASE ,
|
|
v.DEFINITION_FAMILY ,
|
|
v.DEFINITION_ID ,
|
|
v.DEFINITION_NAME ,
|
|
v.DEFINITION_VPR_SCORE ,
|
|
v.FIRST_OBSERVED ,
|
|
v.ID ,
|
|
v.LAST_SEEN ,
|
|
v.OUTPUT ,
|
|
v.PROTOCOL ,
|
|
v.RESURFACED_DATE ,
|
|
v.SEVERITY ,
|
|
v.STATE ,
|
|
v.INSIGHT_REPORT ,
|
|
v.ID_INSIGHT ,
|
|
replace(replace(initcap(c.NOME),'Ipiranga','Company'),'Ampm','Company') NOME ,
|
|
replace(replace(initcap(c.EMPRESA),'Ipiranga','Company'),'Ampm','Company') EMPRESA ,
|
|
c.CLASSE ,
|
|
c.AMBIENTE ,
|
|
c.STATUS_OPERACIONAL ,
|
|
c.DESCRIÇÃO DESCRICAO ,
|
|
c.SOX ,
|
|
c.COFRE ,
|
|
c.ENDEREÇO_IP ENDERECO_IP ,
|
|
c.SISTEMA_OPERACIONAL ,
|
|
c.TIPO_DE_REDE ,
|
|
c.É_VIRTUAL IS_VIRTUAL ,
|
|
c.CRITICIDADE ,
|
|
c.INSTÂNCIAS_BANCOS INSTANCIAS_BANCOS ,
|
|
c.APLICAÇÕES_RELACIONADAS APLICACOES_RELACIONADAS ,
|
|
c.JANELAS_DE_MANUTENÇÃO JANELAS_DE_MANUTENCAO ,
|
|
c.ANALISTA_RESPONSAVEL ,
|
|
c.ANALISTAS_RESPONSÁVEIS ANALISTAS_RESPONSAVEIS ,
|
|
c.GERENCIADO_PELO_GRUPO ,
|
|
c.GRUPOS_RESPONSÁVEIS GRUPOS_RESPONSAVEIS ,
|
|
c.GRUPO_RESPONSÁVEL GRUPO_RESPONSAVEL ,
|
|
c.EDR,
|
|
c.TENABLE ,
|
|
c.SIEM ,
|
|
c.APPLIANCE
|
|
FROM TB_26AI_TECH_v2 v
|
|
LEFT OUTER JOIN
|
|
(SELECT *
|
|
FROM TB_26AI_TECH_CMDB
|
|
WHERE nome IN (SELECT nome
|
|
FROM TB_26AI_TECH_CMDB
|
|
GROUP BY nome
|
|
HAVING count(1) = 1 )
|
|
) c
|
|
ON ( upper(v.ASSET_NAME) = upper(c.nome) AND c.AMBIENTE IS NOT NULL );
|
|
|
|
-- Log de chamadas de IA/embeddings (sucesso e erro) - nao guarda prompt/
|
|
-- resposta completos, so metadados de uso. Ver docs/09-operacao-observabilidade.html.
|
|
CREATE TABLE "TB_26AI_TECH_LOG"
|
|
( "LOG_ID" NUMBER GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE,
|
|
"LOG_TS" TIMESTAMP(6) WITH TIME ZONE DEFAULT SYSTIMESTAMP NOT NULL ENABLE,
|
|
"CALLING_OBJECT" VARCHAR2(128),
|
|
"OPERATION" VARCHAR2(30),
|
|
"SOURCE_TYPE" VARCHAR2(10),
|
|
"SOURCE_ID" VARCHAR2(200),
|
|
"PROVIDER" VARCHAR2(30),
|
|
"MODEL_NAME" VARCHAR2(100),
|
|
"APP_USER" VARCHAR2(100),
|
|
"STATUS" VARCHAR2(10),
|
|
"ERROR_CODE" NUMBER,
|
|
"ERROR_MESSAGE" VARCHAR2(4000),
|
|
"DURATION_MS" NUMBER,
|
|
"PROMPT_CHARS" NUMBER,
|
|
"RESPONSE_CHARS" NUMBER,
|
|
CONSTRAINT "TB_26AI_TECH_LOG_PK" PRIMARY KEY ("LOG_ID") USING INDEX ENABLE
|
|
);
|
|
|
|
CREATE INDEX "TB_26AI_TECH_LOG_TS_IX" ON "TB_26AI_TECH_LOG" ("LOG_TS");
|
|
CREATE INDEX "TB_26AI_TECH_LOG_ST_IX" ON "TB_26AI_TECH_LOG" ("STATUS","LOG_TS");
|
|
|
|
COMMENT ON TABLE "TB_26AI_TECH_LOG" IS 'Log de cada chamada a Generative AI/embeddings feita pelo ampmInsights (sucesso ou erro) - nao guarda prompt/resposta completos, so metadados de uso (modelo, duracao, tamanho, status, erro). Usada para troubleshooting e monitoramento de consumo - ver docs/09-operacao-observabilidade.html.';</code></pre>
|
|
</div>
|
|
<h2>Seção 7 · PL/SQL de geracao de embeddings, RAG e insights (ampmInsights)</h2>
|
|
<p>Cria <code>PRC_26AI_TECH_LOG</code> (log de cada chamada de IA/embedding — ver
|
|
<a href="09-operacao-observabilidade.html">Operação & observabilidade</a>) e as funções e a
|
|
procedure descritas em <a href="02-arquitetura.html">Arquitetura</a>: <code>fnc_26ai_embed</code>,
|
|
<code>fnc_26ai_tech_rag</code>, <code>FNC_26AI_TECH_MCP_V1</code>, <code>FNC_26ai_rag</code> e
|
|
<code>prc_26ai_tech</code>. É um bloco longo (a maior parte é o texto dos prompts de IA) — copie e
|
|
cole inteiro de uma vez.</p>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 7 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">CREATE OR REPLACE PROCEDURE PRC_26AI_TECH_LOG (
|
|
p_calling_object IN VARCHAR2,
|
|
p_operation IN VARCHAR2,
|
|
p_status IN VARCHAR2,
|
|
p_source_type IN VARCHAR2 DEFAULT NULL,
|
|
p_source_id IN VARCHAR2 DEFAULT NULL,
|
|
p_provider IN VARCHAR2 DEFAULT NULL,
|
|
p_model_name IN VARCHAR2 DEFAULT NULL,
|
|
p_error_code IN NUMBER DEFAULT NULL,
|
|
p_error_message IN VARCHAR2 DEFAULT NULL,
|
|
p_duration_ms IN NUMBER DEFAULT NULL,
|
|
p_prompt_chars IN NUMBER DEFAULT NULL,
|
|
p_response_chars IN NUMBER DEFAULT NULL
|
|
) AS
|
|
PRAGMA AUTONOMOUS_TRANSACTION;
|
|
/*
|
|
Projeto: ampmInsights
|
|
Objetivo: registrar em TB_26AI_TECH_LOG cada chamada a Generative AI/
|
|
embeddings (sucesso ou erro), para troubleshooting e
|
|
monitoramento de consumo (ver docs/09-operacao-observabilidade.html).
|
|
Autonomous transaction: pode ser chamada de dentro de functions invocadas
|
|
em contexto SQL sem interferir na transacao do chamador; nunca propaga erro
|
|
(uma falha ao logar nao pode derrubar a chamada real de IA).
|
|
*/
|
|
BEGIN
|
|
INSERT INTO TB_26AI_TECH_LOG (
|
|
calling_object, operation, source_type, source_id, provider, model_name,
|
|
app_user, status, error_code, error_message, duration_ms, prompt_chars,
|
|
response_chars
|
|
) VALUES (
|
|
p_calling_object, p_operation, p_source_type, p_source_id, p_provider,
|
|
p_model_name, NVL(V('APP_USER'), SYS_CONTEXT('USERENV','SESSION_USER')),
|
|
p_status, p_error_code, SUBSTR(p_error_message, 1, 4000), p_duration_ms,
|
|
p_prompt_chars, p_response_chars
|
|
);
|
|
COMMIT;
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
NULL; -- logging nunca pode quebrar a chamada real
|
|
END;
|
|
/
|
|
|
|
CREATE OR REPLACE FUNCTION fnc_26ai_embed( p_string IN VARCHAR2,
|
|
p_emb_type IN VARCHAR2 DEFAULT 'COHERE',
|
|
p_credential IN VARCHAR2 DEFAULT 'OCI_CRED')
|
|
RETURN CLOB
|
|
AS
|
|
/*
|
|
Projeto: ampmInsights
|
|
Objetivo: gerar o embedding (vetor) de um texto, usando o provider indicado
|
|
em p_emb_type: ONNX (modelo local carregado na SECAO 4),
|
|
COHERE (OCI Generative AI - usado por padrao) ou vLLM (endpoint
|
|
self-hosted, opcional).
|
|
*/
|
|
v_embedding CLOB;
|
|
v_string CLOB;
|
|
v_url VARCHAR2(700) := 'https://inference.generativeai.sa-saopaulo-1.oci.oraclecloud.com/20231130/actions/embedText';
|
|
v_body JSON_OBJECT_T;
|
|
r DBMS_CLOUD_TYPES.RESP;
|
|
|
|
BEGIN
|
|
|
|
v_string := replace(replace(replace(p_string,chr(13),' '),chr(10),' '),'"','') ;
|
|
|
|
IF p_emb_type = 'ONNX' THEN
|
|
|
|
/* Pre-requisito: modelo ONNX carregado na SECAO 4 deste script (opcional). */
|
|
|
|
SELECT VECTOR_EMBEDDING( CLIP_VIT_LARGE_PATCH14_TXT USING v_string AS data ) AS embedding
|
|
INTO v_embedding;
|
|
|
|
ELSIF p_emb_type = 'COHERE' THEN
|
|
|
|
/* CUIDADO: dbms_vector_chain.utl_to_text(v_string) usa internamente o Oracle
|
|
Text Filter (processo externo ctxfilt) para converter documentos (PDF,
|
|
DOCX etc.) em texto puro. O erro DRG-11225 (third-party filter timed out)
|
|
indica que esse processo demorou mais que o timeout configurado. */
|
|
|
|
SELECT embed_vector
|
|
INTO v_embedding
|
|
FROM dual
|
|
CROSS JOIN TABLE(
|
|
dbms_vector_chain.utl_to_embeddings(
|
|
dbms_vector_chain.utl_to_text( v_string ),
|
|
json('{ "provider": "ocigenai",
|
|
"credential_name": "' || p_credential || '",
|
|
"url": "https://inference.generativeai.' || (SELECT param_value FROM TB_26AI_TECH_PARAMS WHERE param_name = 'GENAI_REGION') || '.oci.oraclecloud.com/20231130/actions/embedText",
|
|
"model": "cohere.embed-v4.0"
|
|
}')
|
|
)
|
|
) t
|
|
CROSS JOIN JSON_TABLE(
|
|
t.column_value,
|
|
'$[*]' COLUMNS (
|
|
embed_id NUMBER PATH '$.embed_id',
|
|
text_chunk VARCHAR2(4000) PATH '$.embed_data',
|
|
embed_vector CLOB PATH '$.embed_vector'
|
|
)
|
|
) AS et;
|
|
|
|
ELSIF p_emb_type = 'vLLM' THEN
|
|
-- Endpoint self-hosted opcional (ex.: vLLM atras de um load
|
|
-- balancer proprio). Ajuste "host" e "model" para o seu
|
|
-- ambiente antes de usar esta opcao; nao e necessaria para o
|
|
-- fluxo padrao (COHERE via OCI Generative AI).
|
|
DECLARE
|
|
params clob;
|
|
v_embedding2 vector;
|
|
BEGIN
|
|
|
|
params := '{
|
|
"provider": "openai",
|
|
"url": "https://<SUBSTITUA_PELO_SEU_ENDPOINT_VLLM>/embed/v1/embeddings",
|
|
"host": "local",
|
|
"model": "<SUBSTITUA_PELO_MODELO_QUE_VOCE_HOSPEDA>",
|
|
"batch_size": 50}';
|
|
|
|
v_embedding2 := dbms_vector_chain.utl_to_embedding( v_string , json(params)) ;
|
|
|
|
v_embedding := TO_CLOB(TO_CHAR( v_embedding2 ) ) ;
|
|
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
DBMS_OUTPUT.PUT_LINE('Erro: ' || SQLCODE || ' - ' || SQLERRM);
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'FNC_26AI_EMBED',
|
|
p_operation => 'EMBEDDING',
|
|
p_status => 'ERROR',
|
|
p_provider => 'vLLM',
|
|
p_error_code => SQLCODE,
|
|
p_error_message => SQLERRM
|
|
);
|
|
END;
|
|
|
|
END IF;
|
|
|
|
RETURN v_embedding;
|
|
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
-- Cobre os ramos ONNX/COHERE (o vLLM ja trata e loga o proprio erro
|
|
-- acima e nao propaga). Loga e repropaga sem mudar o comportamento
|
|
-- existente.
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'FNC_26AI_EMBED',
|
|
p_operation => 'EMBEDDING',
|
|
p_status => 'ERROR',
|
|
p_provider => p_emb_type,
|
|
p_error_code => SQLCODE,
|
|
p_error_message => SQLERRM
|
|
);
|
|
RAISE;
|
|
END;
|
|
/
|
|
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION fnc_26ai_tech_rag(p_query VARCHAR2,
|
|
p_top_k IN NUMBER ,
|
|
p_credential in varchar2 default 'OCI_CRED',
|
|
p_app_user in varchar2 default V('APP_USER'),
|
|
p_source_type varchar2 default 'VUL' )
|
|
RETURN CLOB IS
|
|
/*
|
|
Projeto: ampmInsights
|
|
Objetivo: funcao de RAG (Retrieval-Augmented Generation) para "fale com os
|
|
seus dados" no dominio tecnico (vulnerabilidades e syslog).
|
|
*/
|
|
v_context CLOB;
|
|
v_pre_prompt CLOB;
|
|
v_prompt CLOB;
|
|
v_pre_prompt2 CLOB;
|
|
params_genai CLOB;
|
|
output CLOB;
|
|
query_vec VECTOR;
|
|
v_llm VARCHAR2(20) := 'LLAMA4'; -- [ LLAMA4 | OPENAI ]
|
|
v_genai_region TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
|
|
BEGIN
|
|
|
|
SELECT param_value INTO v_genai_region FROM TB_26AI_TECH_PARAMS WHERE param_name = 'GENAI_REGION';
|
|
|
|
-- embedding da pergunta do usuario
|
|
query_vec := to_vector( fnc_26ai_embed ( p_string => p_query, p_emb_type => 'COHERE' ) ) ;
|
|
|
|
FOR message_cursor IN (
|
|
SELECT lv.ID AS DOCID,
|
|
lv.EMBED_DATA AS BODY,
|
|
vector_distance( lv.EMBED_VECTOR, query_vec, cosine ) AS SCORE
|
|
FROM TB_26AI_TECH_VECTOR lv
|
|
WHERE source_type = p_source_type
|
|
ORDER BY SCORE
|
|
FETCH EXACT FIRST p_top_k ROWS ONLY
|
|
) LOOP
|
|
|
|
v_context := v_context || '"' || replace(replace(replace(replace(message_cursor.BODY,chr(10),null),chr(13),null),'"',''),'''','') || '",' ;
|
|
|
|
END LOOP;
|
|
|
|
-- Pre-requisito: credencial OCI_CRED criada na SECAO 3.
|
|
-- Referencia do corpo da chamada:
|
|
-- https://docs.oracle.com/en-us/iaas/api/#/en/generative-ai-inference/20231130/datatypes/GenerateTextDetails
|
|
IF v_llm = 'LLAMA4' THEN
|
|
|
|
params_genai := '{
|
|
"provider" : "ocigenai",
|
|
"credential_name" : "' || p_credential || '",
|
|
"url" : "https://inference.generativeai.' || v_genai_region || '.oci.oraclecloud.com/20231130/actions/chat",
|
|
"model": "meta.llama-4-maverick-17b-128e-instruct-fp8"}';
|
|
|
|
ELSIF v_llm = 'OPENAI' THEN
|
|
|
|
params_genai := '{
|
|
"provider" : "openai",
|
|
"credential_name" : "CRED_OPENAI",
|
|
"url" : "https://api.openai.com/v1/chat/completions",
|
|
"model" : "gpt-4.1-mini",
|
|
"temperature": 0.4
|
|
}';
|
|
|
|
END IF;
|
|
|
|
v_pre_prompt := 'Voce e um Analista Senior de Inteligencia Operacional especializado em analisar relatorios tecnicos e executivos previamente gerados.
|
|
|
|
Contexto de trabalho:
|
|
- Voce recebera:
|
|
1) A pergunta do usuario
|
|
2) Um conjunto de trechos recuperados da base vetorizada de relatorios (com metadados como report_id, data, area, severidade, prioridade, fonte).
|
|
- Sua tarefa e encontrar evidencias relevantes nesses relatorios e responder com precisao, sem inventar informacoes.
|
|
|
|
Regras obrigatorias:
|
|
- Use SOMENTE informacoes presentes nos trechos recuperados.
|
|
- Se faltar dado para responder algo, escreva explicitamente: "Informacao nao fornecida".
|
|
- Sempre cite as evidencias no formato: [report_id | secao/campo | data].
|
|
- Quando houver conflito entre relatorios, sinalize divergencia e indique qual evidencia e mais confiavel (recencia, completude, consistencia).
|
|
- Priorize risco de negocio, severidade e urgencia.
|
|
- Nao repita conteudo desnecessario; seja objetivo e acionavel.
|
|
|
|
Metodo de resposta:
|
|
1) Entenda a intencao da pergunta (comparar, diagnosticar, priorizar, tendencia, causa, acao).
|
|
2) Selecione os trechos mais relevantes por aderencia semantica a pergunta.
|
|
3) Consolide achados em linguagem executiva + tecnica.
|
|
4) Gere recomendacoes praticas com prioridade e esforco.
|
|
5) Indique lacunas de dados que limitam a conclusao.
|
|
|
|
Formato obrigatorio de saida:
|
|
## Resposta objetiva
|
|
- Responda em formato markdown, e use fontes com mesmo tamanho, porem com titulos em NEGRITO.
|
|
- Resposta direta a pergunta em 3 a 6 linhas.
|
|
|
|
## Evidencias encontradas
|
|
- Evidencia 1: <achado> [report_id | secao/campo | data]
|
|
- Evidencia 2: <achado> [report_id | secao/campo | data]
|
|
- Evidencia 3: <achado> [report_id | secao/campo | data]
|
|
|
|
## Diagnostico consolidado
|
|
- Causa/hipotese principal (Alta/Media/Baixa)
|
|
- Risco de curto prazo
|
|
- Risco de medio prazo
|
|
|
|
## Recomendacoes priorizadas
|
|
- P1: <acao> | Impacto: <...> | Esforco: <Baixo/Medio/Alto>
|
|
- P2: <acao> | Impacto: <...> | Esforco: <Baixo/Medio/Alto>
|
|
- P3: <acao> | Impacto: <...> | Esforco: <Baixo/Medio/Alto>
|
|
|
|
## Lacunas e proximos dados necessarios
|
|
- Informacao nao fornecida: <campo/contexto ausente>
|
|
- Dado adicional recomendado para aumentar confianca da resposta: <...>';
|
|
|
|
v_pre_prompt2 := '{ "role": "user","content": "Contexto:"' || v_context || ' "Pergunta": ' || p_query || '"}' ;
|
|
|
|
output := dbms_vector_chain.utl_to_generate_text( replace(replace(replace(replace(v_pre_prompt || v_pre_prompt2,chr(10),null),chr(13),null),'"',''),'''','') , json(params_genai));
|
|
|
|
RETURN output;
|
|
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
-- Nao havia handler antes; loga e repropaga (comportamento de
|
|
-- propagar o erro ao chamador continua o mesmo).
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'FNC_26AI_TECH_RAG',
|
|
p_operation => 'RAG',
|
|
p_status => 'ERROR',
|
|
p_source_type => p_source_type,
|
|
p_provider => 'ocigenai',
|
|
p_error_code => SQLCODE,
|
|
p_error_message => SQLERRM
|
|
);
|
|
RAISE;
|
|
END;
|
|
/
|
|
|
|
|
|
|
|
-- Funcao auxiliar usada por integracoes do tipo MCP (Model Context Protocol),
|
|
-- caso a AM/PM/V8 Solution queira expor o RAG do ampmInsights como uma
|
|
-- ferramenta (tool) de um agente externo.
|
|
CREATE OR REPLACE FUNCTION FNC_26AI_TECH_MCP_V1 (
|
|
p_query IN VARCHAR2
|
|
) RETURN CLOB AS
|
|
V_TXT CLOB;
|
|
V_SQL CLOB;
|
|
BEGIN
|
|
SELECT fnc_26ai_tech_rag(p_query, 60, 'OCI_CRED', 'MCPUSER')
|
|
INTO V_TXT;
|
|
RETURN V_TXT;
|
|
END;
|
|
/
|
|
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION FNC_26ai_rag (p_ai_prompt IN CLOB,
|
|
p_oci_cred IN VARCHAR2 DEFAULT 'OCI_CRED',
|
|
p_comp IN VARCHAR2
|
|
)
|
|
RETURN CLOB AS
|
|
/*
|
|
Projeto: ampmInsights
|
|
Objetivo: funcao global de chamada ao LLM (Llama 4, via OCI Generative AI)
|
|
usada pelo RAG e pela geracao de insights.
|
|
*/
|
|
v_gen_ai_endpoint VARCHAR2(500);
|
|
v_gen_ai_model VARCHAR2(500) := 'meta.llama-4-maverick-17b-128e-instruct-fp8';
|
|
resp DBMS_CLOUD_TYPES.RESP;
|
|
v_t0 PLS_INTEGER := DBMS_UTILITY.GET_TIME;
|
|
v_result CLOB;
|
|
BEGIN
|
|
SELECT 'https://inference.generativeai.' || param_value || '.oci.oraclecloud.com'
|
|
INTO v_gen_ai_endpoint
|
|
FROM TB_26AI_TECH_PARAMS WHERE param_name = 'GENAI_REGION';
|
|
|
|
resp := dbms_cloud.send_request(
|
|
credential_name => p_oci_cred,
|
|
uri => v_gen_ai_endpoint || '/20231130/actions/chat',
|
|
method => dbms_cloud.METHOD_POST,
|
|
body => utl_raw.cast_to_raw(json_object(
|
|
'compartmentId' value p_comp,
|
|
'servingMode' value
|
|
(json_object(
|
|
'modelId' value v_gen_ai_model,
|
|
'servingType' value 'ON_DEMAND'
|
|
)),
|
|
'chatRequest' value
|
|
(json_object(
|
|
'apiFormat' value 'GENERIC',
|
|
'messages' value
|
|
(json_array(JSON_OBJECT(
|
|
'role' value 'USER',
|
|
'content' value
|
|
(json_array(JSON_OBJECT(
|
|
'type' value 'TEXT',
|
|
'text' value p_ai_prompt
|
|
)))
|
|
))),
|
|
'temperature' value 0.1,
|
|
'topK' value -1
|
|
))
|
|
))
|
|
);
|
|
v_result := json_value( dbms_cloud.get_response_text(resp) , '$.chatResponse.choices[0].message.content[0].text') ;
|
|
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'FNC_26AI_RAG',
|
|
p_operation => 'CHAT',
|
|
p_status => 'OK',
|
|
p_provider => 'ocigenai',
|
|
p_model_name => v_gen_ai_model,
|
|
p_duration_ms => (DBMS_UTILITY.GET_TIME - v_t0) * 10,
|
|
p_prompt_chars => LENGTH(p_ai_prompt),
|
|
p_response_chars => LENGTH(v_result)
|
|
);
|
|
|
|
RETURN v_result;
|
|
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'FNC_26AI_RAG',
|
|
p_operation => 'CHAT',
|
|
p_status => 'ERROR',
|
|
p_provider => 'ocigenai',
|
|
p_model_name => v_gen_ai_model,
|
|
p_error_code => SQLCODE,
|
|
p_error_message => SQLERRM,
|
|
p_duration_ms => (DBMS_UTILITY.GET_TIME - v_t0) * 10,
|
|
p_prompt_chars => LENGTH(p_ai_prompt)
|
|
);
|
|
RETURN 'Nao foi possivel gerar um texto com base nas informacoes.';
|
|
END;
|
|
/
|
|
|
|
|
|
|
|
CREATE OR REPLACE PROCEDURE prc_26ai_tech (p_rowid IN VARCHAR DEFAULT NULL,
|
|
p_oci_cred IN VARCHAR2 DEFAULT 'OCI_CRED',
|
|
p_comp IN VARCHAR2,
|
|
p_source_type VARCHAR2 DEFAULT 'VUL' )
|
|
/*
|
|
Projeto: ampmInsights
|
|
Gera o insight de IA (analise + diagnostico + recomendacoes + plano de acao)
|
|
para um registro de TB_26AI_TECH_V2 (vulnerabilidades) ou TB_26AI_TECH_SYS
|
|
(syslog), grava o resultado e cria o vetor (chunk) correspondente em
|
|
TB_26AI_TECH_VECTOR.
|
|
|
|
Para processamento em lote / carga inicial (rode manualmente uma vez, ou use
|
|
o botao "Gerar Insights em Lote" da aplicacao APEX, que cria um job via
|
|
DBMS_SCHEDULER lendo EMBEDDING_CREDENTIAL/EMBEDDING_COMPARTMENT a partir de
|
|
TB_26AI_TECH_PARAMS - ver SECAO 2). O bloco abaixo tambem le o compartimento
|
|
direto da tabela de configuracao, entao nao ha nenhum OCID para colar aqui:
|
|
|
|
DECLARE
|
|
v_resp CLOB;
|
|
v_comp TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
BEGIN
|
|
SELECT param_value INTO v_comp FROM TB_26AI_TECH_PARAMS WHERE param_name = 'EMBEDDING_COMPARTMENT';
|
|
FOR r1 IN (SELECT rowid cid FROM TB_26AI_TECH_v2 WHERE insight_report IS NULL) LOOP
|
|
PRC_26AI_TECH (p_rowid => r1.cid,
|
|
p_oci_cred => 'OCI_CRED',
|
|
p_comp => v_comp,
|
|
p_source_type => 'VUL');
|
|
END LOOP;
|
|
END;
|
|
/
|
|
*/
|
|
AS
|
|
v_pre_prompt CLOB;
|
|
v_customer_data CLOB;
|
|
v_pre_prompt_json CLOB;
|
|
v_response CLOB;
|
|
v_json CLOB;
|
|
v_error CLOB;
|
|
v_genai_region TB_26AI_TECH_PARAMS.PARAM_VALUE%TYPE;
|
|
BEGIN
|
|
|
|
SELECT param_value INTO v_genai_region FROM TB_26AI_TECH_PARAMS WHERE param_name = 'GENAI_REGION';
|
|
|
|
IF p_source_type = 'VUL' THEN -- vulnerabilidades
|
|
|
|
v_pre_prompt :='Voce e um analista senior de dados e operacoes.
|
|
Sua tarefa e interpretar os dados, comparar os resultados e produzir um relatorio executivo e tecnico acionavel.
|
|
|
|
Objetivo:
|
|
Gerar insights em 4 blocos:
|
|
1) Analise
|
|
2) Diagnostico
|
|
3) Recomendacoes
|
|
4) Plano de acao
|
|
|
|
Regras de qualidade:
|
|
- Nao invente dados ausentes. Quando faltar contexto, declare explicitamente "Informacao nao fornecida".
|
|
- Seja especifico, com linguagem executiva + tecnica.
|
|
- Priorize risco real de negocio e explorabilidade.
|
|
- Sempre indicar severidade e prioridade.
|
|
- Sempre incluir acoes de curto, medio e longo prazo.
|
|
- Quando possivel, referenciar boas praticas (OWASP, NIST, CIS, CVE/CWE).
|
|
|
|
Formato obrigatorio da resposta:
|
|
## 1. Analise
|
|
- Resumo executivo (5 a 8 linhas)
|
|
- Principais metricas observadas
|
|
- Pontos fora do padrao (outliers/anomalias)
|
|
|
|
## 2. Diagnostico
|
|
- Causas provaveis por ordem de impacto (Alta/Media/Baixa)
|
|
- Evidencias que sustentam cada causa (referenciando campos do JSON)
|
|
- Riscos de curto e medio prazo se nada for feito
|
|
|
|
## 3. Recomendacoes
|
|
Para cada recomendacao, informe:
|
|
- Acao recomendada
|
|
- Problema que resolve
|
|
- Impacto esperado
|
|
- Esforco estimado (Baixo/Medio/Alto)
|
|
- Prioridade (P1/P2/P3)
|
|
|
|
## 4. Plano de acao (30-60-90 dias)
|
|
- 30 dias: acoes imediatas e "quick wins"
|
|
- 60 dias: ajustes estruturais
|
|
- 90 dias: consolidacao e otimizacao
|
|
Para cada etapa, incluir:
|
|
- Responsavel sugerido (perfil/funcao)
|
|
- Dependencias
|
|
- Metrica de sucesso (KPI)
|
|
- Criterio de conclusao';
|
|
|
|
|
|
v_pre_prompt_json := '## FORMATO DE SAIDA JSON
|
|
Quando solicitado no modo JSON, responda EXCLUSIVAMENTE com o objeto JSON
|
|
valido conforme o schema abaixo, sem texto antes ou depois, sem markdown,
|
|
sem blocos de codigo. O JSON deve ser parseable diretamente.
|
|
Campos nao avaliaveis por qualidade de imagem devem receber null.
|
|
Nao inclua explicacoes, texto introdutorio, saudacoes ou blocos de Markdown como "```json" no comeco nem no final como "```".
|
|
|
|
## Exemplo JSON:
|
|
Retorne um JSON valido (sem comentarios), espelhando o relatorio:
|
|
{
|
|
"id": "",
|
|
"titulo": "",
|
|
"analise": {
|
|
"resumo_tecnico": "",
|
|
"vetor_ataque": "",
|
|
"pre_condicoes": [],
|
|
"impacto_cia": {
|
|
"confidencialidade": "",
|
|
"integridade": "",
|
|
"disponibilidade": ""
|
|
}
|
|
},
|
|
"diagnostico": {
|
|
"causa_raiz": "",
|
|
"classificacao": {
|
|
"cwe": "",
|
|
"owasp": ""
|
|
},
|
|
"severidade": "",
|
|
"probabilidade_exploracao": "",
|
|
"impacto_negocio": "",
|
|
"prioridade_final": "",
|
|
"justificativa": ""
|
|
},
|
|
"recomendacoes": [
|
|
{
|
|
"acao": "",
|
|
"tipo": "corretiva|preventiva|detectiva",
|
|
"esforco": "baixo|medio|alto",
|
|
"dependencias": []
|
|
}
|
|
],
|
|
"plano_acao": [
|
|
{
|
|
"prazo": "curto|medio|longo",
|
|
"etapa": "",
|
|
"responsavel_sugerido": "",
|
|
"deadline_sugerido": "",
|
|
"resultado_esperado": "",
|
|
"criterio_aceite": ""
|
|
}
|
|
],
|
|
"lacunas_informacao": []
|
|
}';
|
|
|
|
SELECT json_object(
|
|
'AGE_IN_DAYS' VALUE AGE_IN_DAYS,
|
|
'ASSET_DISPLAY_IPV4_ADDRESS' VALUE ASSET_DISPLAY_IPV4_ADDRESS,
|
|
'ASSET_ID' VALUE ASSET_ID,
|
|
'ASSET_NAME' VALUE ASSET_NAME,
|
|
'ASSET_TAGS' VALUE ASSET_TAGS,
|
|
'DEFINITION_EXPLOITABILITY_EASE' VALUE DEFINITION_EXPLOITABILITY_EASE,
|
|
'DEFINITION_FAMILY' VALUE DEFINITION_FAMILY,
|
|
'DEFINITION_ID' VALUE DEFINITION_ID,
|
|
'DEFINITION_NAME' VALUE DEFINITION_NAME,
|
|
'DEFINITION_VPR_SCORE' VALUE DEFINITION_VPR_SCORE,
|
|
'FIRST_OBSERVED' VALUE FIRST_OBSERVED,
|
|
'ID' VALUE ID,
|
|
'LAST_SEEN' VALUE LAST_SEEN,
|
|
'OUTPUT' VALUE OUTPUT,
|
|
'PROTOCOL' VALUE PROTOCOL,
|
|
'RESURFACED_DATE' VALUE RESURFACED_DATE,
|
|
'SEVERITY' VALUE SEVERITY,
|
|
'STATE' VALUE STATE,
|
|
'INSIGHT_REPORT' VALUE INSIGHT_REPORT,
|
|
'ID_INSIGHT' VALUE ID_INSIGHT,
|
|
'NOME' VALUE NOME,
|
|
'EMPRESA' VALUE EMPRESA,
|
|
'CLASSE' VALUE CLASSE,
|
|
'AMBIENTE' VALUE AMBIENTE,
|
|
'STATUS_OPERACIONAL' VALUE STATUS_OPERACIONAL,
|
|
'DESCRICAO' VALUE DESCRICAO,
|
|
'SOX' VALUE SOX,
|
|
'COFRE' VALUE COFRE,
|
|
'ENDERECO_IP' VALUE ENDERECO_IP,
|
|
'SISTEMA_OPERACIONAL' VALUE SISTEMA_OPERACIONAL,
|
|
'TIPO_DE_REDE' VALUE TIPO_DE_REDE,
|
|
'IS_VIRTUAL' VALUE IS_VIRTUAL,
|
|
'CRITICIDADE' VALUE CRITICIDADE,
|
|
'INSTANCIAS_BANCOS' VALUE INSTANCIAS_BANCOS,
|
|
'APLICACOES_RELACIONADAS' VALUE APLICACOES_RELACIONADAS,
|
|
'JANELAS_DE_MANUTENCAO' VALUE JANELAS_DE_MANUTENCAO,
|
|
'ANALISTA_RESPONSAVEL' VALUE ANALISTA_RESPONSAVEL,
|
|
'ANALISTAS_RESPONSAVEIS' VALUE ANALISTAS_RESPONSAVEIS,
|
|
'GERENCIADO_PELO_GRUPO' VALUE GERENCIADO_PELO_GRUPO,
|
|
'GRUPOS_RESPONSAVEIS' VALUE GRUPOS_RESPONSAVEIS,
|
|
'GRUPO_RESPONSAVEL' VALUE GRUPO_RESPONSAVEL,
|
|
'EDR' VALUE EDR,
|
|
'TENABLE' VALUE TENABLE,
|
|
'SIEM' VALUE SIEM,
|
|
'APPLIANCE' VALUE APPLIANCE
|
|
) AS my_json
|
|
INTO v_customer_data
|
|
FROM v_26ai_tech a
|
|
WHERE cid = p_rowid;
|
|
|
|
v_response := FNC_26ai_rag( p_ai_prompt => v_pre_prompt || '. Dados: ' || v_customer_data,
|
|
p_oci_cred => p_oci_cred,
|
|
p_comp => p_comp
|
|
);
|
|
|
|
v_json := replace( replace( FNC_26ai_rag( p_ai_prompt => 'MODO JSON: ' || v_pre_prompt || ' ' || v_pre_prompt_json || '. Dados: ' || v_customer_data,
|
|
p_oci_cred => p_oci_cred,
|
|
p_comp => p_comp
|
|
) ,'```json','' ),'```','' );
|
|
|
|
UPDATE TB_26AI_TECH_v2
|
|
SET insight_report = v_response,
|
|
insight_json = v_json
|
|
WHERE rowid = p_rowid;
|
|
|
|
ELSIF p_source_type = 'SYS' THEN -- SYSLOG
|
|
|
|
v_pre_prompt :='Voce e um Assistente de Decisao Operacional especializado em interpretacao de eventos Syslog
|
|
gerados por servidores Linux que executam bancos de dados Oracle.
|
|
|
|
Seu objetivo e apoiar equipes de operacao, banco de dados, infraestrutura e seguranca a responder, de forma pratica e rastreavel,
|
|
perguntas como:
|
|
- Diante de um alarme, ocorrencia ou evento operacional, qual acao imediata e recomendada?
|
|
- Existe historico parecido nos dados recuperados?
|
|
- Qual procedimento operacional se aplica?
|
|
- Quando o caso deve ser escalado para DBA, infraestrutura, redes, seguranca, armazenamento ou gestao de crise?
|
|
- Qual evidencia do Syslog sustenta a recomendacao?
|
|
|
|
Esquema dos dados:
|
|
- `id`: identificador sequencial do evento no CSV.
|
|
- `timestamp`: data e hora do evento em formato ISO com fuso horario.
|
|
- `host`: servidor que gerou o evento.
|
|
- `facility`: origem Syslog, como `daemon`, `local0`, `kern`, `authpriv` ou `cron`.
|
|
- `severity`: severidade Syslog, como `info`, `notice`, `warning`, `err` ou `crit`.
|
|
- `process`: processo que registrou o evento, como `oracle`, `tnslsnr`, `rman`, `systemd`, `kernel`, `multipathd`, `crsd`, `cssd`, `oraagent`, `ora_lgwr_*`, `ora_arc*`, `ora_mrp*`, `ora_rfs*`.
|
|
- `pid`: identificador do processo.
|
|
- `oracle_instance`: instancia Oracle relacionada, como `PROD`, `STBY` ou `RAC1`.
|
|
- `message`: mensagem operacional normalizada.
|
|
- `raw_syslog`: linha Syslog original ou aproximada.
|
|
|
|
Contexto operacional esperado:
|
|
- `PROD` representa uma instancia Oracle primaria de producao.
|
|
- `STBY` representa uma instancia standby/Data Guard.
|
|
- `RAC1` representa um ambiente Oracle RAC/Clusterware.
|
|
- Eventos de `tnslsnr` estao associados ao listener Oracle e conectividade de clientes.
|
|
- Eventos de `rman` indicam operacoes de backup e recuperacao.
|
|
- Eventos `ora_arc*` indicam arquivamento de redo logs.
|
|
- Eventos `ora_lgwr*`, `ora_dbw*`, `ora_ckpt*` indicam processos criticos da instancia Oracle.
|
|
- Eventos `ora_mrp*` e `ora_rfs*` indicam replicacao/aplicacao de redo no standby.
|
|
- Eventos `crsd`, `cssd`, `ohasd` e `oraagent` indicam componentes de Oracle Clusterware/RAC.
|
|
- Eventos `kernel`, `multipathd`, `NetworkManager`, `systemd`, `chronyd`, `sshd`, `sudo` e `CROND` representam dependencias do sistema operacional, armazenamento, rede, tempo, acesso e automacao.
|
|
|
|
Regras de interpretacao:
|
|
1. Use prioritariamente os trechos recuperados pelo RAG. Nao invente eventos, historicos ou procedimentos que nao estejam sustentados pelo contexto.
|
|
2. Quando houver pouca evidencia, declare explicitamente a lacuna e indique quais dados adicionais seriam necessarios.
|
|
3. Classifique a criticidade operacional considerando `severity`, processo, instancia, mensagem, impacto potencial e recorrencia.
|
|
4. Diferencie eventos informativos de eventos que exigem acao.
|
|
5. Para eventos `err` ou `crit`, sempre avaliar impacto, acao imediata e escalacao.
|
|
6. Para eventos `warning`, avaliar tendencia, recorrencia e risco de evolucao para indisponibilidade.
|
|
7. Para eventos `info` ou `notice`, considerar se fazem parte de recuperacao, normalizacao ou sequencia posterior a uma falha.
|
|
8. Nunca recomendar comandos destrutivos ou mudancas irreversiveis sem etapa previa de validacao.
|
|
9. Quando sugerir comandos, priorize comandos de diagnostico, leitura e coleta de evidencia.
|
|
10. Use linguagem objetiva, orientada a operacao, sem excesso de explicacao teorica.
|
|
|
|
Padroes relevantes para decisao:
|
|
- `ORA-00600`: erro interno Oracle. Tratar como criticidade alta ou critica. Recomendar coleta de alert log, trace, incidente ADRCI e escalacao para DBA/fornecedor.
|
|
- `ORA-00257`: erro de archiver/FRA cheia. Tratar como risco direto de bloqueio de conexoes e indisponibilidade. Recomendar liberar espaco, validar archivelogs, backup RMAN e destino de archive.
|
|
- `RMAN-03009`: falha de backup. Recomendar verificar canal, destino, espaco, permissao, catalogo e janela de backup.
|
|
- `ORA-01034`: instancia Oracle indisponivel. Recomendar validar status da instancia, listener, alert log e servico systemd.
|
|
- `TNS-12535`: timeout de listener/conectividade. Recomendar validar rede, firewall, listener, carga e origem do cliente.
|
|
- `ORA-00060`: deadlock. Recomendar identificar sessoes/SQL envolvidos, avaliar aplicacao e recorrencia antes de escalar.
|
|
- `CRS-5017` ou falha de recurso RAC: avaliar Clusterware, recursos, logs do CRS e impacto no servico.
|
|
- Latencia em `LGWR`, `DBWR`, voting file, disco ou multipath: avaliar armazenamento, I/O, SAN, filesystem, ASM e impacto em performance.
|
|
- Eventos de Data Guard como gap, espera por sequencia, MRP/RFS: avaliar atraso de replicacao, transporte e aplicacao de redo.
|
|
- Eventos de memoria/cgroup/kernel: avaliar risco de OOM, consumo por instancia e limites de sistema.
|
|
- Eventos de `sudo`, `sshd` e autenticacao: correlacionar com mudancas operacionais ou incidentes de seguranca.
|
|
|
|
Tarefa:
|
|
Gere um report de decisao operacional com base na pergunta do usuario e no contexto recuperado.
|
|
|
|
Formato obrigatorio da resposta:
|
|
1. Resumo executivo
|
|
- Informe em 2 a 4 frases o que ocorreu, qual ativo/instancia foi afetado e qual o nivel de risco operacional.
|
|
2. Evidencias encontradas no Syslog
|
|
- Liste os eventos mais relevantes.
|
|
- Para cada evidencia, inclua `id`, `timestamp`, `host`, `oracle_instance`, `severity`, `process` e a mensagem.
|
|
- Se o contexto nao trouxer evidencia suficiente, diga isso explicitamente.
|
|
3. Interpretacao operacional
|
|
- Explique o significado provavel do evento no contexto Oracle/Linux.
|
|
- Indique se o evento parece isolado, recorrente, parte de uma sequencia de falha ou parte de recuperacao.
|
|
4. Acao recomendada
|
|
- Liste a acao imediata recomendada.
|
|
- Priorize contencao, diagnostico e reducao de impacto.
|
|
- Separe claramente o que deve ser feito agora do que deve ser tratado como analise posterior.
|
|
5. Procedimento aplicavel
|
|
- Indique o procedimento operacional mais adequado, por exemplo:
|
|
- verificar alert log Oracle;
|
|
- validar listener;
|
|
- validar servico systemd;
|
|
- checar FRA/archive logs;
|
|
- validar backup RMAN;
|
|
- investigar storage/multipath;
|
|
- investigar Data Guard;
|
|
- investigar Clusterware/RAC;
|
|
- acionar seguranca para eventos de autenticacao suspeitos.
|
|
6. Confianca da recomendacao
|
|
- Informe `Alta`, `Media` ou `Baixa`.
|
|
- Justifique com base na quantidade e qualidade das evidencias recuperadas.
|
|
Regras finais:
|
|
- Responda em portugues do Brasil.
|
|
- Seja objetivo e operacional.
|
|
- Nao omita risco quando houver `err`, `crit`, `ORA-*`, `RMAN-*`, `CRS-*`, falha de disco, latencia de I/O, falha de listener, Data Guard gap ou falha de servico.
|
|
- Nao declare causa raiz definitiva sem evidencia suficiente.
|
|
- Sempre diferencie fato observado, inferencia e recomendacao.';
|
|
|
|
v_pre_prompt_json := '## FORMATO DE SAIDA JSON
|
|
Quando solicitado no modo JSON, responda EXCLUSIVAMENTE com o objeto JSON
|
|
valido conforme o schema abaixo, sem texto antes ou depois, sem markdown,
|
|
sem blocos de codigo. O JSON deve ser parseable diretamente.
|
|
Campos nao avaliaveis por qualidade de imagem devem receber null.
|
|
Nao inclua explicacoes, texto introdutorio, saudacoes ou blocos de Markdown como "```json" no comeco nem no final como "```".
|
|
|
|
## Exemplo JSON:
|
|
Retorne um JSON valido (sem comentarios), espelhando o relatorio:
|
|
{
|
|
"tipo_relatorio": "decisao_operacional_syslog_oracle_linux",
|
|
"versao_schema": "1.0",
|
|
"fonte_dados": {
|
|
"arquivo_csv": "syslog_oracle_linux_examples.csv",
|
|
"mecanismo": "RAG",
|
|
"modelo_destino": "Llama 4",
|
|
"campos_csv": [
|
|
"id",
|
|
"timestamp",
|
|
"host",
|
|
"facility",
|
|
"severity",
|
|
"process",
|
|
"pid",
|
|
"oracle_instance",
|
|
"message",
|
|
"raw_syslog"
|
|
]
|
|
},
|
|
"classificacao_evento": {
|
|
"nivel_risco": "Baixo|Medio|Alto|Critico",
|
|
"severidade_syslog": "info|notice|warning|err|crit",
|
|
"categoria": "Banco de dados|Sistema operacional|Rede|Storage|Seguranca|Backup|Data Guard|RAC|Autenticacao",
|
|
"impacto_potencial": "Descrever impacto operacional provavel",
|
|
"estado": "Informativo|Em investigacao|Acao requerida|Escalado|Resolvido"
|
|
},
|
|
"resumo_executivo": {
|
|
"descricao": "Resumo em 2 a 4 frases do evento ou alarme analisado",
|
|
"ativo_afetado": {
|
|
"host": "Nome do servidor afetado",
|
|
"oracle_instance": "Instancia Oracle afetada",
|
|
"processo": "Processo principal relacionado ao evento"
|
|
},
|
|
"risco_operacional": "Descricao objetiva do risco",
|
|
"recomendacao_curta": "Acao recomendada em uma frase"
|
|
},
|
|
"evidencias_syslog": [
|
|
{
|
|
"id": 0,
|
|
"timestamp": "YYYY-MM-DDTHH:MM:SS-03:00",
|
|
"host": "host_origem",
|
|
"facility": "facility_syslog",
|
|
"severity": "severity_syslog",
|
|
"process": "processo_origem",
|
|
"pid": 0,
|
|
"oracle_instance": "instancia_oracle",
|
|
"message": "mensagem_normalizada",
|
|
"raw_syslog": "linha_syslog_original",
|
|
"relevancia": "Alta|Media|Baixa"
|
|
}
|
|
],
|
|
"interpretacao_operacional": {
|
|
"fato_observado": "O que foi observado diretamente no Syslog",
|
|
"inferencia": "Interpretacao operacional baseada nas evidencias",
|
|
"possivel_causa": "Hipotese provavel, sem declarar causa raiz definitiva sem evidencia",
|
|
"sequencia_eventos": "Evento isolado, sequencia de falha, recuperacao ou recorrencia",
|
|
"recorrencia": "Isolado|Recorrente|Sequencia de falha|Recuperacao|Indeterminado"
|
|
},
|
|
"acoes_recomendadas": {
|
|
"imediatas": [
|
|
{
|
|
"prioridade": 1,
|
|
"acao": "Acao imediata recomendada",
|
|
"objetivo": "Resultado esperado da acao",
|
|
"responsavel_sugerido": "Operacao N1|Operacao N2|DBA Oracle|Linux/Infraestrutura|Storage|Redes|Seguranca|Sustentacao de Aplicacao|Gestao de Crise"
|
|
}
|
|
]
|
|
}';
|
|
|
|
SELECT json_object(
|
|
'ID_1' VALUE a."ID_1",
|
|
'ID' VALUE a."ID",
|
|
'TIMESTAMP' VALUE a."TIMESTAMP",
|
|
'HOST' VALUE a."HOST",
|
|
'FACILITY' VALUE a."FACILITY",
|
|
'SEVERITY' VALUE a."SEVERITY",
|
|
'PROCESS' VALUE a."PROCESS",
|
|
'PID' VALUE a."PID",
|
|
'ORACLE_INSTANCE' VALUE a."ORACLE_INSTANCE",
|
|
'MESSAGE' VALUE a."MESSAGE",
|
|
'RAW_SYSLOG' VALUE a."RAW_SYSLOG"
|
|
) AS my_json
|
|
INTO v_customer_data
|
|
FROM "TB_26AI_TECH_SYS" a
|
|
WHERE rowid = p_rowid;
|
|
|
|
v_response := FNC_26ai_rag( p_ai_prompt => v_pre_prompt || '. Dados: ' || v_customer_data,
|
|
p_oci_cred => p_oci_cred,
|
|
p_comp => p_comp
|
|
);
|
|
|
|
UPDATE TB_26AI_TECH_SYS
|
|
SET insight_report = v_response,
|
|
insight_json = v_json
|
|
WHERE rowid = p_rowid;
|
|
|
|
END IF;
|
|
|
|
|
|
IF length(v_response) > 0 THEN
|
|
|
|
-- vetorizacao do relatorio gerado
|
|
INSERT INTO TB_26AI_TECH_VECTOR
|
|
SELECT et.embed_id,
|
|
v_response,
|
|
et.embed_vector,
|
|
null,
|
|
p_rowid,
|
|
p_source_type
|
|
FROM dual
|
|
CROSS JOIN TABLE(
|
|
DBMS_VECTOR_CHAIN.UTL_TO_EMBEDDINGS(
|
|
( v_response ) ,
|
|
json('{ "provider": "ocigenai",
|
|
"credential_name": "' || p_oci_cred || '",
|
|
"url": "https://inference.generativeai.' || v_genai_region || '.oci.oraclecloud.com/20231130/actions/embedText",
|
|
"model": "cohere.embed-v4.0"
|
|
}')
|
|
)
|
|
) t
|
|
CROSS JOIN JSON_TABLE(
|
|
t.column_value, '$[*]'
|
|
COLUMNS (
|
|
embed_id NUMBER PATH '$.embed_id',
|
|
text_chunk VARCHAR2(4000) PATH '$.embed_data',
|
|
embed_vector CLOB PATH '$.embed_vector'
|
|
)
|
|
) AS et;
|
|
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'PRC_26AI_TECH',
|
|
p_operation => 'EMBEDDING',
|
|
p_status => 'OK',
|
|
p_source_type => p_source_type,
|
|
p_source_id => p_rowid,
|
|
p_provider => 'ocigenai',
|
|
p_model_name => 'cohere.embed-v4.0',
|
|
p_prompt_chars => LENGTH(v_response)
|
|
);
|
|
|
|
END IF;
|
|
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'PRC_26AI_TECH',
|
|
p_operation => 'INSIGHT_PIPELINE',
|
|
p_status => 'OK',
|
|
p_source_type => p_source_type,
|
|
p_source_id => p_rowid
|
|
);
|
|
|
|
COMMIT;
|
|
|
|
EXCEPTION
|
|
WHEN OTHERS THEN
|
|
v_error := sqlerrm;
|
|
PRC_26AI_TECH_LOG(
|
|
p_calling_object => 'PRC_26AI_TECH',
|
|
p_operation => 'INSIGHT_PIPELINE',
|
|
p_status => 'ERROR',
|
|
p_source_type => p_source_type,
|
|
p_source_id => p_rowid,
|
|
p_error_code => SQLCODE,
|
|
p_error_message => v_error
|
|
);
|
|
-- Antes, o erro tecnico (sqlerrm) era gravado direto em insight_report e
|
|
-- ficava visivel pro usuario de negocio no modal. Agora o erro completo
|
|
-- vai so pro log (TB_26AI_TECH_LOG); o usuario ve uma mensagem amigavel.
|
|
IF p_source_type = 'VUL' THEN
|
|
UPDATE TB_26AI_TECH_v2
|
|
SET insight_report = 'Nao foi possivel gerar o insight para este registro no momento.',
|
|
insight_json = null
|
|
WHERE rowid = p_rowid;
|
|
ELSIF p_source_type = 'SYS' THEN
|
|
UPDATE TB_26AI_TECH_SYS
|
|
SET insight_report = 'Nao foi possivel gerar o insight para este registro no momento.',
|
|
insight_json = null
|
|
WHERE rowid = p_rowid;
|
|
END IF;
|
|
COMMIT;
|
|
END;
|
|
/
|
|
|
|
-- VALIDACAO: confere que todos os objetos desta secao compilaram sem erro
|
|
-- antes de seguir para a instalacao do APEX. Nao vale so olhar se o CREATE
|
|
-- "rodou sem erro na tela" - PL/SQL pode compilar um objeto que chama outro
|
|
-- ainda inexistente sem acusar erro na hora (resolucao adiada de nomes); o
|
|
-- STATUS aqui e a fonte de verdade.
|
|
SELECT object_name, object_type, status
|
|
FROM user_objects
|
|
WHERE object_name IN ('TB_26AI_TECH_LOG','PRC_26AI_TECH_LOG','FNC_26AI_EMBED',
|
|
'FNC_26AI_TECH_RAG','FNC_26AI_RAG','PRC_26AI_TECH')
|
|
ORDER BY object_name;
|
|
-- As 6 linhas tem que aparecer com STATUS = VALID. Se alguma faltar, o
|
|
-- CREATE dela nao rodou (role a secao de novo); se aparecer INVALID, rode
|
|
-- para descobrir o motivo:
|
|
-- SELECT line, position, text FROM user_errors WHERE name = '<NOME_DO_OBJETO>' ORDER BY sequence;</code></pre>
|
|
</div>
|
|
<h2>Seção 8 · Instalar a aplicacao APEX (ampmInsights)</h2>
|
|
<p>Últimos passos, agora fora do SQL Worksheet: instalar a aplicação APEX. Detalhado em
|
|
<a href="05-passo-a-passo-apex.html">Passo a passo: aplicação APEX</a>.</p>
|
|
<div class="code-block">
|
|
<div class="code-bar">
|
|
<span class="code-label">Seção 8 — copiar e colar</span>
|
|
<button class="copy-btn" type="button">Copiar</button>
|
|
</div>
|
|
<pre><code class="lang-sql">-- etapa 1) Criar um workspace APEX (ou reutilizar um existente).
|
|
-- etapa 2) Acessar o workspace usando o usuario de banco AMPMINSIGHTS criado
|
|
-- na SECAO 1 (App Builder > associar o schema AMPMINSIGHTS ao
|
|
-- workspace, se ainda nao estiver associado).
|
|
-- etapa 3) Fazer upload do arquivo 02_ampminsights_apex_app.sql (instalacao
|
|
-- da aplicacao). Confirmar que o "parsing schema" e AMPMINSIGHTS.
|
|
-- Confirmar "Run and Build".
|
|
-- etapa 4) Executar a aplicacao (logar com um usuario criado dentro da
|
|
-- propria aplicacao, ou com o esquema de autenticacao configurado).
|
|
-- etapa 5) Carregar os dados de CMDB (ativos/servidores).
|
|
-- etapa 6) Carregar os dados de vulnerabilidades.
|
|
-- etapa 7) Iniciar o processo de geracao de relatorios (insights) e
|
|
-- vetorizacao (botao "Gerar Insights em Lote" na aplicacao, que cria
|
|
-- um job via DBMS_SCHEDULER usando os parametros da SECAO 2).
|
|
--
|
|
-- Veja o passo a passo detalhado, com telas e checklist, em:
|
|
-- docs/05-passo-a-passo-apex.html</code></pre>
|
|
</div>
|
|
<div class="callout success">
|
|
<div class="callout-title">Terminou o script 1?</div>
|
|
<p>Siga para <a href="05-passo-a-passo-apex.html">Passo a passo: aplicação APEX</a> para importar
|
|
<code>sql/02_ampminsights_apex_app.sql</code>.</p>
|
|
</div>
|
|
|
|
<div class="pillnav"><a class="prev" href="03-pre-requisitos-credenciais.html">← Pré-requisitos & credenciais</a><a class="next" href="05-passo-a-passo-apex.html">Passo a passo: aplicação APEX →</a></div>
|
|
</main>
|
|
</div>
|
|
<script src="assets/main.js"></script>
|
|
</body>
|
|
</html>
|