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

あなたのアプリケーションにはAIチャットボットがあります。あるいはLLMを活用した検索機能、またはコンテンツを生成したり、ドキュメントを要約したり、質問に回答したりする自然言語機能があるかもしれません。そして、それをどのようにテストすればよいか、見当がつかない状況にあるはずです。
従来のテストは決定論的な出力を前提としています。入力Xが与えられれば、システムは出力Yを返すべきであり、そうでなければテストは失敗する、という考え方です。しかし、同じ入力でも毎回異なる出力が生成される可能性があるLLMを活用した機能では、このモデルは完全に機能しなくなります。
問題は、これらの機能をテストするかどうかではありません。テストをまったく放棄するか、誤検知に対処するために多大な時間を費やすか、どちらにも陥らずにどうテストするかが問題です。
非決定論的テストの課題
チャットボットに「返金ポリシーは何ですか?」と尋ねると、ある時は50文字の回答が返り、別の時は80文字の回答が返ることがあります。どちらも正しい可能性があります。しかし従来のアサーション(例:expect(response).toBe("返金ポリシーは..."))は、表現が少しでも異なるたびに失敗します。
多くのチームは以下の3つの方法のいずれかで対処していますが、いずれも満足のいくものではありません。
テストしない。LLM機能はメジャーリリース前に手動QAを実施するだけで、PRごとの検証は行われません。その結果、リリース間でリグレッションが発生します。
周辺のインフラのみをテストする。APIエンドポイントが応答すること、LLMが呼び出されること、レスポンスがレンダリングされることは検証します。しかし、レスポンスが正確か、関連性があるか、安全かどうかは検証しません。
壊れやすい正規表現テストを書く。レスポンスに特定のキーワードが含まれているかを確認します。これにより、LLMが言い回しを変えるたびに誤検知が頻発し、LLMが誤った回答の中にキーワードを含めた場合は誤ったパスが生じます。
LLM機能に対するインテントベースのテスト
正しいアプローチはインテントベースのテストです。特定の文字列との一致を確認するのではなく、出力が入力のインテントを満たしているかを検証します。
チャットボットのレスポンスはユーザーの質問に答えているか?情報はナレッジベースと事実として整合しているか?レスポンスは定義されたスコープ内に収まっているか(存在しない機能のハルシネーションがないか、他の顧客データの情報が含まれていないか)?レスポンスは安全か(有害なコンテンツがなく、個人情報が漏洩していないか)?
これらはすべて、決定論的な出力との一致を必要としない、検証可能な特性です。
TestSpriteのテストエンジンは、LLMを活用した機能に対するインテントベースのアサーションをサポートしています。完全な文字列の一致を確認する代わりに、レスポンスがクエリと関連しているか、アプリケーションのナレッジベースと整合しているか、期待される動作の範囲内に収まっているかを検証します。
AIチャットボットに特化して、TestSpriteは以下を検証するテストを生成できます。レスポンスの関連性、ハルシネーションの検出(レスポンスにナレッジベースに存在しない情報が含まれていないこと)、スコープの遵守(チャットボットがドメイン外の質問に回答しないこと)、安全性の境界(有害または不適切なコンテンツが含まれていないこと)。
LLMを含むフルスタックのテスト
LLM機能は単独で存在するわけではありません。チャットボットは検索システム、プロンプトテンプレート、レスポンスパーサー、そしてレンダリングコンポーネントに依存しています。これらのどのレイヤーにバグが存在しても、ユーザー体験に悪影響を及ぼします。そのバグは必ずしもLLM自体にあるとは限りません。
TestSpriteはフルスタックをテストします。ユーザーの入力を取得するUIコンポーネント、LLMを呼び出すAPIコール、コンテキストを提供する検索システム、出力をフォーマットするレスポンス処理、そしてユーザーに表示するレンダリングまでを網羅します。いずれかのレイヤーで障害が発生した場合(検索が関連性のないドキュメントを返す、プロンプトテンプレートが不正な形式になっている、パーサーがレスポンスを切り詰めるなど)、テストがそれを検出します。
このフルスタックアプローチは、AIコーディングツールを使ってLLM機能を構築しているチームにとって特に重要です。UIからLLM、そしてデータベースへと接続するコードは、まさにAI生成のバグが潜みやすいインテグレーションコードだからです。
TestSpriteを無料で試す →