Depois de uma sessao de troubleshooting real (schema errado, tipo de OCID errado, credencial com valor velho, Application Settings do APEX desincronizadas da tabela de config), formaliza cada um desses pontos como uma checagem que roda imediatamente apos a etapa correspondente, em vez de so aparecer como sintoma bem mais tarde: - Entre Secao 1 e 2: confirma que a sessao trocou para AMPMINSIGHTS (SELECT USER FROM DUAL) antes de continuar. - Fim da Secao 2: confere que EMBEDDING_COMPARTMENT/OCI_TENANCY_OCID/ OCI_USER_OCID tem o PREFIXO de OCID certo (nao so que foram preenchidos) - pega o caso real de hoje onde o OCID do Autonomous Database foi colado no lugar do compartimento. - Fim da Secao 3: lembrete de que a credencial precisa ser recriada se EMBEDDING_COMPARTMENT mudar depois dela ja existir. - Fim da Secao 7: confere STATUS = VALID dos 6 objetos novos antes de seguir pra instalacao do APEX. - docs/09: nova secao explicando que a lupa "AI Insight" le credencial/ compartimento/regiao das Application Settings do APEX (Shared Components), nao da TB_26AI_TECH_PARAMS - as duas fontes precisam ser mantidas em sincronia manualmente. Duas linhas novas no checklist de erros comuns. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1884 lines
102 KiB
HTML
1884 lines
102 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 V1 · 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>
|
|
</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 arquivo <code>CLIP_VIT_LARGE_PATCH14_TXT.onnx</code>, já convertido e testado no formato que o
|
|
Oracle AI Database espera, está incluído neste pacote em <code>modelo-onnx/</code>. O passo 4.1 é só
|
|
localizar esse arquivo; depois é criar seu bucket e subir o arquivo (passo 4.2, via Console OCI ou
|
|
OCI CLI), e 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="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).
|
|
--
|
|
-- 4.1) O arquivo CLIP_VIT_LARGE_PATCH14_TXT.onnx já convertido e testado no
|
|
-- formato que o Oracle AI Database espera está incluído neste pacote,
|
|
-- na pasta modelo-onnx/. Basta usá-lo diretamente no passo 4.2 abaixo.
|
|
-- (Se no futuro você quiser converter um modelo HuggingFace diferente,
|
|
-- o passo a passo está logo abaixo, em "Como converter um modelo
|
|
-- ONNX" — é opcional, não é necessário para usar o arquivo já incluído
|
|
-- aqui.)
|
|
--
|
|
-- 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:
|
|
-- 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 um modelo ONNX (opcional)</h2>
|
|
<p>O arquivo incluído neste pacote (<code>modelo-onnx/CLIP_VIT_LARGE_PATCH14_TXT.onnx</code>) já
|
|
está pronto para uso — você não precisa desta seção para concluir a Seção 4. Ela fica aqui como
|
|
referência para o caso de, no futuro, você querer carregar no banco um modelo ONNX diferente.</p>
|
|
|
|
<h3>Por que um export "cru" pode não funcionar</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 pelo <code>DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD</code> com
|
|
o erro <code>ORA-54426</code>, mesmo que o arquivo abra normalmente em qualquer visualizador ONNX e
|
|
pareça válido.</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), pelo menos ~15 GB de espaço livre em disco e Docker Desktop configurado com
|
|
~10–12 GB de memória (Settings > Resources > Memory) — a conversão baixa o modelo completo
|
|
(~1,7 GB), instala <code>torch</code> e faz tracing + quantização, que usam bem mais RAM do que o
|
|
tamanho do modelo em disco.</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 ali. Montar
|
|
<code>hf-cache</code> e <code>pip-cache</code> no host também evita baixar o modelo (~1,7 GB)
|
|
de novo caso você 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>
|
|
|
|
<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.
|
|
--
|
|
-- A regiao do OCI Generative AI abaixo vem do parametro GENAI_REGION -
|
|
-- nao precisa (nem deve) ser trocada pelo valor de OCI_REGION da tabela
|
|
-- de configuracao (sao coisas diferentes de proposito), ja que o
|
|
-- servico so esta disponivel em algumas regioes especificas da OCI.
|
|
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>
|