create or replace function fnc_26ai_agro( p_image_id in number, p_tipo_cultura in varchar2 default 'Soja', 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 - similaridade e rag para AGRO - leal v2 - prompt nao cita mais origem do dado como documento Embrapa - leal -- PDF BEGIN DBMS_CLOUD.GET_OBJECT( credential_name => 'OCI_CRED', object_uri => 'https://objectstorage.sa-saopaulo-1.oraclecloud.com/p/d8iuDNoKn5EC_JZWO4JukFHL_WatZHxMY_NUnCzvE56WtliIIcCQlwLpH6EIGx-z/n/idajmumkp9ca/b/bucket-database26ai/o/Doc-256-2023OL-1.pdf', directory_name => 'DATA_PUMP_DIR'); END; -- Embedding: INSERT INTO "TB_26AI_AGRO_VECTOR" select embed_id, text_chunk, embed_vector, 'Soja', 'Doc-256-2023OL-1.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', 'Doc-256-2023OL-1.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; -- Citros INSERT INTO "TB_26AI_AGRO_VECTOR" select embed_id, text_chunk, embed_vector , 'Citros', 'agro_citrus_embrapa02.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', 'agro_citrus_embrapa02.pdf')) ), json('{"by":"words","max":"120","split":"sentence","normalize":"all", "overlap":20}') ), 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; v_vector clob; p_prompt clob; p_prompt2 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_AGRO where id = p_image_id; for message_cursor in ( SELECT embed_data, doc_origem FROM TB_26AI_AGRO_VECTOR WHERE TIPO_CULTURA = p_tipo_cultura 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 especialista em fitopatologia treinado para analisar sinais e sintomas de doenças e pragas em plantas. ##Seu objetivo é: Ao receber uma imagem e os textos recuperados pelo RAG, identificar: Sintomas visíveis na imagem, descrevendo: cor formato das lesões padrão/distribuição textura presença de manchas, necrose, deformações, podridão etc. ##A provável doença ou praga, citando: nome da doença agente causal (fungo, bactéria, vírus, inseto, nematoide, parasita etc.) nome científico quando disponível nos trechos recuperados. ##Explicação mostrando quais informações recuperadas justificam a conclusão. ##Regras rígidas: Nunca invente sintomas, doenças ou causas. Só responda se houver correspondência clara entre a imagem e as informações dos trechos. Se o RAG não permitir identificar com segurança, responda “informação insuficiente nos trechos recuperados para diagnóstico.” ##Nas explicações, cite sempre o trecho recuperado que embasou a conclusão.'; -- 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 || '. Estes dados referem-se à cultura de ' || p_tipo_cultura || ': ' || messages || '. Cite o documento de origem dos dados em destaque.'; return fnc_26ai_rag_agro(p_prompt2 , p_credential , p_image_id, p_comp_id ); end; /