
Difyのワークフローを使って今度こそSEO記事を作成する【2024年6月更新】
実は以前もDifyでSEO記事作成を試していました。その模様は「DifyでSEO記事作成を試してみる」に記載しています。ただ、このときはワークフローでの作成はあきらめ、エージェントを使用しています。理由は、当時ワークフローにIteration(ループ処理)がなかったためです。
しかし、2024年5月31日にDifyのv0.6.9がリリースされ、Iterationが実装されました!早速、Iterationを使用してSEO記事作成をやってみたいと思います。結論としてはできたのですが、実用レベルのものができたかというと、、、微妙なところです。
ただ、Iterationの使い方は伝わるんじゃないかと思いますので、ぜひ記事をご覧いただければと思います!
有料記事を購入頂いた方には、このワークフローのDSLをお渡しします!DSLをインポートすれば、私が汗水流しながら?作成したワークフローをそのまま再現することができます。
準備
Difyの環境を作る
今回はMacOSのローカルPC上で動作することを前提とします。
ローカルPC上にDifyを立ち上げる方法は、「DifyでSEO記事作成を試してみる」に詳しく記載していますので、そちらをご覧ください。
また、DifyはかなりアクティブなOSSで頻繁に更新されるため、最新のソースコードに更新しておく必要があります。その方法は「ローカル環境上のDifyでGPT-4oを使えるようにする」をご覧ください。
最新のDifyの仕様を理解する
Difyのワークフローで記事作成するためには、Iterationの機能が必要です。
プロンプト一撃で長い記事作成をしても質のいいものはできず、タスクを分解してなるべく小さい仕事をさせることが、LLMの出力の質を上げるための鉄則ですが、記事作成の場合もまずは見出し構成を決め、各見出しごとの小さく区切った記事作成を順次LLMに依頼するということをします。
そのため、「見出しごとに記事を出力する」という部分にループ処理が必要になり、そこにIterationを使用したいということです。
ということで、Iterationの使い方を調べてみましたが、、、全く情報がでてこない!なんで!?公式ドキュメントは情報の更新が追いついていないのでしょうか。この記事を書いている2024/06/14時点でワークフローのNodeにIterationがまだ追記されていません。
あるのはリリースを告知する動画のみ。ということで、かなり試行錯誤しながら進めました。結果だけを以下にまとめていますが、めちゃめちゃ大変でした。
Dify上でワークフローを設計する
入力と出力を決める
ワークフローは様々な処理をできる「ブロック」をつなぎ合わせて一連の処理を作成するというものです。そのワークフローを通して、最終的に何ができるようになるのかを、まず簡単に定義するところから始めます。
本記事では、以下を前提としてワークフローを作っていきたいと思います。
入力
リライト元参考URL
上位表示したいキーワード
共起語
サジェストワード
対象読者
タイトル
導入文
記事作成の際の注意点
出力
見出し構成
各見出しの文章
つまり、既存の記事をもとに、キーワードや対象読者などある程度の情報は決めていることを前提に、既存の記事を要約して、リライトする形で記事作成をするワークフローを作成していきます。
処理プロセスを設計する
大まかに以下の処理プロセスで記事作成を目指していきます。
与えられたURLをスクレイピングして、記事の内容を取得
記事の内容をすべて要約し、それを端的に表現できる見出し構成を作る
LLMで記事の要約を箇条書きで作成
LLMで箇条書きを見出し構成に変換
LLMで見出し構成を作成
各見出し毎に記事を作成
テンプレートを作成し記事としてまとめる
Dify上でワークフローの各ブロックを作成する

全体像はこんな感じです。一つ一つのブロックで何をしているかを以下で説明します。
Step.1 Start
ブロック Start
入力 上記入力項目すべて
出力 なし
ここは先程列挙した入力項目を指定するだけです。
Step.2 参照元URLの配列を作成

ブロック Code
入力 URLの文字列
出力 文字列配列
Step.1でURLのリストを改行ありの文字列で入力されるため、それをPythonで配列に変換しています。これが必要な理由は、その後で使用するIterationの入力が配列形式である必要があるためです。
Step.3 全URLをスクレイピング

ブロック Iteration
入力 URLの文字列配列
出力 文字列(スクレイピング結果)
Iterationはいわゆるループ処理を行うためのものです。Iterationを使用する場合は、Iterationそのものへの入力と、Iterationからの出力を指定する必要があります。
Step.3-1 各URLをスクレイピング

ブロック Web Scraper
入力 item(Iterationのループ処理内で、各ループ毎に参照される配列の要素。ここでは一つ一つのURL)
出力 文字列(スクレイピング結果)
以前の記事ではCrawlerというToolを使用してURL内のコンテンツを取得しましたが、今回はCrawlerがなぜか動作しなかったため、Web Scraperという別のToolを使用しました。URLを渡せば、その内容を取得してくれます。
Step.4 スクレイピング結果をすべて結合

ブロック Code
入力 スクレイピング結果の文字列配列
出力 文字列
このあとのステップで、与えたURLの内容をすべてマージして要約したいので、単純に全URLの記事の内容を結合してしまいます。
Step.5 記事の見出し構成をGPT-4oで作成

ブロック LLM(モデルはGPT-4oを指定)
入力 文字列(前記事の内容を結合したもの)
出力 文字列(見出し構成案)
前記事の内容をGPT-4oに与え、それを箇条書きで要約し、それをもとにこれから作成する記事の見出し構成案を作ってもらいます。
Step.6 記事の見出し構成をGPT-4oがレビュー、修正

ブロック LLM(モデルはGPT-4oを指定)
入力 文字列(見出し構成案)
出力 文字列(見出し構成最終案)
全Stepで作成した見出し構成案をGPT-4oにレビューさせ、修正させることで最適化します。このステップをいれることで結構質が上がります。
Step.7 見出し構成をPythonの配列の構成にする

ブロック LLM(モデルはGPT-4oを指定)
入力 文字列(見出し構成最終案)
出力 文字列(配列型に整形した文字列)
このあたりからだいぶゴリ押しになってくるのですが、、、Iterationの制約として、A)ネストできない(2重以上のループができない)、B)入力が配列である必要がある(JSONを渡せない)というものがあり、これがネックになって「1:nの関係にある見出し1と見出し2を、見出し1のループを回して、その中で見出し2のループを回して記事作成する」ということがどうしてもできませんでした。
ちょっと伝わりづらいと思いますが、
[
["見出し1: 1つ目の見出し1", "見出し2: 1つ目の見出し2", "概要: 見出し2に対応する概要"],
["見出し1: 1つ目の見出し1", "見出し2: 2つ目の見出し2", "概要: 見出し2に対応する概要"],
["見出し1: 2つ目の見出し1", "見出し2: 1つ目の見出し2", "概要: 見出し2に対応する概要"],
...
["見出し1: n個目の見出し1", "見出し2: 1つ目の見出し2", "概要: 見出し2に対応する概要"],
["見出し1: n個目の見出し1", "見出し2: 2つ目の見出し2", "概要: 見出し2に対応する概要"],
...
["見出し1: n個目の見出し1", "見出し2: n個目の見出し2", "概要: 見出し2に対応する概要"]
]
みたいな配列をGPT-4oに作らせ、一旦文字列形式で出力します。
Step.8 「配列っぽい」文字列型のデータを配列型にする

ブロック Code
入力 文字列(配列型に整形した文字列)
出力 文字列配列
LLMブロックは文字列しか出力できないため、前Stepでは配列っぽい構造を持ったデータを作って文字列として出力しました。これをPyhtonのプログラムで無理やり配列に変換し、Iterationに渡せるようにします。
Step.9 全見出しの記事を作成する

ブロック Iteration
入力 文字列配列
出力 文字列配列(記事本文)
見出しの配列をループ処理で回しながら各見出しの記事本文を作成します。
Step.9-1 各見出しの記事を作成する

ブロック LLM(モデルはGPT-4oを指定)
入力 item(Iterationのループ処理内で、各ループ毎に参照される配列の要素。ここでは見出し1、見出し2を組み合わせた文字列)
出力 文字列(記事本文)
Iterationから渡される見出し1と見出し2、その他Startで入力された情報などを下に、GPT-4oが記事本文を作成します。記事本文作成にあたっては、ほしい内容が出力されるように、結構細かい条件を指定しています。
Step.10 テンプレートを適用する

ブロック Template
入力 文字列配列(記事本文)
出力 文字列
これはおまけのようなものですが、一応記事っぽく整形するために、タイトル、導入文、見出し、本文をテンプレートを使ってまとめます。DifyのTemplateはJinja2を使用しています。
出力を確認

よくわからない・・・笑
まとめ
工夫した点
GPT-4oで見出し構成を作成したあとに、GPT-4oで見出し構成をレビューして修正させると結構いいものに仕上がります。
Iterationで多重ループが使えないことと、JSONを入力できないという制約があるため、GPT-4oにPythonの配列っぽい文字列を作らせるという暴挙(?)により、一応全文ワークフローで出力することはできました。大変だった。。。
改善点、今回できなかった点
GPT-4oに配列を作らせたりしているので、出力が安定せず、たまに配列構造ではないものが出力され、Pythonのエラーが吐かれることがあります。
見出し1 > 見出し2 > 本文、見出し2 > 本文、... > 本文、見出し1 > 見出し2 > … という構造に作成したかったのですが、これがどうしてもできませんでした。もっとワークフローを極めているかた、もしいいアイデアがあればぜひご連絡ください・・!
感想
SEO効果のある記事を作成するくらいのまあまあ大きいタスクをワークフローにやらせるのはなかなか大変。エージェントのほうが良さそう。
ワークフローはもう少し短いステップで済むような処理のほうが向いていそう。
これを言っては元も子もないですが、、、業務に使えるワークフローを作るのであればMake.comを使ったほうがいい。Make.comのほうが柔軟性、拡張性が圧倒的に高い。
最後に
最後までお読みいただき、ありがとうございます!
実は、今回Difyのワークフローでやろうとしていた仕組みはすでに弊社で持っていて、それを利用した「AI記事制作代行サービス」というものを提供しています。ちょうどいい値段で高品質の記事を継続的に作成したいという方はぜひご利用ください!
弊社では、LLM(大規模言語モデル)やアーキテクチャの選定、技術検証、生成AIを使用したプロトタイピングやシステム開発、お客様社内での啓蒙活動等を対応させていただく「生成AIコンサルティング」サービスを提供しています。
もちろん、Difyの構築もお手伝いできます。
また、業務利用できるChatGPTのような仕組みである「セキュアGAI」も提供しています。
この記事は私が経営する株式会社スクーティーのコーポレートブログの下記記事を焼き直したものです。
ここまでご覧いただき、ありがとうございます!
以下からが有料になりますが、本記事で私が作成したワークフローの設定ファイルであるDSLをダウンロードできます。もし記事の拡散にご協力いただけたら無料でダウンロードできます。
ここから先は
この記事が参加している募集
この記事が気に入ったらチップで応援してみませんか?