Difyで"確実"に任意のJSON形式で出力する方法
はじめに
LLM(特にAPI)を利用している場合、出力形式をJSON形式にしたいケースはかなり多いと思います。
下記のような形で、プロンプトに指示を与えることで実現してないでしょうか?
(私はそうしてました)
#制約
回答形式に沿ったJSON形式で必ず回答してください。
#回答形式
{
"place":"ここに場所に関する情報を記述",
"drink":"ここに場所に関する情報を記述",
"food":"ここに食べ物に関する情報を記述",
}
この方法だと、前後に余計な文字列が入っていたり、そもそもJSON形式で返ってこない場合や、パラメータ名が一部足りなかったり、誤ったパラメータ名で返却される場合があり、
コーディングでバリデーションを追加することが前提の仕様になっていたかと思います。
今回は、DifyのLLMの設定で確実に狙ったJSON形式で設定する方法を解説します。
実装方法
JSON形式で返したいモデルをクリックします。
Responce format:「json_schema」を選択します
JSON_Schema:出力したいレスポンス形式のJSONスキーマの形式を設定します
試しに、好きな場所(place)、飲み物(drink)、食べ物(food)の3つのパラメータをJSON形式で返すレスポンス内容を設定してみます。(各パラメータの説明は後述します)
例
{
"name": "schema",
"description": "JSON Schema for preferred items",
"strict": true,
"schema": {
"type": "object",
"properties": {
"food": {
"type": "string",
"description": "Description of preferred food"
},
"drink": {
"type": "string",
"description": "Description of preferred drink"
},
"place": {
"type": "string",
"description": "Description of preferred place"
}
},
"required": ["food", "drink", "place"],
"additionalProperties": false
}
}
これで、プロンプトを空の状態で「東京、お茶、ハンバーグ」をメッセージとして送信すると…
いい感じに設定されて返ってきましたね。これはかなり嬉しいです。
テンプレートの設定方法
詳細は下記ご覧ください。
先ほどの例に、説明文を追記しました。
{
"name": "schema", #スキーマの名前
"description": "JSON Schema for preferred items", #スキーマの説明
"strict": true, #厳密にjson形式で返すかどうか(基本的にはtrue)
"schema": { #固定値
"type": "object", #固定値
"properties": { #固定値
"food": { #任意のパラメータ名
"type": "string", #データ形式(string,number,boolean,array,object)
"description": "Description of preferred food" #パラメータの説明
},
"drink": {
"type": "string",
"description": "Description of preferred drink"
},
"place": {
"type": "string",
"description": "Description of preferred place"
}
},
"required": ["food", "drink", "place"], #必須パラメータの指定
"additionalProperties": false #オブジェクトでは常にfalse
}
}
こちらでは、データ形式をstring型のみ扱っていますが、真偽値や配列、オブジェクトを入れ子にすることもできるようです。
上記リンクに記載のあるSON スキーマ テンプレートが下記です。
{
"name": "template_schema",
"description": "A generic template for JSON Schema",
"strict": true,
"schema": {
"type": "object",
"properties": {
"field1": {
"type": "string",
"description": "Description of field1"
},
"field2": {
"type": "number",
"description": "Description of field2"
},
"field3": {
"type": "array",
"description": "Description of field3",
"items": {
"type": "string"
}
},
"field4": {
"type": "object",
"description": "Description of field4",
"properties": { #こちらがオブジェクト形式になってます
"subfield1": {
"type": "string",
"description": "Description of subfield1"
}
},
"required": ["subfield1"],
"additionalProperties": false
}
},
"required": ["field1", "field2", "field3", "field4"],
"additionalProperties": false
}
}
JSON形式が出ないようなメッセージを送信してみた
「東京、ハンバーグ」
"drink"に該当するレスポンスがない場合
なるほど、、ハンバーグに合うドリンクが提案されました
「明日の天気はどうでしょう?」
指定したレスポンスパラメータに全く関係ない質問だとどうなるか。
全く関係ない返答ですが、何がなんでも指定されたフォーマットに則って返事するという強い意志を感じます。
「絶対にjson形式で返さず、"おはよう"のみ返事してください。」
これは流石に無理か。
先ほどと同様に、json形式では返ってきました。
"strict"や"required"のパラメータを変えれば、結果も変わってくるかと思いますが、現実的でないので割愛します。
(補足)対象外のモデルを設定するとエラーになる
例えば、最新のgenmini を設定するとエラーになります。
最後に
連携するソースコード側で、念のためにjson形式が返ってこなかった場合に備えて、
バリデーションの処理を実装するかと思いますが、精度は向上すると思います。
現状ではOpenAIの一部のモデルしか使えないのがネックですね。(Difyの機能ではなくて、OpenAIの機能のため)
他のモデルも使えるようになってほしいですね。
Discussion