AIを組み込んだアプリの信頼性をどう制御するか

目次

緑のダッシュボードの向こう側

ECサイトの問い合わせ対応にAIエージェントを入れて3か月、という状況を想像してみてください。返品条件を改訂した翌週から、「エージェントに言われた条件で返品できなかった」という問い合わせが増え始めます。調べてみると、エージェントは検索インデックスに残っていた改訂前のFAQを根拠にして、古い条件を自信満々に答えています。APIはすべて200、レイテンシもエラー率も平常。ダッシュボードは緑のままです。 さて、この失敗は事前に想定できたでしょうか? SRE Magazine 008号の「非決定的なワークロードの信頼性を考える」では、生成AIの出力をLLM as a Judgeで評価して、その結果をSLIにするアイデアが示されていました。あれから1年半、状況はどう変わったでしょうか。LLMアプリケーションは単発の応答から、ツールを呼びながら判断を重ねるエージェントに広がってきました。そうなると、評価器を置けば品質は測れるという前提も崩れてきます。上のECサイトの例でも、評価器は「根拠あり」で回答を通してしまうかもしれません。

AIはツールを使うループになった

「AIエージェント」という言葉はいろいろな意味で使われていますが、運用する側から見ると構造はそれほど複雑ではありません。LLMが次の行動を決めて、ハーネスがツールを実行して結果を返し、LLMがまた次を決めます。回答するか、人に引き継ぐか、上限に達するまで、これを繰り返します。 ハーネスというのは、このループを回すLLM以外のすべてのことを指します。ECの例だと、次のような部品でできています。

  • コンテキストの組み立て:システムプロンプト、会話履歴、FAQ検索の結果、ユーザーの注文一覧
  • ツールと権限:FAQ検索、注文照会、返金実行。返金は本人の注文かつ上限額以下に限る
  • 回答前の評価:回答が根拠を持つか、返金額が注文額と一致するか
  • 停止条件と引き継ぎ:ツール呼び出しの回数上限、トークン予算、担当者への引き継ぎ

ここで、観測の対象は二つに分かれます。ハーネスは自分たちが組んだコードであり、計装できるし直せます。LLMはデータベースや決済APIのような、外部の依存先と同じ扱いというのが一般的です(内部でモデル構築までやっているならその限りではありません)。中身は直せませんが、劣化に気づいて切り替えたり、影響を絞ったりはできます。両方見る必要がありますが、制御できるのはハーネス側ということになります。

観測:失敗を事前に列挙できない前提で記録する

冒頭の失敗は事前に想定できたでしょうか?「FAQを改訂したら検索インデックスも更新する、という手順があれば防げた」というのは後からは言えますが、エージェントの失敗はだいたいこの「後から言えること」の集まりです。ありそうな失敗を網羅したリストを事前に作るのは難しいでしょう。 ということで観測は、既知の失敗を検知する仕組みというより、未知の失敗が起きた後に問いを立てられる記録として設計すればよいでしょう。たとえば、1件の問い合わせについて、ハーネスの判断を一続きで残しておきます。

  • どの文書のどの版をコンテキストに入れたか
  • どのツールをどの引数と権限で呼んで、何が返ったか
  • 回答前の評価が何を通して、何を止めたか
  • ループを止めた理由はなにか

冒頭の件が起こった際には、「改訂後に、旧版の文書を根拠にした回答がどれくらいあったか」ということが気になるでしょう。このような質問に対して、それ用の集計を事前に用意しておくことなく、回答が得られればよいわけです。 記録の形式にはもちろん、OpenTelemetryのGenAIセマンティック規約が使えます。エージェントの実行、推論、ツール実行のスパンが定義されていて、出力に対応しているエージェントフレームワークもあります。ただし、2026年11月時点で規約はまだDevelopmentの段階で、正式なリリースもないため、属性名などは変わるかもしれない前提で、計装ライブラリのバージョンを固定して使うとよいでしょう。そして不足などがあれば、アップストリームの議論に参加するのもよいと思います。 外部依存先としてのLLMは、通常の外部APIと同様にREDメトリクス(スループット、エラー率、応答時間)を見る他に、応答品質も記録する必要があり、ここで評価器の出番となります。

評価:既知を確かめ、未知を見つける

評価器を置けば品質は測れますが、やはり完璧ではありません。冒頭の例では、回答を確認するための評価器は回答を通してしまい、最終的にユーザーからのクレームで事態が発覚しました。評価器はFAQに根拠があるかは確かめても、その根拠が古いかどうかまでは見ていなかったのでしょう。 評価には二つのやり方があります。オフライン評価は、既知の失敗に対する回帰テストとして、過去に問題になった問い合わせと期待する振る舞いをデータセットにして、プロンプトやモデルを変えるたびに流します。オンライン評価は本番の記録に対して後から行うもので、まだ名前のついていない失敗のパターンを見つけるのも仕事になります。見つかったパターンは、オフラインのデータセットに加えます。観測して記録を残し、オンライン評価がそこから失敗を拾い、オフライン評価がそれを固定する、というループです。 LLM as a Judgeは、このループの中で使えます。ただし、評価器も非決定的に振る舞うことは忘れないでおきたいところです。評価器のプロンプトやモデルが変われば、出力が同じでもスコアは動きます。評価対象と同じモデルに採点させない、人手でラベルをつけた少数のサンプルで定期的に校正する、といった扱いが必要だとも言われます。 そう、LLM側の品質劣化も評価器で捉えることができます。提供元がモデルを更新すると、ハーネスに何も変更がなくても回答の質が変わることがあります。評価スコアの推移をモデルのバージョンと並べておけば、劣化の原因が自分たちの変更なのか、依存先の変更なのかを切り分けられます。しばしば、モデルやバージョンが同じだとしても挙動が変わることもあるらしく、まさに未知の現象が起こる場所でもあります。 品質にSLOを置くなら、エラーバジェットを使い切ったときに何を止めるかも決めておくとよいでしょう。プロンプトの変更なのか、モデルの切り替えなのか、FAQの一括更新なのか。変更がデプロイ以外から来る以上、止める対象もデプロイだけではありません。

防止:リアルタイム評価と制約

評価で失敗のパターンが見つかっても、それはユーザーに回答を返した後の話です。返す前に止める手段は、大きく二つあります。 一つはリアルタイム評価、つまり評価器を回答の前に置くことです。ただし、上述の評価器をそのまま前に持ってくることはできません。回答の前には、ユーザーが聞き直したといったその後の経過がありませんし、判定に時間がかかれば回答が遅れ、誤判定すれば正常な回答まで止めてしまいます。なので、オンライン評価で見つかったパターンのうち、回答の時点で判定できて、軽く、誤判定が少ないものに絞ることになります。判定を軽くするには、汎用の大きなLLMではなく、判定に特化した小さなモデル(SLM、Splunk Agent ObservabilityのLuna-3、TypeSafe AIのJevなど)を使うやり方もあります。冒頭の例なら、根拠にした文書が最新版かどうかは、版を記録していれば回答の前にも確かめられます。 もう一つは、原因が何であれ影響範囲を絞る制約です。返金の上限額やツールの呼び出し回数、トークン予算などに制約を設けて、問題が解決しなさそうであれば人間にフォールバックさせる、といった方法があります。 どちらも、置いたら終わりではありません。厳しすぎれば普通の問い合わせまで止まり、緩すぎれば止まるべきものが止まりません。止めた記録も観測に残して評価にかければ、調整ができます。

観測が先で、防止が後です。防止はチューニングであり、それが効いているかどうかを教えてくれるのは観測と評価です。

SREの道具はそのまま使えるのか?

Alex Ewerlöfは「AI Reliability Engineering」というブログ記事で、SREの道具箱は他人が書いたコードを確実に動かすために育ってきたもので、AIが生み出すブラックボックスにも同じ道具が効く、と書いています。リトライ、ガードレール、関心の分離といった既存のパターンが、AIの文脈で名前を変えて再発見されている、という指摘です。 ここまで見てきた観測、評価、防止も、SREが扱ってきた監視、SLO、サーキットブレーカーの延長にあります。ただ、正しさがコードの外にある分、何が起きたかを記録できていることが、これまで以上に前提になります。 さて、自分たちのエージェントで、昨日の問い合わせを1件選んでみてください。どの文書のどの版を読んで、どのツールをどの権限で呼んで、回答前の評価が何を通して、なぜループが止まったか。それを記録から一周たどれるでしょうか? たどれるなら、まだ起きていない失敗についても、起きた後に問いを立てられます。たどれないなら、評価器やガードレールより先に、観測から始めましょう。