create or replace FUNCTION fnc_26ai_rag_aiagent(p_query VARCHAR2, p_top_k IN NUMBER , p_prompt_length out number, p_credential in varchar2 default 'OCI_CRED', p_app_user in varchar2 default V('APP_USER') ) RETURN CLOB IS /* Criado por: fernando.leal@oracle.com Data: Oct/2025 Objetivo: demonstrar casos de uso do Oracle AI Database 26ai v1 - funcao de RAG para estudo explorar "fale com seus dados" (quando nao ter AgentAI disponivel para exibicao) - leal */ v_context CLOB; v_pre_prompt clob; v_prompt clob; v_pre_prompt2 clob; params_genai CLOB; output CLOB; query_vec VECTOR; -- https://docs.oracle.com/en/database/oracle/oracle-database/23/arpls/dbms_vector_chain1.html#GUID-017C9002-194C-48E5-B59B-EF5C60BC8405 v_llm varchar2(20) := 'LLAMA4'; -- [ LLAMA4 | OPENAI ] BEGIN -- embedding do prompt para dedicated 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, lv.FILE_NAME from TB_26AI_AIAGENT_VECTOR lv where lower(p_query) <> 'oi' and lower(p_query) <> 'ola' and lower(p_query) <> 'olá' and lower(p_query) <> 'bom dia' and lower(p_query) <> 'boa tarde' and lower(p_query) <> 'teste' -- and vector_distance(lv.EMBED_VECTOR, query_vec, cosine ) >= 8/10 and ( upper(USER_NAME) like 'ADMIN%' or upper(USER_NAME) = upper(p_app_user) ) order by SCORE FETCH EXACT FIRST p_top_k ROWS ONLY ) loop v_context := v_context || '"' || replace(replace(replace(replace(message_cursor.BODY || ' - Citations: ' || message_cursor.file_name , chr(10),null),chr(13),null),'"',''),'''','') || '",' ; end loop; -- -- pre requisito sao as credenciais definidas com nome OCI_CRED criadas a partir de dbms_vector.create_credential -- -- para montar request body abaixo: 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.us-chicago-1.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; -- augmented prompt atraves do vetor criado no banco v_pre_prompt := '"messages": [ { "role": "system", "content": "Objetivo Resgate informações dos documentos de modo a trazer explicações claras e objetivas. Escopo • Responda apenas sobre informações contidas em documentos. • Se a pergunta não estiver nesse escopo, retorne com recusa educada. • Se o prompt tiver um"oi", "olá", "bom dia", ou qualquer tipo de saudação, retorne apenas "Como posso lhe ajudar?" • Sempre cite a origem da resposta, descrita em "Citations" (nome do arquivo PDF, DOC ou imagem PNG, JPG, etc) Formato da resposta • A saída deve ser obrigatoriamente em listas e tópicos, nunca em parágrafos corridos. • Estrutura fixa da resposta: • Título curto com o insight principal. • Resumo em 3 bullets (curtos, diretos). • Principais insights: lista não ordenada (•) para destaques gerais. • Rankings ou comparações: lista ordenada (1, 2, 3). • É proibido escrever respostas fora desse formato. • Use negrito para informações críticas e itálico para sinais preliminares ou hipóteses. • Nunca resposnda com um JSON na resposta. Respostas são para usuários finais, devem ser respostas claras confoirme "Formato da resposta" Guardrails • Nunca exponha PII. • Se não houver evidências suficientes, declare claramente essa limitação no mesmo formato de lista. Linguagem • Sempre em português claro, executivo e direto. • Evite jargões técnicos. • Valores monetários em BRL.",'; v_pre_prompt2 := '{ "role": "user","content": "Contexto:"' || v_context || ' "Pergunta": ' || p_query || '"}' ; -- sem ]' v_prompt := v_pre_prompt || v_pre_prompt2 || ']'; -- para LLama, a contabilizacao é por caracteres p_prompt_length := fnc_26ai_char_count(v_prompt); output := dbms_vector_chain.utl_to_generate_text( replace(replace(replace(replace(v_prompt,chr(10),null),chr(13),null),'"',''),'''','') , json(params_genai)); RETURN output; END; /