4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

生成AIアプリケーションを作る中で、大規模言語モデル(LLM)にJSONを生成してもらいたい場面があるかと思います。

一般的にはLangChainのJSON parserや、LLMのFunction callingでJSON部分を取得する方法がありますが、本記事は、純粋にプロンプトエンジニアリングのみで期待通りのJSONを生成する方法について、試行錯誤のまとめです。

よく陥る失敗パターン

例えば、以下のようなダミーデータをJSONで生成させたい場合、

期待するJSON
{
    "activityDate": "2024-07-02",
    "account": "株式会社ダミー企業",
    "subject": "初回訪問",
    "detail": "株式会社ダミー企業との初回お打ち合わせを実施。製品Xを紹介し、・・・"
}

プロンプトの書き方によっては以下のようなレスポンスになり、後続のparse処理でエラーになることが考えられます。

失敗パターン#1 余計な文章が付加される

JSON部分のみを生成してほしいのに、前後に余計な説明文章が入ってくるパターン。

NG
JSON形式を作成しました。
{
    "activityDate": "2024-07-02",
    "account": "株式会社ダミー企業",
    "subject": "初回訪問",
    "detail": "株式会社ダミー企業との初回お打ち合わせを実施。製品Xを紹介し、・・・"
}
このJSONデータには、以下の情報が含まれております。activityDa・・・

失敗パターン#2 JSON形式がおかしい

一部または全体的に、JSONが期待する形式と異なってしまうケース。

NG
{
    "アクティビティ日": "2024-07-02",
    "企業": "株式会社ダミー企業",
    "タイトル": "初回訪問",
    "詳細": "株式会社ダミー企業との初回お打ち合わせを実施。製品Xを紹介し、・・・"
}

失敗パターン#3 そもそもJSONが作成されない

プロンプトの指示とフォーマットがあまりにもずれていると、そもそもJSONが全く作成されないケースも考えられます。

NG
よくわかりませんでした。もう一度試してください。

解決策

上記パターンを回避し、期待するJSONを得るためのTipsです。

:o: #1 Temperatureの設定

一般的にこの値が小さいと回答のバラツキが抑えられ、大きいとランダム度が増します。JSON生成では失敗パターン#1 余計な文章が付加されるの発生を抑えるために、極力temperature=0.0に設定します。

:o: #2 明確な指示

すごくシンプルなことですが、JSONのみを出力して欲しい旨をきちんと記述します。また、最終行をJSON:で終わらせることでも、失敗パターン#1 余計な文章が付加されるの抑制効果が期待できます。

プロンプト

以下フォーマットのJSONを生成してください。

JSONフォーマット:
(フォーマットについて記述)

最終応答は、"{"で始まり"}"で終わる。または"["で始まり"]"で終わるJSONのみを出力し、JSON以外の文字は一切応答に含めないでください。

JSON:

:o: #3 JSONフォーマットの指定

#3.1 JSON 形式

期待するJSONフォーマットを元に、項目値の部分に指示内容を自然言語で記述します。

JSON
{
    "activityDate": "活動日(yyyy-MM-dd形式)",
    "account": "顧客企業名",
    "subject": "営業活動のタイトル",
    "detail": "営業活動の詳細"
}

シンプルな構造だとこれで大丈夫なことが多いです。ただ、構造が複雑になればなるほど、期待と異なる形式で出力される可能性も高まります。

また、目視では問題なさそうでも実は特殊な文字コードのスペースが入っていて、後続のJSON parse処理でエラー発生。という事象に遭遇したことがありました。
=> なるべくJSONフォーマット部分には、余計なスペース・改行を含めない方が良さそうです。

プロンプト例
以下フォーマットのJSONで返答してください。

JSONフォーマット:
{"activityDate":"活動日(yyyy-MM-dd形式)","account":"顧客企業名","subject":"営業活動のタイトル","detail":"営業活動の詳細"}

最終応答は、"{"で始まり"}"で終わる、または"["で始まり"]"で終わるJSONのみを出力し、JSON以外の文字は一切応答に含めないでください。

JSON:

#3.2 JSON Schema 形式

少し複雑な構造を扱う場合は、JSON Schema形式で記述するのがおすすめです。

JSON Schema
{
  "type": "object",
  "description": "営業活動データ",
  "properties": {
    "activityDate": {"type": "string", "format": "date", "description": "営業活動の実施日"},
    "account": {"type": "string", "description": "営業活動先企業"},
    "subject": {"type": "string", "description": "営業活動の件名"},
    "detail": {"type": "string", "description": "営業活動の詳細説明"}
  }
}

JSON Schemaを使うとデータ型、LLMへの指示等を指定フォーマットで定義できるので、人間の可読性も確保しつつ、失敗パターン#2 JSON形式がおかしいの発生をだいぶ抑えられます。

プロンプト例
以下のJSON Schemaに厳密に従ってJSONで返答してください。

JSON Schema:
{
    "type": "object", 
    "properties": {
        "activityDate": {"type": "string", "format": "date", "description": "営業活動の実施日"},
        "account": {"type": "string", "description": "営業活動先企業"},
        "subject": {"type": "string", "description": "営業活動の件名"},
        "detail": {"type": "string", "description": "営業活動の詳細説明"}
    }
}

最終応答は、"{"で始まり"}"で終わる、または"["で始まり"]"で終わるJSONのみを出力し、JSON以外の文字は一切応答に含めないでください。

JSON:

ユースケース別のプロンプト例

これらTipsを実践した、いくつかのユースケースを想定したプロンプト例です。

:heavy_check_mark: ダミーデータ生成

プロンプト
以下のJSON Schemaに厳密に従って、ダミーの活動データ3件をJSONで生成してください。

JSON Schema:
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "activityDate": {"type": "string", "format": "date", "description": "営業活動の実施日"},
      "account": {"type": "string", "description": "営業活動先企業"},
      "subject": {"type": "string", "description": "営業活動の件名"},
      "detail": {"type": "string", "description": "営業活動の詳細説明"}
    }
  }
}

最終応答は、"["で始まり"]"で終わるJSONのみを出力し、JSON以外の文字は一切応答に含めないでください。

JSON:
レスポンス
[
  {
    "activityDate": "2022-04-01",
    "account": "株式会社A",
    "subject": "新製品プレゼンテーション",
    "detail": "新製品のプレゼンテーションを行いました。詳細については、資料をご参照ください。"
  },
  {
    "activityDate": "2022-04-02",
    "account": "株式会社B",
    "subject": "契約更新の打ち合わせ",
    "detail": "契約更新についての打ち合わせを行いました。次回は具体的な条件について話し合う予定です。"
  },
  {
    "activityDate": "2022-04-03",
    "account": "株式会社C",
    "subject": "新規ビジネス提案",
    "detail": "新規ビジネスの提案を行いました。彼らは興味を持っているようで、引き続き話を進めていきます。"
  }
]

:heavy_check_mark: 非構造データ ⇒ 構造データ変換

自然言語文章をJSON形式の構造データに変換

プロンプト
ユーザインプットから活動データを抽出し、以下のJSON Schemaに厳密に従ってJSONを生成してください。

JSON Schema:
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "activityDate": {"type": "string", "format": "date", "description": "営業活動の実施日"},
      "account": {"type": "string", "description": "営業活動先企業"},
      "subject": {"type": "string", "description": "営業活動の件名"},
      "detail": {"type": "string", "description": "営業活動の詳細説明"}
    }
  }
}

ユーザインプット:
2024年6月10日の活動です。午前、株式会社ABCに訪問。新商品の提案を実施し、新商品の特長や価格について説明。その後、株式会社XYZにも訪問。契約更新の再確認と更新に関して話し合いました。午後には株式会社123にメールで見積もりを送付しました。

最終応答は、"["で始まり"]"で終わるJSONのみを出力し、JSON以外の文字は一切応答に含めないでください。

JSON:
レスポンス
[
  {
    "activityDate": "2024-06-10",
    "account": "株式会社ABC",
    "subject": "新商品の提案",
    "detail": "新商品の特長や価格について説明"
  },
  {
    "activityDate": "2024-06-10",
    "account": "株式会社XYZ",
    "subject": "契約更新の再確認と更新",
    "detail": "契約更新に関して話し合い"
  },
  {
    "activityDate": "2024-06-10",
    "account": "株式会社123",
    "subject": "見積もりの送付",
    "detail": "メールで見積もりを送付"
  }
]

:heavy_check_mark: 非構造データ ⇒ 構造データ変換(エラーハンドリング対応)

前ユースケース非構造データ ⇒ 構造データ変換を応用し、失敗パターン#3 そもそもJSONが作成されない対策tとして、例外エラーも考慮したJSON構造を定義します。

  • success - 正常時はtrue、エラー時はfalse
  • payload - 正常時、データはpayloadに格納
  • errorMessage - エラー発生時のみ、エラー内容をここに書き出す
プロンプト
ユーザーインプットから活動データを抽出し、以下のJSON Schemaに厳密に従ってJSONを生成してください。(もし抽出が上手くできない場合もJSON Schemaに厳密に従ってエラー内容をJSONで生成してください)

JSON Schema:
{
  "type": "object",
  "description": "営業活動データを抽出できた場合もエラーで抽出できなかった場合も対応したJSONです",
  "properties": {"success": {"type": "boolean", "description":"営業活動データ抽出が成功したかどうか"}},
  "required": ["success"],
  "if": {"properties": { "success": { "const": true } }},
  "then": {
    "properties": {
      "payload": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "activityDate": {"type": "string", "format": "date", "description": "営業活動の実施日"},
            "account": {"type": "string", "description": "営業活動先企業"},
            "subject": {"type": "string", "description": "営業活動の件名"},
            "detail": {"type": "string", "description": "営業活動の詳細説明"}
          }
        }
      }
    },
    "required": ["payload"]
  },
  "else": {
    "properties": {
      "errorMessage": {"type": "string", "description": "エラー内容の詳細を記述します"}
    },
    "required": ["errorMessage"]
  }
}

ユーザーインプット:
(ユーザーインプット)

最終応答は、"{"で始まり"}"で終わる、または"["で始まり"]"で終わるJSONのみを出力し、JSON以外の文字は一切応答に含めないでください。`

JSON:

成功時

ユーザーインプット

2024年6月10日の活動です。午前、株式会社ABCに訪問。新商品の提案を実施し、新商品の特長や価格について説明。その後、株式会社XYZにも訪問。契約更新の再確認と更新に関して話し合いました。午後には株式会社123にメールで見積もりを送付しました。

レスポンス
{
  "success": true,
  "payload": [
    {
      "activityDate": "2024-06-10",
      "account": "株式会社ABC",
      "subject": "新商品の提案",
      "detail": "新商品の特長や価格について説明"
    },
    {
      "activityDate": "2024-06-10",
      "account": "株式会社XYZ",
      "subject": "契約更新の再確認",
      "detail": "契約更新に関して話し合い"
    },
    {
      "activityDate": "2024-06-10",
      "account": "株式会社123",
      "subject": "見積もりの送付",
      "detail": "メールで見積もりを送付"
    }
  ]
}

エラー発生時

ユーザーインプット

おはようございます。今日はいい天気ですね。

レスポンス
エラー発生時のJSON
{
  "success": false,
  "errorMessage": "営業活動データが含まれていないため、抽出できませんでした。"
}

【付録】 JSON -> JSON Schema 変換

JSON Schemaを作成するのが面倒!という場合は、ChatGPTやClaudeあたりに以下プロンプトを投げてJSON Schemaのベースを作成してもらい、それを元に適宜修正していくのがおすすめです。

プロンプト

以下JSONをJSON Schema 形式(スキーマ:2020-12)に変換してください。

JSON:
(期待するJSONをここに記述)

Claude 3.5 Sonnet Artifactsでの実行イメージ

image.png

まとめ

JSONだけを出力させるためのプロンプトTipsをまとめます。

  • temperature=0.0に設定する
  • JSONだけ生成して欲しい旨を明確に指示する
  • JSONフォーマットはJSON Schemaで記述する
  • 最終行をJSON:で終わらせる
  • (JSONモード対応モデルを使う場合はONにする)
4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?