◉ANTIGRAVITY LABEN
記事一覧/AIツール
⚙ AIツール/2026-06-24上級

夜通し回したローカルエージェントが、明け方には一手ごとに数秒待たされる — Ollama の応答時間を文脈長から逆算して一定に保つ

夜通し回した Ollama のローカルエージェントが明け方に遅くなる原因を、prompt-eval と generation に分解して実測しました。文脈長と応答時間の関係、num_ctx の設定、直近N手とローリング要約で作業文脈を有界に保つ設計を紹介します。

ollama8gemma412local-llm16latencyai-tools16

✦ プレミアム記事

個人開発で続けているアプリのストア用メタデータを整えるため、夜間にローカルエージェントを回しています。Gemma 4 を Ollama で動かし、手元の機械だけで完結させる構成です。クラウドに出さず、費用もかからない。オフピークの時間帯に黙って働いてくれる、相棒のような存在でした。

ところが、ある朝ログを見て手が止まりました。

序盤の一手は数百ミリ秒で返っていたのに、後半になるほど一手あたりの待ち時間が伸びていきます。明け方には数秒待たされていました。処理した件数は同じ。モデルも同じ。変わったのは、会話に積み上がっていった文脈の長さだけでした。

無人で長く回す前提のエージェントほど、この「後半が重くなる」性質に足をすくわれます。今回はその正体を計測で突き止め、一手の遅延を平準化するまでの手順を残しておきます。

明け方の一手が、なぜ最初の一手より重いのか

ローカルLLMの一回の応答は、大きく二つの時間に分かれます。プロンプト全体を読み込んで内部状態を作る prompt-eval の時間と、そこから新しいトークンを一つずつ生成する generation の時間です。

generation の速度は、出力の長さでほぼ決まります。一方の prompt-eval は、渡したプロンプトの長さに比例して伸びます。会話履歴やツールの出力が積み上がるほど、毎回の prompt-eval が重くなっていきます。

無人エージェントは一手ごとに「これまでの全履歴+新しい指示」を投げ直します。つまり後半の一手は、前半の何倍もの文脈を毎回読み直しているわけです。出力の長さが同じでも、待ち時間だけが静かに膨らんでいく。これが明け方の数秒の正体でした。

応答時間の正体を、prompt-eval と generation に分ける

幸い、Ollama は応答ごとに所要時間の内訳を返してくれます。prompt_eval_count(読み込んだトークン数)、prompt_eval_duration(その所要時間)、eval_count(生成したトークン数)、eval_duration(生成の所要時間)の四つを見れば、遅延がどちらで起きているかを切り分けられます。

時間の単位はナノ秒です。ミリ秒へ直して扱います。

import time, requests
 
OLLAMA = "http://localhost:11434/api/chat"
 
def chat_once(model, messages, num_ctx=8192):
    t0 = time.perf_counter()
    r = requests.post(OLLAMA, json={
        "model": model,
        "messages": messages,
        "stream": False,
        "options": {"num_ctx": num_ctx, "temperature": 0.2},
    }, timeout=600)
    r.raise_for_status()
    d = r.json()
    wall_ms = (time.perf_counter() - t0) * 1000
    prompt_tokens = d.get("prompt_eval_count", 0)
    prompt_ms = d.get("prompt_eval_duration", 0) / 1e6   # ns -> ms
    gen_tokens = d.get("eval_count", 0)
    gen_ms = d.get("eval_duration", 0) / 1e6
    return {
        "text": d["message"]["content"],
        "prompt_tokens": prompt_tokens,
        "prompt_ms": round(prompt_ms, 1),
        "gen_tokens": gen_tokens,
        "gen_ms": round(gen_ms, 1),
        "wall_ms": round(wall_ms, 1),
        "tok_per_s": round(gen_tokens / (gen_ms / 1000), 1) if gen_ms else 0.0,
    }

返り値に wall_ms(実測の往復時間)も入れておくと、計測の取りこぼし(モデルのロード時間など)に気づけます。

一手ごとに記録を残す

切り分けは、一回だけ測っても意味がありません。ループの各手で記録を残し、文脈長と prompt-eval の伸びを並べて眺めます。

import json, pathlib
 
LOG = pathlib.Path("agent_timing.jsonl")
 
def run_step(model, history, user_msg, step):
    history.append({"role": "user", "content": user_msg})
    m = chat_once(model, history)
    history.append({"role": "assistant", "content": m["text"]})
    record = {"step": step, **{k: m[k] for k in
              ("prompt_tokens", "prompt_ms", "gen_tokens", "gen_ms", "wall_ms")}}
    with LOG.open("a") as f:
        f.write(json.dumps(record, ensure_ascii=False) + "\n")
    return m["text"]

このまま素朴に履歴を積み続けると、prompt_tokens が右肩上がりに増え、それに引きずられて prompt_ms も伸びる様子が、ログにそのまま現れます。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦Ollama の prompt_eval_duration と eval_count から、1手ごとの応答時間がどこで伸びているかを数値で切り分ける計測コード
✦文脈長が 2k→12k トークンに伸びたとき prompt-eval が約3倍に膨らむ実測と、num_ctx を意図して固定する判断基準
✦直近N手+ローリング要約+ツール出力の上限切りで、長時間ループでも1手の遅延を約45%平準化する BoundedContext の実装
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

関連記事

⚙ AIツール2026-09-14
二次情報の「10月16日」が一次表に見当たらない — Gemini のモデル廃止日を自分で棚卸しする
Gemini 2.5 系の廃止日として広く出回っている日付が、公式の deprecations 表には載っていませんでした。呼び出しているモデル ID をリポジトリから洗い出し、手元の台帳と突き合わせるところまでを、動くスクリプトで残します。
⚙ AIツール2026-06-17
LM Studio が起動しない・モデルが読み込まれない時の直し方【Mac/Windows・2026年版】
LM Studio が起動しない・モデルが読み込まれない・API サーバーが応答しないときの解決手順を、Mac / Windows 別にまとめた2026年版です。まず試す最短の解決策から原因の分析、解決後の確認方法と再発防止のベストプラクティスまで案内します。
⚙ AIツール2026-06-12
Gemma 4 × Antigravity で組む検索品質の評価ハーネス
RAG の回答が時々ズレる問題を数値に置き換える評価ハーネスの作り方。30問のゴールデンデータセット、recall@5・MRR・nDCG の実装、Gemma 4 による忠実性審査、pytest の回帰テストまで、ローカル環境の実測値と共に共有します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます