LLMを用いたシステム設計で気をつけたいこと

LLM(大規模言語モデル)の導入により、従来の人力に頼っていたパイプラインの自動化が期待されている。しかし、単純に人をLLMに置き換えれば済むというわけではない。LLMはハルシネーションを含め、間違いを含む推論を行いうる。この記事では間違いを含みうるLLMを使ったシステム設計に関して考えたい。

LLMの生成は原理的には決定論的だが、実際にはサービス提供側の都合や計算デバイスレベルでの最適化により、確率論的に振る舞う。つまり、あるタスクを要求した際にミスなく結果が出力されるかどうかは、確率的に決まるということだ。ここでいうミスとは、出力が指定したフォーマットに沿わないことや、ハルシネーションと呼ばれる事実に基づかない内容が含まれることや、そもそも設計者にそぐわない生成が起きることを指す。

こうした確率的に失敗する処理を組み込んだシステムの設計論について考えてみよう。システム設計の理論では、信頼性工学をはじめとする故障率に関する議論が古くから存在する。システムが複数の処理からなるパイプラインで構成される場合、個々の処理の故障率からシステム全体の故障率を推定でき、その回避策も事前に検討できる。この考え方は、現代のAIシステムを構築する上でも非常に参考になる。

たとえば、入力から出力までがシリアルに繋がったシステムを想定する。入力 \(X_0\) から \(X_1, X_2, X_i, \cdots X_N\) まで継起的に処理されるとして個々の処理の生成失敗確率を計算すると、システム全体の成功率は \( P_\text{total} = \prod_{i=1}^{n} p_i \) になる。各タスクの成功率が 90% (\(p=0.9\)) という「そこそこ高精度」なLLM処理を5ステップ直列に繋いだ場合でも、全体の成功率は \( 0.9^5 \approx 0.59 \)、約59% まで低下する。さらに古典的なシステムと異なり、LLMはエラーかどうかの判定が難しい場合も多い。つまり、高度な推論機構であるLLMを使っても全体としては使い物にならないシステムが出来上がってしまう可能性があるわけだ。

この問題に対して、システム全体の信頼性を高めるには、主に3つのアプローチが考えられる。

  1. 生成回数(ステップ数)を減らす: 最新のLLMは、適切なコンテキストを与えれば一度に推論で複数の問題を解ける。処理を不必要に細分化せず、LLMの推論が必要な箇所を適切に集約することで、ステップごとの失敗リスクを抑えることができる。
  2. フォールバック・フィードバックの導入 これはLLMによるコード生成などで多用される手法だ。一度生成させた内容をリンターやコンパイラで機械的にチェックし、エラーが出た場合はその検証結果を添えて再生成(リトライ)させる。
  3. 並列化と選択 一度に複数の候補を生成させ、その中から最適なものを選ぶ。たとえば、1回の失敗率が 30% (\(q=0.3\)) のタスクを3つ並列で走らせると、全体の失敗率は \(0.3^3 = 0.027\)、2.7% まで下がる。この複数の候補生成と淘汰という概念は、Googleの AI co-scientist で扱われているような、中間状態の進化戦略とも通じる。ただし、並列化には「入力が共通であることによるエラーの相関」という問題がある。信頼性工学でいう共通原因失敗(Common Mode Failure)だ。プロンプト自体に誤解を招く表現があれば、並列化したすべてのLLMが同じ間違いを犯す可能性がある。異なるモデルを併用するなどの方法が有効かもしれない。

もちろん、これらの対処法にはトレードオフが存在する。特に「リトライ」や「並列化」は信頼性を向上させる一方で、APIコストの増大やレスポンス速度の低下を招く。LLMの能力を過信せず、検証に基づいた堅実なシステム設計を忘れてはならない。


https://kzmssk.github.io/