Claude Media
Claude APIのレイテンシ削減とTTFT計測 — 実装3パターン

Claude APIのレイテンシ削減とTTFT計測 — 実装3パターン

Claude APIの応答が遅いとき、完了までと最初のトークンまでのどちらが長いかをcurlで測り、モデル・effort・キャッシュ・ストリーミングから選ぶ手順です。

Claude APIの応答が遅いとき、最初に決めるのは「どの待ち時間を縮めたいか」です。画面に最初の文字が出るまでなのか、回答が最後まで終わるまでなのかで、効く打ち手が変わります。この記事では2つの指標の違いを手元で計測し、モデル選択・effort・プロンプト短縮・キャッシュ・ストリーミングの順に、どの待ち時間に効くかを見ていきます。

対策に着手する前に、制約なしで精度の出るプロンプトを先に作っておきます。最初からレイテンシを気にすると、そのタスクで出せる最高精度の水準を見失うためです。

遅いのは「最初の1文字」か「最後の1文字」か

くらべる

2つの指標が指す時間

完了まで

baseline latency

公式の定義では、プロンプトの処理から応答の生成までにかかる時間で、毎秒の入出力トークン数は考慮しません。処理・生成するトークンが少ないほど応答は速くなるため、出力を減らすと縮みます。バッチ処理のように、全文が揃ってから次の工程へ進む用途で効く指標です。

最初のトークンまで

TTFT

プロンプトを送ってから、最初の1トークンが生成されるまでの時間です。最初のトークンまでの時間なので、出力の長さの影響は受けにくい指標です。チャットのように、最初の反応の早さが体感を決める用途で効く指標です。

2つを混同すると改善の的が外れます。ストリーミングを入れても、完了までの時間は変わらないためです。指標を決めずに「速くなった気がする」で判断すると、変更の効果を切り分けられません。

curlで計測する: time_starttransferが最初の1バイトを返す

curlの-wオプションには、リクエスト開始から最初のバイトを受け取るまでの時間time_starttransferと、全体のtime_totalがあります。ストリーミングのリクエストにこの2つを並べると、TTFTに近い値と完了時間を1回で取れます。

curl -sN -o /dev/null https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "stream": true,
    "messages": [{"role": "user", "content": "Hello"}]
  }' \
  -w 'time_starttransfer=%{time_starttransfer} time_total=%{time_total}\n'

time_starttransferには、DNS・TCP・TLSの接続時間も含まれます。接続分を引きたいときは、time_connectやtime_appconnectも併記します。

2つの値の差が、最初のバイトが届いてから生成が終わるまでの時間です。API本体を叩く前に-wの読み方を確かめるため、手元のローカルサーバーで試しました。0.5秒待って最初のイベントを返し、その後は1秒おきに3回イベントを返すだけの模擬サーバーです(Anthropic APIの応答ではありません)。

time_starttransfer=0.503386 time_total=3.520944

time_starttransferは待機の0.5秒に、time_totalは全体の約3.5秒に一致します。-wの2つの値がそれぞれ何を拾うかが、1回の実行で読み取れます。

ただし最初のバイトは、本文の最初のトークンとは限りません。ストリームはmessage_startで始まり、続けてcontent_block_start、content_block_deltaの順に届きます。content_block_deltaのdeltaにはテキスト以外に、thinking_deltaやinput_json_deltaもあります。本文の最初の文字までを正確に測るなら、SDKのストリーミングイベントに受信時刻を記録し、最初のtext_deltaが届いた時刻をとります。

モデルを替える: 最速はHaiku 4.5、単価も一緒に動く

最も直接的な方法は、タスクに見合ったモデルを選ぶことです。速度が最優先なら、高い知性を保ちながら最速の応答を返すClaude Haiku 4.5が候補になります。

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-haiku-4-5",
    "max_tokens": 100,
    "messages": [{"role": "user", "content": "顧客フィードバックを2文で要約してください: [フィードバック本文]"}]
  }'

モデル概要の比較表では、相対レイテンシが最速のHaiku 4.5から、高速のSonnet 5.5、中程度のOpus 5.5、遅めのFable 5.1の順に並びます。この比較は現行ラインナップの中での相対評価で、実際の速度はプロンプト長・出力長・thinkingのeffortで変わります。

モデル相対レイテンシ単価(入力/出力1Mトークン)
Claude Haiku 4.5相対レイテンシ最速単価(入力/出力1Mトークン)$1 / $5
Claude Sonnet 5.5相対レイテンシ高速単価(入力/出力1Mトークン)$2 / $10
Claude Opus 5.5相対レイテンシ中程度単価(入力/出力1Mトークン)$4 / $20
Claude Fable 5.1相対レイテンシ遅い単価(入力/出力1Mトークン)$10 / $50

速度と単価は同じ向きに動きます。速い順に安く、遅い順に高いので、速度を取ると精度の余裕が減る傾向があります。単価そのものの考え方はClaude APIとサブスクの料金比較でも扱っています。

effortを下げる: モデルを替えずに待ち時間を縮める

モデルを替えられないときの手段が、output_config.effortです。公式のeffortの説明では、すべてのトークン数に効くパラメータで、thinkingの有無にかかわらず働くとされています。レベルを下げると、速度とコストを優先する代わりに能力が多少落ちます。

既定値はモデルで異なります。Claude Opus 5・Claude Sonnet 5.5・Claude Fable 5.1はhigh、Claude Opus 5.5はmediumです。既定値を明示しても省略時と同じ挙動になるので、Opus 5.5でmediumを指定しても何も変わりません。

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "output_config": {"effort": "low"},
    "messages": [{"role": "user", "content": "Hello"}]
  }'

モデルごとの公式の推奨も違います。Fable 5.1は既定のhighから始め、評価で品質が保てると確認できたルーチン作業やレイテンシ重視の処理でmediumやlowに下げる、という書き方です。Sonnet 5.5はエージェント用途やレイテンシ重視の用途でなければhighから始め、明確に指定されたエージェント作業ではmediumから始めるとされています。

Sonnet 5.5には、さらにthinkingを絞る設定があります。thinking: {"type": "between_tools"}は最も低いthinking設定で、low・medium・highのeffortで使えます。xhighとmaxでは400エラーになります。between_toolsでは会話の途中でeffortを変えられず、メッセージごとに異なるeffortを指定すると400エラーを返します。一方、Opus 5.5はthinking: {"type": "disabled"}を送ると、どのeffortでも400エラーを返します。thinkingを切って速くするという発想は、モデルによって通りません。

Claude Haiku 4.5は、effortの対応モデル一覧に載っていません。Haiku 4.5で詰める余地は、次の節以降の入力短縮・キャッシュ・ストリーミングにあります。

入力と出力を短くする

処理・生成するトークンが少ないほど応答は速くなります。公式ガイドが挙げる具体策は次のとおりです。

  • プロンプトを明確かつ簡潔にする: 不要な詳細や重複を削ります。Claudeはユースケースの文脈を持たないので、指示が曖昧すぎると意図した論理の飛躍をしてくれません。
  • 簡潔な応答を直接頼む: 冗長な出力が続くなら、短く答えるよう明示します。LLMは単語ではなくトークンで数えるため、単語数の指定より段落数や文数の指定のほうが効きます。
  • max_tokensで上限を置く: 応答の最大長にハードリミットをかけます。

temperatureも短縮の手段として挙がっています。0.2のような低い値は焦点の絞られた短い応答に、0.8のような高い値は多様で長めの出力につながることが「ある」という書き方です。プロンプトの明確さ・出力品質・トークン数のバランスは、値を変えて試して決めます。

長い共通プロンプトはキャッシュでTTFTを縮める

毎回同じ長い指示や資料を先頭に付けるアプリでは、プロンプトキャッシュが効きます。cache_controlで共通の前置きをキャッシュすると、コストとレイテンシが下がります。公式のプロンプトキャッシュの説明では、長い文書で最初のトークンまでの時間が改善しやすいとされています。5分と1時間のキャッシュで、レイテンシの挙動は同じです。

コスト面では、キャッシュ読み取りは基本入力単価の10%です。Fable 5.1は2.5%、Opus 5.5とSonnet 5.5は5%と、モデルにより異なります。出力を減らす手段と違って、共通の前置きが長いアプリほど入力側の待ちを減らせます。

Opusだけの選択肢: 高速モード

Opus 5.5・Opus 5・Opus 4.8には、出力トークン毎秒を最大2.5倍にする高速モードがあります。リクエストにspeed: "fast"を指定し、ベータヘッダーfast-mode-2026-02-01を付けます。プレミアム価格で、リサーチプレビューの扱いです。アクセスにはアカウントマネージャーへの依頼かウェイトリスト登録が必要で、Claude APIのみで提供され、Amazon Bedrockなどでは使えません。公式の指標は出力トークン毎秒なので、最初のトークンまでの時間の短縮は保証されていません。

ストリーミングで見かけの待ち時間を縮める

ストリーミングは、応答全体が完成する前から生成済みの部分を送り始める機能です。リクエストに"stream": trueを付けるだけで有効になり、トークンが届くたびに画面へ出せば、生成時間が同じでも体感の応答は速くなります。

curl -sN https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-5-5",
    "max_tokens": 1024,
    "stream": true,
    "messages": [{"role": "user", "content": "Hello"}]
  }' | grep '^data: ' | sed 's/^data: //' \
    | jq -rj 'select(.delta.type? == "text_delta") | .delta.text'

curlの生の出力はSSE形式で、event:行とdata:行が交互に並びます。jqにそのまま渡すとJSONとして読めないので、data:行だけを取り出してから渡します。公式のCLI(ant messages create --stream --format jsonl)は1行1イベントのJSONで出力するため、jqに直接つなげます。

入れたあとにbaseline latencyだけを測ると、効果が数字に出ません。計測はTTFTに切り替えます。途中でエラーが起きたときの扱いはClaude APIストリーミングのエラー復旧にあります。コード側での組み立てはAgent SDKのストリーミング出力を有効にすると構造化出力とストリーミングの組み込みが扱っています。

どの打ち手がどの待ち時間に効くか

使い分け

効く待ち時間の違い

  • 最初のトークンまで

    モデルをHaikuへ替える、effortを下げる、共通の前置きをキャッシュする、の3つが候補です。effortはthinkingを含む出力トークン全体に効くので、thinkingが長い設定ほど最初の本文までの待ちに響くと考えられます。

  • 完了まで

    出力を短くする、max_tokensで絞る、高速モードで出力速度を上げる、の3つが候補です。出力が長いタスクほど、ここが効きます。

  • 見かけの待ち

    ストリーミングだけです。

試す順序

手順

1つずつ変えて測る

  1. 1

    制約なしの基準を作る

    冒頭で作った精度の出るプロンプトで、モデルもeffortも既定のまま基準の回答を保存します。

  2. 2

    基準を計測する

    time_starttransferと、time_totalからtime_starttransferを引いた値を、同じ入力で数回とります。どちらが長いかで、効く打ち手が分かれます。

  3. 3

    待ち時間に合う打ち手を1つ変える

    上のカードから該当する打ち手を1つ選びます。モデルとeffortは品質への影響も大きいので、変更ごとに基準の回答と見比べます。

1回に1つだけ変えると、どの変更がどれだけ効いたかを切り分けられます。

まとめ

打ち手を選ぶ前に、基準の2つの値のどちらが長いかを測っておきます。ストリーミングを入れたあとは、効果をbaseline latencyでなくTTFTで見ます。

この記事を共有:XはてブLinkedIn