2026年4月16日にAlibabaのQwenチームがApache 2.0で公開したQwen3.6-35B-A3Bは、総パラメータ35B・アクティブパラメータ約3BのスパースMoEモデルです。SWE-bench Verified 73.4%、MCPMark 37.0と、エージェント的コーディングに特化したチューニングが入っています。
この記事では、vLLMでOpenAI互換APIとしてサーブし、Pythonクライアントからツール呼び出し(Function Calling)付きで使うところまでを動かします。
※ 本記事は公開情報をもとにした個人的なまとめです。
前提
- vLLM 0.19.0 以上(公式が推奨するバージョン)
- NVIDIA GPU(RTX 4090 24GB で単体動作可、複数GPUならテンソル並列で大きなコンテキストも扱える)
- Python 3.12
- モデルは初回起動時にHugging Faceから自動ダウンロードされる
1. vLLMのインストール
python -m venv qwen36-env
source qwen36-env/bin/activate
pip install vllm>=0.19.0
古いvLLMではQwen3.6のMoEアーキテクチャをサポートしていないため、必ず0.19.0以上を使ってください。
2. vLLMサーバーの起動
基本起動(推論のみ)
vllm serve Qwen/Qwen3.6-35B-A3B \
--port 8000 \
--tensor-parallel-size 1 \
--max-model-len 32768 \
--reasoning-parser qwen3
--reasoning-parser qwen3 を付けるとthinkingモード(内部推論ステップの生成)が有効になります。コーディング用途ではこれを付けたほうが精度が出ます。
RTX 4090単体の場合は --max-model-len を32768〜65536程度に抑えてください。262144フルに使うにはVRAMが足りません。
ツール呼び出し対応で起動
vllm serve Qwen/Qwen3.6-35B-A3B \
--port 8000 \
--tensor-parallel-size 1 \
--max-model-len 32768 \
--reasoning-parser qwen3 \
--enable-auto-tool-choice \
--tool-call-parser qwen3_coder
--tool-call-parser qwen3_coder は必須です。 このフラグがないと、モデルはツール呼び出しのJSONを生成しますがvLLMがそれをパースできず、構造化されたtool_callオブジェクトとして返ってきません。
複数GPU(例: 4枚)の場合
vllm serve Qwen/Qwen3.6-35B-A3B \
--port 8000 \
--tensor-parallel-size 4 \
--max-model-len 262144 \
--reasoning-parser qwen3 \
--enable-auto-tool-choice \
--tool-call-parser qwen3_coder
起動すると http://localhost:8000/v1 にOpenAI互換のAPIエンドポイントが立ちます。
3. Pythonから基本的なチャット
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="dummy", # vLLMローカルではAPIキー不要
)
response = client.chat.completions.create(
model="Qwen/Qwen3.6-35B-A3B",
messages=[
{"role": "user", "content": "Pythonでフィボナッチ数列のジェネレータを書いてください"}
],
temperature=0.7,
max_tokens=2048,
)
print(response.choices[0].message.content)
OpenAI SDKがそのまま使えるので、既存のコードベースからモデルを差し替えるだけで動きます。
4. ツール呼び出し(Function Calling)
ここからが本題です。Qwen3.6-35B-A3Bはツール呼び出しに対応しており、MCPMarkベンチマークではGemma 4-31Bの18.1%に対して37.0%を記録しています。
import json
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="dummy",
)
# ツール定義
tools = [
{
"type": "function",
"function": {
"name": "search_files",
"description": "プロジェクト内のファイルをキーワードで検索する",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "検索キーワード"
},
"file_extension": {
"type": "string",
"description": "対象の拡張子(例: .py, .ts)"
}
},
"required": ["query"]
}
}
},
{
"type": "function",
"function": {
"name": "read_file",
"description": "指定パスのファイル内容を読み取る",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "ファイルパス"
}
},
"required": ["path"]
}
}
},
{
"type": "function",
"function": {
"name": "write_file",
"description": "指定パスにファイルを書き込む",
"parameters": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "ファイルパス"
},
"content": {
"type": "string",
"description": "書き込む内容"
}
},
"required": ["path", "content"]
}
}
}
]
# エージェント的にツールを呼ばせる
response = client.chat.completions.create(
model="Qwen/Qwen3.6-35B-A3B",
messages=[
{
"role": "system",
"content": "あなたはコーディングエージェントです。ユーザーのリクエストに応じてファイルを検索・読み取り・書き込みしてください。"
},
{
"role": "user",
"content": "プロジェクト内のPythonファイルからデータベース接続を扱っている箇所を探して、接続プールのサイズを5から20に変更してください。"
}
],
tools=tools,
tool_choice="auto",
temperature=1.0, # thinkingモード推奨値
max_tokens=4096,
)
message = response.choices[0].message
# ツール呼び出しの結果を確認
if message.tool_calls:
for call in message.tool_calls:
print(f"Tool: {call.function.name}")
print(f"Args: {call.function.arguments}")
print("---")
else:
print(message.content)
5. ツール呼び出しループ(マルチターン)
実用的なエージェントでは、ツール呼び出し → 結果をモデルに返す → 次のアクション、というループが必要です。
def run_agent(user_request: str, tools: list, max_steps: int = 10):
messages = [
{
"role": "system",
"content": "あなたはコーディングエージェントです。必要なツールを呼び出してタスクを完了してください。"
},
{"role": "user", "content": user_request}
]
for step in range(max_steps):
response = client.chat.completions.create(
model="Qwen/Qwen3.6-35B-A3B",
messages=messages,
tools=tools,
tool_choice="auto",
temperature=1.0,
max_tokens=4096,
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
if not assistant_message.tool_calls:
# ツール呼び出しなし = 完了
print(f"[完了] {assistant_message.content}")
return assistant_message.content
# 各ツール呼び出しを実行
for call in assistant_message.tool_calls:
tool_name = call.function.name
tool_args = json.loads(call.function.arguments)
print(f"[Step {step+1}] {tool_name}({tool_args})")
# ここに実際のツール実行ロジックを入れる
result = execute_tool(tool_name, tool_args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result, ensure_ascii=False),
})
return "最大ステップ数に到達しました"
def execute_tool(name: str, args: dict) -> dict:
"""実際のツール実行(ここではダミー)"""
if name == "search_files":
return {
"files": [
{"path": "src/db/connection.py", "match": "pool_size=5"},
{"path": "src/db/config.py", "match": "POOL_SIZE = 5"},
]
}
elif name == "read_file":
return {"content": f"# {args['path']} の内容がここに入る"}
elif name == "write_file":
return {"status": "ok", "path": args["path"]}
return {"error": "unknown tool"}
execute_tool の中身を実際のファイルシステム操作に差し替えれば、ローカルで動くコーディングエージェントになります。
6. thinkingモードの切り替え
Qwen3.6にはthinkingモード(内部推論を生成してから回答)と非thinkingモード(直接回答)があります。
| モード | temperature | 用途 |
|---|---|---|
| thinking(推奨) | 1.0 | 複雑なコーディング、デバッグ、設計判断 |
| non-thinking | 0.7 | シンプルな質問、コード補完 |
vLLMの起動時に --reasoning-parser qwen3 を付けている場合、thinkingモードがデフォルトで有効です。APIリクエスト側で無効にしたい場合は、vLLM 0.19.0以降で extra_body パラメータを使います。
ハードウェア目安
| 構成 | max-model-len | 備考 |
|---|---|---|
| RTX 4090 (24GB) × 1 | 32,768 | 基本的なコーディングタスクには十分 |
| RTX 4090 × 2(TP=2) | 65,536 | リポジトリ全体を読み込む用途 |
| A100 80GB × 1 | 131,072 | 余裕のある単体構成 |
| H100 × 4(TP=4) | 262,144 | フルコンテキスト、本番運用 |
FP8量子化版(Qwen/Qwen3.6-35B-A3B-FP8)を使えばVRAM使用量をさらに抑えられます。性能はほぼ同等と報告されています。
まとめ
- vLLM 0.19.0以上で
Qwen/Qwen3.6-35B-A3Bをサーブすると、localhost:8000/v1にOpenAI互換APIが立つ - ツール呼び出しには起動時に
--enable-auto-tool-choice --tool-call-parser qwen3_coderが必須 - OpenAI SDK でそのまま叩けるので、既存コードのモデル差し替えだけで動く
- thinkingモード(
temperature=1.0)でコーディング精度が上がる - Apache 2.0ライセンスなので商用利用も自由
3日前に出たばかりのモデルなので、ツール呼び出し周りの安定性はまだコミュニティで検証中です。本番投入前にはご自身のワークロードでテストすることをお勧めします。
参考
- Qwen/Qwen3.6-35B-A3B - Hugging Face
- Qwen3.5 & Qwen3.6 Usage Guide - vLLM Recipes
- QwenLM/Qwen3.6 - GitHub
- vLLM Tool Calling Documentation
