[ AI セーフティ ]

Post-hook 自己改善ループ — 生成 AI 出力を自動でレビュー・リトライする

AI が一発で正しい出力を返す保証はない。Reviewer エージェントと Post-hook を組み合わせ、品質が閾値を下回ったら自動でリトライするループ設計の思想・実装・落とし穴を montage の実例で解説する。

著者: 森本拓見
#claude-code #ai-driven-dev #self-improvement #validation

はじめに

AI が出力する成果物の品質を担保するには、どのタイミングで検証するのが効果的か。

直感的なアプローチは「事前検証」だ。入力を整え、スキーマで制約を与えてから生成させる。Block Schema と Zod によるバリデーションはその一例だ。しかし事前にどれだけ条件を揃えても、AI の出力が常に期待通りになる保証はない。

八雲が行き着いたのは「事後検証 + 自動リトライ」のアプローチだ。生成後に専用の Reviewer が評価し、品質が基準を下回ったら harness の Post-hook がリトライを自動発火する。このループを設計として組み込むことで、一発生成に依存しない堅牢なパイプラインが成立する。


課題: 一発生成の限界

AI コンテンツ生成パイプラインで詳しく書いたように、montage は動画制作を複数のエージェントに役割分担させている。Scriptwriter が台本を書き、Composer が映像レイアウトを設計し、Renderer が動画を生成する。

このパイプラインで最初に直面したのは、各ステージの出力品質が一定しない問題だ。台本の論理構成が飛躍していることがある。グラフとデータが合っていないことがある。字幕がコンテンツと重なることがある。いずれも「それらしい出力」だが、公開に耐える品質ではない。

単純な解決策は人間が目視確認することだ。しかしそれでは AI 駆動の意味が薄れる。「結局人間が全部チェックしている」という状況は避けたかった。


アプローチ: Post-hook で出力をチェック → 失敗時にリトライ

montage が採用した設計は、Reviewer エージェントと harness の Post-hook の組み合わせだ。

Reviewer エージェントは各ステージの出力をルーブリックに基づいて 1〜5 スコアで採点する。採点結果は output/{topic-id}/review/quality-score.json に書き出される。

Post-hook は Reviewer の完了を検知して自動的に走る。.claude/settings.jsonPostToolUse(Bash) フックが scripts/hooks/post-reviewer.sh を起動し、スコアが閾値(3.5)を下回っていれば cause フィールドを読んで適切なステージへのリトライを発火する。

Reviewer 評価 → quality-score.json 書き出し
  → PostToolUse hook → post-reviewer.sh
    → NG なら cause に応じた前ステージにリトライ
      → 再生成 → Reviewer 再評価 → ...

Claude 側はこのループを明示的に呼び出す必要がない。harness の仕組みとして動くため、パイプラインのコードはシンプルに保てる。


ループ条件と最大リトライ回数の設計

ループ設計で最も重要なのは、どこで止めるかだ。

montage では最大リトライ回数を 3 回に設定している。3 回 NG が続いた場合は停止してユーザーに報告する。無限ループを設計上排除するための上限だ。

リトライ先の決定は cause フィールドに委ねる。cause: "narration" なら Scriptwriter へ、cause: "scene-layout" なら Composer へ戻す。原因が曖昧な場合も全体巻き戻しより部分リトライを優先する。台本が良好だった場合に台本まで差し戻すコストを避けるためだ。

冪等性の担保として、スクリプトは quality-score.json の隣に .recorded マーカーを生成して処理済みを判定する。hook が複数回走っても同じスコアを重複処理しない。


Reviewer エージェントとの組み合わせ

Reviewer は specs/quality/rubrics.json で定義されたルーブリックに従い、各次元の加重平均で総合スコアを算出する。判定は OK(3.5 以上)/ WARN(2.5〜3.5)/ NG(2.5 未満)の 3 段階だ。

WARN は記録されるが自動リトライのトリガーにはならない。閾値を下げすぎると無限リトライのリスクが高まるため、WARN は「改善余地の可視化」用途にとどめている。

注意すべきは Reviewer 自体が AI エージェントである点だ。評価も確率的で、同じ出力を二度採点すると異なるスコアになることがある。この揺れを抑えるため、ルーブリックの各項目は「ナレーション文字数が 150〜300 字の範囲か」のような観察可能な条件で定義する。主観ではなく確認可能な事実に変換することで評価の安定性を高める。


運用してわかった効果と落とし穴

効果として大きかったのは、人間の「とりあえず確認」ステップを省けたことだ。Post-hook + Reviewer を入れてから、明らかな品質問題はほとんど自動で解消される。NG が出て修正された履歴はログで追跡でき、リトライが多いステージの傾向把握にも使える。

落とし穴はリトライのコストだ。Scriptwriter のリトライは API コストを、Renderer のリトライはレンダリング時間を消費する。最大 3 回のリトライが全ステージで発動すると、制作コストが数倍に膨らむ。対応は「Reviewer のフィードバックをプロンプト改善に反映してリトライ率を下げる」と「問題ステージだけを差し替える部分リトライの優先」の二つだ。


まとめ + 関連記事

Post-hook 自己改善ループの本質は、「AI が一発で成功する」ことへの依存を設計から外すことだ。失敗を期待値として織り込み、失敗したときに何が起きるかをコードで定義する。

  • Reviewer を独立した評価エージェントとして設計する(生成と評価を分離する)
  • Post-hook でリトライを harness に委ねる(Claude 側に制御フローを持ち込まない)
  • 最大リトライ回数を明示する(無限ループを設計上排除する)
  • cause フィールドで戻り先を絞る(全体巻き戻しより部分リトライを優先する)
  • Reviewer のルーブリックを観察可能な基準で書く(評価の揺れを最小化する)

パイプライン全体のアーキテクチャはYakumo の AI 駆動開発のリアルで、スキーマによる早期検知との組み合わせはBlock Schema と Zodで、各ステージの役割分担はAI コンテンツ生成パイプラインでそれぞれ詳しく扱っている。

ShareX でシェア