Paper-Essence 論文精華配信ワークフロー構築チュートリアル
プロジェクト概要
Paper-Essence は、Difyプラットフォームをベースに構築された自動論文配信ワークフローです。このワークフローは以下のことが可能です。
毎日定時にArXivから指定された研究分野の最新論文を取得
大規模モデルを使用して最も価値のある論文をスマートに選別
OCRで論文PDFを解析し、主要な技術的詳細を抽出
構造化された論文日報を生成し、メールで自動配信
GitHubリポジトリ:https://github.com/LiaoYFBH/PaperFlow。prj\Paper-Essence-CN.ymlまたはprj\Paper-Essence-EN.ymlを直接インポートできます。
事前準備
1. プラットフォームとアカウントの準備
- Difyプラットフォームアカウント:Difyプラットフォームに登録し、ログインしていることを確認してください(Dockerデプロイも利用可能)
- メールアカウント:SMTPをサポートするメールアドレスが必要です(本チュートリアルでは163メールを使用)
- 大規模モデルAPI:文心飛槳星河コミュニティのAPIを設定する必要があります
2. 必要なプラグインのインストール
Difyプラグインマーケットで以下のプラグインをインストールしてください。
| プラグイン名 | 用途 |
|---|---|
| PaddleOCR | PDF/画像OCR解析 |
| 163SMTPメール送信 | 163メールSMTP送信 |
| Supabase | データベースストレージ(配信済み論文の記録) |
| 文心飛槳星河コミュニティ | 星河コミュニティAPIによるBaidu Wenxin大規模モデル呼び出し |
3. Supabaseデータベースの準備
ユーザーにすでに配信した論文をフィルタリングする機能を実現するために、ここではクラウドデータベースSupabaseを使用します。
ステップ 1:ログインしてプロジェクトを作成
supabase.comにアクセスし、右上のログインをクリックし、次に「Start your project」をクリックします。
ステップ 2:データテーブルを作成
SQL Editorで以下のSQLステートメントを実行します。
論文配信情報を記録するための新しいテーブルをデータベースに作成します。テーブル名はpushed_papersと定義し、同時にテーブルに2つの主要なフィールドを設定し、データ整合性制約を追加して、論文配信記録の一意性と有効性を確保します。
create table pushed_papers (
arxiv_id text not null,
pushed_at timestamp default now(),
primary key (arxiv_id)
);
ステップ 3:APIキーを取得
Project Settings → APIで以下の情報を記録します。
NEXT_PUBLIC_SUPABASE_URL→ Dify SupabaseプラグインのSupabase URLに対応NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY→ Dify SupabaseプラグインのSupabase Keyに対応
ステップ 4:DifyでSupabaseプラグインを設定
Difyプラグイン管理でSupabaseプラグインを設定し、上記のURLとKeyを入力します。
ワークフロー全体アーキテクチャ
処理説明
| フェーズ | ノード | 機能説明 |
|---|---|---|
| トリガー | タイマートリガー | 毎日指定時刻に自動起動 |
| 設定 | 設定ノード | すべての環境変数を読み込み、後続の処理のために出力 |
| 翻訳 | LLM翻訳 | 研究テーマを英語に翻訳 |
| 検索 | Get Rows → 前処理 → HTTPリクエスト → 後処理 | 配信済み記録を照会し、ArXivの新しい論文を検索 |
| 一次審査 | LLM一次審査 | LLMを使用して上位3論文を選別 |
| イテレーション | イテレーションノード | 各論文に対して:アンパック→記録→OCR→分析→アセンブル を実行 |
| 出力 | テンプレート変換 → メール送信 | フォーマットされたレポートを生成し、メールで配信 |
このワークフローの完全なビュー:
詳細な構築手順
ステップ 1:ワークフローを作成
- Difyプラットフォームにログイン
- 「スタジオ」→「アプリケーションを作成」→「ワークフロー」タイプを選択
- アプリケーション名を入力
- トリガータイプを選択
ステップ 2:環境変数を設定
UI画面右上の設定ボタンをクリックし、環境変数を追加します。
| 変数名 | 型 | 説明 | 例 |
|---|---|---|---|
table_name |
string | Supabaseテーブル名 | pushed_papers |
SMTP_PORT |
string | メールSMTPポート | 465 |
SMTP_SERVER |
string | SMTPサーバー | smtp.163.com |
SMTP_PASSWORD |
secret | メール認証コード | (あなたの認証コード) |
SMTP_USER |
secret | メールアカウント | your_email@163.com |
MY_RAW_TOPIC |
string | 研究テーマ | agent記憶 |
メール認証コードの取得:163メールにログイン → 設定 → POP3/SMTP/IMAP → サービスを有効にして認証コードを取得
ステップ 3:タイマートリガーノード
ノード名:タイマートリガー
設定項目:
- トリガー頻度:毎日(daily)
- トリガー時間:
8:59 AM(または必要に応じて調整)
ステップ 4:設定ノード(コードノード)
ノード名:設定
ノードタイプ:code
このノードは、すべての環境変数を読み込み、後続のノードで使用するために出力する役割を担います。
入力変数:
- 環境変数から読み込み:
SMTP_PORT,SMTP_SERVER,SMTP_USER,SMTP_PASSWORD,MY_RAW_TOPIC,table_name
出力変数:
raw_topic:研究テーマuser_email:受信メールアドレスfetch_count:検索論文数(デフォルト 50)push_limit:配信数制限(デフォルト 3)days_lookback:遡り日数(デフォルト 30)- およびSMTP関連設定
コード:
import os
def main(
SMTP_USER: str,
MY_RAW_TOPIC: str,
SMTP_PORT: str,
SMTP_SERVER: str,
SMTP_PASSWORD: str,
table_name: str
) -> dict:
user_email = SMTP_USER
raw_topic = MY_RAW_TOPIC
smtp_port = SMTP_PORT
smtp_server = SMTP_SERVER
smtp_password = SMTP_PASSWORD
table_name = table_name
return {
"raw_topic": raw_topic,
"user_email": user_email,
"smtp_port": smtp_port,
"smtp_server": smtp_server,
"smtp_password": smtp_password,
"fetch_count": 50,
"push_limit": 3,
"days_lookback": 30,
"table_name": table_name
}
ステップ 5:研究分野翻訳(LLMノード)
ノード名:研究分野LLM翻訳
ノードタイプ:llm
中国語の研究テーマをArXiv APIが認識できる英語のブールクエリ文字列に翻訳します。
モデル設定:
- モデル:
ernie-4.5-turbo-128kまたはernie-5.0-thinking-preview - 温度:
0.7
システムプロンプト:
あなたは専門の学術翻訳アシスタントです。ユーザーが入力した中国語の研究テーマを英語に翻訳し、ArXiv APIに適したブールクエリ文字列形式に変換してください。
要件:
1. 主要なキーワードを特定し、英語に翻訳する
2. 複数のキーワードをAND/ORで結合する
3. 純粋なテキストで出力し、余分な説明は含めない
4. 例:入力「多模态大模型」→ 出力「multimodal AND large language model」
ステップ 6:配信済み記録の照会(Supabaseノード)
ノード名:Get Rows
ノードタイプ:tool (Supabase)
Supabaseデータベースから配信済みの論文記録を照会し、重複配信を回避します。
設定:
- テーブル名:
{{table_name}}(設定ノードから取得)
ステップ 7:論文の検索(3つのノードに分割)
ワークフローの安定性と保守性を向上させるため、検索機能を「前処理」→「HTTPリクエスト」→「後処理」の3つの連続したノードに分割します。
7.1 論文検索ノード前処理 (コードノード)
ノード名:論文検索ノード前処理
ノードタイプ:code
このノードは、検索パラメータの準備、日付範囲の計算、およびArXiv APIクエリ文字列の構築を担当します。
入力変数:
topic:翻訳された英語の検索語days_lookback:遡り日数count:検索数supabase_output:配信済み記録(重複排除用)
コードロジック:
- 遡り日付(cutoff_date)を計算
- Supabaseから返された配信済み論文IDリストを解析
- topicに基づいてブールクエリ文字列を構築(AND/ORロジックをサポート)
- topicキーワードに基づいてArXiv分類制限を追加(例:cs.CV, cs.CLなど)
- 後続のフィルタリングのために検索キーワードを抽出
出力変数:
base_query:構築されたクエリ文字列pushed_ids:配信済みIDリストcutoff_str:締切日文字列search_keywords:検索キーワードリストfetch_limit:API取得上限数
7.2 HTTPリクエスト (HTTPノード)
ノード名:HTTPリクエスト
ノードタイプ:http-request
ArXiv APIを直接呼び出して、元のXMLデータを取得します。
設定:
- API URL:
export.arxiv.org/api/query - Method:
GET - Query Parameters:
search_query:{{base_query}}start:0max_results:{{fetch_limit}}sortBy:submittedDatesortOrder:descending
7.3 論文検索ノード後処理 (コードノード)
ノード名:論文検索ノード後処理
ノードタイプ:code
APIから返されたXMLデータを解析し、詳細なフィルタリングを行います。
入力変数:
http_response_body: HTTPノードの応答ボディ- および前処理ノードのすべての出力変数
コードロジック:
- XML応答を解析
- 重複排除フィルタリング:
pushed_idsに含まれる論文を除外 - 日付フィルタリング:
cutoff_dateより古い論文を除外 - キーワードフィルタリング:タイトルまたは要約に少なくとも1つの検索キーワードが含まれていることを確認
- JSONオブジェクトリストとして出力をフォーマット
出力変数:
result:最終的に選別された論文リスト(JSON文字列)count:最終論文数debug:デバッグ情報(フィルタリング統計を含む)
ステップ 8:LLM一次審査選別(LLMノード)
ノード名:LLM一次審査
ノードタイプ:llm
LLMを使用して論文を一次審査し、最も価値のある論文を選別します。
システムプロンプト:
あなたは経験豊富な学術研究者であり、論文の価値を迅速に評価することに長けています。
タスク:与えられた論文リストから、最も価値のある上位3論文を選別してください。
評価基準:
1. 革新性:手法が新しいか
2. 実用性:実用的な応用価値があるか
3. 影響力:著者機関、発表状況
4. 技術的深さ:技術的なブレークスルーがあるか
出力要件:
- 純粋なJSON配列形式
- すべての元のフィールドを保持する
- 上位3論文を出力する
ステップ 9:JSON解析(コードノード)
ノード名:JSON解析
ノードタイプ:code
LLMが出力したJSON文字列を解析し、さまざまな可能性のある形式を処理します。
コアロジック:
- ネストされたJSONの処理
papersまたはtop_papersフィールドをサポート- 許容範囲内のエラー処理
ステップ 10:イテレーションノード
ノード名:イテレーション
ノードタイプ:iteration
選別された各論文に対してイテレーション処理を実行します。
設定:
- 入力:
top_papers(論文配列) - 出力:
merged_paper(処理後の論文オブジェクト) - 並列モード:オフ(順次実行)
- エラー処理:エラー発生時に終了
イテレーション内部詳細処理
| 番号 | ノード名 | 型 | 機能 |
|---|---|---|---|
| 1 | DataUnpack | code | イテレーション項目を独立した変数に分解 |
| 2 | Create a Row | tool | arxiv_idをSupabaseに記録して重複を防ぐ |
| 3 | 大規模モデルドキュメント解析 | tool | PaddleOCRでPDFを解析し本文を抽出 |
| 4 | get_footnote_text | code | 脚注情報を抽出(機関識別のために) |
| 5 | truncated_text | code | OCRテキストをトリミング(LLM入力長を制御) |
| 6 | (LLM)分析 | llm | 論文を深く分析し、主要な情報を抽出 |
| 7 | データアセンブル | code | 最終的な論文オブジェクトをアセンブル |
イテレーション項目を独立した変数に分解します。
出力:
title_str:論文タイトルpdf_url:PDFリンクsummary_str:要約published:公開日authors:著者arxiv_id:ArXiv ID
10.2 Create a Row(Supabaseノード)
論文のArXiv IDをデータベースに記録し、重複プッシュを防ぎます。
設定:
- テーブル名:設定ノードから取得
- データ:
{\"arxiv_id\": \"{{arxiv_id}}\"}
10.3 大規模モデル文書解析(PaddleOCRノード)
ノード名:大模型文档解析
ノードタイプ:tool (PaddleOCR)
PaddleOCRを使用して論文PDFを解析し、本文内容を抽出します。
設定:
file:PDF URLfileType:0(PDFファイル)useLayoutDetection:true(レイアウト検出を有効にする)prettifyMarkdown:true(出力を整形する)
10.4 get_footnote_text(コードノード)
OCRテキストから脚注情報を抽出し、後続の機関識別に使用します。
10.5 truncated_text(コードノード)
LLM入力長を制御するためにOCRテキストをトリミングし、トークン制限を超えないようにします。
10.6 LLM深度分析
ノード名:(LLM)分析
ノードタイプ:llm
論文を詳細に分析し、主要な情報を抽出します。
抽出フィールド:
- One_Liner:一文で課題と解決策
- Architecture:モデルアーキテクチャと主要なイノベーションポイント
- Dataset:データソースと規模
- Metrics:主要な性能指標
- Chinese_Abstract:中国語要約翻訳
- Affiliation:著者所属機関
- Code_Url:コードリンク
主要原則:
- 無駄な表現を避ける:具体的な方法を直接述べる
- 詳細を深く掘り下げる:アルゴリズムロジック、損失関数設計をまとめる
- データ優先:SOTAとの比較における改善幅を示す
- N/Aを禁止:合理的に推論する
出力形式:純粋なJSONオブジェクト
10.7 データアセンブリ(コードノード)
ノード名:データ組装
ノードタイプ:code
すべての情報を構造化された論文オブジェクトに組み立てます。
主要機能:
- 公開ステータスの解析(トップカンファレンス論文の識別)
- LLM出力のJSONを解析
- コードリンクの抽出
- 最終的な論文オブジェクトの組み立て
出力フィールド:
title:タイトルauthors:著者affiliation:所属機関pdf_url:PDFリンクsummary:英語要約published:公開ステータスgithub_stats:コードステータスcode_url:コードリンクai_evaluation:AI分析結果
ステップ11:テンプレート変換
ノード名:テンプレート変換
ノードタイプ:template-transform
Jinja2テンプレートを使用して、論文データをフォーマットされたメールコンテンツに変換します。
テンプレート構造:
📅 PaperEssence 研究日報
指定された研究内容"{{ raw_topic }}"に基づき、arxivの過去30日間の更新論文から選ばれた3つの論文を毎日配信します。
--------------------------------------------------
<small><i>⚠️ 注:この内容はAIによって生成されたものであり、学術的な参考のみを目的としています。引用または詳細な研究を行う前に、必ずPDFリンクをクリックして元の論文を確認してください。</i></small>
生成日: {{ items.target_date | default('Today') }}
==================================================
{% set final_list = items.paper | default(items) %}
{% for item in final_list %}
📄 [{{ loop.index }}] {{ item.title }}
--------------------------------------------------
👤 著者: {{ item.authors }}
🏢 所属機関: {{ item.affiliation }}
🔗 PDF: {{ item.pdf_url }}
📅 ステータス: {{ item.published }}
{% if item.code_url and item.code_url != 'N/A' %}
📦 コード: {{ item.github_stats }}
🔗 {{ item.code_url }}
{% else %}
📦 コード: {{ item.github_stats }}
{% endif %}
英語要約:
{{ item.summary | replace('\n', ' ') }}
中国語要約:
{{ item.ai_evaluation.Chinese_Abstract }}
🚀 主要なイノベーション:
{{ item.ai_evaluation.One_Liner }}
📊 まとめ:
--------------------------------------------------
🏗️ アーキテクチャ:
{{ item.ai_evaluation.Architecture | replace('\n- ', '\n\n 🔹 ') | replace('- ', ' 🔹 ') }}
💾 データ:
{{ item.ai_evaluation.Dataset | replace('\n- ', '\n\n 🔹 ') | replace('- ', ' 🔹 ') }}
📈 指標:
{{ item.ai_evaluation.Metrics | replace('\n- ', '\n\n 🔹 ') | replace('- ', ' 🔹 ') }}
==================================================
{% else %}
⚠️ 本日は新しい論文の更新はありません。
{% endfor %}
ステップ12:メール送信
ノード名:163SMTP邮件发送
ノードタイプ:tool (163-smtp-send-mail)
設定:
username_send:送信者メールアドレス(環境変数から読み込み)authorization_code:メール認証コード(環境変数から読み込み)username_recv:受信者メールアドレスsubject:PaperEssence-{{cutoff_str}}-{{today_str}}content:テンプレート変換後のコンテンツ
ステップ13:出力ノード
ノード名:出力
ノードタイプ:end
最終結果を出力し、デバッグと検証を容易にします。
ワークフローを公開してAPIを取得
ワークフローのデバッグが完了したら、右上の公開ボタンをクリックします。
以下の情報を記録します:
- APIエンドポイント:api.dify.ai/v1/workflows/run
- APIキー:
app-xxxxxxxxxxxxのような文字列
毎日自動実行を設定
Difyクラウドプラットフォームのタイマートリガーは無料版で制限がある可能性があるため、Windowsタスクスケジューラとスクリプトを組み合わせて、毎日定時にワークフローをトリガーできます。
前提条件:Git for Windowsのインストール
このソリューションではGit Bashを使用してcurlコマンドを実行するため、まずGit for Windowsをインストールする必要があります。
インストール時の注意点:
- デフォルトのインストールパス(例:
C:\\Program Files\\Git)またはカスタムパス(例:D:\\ProgramFiles\\Git)を選択することをお勧めします - インストールオプションで「Git Bash Here」がチェックされていることを確認してください
Windowsタスクスケジューラの設定
Win + Rを押す →taskschd.mscと入力し、Enterキーを押してタスクスケジューラを開きます- 右側の「タスクの作成」をクリックします
全般タブ:
- 名前:
Paper-Essence Daily Run - 「最上位の特権で実行する」にチェックを入れます
トリガータブ:
- 「新規」をクリックします
- 「タスクの開始」ドロップダウンリストで「スケジュールに従って」を選択します
- 「毎日」を選択し、トリガー時間を設定します(Difyワークフローのタイマー時間と一致させることをお推奨します。例:
20:55) - 「OK」をクリックします
操作タブ:
-
「新規」をクリックします
-
操作で「プログラムの開始」を選択します
-
プログラム/スクリプト:Git Bashのパスを入力します。例:
D:\\ProgramFiles\\Git\\bin\\bash.exe -
引数の追加:
curl -N -X POST "APIアドレス" -H "Authorization: Bearer app-あなたのAPIキー" -H "Content-Type: application/json" -d '{ "inputs": {}, "response_mode": "streaming", "user": "cron-job" }' -
「OK」をクリックしてタスクを保存します
テストとデバッグ
手動テスト
- ワークフローエディタの右上にある「実行」ボタンをクリックします
- 各ノードの実行ステータスを観察します
- 各ノードの出力が期待通りか確認します
実行成功時の効果
ワークフローが正常に実行されると、以下の内容を含むフォーマットされた論文日報メールが届きます:
- 論文タイトル、著者、所属機関
- PDFリンクとコードリンク
- 中国語と英語の要約
- AI分析による主要なイノベーションポイント、アーキテクチャ、データセット、性能指標
まとめ
このチュートリアルでは、YAMLノードの設定とスケジューリング、環境変数とSupabaseの使用について説明し、ArXivからの取得 → PaddleOCRによる解析 → LLMによる分析 → Jinja2によるテンプレート化 → SMTPによる配信というエンドツーエンドのパイプラインを構築し、重複排除とエラー処理も強化しました。
謝辞
張晶先生、関木先生、楊有志先生のご指導に感謝いたします。