本番ログからLLM回帰テスト用データセットを作る最小構成|収集からCI接続まで

本番ログからLLM回帰テスト用データセットを作る最小構成|収集からCI接続まで

LLM(大規模言語モデル)やエージェントを本番運用していると、「昨日は動いていたのに、今日はズレる」場面に出くわすことがあります。プロンプトを1行変えた・モデル版が上がった・索引を更新した、といった変更の直後に回答の当たりがズレる...ログを追っても、モデル起因なのかプロンプト起因なのか一発では切り分けられず、結局ロールバックに頼った経験があるチームは少なくないのではないでしょうか。

手動で失敗例を集めてテストケース化する運用は、トラフィックが増えた時点で続かなくなる傾向があります。失敗をテスト資産に変えるなら、手で集め始める前に「本番ログから失敗候補を自動抽出し、評価データセットへ変換してCIゲートに接続する」レールを先に敷くほうが、チームの負荷を下げやすいと言えます。

この記事では、以下の6工程からなる最小構成を、PII(個人識別情報)マスキングやアクセス制御の設計観点も含めて整理します。

  1. 収集 ― trace_idとバージョン情報の付与
  2. 抽出 ― 決定的シグナルのフィルタ
  3. 正規化 ― 再実行できる評価レコードへの変換
  4. ラベリング ― 最小の人手で合否を回す設計
  5. データセット化 ― 重複排除・版管理
  6. CI接続 ― PRゲートと夜間バッチの二段構え

結論:本番ログを回帰テスト資産に変える最小構成

最小構成の定義(6つの成果物)

ここで扱うのは「本番ログを回帰テストに変えるには、最低何を作ればよいか?」です。

次の6つの成果物が揃えば、本番ログから評価データセットを経てCIゲートまでの導線が回る状態になるはずです。

  1. 収集基盤 ― 本番ログにtrace_idとバージョン情報を付与し、再現に必要な入出力を構造化して残す仕組み
  2. 抽出ルール ― エラー・タイムアウト・スキーマ違反など、決定的な失敗候補を自動で拾うフィルタ群
  3. 正規化パイプライン ― ログ断片を「再実行できる1件(評価レコード)」に変換する処理
  4. ラベリング運用 ― 合否判断を最小の人手で回すためのレビューフローと合意基準
  5. 評価データセット ― 回帰テスト用にフォーマット・分割・重複排除されたケース集合
  6. CIゲート接続 ― PRマージや定期実行で評価を走らせ、基準未達をブロックまたは警告する仕組み

評価(eval)は軽量なE2Eテストの枠組みとして、OpenAIのエージェント評価ガイドでも説明されています。

  1. prompt(入力)
  2. captured run(実行記録)
  3. checks(検証)
  4. score(採点)

要は「実行を記録して、ルールで採点する」という流れを、上の6つの成果物で最小限に組み立てるイメージです。

最初から全工程を完成させる必要はありません。まず収集と抽出だけ通し、ラベリングとCI接続は段階的に育てる形で進めると無理がありません。高度な自動抽出、重み付け、レビューUI、データ品質監視といった拡張は、最小構成が回ってから検討すれば十分です。特定のベンダーやツールに依存しない一般的な設計観点を中心に、以降のセクションで各工程を掘り下げます。

最小を支える前提(用語・責任・境界)

ここで扱うのは「なぜ実装より先に、用語と責任と境界を固めるのか?」です。

本番ログを評価資産に変える作業は複数のロール(PdM・テックリード・運用・情シス)にまたがります。用語がずれたまま進めると、「失敗」の定義一つで手戻りが発生しがちです。

最低限この3つを先に合意しておくと、後工程がスムーズになります。

  • 用語定義 ― 「失敗ケース」「評価レコード」「回帰テスト」「品質ゲート」など、記事内でも使う用語の意味をチーム内で1行ずつ揃えます
  • 責任分界 ― 誰が抽出ルールを決め、誰がラベリングし、誰がゲート基準を承認するか。最小構成では「決める人」と「回す人」の2ロールで始められます
  • データ境界 ― 何を残し何を捨てるか。とくにPIIマスキングや機密データの扱いは、ログ設計の時点で方針がないと後から修正コストが跳ね上がります

「目的定義→データセット収集→メトリクス定義→評価実行→継続評価」という流れはOpenAIの評価ガイドでも示されており、最初の「目的定義」を飛ばすと後工程が空回りしやすい構造になっています。

ここで決めた前提はあくまで初期合意です。運用が回り始めれば定義は更新されていくものなので、最初の完璧さよりも「合意が存在する状態」を作ることが優先になります。

作っておくと安心なチェックリスト

ここでは「結局どこから手をつければよいのか?」を整理します。
目的としては、最低限の導線が動いている状態をゴールに、手順の順序と到達点を決めることです。

以下の順序で進めると手戻りが少ないはずです。

  1. 用語・責任・境界の合意 ― 用語定義・責任分界・データ境界の3点を先に固める
  2. 収集の最小設定 ― trace_id付与とバージョン情報の記録を既存ログ基盤に追加(ログ設計の時点で、後から評価入力を再構成できる粒度を確保しておくのが重要です。具体的にはprompt、取得コンテキスト、ツールI/O、モデル設定など)
  3. 抽出ルールの初版 ― 例外・タイムアウト・スキーマ違反など決定的シグナルだけでフィルタを組む
  4. 正規化とラベリングの素振り ― 抽出された失敗候補を5〜10件だけ手で評価レコードに変換し、合否の判断基準を仮決め
  5. CIへの仮接続 ― 評価スクリプトをCIパイプラインに組み込み、まずは警告のみで回す(ブロッキングへの昇格は運用データが溜まってから)

開発段階からログを十分に取得し、ログから評価ケースを採掘できる状態を早期に作ることは、OpenAIの評価ベストプラクティスでも推奨されています。 手動で失敗例を都度集める運用より先に、この導線を敷いておくほうが、チームの負荷を下げやすい傾向があります。

到達点の目安は「本番で起きた決定的な失敗が、翌日のCIで警告として表示される」状態です。精度や網羅性の改善はこの最小ループが回ってから段階的に進めます。

なぜ手動の失敗ケース収集は続かないのか

でも、そもそもなぜ「人が気づいたら報告する」運用では失敗ケース抽出が早い段階で止まるのか、その構造的な理由を整理します。

出力が揺れる・壊れても気づきにくい

LLMを組み込んだ機能が厄介なのは、非決定的(同じ入力でも出力が毎回揺れうる)な点です。OpenAIのChat Completions APIドキュメントでも、デフォルトでは出力が非決定的であると明記されています。

再現テストの前提が「同じ入力→同じ出力」に依存していると、LLMベースの機能では成り立ちません。

もう一つ押さえておきたいのがサイレント回帰です。モデル提供側の更新やインフラ変更によって、こちらが何も変えていないのにアプリの挙動が変わる現象を指します。2026年のarXiv研究でも、LLMプロバイダのモデル更新がアプリ挙動を予告なく変え、ユーザー苦情で初めて検知される事例が報告されています。

非決定性とサイレント回帰は「たまに起きる例外」ではなく、LLMを使う以上は常態と考えたほうが自然です。この前提を共有しないまま手動収集を始めると、「前は動いていたのに」という報告が増えるだけで原因の切り分けが進まない状況に陥りがちです。

失敗の定義は「次のアクションが決まる粒度」で

失敗ケース抽出で最初にぶつかるのは、「何をもって失敗とするか」という線引きです。失敗分類(taxonomy)は次のアクションが決まる粒度から始めるのが実用的です。

LLMの出力は「正解/不正解」の二値で割り切れない場面が多くあります。たとえば、回答内容は正しいがフォーマットが崩れている、情報は網羅しているが冗長すぎてユーザーが離脱した、といったケースです。「不正解」とだけ記録しても、プロンプトを直すのか、後処理を変えるのか、モデルを切り替えるのかが決まりません。

まずは「このラベルが付いたら、チームの誰が・何を・どう直すか」が1つ決まる粒度を目指すとやりやすくなります。粒度が細かすぎるとラベリングコストが跳ね上がり、粗すぎると対処が曖昧なまま放置されがちです。わずかなプロンプト変更でも性能が大きく変動し得る以上、「プロンプト起因」「モデル起因」「外部データ起因」くらいの軸は初期段階で分けておくと、対処の振り先が明確になります。

失敗定義は一度決めたら終わりではなく、運用しながら粒度を見直す前提で始めるくらいがちょうど良いでしょう。最初から完璧な分類体系を目指すと、定義の議論だけで数週間が過ぎることもあります。

失敗ケースの手動収集が破綻する3要因(再現・優先度・属人化)

手動で失敗を集める運用がなぜ数週間で止まるのか。再現待ち・優先度迷子・属人化の3つが連鎖して運用が停止するパターンが多いです。

再現待ち: 非決定性がある以上、「さっき起きた失敗をもう一度出してください」と言われても再現できないことがあります。ログはあるけど原因追えないという声が現場で出るのは、入力だけ残っていても実行時のモデル版やコンテキストが記録されていないからです。再現できないチケットは優先度が下がり、そのまま塩漬けになりがちです。

優先度迷子: 手動報告が増えると、「どの失敗から対処するか」の判断基準がないまま滞留しがちです。影響範囲もユーザー数も把握できていない状態では、声の大きい報告者のチケットが先に対処され、実際の影響度とは乖離した優先順位になることがあります。

属人化: 失敗かどうかの判断が特定メンバーの暗黙知に依存し始めると、その人が不在のときに判断が止まります。トレースがないと議論が進まないのと同じ構造で、判断基準が共有されていなければ、報告しても「これは失敗なのか仕様なのか」で議論が空転します。

この3要因は独立ではなく連鎖することもあります。再現できないから優先度が決まらない、優先度が決まらないから誰も手を出さない、手を出す人が固定化して属人化する——この循環に入ると、手動収集は自然消滅します。

例外:手動でやって良い場面とやめる判断

「失敗ケースの手動収集はすべて悪」というわけではありません。本番トラフィックが少ない初期段階やPoC段階では、手動で十分なケースもあります。

週に数件しかリクエストがない機能であれば、失敗を1件ずつ目視で優先度判断(トリアージ)しても運用は回るはずです。チームが2〜3人で、全員がプロンプトと出力の文脈を共有できている状態なら、属人化のリスクも限定的です。

ただし、以下のサインが出たら手動運用の限界が近いと言えるでしょう

  • 同じ失敗パターンが2回以上報告されているのにテストケース化されていない
  • 報告チケットが1週間以上未処理で溜まっている
  • 「これは失敗か仕様か」の判断で毎回同じ人に聞きに行っている

こうした兆候が複数重なったタイミングが、自動抽出のレールを敷き始める判断ポイントです。

手動→自動の切り替えは段階的で構いません。最初は決定的な失敗(例外やタイムアウト)だけ自動抽出し、判断が必要なケースは引き続き手動でトリアージする、という混在期間を設けると、移行の負荷を分散できます。

全体像:本番ログから回帰テストになるまでの流れ

失敗ケースの手動収集が続かない構造を確認したうえで、次は失敗ケースを回帰テスト資産に変える6工程の入出力のつながりを整理します。収集からCIゲートまでの流れを、各工程の役割と受け渡し単位で見ていきます。

収集:trace_idとバージョンをまず通す

では、後工程で失敗を再現・分類するために、最初に何を通しておけばよいのでしょうか。

すべてのリクエストに相関ID(trace_id)と版情報(モデル名・プロンプトハッシュ・ツールバージョン)を付与するのが起点になります。失敗を見つけたあとに「どの版で何が起きたか」をたどれないと、抽出しても原因が追えないためです。

「トレースがないと議論が進まない」という声が現場で出がちですが、裏を返せばtrace_idと版情報さえあれば議論の土台ができます。LangSmithでは本番トレースからデータセット例を生成するパターンが一般的とされており、その前提としてトレーシング設定が必要だと説明されています。

具体的には、まずリクエストの入口でtrace_idを発行し、モデル呼び出し・ツール呼び出し・レスポンスの各ステップに同じIDを伝搬させます。版情報はデプロイ時に環境変数やタグとして埋め込んでおくと、ログ検索だけで絞り込めます。

なお、trace_idにユーザーIDやセッション情報を直接埋め込まない設計が無難です。相関IDはあくまで技術的な紐付けに使い、個人識別情報は別レイヤーで管理する形にしておくと、後からPII対応で困りにくくなります。

抽出:決定的シグナル+層化サンプリング

ここで扱うのは「どのログを失敗候補として拾い、どのログを正常サンプルとして残すか」です。

抽出は2系統に分けて設計するとやりやすいです。1つは決定的シグナル(例外・タイムアウト・スキーマ違反など、判断に迷わない失敗)の全量取り込み。もう1つは、正常応答を含む全トラフィックからの層化サンプリングです。

決定的シグナルだけでは「静かに劣化しているが例外にはならないケース」を取りこぼすためです。正常応答の中にも品質が低下した応答が混ざることがあり、分布を維持したサンプルがないと比較の基準がずれていきます。たとえばDatadogは本番トレースからデータセットを直接生成し、現実のシナリオで変更を検証できる機能を提供しています。こうしたツールの活用を視野に入れつつも、抽出ルール自体はツール非依存で設計しておくと移行が楽です。

サンプリング比率は最初から完璧を目指さなくて大丈夫です。まずは決定的シグナルの全量+正常応答の一部で始め、レビュー負荷を見ながら調整していく形がやりやすいです。比率の初期値はチームのレビュー可能件数やコスト上限から逆算し、ベースライン計測後にキャリブレーションする流れが自然です(一例として1〜5%程度から始める方法がありますが、環境依存です)。オンライン評価(本番中のリアルタイム監視)は「異常検知」に寄せ、オフライン評価(回帰テスト)は「再現と比較」に寄せる、という役割分担を意識すると設計がぶれにくくなります(LangSmithの評価ドキュメントに詳しく記載されています)。

正規化:評価レコードという最小単位に落とす

「ログ断片をどう加工すれば、再実行できる1件になるか」を整理します。

正規化の目標は「評価レコード」と呼べる最小単位を作ることです。評価レコードとは、入力(プロンプト+取得コンテキスト)・出力(モデル応答)・期待結果または判定基準・版情報(モデル/プロンプト/ツール/索引バージョン)を1件にまとめたものを指します。

ログのままだと形式がバラバラで、CI上で自動実行する際に毎回パースロジックが必要になるためです。形式を揃えておけば、評価スクリプトは1種類で済みます。Vertex AIのGen AI evaluationでもルーブリック(pass/fail)による評価を提供しており、評価データセットを本番ログからサンプリングして作成できることが示されています。

具体的には、抽出済みログから入力・出力・版情報を取り出し、評価レコードのスキーマに変換します。外部API呼び出しの結果やRAGの取得結果がある場合は、それも根拠(context)として同梱します。

ここで気をつけたいのが、ログ設計の時点で「評価入力を再構成できる粒度」を取っていないと、正規化の段階で情報が足りず再実行できないケースが起きる点です。プロンプト全文・取得コンテキスト・ツールの入出力・モデル設定(temperatureやseed)を収集段階で残しておくことが、正規化を成立させる前提条件になります。

CI:PR用と夜間用の二段構えにする

品質ゲートをCIに接続するとき、速度とコストと誤検知のバランスをどう取るかが悩みどころになりがちです。

PR(プルリクエスト)マージ時に回す軽量チェックと、夜間やリリース前に回すフルセット評価の二段構えが基本形です。

評価データセット全件をPRのたびに回すとコストと待ち時間がかさみ、開発者がゲートを迂回し始めるためです。PRゲートでは件数を絞った高速チェック(致命的な回帰の検知)に集中し、フルセット評価は夜間バッチやリリース候補ビルドで回す形にすると、速度を犠牲にせず網羅性も保てます。

PRゲートにはコアケース(過去に致命的な失敗が出たケース)を件数で絞ったサブセットを割り当てます(一例としてレビュー可能件数から逆算して30〜50件程度をたたき台にする方法がありますが、環境依存です)。夜間バッチには全件セットを回し、結果をダッシュボードに集約します。どちらも「ブロッキング(マージ/リリースを止める)」と「警告(通知だけで止めない)」を分けておくのが運用上の基本です。

最初から厳格なブロッキングにすると誤検知でリリースが止まり、ゲート自体が形骸化する傾向があります。段階導入として、まずは警告のみで始め、誤検知率が安定してからブロッキングに切り替えるのが無難です。責任分界としては、ゲート基準の設定はPdM/テックリードが持ち、誤検知のトリアージは運用チームが担う形にすると意思決定が詰まりにくくなります。フレーク対策や対応手順の詳細は「CI/ゲート接続」セクションで扱います。

収集:残す項目と残さない項目(PII/機密)

全体像で工程間のつながりを確認したので、最初の工程である収集の設計に入ります。ログ設計で問われるのは「何を記録するか」ではなく「何を記録しないか」です。PIIマスキングや機密除外の方針が曖昧なまま収集を始めると、後工程の抽出・正規化で使えないログが溜まるか、逆にインシデントの種を自ら仕込むことになります。ここでは、失敗の再現と原因切り分けに必要な最小メタデータと、ログに残してはいけないデータの線引きを整理します。

残すログ項目:後から再現できる最小メタデータ

「ログはあるけど原因追えない」という状況を避けるために、再現と原因切り分けに必要な項目を先に決めておきたいところです。

ここでの対象はLLM/エージェントの1リクエスト(1トレース)単位の記録です。以下の粒度が最小ラインになります。

再現に必要

  • trace_id / span_id: リクエスト全体と各ステップを一意に紐づける相関ID
  • 入力 + 出力: ユーザークエリ、取得コンテキスト、モデル応答
  • 版情報: モデル名・バージョン、プロンプトテンプレートのID+ハッシュ

あると強い(原因切り分け・コスト可視化)

  • タイムスタンプ: リクエスト開始・終了
  • ツール呼び出しの入出力: 外部APIや検索を呼んだ場合の引数と返却値
  • トークン消費量 / レイテンシ / seed値: コスト異常検知、非決定性の幅を狭めるため

ログ設計の時点で「評価入力を再構成できる粒度」を取っていないと、失敗を抽出してもテストケースに変換できません。特にプロンプトテンプレートの版情報とツールI/Oは見落とされやすい項目です。

入力・出力にユーザーの個人情報が含まれる場合もあります。この扱いは後述のPIIマスキングで処理するため、ここでは「記録対象として必要」という判断と「そのまま保存してよいか」の判断を分けて考えておくとスムーズです。

残さない項目:ログに入れると危険なデータ

ログに直接書き込むと危険なデータは何か。

ログ基盤は運用チーム・開発チームなど複数のロールがアクセスする共有領域です。以下のデータはログに平文で記録しない設計が原則になります。

  • アクセストークン / APIキー / パスワード: 流出時の影響が即座に発生する認証情報
  • 暗号鍵 / 署名鍵: 暗号化の意味を失わせるデータ
  • 機微な個人情報: 医療記録、金融口座番号、マイナンバーなど、法令やポリシーで保護対象とされるもの
  • セッショントークン / Cookie値: 再利用によるなりすましリスクがあるもの

アクセストークンや機微PII、パスワード、暗号鍵などはログに直接記録せず、削除・マスク・サニタイズ・ハッシュ化・暗号化等で扱うことがOWASP Logging Cheat Sheetでも推奨されています。

注意点として、「機微かどうか」の判断は組織のデータ分類ポリシーに依存します。一律のリストで済むものではないため、データ分類の基準を先に決め、ログ設計に反映する順序が自然です。

個人情報(PII)/機密の防波堤:書き込み時マスキング(write-side)と二層保管

「読み出し時にマスクすればいい」という設計と「書き込み時にマスクする」設計では、リスクの性質が変わります。ここではその違いと、二層保管の考え方を整理します。

PII マスキングのタイミングは大きく2つ、read-side(閲覧時)と write-side(書き込み時)に分かれます。永続化前の write-side でマスキングする設計のほうが、結果としてリスクを小さく保ちやすくなります。

read-side マスキングだと、ログ基盤に生データが残るため、アクセス制御の不備やバックアップ経由での漏洩リスクが残りやすい傾向があります。write-side であれば、永続化された時点で機微情報が除去されているため、基盤側の防御が破られた場合でもダメージを限定しやすくなります。

ただし、write-sideマスキングだけでは「マスク前の生データが必要になるケース」(重大インシデントの調査など)に対応できません。そこで二層保管という設計が考えられます。

  • sanitized層: マスキング済みのログ。開発・運用チームが日常的にアクセスする領域
  • raw層: マスキング前の生ログ。アクセスを厳しく制限し、保持期間を短く設定する領域

raw層は「存在するが、普段は誰も触れない」状態にするのが設計意図です。保持期間は組織のポリシーや規制要件で異なりますが、「必要最小限の期間だけ保持し、期限到来で自動削除する」運用が一般的です。

ただし、二層保管はストレージコストと運用負荷が増える面があります。すべてのログに適用するよりは、機微データを含む可能性があるログ種別に絞って適用するほうが運用しやすい傾向があります。

アクセス制御と監査:誰がどこまで見られるか

ログを保管しても、閲覧権限が適切でなければ防波堤として機能しません。「誰がどの層のログをどこまで見られるか」を設計項目として最初に決めておくとぶれにくくなります。

ログ基盤へのアクセスは「見る」「書く」「消す」の3操作に分かれます。NIST SP 800-92の推奨に沿えば、ログファイルへのアクセスを制限し、必要な場合でも追記(append-only)権限とし、閲覧権限は可能な限り絞る設計がよいでしょう。

具体的な設計項目として、以下を最初に固定しておくと運用がぶれにくくなります。

  • 最小権限の原則: sanitized層は開発・運用チーム、raw層はインシデント対応の限定メンバーのみ
  • 閲覧権限の定期見直し: 四半期ごと、または組織変更時に棚卸しする運用ルール
  • 監査ログ: 誰がいつどのログにアクセスしたかを別経路で記録する
  • 書き込み権限: ログ基盤への書き込みはアプリケーションのサービスアカウントに限定し、人間の直接書き込みは原則禁止

監査ログ自体の保護も忘れやすいポイントです。監査ログを改ざん・削除できる権限が広く開いていると、監査の意味が薄れてしまいます。別の保管先に追記専用で書き出す設計が安心です。

相関ID(trace_id)に混ぜてはいけない情報

相関ID(trace_id / span_id)はリクエストの追跡に不可欠ですが、IDそのものに何を含めるかには制約があります。ここで押さえておきたいのは「相関IDに個人識別情報や機微情報を混ぜない」という点です。

traceparent(W3C Trace Context)はサービス間をまたいで伝播するヘッダです。W3C Trace Context Level 2のプライバシー考慮では、traceparent / tracestate の目的はトレース相関であり、個人識別情報や機微情報を入れてはならないと書かれています。

traceparent はログ基盤だけでなく、中間プロキシ、CDN、サードパーティサービスなど想定外の場所に記録される可能性があります。ユーザーIDやセッションIDをtrace_idにエンコードする設計は、意図しない経路で個人を特定できる情報が拡散するリスクを生みます。

相関IDはランダムまたは擬似ランダムな値(UUIDv4など)を使い、ユーザーとの紐づけはログ基盤内部のインデックスで行う形が一般的です。「trace_idからユーザーを引ける」必要がある場合でも、その対応表はログ基盤内部に閉じ、traceparent自体には含めない設計にしておくと安心です。

tracestate にカスタムキーを追加する場合も同様の原則が適用されます。ベンダー固有のキーに機微情報を含めないよう、設計レビュー時にチェック項目として入れておくと見落としを減らせます。

抽出:失敗候補を自動で拾う最小ルール

収集で残すログ項目とPII/機密の線引きが決まったら、次は溜まったログから失敗候補を自動で拾う抽出ルールの設計です。起点をどこに置くかで、レビュー負荷と見逃し率が大きく変わります。人手判断が不要な「決定的シグナル」から抽出を立ち上げ、運用が安定してからユーザー由来やコスト異常のルールを足していく順序が無難です。

まずは決定的な失敗から(例外・タイムアウト・スキーマ違反)

判断に迷わない失敗をどう拾うか。ここでは決定的シグナル、つまり条件判定だけで失敗と断定できるイベントを対象にします。具体的には、未処理例外(HTTP 5xx・ランタイムエラー)、タイムアウト超過、出力スキーマ違反の3種が代表的です。

これらはモデルの出力品質に関係なく「システムとして壊れている」状態なので、人がログを読んで判断する工程を省けます。抽出ルールの第一層はこの3種のフィルタだけで十分に立ち上がります。

誤検知がほぼゼロという点が大きいのではないでしょうか。例外が投げられた、レスポンスが返らなかった、JSONスキーマに合わなかった、といったケースは「失敗ではなかった」と覆ることがほとんどありません。Google SREが監視のゴールデンシグナルとしてErrors(明示的エラー)を挙げているのと同じ考え方で、まず確実に拾える層から固めていくのが自然な流れです。

注意点として、スキーマ違反の検知にはスキーマ定義そのものが手元にある状態が出発点です。出力のJSON Schemaやツール呼び出しの型定義がコード上で管理されていない場合は、先にスキーマを明文化する作業から始めることになります。

ユーザー由来シグナル(再試行・低評価・エスカレーション)を拾う

決定的シグナルだけでは、「動いたけれど役に立たなかった」ケースを取りこぼします。ユーザーの行動から失敗を推定できないか、という発想です。UIや運用フローに埋め込まれたユーザー行動、たとえば再試行(リトライ)、低評価(「役に立たなかった」ボタン等)、人間へのエスカレーションは、その取りこぼしを補う第二層になります。

これらのシグナルは「失敗の可能性が高い」だけで確定ではありません。再試行はネットワーク都合かもしれず、低評価は期待値のズレかもしれません。ユーザー由来シグナルは「失敗候補キュー」への投入に使い、最終判断は人またはルールベースのレビューに委ねる設計がやりやすいです。

LangSmithのrun rulesのように、フィードバックスコアが低い場合にトレースをデータセットへ自動追加する仕組みは、この第二層の実装パターンとして参考になります。

まずUIにフィードバック機能(「役に立った/立たなかった」ボタン、再生成ボタン)を入れ、そのイベントをtrace_idと紐づけてログに残します。エスカレーション(チャットボットからオペレーターへの切り替え等)も同様にイベント化します。これらのイベントが発火したトレースを抽出器が候補キューに流す、という形です。

フィードバック機能を実装してもユーザーが押してくれるとは限りません。低評価の収集率が低い環境では、再試行やエスカレーションのほうが信頼できるシグナルになりがちです。どのシグナルの収集率が高いかは環境依存なので、最初は全種類を候補キューに入れておき、レビュー段階でノイズ比率を見て絞る流れが無難です。

コストや消費量の異常も失敗候補にする

正常に見えるのにコストだけ異常な応答は失敗か。ここを整理します。レイテンシの急増、トークン消費量の跳ね上がり、ツール呼び出し回数の異常といった現象は、例外もスキーマ違反も起きていないのに、内部で何かがおかしい状態を示唆します。

SREの現場で使われるゴールデンシグナルにはLatency・Errors・Saturationが含まれています。Errorsは定義次第で「誤った内容」も含められますが、遅延や過剰消費はLatencyやSaturation側で見るほうがわかりやすいです。LLMやエージェントの文脈では、ループ的なツール呼び出しや冗長な推論で応答が膨張するケースがこれに当たります。

統計的な逸脱を検知するルールを加えると、決定的シグナルとユーザー由来シグナルの間を埋められます。具体的には、過去N日間の同一タスクタイプにおけるp95を超えたトレースを失敗候補キューに入れる、といった形です。

閾値の設定は環境やタスクの種類で大きく変わります。固定値で始めると過検知が増えやすいため、タスクタイプごとのベースラインを一定期間計測してからルール化するほうが運用に乗りやすいです。

過検知と見逃しの扱い(レビューキューと優先度)

抽出ルールの精度をどう運用で受け止めるか。過検知と見逃しはゼロにならない前提で設計し、レビューキューと優先度付けで吸収する形に落とし込むのが無難です。

SREの現場では、障害後に原因と再発防止策を振り返る「ポストモーテム」という慣習があります。ポストモーテムの文化では、ユーザー影響の大きさやデータ損失の有無、復旧にかかった時間などを事前にトリガー基準として定義し、すべてのインシデントを一律に扱わない運用が良いとされています。失敗候補の抽出でも同じ考え方が使えます。

抽出された候補をまずキュー(バックログ)に入れ、以下の優先度で並べます。

  • 決定的シグナル(例外・タイムアウト・スキーマ違反): 最優先でレビューに回します
  • ユーザー由来シグナル: 影響ユーザー数や発生頻度で重み付けします
  • コスト異常: 逸脱度合いでソートし、閾値ぎりぎりのものは後回しにします

「ログはあるけど原因追えない」という状態を避けるには、レビューキューの各項目からtrace_idで元のトレースに即座にジャンプできる導線があるとスムーズです。候補を溜めるだけでレビューされない状態が続くと、抽出ルール自体への信頼が下がり、運用が形骸化します。

見逃し(本来拾うべきだった失敗が候補に入らなかった)への対策は、定期的なランダムサンプリングで補います。本番トレースから無作為にN件を抜き出し、抽出ルールが拾わなかったものに失敗が含まれていないかを確認する作業を週次や隔週で回すと、ルールの穴が見えてきます。

レビューキューの消化率が下がったときに「ルールを緩めて候補を減らす」という手もありますが、根本的な解決にはなりにくいです。まずはレビュー1件あたりの判断コストが高すぎないか(情報不足で判断できない等)を確認し、抽出時に付与するコンテキスト(エラーメッセージ、直前のユーザー入力、影響範囲の概算)を増やすほうが持続しやすいです。

正規化と再現性:評価レコードを再実行可能にする

抽出ルールで失敗候補を拾えるようになっても、そのログ断片が「もう一度同じ条件で走らせられる形」になっていなければ、回帰テストの素材にはなりません。ここでは、抽出した断片を再実行可能な評価レコード1件に変換する正規化の設計を、トレーシングの観点から整理します。

評価に必要な情報を過不足なく1件にまとめるには、最小スキーマの定義から始めるとスムーズです。

評価レコードは最低限「入力(input)」「出力(output)」「根拠(ground_truth または判定基準)」「関連リンク(links)」の4フィールドで構成しておくと扱いやすくなります。

入力にはユーザーの発話やクエリだけでなく、検索(retrieval)で取得したコンテキストも含まれます。検索とは外部知識源から関連情報を引いてくる工程、生成(generation)とはそのコンテキストをもとにLLMが応答を作る工程です。この2つを分けて記録しておかないと、失敗が「検索の問題」なのか「生成の問題」なのかを後から切り分けられません。

出力にはLLMの応答テキストに加え、ツール呼び出し結果やステップの中間出力も対象になります。根拠は「この入力に対して期待される振る舞い」を示すフィールドで、正解テキストの場合もあれば、合否判定のルーブリック(評価基準表)の場合もあります。linksにはtrace_idや元ログのURIを入れておくと、問題が起きたとき原本に遡れます。

最小スキーマに「あると便利」なフィールドを足し始めると肥大化しやすい傾向があります。最初は4フィールドに絞り、不足が判明してから拡張するくらいがちょうど良いです。

再実行に必要な版情報(モデル・プロンプト・ツール・索引)

「ログはあるけど原因追えない」という状態を避けるために、評価レコードにはどの版情報を残すとよいでしょうか。

最低限記録しておきたいのは「モデル名とバージョン」「プロンプトテンプレートのハッシュまたはリビジョン」「外部ツール/APIのバージョン」「検索索引のスナップショットID」の4種類です。評価レコードに必要なバージョン情報とは、同じ入力を与えたとき出力の差分がどの変更に起因するかを特定できる粒度の識別子を指します。

LLMアプリの出力はモデル単体ではなく、プロンプト・ツール・索引といった周辺構成の影響を受けます。構成要素をセットでバージョン管理する考え方は、本番運用チームで広がりつつあります。

デプロイパイプラインで各版情報を環境変数やコンフィグファイルに書き出し、ログ収集時にそのまま評価レコードへコピーする形がスムーズです。手動で後から調べる運用だと、リリースが重なった時点で追跡が破綻しがちです。

版情報の粒度は細かすぎても管理コストが跳ねます。「この変更で出力が変わりうるか?」を基準に、記録対象を絞るとバランスが取りやすいです。

外部依存をスタブ化する(tool stubs)

CIで評価を再実行するとき、外部APIや検索エンドポイントが本番と同じ応答を返す保証はありません。外部依存をどう固定すれば、CI上で安定した再現ができるか。

評価レコードに記録したツール応答や検索結果をそのままスタブ(代替の固定応答)として使う方法が、最小コストで始められます。

本番のツール応答をキャプチャしておけば、CIではそのキャプチャを返すだけで外部通信が不要になります。構成要素をセットでバージョン管理する考え方はDVCなどのツールでも採用されています。

評価レコードのlinksフィールドにツール応答のスナップショットを紐づけておき、CIランナーがそのスナップショットを読み込んでスタブとして返す形にします。新規のツール応答が必要なケースだけ本番APIに問い合わせる「フォールバック付きスタブ」にすると、スタブの陳腐化にも対応できます。

スタブが古くなるとテストが「過去の外部応答に対してだけ合格する」状態に陥ることがあります。スタブの鮮度を定期的に確認する仕組み(たとえば月次でスタブを再キャプチャするジョブ)を入れておくと、この問題を緩和できます。

非決定性に耐える比較方法(seed・複数回・比較タスク化)

LLMの出力は同じ入力でも毎回微妙に異なるため、完全一致で合否を判定すると、変更していないのにテストが落ちる「フレーク」が頻発します。非決定性がある前提で、どう安定した評価に寄せるか。

3つのアプローチを組み合わせるのが一般的です。

  1. seed固定: モデルAPIがseedパラメータをサポートしている場合に乱数を固定して出力のばらつきを抑える
  2. 複数回実行: 同一入力を数回走らせ、合格率や平均スコアで判定する
  3. 比較タスク化: 自由記述の正誤判定を避け、「AとBどちらが要件を満たすか」「ルーブリックのどの段階か」といった分類・比較形式に変換する

seed固定だけではモデル提供側のインフラ変更で再現性が崩れることがあります。複数回実行は安定性を高めますがコストが増えます。比較タスク化は判定基準を明示的にできる利点がありますが、ルーブリック設計に手間がかかります。どれか1つで万能という手段はなく、評価対象の性質に合わせて選ぶ形になります。

まずseed固定を試し、それでもフレーク率が高い評価ケースを特定します。そのケースに対して複数回実行または比較タスク化を適用する、という段階的な導入がコスト面で無理がありません。

注意点として、「seed固定=完全再現」ではない点を前提に、許容範囲を先にチームで決めておくと、フレーク発生時の判断が属人化しにくくなります。

データセット化:最小の人手・版管理・重複排除

正規化した評価レコードが手元に溜まり始めたら、次に考えるのは「評価データセットとしてどう管理すれば回帰テストに使い続けられるか」という点です。レコード単体では再実行できても、束ね方を決めないままケースが増えると、重複・陳腐化・誰が何を判断したか分からない状態が生まれがちです。ここでは、最小の人手で更新が回り続ける評価データセットの設計を整理します。

最小ラベリング設計(誰が何をどこまで)

合否判断をどの粒度で止めれば、ラベリングがスケールするか。ここを先に決めておきます。

最初は二値(pass / fail)だけで始め、詳細ラベル(失敗原因の分類や重篤度)は後から必要になった時点で足す形が無難です。ラベルの選択肢が増えるほど判断のブレが大きくなり、レビュー1件あたりの時間も伸びるためです。

誰がラベルを付けるかは先に決めておく必要があります。典型的な分担は、決定的シグナル(例外・タイムアウト・スキーマ違反)で拾ったケースは自動で fail ラベルを付与し、ユーザー由来シグナルやコスト異常で拾ったケースだけを人手レビューに回す形です。レビュー担当はドメイン知識を持つPdMや業務担当が適任ですが、判断基準を属人化させないために「何を見て pass / fail を決めるか」のガイドラインを3〜5行で書いておくと合意形成がスムーズです。

注意点として、ラベリングの粒度を最初から細かくすると、判断者間の一致率が下がり、評価結果の信頼性そのものが揺らぎます。詳細分類が欲しくなるのは、fail が溜まって「どの種類の失敗が多いか」を分析したくなった段階です。その時点で分類軸を追加しても遅くはありません。

データセット形式:JSONLとメタデータの持ち方

「回帰テストに適したファイル形式は何か?」を整理します。

1行1レコードのJSONL(JSON Lines)が扱いやすい形式です。行単位で追加・削除・差分管理ができ、Gitとの相性もよいためです。CSVでも最低限は回りますが、入力や期待出力に改行や構造化データが含まれると破綻しやすい傾向があります。

各レコードに持たせるメタデータの最小セットは、ケースID・ラベル(pass/fail)・ラベル付与者・ラベル付与日・抽出元の trace_id・対象の評価層(PR用/夜間用など)です。後から分析に効くフィールドとして、失敗シグナル種別(決定的/ユーザー由来/コスト異常)や、対象モデル版を入れておくと、回帰の傾向分析で役立ちます。

メタデータを増やしすぎるとレコード追加のコストが上がり、更新が止まる原因になります。「分析で確実に使うフィールド」と「あると便利なフィールド」を分けて、後者は任意項目にしておくと運用しやすいです。

分割と重複排除:PR用・夜間用・リリース前用

ケースが増えたとき、全件を毎回回すのか。ここを先に決めておきます。

評価データセットを用途別に層(tier)で分割し、実行タイミングごとに使う層を変える形が一般的です。たとえば、PR用は件数を絞った「コアセット」(重篤度の高い失敗ケースや直近の回帰ケース)、夜間用はコアセット+中頻度ケース、リリース前は全件、という三段構えです。

重複排除のキーは、入力の正規化ハッシュ(プロンプト+コンテキストの組み合わせ)を基本にします。同じ入力で異なる期待出力がある場合は、モデル版やプロンプト版も含めた複合キーにする必要があります。重複を放置すると、特定パターンの失敗が過剰に重み付けされ、評価結果の偏りにつながります。

注意点として、層の分け方は組織のCI実行時間の許容範囲に依存します。PR用が5分以内に収まる件数を目安にし、超えたらコアセットを絞るか並列実行を検討する、という判断基準を先に決めておくと運用が安定します。

変更履歴と版管理:datasetをPRで育てる

評価データセットの変更をどう追跡すれば、過去の評価結果と比較できるか。

データセットファイルをコードリポジトリに含め、変更はPR(Pull Request)経由で行う形が自然です。コードの変更と同じレビュープロセスに載せることで、「なぜこのケースを追加/削除したか」が履歴に残ります。

ケース追加・削除・ラベル変更のたびにPRを作り、変更理由をPR本文に書きます。評価プラットフォームによっては、データセットの更新ごとにバージョンが自動生成され、タイムスタンプで履歴を追える仕組みもあります(例:Langfuseでは更新ごとにdataset versionが切られます)。どちらの場合も、「どの版のデータセットで評価した結果か」をCI結果に紐づけておくことが、あとから比較するための前提です。

注意点として、データセットが大きくなるとGitリポジトリの肥大化が問題になることがあります。その場合はGit LFSや外部ストレージ+バージョンタグの組み合わせで管理し、リポジトリ本体にはメタデータとバージョン参照だけを残す方法もあります。

データセット文書化(datasheet)で事故を減らす

「このデータセットは何を測るためのもので、何をカバーしていないか?」を明文化する設計です。

評価データセットには「データシート」(目的・範囲・代表性・制限事項をまとめた文書)を添付しておくと、評価基準のブレや誤用を防ぎやすくなります。Datasheets for Datasetsの考え方では、データセットの動機・構成・収集プロセス・推奨用途などを記載することが提案されています。

最小限のデータシートに含める項目は、データセットの目的(何の回帰を検知するか)、対象範囲(どの機能・どのユーザー層のケースか)、既知の偏り(特定シグナルに偏っていないか)、PIIマスキングの方法と確認状況、最終更新日と責任者です。

注意点として、データシートを作ること自体が目的化すると形骸化します。更新頻度はデータセットの大きな変更(層の追加、ラベリング基準の変更、大量ケース投入)のタイミングに合わせ、軽微な追加のたびに書き直す必要はありません。「データセットPRのテンプレートにデータシート更新チェックを入れる」程度の運用で十分回ります。

CI/ゲート接続:誤検知を抑えて回し続ける運用

評価データセットが揃った段階で問われるのは「CIに組み込んだゲートを、止めるべきものだけ止める精度で回し続けられるか?」という運用設計です。品質ゲートとは、マージやデプロイの前に評価を自動実行し、基準を満たさない変更の進行を制御する仕組みを指します。ゲートは導入よりも維持が難しく、誤検知でリリースが止まり続けると形骸化して誰も見なくなる――ここでは、その崩壊を防ぐ運用の型を整理します。

PRゲートと継続評価を分ける(速い/重い)

CI での評価を「どの粒度で・いつ回すか?」が最初の設計判断です。

PR(プルリクエスト)マージ前に回すゲートと、夜間やリリース前に回す継続評価は分けるのが自然です。PR ゲートに重い評価を全部載せると待ち時間が伸び、開発者がゲートを迂回し始めるためです。

PR ゲートに載せる評価は「軽く・確実に・速く終わる」ものに絞ります。具体的には、スキーマ違反や安全性チェックなど判定が決定的で、数十秒〜数分で終わるケースが良いでしょう。CI/CDに品質ゲートを組み込む仕組みは、こうした軽量チェックから始めるとスムーズです。

一方、全評価データセットを使った回帰テストや、LLM-as-a-Judge による多軸評価は実行時間もコストもかかります。これらは夜間バッチやリリース候補タグの作成時など、頻度を落として別枠で回す形が多いです。

注意点として、PR ゲートと継続評価の境界はチームの開発速度とデータセット規模で変わります。最初は PR ゲートを最小限にしておき、安定したら評価項目を徐々に移動させる段階導入が無難です。

ゲート基準の決め方(ブロック/警告/例外)

「何が赤くなったらマージを止めるか?」を決めるのがゲート基準の設計です。CIゲートにおけるブロッキングとは「基準未達でマージやデプロイを自動的に停止する」判定、警告とは「通知はするが進行は止めない」判定を指します。

最初は警告だけで始め、チームの合意が取れた項目からブロッキングに昇格させる方法が運用を壊しにくいです。

基準を決めるときの判断軸は「その失敗がユーザーに届いたときの影響度」です。たとえば安全性違反(有害出力の生成)やデータ漏洩に直結するケースはブロッキング候補になります。一方、文体の揺れや冗長な回答といった品質劣化は、影響は無視できないものの即座にブロックすると開発が止まるため、警告に分類して週次レビューで拾う形が考えられます。

まず失敗カテゴリごとに影響度(高/中/低)を仮置きし、PdM・テックリード・運用担当で合意を取ります。合意が取れないカテゴリは警告に留め、実データが溜まってから判断を更新するのが安全です。

注意点として、例外(skip)の扱いも最初に決めておく必要があります。緊急ホットフィックスなどでゲートを迂回する手順と、迂回した場合の事後レビュー義務を明文化しておかないと、例外が常態化してゲートが形骸化します。

誤検知(フレーク)を抑える定番手当(再実行・閾値・隔離)

LLM 評価の CI 運用で最も厄介なのは「コードに問題がないのにゲートが赤くなる」誤検知、いわゆるフレークです。

LLM の出力は非決定的であり、外部 API の応答も揺れるため、従来のユニットテストと比べてフレークの発生率は構造的に高くなります。Googleのテスト運用事例では、観測された pass→fail 遷移の約 84% がフレーキーテストに起因していたとされています。

フレークをゼロにするのではなく「フレークを前提に運用で折り合う」設計が落としどころになります。定番の緩和策は大きく3つあります。

再実行(リトライ): 失敗したケースだけを自動で再実行し、再現する失敗のみを本物として扱います。巨大規模のCI運用でも、失敗時のみリランする手法は偽陽性(本当は問題ないのに失敗と判定されること)を減らす実務的な緩和策として使われています。

閾値の緩和: 全ケース合格を条件にするのではなく、合格率 N% 以上をゲート基準にします。具体的な閾値は環境やタスクの非決定性の強さで変わるため、まず警告運用で誤検知率を観測し、チームでベースラインからキャリブレーションする流れが自然です(一例として95%前後を初期値にする方法がありますが、あくまでたたき台です)。

隔離(quarantine): 連続してフレークするケースを一時的にブロッキング対象から外し、別途トリアージキューに回します。隔離の判断基準は「直近N回の実行でM回以上フレークした」といったルールで自動化できます(例:直近5回で3回以上失敗したら隔離)。隔離したケースは定期的にレビューし、修正して復帰させるか廃棄するかを判断します。

注意点として、リトライ回数を増やしすぎると CI の実行時間が膨らみます。リトライ回数の上限(例: 2〜3回)は実行時間の許容範囲から逆算し、それでも不安定なケースは隔離に移すと安心です。

アラートと対応手順:赤くなったときの動き方

「ゲートが赤くなったとき、誰が何を見て、どこまでで判断を下すか?」を手順として固定するのが運用手順書(ランブック)の役割です。

ゲートの赤をトリアージする担当・確認手順・エスカレーション先を事前に決めておかないと、赤が放置されるか、逆に全員が反応して混乱するかのどちらかになりがちです。「トレースがないと議論が進まない」という状況を避けるため、アラートには該当 trace_id と評価結果へのリンクを含めます。

手順の骨格は以下のとおりです。

  • アラート発火: CI が赤になったら Slack 等に通知。通知には trace_id・失敗カテゴリ・該当 PR のリンクを含めます
  • 一次トリアージ: 当番(ローテーション)がフレークか実障害かを判定。再実行で再現しなければフレーク処理、再現すれば次へ進めます
  • 原因切り分け: 評価レコードの入力/出力/版情報を確認し、変更起因(プロンプト/モデル/データ)かインフラ起因かを切り分けます
  • 判断: ブロッキング項目なら PR の修正またはロールバック。警告項目なら issue 化して次スプリントで対応、を基本とします
  • 例外処理: 緊急リリースでゲートを迂回する場合は、迂回理由を記録し、24時間以内に事後レビューを実施します

注意点として、運用手順書は書いた時点では仮説です。実際に赤が出たときの対応ログを蓄積し、月次で手順書を更新するサイクルを組み込んでおくと、手順が現場から乖離しにくくなります。

評価軸の測り方(失敗取り込み速度・再発防止率・ゲート誤検知率)

CI ゲートを回し始めたあとに「この仕組みは機能しているか?」を判断するための運用指標をどう測るかを整理します。

効果を数値で保証することは難しいですが、改善の方向を判断する材料として以下の3指標を測ると意思決定に使いやすいです。

失敗取り込み速度: 本番で検出された失敗が、評価データセットに取り込まれるまでの経過時間(日数)です。測り方は、失敗検出タイムスタンプとデータセットへのコミットタイムスタンプの差分を記録します。この値が大きいほど、同じ失敗が本番で再発するリスク期間が長いことを意味します。

再発防止率: データセットに取り込んだ失敗パターンが、以降のリリースで再び本番に出た割合です。測り方は、取り込み済みの失敗カテゴリが再発した件数を、取り込み済み総数で割ります。この値が高ければゲートのカバレッジに穴がある可能性があり、評価ケースの設計を見直す材料になります。

ゲート誤検知率: CI ゲートが赤を出したうち、実際にはコード変更に問題がなかったケースの割合です。測り方は、トリアージの結果「フレーク」または「誤検知」と判定された件数を、ゲート赤の総数で割ります。この値が高い状態が続くと開発者のゲートへの信頼が下がり、迂回や無視が増えるサインになります。

注意点として、これらの指標は絶対値に意味があるというよりも、トレンドの変化を見て改善の意思決定に使うものです。目標値を天下り的に決めるよりも、初期値を計測してからチームで閾値を合意する方が運用に馴染みやすい傾向があります。

補足:導入時に確認しておきたい点

ここまで扱った CI/ゲート接続の設計は、いくつかの前提と環境依存を含んでいます。以下の論点は導入時に確認しておくとスムーズです。

組織の CI 成熟度: CI パイプライン自体がまだ整備されていない組織では、評価ゲートの前に CI 基盤の構築が先決です。本セクションは最低限の CI 環境がある前提で書いています。

コストの見積もり: LLM 呼び出しを伴う評価は、実行ごとに API コストが発生します。データセット規模と実行頻度に応じたコスト試算は、組織のモデル契約や利用量に依存するため一般化が難しく、本記事では扱いきれていません。

法務・契約・データ分類: 評価データに含まれる情報の分類(機密区分)、外部 API への送信可否、ログの保持期間は、組織のセキュリティポリシーや契約条件で大きく変わります。ここでの設計は一般的なパターンなので、自社に当てはめる際は法務・情報セキュリティ部門と一度すり合わせておくと安心です。

マルチモデル/マルチエージェント構成: 複数のモデルやエージェントが連鎖する構成では、どのステップの評価をどのゲートに配置するかの設計が複雑になります。本セクションは単一モデル〜単純なチェーン構成を想定しており、複雑な構成では追加の設計判断が必要になります。

これらはチーム固有の制約を踏まえて、設計レビューで詰めていく形になります。

よくある質問

本番ログからの評価データセット構築は、どの規模から始めるべき?
最初から全量を対象にする必要はありません。まずは決定的シグナル(例外・タイムアウト・スキーマ違反)だけを抽出し、週に5〜10件程度の失敗候補をレビューするところから始めるのがよいでしょう。運用が回り始めてから、ユーザー由来シグナルやコスト異常の抽出を段階的に追加していく形がスムーズです。
個人識別情報(PII)のマスキングはどのタイミングで行うべき?
永続化前のwrite-side(書き込み時)でマスキングするのが無難です。read-side(閲覧時)マスキングだと、ログ基盤に生データが残るため、アクセス制御の不備やバックアップ経由での漏洩リスクが消えません。調査用に生データが必要な場合は、sanitized層とraw層の二層保管が選択肢になります。
CIゲートで誤検知(フレーク)が多発したらどうする?
LLMの出力が毎回揺れる性質(非決定性)により、フレークはゼロにはなりません。対策としては、失敗ケースの自動再実行(リトライ)、合格率閾値の導入(例:全件合格ではなく95%前後などをたたき台に)、連続フレークケースの隔離(quarantine)の3つを組み合わせるのが定番です。リトライは最大2〜3回程度を目安に絞り、それでも不安定なケースは隔離キューに移すのが実務的です。
評価データセットの版管理はどうすればいい?
データセットファイル(JSONL形式推奨)をコードリポジトリに含め、変更はPR経由で行う形が自然です。「なぜこのケースを追加/削除したか」がPR履歴に残り、過去の評価結果との比較も容易になります。データセットが大きくなったらGit LFSや外部ストレージ+バージョンタグで管理する方法もあります。

最後に

この記事では、本番ログを回帰テスト資産に変える最小構成として、収集からCIゲート接続までの6工程と、PIIマスキング・アクセス制御・版管理の設計観点を整理しました。

ゲートの閾値設計やラベリング基準の粒度は、対象システムの業務ドメインやリスク区分で大きく変わります。法務・契約上のログ保持要件や越境移転の扱いも組織ごとに前提が異なるため、この記事の内容をそのまま適用できるかは、個別に確認しておくと安心です。また、マルチエージェント構成やマルチモデル連鎖では、どのステップの評価をどのゲートに配置するかの追加設計があると良いでしょう。

PASHでは、30〜60分の設計レビュー相談も承っています。
ログ設計・失敗定義・ゲート条件などについて、自社の制約に合わせて棚卸ししたいという場合にもぜひご利用ください。

更新履歴(最終更新: 2026年2月17日
    • 初回公開

この記事をシェアする

著者プロフィール

大崎 一徳 / エンジニア

中小企業向けに、AI導入・業務自動化・ツール開発を支援しています。 PoC から本番運用まで一貫して伴走し、「現場で使われ続ける仕組み」をつくることを大切にしています。

Udacity Deep Learning Nanodegree 修了
日本ディープラーニング協会(JDLA)主催 第1回ハッカソン GPU Eater賞受賞(チーム ニューラルポケット)

関連ガイド

関連記事

RAGナレッジAI・業務自動化のご相談はお気軽に

現状の課題整理から公開後の運用まで、状況に合わせて丁寧にサポートします。