OpenAIよりAssistants APIのベータ版がリリースされました。Oracle APEXよりAssistants APIを呼び出すアプリケーションを作成してみました。
2023年12月1日追記
OpenAIのAssistants APIよりList threadsが削除されたようです。そのためThreadsの扱いは変更する必要があります。
以下の動画は、Assistants APIのOverviewで紹介されている手順を実行しています。
Assistants APIでは、オブジェクトのタイプとしてassistant、assistant.file、thread、message、message.file、run、run.stepを定義し、それぞれのオブジェクトにCreate、Modify、Retrieve、Delete、List(厳密にいうとListはオブジェクトへの操作ではありません)の操作を実装しています。オブジェクトのタイプによっては、一部の操作は実装されていません。例えば、messageオブジェクトにDelete操作はありません。これ以外の特別なAPIとしては、Submit tool outputs to run、Create thread and run、Cancel 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の以下のモデルからスキーマを生成します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
SQLの生成、SQLスクリプトの保存、レビューおよび実行を行います。SQLの実行を確認する画面では、即時実行をクリックします。
SQLスクリプトが実行され、表や索引がすべて生成された時点で、アプリケーションの作成を実行します。
アプリケーション作成ウィザードが起動します。Assistants、Threads、Messagesといったすべてのオブジェクト・タイプに対応したフォーム付き対話モード・レポートのページが追加されています。
アプリケーションの作成を実行します。
アプリケーションが作成されます。このアプリケーションを元に、データ・ソースやプロセスを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を割り当てます。
同様の手順で、プロセス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も追加します。
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のアプリケーション作成の参考になれば幸いです。
完
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
/ |