0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Code のモデル切替設定、実は思ってた仕様と違った

0
Posted at

Claude Code のモデル切替設定、実は思ってた仕様と違った

Claude Codeには「メインのモデルが混雑していて使えないときに、別のモデルへ自動で切り替える」という設定(fallbackModel)がある。

自分はこれを、純粋に「サーバーが混んでいるときの保険」だと思って設定していた。処理能力が足りない時だけ発動する、いわば渋滞回避のバイパスのようなものだと。

ところが公式ドキュメントを読み込んでいくと、この機能が発動する条件は、自分が思っていたより広かった。混雑とはまったく関係ない理由で、しかも通知を見落としたらそのまま気づかない形で切り替わっている可能性がある、ということが分かったのだ。

以下はClaude Code公式ドキュメント(model-config / settings)を読み込んで確認した仕様の話。特定のモデルへの批判ではなく、「思っていた前提と実際の仕様が違った」という気づきの記録。

「混雑時だけ」という前提が、そもそも半分しか合っていなかった

まず公式ドキュメントの基本的な説明はこうだ。

When the primary model is overloaded, unavailable, or returns another non-retryable server error, Claude Code can switch to a fallback model instead of failing the request.

ここまでは想定どおり。だがすぐ後に、まったく別系統の発動条件が書かれていた。**セキュリティやバイオロジー関連のコンテンツを検知する「安全分類器」**が、依頼された内容にフラグを立てた場合にも、同じ仕組みで自動的にフォールバック先のモデルへ切り替わる、というものだ。

Fable 5 and Opus 5 run with safety classifiers for cybersecurity and biology content. When a classifier flags a request and the flagged category has a fallback model, Claude Code re-runs the request on that model and shows a notice in the transcript.

つまりフォールバックは「混雑」と「内容のフラグ」という、性質のまったく違う2つの理由で起こり得る。前者は自分の作業とは無関係な外的要因だが、後者は自分が渡している中身が原因になる。

しかも「何も変わったことをしていないセッションの最初の1回」で起こり得る

一番驚いたのは、このフラグが立つタイミングだった。

Fallback can trigger on the first request of a session, before you send anything unusual, because the first request carries workspace context such as your CLAUDE.md content and git status. A repository that contains security or biology material can trip the classifier on that context alone.

(訳: フォールバックは、セッションの最初のリクエストで発動し得る。まだ何も変わった内容を送っていない段階でだ。なぜなら最初のリクエストには、あなたのCLAUDE.mdの内容やgitの状態といった、作業環境そのものの情報が乗っているから。セキュリティやバイオロジー関連の内容を含むリポジトリは、その文脈情報だけで分類器に引っかかることがある)

自分が何か怪しい質問をしたわけでもなく、ただセッションを開いただけで、リポジトリの中身や設定ファイルの記述だけを理由に切り替わり得る、ということだ。

既定は「立ち止まらずに続ける」側だった

「切り替わるにしても、せめて一度確認してほしい」と思ったが、公式の書き方を見て納得がいった。都度確認する側に倒したいなら、自分でオフにしにいく必要がある。

To decide what happens each time a request is flagged, rather than switching automatically, run /config and turn off Switch models when a message is flagged, or set switchModelsOnFlag to false in your settings file. …

(訳: 自動で切り替えるのではなく、フラグが立つたびに何をするか決めたいなら、/config を開いて「メッセージにフラグが立ったときにモデルを切り替える」をオフにするか、設定ファイルで switchModelsOnFlagfalse にする)

「自動で切り替えるのではなく」という書き方がそのまま答えで、何もしなければ自動で切り替わる側が既定になっている。

救いは、切り替わったこと自体は通知として出ること(さっきの引用にあった shows a notice in the transcript)。裏を返すと、気づく手がかりは基本その通知だけだ。原因の切り分け用には、別の入口も用意されていた。

To check whether customizations are the trigger, start a session with claude --safe-mode, which disables customizations such as CLAUDE.md, skills, MCP servers, and hooks. …

(訳: 自分のカスタマイズが引き金になっているかを確かめたいなら、claude --safe-mode でセッションを始める。CLAUDE.md・スキル・MCPサーバー・フックといったカスタマイズが無効になる)

効果の範囲も、思っていたより狭かった

もう1つ、地味に見落としていたのが「複数の設定ファイルにまたがる場合の扱い」だった。リスト形式の設定は普通、複数のファイルに書いた内容が合算される。ところがfallbackModelはその例外だった。

When you set the same list key, such as permissions.allow, in more than one file, Claude Code combines the lists instead of picking one, so each file can add entries without removing another file's. Two list keys follow their own rules:

  • fallbackModel is an ordered chain where position carries meaning, so Claude Code takes the whole value from the highest-precedence file that defines it.

(訳: permissions.allow のような同じリスト設定を複数のファイルに書いた場合、Claude Codeはどれか1つを選ぶのではなくリストを結合する。だから各ファイルは、他のファイルの記述を消さずに項目を足せる。ただし2つのリスト設定だけは独自のルールに従う。fallbackModel は並び順に意味がある「連なり」なので、Claude Codeはそれを定義しているファイルのうち優先順位が最も高いものから、値を丸ごと取る)

複数の階層に少しずつ書き足していけば積み上がっていく、というよくある設定ファイルの感覚とは違う挙動だ。

ついでに調べ直した、思考の深さと要約のタイミング

フォールバックを追っているうちに、隣接する2つの設定も一緒に確認しておくことにした。

1つは「思考の深さ(effort)」の既定値。モデルが答えを出す前にどれだけ深く考えるかを決める設定で、公式ドキュメントにはこうあった。

The default effort is high on every model that supports effort, except Opus 4.7, which defaults to xhigh.

(訳: effortに対応するどのモデルでも、既定値は high。ただしOpus 4.7だけは既定が xhigh)

「自分は何も設定していないから、控えめな水準で動いているはず」という思い込みは外れていた。何も指定しなければ、最初から high で動いている。

もう1つは、会話が長くなったときの自動要約(auto-compact)がいつ発動するか。何も設定していなければ、こう動くと明記されていた。

If you don't set an auto-compact window, Claude Code compacts when the conversation reaches the model's context limit, except in these sessions:

(訳: auto-compactの窓を自分で設定していなければ、会話がモデルのコンテキスト上限に達したタイミングで要約される。ただし次のセッションは例外)

この「ただし」の後に、例外が5つ箇条書きで並んでいた。クラウドセッション/拡張コンテキスト無しのSonnet 4.6・Opus 4.6(および200Kのコンテキストで動くOpus 4.8・Opus 5)/CLAUDE_CODE_DISABLE_1M_CONTEXT=1 を設定した場合/Sonnet 5/Claude Codeが認識できないモデルID、の5つだ。

つまり「ある程度長くなったら、こまめに要約されている」というのは思い込みだった。かといって「常に上限ぎりぎりまで積み上がる」でもない。どのモデルを、どこで動かしているかによって、要約が走る境界そのものが変わる。危なかったのは、ここの「ただし」を読み飛ばしていたら、自分の環境がどの行に当たるのかを確かめないまま「上限まで大丈夫」と思い込むところだったことだ。

思っていた仕様と、実際の仕様

読み込む前と後で、自分の理解がどう変わったかを整理するとこうなる。

項目 思っていた仕様 実際の仕様
発動条件 サーバー混雑時のみ 混雑に加えて、安全分類器のフラグでも発動する
発動タイミング 何か特殊な依頼をした時 セッション最初のリクエストでも発動し得る
気づき方 何となく分かるはず 切替時に出る通知が手がかり。原因の切り分けは claude --safe-mode
切替後の動作 一度立ち止まって確認される 既定は自動で継続(都度確認したいなら switchModelsOnFlagfalse にする)
複数の設定ファイル 積み上げで合算される fallbackModel は例外で、最優先のファイルの値が丸ごと使われる
思考の深さ(effort) 何も設定していなければ控えめのはず 何も設定していなくても既定は high(Opus 4.7のみ xhigh
自動要約(auto-compact) ある程度で自動的にこまめに要約される 窓を設定していなければモデルの上限で要約される。ただし例外が5つあり、境界はモデルと実行環境で変わる

やってみて分かったこと

「保険のつもりで入れた設定」ほど、普段は意識しないぶん、いざという時の挙動を正確に把握していないことに気づかされた。混雑対策として入れたつもりの設定が、実は自分の作業内容に応じて別の理由でも発動し、しかも通知以外では気づけない形で動いていた。

保険をかけること自体は間違っていない。ただ、その保険がどんな条件で発動するのかは、入れた本人が一番把握できていなかった。設定を入れたら、発動条件まで公式ドキュメントで確認する——当たり前のようで、今回一番身にしみた教訓だった。

関連記事(個人ブログ)

この話をどう測って、どう直したかの詳細は個人ブログに書いています。

参考にした公式ページ


個人ブログ(https://mint041223techblog.netlify.app/)に日々の開発で気づいたことを詳しく書いています(外部サイトに移動します)。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?