情報抽出や構造化データ生成タスクを実行する際、モデルが ```json のような余分なテキストを返し、後続の解析を妨げることがあります。構造化出力を有効にすると、モデルが有効な JSON 文字列を返すことが保証されます。また、JSON スキーマモードを使用すると、出力の構造と型を正確に制御できるため、追加の検証やリトライが不要になります。
使用方法
構造化出力は、JSON オブジェクトと JSON スキーマの 2 つのモードをサポートしています。
-
JSON オブジェクトモード:出力が有効な JSON 文字列であることを保証しますが、特定の構造は保証しません。使用方法:
response_formatパラメーターの設定:リクエストボディで、response_formatを{"type": "json_object"}に設定します。- プロンプトに JSON キーワードを含める:システムメッセージまたはユーザーメッセージには、「JSON」という単語 (大文字と小文字を区別しない) を含める必要があります。そうしない場合、API は
'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'.を返します。
-
JSON スキーマモード:出力が指定された構造に準拠することを保証します。使用方法:
response_formatを{"type": "json_schema", "json_schema": {...}, "strict": true}に設定します。プロンプトに JSON キーワードは不要です。
機能比較:
機能 | JSON オブジェクトモード | JSON スキーマモード |
|---|---|---|
有効な JSON を出力 | はい | はい |
スキーマに厳密に従う | いいえ | はい |
サポート対象モデル | ほとんどの Qwen モデル | 一部の qwen-plus モデルのみ |
|
|
|
プロンプトの要件 | 「JSON」を含める必要があります | 明示的に記述することを推奨します |
ユースケース | 柔軟な JSON 出力 | 正確なスキーマ検証 |
サポート対象モデル
JSON オブジェクト
Qwen
-
テキスト生成モデル
- Qwen-Max:Qwen3.8-Max シリーズ、Qwen3.7-Max シリーズ
- Qwen-Max (ノンシンキングモード):Qwen3.6-Max シリーズ、Qwen3-Max シリーズ、Qwen-Max シリーズ
- Qwen-Plus:Qwen3.7-Plus シリーズ
- Qwen-Plus (ノンシンキングモード):Qwen3.6-Plus シリーズ、Qwen3.5-Plus シリーズ、Qwen-Plus シリーズ
- Qwen-Flash:Qwen3.8-Flash シリーズ、Qwen3.7-Flash シリーズ
- Qwen-Flash (ノンシンキングモード):Qwen3.6-Flash シリーズ、Qwen3.5-Flash シリーズ、Qwen-Flash シリーズ
- Qwen-Turbo (ノンシンキングモード):Qwen-Turbo シリーズ
- Qwen-Coder:Qwen3-Coder シリーズ
- Qwen-Long:Qwen-Long シリーズ
- Qwen3.8 オープンソースシリーズ
- Qwen3.6 オープンソースシリーズ (ノンシンキングモード)
- Qwen3.5 オープンソースシリーズ (ノンシンキングモード)
- Qwen3 オープンソースシリーズ (ノンシンキングモード)
- Qwen3-Coder オープンソースシリーズ
- Qwen2.5 オープンソースシリーズ (数学およびコーダーモデルを除く)
-
マルチモーダルモデル
- Qwen-VL (ノンシンキングモード):Qwen3-VL-Plus シリーズ、Qwen3-VL-Flash シリーズ、Qwen-VL-Max シリーズ (最新およびスナップショットバージョンを除く)、Qwen-VL-Plus シリーズ (最新およびスナップショットバージョンを除く)
- Qwen-Omni:Qwen3.5-Omni-Plus シリーズ
- Qwen3-VL オープンソースシリーズ (ノンシンキングモード)
注記「ノンシンキングモード」とラベル付けされたモデルは、思考モードで response_format を {"type": "json_object"} に設定してもエラーにはなりませんが、一部のモデルは厳密に有効な JSON ではないコンテンツを返す場合があります。確実に有効な JSON が必要な場合は、よくある質問をご参照ください。
Kimi
kimi-k2-thinking
GLM
- glm-5.1
- ノンシンキングモード:glm-5, glm-4.7, glm-4.6
DeepSeek
deepseek-v4-pro, deepseek-v4-flash
JSON スキーマ
Qwen3.7-Plus シリーズ、Qwen3.7-Max シリーズ、Qwen3.8-Max シリーズ、および Qwen3.8-Flash シリーズのモデル。
さらに多くのモデルが近日公開予定です。
はじめに
この例では、個人のプロファイルから構造化情報を抽出します。
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://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 に置き換えてください
base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
model="qwen3.8-max",
messages=[
{
"role": "system",
"content": "ユーザーの名前と年齢を抽出し、JSON 形式で返します"
},
{
"role": "user",
"content": "皆さん、こんにちは。私の名前は田中一郎です。34 歳で、メールアドレスは alexbrown@example.com です。バスケットボールと旅行が好きです",
},
],
response_format={"type": "json_object"}
)
json_string = completion.choices[0].message.content
print(json_string)
応答
{
"Name": "Alex Brown",
"Age": 34
}
Node.js
import OpenAI from "openai";
const openai = new OpenAI({
// 環境変数を設定していない場合は、次の行を apiKey: "sk-xxx" に置き換えてください
apiKey: process.env.DASHSCOPE_API_KEY,
// 北京リージョンのモデルの場合は、baseURL を https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 に置き換えてください
baseURL: "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
});
const completion = await openai.chat.completions.create({
model: "qwen3.8-max",
messages: [
{
role: "system",
content: "ユーザーの名前と年齢を抽出し、JSON 形式で返します"
},
{
role: "user",
content: "皆さん、こんにちは。私の名前は田中一郎です。34 歳で、メールアドレスは alexbrown@example.com です。バスケットボールと旅行が好きです"
}
],
response_format: {
type: "json_object"
}
});
const jsonString = completion.choices[0].message.content;
console.log(jsonString);
応答
{
"name": "Alex Brown",
"age": 34
}
curl
# ======= 重要 =======
# API キーはリージョンによって異なります。API キーを取得するには、https://www.alibabacloud.com/help/model-studio/get-api-key をご参照ください
# 北京リージョンのモデルを使用する場合は、URL を https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1/chat/completions に置き換えてください
# === 実行前にこのコメントを削除してください ===
curl -X POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1/chat/completions \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.8-max",
"messages": [
{
"role": "system",
"content": "名前 (文字列)、年齢 (文字列)、メールアドレス (文字列) を抽出する必要があります。結果を JSON 文字列として出力します。他の無関係なコンテンツは含めないでください。\n例:\nQ: 私の名前はアリス、25 歳、メールアドレスは alice@example.com です\nA: {\"name\":\"アリス\",\"age\":\"25 歳\",\"email\":\"alice@example.com\"}\nQ: 私の名前はボブ、30 歳、メールアドレスは bob@example.com です\nA: {\"name\":\"ボブ\",\"age\":\"30 歳\",\"email\":\"bob@example.com\"}\nQ: 私の名前はチャーリー、メールアドレスは charlie@example.com、40 歳です\nA: {\"name\":\"チャーリー\",\"age\":\"40 歳\",\"email\":\"charlie@example.com\"}"
},
{
"role": "user",
"content": "皆さん、こんにちは。私の名前は田中一郎です。34 歳で、メールアドレスは alexbrown@example.com です"
}
],
"response_format": {
"type": "json_object"
}
}'
応答
{
"choices": [
{
"message": {
"role": "assistant",
"content": "{\"name\":\"田中一郎\",\"age\":\"34 歳\"}"
},
"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": "qwen3.8-max",
"id": "chatcmpl-624b665b-fb93-99e7-9ebd-bb6d86d314d2"
}
DashScope
Python
import os
import dashscope
# 北京リージョンのモデルの場合は、URL を https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1 に置き換えてください。
dashscope.base_http_api_url = 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1'
messages=[
{
"role": "system",
"content": "Extract the user's name and age, and return them in JSON format"
},
{
"role": "user",
"content": "Hi everyone, my name is Alex Brown, I'm 34 years old, my email is alexbrown@example.com, and I enjoy playing basketball and traveling",
},
]
response = dashscope.MultiModalConversation.call(
# 環境変数を設定していない場合は、次の行を api_key="sk-xxx" (Alibaba Cloud Model Studio API キー) に置き換えてください。
api_key=os.getenv('DASHSCOPE_API_KEY'),
model="qwen3.8-max",
messages=messages,
response_format={'type': 'json_object'}
)
json_string = response.output.choices[0].message.content[0]["text"]
print(json_string)
応答
{
"name": "Alex Brown",
"age": 34
}
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://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1 に置き換えます
static {
Constants.baseHttpApiUrl="https://{WorkspaceId}.ap-southeast-1.maas.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", "Extract the user's name and age, and return them in JSON format"))).build();
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(
Collections.singletonMap("text", "Hi everyone, my name is Alex Brown, I'm 34 years old, my email is alexbrown@example.com, and I enjoy playing basketball and traveling"))).build();
ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
// 環境変数を設定していない場合は、次の行を .apiKey("sk-xxx") に置き換えます
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("qwen3.8-max")
.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());
}
}
}
応答
{
"name": "Alex Brown",
"age": 34
}
curl
# ======= 重要事項 =======
# 北京リージョンのモデルの場合は、URL を https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation に置き換えてください
# API キーはリージョンによって異なります。API キーの取得: https://www.alibabacloud.com/help/model-studio/get-api-key
# === 実行前にこのコメントを削除してください ===
curl -X POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3.8-max",
"input": {
"messages": [
{
"role": "system",
"content": "ユーザーの名前と年齢を抽出し、JSON 形式で返します"
},
{
"role": "user",
"content": "皆さん、こんにちは。私の名前は田中一郎です。34 歳で、メールアドレスは alexbrown@example.com です。バスケットボールと旅行が好きです"
}
]
},
"parameters": {
"response_format": {
"type": "json_object"
}
}
}'
応答
{
"name": "Alex Brown",
"age": 34
}
画像と動画のデータ処理
マルチモーダルモデルは、画像や動画の構造化出力もサポートしています。JSON モードを使用して、レシートのフィールド値、画像内のオブジェクトの位置、動画内のイベントなど、視覚コンテンツから構造化データを抽出します。
画像と動画のファイル制限については、「画像と動画の理解」をご参照ください。
OpenAI 互換
Python
import os
from openai import OpenAI
client = OpenAI(
# API キーはリージョンによって異なります。API キーの取得: https://www.alibabacloud.com/help/model-studio/get-api-key
api_key=os.getenv("DASHSCOPE_API_KEY"),
# 北京リージョンのモデルの場合は、base_url を https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 に置き換えてください
base_url="https://{WorkspaceId}.ap-southeast-1.maas.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/model-studio/get-api-key
// 環境変数を設定していない場合は、次の行を apiKey: "sk-xxx" (Model Studio API キー) に置き換えてください
apiKey: process.env.DASHSCOPE_API_KEY,
// 北京リージョンのモデルの場合は、base_url を https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1 に置き換えてください
baseURL: "https://{WorkspaceId}.ap-southeast-1.maas.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://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1/chat/completions に置き換えてください
# API キーはリージョンによって異なります。API キーの取得: https://www.alibabacloud.com/help/model-studio/get-api-key
# === 実行前にこのコメントを削除してください ===
curl --location 'https://{WorkspaceId}.ap-southeast-1.maas.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://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1 に置き換えてください
dashscope.base_http_api_url = 'https://{WorkspaceId}.ap-southeast-1.maas.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://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1 に置き換えてください
static {
Constants.baseHttpApiUrl="https://{WorkspaceId}.ap-southeast-1.maas.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://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation に置き換えてください
# API キーはリージョンによって異なります。API キーの取得: https://www.alibabacloud.com/help/model-studio/get-api-key
# === 実行前にこのコメントを削除してください ===
curl -X POST https://{WorkspaceId}.ap-southeast-1.maas.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": "Alice", "age": "25 years old", "email": "alice@example.com"},
"hobby": ["singing"]
},
ensure_ascii=False
)
# 例 2: 複数の趣味を含む応答
example2_response = json.dumps(
{
"info": {"name": "Bob", "age": "30 years old", "email": "bob@example.com"},
"hobby": ["dancing", "swimming"]
},
ensure_ascii=False
)
# 例 3: hobby フィールドのない応答 (hobby はオプション)
example3_response = json.dumps(
{
"info": {"name": "Dave", "age": "28 years old", "email": "dave@example.com"}
},
ensure_ascii=False
)
# 例 4: hobby フィールドのない別の応答
example4_response = json.dumps(
{
"info": {"name": "Sun Qi", "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/ja/model-studio/get-api-key
api_key=os.getenv("DASHSCOPE_API_KEY"),
# これは北京リージョンの base_url です。シンガポールリージョンのモデルを使用する場合は、base_url を https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1 に置き換えます
base_url="https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1",
)
# dedent は各行の共通の先頭の空白を削除し、ランタイムに余分なスペースを含めずにコード内で文字列をきれいにインデントできるようにします
system_prompt = textwrap.dedent(f"""\
ユーザー入力から個人情報を抽出し、指定された JSON スキーマ形式で出力します。
[出力形式の要件]
出力は、この 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: 私の名前は Alice、25 歳、メールアドレスは alice@example.com、趣味は歌です
A: {example1_response}
例 2 (複数の趣味あり):
Q: 私の名前は Bob、30 歳、メールアドレスは bob@example.com、ダンスと水泳が好きです
A: {example2_response}
例 3 (趣味なし):
Q: 私の名前は Dave、28 歳、メールアドレスは dave@example.com です
A: {example3_response}
例 4 (趣味なし):
Q: 私は Sun Qi、35 歳、メールアドレスは sunqi@example.com です
A: {example4_response}
上記の形式とルールに厳密に従って情報を抽出し、JSON を出力してください。ユーザーが趣味について言及していない場合は、hobby フィールドを含めないでください。\
""")
# モデル API を呼び出して情報抽出を実行
completion = client.chat.completions.create(
model="qwen3.8-max",
messages=[
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": "みなさん、こんにちは。私の名前は Alex Brown、34 歳、メールアドレスは alexbrown@example.com、バスケットボールと旅行が好きです",
},
],
response_format={"type": "json_object"}, # JSON 形式の戻り値を指定
)
# モデルが生成した JSON 結果を抽出して出力
json_string = completion.choices[0].message.content
print(json_string)
応答
{
"info": {
"name": "田中一郎",
"age": "34 歳",
"email": "alexbrown@example.com"
},
"hobby": ["バスケットボール", "旅行"]
}
Node.js
import OpenAI from "openai";
// 事前定義された応答例 (モデルに期待される出力フォーマットを示すため)
// 例 1: すべてのフィールドを含む完全な応答
const example1Response = JSON.stringify({
info: { name: "Alice", age: "25 years old", email: "alice@example.com" },
hobby: ["singing"]
}, null, 2);
// 例 2: 複数の趣味を含む応答
const example2Response = JSON.stringify({
info: { name: "Bob", age: "30 years old", email: "bob@example.com" },
hobby: ["dancing", "swimming"]
}, null, 2);
// 例 3: hobby フィールドなしの応答 (hobby はオプション)
const example3Response = JSON.stringify({
info: { name: "Dave", age: "28 years old", email: "dave@example.com" }
}, null, 2);
// 例 4: hobby フィールドなしの別の応答
const example4Response = JSON.stringify({
info: { name: "Sun Qi", age: "35 years old", email: "sunqi@example.com" }
}, null, 2);
// OpenAI クライアントの設定を初期化
const openai = new OpenAI({
// 環境変数を設定していない場合は、次の行を apiKey: "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://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1 に置き換えます。
baseURL: "https://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/compatible-mode/v1"
});
// 構造化プロンプトを使用してチャット補完リクエストを作成し、出力精度を向上させます
const completion = await openai.chat.completions.create({
model: "qwen3.8-max",
messages: [
{
role: "system",
content: `ユーザー入力から個人情報を抽出し、指定された JSON スキーマフォーマットで出力します:
[出力フォーマット要件]
出力は、この JSON 構造に厳密に従う必要があります:
{
"info": {
"name": "文字列型、必須フィールド、ユーザー名",
"age": "文字列型、必須フィールド、フォーマット 'number years old'、例: '25 years old'",
"email": "文字列型、必須フィールド、標準のメールフォーマット、例: 'user@example.com'"
},
"hobby": ["文字列配列型、オプションフィールド、すべてのユーザーの趣味を含む。言及がない場合は完全に省略"]
}
[フィールド抽出ルール]
1. name: テキストからユーザー名を識別し、抽出必須
2. age: 年齢情報を識別し、'number years old' フォーマットに変換し、抽出必須
3. email: メールアドレスを識別し、元のフォーマットを維持し、抽出必須
4. hobby: ユーザーの趣味を識別し、文字列配列として出力。趣味について言及がない場合は hobby フィールドを完全に省略
[参考例]
例 1 (趣味あり):
Q: My name is Alice, I'm 25 years old, my email is alice@example.com, and my hobby is singing
A: ${example1Response}
例 2 (複数の趣味あり):
Q: My name is Bob, I'm 30 years old, my email is bob@example.com, and I enjoy dancing and swimming
A: ${example2Response}
例 3 (趣味なし):
Q: My name is Dave, I'm 28 years old, and my email is dave@example.com
A: ${example3Response}
例 4 (趣味なし):
Q: I'm Sun Qi, 35 years old, and my email is sunqi@example.com
A: ${example4Response}
上記のフォーマットとルールに厳密に従って情報を抽出し、JSON を出力してください。ユーザーが趣味に言及していない場合は、hobby フィールドを含めないでください。`
},
{
role: "user",
content: "Hi everyone, my name is Alex Brown, I'm 34 years old, my email is alexbrown@example.com, and I enjoy playing basketball and traveling"
}
],
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://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
# 事前定義された応答例 (モデルに期待される出力形式を示すため)
example1_response = json.dumps(
{
"info": {"name": "アリス", "age": "25 歳", "email": "alice@example.com"},
"hobby": ["歌唱"]
},
ensure_ascii=False
)
example2_response = json.dumps(
{
"info": {"name": "ボブ", "age": "30 歳", "email": "bob@example.com"},
"hobby": ["ダンス", "水泳"]
},
ensure_ascii=False
)
example3_response = json.dumps(
{
"info": {"name": "チャーリー", "age": "40 歳", "email": "charlie@example.com"},
"hobby": ["ラップ", "バスケットボール"]
},
ensure_ascii=False
)
messages=[
{
"role": "system",
"content": f"""ユーザー入力から個人情報を抽出し、指定された JSON スキーマ形式で出力します:
[出力フォーマット要件]
出力は、この JSON 構造に厳密に従う必要があります:
{{
"info": {{
"name": "文字列型、必須フィールド、ユーザーの名前",
"age": "文字列型、必須フィールド、フォーマット「数字 歳」、例:「25 歳」",
"email": "文字列型、必須フィールド、標準メールフォーマット、例:「user@example.com」"
}},
"hobby": ["文字列配列型、オプションフィールド、すべてのユーザーの趣味を含む。言及されていない場合は完全に省略"]
}}
[フィールド抽出ルール]
1. name: テキストからユーザーの名前を特定し、抽出する必要があります
2. age: 年齢情報を特定し、「数字 歳」形式に変換し、抽出する必要があります
3. email: メールアドレスを特定し、元の形式を維持し、抽出する必要があります
4. hobby: ユーザーの趣味を特定し、文字列配列として出力します。趣味が言及されていない場合は、hobby フィールドを完全に省略します
[参照例]
例 1 (趣味あり):
Q: 私の名前はアリス、25 歳、メールは alice@example.com、趣味は歌唱です
A: {example1_response}
例 2 (複数の趣味あり):
Q: 私の名前はボブ、30 歳、メールは bob@example.com、ダンスと水泳が好きです
A: {example2_response}
例 3 (複数の趣味あり):
Q: 私のメールは charlie@example.com、40 歳、名前はチャーリー、ラップとバスケットボールができます
A: {example3_response}
上記のフォーマットとルールに厳密に従って情報を抽出し、JSON を出力します。ユーザーが趣味について言及していない場合は、hobby フィールドを出力に含めないでください。"""
},
{
"role": "user",
"content": "皆さん、こんにちは。私の名前は田中一郎です。34 歳で、メールアドレスは alexbrown@example.com です。バスケットボールと旅行が好きです",
},
]
response = dashscope.MultiModalConversation.call(
# 環境変数を設定していない場合は、次の行を Alibaba Cloud Model Studio API キーに置き換えてください: api_key="sk-xxx",
api_key=os.getenv('DASHSCOPE_API_KEY'),
model="qwen3.8-max",
messages=messages,
response_format={'type': 'json_object'}
)
json_string = response.output.choices[0].message.content[0]["text"]
print(json_string)
応答
{
"info": {
"name": "アレックス・ブラウン",
"age": "34歳",
"email": "alexbrown@example.com"
},
"hobby": [
"バスケットボール",
"旅行"
]
}
Java
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://{WorkspaceId}.cn-beijing.maas.aliyuncs.com/api/v1 に置き換えます
static {
Constants.baseHttpApiUrl="https://{WorkspaceId}.ap-southeast-1.maas.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", """
ユーザー入力から個人情報を抽出し、指定された JSON スキーマフォーマットで出力します:
[出力フォーマット要件]
出力は、以下の 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: My name is Alice, I am 25 years old, my email is alice@example.com, and my hobby is singing.
A: {"info":{"name":"Alice","age":"25 years old","email":"alice@example.com"},"hobby":["singing"]}
例2 (複数の趣味あり):
Q: My name is Bob, I am 30 years old, my email is bob@example.com, and I like dancing and swimming.
A: {"info":{"name":"Bob","age":"30 years old","email":"bob@example.com"},"hobby":["dancing","swimming"]}
例3 (趣味なし):
Q: My name is Charlie, my email is charlie@example.com, and I am 40 years old.
A: {"info":{"name":"Charlie","age":"40 years old","email":"charlie@example.com"}}"""))).build();
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(
Collections.singletonMap("text", "皆さん、こんにちは。私の名前は Alex Brown です。34歳で、メールアドレスは alexbrown@example.com です。バスケットボールと旅行が好きです。"))).build();
ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
// 環境変数を設定していない場合は、次の行を .apiKey("sk-xxx") に置き換えます
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("qwen3.8-max")
.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());
}
}
}
応答
{
"info": {
"name": "田中一郎",
"age": "34 歳",
"email": "alexbrown@example.com"
},
"hobby": [
"バスケットボール",
"旅行"
]
}
構造化出力の取得
response_format の type を json_object に設定すると、有効な JSON 文字列が返されますが、その構造は期待と異なる場合があります。これは単純なシナリオに適しています。自動解析、API の相互運用性、および厳密な型制約を必要とするその他の複雑なシナリオでは、type を json_schema に設定して、モデルに指定されたフォーマットに厳密に準拠したコンテンツを出力させます。response_format のフォーマットと例:
{
"type": "json_schema",
"json_schema": {
"name": "schema_name", // スキーマの名前
"strict": true, // 推奨:フォーマットに厳密に従う
"schema": {
"type": "object",
"properties": {...}, // フィールド構造を定義 (右の例を参照)
"required": [...], // 必須フィールドのリスト
"additionalProperties": false // 推奨:定義されたフィールドのみを出力
}
}
}
{
"type": "json_schema",
"json_schema": {
"name": "user_info",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "ユーザー名"
},
"age": {
"type": "integer",
"description": "ユーザーの年齢"
},
"email": {
"type": "string",
"description": "メールアドレス"
}
},
"required": ["name", "age"],
"additionalProperties": false
}
}
}
上記の例では、モデルに 2 つの必須フィールド (name と age) とオプションの email フィールドを持つ JSON オブジェクトを出力させます。
シンガポールリージョンのモデルはまだサポートされていません。
使用方法
OpenAI SDK の parse メソッドを使用すると、Python の Pydantic クラスまたは Node.js の Zod オブジェクトを直接渡すことができます。SDK はそれを自動的に JSON スキーマに変換するため、複雑な JSON を手動で記述する必要はありません。DashScope SDK の場合は、上記のフォーマットに従って JSON スキーマを手動で構築します。
OpenAI 互換
Python
from pydantic import BaseModel, Field
from openai import OpenAI
import os
client = OpenAI(
api_key=os.getenv("DASHSCOPE_API_KEY"),
# 次の URL はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
)
class UserInfo(BaseModel):
name: str = Field(description="ユーザー名")
age: int = Field(description="ユーザーの年齢 (年)")
completion = client.chat.completions.parse(
model="qwen3.8-max",
messages=[
{"role": "system", "content": "名前と年齢の情報を抽出します。"},
{"role": "user", "content": "私の名前は鈴木五郎、25 歳です。"},
],
response_format=UserInfo,
)
result = completion.choices[0].message.parsed
print(f"名前: {result.name}, 年齢: {result.age}")
Node.js
import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";
const openai = new OpenAI(
{
apiKey: process.env.DASHSCOPE_API_KEY,
// 次の URL はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
baseURL: "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
}
);
const UserInfo = z.object({
name: z.string().describe("ユーザー名"),
age: z.number().int().describe("ユーザーの年齢 (年)"),
});
const completion = await openai.chat.completions.parse({
model: "qwen3.8-max",
messages: [
{ role: "system", content: "名前と年齢の情報を抽出します。" },
{ role: "user", content: "私の名前は鈴木五郎、25 歳です。" },
],
response_format: zodResponseFormat(UserInfo, "user_info"),
});
const userInfo = completion.choices[0].message.parsed;
console.log(`名前: ${userInfo.name}`);
console.log(`年齢: ${userInfo.age}`);
コードを実行すると、次の出力が生成されます:
Name: Liu Wu, Age: 25
DashScope
Java SDK はまだサポートされていません。
Python
import os
import dashscope
import json
# 次の URL はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
dashscope.base_http_api_url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
messages = [
{
"role": "user",
"content": [{"text": "私の名前は鈴木五郎、25 歳です。"}],
},
]
response = dashscope.MultiModalConversation.call(
api_key=os.getenv("DASHSCOPE_API_KEY"),
model="qwen3.8-max",
messages=messages,
response_format={
"type": "json_schema",
"json_schema": {
"name": "user_info",
"schema": {
"properties": {
"name": {"title": "名前", "type": "string"},
"age": {"title": "年齢", "type": "integer"},
},
"required": ["name", "age"],
"title": "UserInfo",
"type": "object",
},
},
"strict": True,
},
)
json_object = json.loads(response.output.choices[0].message.content[0]["text"])
print(f"名前: {json_object['name']}, 年齢: {json_object['age']}")
コードを実行すると、次の出力が生成されます:
Name: Liu Wu, Age: 25
設定ガイド
より信頼性の高い構造化出力を得るために、JSON スキーマを使用する際は、以下のガイドラインに従ってください:
-
必須フィールドの宣言
required配列に必須フィールドをリストアップすることを推奨します。オプションのフィールドは省略できます。例:
{
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"email": {"type": "string"}
},
"required": ["name", "age"]
}
入力にメール情報が含まれていない場合、出力にはこのフィールドは含まれません。
-
オプションフィールドの実装
requiredから省略する以外に、null型を許可することもできます:
{
"properties": {
"name": {"type": "string"},
"email": {"type": ["string", "null"]} // 文字列または null にすることができる
},
"required": ["name", "email"] // 両方とも required に含まれる
}
出力には常に email フィールドが含まれますが、その値は null になることがあります。
-
additionalProperties の設定
スキーマで定義されていない追加のフィールドを許可するかどうかを制御します:
{
"properties": {"name": {"type": "string"}},
"required": ["name"],
"additionalProperties": true // 追加のフィールドを許可
}
入力例:"私は佐藤太郎、25 歳です";出力:{"name": "佐藤太郎", "age": 25} (未定義の age フィールドを含む)。
値 | 動作 | ユースケース |
|---|---|---|
| 定義されたフィールドのみを出力 | 正確な構造制御 |
| 追加のフィールドを許可 | より多くの情報をキャプチャ |
- サポートされているデータ型:string、number、integer、boolean、object、array、enum。
本番環境への適用
-
後続に渡す前に検証する
JSON オブジェクトモードを使用する場合、後続サービスに渡す前に出力を検証してください。jsonschema (Python)、Ajv (JavaScript)、Everit (Java) などのライブラリを使用して、期待される JSON スキーマに準拠していることを確認し、フィールドの欠落、型の誤り、または不正なフォーマットによる後続の解析失敗、データ損失、またはビジネスロジックの混乱を防ぎます。失敗した場合は、リクエストをリトライするか、モデルを使用して出力を書き換えます。
-
max_tokens を設定しない
構造化出力が有効になっている場合、
max_tokensを設定しないでください。このパラメーターは出力トークンの数を制限し、デフォルトではモデルの最大値に設定されています。これを設定すると、JSON 文字列が出力の途中で切り捨てられ、解析に失敗する無効な JSON が生成される可能性があります。 -
SDK を使用してスキーマを生成する
SDK を使用してスキーマを自動生成します。これにより、手動でのメンテナンスによるエラーを回避し、自動的な検証と解析を提供します。
from pydantic import BaseModel, Field from typing import Optional from openai import OpenAI import os client = OpenAI( api_key=os.getenv("DASHSCOPE_API_KEY"), # 次の URL はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。 base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1" ) class UserInfo(BaseModel): name: str = Field(description="ユーザー名") age: int = Field(description="ユーザーの年齢") email: Optional[str] = None # オプションのフィールド completion = client.chat.completions.parse( model="qwen3.8-max", messages=[ {"role": "system", "content": "名前と年齢の情報を抽出します。"}, {"role": "user", "content": "私の名前は鈴木五郎、25 歳です。"}, ], response_format=UserInfo # Pydantic モデルを直接渡す ) result = completion.choices[0].message.parsed # 型安全な解析済み結果 print(f"名前: {result.name}, 年齢: {result.age}")import { z } from "zod"; import { zodResponseFormat } from "openai/helpers/zod"; import OpenAI from "openai"; const client = new OpenAI( { apiKey: process.env.DASHSCOPE_API_KEY, // 次の URL はシンガポールリージョン用です。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。 baseURL: "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1" } ); const UserInfo = z.object({ name: z.string().describe("ユーザー名"), age: z.number().int().describe("ユーザーの年齢"), email: z.string().optional().nullable() // オプションのフィールド }); const completion = await client.chat.completions.parse({ model: "qwen3.8-max", messages: [ { role: "system", content: "名前と年齢の情報を抽出します。" }, { role: "user", content: "私の名前は鈴木五郎、25 歳です。" }, ], response_format: zodResponseFormat(UserInfo, "user_info") }); console.log(completion.choices[0].message.parsed);
よくある質問
Q:Qwen の思考モデルはどのようにして構造化出力を生成しますか?
「ノンシンキングモード」とラベル付けされたモデルは、思考モードでは厳密に有効な JSON 文字列ではないコンテンツを返します。これを修正するには、次の 2 段階のアプローチを使用できます:まず、思考モデルを呼び出して高品質の出力を取得し、次に、不正な形式の JSON を JSON モードをサポートするモデルに渡して修正します。
-
思考モデルから出力を取得する
思考モデルを呼び出します。結果は有効な JSON ではない可能性があります。
注意:思考モードが有効な場合に
response_formatパラメーターを{"type": "json_object"}に設定してもエラーは発生しません。以下は、意図的にresponse_formatを省略したフォールバックの例です。モデルの出力が有効な JSON でない場合にのみ使用してください。
completion = client.chat.completions.create(
model="qwen3.8-max",
messages=[
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": "皆さん、こんにちは。私の名前は田中一郎です。34 歳で、メールアドレスは alexbrown@example.com です。バスケットボールと旅行が好きです",
},
],
# 思考モードを有効にする。このフォールバック例では response_format パラメーターを省略しています (直接設定してもエラーは発生しません)
extra_body={"enable_thinking": True},
# 思考モードではストリーミング出力が必要です
stream=True
)
# モデルが生成した JSON 結果を抽出して出力
json_string = ""
for chunk in completion:
if not chunk.choices:
continue
if chunk.choices[0].delta.content is not None:
json_string += chunk.choices[0].delta.content
-
出力を検証して修正する
前のステップの
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://{WorkspaceId}.cn-beijing.maas.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="qwen3.8-max",
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)
エラーコード
モデルの呼び出しが失敗し、エラーメッセージが返された場合は、「エラーコード」で解決策をご参照ください。