全部產品
Search
文件中心

Alibaba Cloud Model Studio:結構化輸出

更新時間:Dec 20, 2025

執行資訊抽取或結構化資料產生任務時,大模型可能返回多餘文本(如 ```json)導致下遊解析失敗。開啟結構化輸出可確保大模型輸出標準格式的 JSON 字串,使用 JSON Schema 模式還能精確控制輸出結構和類型,無需額外驗證或重試。

使用方式

結構化輸出支援JSON Object 與 JSON Schema兩種模式:

  • JSON Object 模式:確保輸出為標準格式的 JSON 字串,但不保證符合特定結構。使用方式:

    1. 設定response_format參數:在請求體中,將 response_format 參數設定為 {"type": "json_object"}

    2. 提示詞包含 JSON 關鍵詞:System Message 或 User Message 中需要包含 "JSON" 關鍵詞(不區分大小寫),否則會報錯:'messages' must contain the word 'json' in some form, to use 'response_format' of type 'json_object'.

  • JSON Schema 模式:確保輸出內容為指定的結構。使用方式:設定 response_format{"type": "json_schema", "json_schema": {...}, "strict": true}

    提示詞無需包含 JSON 關鍵詞。

功能對比:

特性

JSON Object 模式

JSON Schema 模式

輸出有效 JSON

嚴格遵循 Schema

支援模型

Qwen 大部分模型

僅支援 qwen-plus 系列部分模型

response_format 參數設定

{"type": "json_object"}

{"type": "json_schema", "json_schema": {...}, "strict": true}

提示詞要求

必須包含 "JSON"

建議明確說明

適用情境

靈活的 JSON 輸出

精確的結構驗證

支援的模型

JSON Object

  • 文本產生模型

    • 通義千問Max 系列:qwen3-max、qwen3-max-2025-09-23、qwen3-max-preview(非思考模式)qwen-max、qwen-max-latest、qwen-max-2025-01-25 及之後的快照模型

    • 通義千問Plus 系列(非思考模式):qwen-plus、qwen-plus-latest、qwen-plus-2025-01-25及之後的快照模型

    • 通義千問Flash 系列(非思考模式):qwen-flash、qwen-flash-2025-07-28及之後的快照模型

    • 通義千問Turbo 系列(非思考模式):qwen-turbo、qwen-turbo-latest、qwen-turbo-2024-11-01及之後的快照模型

    • 通義千問Coder 系列:qwen3-coder-plus、qwen3-coder-plus-2025-07-22、qwen3-coder-flash、qwen3-coder-flash-2025-07-28

    • 通義千問Long 系列:qwen-long-latest、qwen-long-2025-01-25

  • 文本產生開源模型

    • Qwen3(非思考模式)

    • Qwen3-Coder

    • Qwen2.5 系列的文本模型(不含math與coder模型)

  • 多模態模型

    • 通義千問3-VL-Plus 系列(非思考模式):qwen3-vl-plus、qwen3-vl-plus-2025-09-23及之後的快照模型

    • 通義千問3-VL-Flash 系列(非思考模式):qwen3-vl-flash、qwen3-vl-flash-2025-10-15及之後的快照模型

    • 通義千問VL-Max 系列:qwen-vl-max(不包括最新版與快照版模型)

    • 通義千問VL-Plus 系列:qwen-vl-plus(不包括最新版與快照版模型)

  • 多模態開源模型

    • Qwen3-VL(非思考模式)

說明

思考模式的模型暫不支援結構化輸出功能。

JSON Schema

北京地區的 qwen-plus、qwen-plus-latest、qwen-plus-2025-07-28 及之後更新的快照模型。

更多模型逐步支援中。

模型的上下文、價格、快照版本等資訊請參見模型列表

快速開始

以從簡歷中抽取資訊的簡單情境為例,介紹快速使用結構化輸出的方法。

您需要已擷取與配置 API Key配置API Key到環境變數(準備下線,併入配置 API Key)。如果通過OpenAI SDK或DashScope SDK進行調用,還需要安裝SDK

OpenAI相容

Python

from openai import OpenAI
import os

client = OpenAI(
    # 新加坡和北京地區的API Key不同;如果沒有配置環境變數,請用API Key將下行替換為:api_key="sk-xxx"
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 以下為新加坡地區base_url,北京地區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歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊", 
        },
    ],
    response_format={"type": "json_object"}
)

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

返回結果

{
  "姓名": "劉五",
  "年齡": 34
}

Node.js

import OpenAI from "openai";

const openai = new OpenAI({
    // 如果沒有配置環境變數,請用API Key將下行替換為:apiKey: "sk-xxx"
    apiKey: process.env.DASHSCOPE_API_KEY,
    // 以下為新加坡地區baseURL,使用北京地區的模型請將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歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊"
        }
    ],
    response_format: {
        type: "json_object"
    }
});

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

返回結果

{
  "姓名": "劉五",
  "年齡": 34
}

curl

# ======= 重要提示 =======
# 新加坡和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# 以下為新加坡地區url,若使用北京地區的模型,需將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": "你需要提取出name(名字,為string類型)、age(年齡,為string類型)與email(郵箱,為string類型),請輸出JSON 字串,不要輸出其它無關內容。\n樣本:\nQ:我叫張三,今年25歲,郵箱是zhangsan@example.com\nA:{\"name\":\"張三\",\"age\":\"25歲\",\"email\":\"zhangsan@example.com\"}\nQ:我叫李四,今年30歲,我的郵箱是lisi@example.com\nA:{\"name\":\"李四\",\"age\":\"30歲\",\"email\":\"lisi@example.com\"}\nQ:我叫王五,我的郵箱是wangwu@example.com,今年40歲\nA:{\"name\":\"王五\",\"age\":\"40歲\",\"email\":\"wangwu@example.com\"}"
        },
        {
            "role": "user", 
            "content": "大家好,我叫劉五,今年34歲,郵箱是liuwu@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": "qwen-plus",
    "id": "chatcmpl-624b665b-fb93-99e7-9ebd-bb6d86d314d2"
}

DashScope

Python

import os
import dashscope
# 以下為新加坡地區url,若使用北京地區的模型,需將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歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊", 
    },
]
response = dashscope.Generation.call(
    # 如果使用華北2(北京)地區的模型,需要使用華北2(北京)地區的 API Key,擷取連結:https://bailian.console.alibabacloud.com/?tab=model#/api-key
    # 若沒有配置環境變數,請用阿里雲百鍊API Key將下行替換為:api_key="sk-xxx",
    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)

返回結果

{
  "姓名": "劉五",
  "年齡": 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,若使用北京地區的模型,需將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歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊")
                .build();
        ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
        GenerationParam param = GenerationParam.builder()
                // 若沒有配置環境變數,請用阿里雲百鍊API Key將下行替換為:.apiKey("sk-xxx")
                .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("An error occurred while calling the generation service: " + e.getMessage());
        }
    }
}

返回結果

{
  "姓名": "劉五",
  "年齡": 34
}

curl

# ======= 重要提示 =======
# 新加坡和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# 以下為新加坡地區url,若使用北京地區的模型,需將url替換為:https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation
# === 執行時請刪除該注釋 ===

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歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊"
            }
        ]
    },
    "parameters": {
        "result_format": "message",
        "response_format": {
            "type": "json_object"
        }
    }
}'

返回結果

{
    "output": {
        "choices": [
            {
                "finish_reason": "stop",
                "message": {
                    "role": "assistant",
                    "content": "{\n  \"姓名\": \"劉五\",\n  \"年齡\": 34\n}"
                }
            }
        ]
    },
    "usage": {
        "total_tokens": 72,
        "output_tokens": 18,
        "input_tokens": 54,
        "cached_tokens": 0
    },
    "request_id": "xxx-xxx-xxx-xxx-xxx"
}

圖片、視頻資料處理

除了文本資訊,多模態模型還支援針對映像、視頻資料進行結構化輸出,實現視覺資訊抽取、定位、事件監測等功能。

圖片、視頻檔案限制請參見視覺理解

OpenAI相容

Python

import os
from openai import OpenAI

client = OpenAI(
    # 新加坡和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 以下為新加坡地區base_url,若使用北京地區的模型,需將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": "You are a helpful assistant."}],
        },
        {
            "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": "提取圖中ticket(數群組類型,包括 travel_date、trains、seat_num、arrival_site、price)和 invoice 的資訊(數群組類型,包括 invoice_code 和 invoice_number ),請輸出包含 ticket 和 invoice 數組的JSON"},
            ],
        },
    ],
    response_format={"type": "json_object"}
)
json_string = completion.choices[0].message.content
print(json_string)

返回結果

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "流水",
      "seat_num": "371",
      "arrival_site": "開發區",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

Node.js

import OpenAI from "openai";

const openai = new OpenAI({
  // 新加坡和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
  // 若沒有配置環境變數,請用百鍊API Key將下行替換為:apiKey: "sk-xxx"
  apiKey: process.env.DASHSCOPE_API_KEY,
  // 以下為新加坡地區base_url,若使用北京地區的模型,需將base_url替換為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: "You are a helpful assistant."
        }]
      },
      {
        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: "提取圖中ticket(數群組類型,包括 travel_date、trains、seat_num、arrival_site、price)和 invoice 的資訊(數群組類型,包括 invoice_code 和 invoice_number ),請輸出包含 ticket 和 invoice 數組的JSON"
          }
        ]
      }
    ],
    response_format: {type: "json_object"}
  });
  console.log(response.choices[0].message.content);
}

main()

返回結果

{
  "ticket": [
    {
      "travel_date": "2013-06-29",
      "trains": "流水",
      "seat_num": "371",
      "arrival_site": "開發區",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

curl

# ======= 重要提示 =======
# 以下為新加坡地區base_url,若使用北京地區的模型,需將base_url替換為:https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
# 新加坡和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/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": "You are a helpful assistant."}]},
  {
    "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": "提取圖中ticket(數群組類型,包括 travel_date、trains、seat_num、arrival_site、price)和 invoice 的資訊(數群組類型,包括 invoice_code 和 invoice_number ),請輸出包含 ticket 和 invoice 數組的JSON"}
    ]
  }],
  "response_format":{"type": "json_object"}
}'

返回結果

{
  "choices": [{
    "message": {
      "content": "{\n  \"ticket\": [\n    {\n      \"travel_date\": \"2013-06-29\",\n      \"trains\": \"流水\",\n      \"seat_num\": \"371\",\n      \"arrival_site\": \"開發區\",\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",
    "index": 0,
    "logprobs": null
  }],
  "object": "chat.completion",
  "usage": {
    "prompt_tokens": 486,
    "completion_tokens": 112,
    "total_tokens": 598,
    "prompt_tokens_details": {
      "cached_tokens": 0
    }
  },
  "created": 1755767481,
  "system_fingerprint": null,
  "model": "qwen3-vl-plus",
  "id": "chatcmpl-33249829-e9f3-9cbc-93e4-0536b3d7d713"
}

DashScope

Python

import os
import dashscope

# 以下為新加坡地區base_url,若使用北京地區的模型,需將base_url替換為:https://dashscope.aliyuncs.com/api/v1
dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

messages = [
{
    "role": "system",
    "content": [
    {"text": "You are a helpful assistant."}]
},
{
    "role": "user",
    "content": [
    {"image": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"},
    {"text": "提取圖中ticket(數群組類型,包括 travel_date、trains、seat_num、arrival_site、price)和 invoice 的資訊(數群組類型,包括 invoice_code 和 invoice_number ),請輸出包含 ticket 和 invoice 數組的JSON"}]
}]
response = dashscope.MultiModalConversation.call(
    #若沒有配置環境變數, 請用百鍊API Key將下行替換為: api_key ="sk-xxx"
    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": "流水",
      "seat_num": "371",
      "arrival_site": "開發區",
      "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 {
    
    // 以下為新加坡地區base_url,若使用北京地區的模型,需將base_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", "You are a helpful assistant."))).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", "提取圖中ticket(數群組類型,包括 travel_date、trains、seat_num、arrival_site、price)和 invoice 的資訊(數群組類型,包括 invoice_code 和 invoice_number ),請輸出包含 ticket 和 invoice 數組的JSON"))).build();
        ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
        MultiModalConversationParam param = MultiModalConversationParam.builder()
                // 若沒有配置環境變數,請用百鍊API Key將下行替換為:.apiKey("sk-xxx")
                .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": "流水",
      "seat_num": "371",
      "arrival_site": "開發區",
      "price": "8.00"
    }
  ],
  "invoice": [
    {
      "invoice_code": "221021325353",
      "invoice_number": "10283819"
    }
  ]
}

curl

# ======= 重要提示 =======
# 以下為新加坡地區base_url,若使用北京地區的模型,需將base_url替換為:https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation
# 新加坡和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/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": "You are a helpful assistant."
                    }
                ]
            },
            {
                "role": "user",
                "content": [
                    {
                        "image": "http://duguang-labelling.oss-cn-shanghai.aliyuncs.com/demo_ocr/receipt_zh_demo.jpg"
                    },
                    {
                        "text": "提取圖中ticket(數群組類型,包括 travel_date、trains、seat_num、arrival_site、price)和 invoice 的資訊(數群組類型,包括 invoice_code 和 invoice_number ),請輸出包含 ticket 和 invoice 數組的JSON"
                    }
                ]
            }
        ]
    },
    "parameters": {
        "response_format": {
            "type": "json_object"
        }
    }
}'

返回結果

{
  "output": {
    "choices": [
      {
        "message": {
          "content": [
            {
              "text": "{\n  \"ticket\": [\n    {\n      \"travel_date\": \"2013-06-29\",\n      \"trains\": \"流水\",\n      \"seat_num\": \"371\",\n      \"arrival_site\": \"開發區\",\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"
}

最佳化提示詞

模糊的提示詞(如“返回使用者資訊”)會使模型產生非預期結果。建議在提示詞中準確描述預期 Schema,包括欄位類型、必需性、格式要求(如日期格式),並提供樣本。

OpenAI相容

Python

from openai import OpenAI
import os
import json
import textwrap  # 用於處理多行字串的縮排,提高代碼可讀性

# 預定義樣本響應,用於向模型展示期望的輸出格式
# 樣本1:包含所有欄位的完整響應
example1_response = json.dumps(
    {
        "info": {"name": "張三", "age": "25歲", "email": "zhangsan@example.com"},
        "hobby": ["唱歌"]
    },
    ensure_ascii=False
)
# 樣本2:包含多個hobby的響應
example2_response = json.dumps(
    {
        "info": {"name": "李四", "age": "30歲", "email": "lisi@example.com"},
        "hobby": ["跳舞", "遊泳"]
    },
    ensure_ascii=False
)
# 樣本3:不包含hobby欄位的響應(hobby非必需)
example3_response = json.dumps(
    {
        "info": {"name": "趙六", "age": "28歲", "email": "zhaoliu@example.com"}
    },
    ensure_ascii=False
)
# 樣本4:不包含hobby欄位的響應
example4_response = json.dumps(
    {
        "info": {"name": "孫七", "age": "35歲", "email": "sunqi@example.com"}
    },
    ensure_ascii=False
)

# 初始化OpenAI用戶端,配置API密鑰和基礎URL
client = OpenAI(
    # 新加坡和北京地區的API Key不同。擷取API Key:https://www.alibabacloud.com/help/zh/model-studio/get-api-key
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 以下為新加坡地區url,若使用北京地區的模型,需將url替換為:https://dashscope.aliyuncs.com/compatible-mode/v1
    base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
)

# dedent的作用是去除每行開頭的公用縮排,使字串在代碼中可以美觀地縮排,但在運行時不會包含這些額外的空格
system_prompt = textwrap.dedent(f"""\
    請從使用者輸入中提取個人資訊並按照指定的JSON Schema格式輸出:

    【輸出格式要求】
    輸出必須嚴格遵循以下JSON結構:
    {{
      "info": {{
        "name": "字串類型,必需欄位,使用者姓名",
        "age": "字串類型,必需欄位,格式為'數字+歲',例如'25歲'",
        "email": "字串類型,必需欄位,標準郵箱格式,例如'user@example.com'"
      }},
      "hobby": ["字串數群組類型,非必需欄位,包含使用者的所有愛好,如未提及則完全不輸出此欄位"]
    }}

    【欄位擷取規則】
    1. name: 從文本中識別使用者姓名,必需提取
    2. age: 識別年齡資訊,轉換為"數字+歲"格式,必需提取
    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",  # 指定使用qwen-plus模型
    messages=[
        {
            "role": "system",
            "content": system_prompt  # 使用最佳化後的system prompt
        },
        {
            "role": "user",
            "content": "大家好,我叫劉五,今年34歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊", 
        },
    ],
    response_format={"type": "json_object"},  # 指定返回JSON格式,確保輸出結構化資料
)

# 提取並列印模型產生的JSON結果
json_string = completion.choices[0].message.content
print(json_string)

返回結果

{
  "info": {
    "name": "劉五",
    "age": "34歲",
    "email": "liuwu@example.com"
  },
  "hobby": ["打籃球", "旅遊"]  
}

Node.js

import OpenAI from "openai";

// 預定義樣本響應(用於向模型展示期望的輸出格式)
// 樣本1:包含所有欄位的完整響應
const example1Response = JSON.stringify({
    info: { name: "張三", age: "25歲", email: "zhangsan@example.com" },
    hobby: ["唱歌"]
}, null, 2);

// 樣本2:包含多個hobby的響應
const example2Response = JSON.stringify({
    info: { name: "李四", age: "30歲", email: "lisi@example.com" },
    hobby: ["跳舞", "遊泳"]
}, null, 2);

// 樣本3:不包含hobby欄位的響應(hobby非必需)
const example3Response = JSON.stringify({
    info: { name: "趙六", age: "28歲", email: "zhaoliu@example.com" }
}, null, 2);

// 樣本4:另一個不包含hobby欄位的響應
const example4Response = JSON.stringify({
    info: { name: "孫七", age: "35歲", email: "sunqi@example.com" }
}, null, 2);

// 初始化OpenAI用戶端配置
const openai = new OpenAI({
    // 新加坡地區與北京地區的API Key不同
    // 若沒有配置環境變數,請用阿里雲百鍊API Key將下行替換為:apiKey: "sk-xxx",
    apiKey: process.env.DASHSCOPE_API_KEY,
    // 以下為新加坡地區url,若使用北京地區的模型,需將url替換為: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-plus",
    messages: [
        {
            role: "system",
            content: `請從使用者輸入中提取個人資訊並按照指定的JSON Schema格式輸出:

【輸出格式要求】
輸出必須嚴格遵循以下JSON結構:
{
  "info": {
    "name": "字串類型,必需欄位,使用者姓名",
    "age": "字串類型,必需欄位,格式為'數字+歲',例如'25歲'",
    "email": "字串類型,必需欄位,標準郵箱格式,例如'user@example.com'"
  },
  "hobby": ["字串數群組類型,非必需欄位,包含使用者的所有愛好,如未提及則完全不輸出此欄位"]
}

【欄位擷取規則】
1. name: 從文本中識別使用者姓名,必需提取
2. age: 識別年齡資訊,轉換為"數字+歲"格式,必需提取
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歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊"
        }
    ],
    response_format: {
        type: "json_object"
    }
});

// 提取並列印模型產生的JSON結果
const jsonString = completion.choices[0].message.content;
console.log(jsonString);

返回結果

{
  "info": {
    "name": "劉五",
    "age": "34歲",
    "email": "liuwu@example.com"
  },
  "hobby": [
    "打籃球",
    "旅遊"
  ]
}

DashScope

Python

import os
import json
import dashscope
# 以下為新加坡地區url,若使用北京地區的模型,需將url替換為:https://dashscope.aliyuncs.com/api/v1
dashscope.base_http_api_url = 'https://dashscope-intl.aliyuncs.com/api/v1'

# 預定義樣本響應(用於向模型展示期望的輸出格式)
example1_response = json.dumps(
    {
        "info": {"name": "張三", "age": "25歲", "email": "zhangsan@example.com"},
        "hobby": ["唱歌"]
    },
    ensure_ascii=False
)
example2_response = json.dumps(
    {
        "info": {"name": "李四", "age": "30歲", "email": "lisi@example.com"},
        "hobby": ["跳舞", "遊泳"]
    },
    ensure_ascii=False
)
example3_response = json.dumps(
    {
        "info": {"name": "王五", "age": "40歲", "email": "wangwu@example.com"},
        "hobby": ["Rap", "籃球"]
    },
    ensure_ascii=False
)

messages=[
        {
            "role": "system",
            "content": f"""請從使用者輸入中提取個人資訊並按照指定的JSON Schema格式輸出:

【輸出格式要求】
輸出必須嚴格遵循以下JSON結構:
{{
  "info": {{
    "name": "字串類型,必需欄位,使用者姓名",
    "age": "字串類型,必需欄位,格式為'數字+歲',例如'25歲'",
    "email": "字串類型,必需欄位,標準郵箱格式,例如'user@example.com'"
  }},
  "hobby": ["字串數群組類型,非必需欄位,包含使用者的所有愛好,如未提及則完全不輸出此欄位"]
}}

【欄位擷取規則】
1. name: 從文本中識別使用者姓名,必需提取
2. age: 識別年齡資訊,轉換為"數字+歲"格式,必需提取
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歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊", 
        },
    ]
response = dashscope.Generation.call(
    # 如果使用華北2(北京)地區的模型,需要使用華北2(北京)地區的 API Key,擷取連結:https://bailian.console.alibabacloud.com/?tab=model#/api-key
    # 若沒有配置環境變數,請用阿里雲百鍊API Key將下行替換為:api_key="sk-xxx",
    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": "劉五",
    "age": "34歲",
    "email": "liuwu@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,若使用北京地區的模型,需將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": "字串類型,必需欄位,格式為'數字+歲',例如'25歲'",
    "email": "字串類型,必需欄位,標準郵箱格式,例如'user@example.com'"
  },
  "hobby": ["字串數群組類型,非必需欄位,包含使用者的所有愛好,如未提及則完全不輸出此欄位"]
}

【欄位擷取規則】
1. name: 從文本中識別使用者姓名,必需提取
2. age: 識別年齡資訊,轉換為"數字+歲"格式,必需提取
3. email: 識別郵箱地址,保持原始格式,必需提取
4. hobby: 識別使用者愛好,以字串數組形式輸出,如未提及愛好資訊則完全省略hobby欄位

【參考樣本】
樣本1(包含愛好):
Q:我叫張三,今年25歲,郵箱是zhangsan@example.com,愛好是唱歌
A:{"info":{"name":"張三","age":"25歲","email":"zhangsan@example.com"},"hobby":["唱歌"]}

樣本2(包含多個愛好):
Q:我叫李四,今年30歲,郵箱是lisi@example.com,平時喜歡跳舞和遊泳
A:{"info":{"name":"李四","age":"30歲","email":"lisi@example.com"},"hobby":["跳舞","遊泳"]}

樣本3(不包含愛好):
Q:我叫王五,我的郵箱是wangwu@example.com,今年40歲
A:{"info":{"name":"王五","age":"40歲","email":"wangwu@example.com"}}""")
                .build();
        Message userMsg = Message.builder()
                .role(Role.USER.getValue())
                .content("大家好,我叫劉五,今年34歲,郵箱是liuwu@example.com,平時喜歡打籃球和旅遊")
                .build();
        ResponseFormat jsonMode = ResponseFormat.builder().type("json_object").build();
        GenerationParam param = GenerationParam.builder()
                // 如果使用華北2(北京)地區的模型,需要使用華北2(北京)地區的 API Key,擷取連結:https://bailian.console.alibabacloud.com/?tab=model#/api-key
                // 若沒有配置環境變數,請用阿里雲百鍊API Key將下行替換為:.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("An error occurred while calling the generation service: " + e.getMessage());
        }
    }
}

返回結果

{
  "info": {
    "name": "劉五",
    "age": "34歲",
    "email": "liuwu@example.com"
  },
  "hobby": [
    "打籃球",
    "旅遊"
  ]
}

擷取指定格式的輸出

response_formattype設為json_object,可返回標準 JSON 字串,但內容結構可能不符合預期,適用於簡單情境。對於自動化解析、API 互操作等需要嚴格類型約束的複雜情境,可將 type 設定為 json_schema,強制大模型輸出嚴格符合指定格式的內容。response_format 格式與樣本如下:

格式

樣本

{
  "type": "json_schema",
  "json_schema": {
    "name": "schema_name",       // Schema 的名稱
    "strict": true,              // 推薦設定為 true,嚴格遵守格式
    "schema": {
      "type": "object",
      "properties": {...},       // 定義欄位結構,見右側具體樣本
      "required": [...],         // 必要欄位列表
      "additionalProperties": false  // 推薦設定為 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
    }
  }
}

上述樣本會強制模型輸出包含 name 和 age 兩個必要欄位,以及可選的 email 欄位的 JSON 對象。

僅支援北京地區的以下模型:qwen-plus-latestqwen-plus-2025-12-01qwen-plus-2025-09-11qwen-plus-2025-07-28
暫不支援新加坡地區模型。

使用方法

通過 OpenAI SDK 的 parse 方法,可直接傳入 Python Pydantic 類或 Node.js Zod 對象。SDK 會自動將其轉換為 JSON Schema,無需手動編寫複雜 JSON。DashScope SDK 需參考上文格式,手動構造 JSON Schema。

OpenAI 相容

from pydantic import BaseModel, Field
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

class UserInfo(BaseModel):
    name: str = Field(description="使用者的姓名")
    age: int = Field(description="使用者的年齡,單位為歲")

completion = client.chat.completions.parse(
    model="qwen-plus",
    messages=[
        {"role": "system", "content": "提取姓名與年齡資訊。"},
        {"role": "user", "content": "我叫劉五,今年25歲。"},
    ],
    response_format=UserInfo,
)

result = completion.choices[0].message.parsed
print(f"姓名:{result.name},年齡:{result.age}")
import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";

const openai = new OpenAI(
    {
        apiKey: process.env.DASHSCOPE_API_KEY,
        baseURL: "https://dashscope.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: "qwen-plus",
  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}`);

運行代碼可獲得以下輸出:

姓名:劉五,年齡:25

DashScope

暫不支援 Java SDK。
import os
import dashscope
import json

messages = [
    {
        "role": "user",
        "content": "我叫劉五,今年25歲。",
    },
]
response = dashscope.Generation.call(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    model="qwen-plus",
    messages=messages,
    result_format="message",
    response_format={
        "type": "json_schema",
        "json_schema": {
            "name": "user_info",
            "schema": {
                "properties": {
                    "name": {"title": "Name", "type": "string"},
                    "age": {"title": "Age", "type": "integer"},
                },
                "required": ["name", "age"],
                "title": "UserInfo",
                "type": "object",
            },
        },
        "strict": True,
    },
)
json_object = json.loads(response.output.choices[0].message.content)
print(f"姓名:{json_object['name']},年齡:{json_object['age']}")

運行代碼可獲得以下輸出:

姓名:劉五,年齡:25

配置指南

使用 JSON Schema 時,遵循以下規範可獲得更可靠的結構化輸出:

  • 必要欄位聲明

    推薦將必要欄位列在 required數組中。可選欄位可不列入,例如:

    {
      "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"},
        "email": {"type": "string"}
      },
      "required": ["name", "age"]
    }

    若輸入未提供 email 資訊,輸出中將不包含此欄位。

  • 可選欄位的實現方式

    除不列入 required 外,也可通過允許 null 類型實現:

    {
      "properties": {
        "name": {"type": "string"},
        "email": {"type": ["string", "null"]}  // 可以是字串或 null
      },
      "required": ["name", "email"]  // 兩個都在 required 中
    }

    輸出將始終包含 email 欄位,但其值可能為 null

  • additionalProperties 配置

    控制是否允許輸出未在 schema 中定義的額外欄位:

    {
      "properties": {"name": {"type": "string"}},
      "required": ["name"],
      "additionalProperties": true  // 允許額外欄位
    }

    樣本輸入:"我叫張三,25歲";輸出:{"name": "張三", "age": 25}(包含未定義的 age 欄位)。

    行為

    適用情境

    false

    只輸出定義的欄位

    需要精確控制結構

    true

    允許額外欄位

    需要捕獲更多資訊

  • 支援的資料類型:string、number、integer、boolean、object、array、enum。

應用於生產環境

  • 有效性校正

    若使用 JSON Object 模式,將輸出傳遞給下遊業務前,建議使用工具對其進行有效性校正,如 jsonschema (Python)、Ajv (JavaScript)、Everit (Java)等確保其符合指定的 JSON Schema 要求,避免因欄位缺失、類型錯誤或格式不規範導致下遊系統解析失敗、資料丟失或商務邏輯中斷。失敗時可通過重試、大模型改寫等策略進行修複。

  • 禁用 max_tokens

    請勿在開啟結構化輸出時指定 max_tokens(控制模型輸出 Token 數的參數,預設值為模型最大輸出 Token 數),否則返回的 JSON 字串可能不完整,導致下遊業務解析失敗。

  • 使用 SDK 輔助產生 Schema

    推薦使用 SDK 自動產生 Schema,避免手動維護導致的錯誤,並可以自動驗證和解析。

    from pydantic import BaseModel, Field
    from typing import Optional
    from openai import OpenAI
    import os
    
    client = OpenAI(
        api_key=os.getenv("DASHSCOPE_API_KEY"),
        base_url="https://dashscope.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="qwen-plus",
        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,
            baseURL: "https://dashscope.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: "qwen-plus",
      messages: [
        { role: "system", content: "提取姓名與年齡資訊。" },
        { role: "user", content: "我叫劉五,今年25歲。" },
      ],
      response_format: zodResponseFormat(UserInfo, "user_info")
    });
    
    console.log(completion.choices[0].message.parsed);

常見問題

Q:Qwen 的思考模式模型如何結構化輸出?

A:Qwen 的思考模式模型暫不支援結構化輸出。如需在思考模式下擷取標準 JSON 字串,可在 JSON 解析失敗時引入支援 JSON Mode 的模型進行修複。

  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歲,郵箱是liuwu@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)

錯誤碼

如果模型調用失敗並返回報錯資訊,請參見錯誤資訊進行解決。