2026年8月19日、GLM-5.3 APIの正式提供が始まりました。
GLM-5.3はGLM-5.2と同じベースモデルを使いながら、ポストトレーニングの強化によって、複雑なコーディングや長時間のエージェントタスクで性能を伸ばしたモデルです。
ただし、APIを既存のGLM-5.2実装へそのまま差し替えると、thinkingの扱いで想定外の挙動になる可能性があります。最大の変更は、thinkingを無効化できなくなったことです。
私はAIHubMixに所属しており、本稿ではAIHubMix経由で行った実呼び出しの結果を扱います。サービス紹介ではなく、GLM-5.3をアプリケーションへ組み込む際に再利用できる実装上の知見に絞ります。各APIの挙動は2026年8月14日に検証し、正式提供開始に合わせて内容を整理しました。
先に結論
- thinkingは常時有効で、無効化できない
- 推論強度は
reasoning_effortのlow/high/maxの3段階。デフォルトはmax - コンテキストは1,048,576 tokens、最大出力は131,072 tokens
- Chat Completions / Responses / Claude互換Messagesの3 APIで利用できる
- thinkingの返却形式は3 APIで異なる
- Function Callingは3 APIで動作し、Responses APIでは並列ツール呼び出しも確認できた
- JSONモードは使えるが、厳密な
json_schemaモードは提供されていない - コンテキストキャッシュは自動で有効になる
モデルの前提
| 項目 | 内容 |
|---|---|
| AIHubMix上のモデルID | coding-glm-5.3 |
| コンテキスト | 1M(1,048,576 tokens) |
| 最大出力 | 128K(131,072 tokens) |
| 入力 | テキスト |
| thinking | 常時有効、無効化不可 |
| 推論強度 |
low / high / max(デフォルトはmax) |
| 対応API | Chat Completions / Responses / Claude互換Messages |
1. GLM-5.2との最大の違いは「thinkingを切れない」こと
GLM-5.2ではthinking.typeをenabledまたはdisabledに切り替えられました。GLM-5.3ではenabledのみとなり、thinkingを完全に無効化できません。
推論コストやレイテンシーを抑えたい場合は、無効化するのではなくreasoning_effort="low"を指定します。
from openai import OpenAI
client = OpenAI(
base_url="https://aihubmix.com/v1",
api_key="<AIHUBMIX_API_KEY>",
)
completion = client.chat.completions.create(
model="coding-glm-5.3",
reasoning_effort="low", # low / high / max
extra_body={"thinking": {"type": "enabled"}},
messages=[
{"role": "user", "content": "このPythonコードをレビューしてください"}
],
)
Z.aiはコーディング用途ではmaxを推奨しています。一方、短い分類や単純な抽出処理まで常にmaxにすると、必要以上にthinking tokenを消費します。タスクごとに推論強度を切り替えられる設計にしておく方が扱いやすいです。
なお、AIHubMix経由の検証ではthinking: {"type": "disabled"}を送ってもHTTP 200が返り、thinkingは継続しました。互換処理によってリクエストが継続するためです。
ここで重要なのは、HTTP 200を「指定したパラメータが有効だった」という証拠にしないことです。GLM-5.2から移行する場合は、disabledを残さず、明示的にenabledとreasoning_effort="low"へ変更するのが安全です。
2. thinkingの返却形式はAPIごとに異なる
3つのAPIは同じモデルを呼び出せますが、thinkingの返却場所は共通ではありません。
| API | thinkingの返却先 |
|---|---|
| Chat Completions | message.reasoning_content |
| Responses |
type="reasoning"のoutput item内にあるsummary
|
| Messages |
thinking content block |
Chat Completions
completion = client.chat.completions.create(
model="coding-glm-5.3",
reasoning_effort="max",
messages=[{"role": "user", "content": "17 * 23 - 19 * 11を計算して"}],
)
print(completion.choices[0].message.reasoning_content)
print(completion.choices[0].message.content)
ストリーミング時はdelta.reasoning_contentに入ります。使用量はusage.completion_tokens_details.reasoning_tokensで確認できます。
Responses API
response = client.responses.create(
model="coding-glm-5.3",
input="フランスの首都を都市名だけで答えて",
)
for item in response.output:
print(item.type)
検証では、デフォルトのリクエストでもreasoning itemとmessage itemが返りました。thinkingを有効にするための追加指定は不要です。
Claude互換Messages API
from anthropic import Anthropic
anthropic = Anthropic(
api_key="<AIHUBMIX_API_KEY>",
base_url="https://aihubmix.com",
)
response = anthropic.messages.create(
model="coding-glm-5.3",
max_tokens=4096,
messages=[
{"role": "user", "content": "フランスの首都を都市名だけで答えて"}
],
)
for block in response.content:
print(block.type) # thinking / text
APIを切り替えられるアプリケーションでは、プロバイダーのレスポンスを直接UIへ渡さず、reasoningと最終回答を共通形式へ正規化するadapterを置くと実装が安定します。
3. Function Callingは3 APIで利用可能
Function CallingはChat Completions、Responses、Messagesのすべてで動作しました。ただし、ツール定義の形はAPIごとに異なります。
| API | 主なツール定義 |
|---|---|
| Chat Completions | {"type":"function","function":{...}} |
| Responses | {"type":"function","name":"...","parameters":{...}} |
| Messages | {"name":"...","input_schema":{...}} |
Responses APIでは、1ターンで2件のfunction_call itemが返る並列ツール呼び出しも確認できました。
response = client.responses.create(
model="coding-glm-5.3",
input="東京と大阪の天気を調べて",
parallel_tool_calls=True,
tools=[{
"type": "function",
"name": "get_weather",
"description": "指定した都市の天気を取得する",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
}],
)
並列呼び出しを使う場合、返却順に依存せず、call_idとツール結果を対応付ける必要があります。外部APIにレート制限がある場合は、モデル側が並列で要求してもクライアント側で同時実行数を制御します。
また、Messages APIの検証ではtool_choice: {"type": "none"}を送ってもツール呼び出しが発生しました。確実にツールを禁止したいターンでは、tools自体をリクエストから外す方が安全です。
4. 構造化出力はJSONモードまで
Chat Completionsではresponse_format: json_object、Responses APIではtext.format: json_objectを利用できます。
response = client.responses.create(
model="coding-glm-5.3",
input="フランスの首都をanswerキーで返して",
text={"format": {"type": "json_object"}},
)
一方、上流仕様には厳密なjson_schemaモードがありません。JSONの形を保証したい場合は、次の3段階で扱います。
- プロンプトにJSON Schemaを含める
- クライアント側でパースする
- Schema validatorで検証し、失敗時だけ再生成する
Messages APIには専用のJSONモードがないため、プロンプトで形式を指定します。厳密な引数構造が必要な処理なら、通常の回答ではなくツールのinput_schemaとして表現する方法もあります。
5. コンテキストキャッシュは自動
キャッシュを有効化するためのパラメータはありません。同じ長いprefixを繰り返すと自動でキャッシュされ、APIごとに異なるusageフィールドへ反映されます。
| API | キャッシュヒットの確認先 |
|---|---|
| Chat Completions | prompt_tokens_details.cached_tokens |
| Responses | input_tokens_details.cached_tokens |
| Messages | cache_read_input_tokens |
Chat CompletionsとResponsesでは、同じ長いprefixを連続して送った2回目のリクエストで960 cached tokensを確認できました。
キャッシュを活かすには、system prompt、共通知識、ツール定義など、変化しにくい内容を入力の前方に置きます。ユーザーごと・ターンごとに変化する情報は後方へ寄せると、共通prefixを維持しやすくなります。
6. パラメータ検証をAPIゲートウェイ任せにしない
GLM-5.3ではtemperatureの有効範囲が[0, 1]、top_pが[0.01, 1]です。Z.aiは両方を同時に変更せず、どちらか一方だけを調整することを推奨しています。
検証では、Messages APIへtemperature=3を送るとHTTP 400になりましたが、Chat CompletionsとResponsesでは同じ値でもHTTP 200が返りました。
API間でvalidationの挙動が揃っているとは限りません。次のように、送信前にクライアント側で範囲を確認する方が安全です。
def validate_sampling(temperature: float, top_p: float) -> None:
if not 0 <= temperature <= 1:
raise ValueError("temperature must be between 0 and 1")
if not 0.01 <= top_p <= 1:
raise ValueError("top_p must be between 0.01 and 1")
thinkingのdisabledと同様に、エラーにならなかったパラメータが実際に適用されたとは限りません。未対応値を静かにデフォルトへ戻す経路を想定し、usageやレスポンス内容も含めて確認する必要があります。
実装チェックリスト
- GLM-5.2で使っていた
thinking.type="disabled"を削除する - 軽いタスクは
reasoning_effort="low"へ明示的に振り分ける - コーディングや長時間タスクは
maxを基本に、token使用量も観測する - APIごとにthinkingとtool callを正規化するadapterを用意する
- 並列ツール呼び出しは
call_idで結果を対応付ける - 厳密なJSONはクライアント側でSchema validationする
- キャッシュヒットをusageから継続的に観測する
- HTTP 200だけでパラメータ対応を判定しない
-
temperatureとtop_pは送信前に範囲を検証する
まとめ
GLM-5.3への移行で最も重要なのは、thinkingを「オン・オフする機能」ではなく、常時有効で強度だけを調整する機能として扱うことです。
1M context、128K output、Function Calling、並列ツール呼び出しを組み合わせられるため、長いコーディング作業やエージェント実装には向いています。一方で、3 APIのフィールド差、JSON Schemaの扱い、validationの違いを吸収しないまま実装すると、HTTP 200でも意図と異なる挙動を見逃します。
モデルIDだけを差し替えるのではなく、thinkingの設定、usageの観測、ツール実行、構造化出力まで含めたintegration testを用意してから移行するのがおすすめです。