リアルタイムチャットや長文生成アプリケーションでは、長い待ち時間がユーザーエクスペリエンスを低下させ、サーバー側のタイムアウトを引き起こしてタスクが失敗する可能性があります。ストリーミング出力は、モデルがテキストを生成する際に断片を継続的に返すことで、これらの問題に対処します。
仕組み
ストリーミング出力は、Server-Sent Events (SSE) プロトコルを使用します。ストリーミングリクエストが開始されると、サーバーはクライアントとの HTTP 持続的接続を確立します。モデルがテキストブロック(チャンクと呼ばれます)を生成するたびに、そのチャンクをこの接続を通じて即座にプッシュします。すべてのコンテンツが生成されると、サーバーは終了シグナルを送信します。
クライアントはイベントストリームをリッスンし、テキストチャンクをリアルタイムで受信・処理します。たとえば、インターフェイス上で文字を 1 文字ずつレンダリングします。これは、すべてのコンテンツを一度に返す非ストリーミング呼び出しとは対照的です。
上記コンポーネントは参考用であり、実際のリクエストは送信されません。
課金
ストリーミング出力は、非ストリーミング呼び出しと同じ課金ルールを使用し、リクエスト内の入力トークン数と出力トークン数に基づいて課金されます。
リクエストが中断された場合、出力トークンは、サーバーが終了リクエストを受信する前に生成された部分のみがカウントされます。
使用方法
Qwen3 オープンソース版、QwQ コマーシャルおよびオープンソース版、QVQ、および Qwen-Omni は、ストリーミング出力のみをサポートしています。
ステップ 1:API キーを構成し、リージョンを選択する
API キーを取得済みで、かつ環境変数として構成済みである必要があります。
コード内にハードコーディングするよりも、API キーを環境変数 (DASHSCOPE_API_KEY) として構成する方が安全です。
ステップ 2:ストリーミングリクエストを行う
OpenAI 互換
-
有効化方法
streamをtrueに設定します。 -
トークン使用量の確認
OpenAI プロトコルはデフォルトでトークン使用量を返しません。
stream_options={"include_usage": true}を設定すると、最後に返されるデータチャンクにトークン使用量情報が含まれます。
Python
import os
from openai import OpenAI
# 1. 準備:クライアントを初期化
client = OpenAI(
# ハードコーディングを避けるため、環境変数を使用して API キーを構成。
api_key=os.environ["DASHSCOPE_API_KEY"],
# API キーはリージョンに厳密にバインドされています。base_url が API キーのリージョンと一致することを確認してください。
# シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
# 2. ストリーミングリクエストを実行
completion = client.chat.completions.create(
model="qwen-plus",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Please introduce yourself"}
],
stream=True,
stream_options={"include_usage": True}
)
# 3. ストリーミングレスポンスを処理
# レスポンスフラグメントをリストに格納。繰り返し文字列連結を行うよりも、最後に結合する方が効率的です。
content_parts = []
print("AI: ", end="", flush=True)
for chunk in completion:
if chunk.choices:
content = chunk.choices[0].delta.content or ""
print(content, end="", flush=True)
content_parts.append(content)
elif chunk.usage:
print("\n--- Request usage ---")
print(f"Input Tokens: {chunk.usage.prompt_tokens}")
print(f"Output Tokens: {chunk.usage.completion_tokens}")
print(f"Total Tokens: {chunk.usage.total_tokens}")
full_response = "".join(content_parts)
# print(f"\n--- Full response ---\n{full_response}")
レスポンス
AI: Hello! I am Qwen, a large-scale language model independently developed by Tongyi Lab under Alibaba Group. I can answer questions, create content such as stories, official documents, emails, scripts, perform logical reasoning, programming, express opinions, play games, and more. I support multiple languages, including but not limited to Chinese, English, German, French, and Spanish. If you have any questions or need help, feel free to ask me anytime!
--- Request usage ---
Input Tokens: 26
Output Tokens: 87
Total Tokens: 113
Node.js
import OpenAI from "openai";
async function main() {
// 1. 準備:クライアントを初期化
// ハードコーディングを避けるため、環境変数を使用して API キーを構成。
if (!process.env.DASHSCOPE_API_KEY) {
throw new Error("Set the DASHSCOPE_API_KEY environment variable");
}
// API キーはリージョンに厳密にバインドされています。baseURL が API キーのリージョンと一致することを確認してください。
// シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
const client = new OpenAI({
apiKey: process.env.DASHSCOPE_API_KEY,
baseURL: "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
});
try {
// 2. ストリーミングリクエストを実行
const stream = await client.chat.completions.create({
model: "qwen-plus",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Please introduce yourself" },
],
stream: true,
// 目的:最後のチャンクでトークン使用量を取得。
stream_options: { include_usage: true },
});
// 3. ストリーミングレスポンスを処理
const contentParts = [];
process.stdout.write("AI: ");
for await (const chunk of stream) {
// 最後のチャンクには choices が含まれず、代わりに使用量情報が含まれます。
if (chunk.choices && chunk.choices.length > 0) {
const content = chunk.choices[0]?.delta?.content || "";
process.stdout.write(content);
contentParts.push(content);
} else if (chunk.usage) {
// リクエスト完了。トークン使用量を出力。
console.log("\n--- Request usage ---");
console.log(`Input Tokens: ${chunk.usage.prompt_tokens}`);
console.log(`Output Tokens: ${chunk.usage.completion_tokens}`);
console.log(`Total Tokens: ${chunk.usage.total_tokens}`);
}
}
const fullResponse = contentParts.join("");
// console.log(`\n--- Full response ---\n${fullResponse}`);
} catch (error) {
console.error("Request failed:", error);
}
}
main();
レスポンス
AI: Hello! I am Qwen, a large-scale language model independently developed by Tongyi Lab under Alibaba Group. I can answer questions, create content such as stories, official documents, emails, scripts, perform logical reasoning, programming, express opinions, play games, and more. I support multiple languages, including but not limited to Chinese, English, German, French, and Spanish. If you have any questions or need help, feel free to ask me anytime!
--- Request usage ---
Input Tokens: 26
Output Tokens: 89
Total Tokens: 115
curl
リクエスト
# ======= 重要事項 =======
# DASHSCOPE_API_KEY 環境変数が設定されていることを確認してください
# API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# === 実行前にこのコメントを削除してください ===
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" \
--no-buffer \
-d '{
"model": "qwen-plus",
"messages": [
{"role": "user", "content": "Who are you?"}
],
"stream": true,
"stream_options": {"include_usage": true}
}'
レスポンス
レスポンスは SSE プロトコルに従います。data: で始まる各行がデータチャンクを表します。
data: {"choices":[{"delta":{"content":"","role":"assistant"},"index":0,"logprobs":null,"finish_reason":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[{"finish_reason":null,"delta":{"content":"I am"},"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[{"delta":{"content":" from"},"finish_reason":null,"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[{"delta":{"content":" Alibaba"},"finish_reason":null,"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[{"delta":{"content":"'s large-scale language"},"finish_reason":null,"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[{"delta":{"content":" model, my name is Qwen"},"finish_reason":null,"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[{"delta":{"content":"."},"finish_reason":null,"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[{"finish_reason":"stop","delta":{"content":""},"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: {"choices":[],"object":"chat.completion.chunk","usage":{"prompt_tokens":22,"completion_tokens":17,"total_tokens":39},"created":1726132850,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-428b414f-fdd4-94c6-b179-8f576ad653a8"}
data: [DONE]
-
data::メッセージペイロード。通常は JSON 文字列です。 -
[DONE]:ストリーミングレスポンス全体の終了を示します。
DashScope
-
有効化方法
ストリーミング出力を有効にする方法は、SDK やツールによって異なります。
-
Python SDK:
streamパラメーターをTrueに設定します。 -
Java SDK:
streamCallインターフェイスを使用します。 -
cURL:ヘッダー
X-DashScope-SSEをenableに設定します。
-
-
増分出力の有効化
DashScope プロトコルは、増分および非増分のストリーミング出力の両方をサポートしています。
-
増分(推奨):各データチャンクには、新たに生成されたコンテンツのみが含まれます。
incremental_outputをtrueに設定して、増分ストリーミング出力を有効にします。例:["I love","eating","apples"]
-
非増分:各データチャンクには、これまでに生成されたすべてのコンテンツが含まれるため、ネットワーク帯域幅を無駄にし、クライアントの処理負荷が増加します。
incremental_outputをfalseに設定して、非増分ストリーミング出力を有効にします。例:["I love","I love eating","I love eating apples"]
-
-
トークン使用量の確認
各データチャンクには、リアルタイムのトークン使用量情報が含まれます。
Python
import os
from http import HTTPStatus
import dashscope
from dashscope import Generation
# 1. 準備:API キーとリージョンを構成
# ハードコーディングを避けるため、環境変数を使用して API キーを構成。
try:
dashscope.api_key = os.environ["DASHSCOPE_API_KEY"]
except KeyError:
raise ValueError("Set the DASHSCOPE_API_KEY environment variable")
# API キーはリージョンに厳密にバインドされています。base_url が API キーのリージョンと一致することを確認してください。
dashscope.base_http_api_url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1"
# 2. ストリーミングリクエストを実行
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Please introduce yourself"},
]
try:
responses = Generation.call(
model="qwen-plus",
messages=messages,
result_format="message",
stream=True,
# 重要:パフォーマンスを向上させるために、増分出力を True に設定。
incremental_output=True,
)
# 3. ストリーミングレスポンスを処理
content_parts = []
print("AI: ", end="", flush=True)
for resp in responses:
if resp.status_code == HTTPStatus.OK:
content = resp.output.choices[0].message.content
print(content, end="", flush=True)
content_parts.append(content)
# 最後のパケットかどうかを確認
if resp.output.choices[0].finish_reason == "stop":
usage = resp.usage
print("\n--- Request usage ---")
print(f"Input Tokens: {usage.input_tokens}")
print(f"Output Tokens: {usage.output_tokens}")
print(f"Total Tokens: {usage.total_tokens}")
else:
# エラーを処理
print(
f"\nRequest failed: request_id={resp.request_id}, code={resp.code}, message={resp.message}"
)
break
full_response = "".join(content_parts)
# print(f"\n--- Full response ---\n{full_response}")
except Exception as e:
print(f"An unknown error occurred: {e}")
レスポンス
AI: Hello! I am Qwen, a large-scale language model independently developed by Tongyi Lab under Alibaba Group. I can help you answer questions, create content such as stories, official documents, emails, scripts, perform logical reasoning, programming, express opinions, play games, and more. I support multiple languages, including but not limited to Chinese, English, German, French, and Spanish. If you have any questions or need help, feel free to ask me anytime!
--- Request usage ---
Input Tokens: 26
Output Tokens: 91
Total Tokens: 117
Java
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 io.reactivex.Flowable;
import io.reactivex.schedulers.Schedulers;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import com.alibaba.dashscope.protocol.Protocol;
public class Main {
public static void main(String[] args) {
// 1. API キーを取得
String apiKey = System.getenv("DASHSCOPE_API_KEY");
if (apiKey == null || apiKey.isEmpty()) {
System.err.println("Set the DASHSCOPE_API_KEY environment variable");
return;
}
// 2. Generation インスタンスを初期化
// API キーはリージョンに厳密にバインドされています。baseUrl が API キーのリージョンと一致することを確認してください。
Generation gen = new Generation(Protocol.HTTP.getValue(), "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1");
CountDownLatch latch = new CountDownLatch(1);
// 3. リクエストパラメーターを構築
GenerationParam param = GenerationParam.builder()
.apiKey(apiKey)
.model("qwen-plus")
.messages(Arrays.asList(
Message.builder()
.role(Role.USER.getValue())
.content("Introduce yourself")
.build()
))
.resultFormat(GenerationParam.ResultFormat.MESSAGE)
.incrementalOutput(true) // ストリーミングの増分出力を有効化
.build();
// 4. ストリーミング呼び出しを実行し、レスポンスを処理
try {
Flowable<GenerationResult> result = gen.streamCall(param);
StringBuilder fullContent = new StringBuilder();
System.out.print("AI: ");
result
.subscribeOn(Schedulers.io()) // IO スレッドでリクエストを実行
.observeOn(Schedulers.computation()) // 計算スレッドでレスポンスを処理
.subscribe(
// onNext:各レスポンスフラグメントを処理
message -> {
String content = message.getOutput().getChoices().get(0).getMessage().getContent();
String finishReason = message.getOutput().getChoices().get(0).getFinishReason();
// コンテンツを出力
System.out.print(content);
fullContent.append(content);
// finishReason が null でない場合、最後のチャンクを示します。使用量情報を出力。
if (finishReason != null && !"null".equals(finishReason)) {
System.out.println("\n--- Request usage ---");
System.out.println("Input Tokens: " + message.getUsage().getInputTokens());
System.out.println("Output Tokens: " + message.getUsage().getOutputTokens());
System.out.println("Total Tokens: " + message.getUsage().getTotalTokens());
}
System.out.flush(); // 出力を即座にフラッシュ
},
// onError:エラーを処理
error -> {
System.err.println("\nRequest failed: " + error.getMessage());
latch.countDown();
},
// onComplete:完了コールバック
() -> {
System.out.println(); // 改行
// System.out.println("Full response: " + fullContent.toString());
latch.countDown();
}
);
// メインスレッドが非同期タスクの完了を待機
latch.await();
System.out.println("Program execution complete");
} catch (Exception e) {
System.err.println("Request exception: " + e.getMessage());
e.printStackTrace();
}
}
}
レスポンス
AI: Hello! I am Qwen, a large-scale language model independently developed by Tongyi Lab under Alibaba Group. I can help you answer questions, create content such as stories, official documents, emails, scripts, perform logical reasoning, programming, express opinions, play games, and more. I support multiple languages, including but not limited to Chinese, English, German, French, and Spanish. If you have any questions or need help, feel free to ask me anytime!
--- Request usage ---
Input Tokens: 26
Output Tokens: 91
Total Tokens: 117
curl
リクエスト
# ======= 重要事項 =======
# DASHSCOPE_API_KEY 環境変数が設定されていることを確認してください
# API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
# === 実行前にこのコメントを削除してください ===
curl -X POST https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/text-generation/generation \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-H "X-DashScope-SSE: enable" \
-d '{
"model": "qwen-plus",
"input":{
"messages":[
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Who are you?"
}
]
},
"parameters": {
"result_format": "message",
"incremental_output":true
}
}'
レスポンス
レスポンスは Server-Sent Events (SSE) 形式に従います。各メッセージには以下が含まれます。
-
id:データチャンク番号。
-
event:イベントタイプ。常に "result" です。
-
HTTP ステータスコード情報。
-
data:JSON 形式のデータ。
id:1
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"I am","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":27,"output_tokens":1,"input_tokens":26,"prompt_tokens_details":{"cached_tokens":0}},"request_id":"d30a9914-ac97-9102-b746-ce0cb35e3fa2"}
id:2
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"Qwen","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":30,"output_tokens":4,"input_tokens":26,"prompt_tokens_details":{"cached_tokens":0}},"request_id":"d30a9914-ac97-9102-b746-ce0cb35e3fa2"}
id:3
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":" from Alibaba","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":33,"output_tokens":7,"input_tokens":26,"prompt_tokens_details":{"cached_tokens":0}},"request_id":"d30a9914-ac97-9102-b746-ce0cb35e3fa2"}
...
id:13
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"or need help, feel free to","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":90,"output_tokens":64,"input_tokens":26,"prompt_tokens_details":{"cached_tokens":0}},"request_id":"d30a9914-ac97-9102-b746-ce0cb35e3fa2"}
id:14
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"ask me!","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":92,"output_tokens":66,"input_tokens":26,"prompt_tokens_details":{"cached_tokens":0}},"request_id":"d30a9914-ac97-9102-b746-ce0cb35e3fa2"}
id:15
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"","role":"assistant"},"finish_reason":"stop"}]},"usage":{"total_tokens":92,"output_tokens":66,"input_tokens":26,"prompt_tokens_details":{"cached_tokens":0}},"request_id":"d30a9914-ac97-9102-b746-ce0cb35e3fa2"}
マルチモーダルモデルのストリーミング出力
マルチモーダルモデルは、会話に画像や音声などのコンテンツを追加できます。そのストリーミング出力の実装は、テキスト専用モデルとは以下の点で異なります。
-
ユーザーのメッセージ構築:マルチモーダルモデルの入力には、テキストだけでなく、画像や音声などのマルチモーダル情報も含まれます。
-
DashScope SDK インターフェイス:DashScope Python SDK では MultiModalConversation インターフェイスを使用します。DashScope Java SDK では MultiModalConversation クラスを使用します。
マルチモーダルモデルについては、「画像および動画理解」、「テキスト抽出」、音声理解—Qwen3-Omni-Captioner」、「Kimi」などを参照してください。Qwen-Omni モデルは、出力にテキストまたは音声などのマルチモーダルコンテンツが含まれるため、ストリーミング出力のみをサポートしています。その結果の解析は他のモデルとは異なります。詳細については、「オムニモーダル」をご参照ください。
OpenAI 互換
Python
from openai import OpenAI
import os
client = OpenAI(
# API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# 環境変数を構成していない場合は、次の行を Model Studio API キーに置き換えてください: api_key="sk-xxx"
api_key=os.getenv("DASHSCOPE_API_KEY"),
# シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
completion = client.chat.completions.create(
model="qwen3-vl-plus", # 必要に応じて他のマルチモーダルモデルに置き換え、メッセージを調整してください
messages=[
{"role": "user",
"content": [{"type": "image_url",
"image_url": {"url": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"},},
{"type": "text", "text": "What scene is depicted in the image?"}]}],
stream=True,
# stream_options={"include_usage": True}
)
full_content = ""
print("Streaming output content:")
for chunk in completion:
# stream_options.include_usage が True の場合、最後のチャンクの choices フィールドは空のリストになるためスキップします(トークン使用量は chunk.usage から取得できます)
if chunk.choices and chunk.choices[0].delta.content != "":
full_content += chunk.choices[0].delta.content
print(chunk.choices[0].delta.content)
print(f"Full content: {full_content}")Node.js
import OpenAI from "openai";
const openai = new OpenAI(
{
// API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
// 環境変数を構成していない場合は、次の行を Model Studio API キーに置き換えてください: apiKey: "sk-xxx"
apiKey: process.env.DASHSCOPE_API_KEY,
// シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
baseURL: "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1"
}
);
const completion = await openai.chat.completions.create({
model: "qwen3-vl-plus", // 必要に応じて他のマルチモーダルモデルに置き換え、メッセージを調整してください
messages: [
{role: "user",
content: [{"type": "image_url",
"image_url": {"url": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"},},
{"type": "text", "text": "What scene is depicted in the image?"}]}],
stream: true,
// stream_options: { include_usage: true },
});
let fullContent = ""
console.log("Streaming output content:")
for await (const chunk of completion) {
// stream_options.include_usage が true の場合、最後のチャンクの choices フィールドは空の配列になるためスキップします(トークン使用量は chunk.usage から取得できます)
if (chunk.choices[0] && chunk.choices[0].delta.content != null) {
fullContent += chunk.choices[0].delta.content;
console.log(chunk.choices[0].delta.content);
}
}
console.log(`Full output content: ${fullContent}`)curl
# ======= 重要事項 =======
# シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
# API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/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": "user",
"content": [
{
"type": "image_url",
"image_url": {
"url": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"
}
},
{
"type": "text",
"text": "What scene is depicted in the image?"
}
]
}
],
"stream":true,
"stream_options":{"include_usage":true}
}'DashScope
Python
import os
from dashscope import MultiModalConversation
import dashscope
# シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
dashscope.base_http_api_url = 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1'
messages = [
{
"role": "user",
"content": [
{"image": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"},
{"text": "What scene is depicted in the image?"}
]
}
]
responses = MultiModalConversation.call(
# API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# 環境変数を構成していない場合は、次の行を Model Studio API キーに置き換えてください: api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"),
model='qwen3-vl-plus', # 必要に応じて他のマルチモーダルモデルに置き換え、メッセージを調整してください
messages=messages,
stream=True,
incremental_output=True)
full_content = ""
print("Streaming output content:")
for response in responses:
if response["output"]["choices"][0]["message"].content:
print(response.output.choices[0].message.content[0]['text'])
full_content += response.output.choices[0].message.content[0]['text']
print(f"Full content: {full_content}")Java
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
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 io.reactivex.Flowable;
import com.alibaba.dashscope.utils.Constants;
public class Main {
static {
// シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
Constants.baseHttpApiUrl="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1";
}
public static void streamCall()
throws ApiException, NoApiKeyException, UploadFileException {
MultiModalConversation conv = new MultiModalConversation();
// mutable map を作成する必要があります。
MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
.content(Arrays.asList(Collections.singletonMap("image", "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"),
Collections.singletonMap("text", "What scene is depicted in the image?"))).build();
MultiModalConversationParam param = MultiModalConversationParam.builder()
// API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
// 環境変数を構成していない場合は、次の行を Model Studio API キーに置き換えてください: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("qwen3-vl-plus") // 必要に応じて他のマルチモーダルモデルに置き換え、メッセージを調整してください
.messages(Arrays.asList(userMessage))
.incrementalOutput(true)
.build();
Flowable<MultiModalConversationResult> result = conv.streamCall(param);
result.blockingForEach(item -> {
try {
List<Map<String, Object>> content = item.getOutput().getChoices().get(0).getMessage().getContent();
// コンテンツが存在し、空でないことを確認
if (content != null && !content.isEmpty()) {
System.out.println(content.get(0).get("text"));
}
} catch (Exception e){
System.exit(0);
}
});
}
public static void main(String[] args) {
try {
streamCall();
} catch (ApiException | NoApiKeyException | UploadFileException e) {
System.out.println(e.getMessage());
}
System.exit(0);
}
}curl
# ======= 重要事項 =======
# API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
# === 実行前にこのコメントを削除してください ===
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' \
-H 'X-DashScope-SSE: enable' \
-d '{
"model": "qwen3-vl-plus",
"input":{
"messages":[
{
"role": "user",
"content": [
{"image": "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"},
{"text": "What scene is depicted in the image?"}
]
}
]
},
"parameters": {
"incremental_output": true
}
}'思考モデルのストリーミング出力
思考モデルは、まず reasoning_content(思考プロセス)を返し、次に content(応答)を返します。データパケットのステータスに基づいて、現在の段階が思考中か応答中かを判断します。
思考モデルの詳細については、「ディープシンキング」、「画像および動画理解」、「視覚的推論」をご参照ください。
Qwen3-Omni-Flash(思考モード)のストリーミング出力実装については、「オムニモーダル」をご参照ください。
OpenAI 互換
以下は、OpenAI Python SDK を使用して qwen-plus モデルの思考モードをストリーミングモードで呼び出した際のレスポンス形式です。
# 思考段階
...
ChoiceDelta(content=None, function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content='Cover all key points while')
ChoiceDelta(content=None, function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content='remaining natural and fluent.')
# 応答段階
ChoiceDelta(content='Hello! I am **Qwen', function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content=None)
ChoiceDelta(content='** (', function_call=None, refusal=None, role=None, tool_calls=None, reasoning_content=None)
...
-
reasoning_contentが None ではなく、contentがNoneの場合、現在の段階は思考中です。 -
reasoning_contentが None で、contentがNoneではない場合、現在の段階は応答中です。 -
両方が
Noneの場合、前のパケットと同じ段階にとどまります。
Python
サンプルコード
from openai import OpenAI
import os
# OpenAI クライアントを初期化
client = OpenAI(
# 環境変数を構成していない場合は、Alibaba Cloud Model Studio API キーに置き換えてください: api_key="sk-xxx"
api_key=os.getenv("DASHSCOPE_API_KEY"),
base_url="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1",
)
messages = [{"role": "user", "content": "Who are you"}]
completion = client.chat.completions.create(
model="qwen-plus", # 必要に応じて他のディープシンキングモデルに置き換えてください
messages=messages,
# enable_thinking パラメーターにより思考プロセスを有効化。qwen3-30b-a3b-thinking-2507、qwen3-235b-a22b-thinking-2507、QwQ モデルにはこのパラメーターは影響しません。
extra_body={"enable_thinking": True},
stream=True,
# stream_options={
# "include_usage": True
# },
)
reasoning_content = "" # 完全な思考プロセス
answer_content = "" # 完全な応答
is_answering = False # 応答段階にあるかどうか
print("\n" + "=" * 20 + "思考プロセス" + "=" * 20 + "\n")
for chunk in completion:
if not chunk.choices:
print("\nUsage:")
print(chunk.usage)
continue
delta = chunk.choices[0].delta
# 思考コンテンツのみを収集
if hasattr(delta, "reasoning_content") and delta.reasoning_content is not None:
if not is_answering:
print(delta.reasoning_content, end="", flush=True)
reasoning_content += delta.reasoning_content
# コンテンツを受信し、応答を開始
if hasattr(delta, "content") and delta.content:
if not is_answering:
print("\n" + "=" * 20 + "完全な応答" + "=" * 20 + "\n")
is_answering = True
print(delta.content, end="", flush=True)
answer_content += delta.content
レスポンス
====================思考プロセス====================
ユーザーが「あなたは誰ですか」と尋ねているので、正確でフレンドリな回答を提供する必要があります。まず、自分がアリババグループ傘下の通義実験室が開発した Qwen であることを明確にします。次に、質問への回答、テキスト作成、論理的推論などの主な機能を説明します。ユーザーが快適に感じられるよう、親しみやすいトーンを保ち、過度に専門的な用語を避けます。また、複雑な専門用語を避け、回答を簡潔にすることも重要です。さらに、追加の質問を促すインタラクティブな要素を含めます。最後に、「通義千問」という中国語名と「Qwen」という英語名、および所属企業と研究室といった重要な情報が欠けていないか確認し、ユーザーの期待に応える包括的な回答となるようにします。
====================完全な回答====================
こんにちは!私はアリババグループ傘下の通義実験室が独自に開発した大規模言語モデル Qwen です。質問への回答、テキスト作成、論理的推論、プログラミングなどを行うことができ、高品質な情報とサービスを提供することを目指しています。私を Qwen または単に通義千問と呼んでください。何かお手伝いできることはありますか?
Node.js
サンプルコード
import OpenAI from "openai";
import process from 'process';
// openai クライアントを初期化
const openai = new OpenAI({
apiKey: process.env.DASHSCOPE_API_KEY, // 環境変数から読み取り
baseURL: 'https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1'
});
let reasoningContent = '';
let answerContent = '';
let isAnswering = false;
async function main() {
try {
const messages = [{ role: 'user', content: 'Who are you' }];
const stream = await openai.chat.completions.create({
// 必要に応じて、他の Qwen3 モデルまたは QwQ モデルに置き換えてください
model: 'qwen-plus',
messages,
stream: true,
// enable_thinking パラメーターは思考プロセスを有効にします。このパラメーターは、qwen3-30b-a3b-thinking-2507、qwen3-235b-a22b-thinking-2507、および QwQ モデルには効果がありません。
enable_thinking: true
});
console.log('\n' + '='.repeat(20) + 'Thought process' + '='.repeat(20) + '\n');
for await (const chunk of stream) {
if (!chunk.choices?.length) {
console.log('\nUsage:');
console.log(chunk.usage);
continue;
}
const delta = chunk.choices[0].delta;
// 思考コンテンツのみを収集
if (delta.reasoning_content !== undefined && delta.reasoning_content !== null) {
if (!isAnswering) {
process.stdout.write(delta.reasoning_content);
}
reasoningContent += delta.reasoning_content;
}
// コンテンツを受信したため、応答を開始
if (delta.content !== undefined && delta.content) {
if (!isAnswering) {
console.log('\n' + '='.repeat(20) + 'Full response' + '='.repeat(20) + '\n');
isAnswering = true;
}
process.stdout.write(delta.content);
answerContent += delta.content;
}
}
} catch (error) {
console.error('Error:', error);
}
}
main();
レスポンス
====================思考プロセス====================
わかりました。ユーザーが「あなたは誰ですか」と尋ねているので、自分のアイデンティティを明確に述べる必要があります。まず、自分がAlibaba Cloudが開発した大規模言語モデルであるQwenであることを明確に言うべきです。次に、質問への回答、テキストの作成、論理的推論などの主な機能について言及します。また、中国語および英語を含む多言語対応を強調し、ユーザーが異なる言語でのリクエストに対応できることを伝えます。さらに、学習、仕事、日常生活における支援といったアプリケーションシナリオについても説明します。ただし、ユーザーの質問は直接的なものであるため、詳細な情報は不要かもしれません—簡潔にまとめましょう。また、フレンドリーなトーンを保ち、さらなる質問を歓迎するようにします。バージョン情報や最新のアップデートなどの重要な情報が不足していないか確認しますが、ユーザーはおそらくそれほど詳細を必要としないでしょう。最後に、応答が正確で誤りがないことを確認します。
====================完全な応答====================
私はアリババグループ傘下の通義実験室が独自に開発した大規模言語モデルであるQwenです。質問への回答、テキストの作成、論理的推論、プログラミングなど、さまざまなタスクを処理でき、中国語および英語を含む複数の言語をサポートしています。ご質問やお手伝いが必要な場合は、いつでも気軽にお知らせください!
HTTP
サンプルコード
curl
Qwen3 オープンソースモデルの場合、enable_thinking を true に設定して思考モードを有効にします。enable_thinking パラメーターは、qwen3-30b-a3b-thinking-2507、qwen3-235b-a22b-thinking-2507、QwQ モデルには影響しません。
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": "qwen-plus",
"messages": [
{
"role": "user",
"content": "Who are you"
}
],
"stream": true,
"stream_options": {
"include_usage": true
},
"enable_thinking": true
}'
レスポンス
data: {"choices":[{"delta":{"content":null,"role":"assistant","reasoning_content":""},"index":0,"logprobs":null,"finish_reason":null}],"object":"chat.completion.chunk","usage":null,"created":1745485391,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-e2edaf2c-8aaf-9e54-90e2-b21dd5045503"}
.....
data: {"choices":[{"finish_reason":"stop","delta":{"content":"","reasoning_content":null},"index":0,"logprobs":null}],"object":"chat.completion.chunk","usage":null,"created":1745485391,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-e2edaf2c-8aaf-9e54-90e2-b21dd5045503"}
data: {"choices":[],"object":"chat.completion.chunk","usage":{"prompt_tokens":10,"completion_tokens":360,"total_tokens":370},"created":1745485391,"system_fingerprint":null,"model":"qwen-plus","id":"chatcmpl-e2edaf2c-8aaf-9e54-90e2-b21dd5045503"}
data: [DONE]
DashScope
以下は、DashScope Python SDK を使用して qwen-plus モデルの思考モードを呼び出した際のストリーミングレスポンス形式です。
# 思考段階
...
{"role": "assistant", "content": "", "reasoning_content": "High information density,"}
{"role": "assistant", "content": "", "reasoning_content": "making users feel helped."}
# 応答段階
{"role": "assistant", "content": "I am Qwen", "reasoning_content": ""}
{"role": "assistant", "content": ", developed by Tongyi Lab", "reasoning_content": ""}
...
-
reasoning_contentが "" ではなく、contentが "" の場合、現在の段階は思考中です。 -
reasoning_contentが "" で、contentが "" ではない場合、現在の段階は応答中です。 -
両方が "" の場合、前のパケットと同じ段階にとどまります。
Python
サンプルコード
import os
from dashscope import Generation
import dashscope
dashscope.base_http_api_url = "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/"
messages = [{"role": "user", "content": "Who are you?"}]
completion = Generation.call(
# 環境変数を構成していない場合は、次の行を Alibaba Cloud Model Studio API キーに置き換えてください: api_key = "sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"),
# 必要に応じて他のディープシンキングモデルに置き換えてください
model="qwen-plus",
messages=messages,
result_format="message", # Qwen3 オープンソースモデルは "message" のみをサポート。他のモデルでもより良いエクスペリエンスのために "message" を設定することを推奨します。
# ディープシンキングを有効化。qwen3-30b-a3b-thinking-2507、qwen3-235b-a22b-thinking-2507、QwQ モデルにはこのパラメーターは影響しません。
enable_thinking=True,
stream=True,
incremental_output=True, # Qwen3 オープンソースモデルは true のみをサポート。他のモデルでもより良いエクスペリエンスのために true を設定することを推奨します。
)
# 完全な思考プロセスを定義
reasoning_content = ""
# 完全な応答を定義
answer_content = ""
# 思考を終え、応答を開始したかどうかを判定
is_answering = False
print("=" * 20 + "思考プロセス" + "=" * 20)
for chunk in completion:
# 思考プロセスと応答の両方が空の場合、スキップ
if (
chunk.output.choices[0].message.content == ""
and chunk.output.choices[0].message.reasoning_content == ""
):
pass
else:
# 現在、思考段階にある場合
if (
chunk.output.choices[0].message.reasoning_content != ""
and chunk.output.choices[0].message.content == ""
):
print(chunk.output.choices[0].message.reasoning_content, end="", flush=True)
reasoning_content += chunk.output.choices[0].message.reasoning_content
# 現在、応答段階にある場合
elif chunk.output.choices[0].message.content != "":
if not is_answering:
print("\n" + "=" * 20 + "完全な応答" + "=" * 20)
is_answering = True
print(chunk.output.choices[0].message.content, end="", flush=True)
answer_content += chunk.output.choices[0].message.content
# 完全な思考プロセスと完全な応答を出力するには、以下の行のコメントを外して実行してください
# print("=" * 20 + "完全な思考プロセス" + "=" * 20 + "\n")
# print(f"{reasoning_content}")
# print("=" * 20 + "完全な応答" + "=" * 20 + "\n")
# print(f"{answer_content}")
レスポンス
====================思考プロセス====================
わかりました、ユーザーが「あなたは誰ですか?」と尋ねています。この質問に答える必要があります。まず、私が Alibaba Cloud が開発した大規模言語モデルである Qwen であることを明確にします。次に、質問への回答、テキスト作成、論理的推論などの機能と目的を説明します。また、役立つアシスタントになるという目標を強調します。
表現は会話的で、専門用語や複雑な文構造を避けます。「こんにちは~」のようなフレンドリなフレーズを追加して、会話を自然なものにします。また、開発元、主な機能、使用シナリオなどの重要なポイントを正確に伝え、省略しないようにします。
ユーザーからのフォローアップ質問(具体的なアプリケーション例や技術的な詳細など)の可能性を考慮し、応答にさらなる問い合わせをほのめかすようにします。たとえば、「日常的な質問でも専門的な問題でも、全力でお手伝いします」と述べることで、包括的かつオープンエンドになります。
最後に、流暢さ、繰り返し、冗長な情報をチェックして、応答を簡潔に保ちます。親しみやすさと専門性のバランスを維持し、ユーザーが親しみやすく信頼できると感じるようにします。
====================完全な応答====================
こんにちは~ 私は Alibaba Cloud が開発した大規模言語モデルの Qwen です。質問への回答、テキスト作成、論理的推論、プログラミングなどを通じて、お手伝いとサポートを提供することを目指しています。日常的な質問でも専門的な問題でも、全力でお手伝いします。どのようにお手伝いできますか?
Java
サンプルコード
// dashscope SDK バージョン >= 2.19.4
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 io.reactivex.Flowable;
import java.lang.System;
import com.alibaba.dashscope.utils.Constants;
public class Main {
static {
Constants.baseHttpApiUrl="https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1";
}
private static final Logger logger = LoggerFactory.getLogger(Main.class);
private static StringBuilder reasoningContent = new StringBuilder();
private static StringBuilder finalContent = new StringBuilder();
private static boolean isFirstPrint = true;
private static void handleGenerationResult(GenerationResult message) {
String reasoning = message.getOutput().getChoices().get(0).getMessage().getReasoningContent();
String content = message.getOutput().getChoices().get(0).getMessage().getContent();
if (!reasoning.isEmpty()) {
reasoningContent.append(reasoning);
if (isFirstPrint) {
System.out.println("====================思考プロセス====================");
isFirstPrint = false;
}
System.out.print(reasoning);
}
if (!content.isEmpty()) {
finalContent.append(content);
if (!isFirstPrint) {
System.out.println("\n====================完全な応答====================");
isFirstPrint = true;
}
System.out.print(content);
}
}
private static GenerationParam buildGenerationParam(Message userMsg) {
return GenerationParam.builder()
// 環境変数を構成していない場合は、次の行を Alibaba Cloud Model Studio API キーに置き換えてください: .apiKey("sk-xxx")
.apiKey(System.getenv("DASHSCOPE_API_KEY"))
.model("qwen-plus")
.enableThinking(true)
.incrementalOutput(true)
.resultFormat("message")
.messages(Arrays.asList(userMsg))
.build();
}
public static void streamCallWithMessage(Generation gen, Message userMsg)
throws NoApiKeyException, ApiException, InputRequiredException {
GenerationParam param = buildGenerationParam(userMsg);
Flowable<GenerationResult> result = gen.streamCall(param);
result.blockingForEach(message -> handleGenerationResult(message));
}
public static void main(String[] args) {
try {
Generation gen = new Generation();
Message userMsg = Message.builder().role(Role.USER.getValue()).content("Who are you?").build();
streamCallWithMessage(gen, userMsg);
// 最終結果を出力
// if (reasoningContent.length() > 0) {
// System.out.println("\n====================完全な応答====================");
// System.out.println(finalContent.toString());
// }
} catch (ApiException | NoApiKeyException | InputRequiredException e) {
logger.error("An exception occurred: {}", e.getMessage());
}
System.exit(0);
}
}
レスポンス
====================思考プロセス====================
わかりました。ユーザーが「あなたは誰ですか?」と尋ねたので、以前の設定に基づいて回答する必要があります。まず、私の役割はアリババグループ傘下の大規模言語モデルである Qwen です。会話的でシンプルに保つ必要があります。
ユーザーは私にとって初めての方か、私のアイデンティティを確認している可能性があります。まずは自分が誰なのかを直接述べてから、質問への回答、テキスト作成、プログラミングなどの機能や目的を簡単に説明します。また、ユーザーが私がさまざまな言語を扱えることを知れるよう、多言語対応についても言及します。
また、ガイドラインに従い、人間らしい品質を維持するため、フレンドリーなトーンを使い、親しみやすさのために絵文字を追加することも検討します。ユーザーに対してさらに質問するよう促したり、私の機能(例:何をお手伝いできるか尋ねる)を使ってもらうようにガイドします。
複雑な用語を避け、簡潔にまとめます。多言語対応や具体的な機能など、重要なポイントが欠けていないか確認します。会話的なスタイルとシンプルさを含む、すべての要件を満たす応答になるよう確保します。
====================完全な応答====================
こんにちは!私はアリババグループ傘下の大規模言語モデル、Qwen です。質問に回答したり、物語や公式文書、メール、スクリプトなどのテキストを作成したり、論理的推論を行ったり、プログラミングしたり、意見を述べたり、ゲームをプレイしたりできます。中国語、英語、ドイツ語、フランス語、スペイン語など、複数の言語に対応しています。何かお手伝いできることはありますか?
HTTP
サンプルコード
curl
ハイブリッド思考モデルの場合、enable_thinking を true に設定して思考モードを有効にします。enable_thinking パラメーターは、qwen3-30b-a3b-thinking-2507、qwen3-235b-a22b-thinking-2507、QwQ モデルには影響しません。
# ======= 重要事項 =======
# API キーはリージョンによって異なります。API キーの取得先: https://www.alibabacloud.com/help/zh/model-studio/get-api-key
# シンガポールリージョンの URL。{WorkspaceId} を実際のワークスペース ID に置き換えてください。URL はリージョンによって異なります。
# === 実行前にこのコメントを削除してください ===
curl -X POST "https://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/api/v1/services/aigc/text-generation/generation" \
-H "Authorization: Bearer $DASHSCOPE_API_KEY" \
-H "Content-Type: application/json" \
-H "X-DashScope-SSE: enable" \
-d '{
"model": "qwen-plus",
"input":{
"messages":[
{
"role": "user",
"content": "Who are you?"
}
]
},
"parameters":{
"enable_thinking": true,
"incremental_output": true,
"result_format": "message"
}
}'
レスポンス
id:1
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"Hmm","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":14,"input_tokens":11,"output_tokens":3},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:2
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":15,"input_tokens":11,"output_tokens":4},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:3
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"user","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":16,"input_tokens":11,"output_tokens":5},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:4
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"asked","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":17,"input_tokens":11,"output_tokens":6},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:5
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"\"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":18,"input_tokens":11,"output_tokens":7},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
......
id:358
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"help","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":373,"input_tokens":11,"output_tokens":362},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:359
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":",","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":374,"input_tokens":11,"output_tokens":363},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:360
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"welcome","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":375,"input_tokens":11,"output_tokens":364},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:361
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"anytime","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":376,"input_tokens":11,"output_tokens":365},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:362
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"tell","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":377,"input_tokens":11,"output_tokens":366},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:363
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"me","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":378,"input_tokens":11,"output_tokens":367},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:364
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"!","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":378,"input_tokens":11,"output_tokens":367},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
id:365
event:result
:HTTP_STATUS/200
data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"","role":"assistant"},"finish_reason":"stop"}]},"usage":{"total_tokens":378,"input_tokens":11,"output_tokens":367},"request_id":"25d58c29-c47b-9e8d-a0f1-d6c309ec58b1"}
公開
-
パフォーマンスとリソース管理:バックエンドサービスでは、各ストリーミングリクエストに対して HTTP 持続的接続を維持することでリソースを消費します。適切な接続プールサイズとタイムアウト値を設定してください。高い同時実行性のシナリオでは、ファイルディスクリプタの使用量を監視し、枯渇を防いでください。
-
クライアント側のレンダリング:ウェブフロントエンドでは、
ReadableStreamおよびTextDecoderStreamAPI を使用して、SSE イベントストリームをスムーズに処理・レンダリングし、最高のユーザーエクスペリエンスを提供してください。 -
-
主要メトリック:ストリーミングエクスペリエンスの中核となるメトリックである 初回トークン到達時間 (TTFT) を監視してください。また、API エラー率および平均応答時間も監視します。
-
アラート:特に 4xx および 5xx エラーなど、異常な API エラー率に対してアラートを設定してください。
-
-
Nginx プロキシ構成:Nginx をリバースプロキシとして使用する場合、デフォルトの出力バッファリング (proxy_buffering) によりストリーミングレスポンスのリアルタイム性が損なわれます。データがクライアントに即座にプッシュされるようにするには、Nginx 構成ファイルで
proxy_buffering offを設定してこの機能を無効にしてください。
エラーコード
モデル呼び出しが失敗してエラーメッセージが返された場合は、「エラーコード」をご参照のうえ、解決策を確認してください。
よくある質問
Q:レスポンスに使用量情報が含まれないのはなぜですか?
A:OpenAI プロトコルはデフォルトで使用量情報を返しません。最終的に返されるパケットに使用量情報を含めるには、stream_options パラメーターを設定してください。
Q:ストリーミング出力を有効にしても、モデルの応答品質に影響しますか?
A:いいえ。ただし、一部のモデルはストリーミング出力のみをサポートしており、非ストリーミング呼び出しではタイムアウトエラーが発生する可能性があります。ストリーミング出力の使用を推奨します。
Q:非ストリーミング呼び出しとストリーミング呼び出しの違いは何ですか?
A:主な違いは以下のとおりです。
-
タイムアウト制限:非ストリーミング呼び出しには 300 秒の固定最大タイムアウトがあります。モデルが 300 秒以内に生成を完了しない場合、リクエストはタイムアウトして失敗します。
-
出力構造:非ストリーミング呼び出しは、一度に完全なレスポンス(単一の JSON オブジェクト)を返します。ストリーミング呼び出しは、SSE プロトコルを介してデータチャンクを段階的に返し、各チャンクには生成されたコンテンツの一部が含まれます。クライアントはこれらのチャンクをアセンブルする必要があります。
-
機能互換性:JSON モードや関数呼び出しなどの機能は、どちらもサポートされており、機能的な違いはありません。
タイムアウトを回避し、ユーザーエクスペリエンスを向上させるために、ストリーミング出力の使用を推奨します。
Q:ストリーミング出力は JSON モード(構造化出力)をサポートしていますか?
A:はい。リクエストで stream を true に、response_format を {"type": "json_object"} に設定してください。モデルは JSON 形式のコンテンツフラグメントを段階的に返します。最終的にアセンブルされた出力は、有効な JSON になります。