powered by TechFeed
表示モード
Deep Dive

AIエージェントの品質管理、evalだけでは足りない — 「Sam Altmanが登壇します」と嘘をついたモデルが教えてくれたこと

7月1日、Sentryが「AI agent tradeoffs: what evals catch and reading traces reveal」と題した記事を公開した。この記事では、AIエージェントの品質保証においてeval(自動評価テスト)だけでは不十分であり、実際のトレースを読み解くことで初めて見えてくる問題とトレードオフについて詳しく紹介されている。

7月1日、Sentryが「AI agent tradeoffs: what evals catch and reading traces reveal」と題した記事を公開した。この記事では、AIエージェントの品質保証においてeval(自動評価テスト)だけでは不十分であり、実際のトレースを読み解くことで初めて見えてくる問題とトレードオフについて詳しく紹介されている。


「Sam Altmanが登壇します」——モデルが存在しない登壇者を生成した

Sentryのエンジニアは、「AI Engineer World's Fair」向けにスケジュールビルダーを構築した。匿名ユーザーには軽量・低コストのオープンウェイトモデルを、サインアップ済みユーザーにはより高性能なモデルを割り当てる設計だ。ツール呼び出しと丁寧に作り込んだシステムプロンプトがあれば、小型モデルでも幻覚(ハルシネーション)は起きないはず——そう思っていた。

ユーザーが「有名な登壇者は誰ですか?」と質問した。エージェントの内部ルーターはこの質問を「infoパス」に振り分け、利用可能なツールはgetTracksのみだった。このツールが返すのは以下のようなデータだ:

[
  {
    "id": "agentic-commerce",
    "name": "Agentic Commerce",
    "color": "#22c55e",
    "description": "Agentic Commerce sessions at AI Engineer World's Fair 2026 in San Francisco."
  }
]

登壇者情報は一切含まれていない。にもかかわらず、モデルはSam AltmanやJensen Huangがメインステージに登壇すると回答した。さらに「Chris Hagen, Founder of Stability AI」という、元記事が実在を確認できていない人物名まで生成した。

問題を指摘すると、モデルは堂々と反論した:

「私はSam Altmanを"推測"したわけではありません。APIが提供する公式カンファレンスデータから直接取得しました。getTracks関数を呼び出し、各セッションの登壇者情報を取得しました」

getTracksは登壇者情報を返さない。モデルはデータを捏造し、その出典まで捏造した。

トレースを読んで初めてわかること

トレース(AIエージェントがどのツールを何の引数で呼び出し、何を受け取ったかを記録したログ)上には「Used Tools: getTracks」と表示される。ツールが実行されているため、一見すると回答は根拠に基づいているように見える。問題はそのツール呼び出しの中身を開いて初めて発覚する——登壇者情報があるはずの場所に、トラック情報しか返っていない。

eval(本番前に特定の入力と期待出力のペアを使って自動検証するテスト手法)でも検出できたかもしれない。「回答に含まれる人物名がツールの出力やDBに存在するか」を検証するgroundedness(回答がツール出力などの実データに根拠を持っているかを確認する指標)チェックを実装していれば、このトレースはフラグが立っていたはずだ。Sentryが公開しているevals-are-just-testsの考え方に基づき、vitest-evalで実装でき、LLMジャッジも不要だという。

ただし、誰も最初からそのアサーションを書こうとは思わない。モデルが実際にやらかすのを見て、初めて書く価値があると気づく。evalはその後に書き留めるもので、「書く価値がある」と教えてくれるのはトレースを読む行為だ、と記事は指摘する。

evalが答えられないトレードオフ

groundednessチェック(前述のとおり、回答が実データに根拠を持つかの検証)をオープンモデルとClaudeの両方に走らせれば、品質差は数値で出る。コストとレイテンシもトレースに記録されているから、コスト・品質・速度のトレードオフを表にできる。

しかしevalはその中のどこを選ぶかは決めてくれない。「オープンモデルのスコアが低い」とは言える。「匿名ユーザーの会議スケジュール用途ならその低いスコアで許容範囲か」は言えない。

トレースを読み込んだ結果、著者が検討した選択肢は以下だった:

  • 無料枠に良いモデルを使う → 品質は上がるが、安くしたかったトラフィックのコストが増える
  • ルーティングを修正する → 「誰が登壇?」という質問を、答えられないパスに流さない。最も安価で狭い修正
  • プロンプトを締める → ツールが返していない登壇者名・所属を絶対に名乗らせない
  • groundedness evalを書く → 同じ問題が静かに再発しないようにする
  • そのままでいい → 匿名ユーザーへの会議情報回答なら「見つかりません」で十分

結論として著者は、安価なモデルを維持しつつ、ルーティング修正・プロンプト修正・evalの追加を選んだ。この判断ができたのは、十分な数のトレースを読んでいたからだ。

トレースを見つけやすくする実装

記事では、トレースを実際に活用するための実装例も紹介されている。エージェントのテレメトリにconversation_idを付与して全てのツール呼び出し結果をSentryに記録する方法だ:

experimental_telemetry: {
  isEnabled: true,
  functionId: "conference-scheduler.schedule",
  recordInputs: true,
  recordOutputs: true,
  metadata: {
    agent: "schedule",
    model_id: config.id,
    conversation_id: context.conversationId,
  },
},

さらに別の実装例として、最初のユーザーメッセージとトレースへの直リンクをログに残す方法も紹介されている。怪しい挙動があったとき、記憶ではなくテキスト検索で辿れるようにするためだ:

Sentry.logger.info("agent conversation started", {
  conversation_id: conversationId,
  first_message: messages[0].content,
  user_tier: identity.tier,
  conversation_url: `https://your-app.com/admin/conversations/${conversationId}`,
});

エージェントトレースがエラー・パフォーマンスデータ・ログと同じ場所に集約されることで、「回答がおかしい」→「空のクエリ結果や誤ったルーティングを確認する」という流れが繋がる。evalスコアだけでは、そこまで辿り着けない。


evalは「既知の問題の再発」を検知する。しかし「まだ思いついていない問題」は検知できないし、「コストと品質のどちらを優先するか」という判断も下せない。モデルを変えたりジャッジを追加したりする前に、まずトレースを読む——この順序が重要だ、というのが記事の核心だ。

詳細はAI agent tradeoffs: what evals catch and reading traces revealを参照していただきたい。