【GeminiAPI】OracleAPEXから接続する方法（備忘録）

＜備忘録＞
備忘録として残したいがための記事です。

普段はPythonのプログラムをFunctionsを用いて実行しているが直接呼ばないと処理が遅くなるため、GeminiAPIをOracleAPEXで実行したいが、ためにやってみた。

~~~
declare
    l_url varchar2(1000);
    l_request clob;
    l_response clob;
    l_text clob;
begin
    l_url := 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=（APIキー）';

    l_request := q'~{
      "contents": [
        {
          "parts": [
            {
              "text": "Write a story about a magic backpack"
            }
          ]
        }
      ]
    }~';

    apex_web_service.clear_request_headers();
    apex_web_service.set_request_headers('Content-Type','application/json');

    l_response := apex_web_service.make_rest_request(
        p_url => l_url,
        p_http_method => 'POST',
        p_body => l_request
    );

    dbms_output.put_line('レスポンス: ' || l_response);
    apex_json.parse(l_response);
    l_text := apex_json.get_clob(p_path => 'candidates[1].content.parts[1].text');
    dbms_output.put_line('本文:');
    dbms_output.put_line(l_text);
exception
    when others then
        dbms_output.put_line('エラー: ' || SQLERRM);
end;
~~~

このPartsのtext内容を修正することで利用できます！

4月11日追記
　思ったより、ここからてこずったので追記します。
最終的に以下の記載にしたらうまくいった。
~~~
create or replace FUNCTION HTTP_REQUEST_SUMMARY_GEMINI(
    p_text     CLOB,
    l_preamble CLOB,
    p_user_id  VARCHAR2
) RETURN CLOB IS
    l_url             VARCHAR2(1000);
    l_request         json_object_t;
    l_request_clob    CLOB;
    l_messages        json_array_t := json_array_t();
    l_user_msg        json_object_t := json_object_t();
    l_sys_msg         json_object_t := json_object_t();
    l_part_user       json_object_t := json_object_t();
    l_part_sys        json_object_t := json_object_t();
    l_parts_user      json_array_t := json_array_t();
    l_parts_sys       json_array_t := json_array_t();
    l_response_clob   CLOB;
    l_content         CLOB;
    l_input_tokens    VARCHAR2(255); 
    l_output_tokens   VARCHAR2(255);
    l_prompt_tokens   NUMBER;
    l_completion_tokens NUMBER;
    l_total_tokens    NUMBER;
BEGIN
    APEX_DEBUG.INFO('GEMINI要約スタート');
    APEX_DEBUG.ENABLE;

     -- 前提条件とテキストを結合
    l_part_user := json_object_t();
    l_part_user.put('text', l_preamble || CHR(10) || p_text);
    l_parts_user.append(l_part_user);

    -- user メッセージを作成
    l_user_msg.put('role', 'user');
    l_user_msg.put('parts', l_parts_user);
    l_messages.append(l_user_msg);

    -- リクエスト生成
    l_request := json_object_t();
    l_request.put('contents', l_messages);
    l_request_clob := l_request.to_clob;

    -- HTTP ヘッダ設定
    apex_web_service.clear_request_headers();
    apex_web_service.set_request_headers('Content-Type', 'application/json');

    l_url := 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=（APIキー）';

    l_response_clob := apex_web_service.make_rest_request(
        p_url         => l_url,
        p_http_method => 'POST',
        p_body        => l_request_clob
    );

    APEX_DEBUG.INFO('API連携直後: ' || l_response_clob);

    -- レスポンス処理
    apex_json.parse(l_response_clob);
    l_content := apex_json.get_clob(p_path => 'candidates[1].content.parts[1].text');

    l_input_tokens  := apex_json.get_number(p_path => 'usageMetadata.promptTokenCount');
    l_output_tokens := apex_json.get_number(p_path => 'usageMetadata.candidatesTokenCount');

    -- 出力ログ
    dbms_output.put_line('入力トークン数: ' || l_input_tokens);
    dbms_output.put_line('出力トークン数: ' || l_output_tokens);

    RETURN l_content;
    APEX_DEBUG.DISABLE;
END HTTP_REQUEST_SUMMARY_GEMINI;
/
~~~

個人的なポイントは、GeminiのAPI連携では前提条件を入力する枠がないこと。
USERメッセージに埋め込んで渡す必要がある。

あと、返却された情報は一部配列になってるから表示する際の変数は、きちんと指定されたところを参照しないとエラーになる。

そんな感じで、うまくできるようになりました！

参考にシステムで利用してみてください(^^♪