AIマルチエージェント構成では、1つのAIにすべてを任せるのではなく、Planner・Writer・Reviewerのように役割を分けることで出力品質を安定させやすくなります。
Planner AIは記事設計、Writer AIは本文作成、Reviewer AIは品質確認を担当します。
第2回では、第1回の最小実装で見えた課題を踏まえ、各AIエージェントの役割と、実用化に向けた改善ポイントを整理して修正します。
第1回で作った最小構成を振り返る
第1回では、Windows 11、WSL Ubuntu、Ollama、Gemma 4を使い、ローカル環境で動くAIマルチエージェント記事作成システムの最小実装を作成しました。
構成は以下のような流れでした。
キーワード入力
↓
Planner AI
↓
Writer AI
↓
Reviewer AI
↓
Writer AIで修正
↓
HTML保存
第1回で見えてきた課題
実際に複数回プログラムを実行すると、いくつかの課題が見えてきました。
主な課題は以下です。
・final_article.html が毎回上書きされる
・CSSが付く場合と付かない場合がある
・HTML出力形式が安定しない
・Writer → Reviewer → Writer の後に最終レビューがない
・「最新」と入力しても最新情報が反映されないこれらは、Gemma 4の影響ではなく、マルチエージェントの役割設計と処理フローが最小構成だったことが原因です。
特に重要なのは、次の2点です。
1. 各エージェントの役割がまだ曖昧な部分がある
2. 最終的な品質判定を通過した記事だけを保存する流れになっていないそのため第2回では、まず Planner / Writer / Reviewer の役割を整理し、どのAIに何を任せるべきかを明確にします。
なぜAIを3つの役割に分けるのか
記事作成は、単に文章を書くだけの作業ではありません。
実際には、次のような複数の工程があります。
・検索意図を考える
・読者を決める
・記事構成を作る
・本文を書く
・誤字脱字を確認する
・表現を整える
・内容の過不足を確認する
・HTML形式を整えるこれを1つのAIに一度で任せると、出力が不安定になりやすくなります。
たとえば、次のような問題が起きます。
・構成は良いが本文が弱い
・本文は良いが見出しが曖昧
・レビューはしているが修正が反映されていない
・HTML形式が毎回変わる
・CSSやMarkdownが混ざるそこで、処理を3つの役割に分けます。
Planner AI:考える
Writer AI:書く
Reviewer AI:確認するこの分担によって、それぞれのAIが担当する作業が明確になります。
3つのAIエージェントの全体像
今回の基本構成は以下です。
キーワード
↓
Planner AI:記事設計
↓
Writer AI:本文作成
↓
Reviewer AI:品質確認
↓
Writer AI:修正
↓
Reviewer AI:再確認
↓
保存第1回では、最後の「Reviewer AI:再確認」までは入れていませんでした。
しかし、品質を安定させるには、Writerが修正した後にもう一度Reviewerが確認する流れが必要です。
つまり、実用的には次のような構成が望ましい形です。
Writer AI
↓
Reviewer AI
├ OK → 保存
└ 修正必要 → Writer AIへ戻す
↓
Reviewer AIが再確認このように、Writer AIが作成した記事をReviewer AIが確認し、OKなら保存、修正が必要ならWriter AIへ戻す 流れにします。
Writer AIとReviewer AIをループさせることで、最終的にReviewer AIの確認を通過した記事を保存でき、出力品質を安定できるようになります。
Planner AIの役割
Planner AIは、記事作成の最初に動くエージェントです。
役割は、本文を書くことではありません。
記事を書く前に、何を書くべきかを設計することです。
Planner AIが担当すること
・キーワードの意図を整理する
・想定読者を決める
・記事の目的を決める
・SEOタイトル案を作る
・h2 / h3構成を作る
・Writerへの執筆方針を作るたとえば、キーワードが以下だったとします。
ブロックチェーンこの場合、Planner AIは次のようなことを考えます。
想定読者:
ブロックチェーンに興味がある初心者
検索意図:
ブロックチェーンとは何か、どのように構成するのかを知りたい
記事目的:
ブロックチェーンの基本構造を理解する
構成方針:
Planner / Writer / Reviewer の3役に分けて説明するPlanner AIがしっかり設計すると、Writer AIは迷わず本文を書きやすくなります。
Planner AIのプロンプト例
第1回の最小実装では、Planner AIに次のような指示を出しました。
def run_planner(keyword: str) -> str:
system_prompt = """
あなたは記事設計を担当するPlanner AIです。
入力されたキーワードをもとに、SEO記事の設計を行ってください。
出力は日本語で、整理された形式にしてください。
"""
user_prompt = f"""
以下のキーワードで記事設計を作成してください。
キーワード:
{keyword}
必ず含める項目:
1. 想定読者
2. 検索意図
3. 記事目的
4. SEOタイトル案
5. h2/h3構成
6. 執筆時の注意点
"""
return call_gemma4(system_prompt, user_prompt)このプロンプトは、Planner AIに「記事本文を書かせる」のではなく、記事作成の設計図を作らることを指示していますが、Writer AIへの明確な指示はありません。
第2回は、第1回のプロンプトに、Writer AIへ指示することを追加します。
Planner AIの出力例
Planner AIの出力は、Writer AIが使いやすい形にしておくと便利です。
例:
想定読者:
ローカルLLMやAIエージェントを学び始めた初心者
検索意図:
AIマルチエージェントとは何か、どのように役割を分けるのかを知りたい
記事目的:
Planner / Writer / Reviewer の役割を理解し、簡単な記事作成システムに応用できるようにする
SEOタイトル案:
AIマルチエージェントの基本|Planner・Writer・Reviewerの役割を整理する
h2/h3構成:
h2:AIマルチエージェントとは
h2:Planner AIの役割
h2:Writer AIの役割
h2:Reviewer AIの役割
h2:3つのAIを連携させる流れ
h2:まとめこのような出力をWriter AIに渡すことで、記事の方向性が安定します。
Writer AIの役割
Writer AIは、Planner AIが作った設計に沿って本文を書くエージェントです。
担当するのは、記事本文の作成と修正です。
Writer AIが担当すること
・SEOタイトルを整える
・メタディスクリプションを作る
・AI要約ブロックを作る
・h2 / h3に沿って本文を書く
・FAQを作る
・Reviewer AIの指摘に従って修正するここで重要なのは、Writer AIに自由に書かせすぎないことです。
Planner AIの設計をもとに、以下を守らせます。
・記事の目的から外れない
・見出し構成に沿って書く
・HTML形式を統一する
・過剰な断定表現を避ける
・CSSやMarkdownを混ぜないWriter AIで起きやすい問題
第1回の実行結果では、Writer AIの出力に揺れが見られました。
たとえば、次のような違いです。
・CSS付きのHTMLが出る
・CSSなしのHTMLが出る
・Markdownのような記法が混ざる
・文章だけの出力になる
・HTML構造が不十分になるこれは、Writer AIへの出力ルールがまだ十分に固定されていなかったためです。
単に、
HTML形式で作成してくださいと指示するだけでは、LLMは毎回少し違う形式で出力する可能性があります。
Writer AIの出力ルールを固定する
出力品質を安定させるには、Writer AIに具体的なHTMLルールを与えます。
たとえば、以下のようにします。
重要な出力ルール:
・HTML断片として出力する
・html、head、bodyタグは出力しない
・styleタグ、CSS、JavaScriptは出力しない
・Markdown記法は使わない
・見出しは h2 / h3 を使う
・本文は p タグを使う
・箇条書きは ul / li を使う
・表が必要な場合は table を使うこれにより、CSSあり・なしの揺れを減らせます。
今回は、記事本文として扱いやすくするため、CSSなしのHTML断片に統一する方針が分かりやすいです。
改善後のWriter AIプロンプト例
agents/writer.py の system_prompt は、次のように改善できます。
system_prompt = """
あなたはSEO記事を作成するWriter AIです。
Planner AIの設計に沿って、読みやすく分かりやすい日本語記事をHTML形式で作成してください。
重要な出力ルール:
・HTML断片として出力する
・html、head、bodyタグは出力しない
・styleタグ、CSS、JavaScriptは出力しない
・Markdown記法は使わない
・コードブロック記号 ``` は出力しない
・見出しは h2 / h3 を使う
・本文は p タグを使う
・箇条書きは ul / li を使う
・表が必要な場合は table / tr / th / td を使う
・誇張表現を避ける
・初心者にも理解しやすい文章にする
・根拠のない最新情報や未確認情報は断定しない
"""このように明確なルールを入れることで、Writer AIの出力を安定させやすくなります。
Reviewer AIの役割
Reviewer AIは、Writer AIが作成した記事を確認するエージェントです。
役割は、単なる誤字脱字チェックではありません。
Reviewer AIが担当すること
・検索意図に合っているか確認する
・見出しと本文が一致しているか確認する
・誤字脱字を確認する
・過剰な断定表現を確認する
・AI要約ブロックが分かりやすいか確認する
・FAQが本文と矛盾していないか確認する
・HTML形式がルール通りか確認する特に、第1回で見えた課題を踏まえると、Reviewer AIにはHTML形式のチェックも任せるべきです。
Reviewer AIに追加すべきチェック項目
第1回の最小実装では、Reviewer AIは内容のチェックが中心でした。
しかし、実行結果を見ると、出力形式の揺れも確認すべきです。
そのため、Reviewer AIには以下のチェックを追加します。
・styleタグが含まれていないか
・CSSが混ざっていないか
・JavaScriptが含まれていないか
・Markdown記法が混ざっていないか
・h2 / h3 / p / ul / li で整理されているか
・コードブロック記号 ``` が含まれていないかこれにより、Reviewer AIは「文章の中身」だけでなく、「記事データとして扱いやすいか」も確認できます。
改善後のReviewer AIプロンプト例
agents/reviewer.py では、確認項目を増やします。
def run_reviewer(keyword: str, draft: str) -> str:
"""
Reviewer AI:
Writer AIが作成した記事を確認し、OKまたは修正必要を判定する。
"""
system_prompt = """
あなたは記事品質を確認するReviewer AIです。
記事を読み、SEO・読みやすさ・誤字脱字・過剰表現・構成・HTML形式の観点で確認してください。
重要:
・問題があれば、Writer AIが修正しやすいように具体的に指摘してください。
・問題がなければ、最後に必ず「判定:OK」と書いてください。
・修正が必要な場合は、最後に必ず「判定:修正必要」と書いてください。
"""
user_prompt = f"""
以下の記事をレビューしてください。
キーワード:
{keyword}
記事:
{draft}
確認項目:
1. 検索意図に合っているか
2. 見出しと本文が一致しているか
3. 誤字脱字がないか
4. 過剰な断定表現がないか
5. AI要約ブロックが分かりやすいか
6. FAQが本文と矛盾していないか
7. styleタグ、CSS、JavaScriptが含まれていないか
8. Markdown記法が混ざっていないか
9. コードブロック記号 ``` が含まれていないか
10. HTMLタグの構造が崩れていないか
11. h2 / h3 / p / ul / li などで整理されているか
12. 根拠のない最新情報を断定していないか
出力形式:
・良い点
・修正点
・Writer AIへの具体的な修正指示
・判定:OK または 判定:修正必要
最後の行には、必ず以下のどちらかを書いてください。
判定:OK
または
判定:修正必要
"""
return call_gemma4(system_prompt, user_prompt)Reviewer AIの最後に必ず、
判定:OKまたは、
判定:修正必要を出させることで、プログラム側で次の処理を判断しやすくなります。
WriterとReviewerはループさせるべきか
実用性を高めるなら、WriterとReviewerはループさせるべきです。
第1回の最小実装では、流れは以下でした。
Writer
↓
Reviewer
↓
Writer
↓
保存この場合、最後のWriter修正版をReviewerが確認していません。
つまり、保存される記事は、ReviewerがOKを出した記事とは限らないという問題があります。
そこで、次のような流れに改善します。
Writer
↓
Reviewer
├ OK → 保存
└ 修正必要 → Writerへ戻す
↓
Reviewer再確認
このように、ReviewerがOKを出した記事だけを保存する方が、AI記事作成システムとして自然です。
ループ回数には上限をつける
ただし、WriterとReviewerを無制限にループさせるのは危険です。
Reviewer AIが毎回「修正必要」と判定すると、処理が終わらなくなる可能性があります。
そのため、最大回数を決めます。
最大レビュー回数:3回のようにしておくと安全です。
流れは以下です。
1回目レビュー:修正必要
↓
Writer修正
2回目レビュー:修正必要
↓
Writer修正
3回目レビュー:OKなら保存
↓
修正必要でも最大回数のため保存または停止最初は、最大回数に達したら「最後の修正版を保存する」形でも十分です。
レビューOK判定の簡易実装
Reviewer AIの出力からOK判定を確認する関数を作れます。
def is_review_ok(review: str) -> bool:
return "判定:OK" in review or "判定: OK" in reviewこれは簡易的な判定です。
将来的には、Reviewer AIの出力をJSON形式にして、
{
"status": "OK",
"issues": [],
"summary": "記事品質に問題ありません"
}のようにすると、より安定して判定できます。
ただし、第2回の段階では、まず文字列判定でも十分です。
出力ファイル上書き防止
第1回では、出力ファイル名がfinal_article.htmlで固定でした。
そのため、プログラムを複数回実行すると、前回の記事が上書きされてしまいました。
これはエージェントの役割そのものではありませんが、マルチエージェントの出力を比較・改善するうえでは大きな問題です。
たとえば、次のような比較ができません。
・1回目の出力
・2回目の出力
・Reviewer修正後の出力
・プロンプト変更前後の出力そこで、ファイル名に作成日時を入れることとしました。
from datetime import datetime
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"final_article_{timestamp}.html"これで、以下のようにファイルが残り、プログラムを複数回実行しても上書きされず、出力結果を比較できます。
final_article_20260428_153012.html
final_article_20260428_154530.html
final_article_20260428_160105.html
役割分担を整理した改善後の流れ
第2回時点で目指す流れは、以下です。
キーワード入力
↓
Planner AI:記事設計
↓
Writer AI:初稿作成
↓
Reviewer AI:レビュー
↓
OKなら保存
↓
修正必要ならWriter AIへ戻す
↓
Reviewer AIが再確認
↓
日時付きファイル名で保存これにより、最小実装よりも品質が安定しやすくなります。
改善後のmain.pyイメージ
第2回では、全体フローを以下のように整理できます。
from datetime import datetime
from agents.planner import run_planner
from agents.writer import run_writer
from agents.reviewer import run_reviewer
from mcp_client import save_article
MAX_REVIEW_LOOPS = 3
def is_review_ok(review: str) -> bool:
return "判定:OK" in review or "判定: OK" in review
def main():
print("Gemma 4ローカル・マルチエージェント記事作成システム")
print("-" * 50)
keyword = input("記事キーワードを入力してください: ").strip()
if not keyword:
print("キーワードが入力されていません。終了します。")
return
print("\n[1] Planner AI が記事設計を作成中...")
plan = run_planner(keyword)
print("\n[2] Writer AI が初稿を作成中...")
article = run_writer(keyword=keyword, plan=plan)
latest_review = ""
for loop_count in range(1, MAX_REVIEW_LOOPS + 1):
print(f"\n[3] Reviewer AI がレビュー中... ({loop_count}/{MAX_REVIEW_LOOPS})")
latest_review = run_reviewer(keyword=keyword, draft=article)
if is_review_ok(latest_review):
print("\nReviewer AI の判定:OK")
break
print("\nReviewer AI の判定:修正必要")
print(f"\n[4] Writer AI がレビュー指摘に従って修正中... ({loop_count}/{MAX_REVIEW_LOOPS})")
article = run_writer(
keyword=keyword,
plan=plan,
review=latest_review,
previous_draft=article,
)
else:
print("\n最大レビュー回数に達しました。最後の修正版を保存します。")
print("\n[5] MCP経由でHTMLを保存中...")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"final_article_{timestamp}.html"
result = save_article(filename, article)
print("\n完了しました。")
print(f"保存先: {result['path']}")
if __name__ == "__main__":
main()このコードでは、Reviewer AIがOKを出すまで、最大3回までWriter AIに修正させます。
修正後のプログラム
第2回での主な変更点は以下の通りです。
・final_article.html 固定をやめ、日時付きファイル名で保存
・Writer AI ⇄ Reviewer AI のレビュー・修正ループを追加
・Reviewer AI が OK 判定したら保存
・最大レビュー回数を設定
・Writer AI のHTML出力ルールを固定
・Reviewer AI にHTML形式チェックを追加ファイル構成
第1回からの変更はありません。
article-agent/
├ main.py
├ llm_client.py
├ agents/
│ ├ planner.py
│ ├ writer.py
│ └ reviewer.py
├ mcp_client.py
├ mcp_server.py
└ output/
第2回修正後のプログラム
以下が、第2回での修正後プログラム一式です。
llm_client.py
import ollama
MODEL_NAME = "gemma4:e4b"
# Windows側OllamaのIPv4アドレスに置き換えてください
# 例:OLLAMA_HOST = "http://192.168.x.x:11434"
OLLAMA_HOST = "http://192.168.x.x:11434"
client = ollama.Client(host=OLLAMA_HOST)
def call_gemma4(system_prompt: str, user_prompt: str) -> str:
"""
Gemma 4をOllama経由で呼び出す共通関数。
Planner / Writer / Reviewer の全役割で使う。
"""
response = client.chat(
model=MODEL_NAME,
messages=[
{
"role": "system",
"content": system_prompt,
},
{
"role": "user",
"content": user_prompt,
},
],
)
return response["message"]["content"]agents/planner.py
from llm_client import call_gemma4
def run_planner(keyword: str) -> str:
"""
Planner AI:
キーワードから記事設計を作成する。
"""
system_prompt = """
あなたは記事設計を担当するPlanner AIです。
入力されたキーワードをもとに、SEO記事の設計を行ってください。
本文は書かず、Writer AIが記事を書きやすいように設計情報を整理してください。
出力は日本語で、分かりやすく整理してください。
"""
user_prompt = f"""
以下のキーワードで記事設計を作成してください。
キーワード:
{keyword}
必ず含める項目:
1. 想定読者
2. 検索意図
3. 記事目的
4. SEOタイトル案
5. h2/h3構成
6. 執筆時の注意点
7. Writer AIへの指示
"""
return call_gemma4(system_prompt, user_prompt)agents/writer.py
from llm_client import call_gemma4
def run_writer(
keyword: str,
plan: str,
review: str | None = None,
previous_draft: str | None = None,
) -> str:
"""
Writer AI:
Planner AIの設計に沿って記事を作成する。
Reviewer AIの指摘がある場合は、前回の記事を修正する。
"""
system_prompt = """
あなたはSEO記事を作成するWriter AIです。
Planner AIの設計に沿って、読みやすく分かりやすい日本語記事をHTML形式で作成してください。
重要な出力ルール:
・HTML断片として出力する
・html、head、bodyタグは出力しない
・styleタグ、CSS、JavaScriptは出力しない
・Markdown記法は使わない
・コードブロック記号 ``` は出力しない
・見出しは h2 / h3 を使う
・本文は p タグを使う
・箇条書きは ul / li を使う
・表が必要な場合は table / tr / th / td を使う
・誇張表現を避ける
・初心者にも理解しやすい文章にする
・根拠のない最新情報や未確認情報は断定しない
"""
if review and previous_draft:
user_prompt = f"""
以下の記事を、Reviewer AIの指摘に従って修正してください。
キーワード:
{keyword}
記事設計:
{plan}
修正前の記事:
{previous_draft}
Reviewer AIの指摘:
{review}
修正条件:
・Reviewer AIの指摘を反映する
・HTML断片として出力する
・html、head、bodyタグは出力しない
・styleタグ、CSS、JavaScriptは出力しない
・Markdown記法は使わない
・コードブロック記号 ``` は出力しない
・h2 / h3 / p / ul / li / table などのHTMLタグで整理する
・SEOタイトル、メタディスクリプション、AI要約ブロック、本文、FAQ、まとめを含める
"""
else:
user_prompt = f"""
以下の記事設計をもとに、SEO記事をHTML形式で作成してください。
キーワード:
{keyword}
記事設計:
{plan}
出力条件:
・HTML断片として出力する
・html、head、bodyタグは出力しない
・styleタグ、CSS、JavaScriptは出力しない
・Markdown記法は使わない
・コードブロック記号 ``` は出力しない
・SEOタイトルを含める
・メタディスクリプションを含める
・AI要約ブロックを含める
・h2/h3構成に沿った本文を作成する
・FAQを含める
・まとめを含める
"""
return call_gemma4(system_prompt, user_prompt)agents/reviewer.py
from llm_client import call_gemma4
def run_reviewer(keyword: str, draft: str) -> str:
"""
Reviewer AI:
Writer AIが作成した記事を確認し、OKまたは修正必要を判定する。
"""
system_prompt = """
あなたは記事品質を確認するReviewer AIです。
記事を読み、SEO・読みやすさ・誤字脱字・過剰表現・構成・HTML形式の観点で確認してください。
重要:
・問題があれば、Writer AIが修正しやすいように具体的に指摘してください。
・問題がなければ、最後に必ず「判定:OK」と書いてください。
・修正が必要な場合は、最後に必ず「判定:修正必要」と書いてください。
"""
user_prompt = f"""
以下の記事をレビューしてください。
キーワード:
{keyword}
記事:
{draft}
確認項目:
1. 検索意図に合っているか
2. 見出しと本文が一致しているか
3. 誤字脱字がないか
4. 過剰な断定表現がないか
5. AI要約ブロックが分かりやすいか
6. FAQが本文と矛盾していないか
7. styleタグ、CSS、JavaScriptが含まれていないか
8. Markdown記法が混ざっていないか
9. コードブロック記号 ``` が含まれていないか
10. HTMLタグの構造が崩れていないか
11. h2 / h3 / p / ul / li などで整理されているか
12. 根拠のない最新情報を断定していないか
出力形式:
・良い点
・修正点
・Writer AIへの具体的な修正指示
・判定:OK または 判定:修正必要
最後の行には、必ず以下のどちらかを書いてください。
判定:OK
または
判定:修正必要
"""
return call_gemma4(system_prompt, user_prompt)mcp_server.py
from pathlib import Path
def save_article(filename: str, content: str) -> dict:
"""
記事をoutputフォルダに保存するMCP風ツール。
第2回時点では正式なMCPサーバーではなく、
将来MCP化しやすい関数として実装する。
"""
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)
path = output_dir / filename
path.write_text(content, encoding="utf-8")
return {
"status": "ok",
"path": str(path),
}mcp_client.py
from mcp_server import save_article as tool_save_article
def save_article(filename: str, content: str) -> dict:
"""
MCPクライアント側の呼び出し口。
第2回時点ではローカル関数を呼び出す。
"""
return tool_save_article(filename, content)main.py
from datetime import datetime
from agents.planner import run_planner
from agents.writer import run_writer
from agents.reviewer import run_reviewer
from mcp_client import save_article
MAX_REVIEW_LOOPS = 3
def is_review_ok(review: str) -> bool:
"""
Reviewer AIの出力からOK判定を確認する。
"""
ok_patterns = [
"判定:OK",
"判定: OK",
"判定: Ok",
"判定: Ok",
]
ng_patterns = [
"判定:修正必要",
"判定: 修正必要",
]
for ng in ng_patterns:
if ng in review:
return False
for ok in ok_patterns:
if ok in review:
return True
return False
def main():
print("Gemma 4ローカル・マルチエージェント記事作成システム")
print("-" * 50)
keyword = input("記事キーワードを入力してください: ").strip()
if not keyword:
print("キーワードが入力されていません。終了します。")
return
print("\n[1] Planner AI が記事設計を作成中...")
plan = run_planner(keyword)
print("\n[2] Writer AI が初稿を作成中...")
article = run_writer(keyword=keyword, plan=plan)
latest_review = ""
review_passed = False
for loop_count in range(1, MAX_REVIEW_LOOPS + 1):
print(f"\n[3] Reviewer AI がレビュー中... ({loop_count}/{MAX_REVIEW_LOOPS})")
latest_review = run_reviewer(keyword=keyword, draft=article)
print("\n--- Reviewer AI のレビュー結果 ---")
print(latest_review)
print("--- レビュー結果ここまで ---")
if is_review_ok(latest_review):
print("\nReviewer AI の判定:OK")
review_passed = True
break
print("\nReviewer AI の判定:修正必要")
print(f"\n[4] Writer AI がレビュー指摘に従って修正中... ({loop_count}/{MAX_REVIEW_LOOPS})")
article = run_writer(
keyword=keyword,
plan=plan,
review=latest_review,
previous_draft=article,
)
if not review_passed:
print("\n最大レビュー回数に達しました。最後の修正版を保存します。")
print("\n[5] MCP経由でHTMLを保存中...")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"final_article_{timestamp}.html"
result = save_article(filename, article)
print("\n完了しました。")
print(f"保存先: {result['path']}")
if review_passed:
print("保存状態:Reviewer AI のOK判定後に保存しました。")
else:
print("保存状態:最大レビュー回数に達したため、最後の修正版を保存しました。")
if __name__ == "__main__":
main()修正後のプログラムを実行する
WSL側で実行します。
cd ~/article-agent
source .venv/bin/activate
python main.pyキーワード入力待ちの状態になるので、作成する記事のキーワードを入力します。
Gemma 4ローカル・マルチエージェント記事作成システム
--------------------------------------------------
記事キーワードを入力してください:
キーワードを入力すると記事作成処理が始まり、以下の様に処理が進みます。
(キーワード:ブロックチェーン)の場合
Gemma 4ローカル・マルチエージェント記事作成システム
--------------------------------------------------
記事キーワードを入力してください: ブロックチェーン
[1] Planner AI が記事設計を作成中...
[2] Writer AI が初稿を作成中...
[3] Reviewer AI がレビュー中... (1/3)
--- Reviewer AI のレビュー結果 ---
**良い点**
1. **網羅性と構造:** 「超入門編」「仕組みの解説」という流れが明確で、初心者(検索意図)が知りたい情報を段階的に深く学べる構成になっています。
2. **読みやすさ(可読性):** 「村の住民全員が持っている『共有ホワイトボード』」といった具体的で親しみやすい比喩表現が効果的であり、専門用語の理解を助けています。
3. **SEO対策:** タイトル、メタディスクリプション、導入文、そして各セクションのH2見出しがキーワード「ブロックチェーン」と検索意図を網羅的に取り込めており、検索エンジンからの評価が高い構成です。
4. **デザイン的な工夫:** 比較表(従来のデータベース vs ブロックチェーン)や強調ブロック(`div`の背景色)の利用が非常に効果的で、情報が視覚的に整理されています。
5. **要点の明確化:** AIサマリー、各セクションの小見出し(H3)、そして最後のまとめ(リスト)の三重構造により、読者がどこから情報を得るべきか迷うことなく、理解度を深められるよう設計されています。
**修正点**
1. **構造的な重複(結論部分):** 記事の中盤から終盤にかけて、まとめや結論に関するH2見出しが連続しており、情報が散漫になる傾向があります。
* `<h2>ブロックチェーンの仕組みをまとめると...</h2>`(ボックス型まとめ)
* `<h2>ブロックチェーンって何がすごいの?</h2>`(まとめの問いかけ)
* `<h2>本記事のまとめ</h2>`(リスト形式の再まとめ)
これらがほぼ同じ「まとめ」の内容を異なる形で繰り返しており、読者に「どこが最終的なまとめなのか?」という混乱を与える可能性があります。
2. **表現のトーン(軽微な過剰表現):** 全体的に断定的ながら専門的で説得力がありますが、最終的なまとめを簡潔にまとめることで、より冷静で「信頼できるガイド」としてのトーンが際立ちます。
**Writer AIへの具体的な修正指示**
記事のフローは非常に優れていますが、結論部分(「ブロックチェーンの仕組みをまとめると...」以降)の重複を解消し、読者に最後のメッセージを強く伝える構造にブラッシュアップしてください。
1. **結論ブロックの統合:** `<h2>ブロックチェーンの仕組みをまとめると...</h2>`、`<h2>ブロックチェーンって何がすごいの?</h2>`、`<h2>本記事のまとめ</h2>`の3つのH2見出しを廃止し、最後の「本記事のまとめ」の内容を深掘りした単一のH2(例:`<h2>まとめ:ブロックチェーンが変える未来の信頼(今後の展望)</h2>`など)に統合してください。
2. **情報の流れの改善:** 最後に「まとめ」を行う際は、「これだけは覚えてほしい3つのポイント」といった形で、メッセージ性を強くし、具体的な展望(金融以外の用途、社会変革の可能性)に焦点を当てることで、単なる情報の羅列ではなく「読者への示唆」として終わることができます。
**判定:修正必要**
---
*(レビューAIとしての最終判定)*
--- レビュー結果ここまで ---
Reviewer AI の判定:修正必要
[4] Writer AI がレビュー指摘に従って修正中... (1/3)
[3] Reviewer AI がレビュー中... (2/3)
--- Reviewer AI のレビュー結果 ---
**【重要】レビュー対象の本文が「(コンテンツ本文ここに挿入)」というプレースホルダーのみのため、具体的な記事内容に関する評価を行うことができません。構造的な観点からのレビューと、記事内容の補完が必要である旨を指摘します。**
### 良い点
* **構造の準備:** 記事を格納するための基本的なHTMLタグ(`<div id="content">`)が用意されており、コンテンツ挿入の準備が整っています。
* **網羅的な指示:** ユーザーが提供している確認項目が非常に詳細で、品質管理の視点が包括的です。
### 修正点
* **記事内容の欠落:** 最も大きな問題点として、SEOや読者に価値を提供する「記事本文」が一つも含まれていません。これはレビューの実施を不可能にしています。
* **構造的な改善点(仮定):** 本文を挿入する際は、最低限、適切な構造タグ(`<h2>`、`<h3>`、`<p>`、`<ul>`など)を用いて、読みやすく論理的な流れを意識して記述する必要があります。
### Writer AIへの具体的な修正指示
1. **記事本文の入力:** まず、ターゲットキーワード(ブロックチェーン)に基づいた、検索ユーザーの疑問や知りたい情報(検索意図)を満たす具体的な記事本文全体を記述してください。
2. **構造化:** 本文を記述する際は、単なる文章の羅列にせず、H2タグ(大見出し)とH3タグ(小見出し)を適宜使用し、情報を階層的に整理してください。
3. **結論の明確化:** 読者が「この記事から何を得られるか」を冒頭や最後に明確に伝えるためのまとめや結論部分を設けることを推奨します。
### 判定
判定:修正必要
--- レビュー結果ここまで ---
Reviewer AI の判定:修正必要
[4] Writer AI がレビュー指摘に従って修正中... (2/3)
[3] Reviewer AI がレビュー中... (3/3)
--- Reviewer AI のレビュー結果 ---
・良い点
構成が非常に優れており、専門的なテーマを扱うガイド記事として理想的です。
1. **流れの完璧さ:** 導入(定義)→ 仕組み(技術解説)→ 応用(事例)という流れが非常に論理的で、読者が飽きずに理解を深められる構造になっています。
2. **視覚的な理解促進:** 「従来のデータベースとの比較表」は、抽象的な概念を具体的な比較軸で説明できており、読者の理解を飛躍的に深める非常に効果的な要素です。
3. **トーン&マナー:** 専門的でありながら、「専門的な知識がなくても『なるほど!』と感じられるよう」という目的を達成するための親切なトーンが保たれています。
4. **網羅性:** 「Web3」「分散型」「改ざん不能」「透明性」など、関連する重要なキーワードを自然に盛り込めています。
・修正点
全体的に非常に高品質ですが、プロフェッショナルな記事としてさらに洗練させるための改善点を提案します。
1. **インラインCSSの修正(メンテナンス性):** 仕組みの解説部分にある、`style="background-color: #f0f0f0; padding: 10px; border-left: 5px solid #0056b3;"` のようなインラインCSSは、後々の修正やデザインの一貫性の維持が難しくなります。もしこの装飾的な強調を維持したい場合は、専用のクラス名を設定し、CSSファイル(または`<style>`タグ)で管理することをおすすめします。
2. **冗長なリード文の調整(初速改善):** 導入部(リード文)の熱意は伝わりますが、最初に「何が言えるか(結論)」を提示する部分をもう少し前に出すことで、読者の離脱率を下げ、記事への集中力を高めることができます。
3. **マークアップの微調整(H2の統一性):** 「目次」セクションの前に、単なるH2ではなく、目次であることを示す区切り(例:目次見出し)を設け、よりセクションの境界を明確にすると、読みやすさが向上します。
・Writer AIへの具体的な修正指示
1. **目次セクションの改善:** 「この記事で学べること(目次)」のH2直前に、目次であることを強調する、単体の見出し要素(例えば、キャプションのような装飾)を追加するか、「この記事の構成」といったより明確な見出しに変更してください。
2. **技術解説の装飾の修正:** 「【まとめ】なぜブロックチェーンは信頼できるのか?」のボックス装飾について、`<h3 style="..."`となっている部分の`style`属性を削除し、代わりにクラス名(例:`info-box`)を利用して装飾を行うよう修正してください。これにより、コーディングの可読性が高まり、CMSでの管理が容易になります。
3. **リード文の調整(優先度):** 記事の導入部において、長い問いかけや「気づきを促す」要素を減らし、代わりに「この記事を読むと、〇〇がわかる」といった形で、読者への即時的なメリット提示をより強調してください。(ただし、この変更は任意です。)
**評価のまとめ:**
非常に論理的で、初心者から一定レベルの読者まで対応できる構成の良質なコンテンツです。表現や構造に大きな問題はありませんが、微調整を加えることで、プロフェッショナルなWeb記事としての完成度が一段上がります。
--- レビュー結果ここまで ---
Reviewer AI の判定:修正必要
[4] Writer AI がレビュー指摘に従って修正中... (3/3)
最大レビュー回数に達しました。最後の修正版を保存します。
[5] MCP経由でHTMLを保存中...
完了しました。
保存先: output/final_article_20260429_160118.html
保存状態:最大レビュー回数に達したため、最後の修正版を保存しました。記事の作成が完了すると、article-agent/output/フォルダに、HTML記事(final_article_年月日_時間.html)が保存されます。
今回の修正プログラムで、キーワードがブロックチェーンで作成された記事を以下に添付します。
ファイル形式:Shift_JIS
ファイル形式:UTF-8
「最新情報」が反映されない問題への対応
第1回の検証では、キーワードに「最新」を入れても、最新情報が十分に反映されないケースがありました。
これは、現在のシステムにWeb検索機能がないためです。
Gemma 4はローカルLLMとして動いています。
そのため、現時点の構成では、Webにアクセスして最新情報を取得しているわけではありません。
つまり、現在の構成は以下です。
ローカルLLMの内部知識だけで記事を書くそのため、次のようなキーワードでは注意が必要です。
・最新AI
・AI 2026年
・最新トレンド
・新機能
・リリース情報これらを正確に扱うには、将来的にResearcher AIとWeb検索MCPを追加する予定です。
ただし、それは第5回以降で扱う内容にします。
第2回では、まず Planner / Writer / Reviewer の役割を安定させること に集中して修正しました。
第2回での結論
今回の修正により、Writer AIとReviewer AIをループさせ、日時付きファイル名で記事を保存できるようになりました。
一方で、実行結果からは、Writer AIが途中で本文をプレースホルダー化してしまうケースや、CSSを出力しない指示にもかかわらずstyleタグやインラインCSSが残るケースが確認できました。
つまり、マルチエージェントをループさせるだけでは、品質が必ず安定するわけではありません。
次回は、Planner・Writer・Reviewerの各出力を途中保存し、どの段階で出力が崩れたのかを確認できるようにします。
今後のシリーズ構成
今回の検証結果を踏まえ、シリーズ構成は次のように整理できます。
第1回:Gemma 4・Ollama・WSLで最小実装
第2回:Planner / Writer / Reviewer の役割を整理する
第3回:AI記事作成の失敗原因を見つける|途中保存でマルチエージェントをデバッグする
第4回:MCP風ツールを正式なMCP構成へ近づける
第5回:Researcher AIとWeb検索MCPで最新情報に対応する
第6回:イベント駆動型マルチエージェントへ発展させるまとめ:AIマルチエージェントは役割分担が重要
AIマルチエージェント構成では、単にAIを複数回呼び出すだけでは不十分です。
重要なのは、それぞれのAIに明確な役割を与えることです。
Planner AI:何を書くかを決める
Writer AI:設計に沿って書く
Reviewer AI:品質を確認するさらに、実用性を高めるには、次の改善も必要です。
・WriterとReviewerをループさせる
・ReviewerがOKを出した記事を保存する
・HTML出力ルールを固定する
・保存ファイル名に日時を入れる第1回では、Gemma 4を使ってAIマルチエージェント記事作成システムを最小構成で動かしました。
第2回では、その中核となる Planner / Writer / Reviewer の役割を整理しました。
第3回では、AI記事作成の失敗原因を見つけ、途中保存でマルチエージェントをデバッグします。
