🤖

コーディングエージェントを使う上で意識したほうがいいLLMの特性

に公開

こんにちは。株式会社アプリボットでクライアントエンジニアをしている@siguma_sigです。

こちらは Applibot Advent Calendar 2025 2 日目の記事になります。

前日は、@yucchiyさんUnity 6.3から使えるSprite Atlas Analyzerを触ってみるでした!

今回の記事では、コーディングエージェントを使う上で意識したほうがいい LLM の特性について、そういった特性がある理由とセットで説明していきます。
昨今のコーディングエージェントはモデルやツールが非常に優れているため、気にせず使用していてもある程度の性能は出ますが、より精度高く望んだアウトプットが出せるようにするため、ぜひ意識してみてください。

私は、ML、LLM を専門としていないため、誤った内容がありましたらぜひ X などを通じてご指摘いただけると嬉しいです。

LLMの特性

そもそもLLMはどう動いているか

LLM の特性について説明する前に、そもそも LLM はどうやって文章を出力しているのかを簡単に説明します。

LLM で入力内容に対して文章が生成される流れは主に下記のようになります。

  1. 入力内容をトークンと呼ばれる単位に分割する
  2. 分割したトークン単位で、埋め込みと呼ばれるベクトルへ変換する
  3. 変換されたベクトル群をもとに、入力内容全体を理解する
  4. 理解した内容を元に、次のトークンとしてあり得そうなものを列挙し、選定する
  5. 新しく選んだトークンと合わせて、再度3から実行する
  6. これをトークン生成が終わるまで実行する

トークンとは、例えば下記のように文章を分割した際の最小単位のことです。

I love gaming →「I」,「love」,「gaming」

分割単位は、トークナイザーによって変わることには注意してください。
これらを対応するベクトル表現に変換します。例えば下記のようなイメージです。

「I」→[1.02, 2.13, 0.23]

これによって、トークンの意味を数値で表しています。

数値で表したトークンは、それ単体だと文脈を含まない意味になってしまうため、これを文脈を含んだ意味になるように計算をしていきます。

文脈を含まない意味とは、例えば「love」というのは一体なにが好きなのかというのは変換した直後のベクトルには含まれていないということです。

これを文脈を含んだ意味になるように、数値を調整したのちに、それに続くトークンとしてあり得そうなものを計算します。

続くトークンとしてあり得そうなものは、複数の候補が確率として表現されます。

例えば、I love gaming に続きそうなものといえば「pc」だったり、「and」だったり、「because」だったりするかもしれません。

その場合、例えば下記のような確率の候補の一覧になります。

pc → 0.65, and → 0.25, because → 0.1

この中から、どれが選ばれるかは LLM へ与えるパラメータに寄りますが、一般的には最も確率が高いものを選ばれることが多いです。

このようにして、続くトークンである「pc」が選ばれたら、元の文章に「pc」を連結して、続きの文章を生成していきます。
これを繰り返すことで文章を生成しているのが、LLM になります。

より詳細に知りたい方は、「Transformer」や「LLM Attention」などのキーワードで調べてみるのが良いでしょう。

非決定性

LLM の特性の1つとして、非決定性があります。
これは、同じ入力に対して出力が一意に定まらないということです。

なぜ定まらないのかというと、先程の説明の中で出てきたとおり、LLM は確率によって、生成する文章が変わるからです。

もし、途中で続くトークンが、先程の例で上げた「pc」ではなく、「and」が選ばれたらその後の文章は全く違うものになるでしょう。

これは、LLM の表現の豊かさを担保している良い点でもありますが、プログラミングや計算のような正確性を求められるような場面ではデメリットになります。

では、どのようにこの非決定性に向き合えば良いかでいうと、決定性が必要な場面は従来通りのプログラムに託すのがおすすめです。

例えば、コーディングエージェントで定期的に行いたい PDF の加工処理があれば、加工処理全体を LLM に任せるのではなく、加工処理ができるプログラムの生成を LLM に任せることをおすすめします。
そうすることで、確実に同じ加工処理のフローが担保できます。

コンテキストウィンドウ

次は、コンテキストウィンドウについて説明します。
まず、LLM の文脈で言うコンテキストとは何かというところから解説します。

コンテキストとは、主に下記のような内容で構成されます。

  • ユーザーからのメッセージ
  • LLM とすでに会話をしていた場合は、そのやり取り全体
  • LLM に対してアプリケーションからデフォルトで与えられるシステムプロンプトなどの追加指示

特に、コンテキストには LLM からの応答やシステムプロンプトなど、ユーザーが入力した情報以外も含まれることには注意が必要です。

続いて、コンテキストウィンドウとは、 LLM が一度に処理できるコンテキストのサイズ のことを指します。

このサイズは、 LLM によってまちまちです。
基本的に、コンテキストウィンドウは扱えるトークン数で表記されます。

例えば、直近よく使われているであろうコーディングエージェントのモデルのトークン数は下記のようになっています。

モデル名 コンテキストウィンドウ
GPT-5.1-codex-max 最大400kトークン
Claude Opus 4.5 最大200kトークン
Claude Sonnet 4.5 最大1Mトークン
Gemini 3.0 Pro 最大1Mトークン

コンテキストウィンドウサイズが大きいものは大量の文章を扱えるため、コンテキストウィンドウサイズは大きいほど望ましいでしょう。
ただし、次に説明する Context Rot などの問題もあるため、たとえウィンドウサイズが大きくても、現在の LLM では扱うコンテキストサイズはできる限り小さくするほうが良いとされています。

Context Rot

Context Rot とは、コンテキスト腐食とも呼ばれ、入力トークンが長くなればなるほどモデルの性能が落ちるという現象です。

一般的なモデルの入力トークンの長さに対しての性能を示すベンチマークとして、 NeedleInAHaystack というものがあります。
このベンチマークでは、非常に長いコンテキストの中から、指定した内容を見つけられるのかというものを測っています。
これによって測れているのは、特定情報を探し出すという能力であり、長文についての理解度を正確に測れているわけではありません。
そのため、現在の LLM はベンチマークで表されている数値以上に、長文が苦手だと考えられています。

ではなぜ Context Rot という現象が起きるのかというと、 LLM の下記のような特性が原因です。

  1. 各トークンは文脈を含んだトークンになるように計算されるが、文章が長くなればなるほどその文脈の意味が希釈される
  2. 学習データ側がそこまで長い文章を含んでいない
  3. 文章内の位置を表す値が長くなりすぎるとうまく位置を表現できなくなる

1つ目については、冒頭の LLM はどう動いているかのところでも説明しましたが、各トークンは文脈を含んだトークンになるように計算がされています。
ただ、文脈というのは、文章が長くなればなるほど色々な文脈が含まれるようになるため、各トークンに含まれている1つごとの文脈が薄くなってしまいます。
それによって、 LLM がしっかりとした文脈を捉えることができず、性能が落ちてしまいます。

2つ目については、書いた通りで学習データ側は長い文章よりも短い文章のほうが多く含まれているため、モデルがうまく扱えていないという現象が起こってしまいます。

3つ目については、冒頭の LLM の説明では省きましたが、実は入力されたトークン化され、ベクトル化された値には文章内の位置を表す情報が含まれています。
この位置を表す情報は、あくまで数値であるため、長くなりすぎると誤差や周期の問題で、相対的な位置をうまく表現できなくなってしまいます。
それによって、 LLM が文章内の位置関係を誤って考えてしまい、性能が落ちてしまいます。

より詳細について知りたい方は、Context Rot や「RoPE」という LLM が位置関係をどう表現しているかのアルゴリズムについて調べてみてください。

ハルシネーション

続いて、聞いたことがある人も多いであろうハルシネーションについて説明します。
ハルシネーションとは、 LLM による回答で、それっぽいけど間違っている回答を生成することです。

では、ハルシネーションはなぜ起きるのかでいうと、主に下記のような原因があると考えています。

  1. 必要な情報が与えきれていない
  2. そもそも必要な情報が取れない
  3. プロンプトが曖昧

1つ目については、LLM には回答してもらうために必要な情報はしっかりと人間側から与える必要があるあります。
例えば、〇〇の機能を実装してほしいという依頼の場合は、〇〇の機能の情報をしっかりと伝える必要があるということです。
冒頭にも説明した通り、 LLM はあくまで確率的に予想して処理を行うため、その予想が正しい方向に行くように、与える情報を考えるのがとても大事です。

2つ目については、 LLM がアクセスできる範囲内に必要な情報がない場合、アクセスするための手段を与える必要があるということです。
1つ目のように、人間がプロンプトを通して伝えられる情報には限りがあるため、 LLM が自律的にそういった情報を取れる環境を作ることが望ましいです。
その手段の1つとして、Tool Calling であったり、 MCP があります。
これらを使うことで、 LLM が人間が普段使っているチャットツールの情報や、資料管理ツールの情報を取ってくることができるようになります。
また、 LLM は知識のカットオフといって、学習データの都合上直近の情報は知りません。
そのため、一般公開されている情報であっても、直近の情報については同様にツールなどを通して伝えることが大切です。

3つ目については、LLM には、指示を明確に、矛盾なくする必要があるということです。
例えば、実装をしてほしいのか、調査だけしてほしいのか。また調査範囲はどの範囲なのかというのを明確に定義して伝える必要があります。
これをうまく伝えるための手法として、プロンプトエンジニアリングというものがあります。
例えば、Few Shot という LLM に対していくつか例を与えることで、出力がその例に沿った形へなるように促すことは非常に有用です。

近年の LLM の性能は非常に向上しているので、ハルシネーションが起きてしまう場合には、モデルの性能を疑うのではなく、まず自分のプロンプトなど与えているコンテキスト側を疑うことが大切だと考えています。

推論

最後に、推論について説明します。
ここでいう推論とは、人間が問題を解くときのように、条件整理→仮説→計算→結論のように過程を踏んで出力を生成する処理のことを指します。

最近の LLM は、この推論と呼ばれるものを強化しているモデルが多く登場しています。
ではなぜ推論が LLM にとって有効なのでしょうか。

これは、推論の過程でモデル自身が、回答が正しい方向に行くようなコンテキストを生成してくれるからです。
問題の答えに対して、一足飛びに出力しようとしてしまうと、コンテキストが不足しており間違った内容を出力してしまう可能性があります。
これを推論を有効にすることで、一歩一歩出力をしていき、必要な情報がその中で自然にコンテキストへ含まれるようになるのです。

推論をより強化する CoT について解説した記事を以前書いているので、ぜひ下記の記事も読んでみてください。

ClaudeCodeの拡張思考モード解説

コーディングエージェントの活用にどう活きるか

ここまで話してきた内容が、普段のコーディングエージェントの活用時にどう活きるかを説明していきます。
今回は私が普段よく使用している Claude Code を基準に記載します。

最も意識すべきは、コンテキストエンジニアリングとも呼ばれる、コンテキスト管理の方法です。
ここまで読んでくださった方はなんとなく理解していると思いますが、 LLM のアウトプットは与えるコンテキストに依存するといっても過言ではありません。
Context Rot であったり、ハルシネーションが起きないように長すぎず、でも内容が不足しすぎていないようにコンテキストを与える必要があります。

Claude Code でいうと、うまくコンテキストを扱うための仕組みが数多く用意されています。

例えば、SubAgent を使うことでメインのエージェントのコンテキストサイズは消費せずに処理を行うことができます。
これにより、調査系のタスクは SubAgent に回すことで、膨大な WebSearch やコード Grep の結果をメインのエージェントに与えること無く、必要なコンテキストだけを渡すことができます。

他にも、割と最近導入された Skills というのはまさにコンテキスト消費を気遣った機能です。
Skills を利用することで、必要なタイミングで必要なコンテキストをエージェントが拾ってくることができるようになります。
例えば、現在の実装が UI に関連するものであれば、そのタイミングで UI の実装に関するルールや情報を Skills を通して入手します。
過去は、CLAUDE.md に大量の情報を記載していましたが、現在であれば常に使わないコンテキストは Skills に寄せるのが良いでしょう。

また、 Claude Code では、Status Line という機能があり、チャットの入力欄の下部に好きな情報を出しておくことができます。
ここに、常に現在のセッションでの消費トークン数を出力しておくことで、コンテキストウィンドウサイズへの意識が上がります。
例えば、消費トークン数が多くなり、コンテキストウィンドウがいっぱいになってきたと感じたら、 /clear コマンドでセッションをクリアすることが有効です。

まとめ

今回は、コーディングエージェントを扱う上で意識したほうが良い LLM の特性について説明しました。
LLM は、現在主流の Transformer というアーキテクチャが提案されてからもまだ10年も経っておらず、非常に進化が早い領域です。
ただ、今回説明した内容は、このアーキテクチャが根本から変わらない限りは役に立つ内容でしょう。

今回の記事で、 LLM の裏側について興味を持たれた方は、ぜひ色々と調べてみてください。

アプリボット

Discussion