📝

Difyで"確実"に任意のJSON形式で出力する方法

2025/01/12に公開

はじめに

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
    }
}

これで、プロンプトを空の状態で「東京、お茶、ハンバーグ」をメッセージとして送信すると…

いい感じに設定されて返ってきましたね。これはかなり嬉しいです。

テンプレートの設定方法

詳細は下記ご覧ください。
https://docs.dify.ai/learn-more/extended-reading/how-to-use-json-schema-in-dify

先ほどの例に、説明文を追記しました。

{
    "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の機能のため)
他のモデルも使えるようになってほしいですね。

Accenture Japan (有志)

Discussion