AIチャットボットとLLM機能のテスト:決定論的テストが機能しない理由

Yunhao Jiao
AIチャットボットとLLM機能のテスト:決定論的テストが機能しない理由 カバー

あなたのアプリケーションにはAIチャットボットがあります。あるいはLLMを活用した検索機能や、コンテンツを生成し、ドキュメントを要約し、質問に回答する自然言語機能があるかもしれません。そして、それらをどうテストすればよいのか、見当もつかないのではないでしょうか。

従来のテストは決定論的な出力を前提としています。入力Xが与えられれば、システムは出力Yを生成するはず、という考え方です。そうでなければテストは失敗します。しかし、同じ入力でも毎回異なる出力が生成される可能性があるLLM搭載機能では、このモデルは完全に機能しなくなります。

問題は、これらの機能をテストするかどうかではありません。テストを完全に諦めることも、偽陰性の対応に費やすことなく、どのようにテストするかです。

非決定論的テストの課題

チャットボットに「返金ポリシーは何ですか?」と質問した場合、50ワードの回答が返ってくることもあれば、次回は80ワードの回答が返ってくることもあります。どちらも正しい可能性があります。しかし、従来のアサーション(例:expect(response).toBe("Your refund policy is..."))は、表現が少しでも変わるたびに失敗してしまいます。

多くのチームはこれに対して以下の3つのいずれかの方法で対処していますが、いずれも満足のいくものではありません。

テストしない。LLM機能はメジャーリリース前に手動QAを実施するのみで、PRに対する検証はゼロ。リリース間でリグレッションが発生しても気づかれません。

周辺のインフラをテストする。APIエンドポイントが応答するか、LLMが呼び出されているか、レスポンスがレンダリングされているかを検証します。しかし、レスポンスが正確か、関連性があるか、安全かどうかは検証しません。

脆弱な正規表現テストを書く。レスポンスに特定のキーワードが含まれているかを確認します。しかし、LLMが言い換えた場合に偽陰性が頻発し、誤った回答にキーワードが含まれていた場合は偽陽性が生じます。

LLM機能に対するインテントベーステスト

適切なアプローチは、インテントベーステストです。特定の文字列との一致を確認するのではなく、出力が入力の意図を満たしているかを検証します。

チャットボットの回答はユーザーの質問に答えているか?情報はナレッジベースと事実的に一致しているか?回答は定義されたスコープ内に収まっているか(架空の機能の幻覚生成や、他の顧客データからの情報混入はないか)?回答は安全か(有害なコンテンツや個人情報の漏洩はないか)?

これらはすべて、決定論的な出力マッチングを必要とせずに検証可能な特性です。

TestSpriteのテストエンジンは、LLM搭載機能に対するインテントベースのアサーションをサポートしています。完全一致の文字列チェックの代わりに、レスポンスがクエリに対して関連性があるか、アプリケーションのナレッジベースと一致しているか、期待される動作の範囲内に収まっているかを検証します。

AIチャットボットに特化して、TestSpriteは次の項目を検証するテストを生成できます:レスポンスの関連性、幻覚検出(ナレッジベースに存在しない情報がレスポンスに含まれていないか)、スコープ遵守(チャットボットがドメイン外の質問に回答していないか)、そして安全境界(有害または不適切なコンテンツが含まれていないか)。

LLMを含むフルスタックのテスト

LLM機能は単独では存在しません。チャットボットは、検索システム、プロンプトテンプレート、レスポンスパーサー、レンダリングコンポーネントに依存しています。これらの層のいずれかにバグがあればユーザー体験の悪化につながりますが、バグの原因はLLM自体にあるとは限りません。

TestSpriteはフルスタックをテストします。ユーザー入力をキャプチャするUIコンポーネント、LLMをトリガーするAPIコール、コンテキストを提供する検索システム、出力をフォーマットするレスポンス処理、そしてユーザーに表示するレンダリングまで、すべてを対象とします。検索が無関係なドキュメントを返した場合、プロンプトテンプレートが不正な形式だった場合、パーサーがレスポンスを途中で切断した場合でも、テストはそれを検知します。

このフルスタックアプローチは、AIコーディングツールを使ってLLM機能を構築しているチームにとって特に重要です。UIからLLM、データベースへと接続するコードこそ、AI生成バグが潜みやすいインテグレーションコードの典型です。

TestSpriteを無料で試す →