精度の高いLLMアプリがユーザーに嫌われる、という逆説をよく耳にします。理由はほとんどの場合UXにあります。応答が何秒も沈黙し、エラー時に呪文のようなメッセージが出て、フィードバックを送る手段がない――このような設計では、モデルがどれほど優秀でも人は使ってくれません。本記事ではストリーミングでローディング体験を設計し、エラーを人間の言葉で伝え、フィードバックを摩擦なく収集する、という3本柱でLLMアプリのUXを整えるアプローチを解説します。
LLMアプリUXの特殊性
LLMアプリのUXは、従来のWebアプリと大きく異なる点が3つあります。第一に応答に時間がかかることです。数百ミリ秒で返せる従来のAPIと違い、LLMは数秒単位の応答が当たり前です。第二に応答が非決定的であることです。同じ質問でも毎回微妙に異なる回答が返ります。第三に誤りが混ざる可能性があり、しかもその誤りが流暢な文章の中に紛れていることです。
これらの特殊性は、そのままUX設計の課題になります。長い待ち時間をどう感じさせないか、非決定性を裏切りと感じさせないか、誤りをユーザーにどう伝えるか――この3つを意識しないLLMアプリは、使えば使うほどユーザーの信頼を失っていきます。UXは「見た目」ではなく、アプリへの信頼を積み上げる装置であるという視点が重要です。
ローディング体験の設計
ローディング体験の最重要ポイントは、応答開始までの沈黙をなくすことです。人間の感覚的には「1秒以上の沈黙 = 遅い」と判定されます。ストリーミング表示を実装すれば、最初のトークンが200〜500msで出現するため、同じ処理時間でも体感は劇的に変わります。
Next.js App RouterとServer Actionsでのストリーミング実装例です。
// app/chat/page.tsx
"use client";
import { useState } from "react";
export default function Chat() {
const [text, setText] = useState("");
const [loading, setLoading] = useState(false);
async function send(prompt: string) {
setText("");
setLoading(true);
const res = await fetch("/api/chat", { method: "POST", body: prompt });
const reader = res.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
setText(prev => prev + decoder.decode(value));
}
setLoading(false);
}
return (
<div>
{loading && text === "" && <span className="animate-pulse">考え中...</span>}
<p className="whitespace-pre-wrap">{text}</p>
</div>
);
}
ストリーミング以外にも、長時間処理がある場合は「ツール呼び出し中」「ドキュメント検索中」といった中間状態の表示を組み合わせると、ユーザーが進行状況を把握できて安心感が増します。
エラーハンドリングのUX
エラーメッセージの設計は、ユーザー信頼の分水嶺です。スタックトレースをそのまま表示するのは論外ですが、「エラーが発生しました」という一行だけも不親切です。エラーの種類ごとに、次のような対応を用意すべきです。
| エラー | ユーザーへの表示 | 裏側の処理 | リトライ戦略 |
|---|---|---|---|
| レート制限 | 「混雑しています。数秒後に自動で再試行します」 | 指数バックオフでリトライ | 3〜5回自動 |
| タイムアウト | 「応答に時間がかかっています。もう一度お試しください」 | ログ記録、バックエンドは継続 | ユーザー操作で再試行 |
| スキーマ検証失敗 | (ユーザーには見せず) | 内部でエラー付きリトライ | 2〜3回自動 |
| ハルシネーション疑い | 「この回答は十分に検証されていません」警告 | ガードレール評価 | 手動確認 |
| 不適切コンテンツ | 「その質問にはお答えできません」 | ブロック理由をログ | リトライ不可 |
| ネットワークエラー | 「接続できません。ネットワークをご確認ください」 | 再送キュー | 接続復旧時に自動 |
特に重要なのは、AIの回答に誤りが含まれる可能性を常に示唆することです。全ての回答に免責表示を付けるのは冗長ですが、「出典を表示する」「フィードバックボタンを置く」といった設計で、ユーザー自身が回答を検証できる導線を作ってください。
フィードバック収集の設計
フィードバックはLLMアプリの改善サイクルの命です。評価データセットを自動的に育てるためにも、ユーザーから摩擦なく情報を集める仕組みが必要です。
| 方式 | 収集データ | ユーザー負担 | 精度 | 実装難易度 |
|---|---|---|---|---|
| Thumbs up/down | 二値評価 | 極小 | 中 | 易 |
| 5段階評価 | 順序尺度 | 小 | 中〜高 | 易 |
| 自由記述フィードバック | テキスト | 大 | 高 | 中 |
| 暗黙フィードバック | 滞在時間・再質問・コピー操作 | ゼロ | 中 | 高 |
| 明示的修正 | 「こう答えてほしい」の入力 | 中 | 非常に高 | 中 |
シンプルなThumbs up/downコンポーネントの例です。
// components/Feedback.tsx
"use client";
import { useState } from "react";
export function Feedback({ messageId }: { messageId: string }) {
const [rating, setRating] = useState<"up" | "down" | null>(null);
async function send(value: "up" | "down") {
setRating(value);
await fetch("/api/feedback", {
method: "POST",
body: JSON.stringify({ messageId, rating: value }),
});
}
return (
<div className="flex gap-2">
<button onClick={() => send("up")} disabled={rating !== null}>👍</button>
<button onClick={() => send("down")} disabled={rating !== null}>👎</button>
</div>
);
}
Thumbs downを押されたときだけ「差し支えなければ理由を教えてください」と自由記述欄を開く段階的フィードバック設計は、データ品質と応答率のバランスが取れたパターンです。
UXのベストプラクティス10選
- ストリーミングを必ず実装する――体感速度の改善は無料でできる最大の投資
- プロンプト例を表示する――空のチャット画面は初心者を混乱させる。「何ができるか」の例を3つほど提示
- 中断機能を用意する――長い応答を途中で止められるStopボタンは必須
- 出典・参照を表示する――信頼性とユーザーの検証能力を高める
- 会話履歴を保持する――ページ再読み込みで履歴が消えるのはストレスの源
- 入力制限を明示する――最大トークン数・ファイルサイズをリアルタイム表示
- コピー・ダウンロード機能――生成物を外部で再利用する導線を用意
- 再生成ボタン――非決定性の受け入れ装置。気に入らなければ別案を見せる
- アクセシビリティ――スクリーンリーダーがストリーミング出力を読み上げられるよう配慮
- 多言語対応――モデルは多言語対応でも、UIの文言が英語だけだと国際展開で詰まる
まとめ
LLMアプリのUXは「モデルの特殊性を補う装置」です。応答速度・非決定性・誤りへの対処を前提に、ユーザーが安心して使える導線を設計することが、モデルの品質を活かすための必要条件になります。関連記事としてレイテンシ最適化、プロンプトエンジニアリング入門、ハルシネーション対策、カスタマーサポートAIエージェントもあわせてご参照ください。
よくある質問(FAQ)
Q1. LLMアプリのUXで最も重要なポイントは?
A. ストリーミング応答の実装です。LLMの応答には数秒かかるため、テキストが順次表示されるストリーミングUIが体感速度とユーザー満足度を大幅に向上させます。実装コストも小さいため、対話型アプリでは最初に取り組むべき改善項目です。
Q2. ハルシネーションをユーザーにどう伝えるべきですか?
A. 「AIの回答には誤りが含まれる場合があります」という免責表示と、出典リンクの表示、フィードバックボタン(回答の正確性の評価)を組み合わせるのが効果的です。ユーザー自身が回答を検証できる導線を用意することで、信頼関係を維持できます。
Q3. ユーザーフィードバックの収集方法は?
A. 最もシンプルなのは「いいね/悪いね」のボタンです。より詳細なフィードバックが必要な場合は、5段階評価や自由記述のフォームを用意します。ユーザー負担を最小化しつつ、改善に必要なデータを収集するバランスが重要です。悪い評価時のみ理由入力を促す段階的設計が定石です。