すべてのプロダクト
Search
ドキュメントセンター

:構造化出力

最終更新日:May 09, 2026

構造化出力(JSON モード)を使用すると、モデルは直接コードで解析可能な有効な JSON 文字列を返します。これにより、json などの余分なテキストが含まれて下流の解析処理が中断される問題を回避できます。

使用方法

構造化出力を有効にするには、リクエスト内で response_format を設定し、以下の 2 つの要件を満たす必要があります。

  1. リクエストボディ内で response_format パラメーターを {"type": "json_object"} に設定します。

  2. システムメッセージまたはユーザーメッセージ内に「JSON」という単語(大文字・小文字を区別しない)を含めます。これを含めない場合、API は次のエラーを返します:'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'.

対応モデル

Qwen

  • テキスト生成モデル

    • Qwen-Max(ノンシンキングモード): Qwen3.6-Max シリーズ、Qwen3-Max シリーズ、Qwen-Max シリーズ

    • Qwen-Plus(ノンシンキングモード): Qwen3.6-Plus シリーズ、Qwen3.5-Plus シリーズ、Qwen-Plus シリーズ

    • Qwen-Flash(ノンシンキングモード): Qwen3.6-Flash シリーズ、Qwen3.5-Flash シリーズ、Qwen-Flash シリーズ

    • Qwen-Turbo(ノンシンキングモード): Qwen-Turbo シリーズ

    • Qwen-Coder: Qwen3-Coder シリーズ

    • Qwen-Long: Qwen-Long シリーズ

    • Qwen3.6 オープンソースシリーズ(ノンシンキングモード)

    • Qwen3.5 オープンソースシリーズ(ノンシンキングモード)

    • Qwen3 オープンソースシリーズ(ノンシンキングモード)

    • Qwen3-Coder オープンソースシリーズ

    • Qwen2.5 オープンソースシリーズ(math モデルおよび coder モデルを除く)

  • マルチモーダルモデル

    • Qwen-VL(ノンシンキングモード): Qwen3-VL-Plus シリーズ、Qwen3-VL-Flash シリーズ、Qwen-VL-Max シリーズ(最新版およびスナップショット版を除く)、Qwen-VL-Plus シリーズ(最新版およびスナップショット版を除く)

    • Qwen-Omni: Qwen3.5-Omni-Plus シリーズ、Qwen3.5-Omni-Flash シリーズ

    • Qwen3-VL オープンソースシリーズ(ノンシンキングモード)

説明

思考モードのモデルは、現時点で構造化出力をサポートしていません。

Kimi

kimi-k2-thinking

GLM

ノンシンキングモード:glm-5.1、 glm-5、glm-4.7、glm-4.6

クイックスタート

この例では、個人プロファイルから構造化情報を抽出します。

API キーを作成し、API キーを環境変数としてエクスポートします。OpenAI SDK または DashScope SDK を使用して呼び出す場合は、SDK をインストールしてください。

OpenAI 互換

Python

from openai import OpenAI
import os

client = OpenAI(
    # API キーはリージョンごとに異なります。環境変数を設定していない場合は、次の行を api_key="sk-xxx" に置き換えます
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 中国 (北京) リージョンのモデルを使用する場合は、base_url を次のように置き換えてください: https://dashscope.aliyuncs.com/compatible-mode/v1
    base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
)

completion = client.chat.completions.create(
    model="qwen-flash",
    messages=[
        {
            "role": "system",
            "content": "ユーザーの名前と年齢を抽出し、JSON 形式で返してください"
        },
        {
            "role": "user",
            "content": "みなさん、こんにちは。私の名前は田中一郎で、34 歳です。メールアドレスは tanaka@example.com で、バスケットボールと旅行が趣味です", 
        },
    ],
    response_format={"type": "json_object"}
)

json_string = completion.choices[0].message.content
print(json_string)

応答

{
  "Name": "田中一郎",
  "Age": 34
}

Node.js

import OpenAI from "openai";

const openai = new OpenAI({
    // 環境変数を設定していない場合は、次の行を apiKey: "sk-xxx" に置き換えます
    apiKey: process.env.DASHSCOPE_API_KEY,
    // 中国 (北京) リージョンのモデルを使用する場合は、baseURL を次のように置き換えてください: https://dashscope.aliyuncs.com/compatible-mode/v1
    baseURL: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
});

const completion = await openai.chat.completions.create({
    model: "qwen-flash",
    messages: [
        {
            role: "system",
            content: "ユーザーの名前と年齢を抽出し、JSON 形式で返してください"
        },
        {
            role: "user",
            content: "みなさん、こんにちは。私の名前は田中一郎で、34 歳です。メールアドレスは tanaka@example.com で、バスケットボールと旅行が趣味です"
        }
    ],
    response_format: {
        type: "json_object"
    }
});

const jsonString = completion.choices[0].message.content;
console.log(jsonString);

応答

{
  "name": "田中一郎",
  "age": 34
}

curl

# ======= 重要事項 =======
# API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/ja/model-studio/get-api-key
# 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
# === 実行前にこのコメントを削除してください ===
curl -X POST https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
    "model": "qwen-plus",
    "messages": [
        {
            "role": "system",
            "content": "名前(文字列)、年齢(文字列)、メールアドレス(文字列)を抽出してください。結果を JSON 文字列として出力します。他の不要な内容は含めないでください。\n例:\nQ: 私の名前は張三で、25 歳、メールアドレスは zhangsan@example.com です\nA: {\"name\":\"張三\",\"age\":\"25 years old\",\"email\":\"zhangsan@example.com\"}\nQ: 私の名前は李四で、30 歳、メールアドレスは lisi@example.com です\nA: {\"name\":\"李四\",\"age\":\"30 years old\",\"email\":\"lisi@example.com\"}\nQ: 私の名前は王五で、メールアドレスは wangwu@example.com、40 歳です\nA: {\"name\":\"王五\",\"age\":\"40 years old\",\"email\":\"wangwu@example.com\"}"
        },
        {
            "role": "user", 
            "content": "みなさん、こんにちは。私の名前は田中一郎で、34 歳、メールアドレスは tanaka@example.com です"
        }
    ],
    "response_format": {
        "type": "json_object"
    }
}'

応答

{
    "choices": [
        {
            "message": {
                "role": "assistant",
                "content": "{\"name\":\"Alex Brown\",\"age\":\"34 years old\"}"
            },
            "finish_reason": "stop",
            "index": 0,
            "logprobs": null
        }
    ],
    "object": "chat.completion",
    "usage": {
        "prompt_tokens": 207,
        "completion_tokens": 20,
        "total_tokens": 227,
        "prompt_tokens_details": {
            "cached_tokens": 0
        }
    },
    "created": 1756455080,
    "system_fingerprint": null,
    "model": "qwen-plus",
    "id": "chatcmpl-624b665b-fb93-99e7-9ebd-bb6d86d314d2"
}

DashScope

Python

import os
import dashscope
# 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/api/v1
dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

messages=[
    {
        "role": "system",
        "content": "ユーザーの名前と年齢を抽出し、JSON 形式で返してください"
    },
    {
        "role": "user",
        "content": "みなさん、こんにちは。私の名前は田中一郎で、34 歳です。メールアドレスは tanaka@example.com で、バスケットボールと旅行が趣味です", 
    },
]
response = dashscope.Generation.call(
    # 環境変数を設定していない場合は、次の行を api_key="sk-xxx"(Alibaba Cloud Model Studio API キー)に置き換えます
    api_key=os.getenv('DASHSCOPE_API_KEY'),
    model="qwen-flash", 
    messages=messages,
    result_format='message',
    response_format={'type': 'json_object'}
    )
json_string = response.output.choices[0].message.content
print(json_string)

応答

{
  "name": "Alex Brown",
  "age": 34
}

Java

DashScope Java SDK のバージョンは 2.18.4 以上である必要があります。

// DashScope Java SDK のバージョンは 2.18.4 以上である必要があります

import java.util.Arrays;
import java.lang.System;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.common.ResponseFormat;
import com.alibaba.dashscope.protocol.Protocol;

public class Main {
    public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
        // 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/api/v1
        Generation gen = new Generation(Protocol.HTTP.getValue(), "https://dashscope-intl.aliyuncs.com/api/v1");
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("ユーザーの名前と年齢を抽出し、JSON 形式で返してください")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("みなさん、こんにちは。私の名前は田中一郎で、34 歳です。メールアドレスは tanaka@example.com で、バスケットボールと旅行が趣味です")
                .build();
        ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
        GenerationParam param = GenerationParam.builder()
                // 環境変数を設定していない場合は、次の行を .apiKey("sk-xxx")(Alibaba Cloud Model Studio API キー)に置き換えます
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .model("qwen-flash")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .responseFormat(jsonMode)
                .build();
        return gen.call(param);
    }

    public static void main(String[] args) {
        try {
            GenerationResult result = callWithMessage();
            System.out.println(result.getOutput().getChoices().get(0).getMessage().getContent());
        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            // ロギングフレームワークを使用して例外を記録します
            System.err.println("生成サービスの呼び出し中にエラーが発生しました:" + e.getMessage());
        }
    }
}

応答

{
  "name": "田中一郎",
  "age": 34
}

curl

# ======= 重要事項 =======
# 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation
# API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/ja/model-studio/get-api-key
# === 実行前にこのコメントを削除してください ===

curl -X POST https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/text-generation/generation \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
    "model": "qwen-flash",
    "input": {
        "messages": [
            {
                "role": "system",
                "content": "ユーザー'\''の名前と年齢を抽出し、JSON 形式で返してください"
            },
            {
                "role": "user", 
                "content": "みなさん、こんにちは。私の名前は田中一郎で、34 歳です。メールアドレスは tanaka@example.com で、バスケットボールと旅行が趣味です"
            }
        ]
    },
    "parameters": {
        "result_format": "message",
        "response_format": {
            "type": "json_object"
        }
    }
}'

応答

{
  "name": "田中一郎",
  "age": 34
}

画像および動画データ処理

マルチモーダルモデルも、画像や動画に対する構造化出力をサポートしています。JSON モードを使用して、レシートのフィールド値、画像内のオブジェクト位置、動画内のイベントなど、視覚コンテンツから構造化データを抽出できます。

画像および動画ファイルの制限については、「画像および動画の理解」をご参照ください。

OpenAI 互換

Python

import os
from openai import OpenAI

client = OpenAI(
    # API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/ja/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 中国 (北京) リージョンのモデルを使用する場合は、base_url を次のように置き換えてください: https://dashscope.aliyuncs.com/compatible-mode/v1
    base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
)

completion = client.chat.completions.create(
    model="qwen3-vl-plus",
    messages=[
        {
            "role": "system",
            "content": [{"type": "text", "text": "あなたは親切なアシスタントです。"}],
        },
        {
            "role": "user",
            "content": [
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"
                    },
                },
                {"type": "text", "text": "画像からチケット情報(配列型。travel_date、trains、seat_num、arrival_site、price を含む)と請求書情報(配列型。invoice_code および invoice_number を含む)を抽出してください。チケットおよび請求書の両方の配列を含む JSON を出力してください"},
            ],
        },
    ],
    response_format={"type": "json_object"}
)
json_string = completion.choices[0].message.content
print(json_string)

応答

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "stream",
      "seat_num": "371",
      "arrival_site": "Development Zone",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

Node.js

import OpenAI from "openai";

const openai = new OpenAI({
  // API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/ja/model-studio/get-api-key
  // 環境変数を設定していない場合は、次の行を apiKey: "sk-xxx"(Model Studio API キー)に置き換えます
  apiKey: process.env.DASHSCOPE_API_KEY,
  // 中国 (北京) リージョンのモデルを使用する場合は、baseURL を https://dashscope.aliyuncs.com/compatible-mode/v1 に置き換えてください
  baseURL: "https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
});

async function main() {
  const response = await openai.chat.completions.create({
    model: "qwen3-vl-plus",
    messages: [{
        role: "system",
        content: [{
          type: "text",
          text: "あなたは親切なアシスタントです。"
        }]
      },
      {
        role: "user",
        content: [{
            type: "image_url",
            image_url: {
              "url": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"
            }
          },
          {
            type: "text",
            text: "画像からチケット情報(配列型。travel_date、trains、seat_num、arrival_site、price を含む)と請求書情報(配列型。invoice_code および invoice_number を含む)を抽出してください。チケットおよび請求書の両方の配列を含む JSON を出力してください"
          }
        ]
      }
    ],
    response_format: {type: "json_object"}
  });
  console.log(response.choices[0].message.content);
}

main()

応答

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "stream",
      "seat_num": "371",
      "arrival_site": "Development Zone",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

curl

# ======= 重要事項 =======
# 中国 (北京) リージョンのモデルを使用する場合は、base_url を次のように置き換えてください: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
# API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/ja/model-studio/get-api-key
# === 実行前にこのコメントを削除してください ===

curl --location 'https://dashscope-intl.aliyuncs.com/compatible-mode/v1/chat/completions' \
--header "Authorization: Bearer $DASHSCOPE_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
  "model": "qwen3-vl-plus",
  "messages": [
  {"role":"system",
  "content":[
    {"type": "text", "text": "あなたは親切なアシスタントです。"}]},
  {
    "role": "user",
    "content": [
      {"type": "image_url", "image_url": {"url": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"}},
      {"type": "text", "text": "画像からチケット情報(配列型。travel_date、trains、seat_num、arrival_site、price を含む)と請求書情報(配列型。invoice_code および invoice_number を含む)を抽出してください。チケットおよび請求書の両方の配列を含む JSON を出力してください"}
    ]
  }],
  "response_format":{"type": "json_object"}
}'

応答

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "stream",
      "seat_num": "371",
      "arrival_site": "Development Zone",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

DashScope

Python

import os
import dashscope

# 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/api/v1
dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

messages = [
{
    "role": "system",
    "content": [
    {"text": "あなたは親切なアシスタントです。"}]
},
{
    "role": "user",
    "content": [
    {"image": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"},
    {"text": "画像からチケット情報(配列型。travel_date、trains、seat_num、arrival_site、price を含む)と請求書情報(配列型。invoice_code および invoice_number を含む)を抽出してください。チケットおよび請求書の両方の配列を含む JSON を出力してください"}]
}]
response = dashscope.MultiModalConversation.call(
    # 環境変数を設定していない場合は、次の行を api_key ="sk-xxx"(Model Studio API キー)に置き換えます
    api_key = os.getenv('DASHSCOPE_API_KEY'),
    model = 'qwen3-vl-plus',
    messages = messages,
    response_format={'type': 'json_object'}
)
json_string = response.output.choices[0].message.content[0]["text"]
print(json_string)

応答

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "Liushui",
      "seat_num": "371",
      "arrival_site": "Development Zone",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

Java

// DashScope Java SDK のバージョンは 2.21.4 以上である必要があります

import java.util.Arrays;
import java.util.Collections;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.alibaba.dashscope.common.ResponseFormat;
import com.alibaba.dashscope.utils.Constants;

public class Main {
    
    // 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/api/v1
    static {
        Constants.baseHttpApiUrl="https://dashscope-intl.aliyuncs.com/api/v1";
    }
    public static void simpleMultiModalConversationCall()
            throws ApiException, NoApiKeyException, UploadFileException {
        MultiModalConversation conv = new MultiModalConversation();
        MultiModalMessage systemMessage = MultiModalMessage.builder().role(Role.SYSTEM.getValue())
                .content(Arrays.asList(
                        Collections.singletonMap("text", "あなたは親切なアシスタントです。"))).build();
        MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
                .content(Arrays.asList(
                        Collections.singletonMap("image", "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"),
                        Collections.singletonMap("text", "画像からチケット情報(配列型。travel_date、trains、seat_num、arrival_site、price を含む)と請求書情報(配列型。invoice_code および invoice_number を含む)を抽出してください。チケットおよび請求書の両方の配列を含む JSON を出力してください"))).build();
        ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
        MultiModalConversationParam param = MultiModalConversationParam.builder()
                // 環境変数を設定していない場合は、次の行を .apiKey("sk-xxx")(Model Studio API キー)に置き換えます
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .model("qwen3-vl-plus")
                .messages(Arrays.asList(systemMessage, userMessage))
                .responseFormat(jsonMode)
                .build();
        MultiModalConversationResult result = conv.call(param);
        System.out.println(result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text"));
    }
    public static void main(String[] args) {
        try {
            simpleMultiModalConversationCall();
        } catch (ApiException | NoApiKeyException | UploadFileException e) {
            System.out.println(e.getMessage());
        }
    }
}

応答

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "stream",
      "seat_num": "371",
      "arrival_site": "Development Zone",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

curl

# ======= 重要事項 =======
# 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation
# API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/ja/model-studio/get-api-key
# === 実行前にこのコメントを削除してください ===

curl -X POST https://dashscope-intl.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
    "model": "qwen3-vl-plus",
    "input": {
        "messages": [
            {
                "role": "system",
                "content": [
                    {
                        "text": "あなたは親切なアシスタントです。"
                    }
                ]
            },
            {
                "role": "user",
                "content": [
                    {
                        "image": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"
                    },
                    {
                        "text": "画像からチケット情報(配列型。travel_date、trains、seat_num、arrival_site、price を含む)と請求書情報(配列型。invoice_code および invoice_number を含む)を抽出してください。チケットおよび請求書の両方の配列を含む JSON を出力してください"
                    }
                ]
            }
        ]
    },
    "parameters": {
        "response_format": {
            "type": "json_object"
        }
    }
}'

応答

{
  "output": {
    "choices": [
      {
        "message": {
          "content": [
            {
              "text": "{\n  \"ticket\": [\n    {\n      \"travel_date\": \"2013-06-29\",\n      \"trains\": \"train number\",\n      \"seat_num\": \"371\",\n      \"arrival_site\": \"Development Zone\",\n      \"price\": \"8.00\"\n    }\n  ],\n  \"invoice\": [\n    {\n      \"invoice_code\": \"221021325353\",\n      \"invoice_number\": \"10283819\"\n    }\n  ]\n}"
            }
          ],
          "role": "assistant"
        },
        "finish_reason": "stop"
      }
    ]
  },
  "usage": {
    "total_tokens": 598,
    "input_tokens_details": {
      "image_tokens": 418,
      "text_tokens": 68
    },
    "output_tokens": 112,
    "input_tokens": 486,
    "output_tokens_details": {
      "text_tokens": 112
    },
    "image_tokens": 418
  },
  "request_id": "b129dce1-0d5d-4772-b8b5-bd3a1d5cde63"
}

プロンプトの最適化

「ユーザー情報を返してください」といった曖昧なプロンプトでは、予測不能な出力構造になってしまいます。信頼性の高い結果を得るには、プロンプト内で期待されるスキーマを明確に記述してください。具体的には、フィールド名、データ型、必須/任意のステータス、日付形式などのフォーマット制約を指定し、例を含めてください。

OpenAI 互換

Python

from openai import OpenAI
import os
import json
import textwrap  # 複数行文字列のインデントを処理し、コードの可読性を向上させます

# 期待される出力形式をモデルに示すための事前定義された例となる応答
# 例 1:すべてのフィールドを含む完全な応答
example1_response = json.dumps(
    {
        "info": {"name": "張三", "age": "25 years old", "email": "zhangsan@example.com"},
        "hobby": ["singing"]
    },
    ensure_ascii=False
)
# 例 2:複数の趣味を含む応答
example2_response = json.dumps(
    {
        "info": {"name": "李四", "age": "30 years old", "email": "lisi@example.com"},
        "hobby": ["dancing", "swimming"]
    },
    ensure_ascii=False
)
# 例 3:hobby フィールドを含まない応答(hobby は任意)
example3_response = json.dumps(
    {
        "info": {"name": "趙六", "age": "28 years old", "email": "zhaoliu@example.com"}
    },
    ensure_ascii=False
)
# 例 4:hobby フィールドを含まない別の応答
example4_response = json.dumps(
    {
        "info": {"name": "孫七", "age": "35 years old", "email": "sunqi@example.com"}
    },
    ensure_ascii=False
)

# OpenAI クライアントを初期化します
client = OpenAI(
    # 環境変数を設定していない場合は、次の行を api_key="sk-xxx" に置き換えます
    # API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 以下は中国 (北京) リージョンの base_url です。シンガポールリージョンのモデルを使用する場合は、base_url を次のように置き換えてください: https://dashscope-intl.aliyuncs.com/compatible-mode/v1
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

# dedent は各行から共通の先頭空白を削除し、コード内で文字列をきれいにインデントでき、実行時に余分なスペースを含めないようにします
system_prompt = textwrap.dedent(f"""\
    ユーザー入力から個人情報を抽出し、指定された JSON Schema 形式で出力してください:

    [出力形式の要件]
    出力は以下の JSON 構造に厳密に従う必要があります:
    {{
      "info": {{
        "name": "文字列型、必須フィールド、ユーザーの名前",
        "age": "文字列型、必須フィールド、形式は '数字 years old'(例:'25 years old')",
        "email": "文字列型、必須フィールド、標準的なメール形式(例:'user@example.com')"
      }},
      "hobby": ["文字列の配列型、任意フィールド、ユーザーのすべての趣味を含む。言及されていない場合は完全に省略"]
    }}

    [フィールド抽出ルール]
    1. name:テキストからユーザーの名前を特定し、必ず抽出します
    2. age:年齢情報を特定し、'数字 years old' 形式に変換し、必ず抽出します
    3. email:メールアドレスを特定し、元の形式を保持し、必ず抽出します
    4. hobby:ユーザーの趣味を特定し、文字列の配列として出力します。趣味が言及されていない場合は、hobby フィールドを完全に省略します

    [参照例]
    例 1(趣味あり):
    Q: 私の名前は張三で、25 歳、メールアドレスは zhangsan@example.com、趣味は歌うこと
    A: {example1_response}

    例 2(複数の趣味あり):
    Q: 私の名前は李四で、30 歳、メールアドレスは lisi@example.com、ダンスと水泳が好き
    A: {example2_response}

    例 3(趣味なし):
    Q: 私の名前は趙六で、28 歳、メールアドレスは zhaoliu@example.com
    A: {example3_response}

    例 4(趣味なし):
    Q: 私は孫七で、35 歳、メールアドレスは sunqi@example.com
    A: {example4_response}

    上記の形式とルールに厳密に従って情報を抽出し、JSON を出力してください。ユーザーが趣味を言及していない場合は、hobby フィールドを含めないでください。\
""")

# 情報抽出のためにモデル API を呼び出します
completion = client.chat.completions.create(
    model="qwen-plus",
    messages=[
        {
            "role": "system",
            "content": system_prompt
        },
        {
            "role": "user",
            "content": "みなさん、こんにちは。私の名前は田中一郎で、34 歳、メールアドレスは tanaka@example.com、バスケットボールと旅行が趣味です", 
        },
    ],
    response_format={"type": "json_object"},  # JSON 形式での返却を指定します
)

# モデルが生成した JSON 結果を抽出して出力します
json_string = completion.choices[0].message.content
print(json_string)

応答

{
  "info": {
    "name": "Alex Brown",
    "age": "34 years old",
    "email": "alexbrown@example.com"
  },
  "hobby": ["Basketball", "Traveling"]  
}

Node.js

import OpenAI from "openai";

// 期待される出力形式をモデルに示すための事前定義された例となる応答
// 例 1:すべてのフィールドを含む完全な応答
const example1Response = JSON.stringify({
    info: { name: "張三", age: "25 years old", email: "zhangsan@example.com" },
    hobby: ["singing"]
}, null, 2);

// 例 2:複数の趣味を含む応答
const example2Response = JSON.stringify({
    info: { name: "李四", age: "30 years old", email: "lisi@example.com" },
    hobby: ["dancing", "swimming"]
}, null, 2);

// 例 3:hobby フィールドを含まない応答(hobby は任意)
const example3Response = JSON.stringify({
    info: { name: "趙六", age: "28 years old", email: "zhaoliu@example.com" }
}, null, 2);

// 例 4:hobby フィールドを含まない別の応答
const example4Response = JSON.stringify({
    info: { name: "孫七", age: "35 years old", email: "sunqi@example.com" }
}, null, 2);

// OpenAI クライアント構成を初期化します
const openai = new OpenAI({
    // 環境変数を設定していない場合は、次の行を api_key="sk-xxx"(Alibaba Cloud Model Studio API キー)に置き換えます
    // API キーはリージョンごとに異なります。API キーの取得方法: https://www.alibabacloud.com/help/en/model-studio/get-api-key
    apiKey: process.env.DASHSCOPE_API_KEY,
    // 以下は中国 (北京) リージョンの base_url です。シンガポールリージョンのモデルを使用する場合は、base_url を次のように置き換えてください: https://dashscope-intl.aliyuncs.com/compatible-mode/v1
    baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1"
});

// 出力精度を向上させるために構造化されたプロンプトを使用してチャット補完リクエストを作成します
const completion = await openai.chat.completions.create({
    model: "qwen-plus",
    messages: [
        {
            role: "system",
            content: `[出力形式の要件]
出力は以下の JSON 構造に厳密に従う必要があります:
{
  "info": {
    "name": "文字列型、必須フィールド、ユーザーの名前",
    "age": "文字列型、必須フィールド、形式は '数字 years old'(例:'25 years old')",
    "email": "文字列型、必須フィールド、標準的なメール形式(例:'user@example.com')"
  },
  "hobby": ["文字列の配列型、任意フィールド、ユーザーのすべての趣味を含む。言及されていない場合は完全に省略"]
}

[フィールド抽出ルール]
1. name:テキストからユーザーの名前を特定し、必ず抽出します
2. age:年齢情報を特定し、'数字 years old' 形式に変換し、必ず抽出します
3. email:メールアドレスを特定し、元の形式を保持し、必ず抽出します
4. hobby:ユーザーの趣味を特定し、文字列の配列として出力します。趣味が言及されていない場合は hobby フィールドを完全に省略します

[参照例]
例 1(趣味あり):
Q: 私の名前は張三で、25 歳、メールアドレスは zhangsan@example.com、趣味は歌うこと
A: ${example1Response}

例 2(複数の趣味あり):
Q: 私の名前は李四で、30 歳、メールアドレスは lisi@example.com、ダンスと水泳が好き
A: ${example2Response}

例 3(趣味なし):
Q: 私の名前は趙六で、28 歳、メールアドレスは zhaoliu@example.com
A: ${example3Response}

例 4(趣味なし):
Q: 私は孫七で、35 歳、メールアドレスは sunqi@example.com
A: ${example4Response}

上記の形式とルールに厳密に従って情報を抽出し、JSON を出力してください。ユーザーが趣味を言及していない場合は、hobby フィールドを含めないでください。`
        },
        {
            role: "user",
            content: "みなさん、こんにちは。私の名前は田中一郎で、34 歳、メールアドレスは tanaka@example.com、バスケットボールと旅行が趣味です"
        }
    ],
    response_format: {
        type: "json_object"
    }
});

// モデルが生成した JSON 結果を抽出して出力します
const jsonString = completion.choices[0].message.content;
console.log(jsonString);

応答

{
  "info": {
    "name": "Alex Brown",
    "age": "34 歳",
    "email": "alexbrown@example.com"
  },
  "hobby": [
    "バスケットボールをする",
    "旅行"
  ]
}

DashScope

Python

import os
import json
import dashscope

# シンガポールリージョンのモデルを使用する場合は、次の行のコメントを解除してください
# dashscope.base_http_api_url = "https://dashscope-intl.aliyuncs.com/api/v1"

# 期待される出力形式をモデルに示すための事前定義された例となる応答
example1_response = json.dumps(
    {
        "info": {"name": "張三", "age": "25 years old", "email": "zhangsan@example.com"},
        "hobby": ["singing"]
    },
    ensure_ascii=False
)
example2_response = json.dumps(
    {
        "info": {"name": "李四", "age": "30 years old", "email": "lisi@example.com"},
        "hobby": ["dancing", "swimming"]
    },
    ensure_ascii=False
)
example3_response = json.dumps(
    {
        "info": {"name": "王五", "age": "40 years old", "email": "wangwu@example.com"},
        "hobby": ["Rap", "basketball"]
    },
    ensure_ascii=False
)

messages=[
        {
            "role": "system",
            "content": f"""ユーザー入力から個人情報を抽出し、指定された JSON Schema 形式で出力してください:

[出力形式の要件]
出力は以下の JSON 構造に厳密に従う必要があります:
{{
  "info": {{
    "name": "文字列型、必須フィールド、ユーザーの名前",
    "age": "文字列型、必須フィールド、形式は '数字 years old'(例:'25 years old')",
    "email": "文字列型、必須フィールド、標準的なメール形式(例:'user@example.com')"
  }},
  "hobby": ["文字列の配列型、任意フィールド、ユーザーのすべての趣味を含む。言及されていない場合は完全に省略"]
}}

[フィールド抽出ルール]
1. name:テキストからユーザーの名前を特定し、必ず抽出します
2. age:年齢情報を特定し、'数字 years old' 形式に変換し、必ず抽出します
3. email:メールアドレスを特定し、元の形式を保持し、必ず抽出します
4. hobby:ユーザーの趣味を特定し、文字列の配列として出力します。趣味が言及されていない場合は hobby フィールドを完全に省略します

[参照例]
例 1(趣味あり):
Q: 私の名前は張三で、25 歳、メールアドレスは zhangsan@example.com、趣味は歌うこと
A: {example1_response}

例 2(複数の趣味あり):
Q: 私の名前は李四で、30 歳、メールアドレスは lisi@example.com、ダンスと水泳が好き
A: {example2_response}

例 3(複数の趣味あり):
Q: メールアドレスは wangwu@example.com、40 歳、名前は王五で、Rap ができてバスケットボールができます
A: {example3_response}

上記の形式とルールに厳密に従って情報を抽出し、JSON を出力してください。ユーザーが趣味を言及していない場合は、hobby フィールドを含めないでください。"""
        },
        {
            "role": "user",
            "content": "みなさん、こんにちは。私の名前は田中一郎で、34 歳、メールアドレスは tanaka@example.com、バスケットボールと旅行が趣味です", 
        },
    ]
response = dashscope.Generation.call(
    # 環境変数を設定していない場合は、次の行を api_key="sk-xxx"(Alibaba Cloud Model Studio API キー)に置き換えます
    api_key=os.getenv('DASHSCOPE_API_KEY'),
    model="qwen-plus", 
    messages=messages,
    result_format='message',
    response_format={'type': 'json_object'}
    )
json_string = response.output.choices[0].message.content
print(json_string)

応答

{
  "info": {
    "name": "Alex Brown",
    "age": "34 歳",
    "email": "alexbrown@example.com"
  },
  "hobby": [
    "バスケットボールをする",
    "旅行"
  ]
}

Java

import java.util.Arrays;
import java.lang.System;
import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.common.ResponseFormat;
import com.alibaba.dashscope.protocol.Protocol;

public class Main {
    public static GenerationResult callWithMessage() throws ApiException, NoApiKeyException, InputRequiredException {
        // 中国 (北京) リージョンのモデルを使用する場合は、URL を次のように置き換えてください: https://dashscope.aliyuncs.com/api/v1
        Generation gen = new Generation(Protocol.HTTP.getValue(), "https://dashscope-intl.aliyuncs.com/api/v1");
        Message systemMsg = Message.builder()
                .role(Role.SYSTEM.getValue())
                .content("""
                ユーザー入力から個人情報を抽出し、指定された JSON Schema 形式で出力してください:

[出力形式の要件]
出力は以下の JSON 構造に厳密に従う必要があります:
{
  "info": {
    "name": "文字列型、必須フィールド、ユーザーの名前",
    "age": "文字列型、必須フィールド、形式は '数字 years old'(例:'25 years old')",
    "email": "文字列型、必須フィールド、標準的なメール形式(例:'user@example.com')"
  },
  "hobby": ["文字列の配列型、任意フィールド、ユーザーのすべての趣味を含む。趣味が言及されていない場合は、このフィールドを出力に含めないでください。"]
}

[フィールド抽出ルール]
1. name:テキストからユーザーの名前を特定します。これは必須フィールドです。
2. age:年齢情報を特定し、'数字 years old' 形式に変換します。これは必須フィールドです。
3. email:メールアドレスを特定し、元の形式を保持します。これは必須フィールドです。
4. hobby:ユーザーの趣味を特定し、文字列の配列として出力します。趣味が言及されていない場合は、hobby フィールドを完全に省略します。

[例]
例 1(趣味あり):
Q: 私の名前は張三で、25 歳、メールアドレスは zhangsan@example.com、趣味は歌うこと。
A: {"info":{"name":"張三","age":"25 years old","email":"zhangsan@example.com"},"hobby":["singing"]}

例 2(複数の趣味あり):
Q: 私の名前は李四で、30 歳、メールアドレスは lisi@example.com、ダンスと水泳が好き。
A: {"info":{"name":"李四","age":"30 years old","email":"lisi@example.com"},"hobby":["dancing","swimming"]}

例 3(趣味なし):
Q: 私の名前は王五で、メールアドレスは wangwu@example.com、40 歳です。
A: {"info":{"name":"王五","age":"40 years old","email":"wangwu@example.com"}}""")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("みなさん、こんにちは。私の名前は田中一郎で、34 歳、メールアドレスは tanaka@example.com、バスケットボールと旅行が趣味です。")
                .build();
        ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
        GenerationParam param = GenerationParam.builder()
                // 中国 (北京) リージョンのモデルを使用する場合は、中国 (北京) リージョン用の API キーが必要です。キーの取得方法: https://bailian.console.alibabacloud.com/?tab=model#/api-key
                // 環境変数を設定していない場合は、次の行を Alibaba Cloud Model Studio API キーに置き換えてください:.apiKey("sk-xxx")
                .apiKey(System.getenv("DASHSCOPE_API_KEY"))
                .model("qwen-plus")
                .messages(Arrays.asList(systemMsg, userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .responseFormat(jsonMode)
                .build();
        return gen.call(param);
    }
    public static void main(String[] args) {
        try {
            GenerationResult result = callWithMessage();
            System.out.println(result.getOutput().getChoices().get(0).getMessage().getContent());
        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            // ロギングフレームワークを使用して例外を記録します。
            System.err.println("生成サービスの呼び出し中にエラーが発生しました:" + e.getMessage());
        }
    }
}

応答

{
  "info": {
    "name": "Alex Brown",
    "age": "34 years old",
    "email": "alexbrown@example.com"
  },
  "hobby": [
    "バスケットボールをする",
    "旅行"
  ]
}

本番環境に適用

  • 下流サービスに渡す前に検証する

    常に、下流サービスに渡す前に JSON 出力を検証してください。jsonschema(Python)、Ajv(JavaScript)、Everit(Java)などのライブラリを使用して、フィールドの欠落、型エラー、フォーマットの問題をチェックします。検証に失敗した場合は、リクエストを再試行するか、別のモデルを使用して出力を修正してください。

  • max_tokens を設定しない

    構造化出力を有効にしている場合は、max_tokens を設定しないでください。このパラメーターは出力トークン数を上限で制限し、デフォルトではモデルの最大値になります。これを設定すると、JSON 文字列が出力途中で切り捨てられ、解析に失敗する無効な JSON が生成される可能性があります。

よくある質問

Q:Qwen の思考モードモデルはどのように構造化出力を生成しますか?

Qwen の思考モードモデルは、構造化出力を直接サポートしていません。思考モードモデルから有効な JSON 文字列を取得するには、2 ステップのアプローチを使用します。まず、思考モードモデルを呼び出して高品質な出力を取得し、次に不正な JSON を JSON モードをサポートするモデルに渡して修正します。

  1. 思考モードモデルから出力を取得する

    思考モードモデルを呼び出します。結果は有効な JSON ではない可能性があります。

    思考モードを有効にする際に、response_format パラメーターを {"type": "json_object"} に設定しないでください。そうしないとエラーが発生します。
    completion = client.chat.completions.create(
        model="qwen-plus",
        messages=[
            {"role": "system", "content": system_prompt},
            {
                "role": "user",
                "content": "みなさん、こんにちは。私の名前は田中一郎で、34 歳です。メールアドレスは tanaka@example.com で、バスケットボールと旅行が趣味です",
            },
        ],
        # 思考モードを有効にします。response_format パラメーターを {"type": "json_object"} に設定しないでください。そうしないとエラーが発生します
        extra_body={"enable_thinking": True},
        # 思考モードではストリーミング出力が必須です
        stream=True
    )
    # モデルが生成した JSON 結果を抽出して出力します
    json_string = ""
    for chunk in completion:
        if chunk.choices[0].delta.content is not None:
            json_string += chunk.choices[0].delta.content
  2. 出力を検証して修正する

    前のステップで取得した json_string を解析しようとします:

    • モデルが有効な JSON を返した場合は、直接解析して使用します。

    • モデルが無効な JSON を返した場合は、構造化出力をサポートするモデル(ノンシンキングモードの qwen-flash など、高速で低コストのモデルが適しています)を呼び出してフォーマットを修正します。

    import json
    from openai import OpenAI
    import os
    
    # OpenAI クライアントを初期化します(前のコードブロックで client 変数が定義されていない場合は、以下の行のコメントを解除してください)
    # client = OpenAI(
    #     api_key=os.getenv("DASHSCOPE_API_KEY"),
    #     base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    # )
    
    try:
        json_object_from_thinking_model = json.loads(json_string)
        print("標準的な JSON 文字列を生成しました")
    except json.JSONDecodeError:
        print("標準的な JSON 文字列を生成しませんでした。構造化出力をサポートするモデルで修正します")
        completion = client.chat.completions.create(
            model="qwen-flash",
            messages=[
                {
                    "role": "system",
                    "content": "あなたは JSON 形式の専門家です。ユーザーの JSON 文字列を標準形式に修正してください",
                },
                {
                    "role": "user",
                    "content": json_string,
                },
            ],
            response_format={"type": "json_object"},
        )
        json_object_from_thinking_model = json.loads(completion.choices[0].message.content)

エラーコード

モデルの呼び出しに失敗してエラーメッセージが返された場合は、「エラーメッセージ」を参照して解決してください。