複数LLM比較機能の要件定義とQA観点
同一プロンプトを複数のLLMへ送り、回答を比較する機能について、実装前に決めたい要件とQA観点を整理します。
本稿は公開画面から確認できる一般的な振る舞いを題材にした設計例です。特定サービスの内部APIや実装を説明するものではありません。
対象とする公開上の振る舞い
Wikis AI では、選択したAIモデルに一つの質問を送り、独立してストリーミングされる回答を別パネルで比較し、選んだモデルとの会話を続ける体験が案内されています。
また AI Wiki は、AIトピックの構造化ガイド、元回答の比較、追加質問への導線として公開されています。本稿では前者のライブ比較をQA対象にします。
要件を状態で定義する
複数回答は完了タイミングが異なります。画面全体を loading / done の2状態にすると、部分失敗や再試行を正確に表現できません。
| 対象 | 状態例 | 期待する表示 | 操作 |
|---|---|---|---|
| 比較ターン | draft / submitted / finished | 共通プロンプト、作成時刻 | 新規質問 |
| 回答パネル | queued / streaming / complete | モデル名、本文、進捗 | キャンセル |
| 回答パネル | error / cancelled | エラーの範囲、既存本文 | 個別再試行 |
| フォローアップ | idle / sending / failed | 対象モデル、会話文脈 | 再送 |
重要なのは、失敗をパネル単位に閉じ込めることです。1件が失敗しても、完了済みの回答は読める状態を維持します。
受け入れ条件
AC1: 同じ質問との対応が崩れない
- 送信後に表示中の質問文が暗黙に書き換わらない
- 編集した場合は新しい比較ターンとして作成される
- 各回答にモデルラベルが常に表示される
AC2: 非同期の順序に依存しない
- 完了順が入れ替わってもパネルの対応が崩れない
- 1件のエラーが他のストリームを停止させない
- 再試行は対象パネルだけを初期化する
AC3: 比較と検証を混同しない
- 複数回答の一致を「事実確認済み」と表示しない
- 重要な主張は一次資料や実テストで確認する必要があると分かる
- コピー時にモデル名を含めるか、出典情報を保持する
Playwrightによる説明用テスト
実際のセレクタや通信モックは対象プロダクトに合わせて変更してください。
import { test, expect } from "@playwright/test";
test("1パネルの失敗後も他の回答を保持する", async ({ page }) => {
await page.route("**/compare", async (route) => {
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({ turnId: "t1", panelIds: ["a", "b", "c"] }),
});
});
await page.goto("/compare");
await page.getByLabel("質問").fill("説明用の質問");
await page.getByRole("button", { name: "比較する" }).click();
// 説明用ヘルパーで非同期イベントを注入する想定
await page.evaluate(() => {
window.dispatchEvent(new CustomEvent("answer", {
detail: { panelId: "a", status: "complete", text: "回答A" },
}));
window.dispatchEvent(new CustomEvent("answer", {
detail: { panelId: "b", status: "error", message: "一時的な失敗" },
}));
});
await expect(page.getByTestId("panel-a")).toContainText("回答A");
await expect(page.getByTestId("panel-b")).toContainText("一時的な失敗");
await expect(page.getByTestId("panel-b").getByRole("button", { name: "再試行" })).toBeVisible();
});
この例はそのまま動作する製品テストではなく、検証したい境界を示すものです。SSEやWebSocketを使う場合は、切断、再接続、重複チャンク、順序の逆転も追加します。
テストマトリクス
| ケース | A | B | C | 確認点 |
|---|---|---|---|---|
| 通常 | complete | complete | complete | ラベルと回答の対応 |
| 速度差 | streaming | complete | queued | 途中状態が独立 |
| 部分失敗 | complete | error | complete | 成功回答を保持 |
| キャンセル | cancelled | streaming | complete | 対象だけ停止 |
| 再試行 | complete | queued | complete | Bだけ再初期化 |
完了状態のスクリーンショットだけでなく、イベント順序を変えたテストが必要です。
モバイルとアクセシビリティ
横並びのパネルはモバイルで縦積みになります。次を確認します。
- 共通質問が回答より先に読まれる
- 各カードの先頭でモデル名を確認できる
- 見た目の色だけで状態を区別しない
- キーボードで全操作へ到達できる
- ストリーム全文を
aria-liveで逐次読み上げない - 完了、失敗、キャンセルを短い通知で伝える
非機能要件
負荷、利用制限、タイムアウト、キャンセル、再試行の冪等性、ログ上の個人情報、プロンプト保持期間を明文化します。複数モデル対応は外部依存が増えるため、障害範囲と観測性もパネル単位で持てると調査しやすくなります。
モデル名や利用可能機能は変わり得ます。表示値を固定文字列としてテストするより、設定から渡されたラベルとパネルの対応を検証する方が保守的です。
まとめ
複数LLM比較機能のQAでは、「三つの回答が表示された」だけでは不十分です。
同一質問との対応、独立したストリーム、部分失敗、個別再試行、モバイルの読み順、比較と検証の言葉の境界まで要件にします。ユーザーが違いを見つけ、次の確認へ進めることが、比較UIの本当の完了条件です。