【第3回】途中保存で品質を安定させる|途中結果を保存して品質を安定させる

スポンサーリンク
この記事は約34分で読めます。

AIマルチエージェントによる記事作成では、完成した記事だけを見ても、どの工程で問題が発生したのか判断が難しいという課題があります。

第3回では、この課題を解決するため、各AI(Planner・Writer・Reviewer)の出力を段階的に保存し、レビュー結果やHTMLチェック結果もファイルとして記録することで、失敗の原因を特定しやすくしました。

さらに、Python側で品質チェック機能を強化しました。
具体的には、Markdown記法の崩れやCSS混入を自動で検出・修正し、Reviewer AIとPythonチェックの両方をクリアした記事だけを最終保存する仕組みを構築しています。

この二段階チェック体制により、記事品質の安定化と問題発生時の迅速な原因究明が可能になります。

第2回で見えた課題

第2回では、Planner AI、Writer AI、Reviewer AIの役割を整理し、Writer AIとReviewer AIをループさせる構成に改善しました。

基本の流れは以下の通りです。

キーワード入力

Planner AI

Writer AI

Reviewer AI
├ OK → 保存
└ 修正必要 → Writer AIへ戻す

この仕組みによって、単純な一方向の処理ではなく、Reviewer AIの指摘をWriter AIに戻して記事を改善する流れを作れました。

しかし、実際に動かしてみると、次のような課題が見つかりました。

・Reviewer AIの判定形式が安定しない
・「判定:OK」と出る場合もあれば、別の表現になる場合がある
・HTMLにMarkdown記法が混ざる
・styleタグやインラインCSSが残る場合がある
・最終記事だけでは、どの段階で問題が起きたか分かりにくい

そこで第3回では、記事作成の途中結果を保存しながら、どのAIが、どの段階で、どのような出力をしたのか確認できるようにします。

第3回での作成ファイル

第3回では、1回の実行ごとに専用フォルダを作成し、その中に途中結果を保存します。

たとえば、キーワードが「ブロックチェーン」の場合、以下のようなフォルダ構成になります。

output/
└ 20260430_172544_ブロックチェーン/
├ plan.txt
├ draft_1.html
├ draft_2.html
├ review_1.txt
├ review_2.txt
├ validation_1.txt
├ validation_2.txt
├ final_article.html
└ run_summary.txt

このように保存しておくことで、次の確認ができます。

plan.txt
→ Planner AIの記事設計

draft_1.html
→ Writer AIの初稿

review_1.txt
→ Reviewer AIの1回目レビュー

validation_1.txt
→ Python側HTMLチェックの1回目結果

draft_2.html
→ Writer AIの修正版

review_2.txt
→ Reviewer AIの2回目レビュー

validation_2.txt
→ Python側HTMLチェックの2回目結果

final_article.html
→ 最終保存された記事

run_summary.txt
→ 実行全体の結果

つまり、第3回の目的は、単に記事を生成することではありません。

AI記事作成プロセスにおける失敗原因を可視化し、出力品質を安定させることが狙いです。

途中保存が必要な理由

AIマルチエージェントでは、複数のAIが順番に出力を渡し合います。

Planner AI

Writer AI

Reviewer AI

Writer AI

Reviewer AI

この流れでは、最終記事だけを見ても、どこで出力が崩れたのか分かりません。

たとえば、最終記事にMarkdown記法が残っていた場合、原因はいくつか考えられます。

・Writer AIが初稿でMarkdownを出した
・Reviewer AIがMarkdown混入を見逃した
・Writer AIが修正時にMarkdownを追加した
・Python側で検出していなかった

途中結果を保存していれば、原因を段階ごとに確認できます。

draft_1.html に問題がある
→ 初稿の時点でWriter AIが崩している

review_1.txt で指摘されていない
→ Reviewer AIが見逃している

validation_1.txt で検出されている
→ Python側チェックが機能している

draft_2.html で修正されている
→ Writer AIまたはPython側整形が効いている

このように、途中保存はAIマルチエージェントのデバッグに欠かせない仕組みといえます。

今回の改善ポイント

第3回では、主に以下の3つを改善しました。

1. Reviewer AIの判定形式を読み取れるようにする
2. Python側でHTMLを自動整形する
3. Python側HTMLチェックを通過した記事だけを保存する

次から、それぞれの処理を解説します。

改善1:Reviewer AIの判定形式を読み取る

第2回までの課題の一つは、Reviewer AIの判定形式が安定しないことでした。

本来は、

判定:OK

または、

判定:修正必要

のどちらかだけを出してほしいところです。

しかし、実際には次のように、判定:の後ろに改行が入ったり・判定結果が文字列で出力される場合がありました。

判定:
OK

判定:A+ (非常に高品質。軽微な構造的修正のみ推奨)

判定:⭐️⭐️⭐️⭐️⭐️ (5/5)

この場合、人間にはレビュー結果が正常だと分かりますが、プログラム側ではレビュー結果が正常と判断できない可能性があります。

そこで main.py では、get_review_status() を使い、判定OKの出力を、次の両方に対応できるようにしました。

判定:OK
判定:
OK

さらに、判定が文字列で出力される場合の対応として、形式不明の出力を用意しました。

main.py では、Reviewer AIの出力から判定行を探し、OK修正必要UNKNOWN のいずれかとして扱うようにしています。

これにより、Reviewer AIの出力が多少揺れても、プログラム側で判定を読み取りやすくなりました。

改善2:Reviewer AIの判定出力を厳格化する

reviewer.py 側でも、判定出力を安定させるためにプロンプトを調整しました。

Reviewer AIには、最後の判定を必ず以下のどちらかだけにするよう指示しています。

判定:OK

または、

判定:修正必要

さらに、判定行には以下を入れないようにしました。

・絵文字
・星評価
・補足説明
・英語コメント
・「このまま公開可能」などの曖昧な表現

これと同時に、判定行を最後に1回だけ出力するように指示を加えました。

これにより、AIの自然な文章評価を、プログラムが処理しやすい形式としました。

改善3:Python側でHTMLを自動整形する

AIに「HTMLだけで出力してください」と指示しても、実際には次のようなものが混ざることがあります。

・Markdownの **太字**
・コードブロック記号
・styleタグ
・scriptタグ
・インラインCSS
・html / head / body タグ

そこで validators.py に、HTMLを自動整形する sanitize_html_fragment() を追加しました。

主な処理は以下です。

・Markdownの **強調** を <strong>強調</strong> に変換
・コードブロック記号を削除
・styleタグとscriptタグを削除
・style属性を削除
・html/head/body付きの場合は本文部分だけを抽出

validators.py には、Markdown太字記法を <strong> に変換する処理、styleタグやscriptタグを削除する処理、HTML文書全体が出てしまった場合に本文断片へ近づける処理が含まれています。

これにより、Writer AIが多少ルールを外しても、Python側で一定程度補正できるようにしています。

改善4:Python側HTMLチェックを追加する

自動整形した後も、最終的に問題が残っていないか確認する必要があります。

そこで、validate_html_fragment() で以下をチェックします。

・styleタグが残っていないか
・インラインCSSが残っていないか
・scriptタグが残っていないか
・Markdown記法が残っていないか
・html/head/bodyタグが残っていないか
・プレースホルダーが残っていないか
・h2タグがあるか
・pタグがあるか

このPython側チェックにより、Reviewer AIが見逃した形式上の問題も検出できるようになりました。

今回の実行結果

今回の作業では、「ブロックチェーン」というキーワードを使って記事を自動生成しました。

プログラムの動作確認と改善のため、合計3回のテストを実施しています。
各回の実行結果(ターミナル出力)は以下の通りです。

第1回目テスト結果(utf-8)

第2回目テスト結果(utf-8)

第3回目テスト結果(utf-8)

第1回目、第2回目テストでは、判定:OKが正常に出力されず、最大レビュー回数に達して終了しています。
第3回目テストの2回目のレビュー処理で、判定:OKが正常な形式で出力されReviewer AI + Python側HTMLチェック の判定:OKとなり、レビューが完了した記事が出力されました。

第3回目テストでの run_summary.txt (実行全体の結果)では、以下のように記録されています。

保存状態:OK判定後に保存
Reviewer最終判定:OK
最終Python側HTMLチェック:OK

第3回目テスト run_summary.txt(utf-8)

第3回目テスト完成記事(utf-8)

第3回目テスト完成記事(Shift-jis)

修正後のプログラム

以下は、第3回のファイル構成と使用プログラム一式です。

ファイル構成

article-agent
├─ agents
│ ├── planner.py
│ ├── reviewer.py
│ └── writer.py
├── llm_client.py
├── main.py
├── mcp_client.py
├── mcp_server.py
└── validators.py     

使用プログラム一式

planner.py

reviewer.py

writer.py

llm_client.py

main.py

mcp_client.py

mcp_server.py

validators.py  

まとめ:途中保存でAI記事作成の失敗原因を可視化する

第3回では、AI記事作成の各段階を可視化し、問題の特定を容易にする仕組みを構築しました。

具体的には、以下の6つの段階をそれぞれファイルとして保存することで、どの工程で問題が発生したのかを追跡できるようにしました。

  • Planner AIの設計
  • Writer AIの初稿
  • Reviewer AIのレビュー
  • Python側HTMLチェック
  • Writer AIの修正版
  • 最終記事

この可視化により、第2回で採用したWriter AIとReviewer AIのループ処理では、出力品質が安定しないという課題が明確になりました。

対策として、第3回ではReviewer AIの判定結果をPython側で解析し、「OK」「修正必要」「UNKNOWN」の3つの状態として処理する方式に変更しました。

ただし、今後イベント駆動型マルチエージェントシステムへ発展させる際、自然言語のレビュー結果だけに依存して次の処理を決定するのは不安定です。

そのため、将来的な改善案として、Reviewer AIには自然言語レビューとは別にJSON形式の判定結果を出力させる予定です。
Python側でこのJSONを検証し、statusに応じて article.approvedarticle.revision_required といったイベントを発火させることで、より確実なシステムを作成する予定です。

次回の第4回では、MCP風ツールを整理し、より正式なMCP構成へ近づけていきます。