第7部 LLMを使った開発の基礎
第25章LLMはステートレスである
ここからの第7部では、LLMを実際のアプリケーションに組み込んで使う、開発の視点を扱います。最初に 押さえておきたいのが、LLMは「ステートレス」であるという性質です。ここを理解しておくと、チャットが 文脈を覚えているように見えるしくみも、すっきりと理解できます。開発でつまずきやすい点の多くが、この 性質から説明できます。
この部のコードについて
第7部と第8部では、理解を助けるために短いコード例を添えます。いずれも考え方を示すためのイメージで、 中身が分からなくても本文は読み進められます。コードに関心のない場合は、読み飛ばしてかまいません。
25.1ステートレスとは
ステートレスとは、前回のやり取りの状態を内部に保持しないという性質です。LLMは、呼び出しごとに、その時に渡された入力だけをもとに応答します。
ステートレスとは、「状態を持たない」という意味の言葉です。LLMに当てはめると、モデルは前回の呼び出しの 内容を内部に覚えておらず、呼び出されるたびに、その時に渡された入力だけを見て応答する、ということです。 第10章で見たとおり、私たちがLLMを使うのは推論の段階であり、やり取りの内容がモデルの中身(パラメータ)に 取り込まれることはありません。つまり、一回一回の呼び出しは、それぞれ独立しています。
この性質は、Webの世界で以前から知られている考え方でもあります。多くのWebのしくみは、一つ一つの要求を 独立して処理し、前の要求のことは覚えていません。LLMも同じで、呼び出しごとに記憶がまっさらになる、と 考えると分かりやすいでしょう。ここを最初に押さえておくと、後で「なぜ会話の管理が必要なのか」が すんなり理解できます。
25.2LLMは入力をもとに出力を返すだけ
LLMの働きは、入力を受け取って出力を返す、という一回きりの処理です。入力に含まれていない情報は、たとえ前に伝えたことでも考慮されません。
LLMの基本的な働きは、とてもシンプルです。入力を受け取り、それに続く出力を返す。ただそれだけです。 裏を返せば、その時の入力に含まれていない情報は、考慮のしようがありません。たとえ前回の呼び出しで 伝えた内容でも、今回の入力に入っていなければ、モデルはそれを知らない状態で応答します。LLMを、記憶を 持った相手ではなく、毎回まっさらな状態で入力だけを処理する関数のようなものだと捉えると、正確です。
身近なたとえ
毎回記憶がリセットされる窓口の担当者にたとえられます。用件を伝えれば的確に答えてくれますが、 前回何を話したかは覚えていません。続きの相談をしたいなら、これまでの経緯をもう一度説明する必要が あります。LLMとのやり取りは、これに近いものです。
25.3モデル自身は前回の入力を覚えていない
モデルは前回の入力を保持しないため、続きのやり取りを成立させるには、必要な情報を毎回の入力に含める必要があります。
ステートレスであることは、開発のうえで重要な意味を持ちます。モデル自身は前回の入力を覚えていないので、 会話の続きを成立させたいなら、これまでのやり取りを毎回の入力に含めて渡す必要があります。次のコードは、 この点をイメージで示したものです。二回目の呼び出しでは、一回目の内容が渡されていないため、モデルは それを踏まえられません。
reply1 = llm("私の名前はハルです")
# → 名前を受け取った応答が返る
reply2 = llm("私の名前は何でしたか")
# → 前回の入力は渡していないので、名前は分からない
二回目の呼び出しで名前を思い出させたいなら、その情報を入力に含めなければなりません。ここが、多くの人が 最初に戸惑うところです。チャットでは覚えているように見えるのに、コードから素直に呼ぶと覚えていない。 この差を埋めているのが、次章で見る「会話履歴の管理」です。「これまでの情報を渡し直す」という作業を どこかが担っているからこそ、会話が成り立ちます。
25.4ステートレスであることの利点
ステートレスであることは不便なだけでなく、大きな利点もあります。呼び出しが独立しているため、扱いが単純で、多数の利用者を並行してさばきやすくなります。
ステートレスというと不便に思えるかもしれませんが、これは設計上の大きな利点でもあります。呼び出しが それぞれ独立しているため、しくみが単純で、どの呼び出しをどの計算機で処理しても結果が変わりません。 これにより、多数の利用者からの要求を並行してさばきやすくなり、大規模なサービスとして提供しやすく なります。また、状態を持たないぶん、あるやり取りの内容が別のやり取りに紛れ込む心配もありません。
実務メモ:「渡さなければ、ない」を前提に設計する
ステートレスを一言でいえば、「入力に渡していないものは、モデルにとって存在しない」ということです。 利用者ごとの情報、直前のやり取り、参照させたい資料は、必要なら毎回こちらから入力に含める必要が あります。逆にいえば、渡さなければ他の利用者の情報が混ざる心配もありません。アプリを設計するときは、 「この呼び出しに、必要な情報がすべて入っているか」を確認する癖をつけると、覚えていないことによる 不具合を防げます。状態はモデルではなく、こちら側で持つ。これが開発の基本姿勢です。
つまり、「モデルは記憶を持たない」という制約と、「だから会話の管理はこちらで行う」という設計は、 裏表の関係にあります。次の章では、この会話の管理を、プログラム側でどのように行うのかを具体的に 見ていきます。
この章の要点
- ステートレスとは、前回のやり取りの状態を内部に保持しない性質のことです。
- LLMは、その時の入力だけをもとに出力を返します。入力にない情報は考慮されません。
- 続きのやり取りを成立させるには、必要な情報を毎回の入力に含める必要があります。
- ステートレスは、しくみが単純で多数の利用を並行処理しやすいという利点をもたらします。
- 「渡していないものは存在しない」を前提に、状態はこちら側で持つのが開発の基本です。