From e3d9c06fdab92477504b8796d88133cfefa9f993 Mon Sep 17 00:00:00 2001 From: flealdba Date: Fri, 8 May 2026 13:15:19 +0000 Subject: [PATCH] Upload files to "/" --- fnc_26ai_embed.sql | 143 ++++++++++++++++++++++++ fnc_26ai_embed_image_cohere.sql | 144 ++++++++++++++++++++++++ fnc_26ai_food.sql | 192 ++++++++++++++++++++++++++++++++ fnc_26ai_health.sql | 153 +++++++++++++++++++++++++ fnc_26ai_health_hemograma.sql | 123 ++++++++++++++++++++ 5 files changed, 755 insertions(+) create mode 100644 fnc_26ai_embed.sql create mode 100644 fnc_26ai_embed_image_cohere.sql create mode 100644 fnc_26ai_food.sql create mode 100644 fnc_26ai_health.sql create mode 100644 fnc_26ai_health_hemograma.sql diff --git a/fnc_26ai_embed.sql b/fnc_26ai_embed.sql new file mode 100644 index 0000000..ca1e932 --- /dev/null +++ b/fnc_26ai_embed.sql @@ -0,0 +1,143 @@ +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 +/* + + Criado por: fernando.leal@oracle.com + Data: Oct/2025 + Objetivo: demonstrar casos de uso do Oracle AI Database 26ai + + v1 - embedding de dados com Cohere On-Demand- leal + +*/ + 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 + + /* Carga previa do ONNX ao banco (pre requisito) + BEGIN + DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD( + model_name => 'multilingual_e5_base', + credential => 'OCI_CRED', + uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-poc-rag/o/multilingual-e5-base.onnx', + metadata => JSON('{"function" : "embedding", "embeddingOutput" : "embedding" , "input": {"input": ["DATA"]}}') + ); + END; + + BEGIN + DBMS_VECTOR.DROP_ONNX_MODEL( model_name => 'paraphrase_multilingual'); + END; + + */ + + SELECT VECTOR_EMBEDDING( multilingual_e5_base 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 ), O utl_to_text 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 significa que esse processo + demorou mais que o timeout configurado e foi abortado pelo Oracle. */ + + select embed_vector + into v_embedding + from dual + CROSS JOIN TABLE( + dbms_vector_chain.utl_to_embeddings( + -- dbms_vector_chain.utl_to_chunks( + dbms_vector_chain.utl_to_text( v_string ), + -- json('{"by":"words","max":"400","overlap":40,"split":"sentence","normalize":"all"}') + -- ), + -- + -- json para cohere embedding + -- + json('{ "provider": "ocigenai", + "credential_name": "' || p_credential || '", + "url": "https://inference.generativeai.us-chicago-1.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 + + declare + params clob; + v_embedding2 vector; + begin + + -- Set host to local to disable credential + -- The provider value must specify openai + -- https://docs.oracle.com/en/database/oracle/oracle-database/26/vecse/utl_to_embedding-and-utl_to_embeddings-dbms_vector_chain.html + + params := '{ + "provider": "openai", + "url": "https://hub-gpus.DOMINIO.com.br/embed/v1/embeddings", + "host": "local", + "model": "Qwen/Qwen3-Embedding-4B", + "batch_size": 50}'; + + -- dicas: https://docs.oracle.com/en/database/oracle/oracle-database/26/vecse/utl_to_embedding-and-utl_to_embeddings-dbms_vector.html + + v_embedding2 := dbms_vector_chain.utl_to_embedding( v_string , json(params)) ; + + v_embedding := TO_CLOB(TO_CHAR( v_embedding2 ) ) ; + + -- Confirmar resultado + --DBMS_OUTPUT.PUT_LINE('Dimensões : ' || VECTOR_DIMENSION_COUNT(v_embedding)); + --DBMS_OUTPUT.PUT_LINE('Format : ' || VECTOR_DIMENSION_FORMAT(v_embedding)); + exception + when OTHERS THEN + DBMS_OUTPUT.PUT_LINE('Erro: ' || SQLCODE || ' - ' || SQLERRM); + end; + + +-- neste tenancy nao tenho o endpoint do COHERE-DEDICATED - leal 17-10-2025 +/* elsif p_emb_type = 'COHERE-DEDICATED' then + + v_body := json_object_t('{"servingMode":{"servingType":"DEDICATED", + "endpointId":"ocid1.generativeaiendpoint.oc1.sa-saopaulo-1.amaaaaaaa2b7yriam5myabesz5cyoxez4f266vx656q3lrfwe3a753y5keoq" + }, + "inputs":["' || v_string || '"], + "compartmentId":"ocid1.compartment.oc1..aaaaaaaa5ewni44wndu5nwrhbqss4jaoel742xvprjkg64kb7vt7es4utzua"} + '); + + r := dbms_cloud.send_request( + credential_name => 'OCI_CRED', + uri => v_url, + method => dbms_cloud.method_post, + body => utl_raw.cast_to_raw(v_body.to_clob), + headers => json_object('Accept' value 'application/json', 'X-Custom-Header' VALUE 'My-Custom-Value') + ); + + select jt.embeddings + into v_embedding + from dual j, + json_table( dbms_cloud.get_response_text(r), '$' columns (embeddings clob PATH '$.embeddings[*].vector()') ) jt; +*/ + end if; + + return v_embedding; + +end; +/ \ No newline at end of file diff --git a/fnc_26ai_embed_image_cohere.sql b/fnc_26ai_embed_image_cohere.sql new file mode 100644 index 0000000..19149eb --- /dev/null +++ b/fnc_26ai_embed_image_cohere.sql @@ -0,0 +1,144 @@ +create or replace FUNCTION fnc_26ai_embed_image_cohere (image_name in VARCHAR2, + image_blob in BLOB, + oci_cred IN VARCHAR2 default 'OCI_CRED', + p_comp_id in varchar2, + p_code_mode in number default 1 ) +return clob +as +/* + + Criado por: fernando.leal@oracle.com + Data: Oct/2025 + Objetivo: demonstrar casos de uso do Oracle AI Database 26ai + + v1 - embedding de imagnes com Cohere On-Demand - leal + +*/ + + -- modelos: https://docs.oracle.com/en-us/iaas/Content/generative-ai/pretrained-models.htm + -- cuidado com pre requisito (1) + gen_ai_endpoint varchar2(500) := 'https://inference.generativeai.us-chicago-1.oci.oraclecloud.com'; + gen_ai_model varchar2(500) := 'cohere.embed-v4.0'; + + embed_resp dbms_cloud_types.RESP; + + file_extension VARCHAR2(5); + base64_image CLOB := NULL; + invalid_image EXCEPTION; + image_too_big EXCEPTION; + request_json_part1 CLOB; + request_json_part2 CLOB; + request_body BLOB; + v_vector vector; +BEGIN + + if p_code_mode = 1 then + + -- get file extension from file name and validate + file_extension := lower(regexp_replace(image_name, '.*\.([a-zA-Z0-9]+)$', '\1')) ; + + -- create temp blob + dbms_lob.createtemporary(request_body, FALSE); + -- base64 encode the image + base64_image := APEX_WEB_SERVICE.BLOB2CLOBBASE64(image_blob,'N','N'); + + -- validate size of base64 image, must be less than 5 mb + -- if length(base64_image) > 5242880 then + -- raise image_too_big; + -- end if; + + -- define beginning of request payload + request_json_part1 := to_clob('{"inputs": ["data:image/' || file_extension || ';base64,'); + + -- define ending of request payload + request_json_part2 := to_clob('"], + "servingMode": { + "servingType": "ON_DEMAND", + "modelId": "' || gen_ai_model || '" + }, + "truncate": "NONE", + "inputType": "IMAGE", + "compartmentId": "' || p_comp_id || '"}'); + + -- append part1 json to request blob + dbms_lob.append(request_body, apex_util.clob_to_blob(p_clob => request_json_part1,p_charset => 'AL32UTF8')); + -- append base64 image to request blob + dbms_lob.append(request_body, apex_util.clob_to_blob(p_clob => base64_image,p_charset => 'AL32UTF8')); + -- append part2 json to request blob + dbms_lob.append(request_body, apex_util.clob_to_blob(p_clob => request_json_part2,p_charset => 'AL32UTF8')); + -- Call GenAI Embed Service + embed_resp := dbms_cloud.send_request( + credential_name => oci_cred, + uri => gen_ai_endpoint || '/20231130/actions/embedText', + method => dbms_cloud.METHOD_POST, + body => request_body + ); + -- free temp blob + dbms_lob.freetemporary(request_body); + -- return embed reponse + RETURN dbms_cloud.get_response_text(embed_resp); + + + elsif p_code_mode = 2 then + + + RETURN to_clob( DBMS_VECTOR.UTL_TO_EMBEDDING( + image_blob, + 'image', + JSON('{ + "provider": "OCIGenAI", + "credential_name": "' || oci_cred || '", + "url": "https://inference.generativeai.us-chicago-1.oci.oraclecloud.com/20231130/actions/embedText", + "model": "' || gen_ai_model || '" + }') + ) ) ; + + + elsif p_code_mode = 3 then + + SELECT VECTOR_EMBEDDING( VIT_BASE_PATCH16_224 USING image_blob AS data ) as embedding + into v_vector; + + return to_clob( v_vector ); + + elsif p_code_mode = 4 then + + /* https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/onnx-pipeline-models-multi-modal-embedding.html + + begin + DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD( + model_name => 'CLIP_VIT_LARGE_PATCH14_IMG', + credential => 'OCI_CRED', + uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/p/py9iUuDsr_WFX6L0ziRvgPkYIhTYsdTgq6SF9S1j1pJWkS67jx2lXWqXz4cZkdDP/n/idi1o0a010nx/b/bucket-database-26ai/o/clip-vit-large-patch14_img.onnx', + metadata => JSON('{"function" : "embedding", "embeddingOutput" : "embedding" , "input": {"input": ["DATA"]}}') + ); + + DBMS_VECTOR.LOAD_ONNX_MODEL_CLOUD( + model_name => 'CLIP_VIT_LARGE_PATCH14_TXT', + credential => 'OCI_CRED', + uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/p/py9iUuDsr_WFX6L0ziRvgPkYIhTYsdTgq6SF9S1j1pJWkS67jx2lXWqXz4cZkdDP/n/idi1o0a010nx/b/bucket-database-26ai/o/clip-vit-large-patch14_txt.onnx', + metadata => JSON('{"function" : "embedding", "embeddingOutput" : "embedding" , "input": {"input": ["DATA"]}}') + ); + + END; + */ + + -- select DBMS_VECTOR.UTL_TO_EMBEDDING( + -- image_blob , + -- 'image', + -- json('{"provider":"database", "model":"CLIP_VIT_LARGE_PATCH14_IMG"}') ) + -- into v_vector; + + SELECT VECTOR_EMBEDDING( CLIP_VIT_LARGE_PATCH14_IMG USING image_blob AS data ) as embedding + into v_vector; + + return to_clob( v_vector ); + end if; + +EXCEPTION + WHEN invalid_image THEN + RAISE_APPLICATION_ERROR(-20001,'Invalid Image Extension, must be png,jpg,jpeg: ' || image_name); + WHEN image_too_big THEN + RAISE_APPLICATION_ERROR(-20002,'Base64 Image Over 5 MB: ' || length(base64_image) || ' - ' || image_name); +END; +/ \ No newline at end of file diff --git a/fnc_26ai_food.sql b/fnc_26ai_food.sql new file mode 100644 index 0000000..9b374e6 --- /dev/null +++ b/fnc_26ai_food.sql @@ -0,0 +1,192 @@ +create or replace function fnc_26ai_food( p_image_id in number, + p_comp_id in varchar2, + p_credential in varchar2 default 'OCI_CRED') +return clob +as +/* + + Criado por: fernando.leal@oracle.com + Data: Oct/2025 + Objetivo: demonstrar casos de uso de Food & Nutrition + + v1 - Food & Nutrition leal + +-- PDF + + BEGIN + DBMS_CLOUD.GET_OBJECT( + credential_name => 'OCI_CRED', + object_uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-database-26ai/o/food02.pdf', + directory_name => 'DATA_PUMP_DIR'); + END; + +-- Embedding: + + CREATE TABLE "TB_26AI_FOOD_VECTOR" + ( "EMBED_ID" NUMBER, + "EMBED_DATA" VARCHAR2(4000), + "EMBED_VECTOR" VECTOR, + "DOC_ORIGEM" VARCHAR2(200) + ) ; + + CREATE TABLE "TB_26AI_FOOD" + ( "ID" NUMBER GENERATED ALWAYS AS IDENTITY MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 66 CACHE 20 ORDER NOCYCLE NOKEEP NOSCALE NOT NULL ENABLE, + "FILE_NAME" VARCHAR2(200), + "FILE_MIMETYPE" VARCHAR2(200), + "FILE_CHARSET" VARCHAR2(200), + "FILE_BLOB" BLOB, + "UPDATED_DATE" DATE, + CREATED_BY varchar2(200) default 'ADMIN' + ) ; + + +INSERT INTO "TB_26AI_FOOD_VECTOR" +select embed_id, + text_chunk, + embed_vector, + 'guia_alimentar_populacao_brasileira_2ed.pdf' + from dual dt + CROSS JOIN TABLE( + dbms_vector_chain.utl_to_embeddings( + dbms_vector_chain.utl_to_chunks( + -- PDF Embrapa - Doencas no cultivo da Soja + dbms_vector_chain.utl_to_text( to_blob(bfilename('DATA_PUMP_DIR', 'guia_alimentar_populacao_brasileira_2ed.pdf')) ), + json('{"by":"words","max":"100","split":"sentence","normalize":"none", "overlap":0}') + ), + json('{ + "provider": "ocigenai", + "credential_name": "OCI_CRED", + "url": "https://inference.generativeai.us-chicago-1.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 CLOB PATH '$.embed_data', + embed_vector CLOB PATH '$.embed_vector' + ) + ) AS et; + + +INSERT INTO "TB_26AI_FOOD_VECTOR" +select embed_id, + text_chunk, + embed_vector, + 'food02.pdf' + from dual dt + CROSS JOIN TABLE( + dbms_vector_chain.utl_to_embeddings( + dbms_vector_chain.utl_to_chunks( + dbms_vector_chain.utl_to_text( to_blob(bfilename('DATA_PUMP_DIR', 'food02.pdf')) ), + json('{"by":"words","max":"150","split":"newline","sentence":"none", "overlap":0}') + ), + json('{ + "provider": "ocigenai", + "credential_name": "OCI_CRED", + "url": "https://inference.generativeai.us-chicago-1.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 CLOB PATH '$.embed_data', + embed_vector CLOB PATH '$.embed_vector' + ) + ) AS et; + + + +INSERT INTO "TB_26AI_FOOD_VECTOR" +select embed_id, + text_chunk, + embed_vector, + 'guia_alimentar_cardapios.pdf' + from dual dt + CROSS JOIN TABLE( + dbms_vector_chain.utl_to_embeddings( + dbms_vector_chain.utl_to_chunks( + dbms_vector_chain.utl_to_text( to_blob(bfilename('DATA_PUMP_DIR', 'guia_alimentar_cardapios.pdf')) ), + json('{"by":"words","max":"120","split":"sentence","normalize":"none", "overlap":0}') + ), + json('{ + "provider": "ocigenai", + "credential_name": "OCI_CRED", + "url": "https://inference.generativeai.us-chicago-1.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 CLOB PATH '$.embed_data', + embed_vector CLOB PATH '$.embed_vector' + ) + ) AS et; + + +*/ + messages CLOB; + v_vector clob; + p_prompt clob; + p_prompt2 clob; + v_total_calorias varchar(200); +begin + + SELECT json_value( fnc_26ai_embed_image_cohere(file_name, file_blob, p_credential, p_comp_id) , '$.embeddings[*].vector()') + INTO v_vector + from TB_26AI_FOOD + where id = p_image_id; + + for message_cursor in ( + + SELECT embed_data, doc_origem + FROM TB_26AI_FOOD_VECTOR + ORDER BY VECTOR_DISTANCE(EMBED_VECTOR, v_vector , COSINE ) + FETCH EXACT FIRST 60 ROWS ONLY + + ) loop + + messages := messages || '"' || replace(replace(replace(replace(message_cursor.embed_data || '- Fonte:' || message_cursor.doc_origem ,chr(10),null),chr(13),null),'"',''),'''','') || '",' ; + + END LOOP; + + p_prompt := 'Você é um analista de nutrição profissional especializado em avaliar refeições usando entradas de imagem e em recuperar informações nutricionais utilizando RAG a partir do Oracle 26ai Vector Database. +Sua tarefa: +Analisar a imagem de entrada. +Identificar cada item alimentar no prato. +Estimar tamanhos de porções. +Inferir ingredientes ocultos (óleo, manteiga, molhos, açúcar, sal). +Gerar embeddings. +Converter cada item alimentar detectado em uma descrição textual normalizada (adequada para embeddings). +Exemplo: “peito de frango grelhado 120g”, “arroz branco 150g”, “salada verde 80g com molho”. +Executar a Vector Similarity Search. +Recuperar os fatos nutricionais mais próximos do repositório vetorial. +Dados típicos retornados: +calorias; +proteínas; +carboidratos; +gorduras; +fibras; +densidade de micronutrientes; +impacto glicêmico; +Consulte a base da TBCA para obter a composição nutricional (macronutrientes, micronutrientes, fibras, etc.) - Tabela Brasileira de Composição de Alimentos, versão 7.3. São Paulo: USP; 2025. +Combine os resultados do RAG com sua própria estimativa visual. +Quando dados estiverem faltando, estime valores de forma conservadora. +Sua resposta deve sempre estar totalmente fundamentada nos dados retornados pelo RAG quando disponíveis. +Se o RAG não retornar nenhuma correspondência, declare explicitamente "fonte": "estimativa visual". Responda em formato Markdown e portugues Brasil.'; + + -- cuidado com temperatura usando "." ou "," + --execute immediate('alter session set nls_numeric_characters=''.,'' '); + + -- sem re-rank (opcao de uso para refinar resultado) + p_prompt2 := p_prompt || '. Dados privados encontrados: ' || messages || '. Cite o documento de origem dos dados.'; + + return fnc_26ai_rag_food(p_prompt2 , p_credential , p_image_id, p_comp_id ); + +end; +/ \ No newline at end of file diff --git a/fnc_26ai_health.sql b/fnc_26ai_health.sql new file mode 100644 index 0000000..e6f5fc7 --- /dev/null +++ b/fnc_26ai_health.sql @@ -0,0 +1,153 @@ +create or replace function fnc_26ai_health( p_image_id in number, + p_source in varchar2, + p_comp_id in varchar2, + p_credential in varchar2 default 'OCI_CRED') +return clob +as +/* + + Criado por: fernando.leal@oracle.com + Data: Oct/2025 + Objetivo: demonstrar casos de uso do Oracle AI Database 26ai + + v1 - funcao principal de Heathcare, com similaridade e RAG - leal + + + -- + -- Pre Req para Re-Rank: criamos nova credential para Cohere + -- Podemos usar ReRank como ONNX atraves de https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/onnx-pipeline-models-reranking-pipeline.html + -- + DECLARE + jo json_object_t; + BEGIN + jo := json_object_t(); + jo.put('access_token', 'xxxxxxxxxxZBDKaQjPzB2Xdt8CkMtNz3KYRc1H0PjzRf6wkHxxxxxxxxxxxxx'); -- seu token Cohere. Gere Token em https://dashboard.cohere.com/ + DBMS_VECTOR.CREATE_CREDENTIAL( + credential_name => 'COHERE_CRED', + params => json(jo.to_string)); + END; + + -- PDFs + + BEGIN + DBMS_CLOUD.GET_OBJECT( + credential_name => 'OCI_CRED', + object_uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-database-26ai/o/ecg.pdf', + directory_name => 'DATA_PUMP_DIR'); + END; + + BEGIN + DBMS_CLOUD.GET_OBJECT( + credential_name => 'OCI_CRED', + object_uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-database-26ai/o/raiox.pdf', + directory_name => 'DATA_PUMP_DIR'); + END; + + + BEGIN + DBMS_CLOUD.GET_OBJECT( + credential_name => 'OCI_CRED', + object_uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-database-26ai/o/ressonancia2.pdf', + directory_name => 'DATA_PUMP_DIR'); + END; + + BEGIN + DBMS_CLOUD.GET_OBJECT( + credential_name => 'OCI_CRED', + object_uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-database-26ai/o/esoes_pele_dermatologia.pdf', + directory_name => 'DATA_PUMP_DIR'); + END; + + + -- Embedding com Cohere + + + INSERT INTO "TB_26AI_HEALTH_VECTOR" + select 'raiox.pdf' object_name, + embed_id, + text_chunk, + embed_vector + from dual dt + CROSS JOIN TABLE( + dbms_vector_chain.utl_to_embeddings( + dbms_vector_chain.utl_to_chunks( + dbms_vector_chain.utl_to_text( to_blob(bfilename('DATA_PUMP_DIR', 'raiox.pdf' )) ), + -- dicas para chunking: https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/explore-chunking-techniques-and-examples.html + json('{"by":"words","max":"220","split":"sentence","normalize":"all", "overlap":50}') + ), + json('{ + "provider": "ocigenai", + "credential_name": "OCI_CRED", + "url": "https://inference.generativeai.us-chicago-1.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; + +*/ + messages CLOB; + params_genai CLOB; + v_vector clob; + p_prompt clob; + p_prompt2 clob; + reranked_output json; + output CLOB; +begin + + SELECT json_value( fnc_26ai_embed_image_cohere(file_name, file_blob, p_credential , p_comp_id) , '$.embeddings[*].vector()') + INTO v_vector + from TB_26AI_HEALTH + where id = p_image_id; + + for message_cursor in ( + + SELECT embed_data , source + FROM TB_26AI_HEALTH_VECTOR + ORDER BY VECTOR_DISTANCE(EMBED_VECTOR, v_vector , EUCLIDEAN_SQUARED ) + FETCH EXACT FIRST 10 ROWS ONLY + ) loop + + messages := messages || '"' || replace(replace(replace(replace(message_cursor.embed_data || ' (' || message_cursor.source || ')',chr(10),null),chr(13),null),'"',''),'''','') || '",' ; + + END LOOP; + + p_prompt := 'Atue como um especialista médico em ressonância magnética da coluna cervical, cardiologia, radiologia do crânio e dermatologia. + A partir da imagem gere laudos técnicos precisos e com respaldo médico a partir de uma destas especialiadades. + No caso de detectar algo grave, sugira que o usuário procure um especialista. Não dê resultados graves como Melanoma. + Nestes caso, oriente que procure-se um dermatologista. + Sempre cite a origem encontrada em banco no caso de PDF vetorizado. Nunca cite nome do paciente ou do médico caso esteja visível na imagem.'; + + -- cuidado com temperatura usando "." ou "," + execute immediate('alter session set nls_numeric_characters=''.,'' '); + + -- + -- ReRank (https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/use-reranking-better-rag-results.html) + -- + params_genai := '{"provider": "cohere", + "credential_name": "COHERE_CRED", + "url": "https://api.cohere.com/v1/rerank", + "model": "rerank-v3.5", + "return_documents": true, + "top_n": 1 }'; + + reranked_output := dbms_vector_chain.rerank( p_prompt , json('{ "documents": [ ' || messages || '] }'), json(params_genai)); + + -- cuidado com temperatura usando "." ou "," + execute immediate('alter session set nls_numeric_characters=''.,'' '); + + p_prompt2 := p_prompt || '. Informações obtidas para a imagem : ' || JSON_VALUE( JSON_SERIALIZE(reranked_output), '$[0].content' ); + + -- rag + output := fnc_26ai_rag_health(p_prompt2 , p_credential, p_image_id, p_comp_id); + + return output ; + +end; +/ \ No newline at end of file diff --git a/fnc_26ai_health_hemograma.sql b/fnc_26ai_health_hemograma.sql new file mode 100644 index 0000000..9d8bb4d --- /dev/null +++ b/fnc_26ai_health_hemograma.sql @@ -0,0 +1,123 @@ +create or replace function fnc_26ai_health_hemograma( p_id in number, + p_comp_id in varchar2, + p_credential in varchar2 default 'OCI_CRED' ) +return clob +as +/* + + Criado por: fernando.leal@oracle.com + Data: Dez/2025 + Objetivo: demonstrar casos de uso do Oracle AI Database 26ai + + v1 - RAG para gerar correlacao dos exames do hemograma + +*/ + messages clob; + v_response clob; +begin + +-- pre requisito: execucao de PRC_26AI_HEALTH_HEMOGRAMA para gerar TB_26AI_HEALTH_HEMOGRAMA_TMP + + -- insigths + for r1 in ( select '"exame": ' || exame || ': ' || valor txt + from TB_26AI_HEALTH_HEMOGRAMA_TMP + where id = p_id ) loop + messages := messages || r1.txt; + end loop; + + v_response := fnc_26ai_rag('Você é um assistente clínico especializado em análise integrada de exames laboratoriais, + com abordagem semelhante à de médicos especialistas experientes + (endocrinologia, cardiologia, nefrologia, hepatologia, hematologia e clínica médica). + + Receberá um conjunto estruturado de resultados laboratoriais (hemograma completo, + marcadores metabólicos, inflamatórios, renais, eletrolíticos, vitamínicos e hormonais). + + OBJETIVO PRINCIPAL: + Realizar uma análise CORRELACIONAL dos exames, identificando padrões, relações + fisiopatológicas e possíveis tendências que NÃO são evidentes quando os exames + são analisados de forma isolada. + + REGRAS IMPORTANTES: + - NÃO descreva exame por exame individualmente. + - NÃO limite a análise a “dentro” ou “fora” do intervalo de referência. + - NÃO forneça diagnóstico médico definitivo. + - NÃO substitua avaliação médica presencial. + - Evite linguagem técnica excessiva; seja claro, preciso e explicativo. + + FOCO DA ANÁLISE: + 1. Correlações entre sistemas: + - Metabolismo glicídico ↔ perfil inflamatório + - Função renal ↔ eletrólitos ↔ metabolismo ósseo + - Metabolismo do ferro ↔ hemograma ↔ vitaminas + - Perfil endócrino ↔ risco cardiometabólico + - Inflamação crônica subclínica ↔ risco cardiovascular + + 2. Identificação de padrões clínicos sugestivos: + - Tendência a resistência insulínica + - Risco cardiometabólico precoce + - Estados inflamatórios de baixo grau + - Alterações no metabolismo do ferro e vitaminas + - Impactos hormonais e eletrolíticos interligados + + 3. Insights clínicos de alto nível: + - O que chama atenção quando os exames são analisados em conjunto + - Possíveis mecanismos fisiológicos envolvidos + - Pontos que merecem acompanhamento ou investigação futura + + 4. Recomendações NÃO medicamentosas: + - Estilo de vida + - Alimentação + - Atividade física + - Monitoramento laboratorial + - Acompanhamento médico especializado (quando pertinente) + + FORMATO DA RESPOSTA: + - Texto corrido, organizado por tópicos claros e em Markdown + - Linguagem clínica acessível + - Ênfase em raciocínio médico integrado + - Sem alarmismo + - Sem conclusões diagnósticas fechadas + + ##Considere estas referencias na análise: +1- Hematologia (base do hemograma) +Hoffbrand’s Essential Haematology +Wintrobe’s Clinical Hematology +UpToDate – Hematology +American Society of Hematology (ASH) +British Society for Haematology (BSH) +2- Endocrinologia (hormônios, metabolismo, tireoide) +Endocrine Society Clinical Practice Guidelines +Williams Textbook of Endocrinology +UpToDate – Endocrinology +ADA – American Diabetes Association +3- Hepatologia (fígado, enzimas, metabolismo do ferro) +EASL – European Association for the Study of the Liver +AASLD Practice Guidelines +Zakim and Boyer’s Hepatology +UpToDate – Liver Diseases +4- Nutrição e Metabolismo +ASPEN Guidelines (nutrição clínica) +ESPEN Guidelines +Modern Nutrition in Health and Disease +NIH – Office of Dietary Supplements +5- Nefrologia (impacto renal no hemograma) +KDIGO Guidelines +Brenner & Rector’s The Kidney +UpToDate – Nephrology +6- Inflamação, Infecção e Imunologia +Harrison’s Principles of Internal Medicine +CDC / WHO (contexto infeccioso) +UpToDate – Infectious Diseases +7- Evidência científica +PubMed / Medline +Cochrane Library +BMJ Best Practice + + CONTEXTO: + Os exames pertencem a um adulto, sem informações clínicas adicionais além dos resultados laboratoriais. + Baseie-se exclusivamente na correlação entre os dados fornecidos. Dados: ' || messages , p_credential, p_comp_id ); + + return v_response; + +end; +/ \ No newline at end of file