【第7回】AI記事作成 イベント駆動型マルチエージェントへ発展させる

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

第7回では、これまで順番に実行していたAI記事作成フローを、イベント駆動型の考え方で整理します。
Reviewer AIのJSON判定やPython側HTMLチェックの結果を status として扱い、
article.revision_requiredvalidation.failedarticle.approved などのイベントに変換します。
これにより、AIエージェント同士の処理を追跡しやすくなり、将来的なDispatcher実装や正式なイベント駆動システムへ発展させやすくなります。

第6回AI記事作成まででできたこと

第6回AI記事作成では、Planner AI、Writer AI、Reviewer AIに加えて、Researcher AI を追加しました。

Researcher AIは、記事を書く前に検索クエリを作成し、Brave Search APIを使ったWeb検索MCP風ツールから検索結果を受け取り、Writer AIへ渡す調査メモを作成しました。

これにより、ローカルLLMだけでは不足しやすい最新情報を、記事作成フローに取り込めるようになりました。

第6回AI記事作成までの流れは、次のような順番実行型です。

Planner AI

Researcher AI

Writer AI

Reviewer AI

Python側HTMLチェック

保存

この形は分かりやすく、学習にも向いています。
ただし、エージェントが増えるほど、main.py が大きくなりやすいという問題があります。
そこで第7回AI記事作成では、処理を イベント駆動型 の考え方で整理します。

イベント駆動型とは

イベント駆動型とは、簡単にいうと、何かが起きたら、それに応じて次の処理を実行する仕組みです。

これまでの処理では、main.py が順番に各処理を呼んでいました。

main.pyが順番に呼ぶ

Planner AI

Researcher AI

Writer AI

Reviewer AI

Validator

保存

イベント駆動型では、処理結果をイベントとして扱います。

イベント駆動型マルチエージェント処理の流れ
plan.created

research.completed

draft.created

review.completed

validation.completed

article.approved

article.saved

つまり、処理を単なる順番ではなく、状態の変化として見る考え方です。

イベント駆動型にする理由

イベント駆動型にする理由は、マルチエージェント構成が大きくなったときに管理しやすくするためです。

第6回までの構成では、main.py が多くの判断を持っています。

・次にどのAIを呼ぶか
・レビュー結果がOKか
・修正が必要か
・HTMLチェックが通ったか
・保存するか
・最大レビュー回数に達したか

この判断が増えると、main.py が複雑になります。

イベント駆動型では、次のように整理します。

何が起きたか

どのeventか

statusは何か

次に実行する処理を決める

たとえば、Reviewer AIがOKを出した場合は、次のように考えます。

review.completed

status = OK

Validatorへ進む

一方で、Reviewer AIが修正必要と判断した場合は、次のようになります。

review.completed

status = REVISION_REQUIRED

Writer AIへ戻して修正

第5回AI記事作成のJSON判定の利用

第7回AI記事作成で重要になるのが、第5回で実装したReviewer AIのJSON判定です。

第5回では、Reviewer AIの自然文レビューとは別に、次のようなJSONを出力させました。

この statusnext_action は、イベント駆動型にそのまま使えます。

status: OK

article.approved

status: REVISION_REQUIRED

article.revision_required

status: UNKNOWN

review.failed

つまり、第5回でJSON化したことは、第7回でイベント駆動型へ進むための準備だったといえます。

第7回AI記事作成で使うイベント例

第7回では、まず次のようなイベントを使います。

plan.created
research.completed
draft.created
draft.revised
review.completed
article.revision_required
validation.completed
validation.failed
article.approved
article.saved

それぞれの意味は次の通りです。

イベント名意味
plan.createdPlanner AIが記事設計を作成した
research.completedResearcher AIが調査メモを作成した
draft.createdWriter AIが初稿を作成した
draft.revisedWriter AIが修正版を作成した
review.completedReviewer AIがレビューを完了した
article.revision_requiredReviewer AIにより修正が必要と判断された
validation.completedPython側チェックが完了した
validation.failedPython側チェックで問題が見つかった
article.approved記事が公開可能と判断された
article.saved最終記事が保存された

このようにイベント名を決めておくと、あとから処理を追加しやすくなります。

修正ループは2種類ある

第7回AI記事作成では、修正ループを2種類に分けて考えます。

2種類の修正ループを表すフロー

1つ目は、Reviewer AI起点の修正ループです。

Writer AI

Reviewer AI

修正必要

Writer AIへ戻す

Reviewer AIは、主に次のような観点を見ます。

・記事構成
・読みやすさ
・SEO観点
・トーン
・内容の不足
・検索意図とのズレ

2つ目は、Validator起点の修正ループです。

Writer AI

Reviewer AI

OK

Validator

問題あり

Writer AIへ戻す

Validatorは、主に次のような機械的・形式的な問題を見ます。

・HTML断片として正しいか
・styleタグやscriptタグがないか
・Markdown記法が残っていないか
・pタグやh2タグがあるか
・プレースホルダーが残っていないか
・不自然なHTMLタグがないか

つまり、第7回では次のように整理できます。

Reviewer AI
→ 内容の改善点を返す

Validator
→ 形式・構造の改善点を返す

Writer AI
→ 両方の指摘を受けて修正する

処理の流れをイベントで置き換える

イベント駆動型マルチエージェントに向けて、第6回AI記事作成までの流れをイベントを使って置き換えます。

処理の流れをイベントで置き換える

第6回AI記事作成までの流れは、次のような順番実行型でした。

1. Planner AIが記事設計を作る
2. Researcher AIが調査メモを作る
3. Writer AIが記事を書く
4. Reviewer AIがレビューする
5. Python側HTMLチェックをする
6. OKなら保存する

第7回AI記事作成では、これをイベントとして実行します。

plan.created

research.completed

draft.created

review.completed

validation.completed

article.approved

article.saved

修正が必要な場合は、次のようになります。

draft.created

review.completed

article.revision_required

draft.revised

review.completed

validation.completed

article.approved

article.saved

Validatorで問題が出た場合は、次の流れです。

review.completed

status = OK

validation.completed

validation.failed

draft.revised

review.completed

validation.completed

article.approved

article.saved

このようにイベントとして整理すると、記事作成の流れを「状態遷移」として追跡できます。

第7回AI記事作成 ファイル構成と追加・変更ファイル

第7回AI記事作成のファイル構成

第7回AI記事作成で追加するファイル

event_types.py

イベント名をまとめるためのファイルです。

役割:
・イベント名を定数として管理する
・plan.created などの文字列のタイプミスを防ぐ
・main.py からイベント名を呼び出しやすくする

主なイベント名は以下です。

PLAN_CREATED
RESEARCH_COMPLETED
DRAFT_CREATED
DRAFT_REVISED
REVIEW_COMPLETED
ARTICLE_REVISION_REQUIRED
VALIDATION_COMPLETED
VALIDATION_FAILED
ARTICLE_APPROVED
ARTICLE_SAVED

event_types.py

イベント名を定義するファイル。

event_bus.py

イベントを記録するためのファイルです。

役割:
・処理の節目で event を発行する
・event / status / payload を記録する
・最後に event_log.json として保存できる形にする

第7回AI記事作成では、正式なイベントキューや非同期処理をつくりません。

event_bus.pyイベント履歴を記録する簡易EventBus として使います。

event_bus.py

イベントを記録するファイル。

第7回AI記事作成で変更するファイル

main.py

第7回で最も大きく変更するファイルです。

変更内容:
・EventBusを読み込む
・event_types.py のイベント名を読み込む
・Planner完了時に plan.created を記録する
・Researcher完了時に research.completed を記録する
・Writer初稿作成時に draft.created を記録する
・Writer修正時に draft.revised を記録する
・Reviewer完了時に review.completed を記録する
・Reviewerが修正必要なら article.revision_required を記録する
・Validatorチェック完了時に validation.completed を記録する
・Validatorで問題があれば validation.failed を記録する
・記事がOKなら article.approved を記録する
・保存完了時に article.saved を記録する
・event_log.json を保存する

第7回では、main.pyディスパッチャー相当 の役割も持ちます。

event_bus.py
→ イベントを記録する

main.py
→ event / status を見て次の処理を決める

main.py

第6回AI記事作成の処理に、event_bus.pyevent_types.py を追加して、各処理の節目で event_log.json にイベントを記録する構成です。

agents/researcher.py

出力が日本語以外になる場合のを修正。

agents/researcher.py

第7回AI記事作成で追加される出力ファイル

第7回では、実行結果フォルダに以下が追加されます。

第7回AI記事作成の実行結果

ターミナル出力

(UTF-8)

(SHIFT-JIS)

出力記事

(UTF-8)

(SHIFT-JIS)

event_log.json

(UTF-8)

(SHIFT-JIS)

イベント駆動型マルチエージェント実装範囲

第7回のイベント駆動型マルチエージェントでは、正式なDispatcherや非同期イベントキューまで実装しません。

第7回のイベント駆動型マルチエージェントでの実装範囲は以下の様になります。

実装する機能:
・イベント名を定義する
・イベントを記録する
・event_log.json に保存する
・main.py の分岐をディスパッチャー相当として扱う

実装しない機能:
・dispatcher.py の分離
・本格的なEvent Queue
・非同期処理
・ワーカー実行
・リトライ制御

つまり、第7回の追加・変更は最小限で、イベント駆動型の考え方を現在のマルチエージェント記事作成システムに導入する回です。

まとめ:イベント化するとAIエージェントの流れが見える

第7回AI記事作成では、これまで順番に実行していたAI記事作成フローを、イベント駆動型の考え方で整理しました。

第5回でReviewer AIの判定をJSON化し、第6回でResearcher AIとWeb検索MCP風ツールを追加しました。

第7回では、その結果を eventstatus で扱います。

Reviewer AIがOK

review.completed

validation.completed

Reviewer AIが修正必要

article.revision_required

Writer AIへ戻す

Validatorが問題を検出

validation.failed

Writer AIへ戻す

このように、処理の節目をイベントとして記録することで、どこで何が起きたかを追いやすくなります。

第7回は、ローカルAIマルチエージェント記事作成システムを、状態を持つエージェントシステムへ変更する回でした。

今回のイベント駆動型では、ディスパッチャー部分は main.py 内の status 判定と分岐処理になります。

今後、本格的にイベント駆動型にする場合は、ディスパッチャー部分をmain.pyから分離してDispatcherでイベント振り分けをする必要があります。

Dispatcherを実装したイベント駆動型マルチエージェント

Dispatcherを実装したイベント駆動型マルチエージェントの処理フロー図