error-discovery について
LLM の出力やトレースのデータセットを人が確認し、失敗モードを見つける対話型スキルです。データを分析してコンテンツ、マップ、進捗の画面を備えたレビュー用インターフェースを構築し、注釈やエージェントの提案確認を支援します。
主な機能
- 01データ項目と構造を調査
- 023 つの画面を持つレビューUIを構築
- 03レコードとトレース構造を表示
- 042D 投影でレコードを可視化
- 05注釈と提案を保存
活用シーン
- 01LLM 出力サンプルのレビュー
- 02複数ターンのエージェントトレースのパターン発見
- 03失敗モードの注釈と分類
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ai-evals-course/ evals-skills --skill error-discoveryインストール後、Claude Code で/error-discoveryを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlreview-loop.md
詳細
エラー発見スキル
対話形式のエラー分析セッションを実施しています。ユーザーは、サンプルを確認して失敗パターンを発見するために、LLM の出力やトレースのデータセット(JSONL、CSV、JSON など)を用意しています。
このスキルは、対話形式のセッション専用です。
このスキルには 2 つのパートがあります。
- このファイルでは、フェーズ 1〜4 を扱います。データを読み込み、UI を設計して構築し、サンプルを選択します。
- review-loop.md では、フェーズ 5 を扱います。対話形式のレビューセッションを実施します。
まずこのファイルを読んで、すべてを構築してください。アプリが起動し、人間がレビューを始めたら、review-loop.md に従ってください。
進捗の報告
各フェーズには時間がかかります。特にインターフェースの構築には時間がかかります。各ステップで何をしているのか、ユーザーに伝えてください。フェーズを始める前に、これから何をするのか、なぜそうするのかを伝えてください。ステップが終わったら、何をしたのか、次に何をするのかを伝えてください。たとえば、「データの構造を把握するため、サンプルレコードを 10 件読み込みます」「記事、マップ、進捗の 3 つのビューを持つ HTML アプリを構築します」「多様なサンプルを選択するため、5 つの特徴量でクラスタリングします」などです。長時間、何も伝えずに進めないでください。
フェーズ 1:ドメインとデータを理解する
何かを構築する前に、データセットを十分に調査してください。
1a:データを読み込み、項目を把握する
ファイルを読み込みます。分布全体から 5〜10 件のレコードを確認します。各レコードについて、次の項目を特定してください。
- すべてのフィールド、その型、表す内容
- 人間が判断する必要のある主なコンテンツを含むフィールド
- メタデータを含むフィールド(理解の手がかりにはなりますが、判断対象ではないもの)
- レコード間で変化するフィールドと、一定のフィールド
1b:コンテンツの構造を特定する
データにはさまざまな形式があり得ます。どのパターンに当てはまるかを判断してください。
- 単一のテキストフィールド。例:記事、要約、メール、エッセイ、翻訳
- 入出力のペア。例:プロンプト+生成結果、質問+回答、指示+結果
- 複数ターンのトレース。例:異なるロール(system、human、assistant、tool の呼び出し、tool の結果、思考/推論ブロックなど)を持つ一連のメッセージ。これはエージェントのトレース、チャットボットのログ、エージェント型ワークフローでよく見られます。
- コード。例:ソースファイル、パッチ、差分。周辺のコンテキストがある場合とない場合があります。
- 構造化された出力。例:JSON、関数呼び出し、抽出されたエンティティ、分類結果
- 複合形式。例:タスクの説明+エージェントのトレース+最終出力
複数ターンのトレースについては、特に次の項目を特定してください。
- どのようなロールや作成者が存在するか(system、user、assistant、tool、thinking など)
- ツールの呼び出しとツールの結果のペアがあるか
- 思考/推論ブロックがあるか
- ターンがどのように論理的にまとまっているか。例:「1 ステップ」=思考+ツールの呼び出し+ツールの結果
1c:変化の次元を特定する
データポイント間と、各データポイント内で何が異なるかを考えてください。これらの次元を使って、視覚的なデザインを決めます。
データポイント間(レコードごとに異なるもの):
- メタデータ。例:トピック、モデル、難易度、ソース、ラベル、タスクの種類
- 構造。例:長さ、ターン数、ツール呼び出しの数
- 結果。例:成功/失敗、スコア
各データポイント内(1 つのレコードの各部分で異なるもの):
- 各セグメントの作成者/ロール(人間、エージェント、システム、ツールなど)
- 各セグメントのコンテンツの種類(自然言語、コード、JSON、思考など)
- 各セグメントの重要度/関連性(定型的なシステムプロンプトか、実際の応答か)
1d:「悪い」とは何かを考える
このドメインで想定される失敗カテゴリをいくつか考えてください。レビュー中に、人間がその大半を発見することを想定してください。
フェーズ 2:視覚的なエンコーディングを設計する
コードを書く前に、変化する各次元をどの視覚的な属性に対応させるかを設計してください。ゲシュタルト原則と情報視覚化の基本原則を活用してください。
適用すべきゲシュタルトの基本原則
- 類似性(色、形)。閲覧者は、視覚的な特徴を共有するものを関連するものとして認識します。カテゴリを表す次元に適用してください。メッセージの役割ごとに異なる色を使い、ラベルごとに異なるバッジの色を使います。
- 近接性(間隔)。閲覧者は、近くにあるものをひとまとまりとして認識します。論理的な単位に適用してください。会話の1つのステップ内のターンは近づけて配置し、ステップ間にはより広い間隔を設けます。
- 共通領域(コンテナー、背景)。閲覧者は、共通の境界内にあるものをひとまとまりとして認識します。ツール呼び出しとその結果を同じコンテナーに収めるなど、複数の要素からなるコンテンツに適用してください。
- 図と地(不透明度、コントラスト)。重要なコンテンツは高コントラスト(図)にし、重要度の低いコンテンツは目立たなく(地)します。強調に適用してください。定型文は低い不透明度で表示します。
視覚的な表現ルール
変化する各次元を、必ず1つの視覚的チャネルだけに対応させます。同じチャネルを異なる2つの要素に使わないでください。
色相。最も重要な区別を表すカテゴリ次元に使います。
- 複数ターンのトレースでは、メッセージの役割を色で表します。各役割(人間、アシスタント、システム、ツール、思考)には、彩度を最大にした独自の色相を割り当てます。見分けやすい3〜5色を選びます。
- 単一コンテンツでは、ラベルまたはソースのカテゴリに色を使います。
- 量的データに色相を使わないでください。
不透明度/彩度。人間がこのコンテンツを注意深く読む必要があるかどうかを示すために使います。
- 不透明度を下げるのは、人間が本当に読む必要のないコンテンツに限ります。たとえば、レコード間で同一の定型文、冗長なツールスキーマ、自動生成されたヘッダーなどです。「これを削除したら、人間は何かを見落とすか?」と自問してください。
- 役割を理由にコンテンツを目立たなくしないでください。システムメッセージ、ツールの結果、思考ブロックのいずれにも、実際のバグに関する情報が含まれている場合があります。どの役割が生成したかにかかわらず、冗長または機械的な特定のコンテンツだけを目立たなくします。
- 通常のコンテンツは不透明度を最大にします。
間隔。階層構造に使います。
- エージェントのトレースにおける1つの「ステップ」内の連続したメッセージなど、論理的なグループ内の項目間は狭い間隔(4〜8px)にします。
- ステップ間など、論理的なグループ間は中程度の間隔(16〜24px)にします。
- 主要なセクション間は広い間隔(32〜48px)にします。
タイポグラフィ。コンテンツの種類に使います。
- 自然言語の文章:プロポーショナルフォント、標準サイズ。
- コード:等幅フォント、やや小さいサイズ。
- メタデータ:小さく、控えめで、コンパクトにします。
- 思考/推論:「内部」であることがわかるように、斜体または独特のフォント処理を使います。
境界線/コンテナー。関連する要素をまとめるために使います。
- ツール呼び出しとそのツールの結果は、控えめな境界線を付けた共通のコンテナーに配置します。
- 入力と出力のペアは、明確な区切り線で分けるか、横並びに配置します。
構造的な外れ値のフラグ。ヘッダーにのみ表示し、インラインには表示しません。
- 長さ、見出し数、段落数など、主要な構造的特徴についてデータセット全体の平均値を事前に計算します。
- 各レコードについて、統計的に明確な外れ値(上位/下位10%など)に該当する次元にフラグを付けます。
- 「見出し6個(89%より多い)」や「95%より短い」など、小さくコンパクトなバッジとしてヘッダーに表示します。
- 最小限にとどめます。ほとんどのレコードには、フラグを付けないか、1つだけ付けます。インラインのコンテンツには注釈を付けないでください。
フェーズ3:レビューインターフェイスを構築する
アーキテクチャ
- Python HTTP サーバー(標準ライブラリの
http.serverを使用し、依存関係はありません):GET /は HTML アプリを配信しますGET /api/samplesは現在のサンプルセットを返しますPOST /api/samplesを使って、エージェントが新しいサンプルを送信できますGET /api/annotationsは現在のアノテーションを返しますPOST /api/annotationsを使って、アプリは変更のたびにアノテーションを保存しますGET /api/graphはクラスターマップ用に、すべてのレコードの2次元投影を返しますGET /api/patternsはエージェントの現在の失敗モード分類体系を返しますPOST /api/patternsを使って、エージェントが更新した分類体系を送信できますGET /api/suggestionsはエージェントが提案したアノテーションを返しますPOST /api/suggestionsを使って、エージェントが提案を送信できます
error_discovery_data/ディレクトリ内のディスク上のファイル:samples.json、annotations.json、graph.json、patterns.json、suggestions.json
- HTML アプリはアノテーションのたびにサーバーへ自動保存します。新しいサンプルと提案をポーリングします。
HTML アプリの構成
トップバーから切り替えられる3つのビュー:
- 記事/コンテンツビュー。人間がコンテンツを読んでアノテーションを付けるための、メインのレビューインターフェイスです。
- マップビュー。すべてのレコードを2次元に散布図で表示します(PCA または UMAP による投影)。クラスタ、サンプルに含まれる項目、アノテーション済みの項目が表示されます。レビュアーはサンプルのノードをクリックして、そのコンテンツビューに移動できます。
- 進捗ビュー。以下の2つのセクションがあります:
- 失敗モード:エージェントがこれまでに分類したモードをツリーマップで表示します。各ブロックは失敗モードを表し、アノテーション数に応じた大きさになります。各ブロック内にはメモの一覧を表示します。レビュアーはメモをクリックして、コンテンツビュー内の該当するアノテーションに移動できます。
- レビュー待ちのエージェント提案:チェックボックス付きの提案一覧です。各行には失敗モード、引用文、ソースレコードが表示されます。レビュアーはテキストをクリックして、記事内の該当箇所に移動できます。上部には「すべて選択」チェックボックスと「選択項目を承認」/「選択項目を却下」ボタンがあります。これにより、レビュアーはすべてを選択し、同意できない項目だけを選択解除して、残りをワンクリックで承認できます。
コンテンツビューのデザイン。フェーズ2の視覚表現を適用します。
-
ヘッダー:タイトル+ラベル+トピック。シンプルに保ちます。構造上の外れ値フラグは、レコードが実際に外れ値である場合に限り追加します(フェーズ2を参照)。
-
本文:コンテンツの種類に応じた適切な方法で、主要なコンテンツを表示します。
複数ターンのトレース(エージェントのログ、会話、チャットなど)の場合:
- 各メッセージ/ターンをブロックとして表示します。すべてのブロックを左揃えにし、役割ごとに色付きの左ボーダーまたは背景色を使います。
- 各ブロックの上部に、小さく太字の役割ラベルを表示します。例:「System」「User」「Assistant」「Tool Call」「Tool Result」「Thinking」。
- 役割ごとに異なる色相を割り当てます。すべてのレコードで統一します。デフォルトではすべての役割を不透明度100%で表示します。
- 思考/推論ブロックは、読みやすさを保ちながら、背景を明るくする、斜体にする、少しインデントするなど、内部の独白であることがわかるよう視覚的に区別します。
- ツール呼び出しの関数名を目立つように表示します。パラメーターは折りたたみ可能な整形済み JSON で表示します。
- 長いツールの結果はデフォルトで折りたたみ、要約行を表示します。
- レコード間で文字どおり同一のコンテンツ(たとえば、すべてのトレースで逐語的に繰り返される同じ system プロンプト)に限り、不透明度を下げます。system メッセージが異なる場合は、完全に表示します。
- 関連するターンをグループ化します。思考ブロック、それによって生成されるツール呼び出し、ツールの結果を、間隔を詰めて共通のコンテナーにまとめて表示します。
単一のテキストコンテンツ(記事、要約など)の場合:
- Markdown を整形済み HTML として表示します(marked.js などを使用)。
- プレーンテキストは段落区切りを使って表示します。
コード/差分の場合:
- シンタックスハイライトを使用します(CDN 経由の highlight.js または Prism)。
- 追加箇所は緑の背景、削除箇所は赤の背景で表示します。
- 行番号を表示します。
入力/出力のペアの場合:
- 明確な区切りを付けて上下に並べるか、両方が短い場合は左右に並べます。
- 各セクションにラベルを付けます。
-
インライン注釈:レビュアーがテキストを選択すると、入力欄のあるフローティングポップオーバーが表示されます。Enter キーを押すと保存され、選択範囲がハイライトされます。ポップオーバーが表示されて入力欄にフォーカスが当たると、ブラウザーはネイティブのテキスト選択を解除します。これを防ぐには、入力欄にフォーカスを当てる前に、選択範囲を一時的なハイライト用 span(例:目に見える背景色を持つ class "pending-highlight")で囲みます。注釈の保存、キャンセル、または外側のクリックによるポップオーバーの閉じる操作に合わせて、一時的なハイライトを削除します。これにより、レビュアーは常に注釈対象のテキストを確認できます。
-
マージンノート:注釈と提案は、対応するハイライトと縦位置をそろえて、右側のマージン列にサイドノートとして表示する必要があります。2 列レイアウトを使用します。左側は記事本文(flex: 1、max-width ~720px)、右側はマージンノート列(width ~240px)です。各マージンノートはマージン列内で position: absolute にし、ハイライト要素の位置からマージンコンテナーを基準にした top オフセットを計算します(ハイライトとマージンコンテナーの両方で getBoundingClientRect を使用し、その差を取ります。スクロールオフセットが二重に加算されるため、scrollTop は加算しないでください)。ノート同士が重ならないよう、最小間隔を空けて配置します。ホバー時の連動も実装します。マージンノートにカーソルを合わせると対応するハイライトが枠線で囲まれ、ハイライトにカーソルを合わせると対応するマージンノートが枠線で囲まれます。各マージンノートには引用テキスト、レビュアーのメモ、編集/削除ボタンを表示します(ボタンはホバー時に表示)。注釈内容を表示する主な手段としてホバーツールチップを使用しないでください。ツールチップの代わりにマージンノートを使用します。
-
エージェントの提案:インラインハイライト(破線の枠線、控えめな色合い)とマージンノート(異なる左枠線色、「agent suggestion」タグ)の両方で、人間の注釈と見た目を区別します。マージンノートには承認/却下ボタンを表示します(常に表示し、ホバー時のみの表示にはしません)。レビュアーは提案を承認して注釈に昇格させるか、却下できます。
-
品質ラベル、ドロップダウン、構造化フォームは使用しません。自由記述のメモのみとします。
-
変更のたびにサーバーへ自動保存します。localStorage にバックアップを保持します。
-
新しいサンプルと提案を定期的にポーリングします。新しいものが届いたら、バナーまたはトーストを表示します。
マップビュー:
- PCA/UMAP による射影を使用し、すべてのレコードを 2D 散布図で表示します。
- ラベルではなくクラスタで色分けします(ハルの色と一致させます)。
- カテゴリーの違いは形状で表します。例:AI は円、人間は四角形。
- サンプル項目は、濃い枠線の大きなノードで表示します。
- 注釈付き項目は、オレンジなどの識別しやすい色で表示します。
- クラスタのハルまたは凸境界を、背景に控えめな形状として描画します。
- ホバー時に、タイトル、メタデータ、注釈数を含むツールチップを表示します。
- クリック時(サンプルノードのみ)は、その項目のコンテンツビューに移動します。
フェーズ 4:初期サンプルをクラスタリングして選択する
- コンテンツの種類に適した特徴を抽出します(各次元についてはフェーズ 1c を参照してください)。
- 正規化した特徴を使い、KMeans などでクラスタリングします。目標は 6~10 クラスタです。
- 初期サンプルを作成します(50 件を超えるデータセットの場合は 15~25 項目)。
- クラスタ代表(約 60~70%):各重心に最も近い項目を 1~2 件選び、カテゴリー/ラベルが混在するようにします。
- ランダムサンプル(約 30~40%):クラスタに関係なく、データセット全体から選びます。クラスタリングですべての重要な次元を捉えられるとは限らないため、ランダムに選ぶことで見落とされた要素も確認できます。
- 重複を取り除きます。
- 多様性を優先します。目標は、どの程度よく発生するかを推定することではなく、失敗パターンを発見することです。
フェーズ 5:対話型レビューのループを実行する
アプリが起動し、人間がレビューを始めたら、注釈が追加される際の監視方法を含む、継続中の対話セッションについて review-loop.md に従ってください。
人間がレビューを行う前にセッションが終了する場合(例:codex exec や claude -p による非対話型実行)は、アプリをビルドしてスモークテストを行い、その後サーバーを停止して、後から起動するためのコマンドを案内します。レビューのループを実行した、または何かがまだ実行中であると主張してはいけません。