品質基準が一種類だと何が困るか
LLM 出力の品質チェックを「OK か NG か」の二値で作ると、すぐに行き詰まります。
性質の異なる二種類の問題を、同じ物差しで測ろうとするためです。一つは絶対に許せないエラー——事実と異なる記述(ハルシネーション)、必須項目の欠落、明らかな破綻。もう一つは許容範囲内の揺れ——文体のトーン、文章量の増減、言い回しの違い。
前者は問答無用でブロックすべきです。しかし後者まで同じ基準でブロックすると、プロンプトの改善すら通らなくなります。「前と違う出力 = 不合格」にしてしまうと、何も変えられない。
この行き詰まりを抜けるのが、品質ゲートを二段に分ける設計です。
Stage 1 — 絶対的な最低条件
Stage 1 は「この出力を本番に出して大丈夫か」を見ます。ゴールデンとの比較は一切せず、その出力単体が最低ラインを満たしているかだけを判定します。
判定の材料は、各出力に付与された品質ラベルです。OK / NG のような二値でも、high / medium / low のような段階でもよいですが、「これ以下は許さない」という下限を決めておきます。
RANK = {"low": 0, "ng": 0, "medium": 1, "high": 2, "ok": 2}
def stage1_pass(label: str) -> bool:
return RANK[label] >= 1 # low / ng は即失敗
Stage 1 の失敗は「リリースを止めるべき事態」です。CI ではこれをエラー終了させ、マージをブロックします。
Stage 2 — ゴールデンとの比較(回帰防止)
Stage 2 は「以前より悪くなっていないか」を見ます。現在の出力を、承認済みのゴールデンデータと突き合わせ、品質ラベルが後退していれば回帰(regression)として記録します。
ゴールデン high → 現在 medium → Stage 2 失敗(後退)
ゴールデン medium → 現在 high → Stage 2 通過(改善)
ゴールデンなし → 現在 何でも → Stage 2 スキップ(新規ケース)
Stage 2 の失敗は「リリースを止めるほどではないが、人が見るべき変化」です。プロンプトを実験的に変えているときは一時的に Stage 2 失敗を許容して回す、という運用ができます。
終了コードで「何をブロックするか」を制御する
二つの Stage を別々の終了コードに割り当てると、CI 側で blocking の強さを選べます。
exit 0: Stage 1 / Stage 2 ともに通過
exit 1: Stage 1 通過、Stage 2 で回帰あり(警告)
exit 2: Stage 1 失敗(最低条件割れ)
exit 2 は必ず止める。exit 1 は止めるかどうかをプロジェクトの段階で決める——開発初期は警告に留め、リリース前は止める、といった使い分けです。
# CI 設定の例(GitHub Actions)
- name: quality gate
run: sim quality-gate
# シェルの終了コードで分岐:
# 2 → ジョブ失敗
# 1 → 警告として続行(後続でレビュー依頼を出す等)
STALE 検出(前回の記事で扱った「結果が古い」状態)を exit 2 に昇格させる --strict のようなオプションを足せば、リリース前の最終チェックとして「古い結果での合格」も塞げます。
カテゴリラベルと連続スコアの両建て
ここまではラベル(OK/NG、high/low)を前提にしましたが、タスクによっては連続値スコア(0.0〜1.0)で閾値判定したいこともあります。その場合は閾値を粒度別に指定できる設計にしておくと柔軟です。
sim quality-gate \
--score-threshold screening=0.7 \
--score-threshold scoring.comment=0.8
パイプライン単位・ステップ単位・項目単位と粒度を変えて指定できれば、「スクリーニング全体は 0.7 以上、採点コメントは 0.8 以上」のように、重要度に応じた基準を引けます。
まとめ
- 品質基準を「絶対的な最低条件(Stage 1)」と「回帰防止(Stage 2)」に分けると、過剰ブロックを避けつつ品質を守れる
- Stage 1 は出力単体の最低ライン、Stage 2 はゴールデンとの相対比較
- 終了コード(0/1/2)を分けることで、CI 側で blocking の強さを選べる
--strictで STALE も止める、--score-thresholdで連続値の粒度別閾値、と拡張できる
品質ゲートをクリアした後、ハルシネーション・法的配慮・品質改善の 3 シグナルを統合した上位のリリースゲートでリリース可否を最終判定する。