上記の記事で作成したAPEXアプリケーションを、Structured Outputsの指定ができるように改変しました。API呼び出しを実装しているパッケージUTL_OPENAI_CHAT_APIも、Structured Outputsに対応するために変更しています。ただしFunction Callingを実装していたので、改変部分は非常に少ないです。
パッケージ定義
https://gist.github.com/ujnak/93c9d427ccef53e30dd89e623f08c880
パッケージ本体
https://gist.github.com/ujnak/a6126f7e9ee264d0e384103cea0379b5
以下は、Structured Outputsを指定してOpenAIのChat Completions APIを呼び出した結果です。
与えているシステム・プロンプトとユーザーのメッセージは、OpenAIのStructured outputsのドキュメントにExampleとして掲載されていたものを与えています。
「You are a helpful math tutor. Guide the user through the solution step by step.」
ユーザー・メッセージ
「how can I solve 8x + 7 = -23」
{
"steps" :
[
{
"explanation" : "Start with the original equation: 8x + 7 = -23",
"output" : "8x + 7 = -23"
},
{
"explanation" : "To isolate the term with x, subtract 7 from both sides of the equation.",
"output" : "8x + 7 - 7 = -23 - 7"
},
{
"explanation" : "Simplifying both sides gives us: 8x = -30",
"output" : "8x = -30"
},
{
"explanation" : "Next, divide both sides by 8 to solve for x.",
"output" : "x = -30 / 8"
},
{
"explanation" : "Simplifying -30/8 gives us -15/4 or -3.75.",
"output" : "x = -3.75 or x = -15/4"
}
],
"final_answer" : "x = -15/4 or x = -3.75"
}
Structured Outputsに対応したAPEXアプリケーションのエクスポートを以下に置きました。https://github.com/ujnak/apexapps/blob/master/exports/chat-with-generative-ai-so.zip
以下より、アプリケーションの変更点を紹介します。
最初に、Structured Outputsの指定に含めるJSONスキーマを保存する表を作成します。クイックSQLの以下のモデルより、表OPENAI_RESPONSE_FORMATSを作成しています。
# prefix: openai
response_formats
format_name vc80 /nn
format_type vc20 /check text,json_object,json_schema
json_schema json
description vc4000
クイックSQLで列のタイプにjsonを指定すると、DDLでの列定義はclob check (json_schema is json)になります。本当はCLOB型ではなくBLOB型にformat osonの指定を加えるか、23aiであればJSON型とする方が、容量面でも性能面でも有利です。今回はAPEXのアプリケーションの作りやすさを優先して、CLOB型のままとします。Oracle APEXのウィザードは、CLOB型についてはテキスト領域を自動生成し、BLOB型についてはファイル選択を生成します。
対話モード・レポート、フォームともに、ソースの表としてOPENAI_RESPONSE_FORMATSが指定されている、ごく一般的なページになります。
表OPENAI_RESPONSE_FORMATSには、設定の名前である列FORMAT_NAME、形式の指定である列FORMAT_TYPE、出力形式を指定するJSONスキーマの列JSON_SCHEMAと、補足説明を記述する列DESCRIPTIONがあります。
FORMAT_TYPEとして指定できる値はtext、json_objectと、Structured Outputsの指定であるjson_schemaがあります。これらの値は、ページ・アイテムのタイプを選択リストとし、静的値として設定しています。
列JSON_SCHEMAには、正確に言うとOpenAIのChat Completions APIのメッセージの属性reponse_formatに与えるJSONデータを設定します。今回の実装例で参照しているOpenAIのExampleでは、以下の値がJSON Schemaとして設定する値になります。
schema属性のJSONデータが本来はJSONスキーマになりますが、name、strict、schema属性を含むJSONオブジェクトをJSONスキーマとして設定しています。
{
"name" : "math_reasoning",
"schema" :
{
"type" : "object",
"properties" :
{
"steps" :
{
"type" : "array",
"items" :
{
"type" : "object",
"properties" :
{
"explanation" :
{
"type" : "string"
},
"output" :
{
"type" : "string"
}
},
"required" :
[
"explanation",
"output"
],
"additionalProperties" : false
}
},
"final_answer" :
{
"type" : "string"
}
},
"required" :
[
"steps",
"final_answer"
],
"additionalProperties" : false
},
"strict" : true
}
JSONデータを入力するページ・アイテムに計算を設定し、保存するデータをプリティ・プリントしています。
select json_serialize(:P5_JSON_SCHEMA pretty) from dual
以上で、Structured Outputsのresponse_formatを設定するページが作成できました。
ホーム・ページのTool Setの選択を行う選択リストの下に、Response Formatを選択するページ・アイテムを作成します。
ページ・アイテムのタイプは選択リスト、LOVのSQL問合せとして、以下のSELECT文を記述します。
select format_name d, id r from openai_response_formats
Chat Completions APIの応答なるJSONデータが読みやすくなるように、本体の拡張フォーマットをオンにし、HTML式に以下を記述します。
<pre>&CLOB001.</pre>
ボタンSend Messageをクリックしたときに呼び出されるプロセスSend Messageは、パッケージUTL_OPENAI_CHAT_APIに含まれるプロシージャCHATを呼び出しています。
Structured Outputsに対応するため、引数p_response_formatの扱いを変えています。また、引数p_json_schemaが追加されています。
引数p_response_formatは値のタイプをSQL問合せ(単一の値を返す)に変更し、SQL問合せとして、以下を記述しています。ページ・アイテムP1_RESPONSE_FORMATで選択したフォーマット・タイプ(つまりtext、json_object、json_schemaのどれか)が、引数p_response_formatに渡されます。
select format_type from openai_response_formats where id = :P1_RESPONSE_FORMAT
select json_schema from openai_response_formats where id = :P1_RESPONSE_FORMAT
ページ・アイテムP1_RESPONSE_FORMATで選択したJSONスキーマが、引数p_json_schemaに渡されます。
APEXアプリケーションをStructured Outputsに対応させるために行なった変更は以上になります。
Ollamaにllama3.2をロードして、Structured Outputsに対応しているかどうか確認してみました。
指示通りに正解を返しますが、Strucured Outputsは無視されました。OllamaでサポートしているのはあくまでJSON mode(typeがjson_objectで、schemaまでは指定できない)までのようです。
llama3.2の回答です。
To solve for x, we need to isolate the variable x on one side of the equation.
Here's our starting point:
8x + 7 = -23
Step 1: Subtract 7 from both sides of the equation to get rid of the constant term on the left-hand side.
This will give us a new equation with no constant terms on the left-hand side:
8x = -23 - 7
= -30
Now we have:
8x = -30
Step 2: Divide both sides of the equation by 8 to isolate x. This is called "inverse operations".
Dividing by 8 will cancel out the coefficient (the number multiplied by the variable) on the left-hand side.
(-30) ÷ 8 = ?
= -3.75
And that's our solution for x!
Now you know: x = -3.75
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完