create or replace FUNCTION fnc_26ai_rag_telecom(p_query VARCHAR2, 
                                   p_top_k IN NUMBER, 
                                   p_new_session in number, 
                                   p_credential  in varchar2 default 'OCI_CRED'
                                   ) 
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 TELECOM - leal


begin
		dbms_cloud_ai.create_profile(
			profile_name => 'PROF_TELECOM_V1', 
			attributes =>
				'{"provider": "oci",
				"credential_name": "OCI_CRED",
				"oci_compartment_id":  "ocid1.compartment.oc1..aaaaaaaakvd4bq4b3n7yn3gjjqzfhsl62dec44tjvi2iwa3sugw5frgfpzea",
				"region": "us-chicago-1",
				"model": "meta.llama-4-maverick-17b-128e-instruct-fp8", 
				"oci_apiformat": "GENERIC",  
				"object_list": [
					 {"owner": "AICHAT1", "name": "V_26AI_REMARK"},  
                     {"owner": "AICHAT1", "name": "V_26AI_MASTER"},   
                     {"owner": "AICHAT1", "name": "V_26AI_CLIENTE_FIXA_MOVEL_CONSOLIDADO"} 
				 ],
				"comments": true,
				"temperature": 0.1	
				}'
			);
end;
/


*/
   v_response_vector  CLOB;
   v_pre_prompt clob;
   v_prompt clob;
   params_genai CLOB;
   output CLOB;
   query_vec VECTOR;

   v_has number;
   v_assistant clob;

   v_i number :=0 ;

   v_response_selectai clob;

   v_pre_prompt2 clob;

   v_select_ai_preprompt varchar2(4000) := ' . Não adicione nenhum filtro de data a menos que seja solicitado.';
   v_select_ai_profile varchar2(20) := 'PROF_TELECOM_V1';

BEGIN

  -- embedding do prompt para dedicated
  query_vec := to_vector(  fnc_26ai_embed ( p_string => p_query ,p_emb_type=>'COHERE') ); -- neste tenancy nao temos o DEDICATED - leal 17-10-25

      for message_cursor in (
                        select lv.id as DOCID, 
                               lv.EMBED_DATA as BODY, 
                               vector_distance(lv.embed_vector, query_vec, cosine ) AS SCORE,
                               null txt_aug
                        from  TB_26AI_TELECOM_VECTOR_DATA lv
                        order by SCORE 
                        FETCH EXACT FIRST p_top_k ROWS ONLY    
                    ) loop

        v_i :=  message_cursor.SCORE;
        v_response_vector := v_response_vector || '"' || replace(replace(replace(replace(message_cursor.BODY || ': ' || message_cursor.txt_aug,chr(10),null),chr(13),null),'"',''),'''','') || '",' ;

      END LOOP;


      begin  
           SELECT DBMS_CLOUD_AI.GENERATE(prompt       =>  p_query  || v_select_ai_preprompt ,
                                          profile_name => v_select_ai_profile,
                                          action       => 'runsql') response  
           into v_response_selectai;  

           if v_response_selectai like 'Sorry%' or v_response_selectai like 'No data found%' then
               v_response_selectai := '--' ; 
           end if;
      exception
        when others then
           v_response_selectai := '-' ; 
      end;


  -- 
  -- 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
  --
   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"}';


       -- augmented prompt atraves do vetor criado no banco
     v_pre_prompt := '"messages": [
            {
                "role": "system",
                "content": "Objetivo
Transformar perguntas em análises qualitativas ou quantitativas e acionáveis para os executivos, cobrindo todos os motivos de contato.
Instruções
Escopo
	•	Responda apenas sobre chamadas e motivos de contato no call center.
	•	Se a pergunta não estiver nesse escopo, retorne com recusa educada.
Processo
	•	Classifique os resultados em temas: Técnico; Contas; Retenção; Vendas; Comercial/Atendimento.
	•	Extraia sinais relevantes: qualidade de serviço, motivos dominantes de contato, intenções de cancelamento, menções a concorrentes, objeções de preço, falhas de processo, elogios, risco qualitativo de churn.
	•	Analise sentimento (positivo, negativo, neutro) e emoções (raiva, frustração, ansiedade, alívio).
	•	Avalie pitch de vendas quando aplicável.
	•	Sintetize sempre em linguagem executiva.
	•	Nunca invente números; se usar contagens, declare a amostra.
    •	Nunca traga informações como "Não há dados suficientes para montar um gráfico" 
Formato da resposta (não use Markdown)
	•	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 executivo: exatamente 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.
Guardrails
	•	Nunca exponha PII.
	•	Não reporte métricas individuais de agentes.
	•	Se não houver evidências suficientes, declare claramente essa limitação no mesmo formato de lista.
    •	Nunca cite "Não há necessidade de gráfico, pois os dados podem ser facilmente compreendidos na lista ordenada acima."
Linguagem
	•	Sempre em português claro, executivo e direto.
	•	Evite jargões técnicos.
	•	Estruture como briefing para diretoria.
	•	Valores monetários em BRL.",';


    v_pre_prompt2 := '{ "role": "user","content": "Contexto Chamadas:"' || v_response_vector  || ' "Contexto BI": ' || v_response_selectai || ' "Pergunta": ' || p_query   || '"}' ; -- sem ]'

    v_prompt := v_pre_prompt || v_pre_prompt2 || ']';

    begin
       output := dbms_vector_chain.utl_to_generate_text(  replace(replace(replace(replace(v_prompt,chr(10),null),chr(13),null),'"',''),'''','')  , json(params_genai));
    exception
      when others then
           begin
            v_prompt := v_pre_prompt || v_pre_prompt2 ;
            output := dbms_vector_chain.utl_to_generate_text(  replace(replace(replace(replace(v_prompt,chr(10),null),chr(13),null),'"',''),'''','')  , json(params_genai));
           exception
               when others then
                     v_prompt := v_pre_prompt;
                     output := dbms_vector_chain.utl_to_generate_text(  replace(replace(replace(replace(v_prompt,chr(10),null),chr(13),null),'"',''),'''','')  , json(params_genai));
           end ;     
    end;  

   --output := FNC_AI_LLAMA(  replace(replace(replace(replace(messages,chr(10),null),chr(13),null),'"',''),'''','')  ,'OCI_CRED');
   RETURN output;

END;
/