2023年11月10日金曜日

Oracle APEXのアプリケーションからOpenAIのAssistants APIを呼び出す

OpenAIよりAssistants APIのベータ版がリリースされました。Oracle APEXよりAssistants APIを呼び出すアプリケーションを作成してみました。

2023年12月1日追記

OpenAIのAssistants APIよりList threadsが削除されたようです。そのためThreadsの扱いは変更する必要があります。

以下の動画は、Assistants APIのOverviewで紹介されている手順を実行しています。


Assistants APIを呼び出すPL/SQLのパッケージをUTL_OPENAI_ASSISTANTS_APIとして作成しています。パッケージのコードは、本記事の最後に添付しています。

Assistants APIでは、オブジェクトのタイプとしてassistantassistant.filethreadmessagemessage.filerunrun.stepを定義し、それぞれのオブジェクトにCreateModifyRetrieveDeleteList(厳密にいうとListはオブジェクトへの操作ではありません)の操作を実装しています。オブジェクトのタイプによっては、一部の操作は実装されていません。例えば、messageオブジェクトにDelete操作はありません。これ以外の特別なAPIとしては、Submit tool outputs to runCreate thread and runCancel a runがあります。パッケージUTL_OPENAI_ASSISTANTS_APIにはCreate thread and runの呼び出しは含まれていません。また、List操作はRESTデータ・ソースとして作成したので、パッケージにList操作を呼び出すファンクションは含まれていません。

オブジェクト・タイプが定義されていて、それぞれのオブジェクトにいわゆるCRUD操作(Create、Read、Update、Delete)があるので、Oracle APEXとしては扱いやすい形式です。ただし、RESTサービスからはAPEXアプリケーションを自動生成することはできません。

OpenAIのAssistants APIのリファレンスには、ぞれぞれのオブジェクト・タイプの定義が記載されています。その情報を元に、仮のスキーマを生成します。クイックSQLの以下のモデルからスキーマを生成します。

# prefix: openaisc
# pk: guid
# genpk: false
assistants
id vc40
object vc40 /default assistant
created_at num
name vc256
description vc512
model vc40
instructions clob
tools json
file_ids json
metadata json
assistant_files
id vc40
object vc40 /default assistant.file
created_at num
assistant_id /fk assistants
threads
id vc40
object vc40 /default thread
created_at num
metadata json
messages
id vc40
object vc40 /default thread.message
created_at num
thread_id /fk threads
role vc16 /check user,assistant
content json
assistant_id /fk assistants
file_ids json
metadata json
message_files
id vc40
object vc40 /default thread.message.file
created_at num
message_id /fk messages
runs
id vc40
object vc40 /default thread.run
created_at num
thread_id /fk threads
assistant_id /fk assistants
status vc16 /check queued,in_progress,requires_action,cancelling,cancelled,failed,completed,expired
required_action json
last_error json
expires_at num
started_at num
cancelled_at num
failed_at num
completed_at num
model vc40
instructions clob
tools json
file_ids json
metadata json
run_steps
id vc40
object vc40 /default thread.run.step
created_at num
assistant_id /fk assistants
thread_id /fk threads
run_id /fk runs
type vc20 /check message_creation,tool_calls
status vc16 /check in_progress,cancelled,failed,completed,expired
step_details json
last_error json
expired_at num
cancelled_at num
failed_at num
completed_at num
metadata json
view raw openaisc.model hosted with ❤ by GitHub

SQLの生成SQLスクリプトの保存レビューおよび実行を行います。SQLの実行を確認する画面では、即時実行をクリックします。


SQLスクリプトが実行され、表や索引がすべて生成された時点で、アプリケーションの作成を実行します。


アプリケーション作成ウィザードが起動します。AssistantsThreadsMessagesといったすべてのオブジェクト・タイプに対応したフォーム付き対話モード・レポートのページが追加されています。

アプリケーションの作成を実行します。


アプリケーションが作成されます。このアプリケーションを元に、データ・ソースやプロセスをAssistants APIを呼び出すように、置き換えていきます。


アプリケーション作成直後の状態です。


Assistantsを開くと、Assistantsを一覧する対話モード・レポートのページが表示されます。

作成をクリックします。


オブジェクトAssistantsが持つ属性の入力画面が、画面右よりドロワーとして開きます。


ページ・デザイナを開きます。

フォームが開く時に、データ・ソースより値を取り出しページ・アイテムに設定するプロセス初期化フォームAssistantが作成されています。

このプロセスをAssistants APIのRetrieve assistant APIの呼び出しに置き換えます。

識別名前Retrieve assistantタイプとしてAPIの呼び出しを選択します。設定タイプPL/SQL Packageを選択し、パッケージとしてUTL_OPENAI_ASSISTANTS_APIを設定します。プロシージャまたはファンクション名RETRIEVE_ASSISTANTです。

サーバー側の条件タイプアイテムはNULLではないを選択し、アイテムとしてP3_IDを選択します。


パッケージUTL_OPENAI_ASSISTANTS_APIに実装したファンクションは、ファンクションの結果としてID値を返すようにしています。この値は、パラメータにP3_ASSISTANT_IDとして含まれています。そのため、出力を無視します。


オブジェクトAssistantの主キーとなる属性はassistant_idですが、仮に作成した表では主キーとなる列はすべてIDになっています。そのため、主キーに対応するパラメータ(Assistantではp_assistant_id)に、手動で主キーとなるページ・アイテム(今回の例ではP3_ID)を割り当てます。


また、デバッグ用に出力パラメータとしてp_responseを定義しています。APEXのプロセスから呼び出す際は、出力を無視します。


以上でフォームにデータを読み込むプロセスの置き換えができました。


左ペインでプロセス・ビューを開き、データの挿入、更新、削除を行なうプロセスを置き換えます。

最初にプロセスを削除します。


ボタンCREATEをクリックしたときに実行するプロセスを作成します。呼び出されるファンクションCREATE_ASSISTANTです。


CREATEの場合は、ファンクションの結果が主キーの値なので、値のアイテムにP3_IDを割り当てます。


デバッグ用のパラメータp_response出力は無視します。


同様の手順で、プロセスModify assistantおよびDelete assistantを作成すると、オブジェクトAssistantの操作の実装は完了です。


Assistantの一覧を取得するRESTデータ・ソースを作成します。1つ以上のAssistantを作成した後に作業を行います。データがないとデータ・プロファイルは自動的に生成されません。

共有コンポーネントRESTデータ・ソースを開きます。


作成をクリックします。


RESTデータ・ソースの作成最初からを選びます。

に進みます。


RESTデータ・ソース・タイプとして簡易HTTPを選択します。名前List assistantsとします。

URLエンドポイントはOpenAIのAPI Referenceより、以下を指定します。

https://api.openai.com/v1/assistants


List messagesのようにパスに変数が含まれる場合は、以下のように{thread_id}といった記述を:thread_idに置き換えます。

https://api.openai.com/v1/threads/{thread_id}/messages

以下に置き換えて設定します。

https://api.openai.com/v1/threads/:thread_id/messages

このようにURLに含まれるコロンで始まる名前は、URLパラメータとして認識されます。データ・プロファイルを自動生成するために、1行はデータが返される値を設定します。


リモート・サーバーサービスURLパスの設定を確認し、へ進みます。


Assistants APIのページングの仕様が不明だったため、ページ区切りタイプとしてページ区切りなしを選択しています。

へ進みます。


認証が必要ですオンにして、OpenAIのAPIを呼び出すために使用するWeb資格証明を設定します。

Assistants APIを呼び出すためには、特別なHTTPヘッダーを設定する必要があります。そのため、ここでは検出を実行できません。RESTソースの手動作成をクリックします。


RESTデータ・ソースが作成されます。編集画面を開きます。


パラメータのセクションより、パラメータの作成をクリックします。


パラメータタイプとしてHTTPヘッダーを選択し、名前OpenAI-Betaを指定します。デフォルト値assistants=v1です。静的オンにします。これでREST API呼び出し時にHTTPヘッダーとして以下が追加されます。

OpenAI-Beta: assistants=v1


同様にHTTPヘッダーとしてContent-Type: application/jsonも追加します。


必要なHTTPヘッダーが追加され、OpenAIのAssistants APIを呼び出せるようになりました。


データ・プロファイルの編集をクリックします。


Assistants APIのList操作の行セレクタdataになります。行セレクタdataを指定し、データ・プロファイルの再検出をクリックします。


List操作で返されるレスポンスにデータが含まれていれば、データ・プロファイルとして含まれる属性(列)が自動的に生成されます。

データ・プロファイルの置換をクリックします。


以上でRESTデータ・ソースの作成は完了です。変更の適用をクリックし、RESTデータ・ソースの編集画面を閉じます。


RESTデータ・ソースが作成されたら、対応する対話モード・レポートのソース位置RESTソースに変更し、RESTソースを作成したRESTデータ・ソースに変更します。


データ・ソースの設定を変更すると、対話モード・レポートにOpenAI側に作成されているオブジェクトが一覧されます。


以上が基本的な実装手順です。

オブジェクトMessageの場合のように、List messages APIで一覧を取得する際にthread_idが必要な場合は、レポートのページにページ・アイテム(この例ではP8_THREAD_ID)を作成し、それをパラメータに割り当てます。


Threadを一覧するページから、Threadを選択してMessagesのページを開くように、対話モード・レポートリンクを設定します。


オブジェクトrunのように、レポートから詳細画面を開く際に主キーの値(runの場合はrun_id)だけでなく、別のIDが必要な場合があります(runの場合はthread_id)。

デフォルトでは主キーの列だけが設定されているため、アイテムの設定にページ・アイテムと値のペアを追加する必要があります。


オブジェクトのRetrieve呼び出しで取り出せる属性の数は、ほとんどの場合、CreateやModifyで設定できる属性の数より多くなっています。Retrieveで取り出せるがCreateやModifyには含まれていない属性は、読み出しのみの属性です。そのため、フォームのページ・アイテムのタイプ表示のみに変更します。


タイプ表示のみにし、設定ページの送信時に送信オフにします。


このような作業を行なって作成したAPEXアプリケーションのエクスポートを、以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/openai-assistants-sample.zip

Oracle APEXのアプリケーション作成の参考になれば幸いです。


パッケージUTL_OPENAI_ASSISTANTS_APIのコードです。長いですが、実装している処理は単純です。

create or replace package utl_openai_assistants_api
as
/* Assistantの作成 */
function create_assistant(
p_model in varchar2
,p_name in varchar2 default null
,p_description in varchar2 default null
,p_instructions in clob default null
,p_tools in clob default null
,p_file_ids in clob default null
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Assistantの取得 */
function retrieve_assistant(
p_assistant_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_model out varchar2
,p_name out varchar2
,p_description out varchar2
,p_instructions out clob
,p_tools out clob
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
/* Assistantの更新 */
function modify_assistant(
p_assistant_id in varchar2
,p_model in varchar2 default null
,p_name in varchar2 default null
,p_description in varchar2 default null
,p_instructions in clob default null
,p_tools in clob default null
,p_file_ids in clob default null
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Assistantの削除 */
function delete_assistant(
p_assistant_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_deleted out boolean
)
return varchar2;
/* Assistant fileの作成 */
function create_assistant_file(
p_assistant_id in varchar2
,p_file_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Assistant fileの取得 */
function retrieve_assistant_file(
p_assistant_id in varchar2
,p_file_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
/* Assistant fileの削除 */
function delete_assistant_file(
p_assistant_id in varchar2
,p_file_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_deleted out boolean
)
return varchar2;
/* Threadの作成 */
function create_thread(
p_messages in clob default null
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Threadの取得 */
function retrieve_thread(
p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
/* Threadの更新 */
function modify_thread(
p_thread_id in varchar2
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Threadの削除 */
function delete_thread(
p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_deleted out boolean
)
return varchar2;
/* Messageの作成 */
function create_message(
p_thread_id in varchar2
,p_role in varchar2 default 'user'
,p_content in varchar2
,p_file_ids in clob default null
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Messageの取得 */
function retrieve_message(
p_message_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_role out varchar2
,p_content out clob
,p_assistant_id out varchar2
,p_run_id out varchar2
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
/* Messageの更新 */
function modify_message(
p_message_id in varchar2
,p_thread_id in varchar2
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Message fileの取得 */
function retrieve_message_file(
p_file_id in varchar2
,p_message_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
/* Runの作成 */
function create_run(
p_thread_id in varchar2
,p_assistant_id in varchar2
,p_model in varchar2 default null
,p_instructions in varchar2 default null
,p_tools in clob default null
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Runの取得 */
function retrieve_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_assistant_id out varchar2
,p_status out varchar2
,p_started_at out number
,p_expires_at out number
,p_cancelled_at out number
,p_failed_at out number
,p_completed_at out number
,p_last_error out clob
,p_model out varchar2
,p_instructions out clob
,p_tools out clob
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
/* Runの修正 */
function modify_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Submit tool outputs to run */
function submit_tool_outputs_to_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_tool_outputs in clob
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_assistant_id out varchar2
,p_status out varchar2
,p_started_at out number
,p_expires_at out number
,p_cancelled_at out number
,p_failed_at out number
,p_completed_at out number
,p_last_error out clob
,p_model out varchar2
,p_instructions out clob
,p_tools out clob
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
/* Runのキャンセル */
function cancel_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2;
/* Run Stepの取得 */
function retrieve_run_step(
p_step_id in varchar2
,p_run_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_assistant_id out varchar2
,p_type out varchar2
,p_status out varchar2
,p_step_details out clob
,p_last_error out clob
,p_expired_at out number
,p_cancelled_at out number
,p_failed_at out number
,p_completed_at out number
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2;
end utl_openai_assistants_api;
/
create or replace package body utl_openai_assistants_api
as
/* put attribute if not null */
procedure put_if_exists(
p_json in out json_object_t
,p_name in varchar2
,p_value in varchar2
)
as
begin
if p_value is not null then
p_json.put(p_name, p_value);
end if;
end put_if_exists;
procedure put_if_exists(
p_json in out json_object_t
,p_name in varchar2
,p_value in clob
)
as
begin
if p_value is not null then
p_json.put(p_name, p_value);
end if;
end put_if_exists;
procedure put_if_exists_array(
p_json in out json_object_t
,p_name in varchar2
,p_value in clob
)
as
l_array json_array_t;
begin
if p_value is not null then
l_array := json_array_t(p_value);
p_json.put(p_name, l_array);
end if;
end put_if_exists_array;
procedure put_if_exists_object(
p_json in out json_object_t
,p_name in varchar2
,p_value in clob
)
as
l_object json_object_t;
begin
if p_value is not null then
l_object := json_object_t(p_value);
p_json.put(p_name, l_object);
end if;
end put_if_exists_object;
function get_if_exists_array(
p_json in json_object_t
,p_name in varchar2
)
return clob
as
l_array json_array_t;
l_value clob := null;
begin
l_array := p_json.get_array(p_name);
if l_array is not null then
l_value := l_array.to_clob();
end if;
return l_value;
end get_if_exists_array;
function get_if_exists_object(
p_json in json_object_t
,p_name in varchar2
)
return clob
as
l_object json_object_t;
l_value clob := null;
begin
l_object := p_json.get_object(p_name);
if l_object is not null then
l_value := l_object.to_clob();
end if;
return l_value;
end get_if_exists_object;
/* Private function to call OpenAI API with POST method (Create or Modify) */
function call_openai_api(
p_url in varchar2
,p_request in json_object_t default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2
as
l_request clob;
l_response clob;
l_response_json json_object_t;
l_id varchar2(40);
e_api_call_failed exception;
begin
if p_request is not null then
l_request := p_request.to_clob();
else
l_request := null;
end if;
apex_web_service.clear_request_headers;
apex_web_service.set_request_headers('OpenAI-Beta','assistants=v1',p_reset => false);
apex_web_service.set_request_headers('Content-Type','application/json',p_reset => false);
l_response := apex_web_service.make_rest_request(
p_url => p_url
,p_http_method => 'POST'
,p_body => l_request
,p_credential_static_id => p_credential_static_id
);
if apex_web_service.g_status_code <> 200 then
apex_debug.info('status = %s, reseponse = %s', apex_web_service.g_status_code, l_response);
raise e_api_call_failed;
end if;
l_response_json := json_object_t(l_response);
l_id := l_response_json.get_string('id');
p_response := l_response;
return l_id;
end call_openai_api;
/* Private function to call OpenAI API with GET method (Retrieve) */
function call_openai_api_retrieve(
p_url in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
l_response clob;
l_response_json json_object_t;
l_id varchar2(40);
e_api_call_failed exception;
begin
apex_web_service.clear_request_headers;
apex_web_service.set_request_headers('OpenAI-Beta','assistants=v1',p_reset => false);
apex_web_service.set_request_headers('Content-Type','application/json',p_reset => false);
l_response := apex_web_service.make_rest_request(
p_url => p_url
,p_http_method => 'GET'
,p_credential_static_id => p_credential_static_id
);
if apex_web_service.g_status_code <> 200 then
apex_debug.info('status = %s, reseponse = %s', apex_web_service.g_status_code, l_response);
raise e_api_call_failed;
end if;
l_response_json := json_object_t(l_response);
p_object := l_response_json.get_string('object');
p_created_at := l_response_json.get_number('created_at');
l_id := l_response_json.get_string('id');
p_response := l_response;
return l_id;
end call_openai_api_retrieve;
function call_openai_api_delete(
p_url in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_deleted out boolean
)
return varchar2
as
l_request clob;
l_response clob;
l_response_json json_object_t;
l_id varchar2(40);
e_api_call_failed exception;
begin
apex_web_service.clear_request_headers;
apex_web_service.set_request_headers('OpenAI-Beta','assistants=v1',p_reset => false);
apex_web_service.set_request_headers('Content-Type','application/json',p_reset => false);
l_response := apex_web_service.make_rest_request(
p_url => p_url
,p_http_method => 'DELETE'
,p_credential_static_id => p_credential_static_id
);
if apex_web_service.g_status_code <> 200 then
apex_debug.info('status = %s, reseponse = %s', apex_web_service.g_status_code, l_response);
raise e_api_call_failed;
end if;
l_response_json := json_object_t(l_response);
l_id := l_response_json.get_string('id');
p_object := l_response_json.get_string('object');
p_deleted := l_response_json.get_boolean('deleted');
p_response := l_response;
return l_id;
end call_openai_api_delete;
/*
* Create assistant
* Ref: https://platform.openai.com/docs/api-reference/assistants/createAssistant
*/
function create_assistant(
p_model in varchar2
,p_name in varchar2
,p_description in varchar2
,p_instructions in clob
,p_tools in clob
,p_file_ids in clob
,p_metadata in clob
,p_credential_static_id in varchar2
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
l_request.put('model', p_model);
put_if_exists(l_request,'name',p_name);
put_if_exists(l_request,'description',p_description);
put_if_exists(l_request,'instructions',p_instructions);
put_if_exists_array(l_request,'tools',p_tools);
put_if_exists_array(l_request,'file_ids',p_file_ids);
put_if_exists_object(l_request,'metadata',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/assistants'
,p_request => l_request
,p_response => p_response
);
end create_assistant;
/*
* Retrieve assistant
* Ref: https://platform.openai.com/docs/api-reference/assistants/getAssistant
*/
function retrieve_assistant(
p_assistant_id in varchar2
,p_credential_static_id in varchar2
,p_response out clob
,p_model out varchar2
,p_name out varchar2
,p_description out varchar2
,p_instructions out clob
,p_tools out clob
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
l_id varchar2(40);
l_response_clob clob;
l_response json_object_t;
begin
l_id := call_openai_api_retrieve(
p_url => 'https://api.openai.com/v1/assistants/' || p_assistant_id
,p_response => l_response_clob
,p_object => p_object
,p_created_at => p_created_at
);
l_response := json_object_t(l_response_clob);
p_model := l_response.get_string('model');
p_name := l_response.get_string('name');
p_description := l_response.get_string('description');
p_instructions := l_response.get_string('instructions');
p_tools := get_if_exists_array(l_response, 'tools');
p_file_ids := get_if_exists_array(l_response, 'file_ids');
p_metadata := get_if_exists_object(l_response, 'metadata');
p_response := l_response_clob;
return l_id;
end retrieve_assistant;
/*
* Modify assistant
* Ref: https://platform.openai.com/docs/api-reference/assistants/modifyAssistant
*/
function modify_assistant(
p_assistant_id in varchar2
,p_model in varchar2
,p_name in varchar2
,p_description in varchar2
,p_instructions in clob
,p_tools in clob
,p_file_ids in clob
,p_metadata in clob
,p_credential_static_id in varchar2
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
put_if_exists(l_request,'model',p_model);
put_if_exists(l_request,'name',p_name);
put_if_exists(l_request,'description',p_description);
put_if_exists(l_request,'instructions',p_instructions);
put_if_exists_array(l_request,'tools',p_tools);
put_if_exists_array(l_request,'file_ids',p_file_ids);
put_if_exists_object(l_request,'metadata',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/assistants/' || p_assistant_id
,p_request => l_request
,p_response => p_response
);
end modify_assistant;
/*
* Delete assistant
* Ref: https://platform.openai.com/docs/api-reference/assistants/modifyAssistant
*/
function delete_assistant(
p_assistant_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_deleted out boolean
)
return varchar2
as
begin
return call_openai_api_delete(
p_url => 'https://api.openai.com/v1/assistants/' || p_assistant_id
,p_response => p_response
,p_object => p_object
,p_deleted => p_deleted
);
end delete_assistant;
/**
* Create assistant file
* Ref: https://platform.openai.com/docs/api-reference/assistants/createAssistantFile
*/
function create_assistant_file(
p_assistant_id in varchar2
,p_file_id in varchar2
,p_credential_static_id in varchar2
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
l_request.put('file_id', p_file_id);
return call_openai_api(
p_url => 'https://api.openai.com/v1/assistants/' || p_assistant_id || '/files'
,p_request => l_request
,p_response => p_response
);
end create_assistant_file;
/**
* Retrieve assistant file
* Ref: https://platform.openai.com/docs/api-reference/assistants/getAssistantFile
*/
function retrieve_assistant_file(
p_assistant_id in varchar2
,p_file_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
begin
return call_openai_api_retrieve(
p_url => 'https://api.openai.com/v1/assistants/' || p_assistant_id || '/files/' || p_file_id
,p_response => p_response
,p_object => p_object
,p_created_at => p_created_at
);
end retrieve_assistant_file;
/**
* Delete assistant file
* Ref: https://platform.openai.com/docs/api-reference/assistants/deleteAssistantFile
*/
function delete_assistant_file(
p_assistant_id in varchar2
,p_file_id in varchar2
,p_credential_static_id in varchar2
,p_response out clob
,p_object out varchar2
,p_deleted out boolean
)
return varchar2
as
begin
return call_openai_api_delete(
p_url => 'https://api.openai.com/v1/assistants/' || p_assistant_id || '/files/' || p_file_id
,p_response => p_response
,p_object => p_object
,p_deleted => p_deleted
);
end delete_assistant_file;
/*
* Create thread
* Ref: https://platform.openai.com/docs/api-reference/threads/createThread
*/
function create_thread(
p_messages in clob default null
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
put_if_exists_array(l_request,'messages',p_messages);
put_if_exists_object(l_request,'metadata',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/threads'
,p_request => l_request
,p_response => p_response
);
end create_thread;
/**
* Retrieve thread
* Ref: https://platform.openai.com/docs/api-reference/threads/getThread
*/
function retrieve_thread(
p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
l_id varchar2(40);
l_response_clob clob;
l_response json_object_t;
begin
l_id := call_openai_api_retrieve(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id
,p_response => l_response_clob
,p_object => p_object
,p_created_at => p_created_at
);
l_response := json_object_t(l_response_clob);
p_metadata := get_if_exists_object(l_response,'metadata');
p_response := l_response_clob;
return l_id;
end retrieve_thread;
/**
* Modify thread
* Ref: https://platform.openai.com/docs/api-reference/threads/modifyThread
*/
function modify_thread(
p_thread_id in varchar2
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
put_if_exists_object(l_request,'metadata',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id
,p_request => l_request
,p_response => p_response
);
end modify_thread;
/**
* Delete thread
* Ref: https://platform.openai.com/docs/api-reference/threads/deleteThread
*/
function delete_thread(
p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_deleted out boolean
)
return varchar2
as
begin
return call_openai_api_delete(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id
,p_response => p_response
,p_object => p_object
,p_deleted => p_deleted
);
end delete_thread;
/*
* Create message
* Ref: https://platform.openai.com/docs/api-reference/messages/createMessage
*/
function create_message(
p_thread_id in varchar2
,p_role in varchar2
,p_content in varchar2
,p_file_ids in clob default null
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
l_request.put('role', p_role);
l_request.put('content', p_content);
put_if_exists_array(l_request,'file_ids',p_file_ids);
put_if_exists_object(l_request,'metatada',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/messages'
,p_request => l_request
,p_response => p_response
);
end create_message;
/**
* Retrieve message
* Ref: https://platform.openai.com/docs/api-reference/messages/getMessage
*/
function retrieve_message(
p_message_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_role out varchar2
,p_content out clob
,p_assistant_id out varchar2
,p_run_id out varchar2
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
l_id varchar2(40);
l_response_clob clob;
l_response json_object_t;
begin
l_id := call_openai_api_retrieve(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/messages/' || p_message_id
,p_response => l_response_clob
,p_object => p_object
,p_created_at => p_created_at
);
l_response := json_object_t(l_response_clob);
p_role := l_response.get_string('role');
p_content := get_if_exists_array(l_response,'content');
p_assistant_id := l_response.get_string('assistant_id');
p_run_id := l_response.get_string('run_id');
p_file_ids := get_if_exists_array(l_response,'file_ids');
p_metadata := get_if_exists_object(l_response,'metadata');
p_response := l_response_clob;
return l_id;
end retrieve_message;
/**
* Modify message
* Ref: https://platform.openai.com/docs/api-reference/messages/modifyMessage
*/
function modify_message(
p_message_id in varchar2
,p_thread_id in varchar2
,p_metadata in clob
,p_credential_static_id in varchar2
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
put_if_exists_object(l_request,'metadata',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/messages/' || p_message_id
,p_request => l_request
,p_response => p_response
);
end modify_message;
/**
* Retrieve message file
* Ref: https://platform.openai.com/docs/api-reference/messages/getMessageFile
*/
function retrieve_message_file(
p_file_id in varchar2
,p_message_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
begin
return call_openai_api_retrieve(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/messages/' || p_message_id || '/files/' || p_file_id
,p_response => p_response
,p_object => p_object
,p_created_at => p_created_at
);
end retrieve_message_file;
/**
* Create run
* Ref: https://platform.openai.com/docs/api-reference/runs/createRun
*/
function create_run(
p_thread_id in varchar2
,p_assistant_id in varchar2
,p_model in varchar2
,p_instructions in varchar2
,p_tools in clob
,p_metadata in clob
,p_credential_static_id in varchar2
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
l_request.put('assistant_id', p_assistant_id);
put_if_exists(l_request,'model',p_model);
put_if_exists(l_request,'instructions',p_instructions);
put_if_exists_array(l_request,'tools',p_tools);
put_if_exists_object(l_request,'metadata',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/runs'
,p_request => l_request
,p_response => p_response
);
end create_run;
/**
* Retieve run
* Ref: https://platform.openai.com/docs/api-reference/runs/getRun
*/
function retrieve_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_assistant_id out varchar2
,p_status out varchar2
,p_started_at out number
,p_expires_at out number
,p_cancelled_at out number
,p_failed_at out number
,p_completed_at out number
,p_last_error out clob
,p_model out varchar2
,p_instructions out clob
,p_tools out clob
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
l_id varchar2(40);
l_response_clob clob;
l_response json_object_t;
begin
l_id := call_openai_api_retrieve(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/runs/' || p_run_id
,p_response => l_response_clob
,p_object => p_object
,p_created_at => p_created_at
);
l_response := json_object_t(l_response_clob);
p_assistant_id := l_response.get_string('assistant_id');
p_status := l_response.get_string('status');
p_started_at := l_response.get_number('started_at');
p_expires_at := l_response.get_number('expires_at');
p_cancelled_at := l_response.get_number('cancelled_at');
p_failed_at := l_response.get_number('failed_at');
p_completed_at := l_response.get_number('completed_at');
p_last_error := get_if_exists_object(l_response,'last_error');
p_model := l_response.get_string('model');
p_instructions := l_response.get_clob('instructions');
p_tools := get_if_exists_array(l_response,'tools');
p_file_ids := get_if_exists_array(l_response,'file_ids');
p_metadata := get_if_exists_object(l_response,'metadata');
p_response := l_response_clob;
return l_id;
end retrieve_run;
/**
* Modify run
* Ref: https://platform.openai.com/docs/api-reference/runs/modifyRun
*/
function modify_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_metadata in clob default null
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2
as
l_request json_object_t := json_object_t();
begin
put_if_exists_object(l_request,'metadata',p_metadata);
return call_openai_api(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/runs/' || p_run_id
,p_request => l_request
,p_response => p_response
);
end modify_run;
/**
* Submit tool outputs to run
* Ref: https://platform.openai.com/docs/api-reference/runs/submitToolOutputs
*/
function submit_tool_outputs_to_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_tool_outputs in clob
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_assistant_id out varchar2
,p_status out varchar2
,p_started_at out number
,p_expires_at out number
,p_cancelled_at out number
,p_failed_at out number
,p_completed_at out number
,p_last_error out clob
,p_model out varchar2
,p_instructions out clob
,p_tools out clob
,p_file_ids out clob
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
l_id varchar2(40);
l_request json_object_t := json_object_t();
l_response_clob clob;
l_response json_object_t;
begin
put_if_exists_array(l_request,'tool_outputs',p_tool_outputs);
l_id := call_openai_api(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/runs/' || p_run_id || '/submit_tool_outputs'
,p_request => l_request
,p_response => l_response_clob
);
l_response := json_object_t(l_response_clob);
p_assistant_id := l_response.get_string('assistant_id');
p_status := l_response.get_string('status');
p_started_at := l_response.get_number('started_at');
p_expires_at := l_response.get_number('expires_at');
p_cancelled_at := l_response.get_number('cancelled_at');
p_failed_at := l_response.get_number('failed_at');
p_completed_at := l_response.get_number('completed_at');
p_last_error := get_if_exists_object(l_response,'last_error');
p_model := l_response.get_string('model');
p_instructions := l_response.get_clob('instructions');
p_tools := get_if_exists_array(l_response,'tools');
p_file_ids := get_if_exists_array(l_response,'file_ids');
p_metadata := get_if_exists_object(l_response,'metadata');
p_object := l_response.get_string('object');
p_created_at := l_response.get_number('created_at');
p_response := l_response_clob;
return l_id;
end submit_tool_outputs_to_run;
/**
* Cancel run
* Ref: https://platform.openai.com/docs/api-reference/runs/cancelRun
*/
function cancel_run(
p_run_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
)
return varchar2
as
begin
return call_openai_api(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/runs/' || p_run_id || '/cancel'
,p_response => p_response
);
end cancel_run;
/**
* Retrieve run step
* Ref: https://platform.openai.com/docs/api-reference/runs/getRunStep
*/
function retrieve_run_step(
p_step_id in varchar2
,p_run_id in varchar2
,p_thread_id in varchar2
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY'
,p_response out clob
,p_assistant_id out varchar2
,p_type out varchar2
,p_status out varchar2
,p_step_details out clob
,p_last_error out clob
,p_expired_at out number
,p_cancelled_at out number
,p_failed_at out number
,p_completed_at out number
,p_metadata out clob
,p_object out varchar2
,p_created_at out number
)
return varchar2
as
l_id varchar2(40);
l_response_clob clob;
l_response json_object_t;
begin
l_id := call_openai_api_retrieve(
p_url => 'https://api.openai.com/v1/threads/' || p_thread_id || '/runs/' || p_run_id || '/steps/' || p_step_id
,p_response => l_response_clob
,p_object => p_object
,p_created_at => p_created_at
);
l_response := json_object_t(l_response_clob);
p_assistant_id := l_response.get_string('assistant_id');
p_type := l_response.get_string('type');
p_status := l_response.get_string('status');
p_step_details := get_if_exists_object(l_response,'step_details');
p_last_error := get_if_exists_object(l_response,'last_error');
p_expired_at := l_response.get_number('expired_at');
p_cancelled_at := l_response.get_number('cancelled_at');
p_failed_at := l_response.get_number('failed_at');
p_completed_at := l_response.get_number('completed_at');
p_metadata := get_if_exists_object(l_response,'metadata');
p_response := l_response_clob;
return l_id;
end retrieve_run_step;
end utl_openai_assistants_api;
/