diff --git a/pkg_26ai_traffic_load.sql b/pkg_26ai_traffic_load.sql new file mode 100644 index 0000000..9764269 --- /dev/null +++ b/pkg_26ai_traffic_load.sql @@ -0,0 +1,57 @@ +create or replace package PKG_26AI_TRAFFIC_LOAD +as +/* + + Criado por: fernando.leal@oracle.com + Data: Abril/2026 + Objetivo: Identificar informacoes de imagens como placas, modelo do veiculo e infracoes (uso de celular) + + v1 - Traffic Load - leal + +*/ + + -- + -- chamada a API do Vision. Definir modo de extracao com p_feature_type + -- + function fnc_26ai_traffic_vision( p_base64_image in clob, + p_feature_type in varchar2 , + p_comp_id in varchar2) + return clob; + + -- + -- funcao de rag para extracao de informacoes da imagem + -- + function fnc_26ai_traffic_rag (p_base64_image IN clob, + p_oci_cred IN VARCHAR2, + p_comp_id in varchar2) + return clob; + + PROCEDURE prc_refresh_files(p_oci_cred IN VARCHAR2 default 'OCI_CRED', + p_bucket in varchar2 default null, + p_mimetype in varchar2 default 'PNG', + p_embedding_name in varchar2 default 'COHERE'); + + PROCEDURE prc_reserve_files ( + p_limit IN NUMBER, + p_worker_id IN VARCHAR2, + p_oci_cred IN VARCHAR2 default 'OCI_CRED', + p_bucket in varchar2 , + p_docs OUT SYS.ODCIVARCHAR2LIST, + p_mimetype in varchar2 default 'PNG', + p_embedding_name in varchar2 default 'COHERE' ) ; + + PROCEDURE proc_process_files(p_limit in number default 10, + p_worker_id in number, + p_stop_process_list in varchar2 default 'N', + p_mimetype in varchar2 default 'PNG', + p_embedding_name in varchar2 default 'COHERE'); + + PROCEDURE proc_remove_jobs; + + PROCEDURE proc_add_jobs(p_limit in number, + p_total_jobs in number, + p_mimetype in varchar2 default 'PNG', + p_embedding_name in varchar2 default 'COHERE'); + +end; +/ \ No newline at end of file diff --git a/prc_26ai_access_control.sql b/prc_26ai_access_control.sql new file mode 100644 index 0000000..61fe0e2 --- /dev/null +++ b/prc_26ai_access_control.sql @@ -0,0 +1,198 @@ +create or replace procedure prc_26ai_access_control +as + v_workspace varchar2(20) := 'AICHAT1'; + v_default_schema varchar2(20) := 'AICHAT1'; + v_app_alias varchar2(20) := '26ai Demo Hub'; + + v_workspace_id number ; + v_role_id varchar2(200) := '48398609518762455:48398772342762456'; -- CUIDADO, checar em APEX_APPL_ACL_USERS apos definicao de um user manualmente + v_error varchar2(4000); + v_has number; +begin + +/* + Criado por: fernando.leal@oracle.com + Data: Nov/2025 + Objetivo: agendar rotina para criacao de usuarios no APEX. + Em telas publicas ainda nao logadas nao é permitido usar este tipo de rotina, por isso, sera assincrona. + + v1 - rotina para criacao de APEX user assincrono - leal + + +-- CUIDADO: requer JOB de banco: +-- CUIDADO: job deve estar associado ao ADMIN em funcao da permissao de criar novo usuario + +BEGIN + DBMS_SCHEDULER.create_job ( + job_name => 'job_26ai_access_control', + job_type => 'PLSQL_BLOCK', + job_action => 'begin aichat1.prc_26ai_access_control; end;', + start_date => sysdate, + repeat_interval => 'freq=secondly;', + enabled => TRUE); +END; + +-- Pagina 9999 possui comandos de controle sobre tabela tb_26ai_access_control + +*/ + + -- Descobrir o ID do workspace onde está a credencial + SELECT workspace_id + into v_workspace_id + FROM apex_workspaces + WHERE workspace = v_workspace; + + -- Ativar o contexto APEX + -- CUIDADO pois esta sendo executado via rotina de banco, e nao via APEX, por isso, o contexto do workspace + apex_util.set_security_group_id(v_workspace_id); + + -- para casos com recriacao do user / reset + for r1 in (select * + from tb_26ai_access_control + where CREATED_STATUS = 'E' ) loop + + begin + APEX_UTIL.REMOVE_USER( p_user_name => r1.USERNAME ); + exception + when others then + null; + end; + + APEX_UTIL.CREATE_USER( + p_user_name => r1.USERNAME, + p_email_address => lower(r1.EMAIL), + p_web_password => r1.INITIAL_PWD, + p_change_password_on_first_use => 'Y', -- cuidado + p_default_schema => v_default_schema + ); + + begin + + delete APEX_APPL_ACL_USERS + where USER_NAME_LC = lower(r1.USERNAME); + + insert into APEX_APPL_ACL_USERS(WORKSPACE_ID, + WORKSPACE, + WORKSPACE_DISPLAY_NAME, + APPLICATION_ID, + APPLICATION_NAME, + WORKING_COPY_NAME, + USER_NAME, + USER_NAME_LC, + ROLE_IDS, + ROLE_NAMES) + values(v_workspace_id, --:WORKSPACE_ID, + v_workspace, + v_workspace, + r1.app_id, --:APP_ID, + v_app_alias, -- :APP_ALIAS, + null, + r1.USERNAME, + lower(r1.USERNAME), + v_role_id, + 'Contributor, Reader'); + + + /* + ou + + -- Atribui role no app destino + apex_acl.add_user_role( + p_application_id => r.id, + p_user_name => r.user_name, + p_role_static_id => r.role_static_id + ); + + */ + + exception + when others then + null; + end; + + update tb_26ai_access_control + set CREATED_STATUS = 'Y' + where USERNAME = r1.USERNAME + and CREATED_STATUS = 'E'; -- cuidado + + end loop; + + + for r1 in (select * + from tb_26ai_access_control + where CREATED_STATUS = 'N' ) loop + + begin + + --- begin + --- APEX_UTIL.REMOVE_USER( p_user_name => r1.USERNAME ); + -- exception + -- when others then + -- null; + --- end; + + select count(1) + into v_has + from APEX_APPL_ACL_USERS + where USER_NAME_LC = lower(r1.USERNAME); + + if v_has = 0 then + + APEX_UTIL.CREATE_USER( + p_user_name => r1.USERNAME, + p_email_address => lower(r1.EMAIL), + p_web_password => r1.INITIAL_PWD, + p_change_password_on_first_use => 'Y', -- cuidado + p_default_schema => v_default_schema + ); + + begin + insert into APEX_APPL_ACL_USERS(WORKSPACE_ID, + WORKSPACE, + WORKSPACE_DISPLAY_NAME, + APPLICATION_ID, + APPLICATION_NAME, + WORKING_COPY_NAME, + USER_NAME, + USER_NAME_LC, + ROLE_IDS, + ROLE_NAMES) + values(v_workspace_id, --:WORKSPACE_ID, + v_workspace, + v_workspace, + r1.app_id, --:APP_ID, + v_app_alias, -- :APP_ALIAS, + null, + r1.USERNAME, + lower(r1.USERNAME), + v_role_id, + 'Contributor, Reader'); + exception + when others then + null; + end; + + update tb_26ai_access_control + set CREATED_STATUS = 'Y' + where USERNAME = r1.USERNAME + and CREATED_STATUS = 'N'; + + end if; + + exception + when others then + v_error := sqlerrm; + + update tb_26ai_access_control + set CREATED_STATUS = v_error + where USERNAME = r1.USERNAME + and CREATED_STATUS = 'N'; + + end; + + end loop; + + commit; + +end; +/ \ No newline at end of file diff --git a/prc_26ai_backup_demohub.sql b/prc_26ai_backup_demohub.sql new file mode 100644 index 0000000..ee7782e --- /dev/null +++ b/prc_26ai_backup_demohub.sql @@ -0,0 +1,109 @@ +create or replace procedure prc_26ai_backup_demohub( p_only_replicate in varchar2 default 'N') +authid current_user +as + v_file_name varchar2(200) := '26ai_demohub' || to_char(sysdate,'ddmmrrrr'); + v_bucket varchar2(500) := 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-database-26ai/o/'; + v_backup_start date; + h1 NUMBER; +BEGIN +/* + + Criado por: fernando.leal@oracle.com + Data: Oct/2025 + Objetivo: backup da base de dados do 26ai DemoHub + + v1 - leal + + Requer Scheduler de banco criado para executar 1x por semana (criado sob owner ADMIN) + + 1- (aichat1) GRANT INHERIT PRIVILEGES ON USER AICHAT1 TO ADMIN; + (admin) GRANT INHERIT PRIVILEGES ON USER ADMIN TO AICHAT1; + + 2- + BEGIN + DBMS_SCHEDULER.create_job ( + job_name => 'job_26ai_backup_logico', + job_type => 'PLSQL_BLOCK', + job_action => 'begin aichat1.prc_26ai_backup_demohub; end;', + start_date => sysdate, + repeat_interval => 'freq=weekly;', + enabled => TRUE); +END; + +*/ + v_backup_start := sysdate; + + if p_only_replicate = 'N' then + + -- Open the export job + h1 := DBMS_DATAPUMP.OPEN( + operation => 'EXPORT', + job_mode => 'SCHEMA', + job_name => 'AICHAT_EXPORT_' || to_char(sysdate,'rrrrmmddhh24miss') || '_' || v_file_name, + version => 'LATEST' + ); + + -- Specify the dump file destination + DBMS_DATAPUMP.ADD_FILE( + handle => h1, + filename => v_file_name || '.dmp', + directory => 'DATA_PUMP_DIR', + filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_DUMP_FILE, + reusefile => 1 + ); + + -- Specify the log file destination + DBMS_DATAPUMP.ADD_FILE( + handle => h1, + filename => v_file_name || '.log', + directory => 'DATA_PUMP_DIR', + filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE, + reusefile => 1 + ); + + -- Export only the GUEST schema + DBMS_DATAPUMP.METADATA_FILTER( + handle => h1, + name => 'SCHEMA_EXPR', + value => 'IN (''AICHAT1'')' + ); + + -- Start and detach + DBMS_DATAPUMP.START_JOB(h1); + DBMS_DATAPUMP.DETACH(h1); + + insert into aichat1.tb_26ai_backup_log + values ( v_backup_start, sysdate, v_file_name || '.dmp' , v_file_name || '.log', v_bucket, 'latinoamerica'); + + commit; + + -- replicacao do arquivo para object storage + elsif p_only_replicate = 'Y' then + + DBMS_CLOUD.PUT_OBJECT(credential_name => 'OCI_CRED', + object_uri => v_bucket, + directory_name => 'DATA_PUMP_DIR', + file_name => v_file_name || '.dmp'); + + DBMS_CLOUD.PUT_OBJECT(credential_name => 'OCI_CRED', + object_uri => v_bucket, + directory_name => 'DATA_PUMP_DIR', + file_name => v_file_name || '.log'); + + -- remove o arquivo temporario armazenado no DATA_PUMP_DIR + DBMS_CLOUD.DELETE_FILE( + directory_name => 'DATA_PUMP_DIR', + file_name => v_file_name || '.dmp' + ); + -- remove o arquivo temporario armazenado no DATA_PUMP_DIR + DBMS_CLOUD.DELETE_FILE( + directory_name => 'DATA_PUMP_DIR', + file_name => v_file_name || '.log' + ); + + end if; + + + +END; +/ \ No newline at end of file diff --git a/prc_26ai_food.sql b/prc_26ai_food.sql new file mode 100644 index 0000000..82fb09a --- /dev/null +++ b/prc_26ai_food.sql @@ -0,0 +1,21 @@ +create or replace procedure prc_26ai_food( p_image_id in number, + p_comp_id in varchar2, + p_credential in varchar2 default 'OCI_CRED', + p_kcal out varchar2) +as +/* + + Criado por: fernando.leal@oracle.com + Data: Oct/2025 + Objetivo: demonstrar casos de uso de Food & Nutrition + + v1 - Food & Nutrition leal + +*/ +begin + + p_kcal := fnc_26ai_rag_food('retorne o total de calorias desta refeição, sem trazer nenhuma informação extra nem complmenetar.' || + 'Não adicione nenhum dados além do total de calorias.' , p_credential, p_image_id, p_comp_id ); + +end; +/ \ No newline at end of file diff --git a/prc_26ai_health_hemograma.sql b/prc_26ai_health_hemograma.sql new file mode 100644 index 0000000..34dcb4e --- /dev/null +++ b/prc_26ai_health_hemograma.sql @@ -0,0 +1,104 @@ +create or replace procedure prc_26ai_health_hemograma( p_id in number, + p_comp_id in varchar2, + p_credential in varchar2 default 'OCI_CRED') +as +/* + + Criado por: fernando.leal@oracle.com + Data: Dez/2025 + Objetivo: demonstrar casos de uso do Oracle AI Database 26ai + + v1 - extrair chunks do hemograma para viabilizar a execucao da funcao de RAG. Tabela TMP: TB_26AI_HEALTH_HEMOGRAMA_TMP + +*/ + v_hemograma clob := empty_clob(); + v_chunk VARCHAR2(32767); + v_offset INTEGER := 1; + v_chunk_size CONSTANT INTEGER := 10000; -- 10 KB + v_length INTEGER; + v_has number; +begin + + select count(1) + into v_has + from TB_26AI_HEALTH_HEMOGRAMA_TMP + where id = p_id; + + if v_has = 0 then + + select replace(replace(replace(replace( dbms_vector_chain.utl_to_text( dt.file_content ) ,chr(10),' '),chr(13),' '),'"',''),'''','') + into v_hemograma + from TB_26AI_HEALTH_HEMOGRAMA dt + where id = p_id; + + -- Tamanho total do texto + v_length := dbms_lob.getlength(v_hemograma); + + -- Loop em blocos de 10KB + WHILE v_offset <= v_length LOOP + + v_chunk := dbms_lob.substr( + v_hemograma, + v_chunk_size, + v_offset + ); + + insert into TB_26AI_HEALTH_HEMOGRAMA_TMP + WITH dados AS ( + SELECT FNC_26ai_RAG( + '##Você é um sistema de extração de dados laboratoriais. + ##Tarefa: + A partir do texto bruto de um laudo de exames laboratoriais, extraia SOMENTE os exames realizados e seus respectivos valores numéricos com unidades. + ##Regras obrigatórias: + 1. Retorne exclusivamente um objeto JSON, e nunca use Markdown como ```json . + 2. Cada chave deve ser o nome do exame (em português, da mesma maneira que esta no hemograma original). + 3. Cada valor deve conter apenas o valor do exame + unidade, exatamente como apresentado no laudo. + 4. Ignore completamente: + - Intervalos de referência + - Percentuais quando houver valor absoluto equivalente (priorize o valor absoluto) + - Dados do paciente, médicos, datas, assinaturas, métodos, gráficos, observações, textos legais e administrativos + - Repetições do mesmo exame (considere apenas o resultado mais recente) + 5. Não faça interpretações clínicas. + 6. Não normalize valores nem converta unidades. + 7. Não inclua textos explicativos. + 8. Não agrupe exames — cada exame deve ser uma entrada independente. + 9. Caso um exame possua mais de uma medida válida (ex: percentual e absoluto), utilize o valor absoluto com unidade. + ##Formato de saída (exemplo): + { + "exames": [ + ["eritrocitos", "4,65 10^6/µL"], + ["hemoglobina", "14,8 g/dL"], + ["hematocrito", "43,8 %"], + ["vcm", "94,3 fL"] + ... + ] + } + ##Texto de entrada:' || v_chunk, p_credential, p_comp_id ) json_text + ) + SELECT + p_id, + v('APP_SESSION'), + current_timestamp, + v_chunk, + jt.exame_nome, + jt.exame_valor + FROM dados d, + JSON_TABLE( + d.json_text, + '$.exames[*]' + COLUMNS ( + exame_nome VARCHAR2(100) PATH '$[0]', + exame_valor VARCHAR2(100) PATH '$[1]' + ) + ) jt; + + v_offset := v_offset + v_chunk_size; + + END LOOP; + + end if; -- if v_has = 0 then + +commit; + +end; +/ \ No newline at end of file