APIコールの遅延、トークンの過剰利用、出力内容の制御──LLMOpsを考える
ここからは、LLMアプリケーションを開発・運用するポイントを考えてみましょう。LLMは、ユーザーからの入力(プロンプト)を受け取り、出力を生成する推論のプロセスで大規模なニューラルネットワークによって大量の計算が行われます。その特性上、推論APIのコール時に遅延が乗りやすいため、類似の問い合わせであればキャッシュサーバーから返すことでユーザーの体験を向上させるような工夫も考えられます。これはユーザーの体験向上という側面もありますが、トークン数に応じて従量課金されるLLM APIを呼び出す回数を減らすことでコストの削減にも寄与します。
コストの観点でいえば、過剰な使いすぎによって運用コストが上がってしまうことを防ぐために、ある一定以上のトークン利用で制限するような工夫などの導入も検討可能です。また、仮に社外に公開するアプリケーションを作っている場合は、モデルへの入出力には以下の観点で気を配り、実装する必要があります。
- プロンプトインジェクション[3]の対策
- 個人情報などの機密情報をLLMに入力しないような制御
- 公序良俗に反するような出力をLLMにさせないための制御
[3] 不正な入力を混ぜることで、システムを意図しない動作に誘導する、または開発者が禁止している情報を出力させるための攻撃手法のこと
これに加えて、作ったアプリケーションを長く利用してもらうためには、フィードバックを取り入れ継続的に改善していくことが大切です。この適切なフィードバックループを回すためには、加えた変更に対して改善前と改善後で「どこが」、「どれくらい」、「どのように」変わったのかを可能な限り定量的に評価する必要があります。そのためLLMアプリケーションでは、通常のアプリケーションに加え以下のような情報を収集し、活用する必要があります。
- ユーザーの入力と最終的な出力結果
-
最終的な出力結果に至るまでの以下のような情報
- どのような工程を経て最終出力がされているのか
- プロンプトが各工程でどのように変化しているのか
- どこでどの程度時間がかかっているのか
入力とその最終的な出力結果は、ユーザーによる評価(Good/Bad,etc.)やドメインエキスパートによる評価、LLMによる評価[4]に活用されます。この評価結果は、例えばプロンプトを調整した後に出力結果のスコアがどの程度改善したのか、という指標に用いてその調整がどの程度意味があったのかを定量的に知るために役立ちます。
[4]「LLM as a Judge」と呼ばれる評価手法のこと。人手を介さずに評価が可能なため、例えばリリース前に決められた入力セットに対する品質の評価に使用することが可能です。一方で、評価の質もLLMの確率的な振る舞いに依存してしまうため、その点に注意も必要です
また、最終的な出力結果に至るまでの各種情報は、例えばアプリケーションの中でどこがボトルネックになっているのか、エージェントのような構成を取っている場合に開発者の意図通りに動いているのか、などを確認するために利用できます。
LLMの利用がそのアプリケーションにとってコア機能の場合は、LLMがプロバイダー側のサービスダウンなどで使えない場合に備えてリトライや別のLLMへフォールバックするような実装も加えておく必要があるでしょう。
以上のことを踏まえると、LLMを活用したアプリケーションの典型的な構成は下の図のようになります。
LLMアプリケーションの開発・運用における課題
前述した通り、LLMを活用したアプリケーションでは単にLLMのAPIを呼び出すだけではなく、それに付随する多くの課題が伴います。ここではその課題に対するアプローチを深掘りしていきます。特に単一のアプリケーションだけでなく、複数のアプリケーションを開発・運用することを想定すると、よりイメージがつきやすいかと思います。
ライブラリを利用するアプローチ
先ほど述べた課題の多くは特定のアプリケーションに閉じたものではなく、多くのアプリケーションで共通して発生するものです。そのような課題には、大抵の場合楽に実装するためのライブラリが提供されています。今回のケースで具体例を挙げると以下の通りです。
| 課題 | 提供ライブラリ名 |
|---|---|
| リトライやフォールバック | LangChain, LangGraph, LLamaIndex, LiteLLM SDK, Tenacity, … |
| プロンプト管理 | LangSmith, Langfuse, … |
| 外部ツールとの統合 | LangChain, LangGraph, LlamaIndex, Semantic Kernel, Haystack, … |
| キャッシュサーバーとの統合 | LangChain, LlamaIndex, LiteLLM SDK, GPTCache, … |
| レート制限 | LiteLLM SDK, … |
| オブザーバビリティ | LangSmith, Langfuse, OpenLLMetry, OpenLit, … |
単一のアプリケーションに対して実装を行う際も有効的に使えば実装コストを減らすことができますが、複数のアプリケーションに対して実装を行う際には再実装を防ぐという点でさらに効果的に活用できます。
また、ライブラリを活用して実装することで柔軟性が高くなります。実現したいユースケースに合わせて選定することも可能であり、大抵のライブラリでは(限度はありますが、)標準ではサポートされないケースに対して拡張するためのポイントが用意されています。ライブラリを利用したアプローチを図解すると以下の通りです。
