AI記事生成で重複コンテンツを防ぐ設計──スプレッドシートとWordPressの2段構えにした理由
重複コンテンツのリスクは最初から分かっていた
AI記事生成システムを設計するとき、重複コンテンツの問題は最初から意識していました。
理由は自分のブログ運営の経験からです。普段使っているBizinetsの記事パイプラインでは、投稿済み記事の情報をCSVに記録して、次の記事作成時にそのCSVを参照して重複を防ぐ仕組みを使っています。同じ構造をDifyでも実装しようと、最初からGoogleスプレッドシートを設計に組み込みました。
スプレッドシートだけでは防げないことに気づいた
ただ、実装を進めるうちに問題が見えてきました。
Googleスプレッドシートに記録できるのは、このシステムで投稿した記事だけです。それ以前にWordPressに手動で投稿していた記事や、別の方法で作った記事は記録されていません。
つまりスプレッドシートの重複チェックは、システム稼働後の記事しか対象にならない。既存の投稿記事と似たキーワードで新しい記事を作ってしまうリスクが残るわけです。
そこでWordPressのREST APIから投稿済み記事の一覧を取得して、スプレッドシートの記録と合わせて重複チェックに使う設計に変えました。
変更前:スプレッドシートのみ参照
変更後:スプレッドシート + WordPressの投稿記事 を合算して参照403エラーが結果的にコスト節約になった
皮肉な話ですが、この設計変更を実装したとき、403エラーが助かる結果をもたらしました。
Difyのワークフローは最初のHTTPリクエストが成功しないと次のノードに進みません。WordPressへの記事取得リクエストが最初のノードにあったおかげで、エックスサーバーの海外IP制限に引っかかって即座にエラーが出ました。
言い換えると、最初のステップで止まったため、後続のAI処理(クレジット消費が大きい部分)が一切動かなかったのです。
設計ミスを早期に検出できたうえ、無駄なAPIコストも発生しませんでした。重複防止の仕組みを最初に置いたことが、結果的にエラー検出の早期化にもつながりました。
2つのHTTPノードが1つにまとまった
最初の設計では、スプレッドシートからデータを取得するHTTPノードとWordPressから取得するHTTPノードを並列で置いていました。
ところが、GASを中継に使う設計に変えた結果、両方の処理をGASのactionで振り分けられるようになりました。
変更前:
HTTPノードA → Googleシートから取得
HTTPノードB → WordPressから取得(403エラーで失敗)
変更後:
HTTPノード1本 → GASにPOST
→ action: get_articles
→ シートのデータ + WPの投稿記事を合算して返すノードが減ってワークフローがシンプルになりました。GASの中でスプレッドシートとWordPressの両方を処理するため、Dify側は1本のHTTPリクエストで済みます。
重複防止の精度と限界
この仕組みで重複コンテンツのリスクはかなり減りました。ただ完全ではありません。
現在の重複チェックは「キーワードとタイトルの文字列一致」を見ています。意味的に近い記事(別のキーワードだが内容が被る)は検出できません。
現在の精度:
✓ 同一キーワードの重複 → 防げる
✓ 同一タイトルの重複 → 防げる
✗ 意味的に近いが表現が違う記事 → 防げない意味的な重複を防ぐには、記事の内容を比較する仕組みが必要です。現時点では実装していません。
動いてから見えてきた問題
システムが動いてGoogleシートに記事が溜まり始めたとき、別の疑問が浮かびました。
重複を防ぐことはできた。でも、何を書くべきかの判断はどこにもありません。
システムはキーワードを生成して記事を書きます。重複しないように管理もします。ただ、そのキーワードがサイト全体の設計として正しいかどうか、読者にとって本当に必要な記事かどうかは、システムには判断できません。
重複しない記事を量産することと、価値ある記事を作ることは別の話です。自動化できるのは前者だけで、後者は設計者が判断しなければなりません。
その「何を書くべきか」の判断軸をどう持つか。それはツールの話ではなく、設計の話です。bizinets.bizで書いています。
bizinets.biz
記事を読んで「もっと知りたい」と思ったあなたへ
bizinets.biz では、ビジネスの仕組みづくりを体系的に学べるコンテンツを用意しています。まずは一度、覗いてみてください。
bizinets.biz へ行く →