最近ベータ版が出たAssistants APIに含まれる機能にretrievalとcode_interpreterがあります。これらの機能が使用するassistant fileは、purpose="assistants"でFilesにアップロードされているファイルのfile_idをassistant fileにアタッチするという仕様のようです。
Create assistant file
https://platform.openai.com/docs/api-reference/assistants/createAssistantFile
ファイルのアップロードができれば十分なので、あまり手の込んだ実装はしていません。
Downloadをクリックするとエラーが発生しました。エラー・メッセージを確認すると、そもそもpurposeがassistantsのファイルはダウンロード不可のようです。purposeがfine-tuneであればダウンロードできるのかもしれません。
body: { "error": { "message": "Not allowed to download files of purpose: assistants", "type": "invalid_request_error", "param": null, "code": null } }
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_files_api | |
as | |
/** | |
* OpenAI Upload fileを呼び出す。 | |
* 参照: https://platform.openai.com/docs/api-reference/files/create | |
* | |
* @param p_filename アップロードされるファイル名 | |
* @param p_content_type ファイル形式 | |
* @param p_file_content ファイル本体 | |
* @param p_purpose OpenAIでのファイルの用途 fine-tuneかassistantsのどちらか | |
* @param p_credential_static_id Web資格証明 | |
* @param p_file アップロードされたファイルのメタデータ JSON形式 | |
* @return file_id | |
*/ | |
function upload_file( | |
p_filename in varchar2 | |
,p_content_type in varchar2 | |
,p_file_content in blob | |
,p_purpose in varchar2 default 'assistants' | |
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY' | |
,p_file out clob | |
) | |
return varchar2; | |
/** | |
* OpenAI Retrieve file、Retrieve file contentを呼び出す。 | |
* 参照: https://platform.openai.com/docs/api-reference/files/retrieve | |
* 参照: https://platform.openai.com/docs/api-reference/files/retrieve-contents | |
* | |
* @param p_file_id file_id | |
* @param p_credential_static_id Web資格証明 | |
* @param p_file ファイルのメタデータ JSON形式 | |
* @param p_file_content ファイル本体 BLOB形式 | |
* @return file_id | |
*/ | |
function retrieve_file( | |
p_file_id in varchar2 | |
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY' | |
,p_file out clob | |
,p_file_content out blob | |
) | |
return varchar2; | |
/** | |
* OpenAI delete fileを呼び出す。 | |
* 参照: https://platform.openai.com/docs/api-reference/files/delete | |
* | |
* @param p_file_id file_id | |
* @param p_credential_static_id Web資格証明 | |
*/ | |
function delete_file( | |
p_file_id in varchar2 | |
,p_credential_static_id in varchar2 default 'OPENAI_API_KEY' | |
,p_file out clob | |
) | |
return varchar2; | |
end utl_openai_files_api; | |
/ | |
create or replace package body utl_openai_files_api | |
as | |
/** | |
* ファイルのアップロード | |
*/ | |
function upload_file( | |
p_filename in varchar2 | |
,p_content_type in varchar2 | |
,p_file_content in blob | |
,p_purpose in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_file out clob | |
) | |
return varchar2 | |
as | |
l_response clob; | |
l_multipart apex_web_service.t_multipart_parts; | |
l_multipart_request blob; | |
e_api_call_failed exception; | |
l_file json_object_t; | |
begin | |
apex_web_service.clear_request_headers; | |
/* | |
* アップロードするファイルを指定する。 | |
*/ | |
apex_web_service.append_to_multipart( | |
p_multipart => l_multipart | |
,p_name => 'file' | |
,p_filename => p_filename | |
,p_content_type => p_content_type | |
,p_body_blob => p_file_content | |
); | |
/* | |
* purposeを指定する。 | |
*/ | |
apex_web_service.append_to_multipart( | |
p_multipart => l_multipart | |
,p_name => 'purpose' | |
,p_content_type => 'text/plain' | |
,p_body => p_purpose | |
); | |
l_multipart_request := apex_web_service.generate_request_body(l_multipart); | |
l_response := apex_web_service.make_rest_request( | |
p_url => 'https://api.openai.com/v1/files' | |
,p_http_method => 'POST' | |
,p_body_blob => l_multipart_request | |
,p_credential_static_id => p_credential_static_id | |
); | |
if apex_web_service.g_status_code <> 200 then | |
apex_debug.info('status_code = %s, response = %s', apex_web_service.g_status_code, l_response); | |
raise e_api_call_failed; | |
end if; | |
p_file := l_response; | |
l_file := json_object_t(p_file); | |
return l_file.get_string('id'); | |
end upload_file; | |
/** | |
* ファイルのダウンロード | |
*/ | |
function retrieve_file( | |
p_file_id in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_file out clob | |
,p_file_content out blob | |
) | |
return varchar2 | |
as | |
l_url varchar2(400); | |
l_response clob; | |
e_api_call_failed exception; | |
l_file json_object_t; | |
begin | |
/* ファイルのメタデータの取得 */ | |
l_url := 'https://api.openai.com/v1/files/' || p_file_id; | |
apex_web_service.clear_request_headers; | |
l_response := apex_web_service.make_rest_request( | |
p_url => l_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_code = %s, response = %s', apex_web_service.g_status_code, l_response); | |
raise e_api_call_failed; | |
end if; | |
/* ファイルのメタデータをp_fileとして返す。 */ | |
p_file := l_response; | |
/* ファイルの内容をBOBとして取得する */ | |
l_url := l_url || '/content'; | |
apex_web_service.clear_request_headers; | |
p_file_content := apex_web_service.make_rest_request_b( | |
p_url => l_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_code = %s, failed to download file', apex_web_service.g_status_code); | |
raise e_api_call_failed; | |
end if; | |
l_file := json_object_t(p_file); | |
return l_file.get_string('id'); | |
end retrieve_file; | |
/** | |
* ファイルの削除 | |
*/ | |
function delete_file( | |
p_file_id in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_file out clob | |
) | |
return varchar2 | |
as | |
l_url varchar2(400); | |
l_response clob; | |
e_api_call_failed exception; | |
l_file json_object_t; | |
begin | |
/* ファイルのメタデータの取得 */ | |
l_url := 'https://api.openai.com/v1/files/' || p_file_id; | |
apex_web_service.clear_request_headers; | |
l_response := apex_web_service.make_rest_request( | |
p_url => l_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_code = %s, response = %s', apex_web_service.g_status_code, l_response); | |
raise e_api_call_failed; | |
end if; | |
/* 削除したファイルのメタデータをp_fileとして返す。 */ | |
p_file := l_response; | |
l_file := json_object_t(p_file); | |
return l_file.get_string('id'); | |
end delete_file; | |
end utl_openai_files_api; | |
/ |
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/openai-files-sample.zip
アップロードしたファイルは、OpenAIの画面からも確認できます。
ファイルのアップロードは、ファイルを選択するページ・アイテムP1_FILE(タイプはファイルのアップロード)とボタンUPLOADで実装しています。ストレージのタイプとして表APEX_APPLICATION_TEMP_FILESを選択します。
ボタンUPLOADをクリックしたときに実行されるプロセスには、以下のコードを記述しています。
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
declare | |
l_file clob; | |
l_id varchar2(400); | |
begin | |
for r in ( | |
select * from apex_application_temp_files | |
where name = :P1_FILE | |
) | |
loop | |
l_id := utl_openai_files_api.upload_file( | |
p_filename => r.filename | |
,p_content_type => r.mime_type | |
,p_file_content => r.blob_content | |
,p_credential_static_id => :G_OPENAI_API_KEY | |
,p_file => l_file | |
); | |
:P1_RESPONSE := l_file; | |
end loop; | |
end; |
ターゲットの設定ではページはページ1、つまり同じページに遷移させています。file_idをページ・アイテムのP1_IDに渡しています。リクエストの値は、ダウンロードの場合はDOWNLOAD、削除の場合はDELETEを渡し、レンダリング前に作成しているプロセスを呼び出す条件に使用します。
ファイルをダウンロードするプロセスは、レンダリング前のヘッダー前に作成しています。実行するコードとして、以下を記述します。
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
declare | |
l_id varchar2(400); | |
l_filename varchar2(400); | |
l_file clob; | |
l_file_content blob; | |
l_file_json json_object_t; | |
l_download apex_data_export.t_export; | |
begin | |
l_id := utl_openai_files_api.retrieve_file( | |
p_file_id => :P1_ID | |
,p_file => l_file | |
,p_file_content => l_file_content | |
,p_credential_static_id => :G_OPENAI_API_KEY | |
); | |
l_file_json := json_object_t(l_file); | |
l_filename := l_file_json.get_string('filename'); | |
/* download */ | |
l_download.file_name := l_filename; | |
l_download.as_clob := FALSE; | |
l_download.content_blob := l_file_content; | |
apex_data_export.download( p_export => l_download ); | |
apex_application.stop_apex_engine; | |
end; |
サーバー側の条件のタイプにリクエスト = 値を選択し、値としてDOWNLOADを設定します。
削除もほぼ同じ実装です。削除を行なうプロセスのコードとして、以下を記述します。
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
declare | |
l_id varchar2(400); | |
l_filename varchar2(400); | |
l_file clob; | |
begin | |
l_id := utl_openai_files_api.delete_file( | |
p_file_id => :P1_ID | |
,p_file => l_file | |
,p_credential_static_id => :G_OPENAI_API_KEY | |
); | |
end; |
サーバー側の条件のタイプにリクエスト = 値を選択し、値としてDELETEを設定します。
OpenAIのFilesにアップロードされているファイルの一覧は、以下のURLを呼び出すことで取得できます。
https://api.openai.com/v1/files
最低1つでもファイルがアップロード済みであれば、RESTデータ・ソースの作成時にレスポンスを自動的に認識してくれます。
OpenAIのFiles APIを使ったAPEXアプリケーションの説明は以上です。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完