create or replace function fnc_26ai_utilities( 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: Dez/2025
  Objetivo: demonstrar casos de uso do Oracle AI Database 26ai

  v1 - funcao principal de Utilities, com similaridade e RAG - leal


-- carga imagens

    DECLARE
      v_bucket VARCHAR2(2000) := 
          'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-img-tmp-torrescarga/o/';
    BEGIN

     -- lista todos arquivos do bucket que ainda nao foram vetorizados
     FOR r1 IN (
        SELECT object_name,  
               substr(object_name,1,instr(object_name,'/')-1) torre_name,
               substr(object_name,instr(object_name,'/')+1) file_name
        FROM DBMS_CLOUD.LIST_OBJECTS('OCI_CRED', 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-img-tmp-torrescarga/o')
        WHERE lower(object_name) LIKE '%.jpg'
          AND object_name NOT IN (
                SELECT object_name
                FROM TB_26AI_UTILITIES_LOG
                WHERE status = 'P'
          )  
     ) LOOP

        -- copia temporaria do PDF para o DIRECTORY
        -- exemplo >  https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-img-tmp-torrescarga/o/T.472%2FDJI_0167.JPG
        DBMS_CLOUD.GET_OBJECT(
            credential_name => 'OCI_CRED',
            object_uri      => v_bucket || replace( r1.object_name, '%2F', '/') ,
            directory_name  => 'DATA_PUMP_DIR'
        );

       -- teste:  select *  FROM DBMS_CLOUD.LIST_FILES ('DATA_PUMP_DIR') where object_name like 'DJI%'
       
       
       insert into TB_26AI_UTILITIES
         ( FILE_NAME,
           FILE_MIMETYPE,
           FILE_BLOB,
           UPDATED_DATE,
           CREATED_BY,
           REFERENCE_NAME)
       values( 
            r1.file_name,
            'image/jpeg',
            to_blob(bfilename('DATA_PUMP_DIR', r1.file_name )),
            sysdate,
            'admin2',
            r1.torre_name
         );   
           
        INSERT INTO TB_26AI_UTILITIES_LOG
        VALUES (sysdate, r1.object_name, 'P');

        COMMIT;

        -- remove o arquivo temporario armazenado no DATA_PUMP_DIR
        DBMS_CLOUD.DELETE_FILE(
            directory_name => 'DATA_PUMP_DIR',
            file_name      =>  r1.file_name
        );

     END LOOP;

    END;
     



--Ajuste de Status

        declare
          v_status varchar2(200);
          v_has number;
        begin

         for r1 in (select * from TB_26AI_UTILITIES where status_torre is null ) loop
         
            v_status := FNC_26ai_rag ( 'A partir deste texto retorne uma "Classificação da Gravidade": 
    # Risco controlável - PRIORIDADE 3, PRIORITÁRIA 60D
    # Risco alto - PRIORIDADE 2, URGÊNCIA 30D
    # Risco elevado - PRIORIDADE 1, URGÊNCIA 15D
    # Risco eminente - PRIORIDADE 0, EMERGÊNCIA (1 dia)
    # Avaliação - PRIORIDADE 4, NECESSÁRIA 210D
    # Monitoramento - PRIORIDADE 5, MONITORÁVEL 1A
    # Histórico - PRIORIDADE 6, GERENCIÁVEL 3A
    # Acompanhamento - PRIORIDADE 7, MONITORAMENTO 10 A
    # Cadastro - PRIORIDADE 8, INFORMATIVA
    Retorne apenas a classificaco como: "Risco controlável","Risco alto","Risco elevado","Risco eminente","Avaliação","Monitoramento","Histórico","Acompanhamento","Cadastro". Nenhum comentario é permitido. 
    Dados: '  ||  fnc_26ai_utilities( p_image_id =>  r1.id , 
                                            p_comp_id => 'ocid1.compartment.oc1..aaaaaaaakvd4bq4b3n7yn3gjjqzfhsl62dec44tjvi2iwa3sugw5frgfpzea' ) , 
             'OCI_CRED',  
            ''  
             ) ;

            update TB_26AI_UTILITIES set status_torre = v_status where id = r1.id;
            commit;
            
         end loop;   
            
        end;

-- Geo

begin
    UPDATE TB_26AI_UTILITIES t
    SET GEOMETRY = SDO_GEOMETRY(
            2001,                 -- 2D point
            4326,                 -- SRID
            SDO_POINT_TYPE(t.LONGITUDE, t.LATITUDE, NULL),
            NULL,
            NULL
    )
    where  GEOMETRY is null ;
    commit;   
end;    


-- Carga PDFs para vetorizacao

   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/GED_15328_CPFL.pdf',
       directory_name => 'DATA_PUMP_DIR');
   END;
	
   INSERT INTO "TB_26AI_UTILITIES_VECTOR"
        select  'GED_15328_CPFL.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', 'GED_15328_CPFL.pdf' )) ), 
                                 json('{"by":"words","max":"320","split":"sentence","normalize":"all", "overlap":50}')
                             ),
                            json('{"provider":"database", "model":"CLIP_VIT_LARGE_PATCH14_TXT"}')
                         )
                     )  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;

    Imagem

        select DBMS_VECTOR.UTL_TO_EMBEDDING(
         to_blob(bfilename('DATA_PUMP_DIR', 'migrate.JPG'))  ,
        'image',
         json('{"provider":"database", "model":"CLIP_VIT_LARGE_PATCH14_IMG"}') ) ;

   
*/
   messages CLOB;
   params_genai CLOB;
   v_vector clob; 
   p_prompt clob;
   p_prompt2 clob;
   reranked_output json;
   output CLOB; 

  v_best_text       CLOB;
  v_best_score      NUMBER;
begin

  -- Referencia Multi Modal:  https://docs.oracle.com/en/database/oracle/oracle-database/23/vecse/onnx-pipeline-models-multi-modal-embedding.html

  -- padrao 4 usa ONNX com CLIP_VIT_LARGE_PATCH14_IMG
  -- embedding abaixo usa CLIP_VIT_LARGE_PATCH14_TXT

  SELECT json_value( fnc_26ai_embed_image_cohere(image_name => file_name, 
                                                 image_blob => file_blob, 
                                                 oci_cred => p_credential ,
                                                 p_comp_id => p_comp_id, 
                                                 p_code_mode => 4 -- cuidado
                                                 ) , '$.embeddings[*].vector()')        
    INTO v_vector
    from TB_26AI_UTILITIES
    where id = p_image_id;   

  for message_cursor in (

           SELECT embed_data , source
						FROM TB_26AI_UTILITIES_VECTOR
						ORDER BY VECTOR_DISTANCE(EMBED_VECTOR, v_vector , COSINE    )
						FETCH EXACT FIRST 50 ROWS ONLY     -- era 60
                ) loop

      messages := messages || '"' || replace(replace(replace(replace(message_cursor.embed_data || ' (' || message_cursor.source || ')',chr(10),null),chr(13),null),'"',''),'''','') || '",' ;

  END LOOP;

  messages :=  RTRIM( messages , ',') ;

     p_prompt := 'Você é um especialista em inspeção aérea de linhas de transmissão utilizando drones, com profundo conhecimento em engenharia estrutural, manutenção de ativos elétricos de alta tensão e avaliação de riscos operacionais.
Sua tarefa é analisar imagens aéreas (ou frames de vídeo) capturadas por drones de inspeção, identificando falhas visíveis, sinais precoces de degradação e condições de risco em torres de transmissão e seus componentes associados.

## Objetivo da Análise
Realizar uma avaliação visual detalhada e sistemática, explorando a vantagem do drone de acessar pontos elevados, ângulos não convencionais e regiões críticas, com foco em:
Detecção proativa de anomalias que possam evoluir para falhas
Detecção reativa de danos evidentes já instalados
Priorização de riscos à segurança e à continuidade do serviço

## Considerações Específicas para Imagens de Drones
Durante a análise, leve em conta que:
A imagem pode apresentar variação de iluminação, sombras fortes ou reflexos
Alguns componentes podem estar parcialmente ocultos por cabos, vegetação ou pela própria estrutura
A resolução e o nível de zoom podem variar entre diferentes regiões da imagem
A perspectiva aérea pode causar distorções de escala ou alinhamento
Sempre que houver incerteza, registre explicitamente a limitação visual.

## Pontos de Atenção Obrigatórios
1. Estrutura da Torre (Foco Aéreo)
Deformações, empenamentos ou desalinhamentos visíveis nos braços, travessas e montantes
Elementos estruturais ausentes, soltos ou deslocados
Parafusos, porcas e chapas de ligação com sinais de afrouxamento ou corrosão
Condições da base ou fundação quando visíveis a partir do voo
2. Corrosão e Degradação de Materiais
Corrosão superficial vs. corrosão avançada (escamas, perda de seção)
Concentração de corrosão em pontos críticos:
Juntas estruturais
Interfaces parafusadas
Regiões de acúmulo de água
Comparação visual entre diferentes partes da torre para identificar degradação desigual
3. Isoladores (Alta Prioridade em Inspeção por Drone)
Isoladores quebrados, trincados, lascados ou ausentes
Cadeias de isoladores desalinhadas ou com inclinação anormal
Sinais de contaminação severa (poluição, poeira, salinidade, fezes de aves)
Diferenças de aparência entre isoladores da mesma cadeia
4. Condutores, Cabos e Acessórios
Grampos de ancoragem e suspensão com desgaste ou deslocamento
Espaçadores e amortecedores de vibração ausentes, danificados ou fora de posição
Cabos com desgaste, fios rompidos, desalinhamento ou marcas térmicas
Distância inadequada entre cabos, torre e outros elementos
5. Riscos à Segurança e Operação
Qualquer condição que possa resultar em:
Curto-circuito
Descarga elétrica
Queda de componentes
Colapso estrutural parcial ou total
Presença de objetos estranhos (vegetação, pipas, cabos, ninhos) próximos a condutores ou isoladores
Situações que demandem intervenção imediata, monitoramento reforçado ou manutenção programada

## Formato da Resposta Esperada
Organize sua análise da seguinte forma:
Resumo Geral da Condição da Torre (Visão Aérea)
Anomalias Identificadas
Descrição clara
Localização aproximada (ex.: braço superior direito, cadeia de isoladores, etc)
Procure referencias técnicas no documento da CPFL "GED_15328_CPFL.pdf" para contextualizar e formatar a resposta. 
Classificação da Gravidade:
# Risco controlável - PRIORIDADE 3, PRIORITÁRIA 60D
# Risco alto - PRIORIDADE 2, URGÊNCIA 30D
# Risco elevado - PRIORIDADE 1, URGÊNCIA 15D
# Risco eminente - PRIORIDADE 0, EMERGÊNCIA (1 dia)
# Avaliação - PRIORIDADE 4, NECESSÁRIA 210D
# Monitoramento - PRIORIDADE 5, MONITORÁVEL 1A
# Histórico - PRIORIDADE 6, GERENCIÁVEL 3A
# Acompanhamento - PRIORIDADE 7, MONITORAMENTO 10 A
# Cadastro - PRIORIDADE 8, INFORMATIVA

## Impacto Potencial na Segurança e na Operação
Recomendações Técnicas
Inspeção complementar (solo, térmica, LiDAR (Light Detection And Ranging), etc.)
Manutenção corretiva ou preventiva
Caso não sejam identificadas anomalias relevantes, declare explicitamente que nenhum problema visível foi detectado nas imagens analisadas, 
ressaltando as limitações inerentes à inspeção por drone (ângulo, resolução, oclusões).

## FONTES:
Sempre cite as referencias de pesquisa, como documentos PDF vetorizados. 
Fonte CPFL: https://objectstorage.sa-saopaulo-1.oraclecloud.com/n/idi1o0a010nx/b/bucket-database-26ai/o/GED_15328_CPFL.pdf
Procure referencias IEEE e na Abrate (Fonte: https://abrate.org.br/) ';

    -- 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)
       --
       /*
            --
            -- 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');  -- Token em https://dashboard.cohere.com/
               DBMS_VECTOR.CREATE_CREDENTIAL(
                      credential_name => 'COHERE_CRED',
                      params => json(jo.to_string));
            END;
       */
  /* params_genai := '{"provider": "cohere",
    "credential_name": "COHERE_CRED",
    "url": "https://api.cohere.com/v1/rerank",
    "model": "rerank-v3.5",
    "return_documents": true,
    "top_n": 15  }';   -- era 20

    reranked_output := dbms_vector_chain.rerank( p_prompt , json('{  "documents": [ ' || messages || '] }'), json(params_genai));

    p_prompt2 := JSON_SERIALIZE(reranked_output)   ;   

  -- Score do top resultado
  v_best_score := JSON_VALUE(
    p_prompt2,
    '$[0].relevance_score'
    RETURNING NUMBER
    NULL ON ERROR    -- ← evita exception silenciosa
  );

  -- Texto do top resultado
  -- Campo correto é 'document.text', não 'content'
  v_best_text := JSON_VALUE(
    p_prompt2,
    '$[0].document.text'
    RETURNING CLOB
    NULL ON ERROR
  ); */

    -- rag
    output :=  fnc_26ai_rag_utilities(p_prompt || '. Dados: ' || messages , p_credential, p_image_id, p_comp_id);

    return output ;

end;
/