Paper-Essence — 教程:构建一个自动化论文摘要工作流

Paper-Essence — 教程:构建自动化论文摘要工作流

:open_book: 项目概览

Paper-Essence 是一个基于 Dify 平台构建的自动化论文摘要工作流。该工作流可以:

  • :one_o_clock: 每日定时从 arXiv 获取指定研究领域的最新论文
  • :robot: 使用大型语言模型筛选并选择最有价值的论文
  • :page_facing_up: 使用 OCR 解析 PDF 论文以提取技术细节
  • :e_mail: 生成结构化的每日摘要并通过电子邮件发送

GitHub 仓库:github.com/LiaoYFBH/PaperFlow — 您可以直接导入 prj/Paper-Essence-CN.ymlprj/Paper-Essence-EN.yml


:hammer_and_wrench: 前提条件

1. 平台和账户

  • Dify 账户:注册并登录 Dify
  • 电子邮件账户:一个支持 SMTP 的电子邮件(本教程使用 163 邮箱)
  • LLM API:配置星河社区 API

2. 安装所需插件

从 Dify 插件市场安装以下插件:

插件 用途
paddle-aistudio/ernie-paddle-aistudio 星河社区 API
langgenius/paddleocr 用于 PDF 和图像的 OCR
wjdsg/163-smtp-send-mail 163 SMTP 邮件发送
langgenius/supabase 用于已推送记录的数据库存储

3. 准备 Supabase 数据库

我们使用云数据库 (Supabase) 来记录已推送的论文,以避免重复。

步骤 1:登录并创建项目

访问 supabase.com 创建账户并启动一个新项目。

步骤 2:创建表

在 SQL 编辑器中,运行以下 SQL 语句来创建一个记录已推送论文 ID 的表,以确保不重复:

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 URL
  • NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY → Dify 插件的 Supabase Key

步骤 4:在 Dify 中配置 Supabase 插件

在 Dify 中,前往插件市场,找到 Supabase 插件,并输入您上一步获取的 URL 和 Key。

(可选) 使用 Docker 部署 Dify

环境设置

本教程使用 WSL + Docker。您可以参考微软文档进行 WSL 和 Docker 配置。

克隆 Dify 仓库

首先,克隆 Dify 仓库。如果您尚未配置 Git,可以直接从仓库页面下载 ZIP 文件并解压。

如果您已配置 Git,请在终端中运行以下命令:

# Clone Dify repository
git clone https://github.com/langgenius/dify.git

您需要配置 Git 和 Docker。

# Navigate to docker deployment directory
cd dify/docker

# Copy environment configuration file
cp .env.example .env

首先,打开 Docker Desktop,然后在终端中输入:

# Start Dify (this will automatically pull images and start all services)
docker compose up -d

检查状态:

docker compose ps

访问应用程序:http://localhost/


:bar_chart: 工作流架构

工作流遵循以下核心流程:

计划触发器 (Schedule Trigger) → 配置 (Configuration) (代码) → LLM 翻译 (LLM trans) (llm - 翻译主题) → 获取行 (Get Rows) (工具 - 检查已推送论文) → 搜索预处理 (Search Pre-process) (代码) → HTTP 请求 (HTTP Request) (http-request) → 搜索后处理 (Search Post-process) (代码) → LLM 初审 (LLM Initial Review) (llm) → JSON 解析 (JSON Parse) (代码) → 迭代 (Iteration) (对于每篇论文:数据解包 (DataUnpack) (代码) → 创建行 (Create a Row) (工具) → 文档解析 (Document Parsing) (工具 - OCR) → 获取脚注文本 (get_footnote_text) (代码) → 截断文本 (truncated_text) (代码) → 分析 (Analysis) (llm) → 数据组装 (Data Assembly) (代码)) → 模板转换 (Template Transform) (模板转换) → 163 SMTP 邮件发送器 (163 SMTP Email Sender) (工具) → 输出 (Output) (结束)

此工作流的完整视图:


:wrench: 分步设置

步骤 1 — 创建工作流

  1. 登录 Dify
  2. 在工作室 (Studio) 中,点击“创建应用 (Create App)” → 选择“工作流 (Workflow)”
  3. 输入应用程序名称
  4. 选择工作流的触发器类型 (Trigger type)

步骤 2 — 配置环境变量

点击右上角的“设置 (Settings)”按钮,然后选择“添加变量 (Add Variable)”。

这些环境变量将被配置节点(一个代码节点)读取,并输出给下游节点。

关键变量:

名称 类型 描述 示例
table_name string Supabase 表名 pushed_papers
SMTP_PORT string SMTP 端口 465
SMTP_SERVER string SMTP 服务器 smtp.163.com
SMTP_PASSWORD secret SMTP 授权码 (您的授权码)
SMTP_USER secret SMTP 用户/邮箱 your_email@163.com
MY_RAW_TOPIC string 研究主题 agent memory
要获取您的电子邮件授权码,请登录您的电子邮件提供商设置并为第三方应用程序生成一个 SMTP 授权码。

步骤 3 — 定时触发器

节点名称:Scheduled Trigger

配置:

  • 触发频率:每日
  • 触发时间8:59 AM(或根据需要调整)

步骤 4 — 配置(代码节点)

节点名称:Configuration(类型:code)— 此代码节点读取环境变量,处理它们,并为下游节点输出配置值。

输入变量:

  • 来自环境变量:SMTP_PORTSMTP_SERVERSMTP_USERSMTP_PASSWORDMY_RAW_TOPICtable_name

输出变量:

  • raw_topic:研究主题
  • user_email:收件人邮箱
  • fetch_count:要获取的论文数量(默认:50)
  • push_limit:推送限制(默认:3)
  • days_lookback:回溯天数(默认:30)
  • 加上 SMTP 配置

步骤 5 — LLM 翻译(LLM 节点)

节点名称:LLM trans(类型:llm)— 将研究主题转换为针对 arXiv 优化的英文布尔查询。

模型配置:

  • 模型:ernie-4.5-turbo-128kernie-5.0-thinking-preview。如果您选择深度思考模型(ernie-5.0-thinking-preview),则需要启用推理格式分离。
  • 温度:0.7

提示词规则: 提取核心概念,翻译术语(如果需要),使用 AND/OR 构建布尔逻辑,将短语用引号括起来,并仅输出查询字符串。


步骤 6 — 查询已推送记录(Supabase 节点)

节点名称:Get Rows(类型:tool - Supabase 插件)— 获取已推送的 arXiv ID 以避免重复。

配置:

  • 表名:{{table_name}}(来自 Configuration 节点)

步骤 7 — 搜索论文(3 个节点)

为了提高稳定性和可维护性,搜索功能被拆分为“预处理”→“HTTP 请求”→“后处理”。

7.1 搜索预处理(代码节点)

节点名称:Search Pre-process(类型:code)— 构建 arXiv API 请求并准备搜索参数。

输入变量:

  • topic:翻译后的英文搜索词
  • days_lookback:回溯天数
  • count:要获取的论文数量
  • supabase_output:已推送的记录(用于去重)

代码逻辑:

  1. 计算截止日期 (cutoff_date)
  2. 解析 Supabase 返回的已推送论文 ID 列表
  3. 根据主题构建布尔查询字符串(支持 AND/OR 逻辑)
  4. 根据主题关键词添加 arXiv 类别限制(例如,cs.CV, cs.CL)
  5. 提取搜索关键词用于后续过滤

输出变量:

  • base_query:构建的查询字符串
  • pushed_ids:已推送 ID 列表
  • cutoff_str:截止日期字符串
  • search_keywords:搜索关键词列表
  • fetch_limit:API 获取限制

7.2 HTTP 请求(HTTP 节点)

节点名称:HTTP Request(类型:http-request)— 调用 arXiv API 获取原始 XML 数据。

配置:

  • API URLhttp://export.arxiv.org/api/query
  • 方法GET

7.3 搜索后处理(代码节点)

节点名称:Search Post-process(类型:code)— 解析 XML 响应并过滤论文。

输入变量:

  • http_response_body:HTTP 节点响应体
  • 加上来自预处理节点的所有输出变量

代码逻辑:

  1. 解析 XML 响应
  2. 去重过滤:移除 pushed_ids 中的论文
  3. 日期过滤:移除早于 cutoff_date 的论文
  4. 关键词过滤:确保标题或摘要包含至少一个搜索关键词
  5. 将输出格式化为 JSON 对象列表

输出变量:

  • result:最终过滤后的论文列表(JSON 字符串)
  • count:最终论文数量
  • debug:调试信息(包括过滤统计)

步骤 8 — LLM 初步审查

节点名称:LLM Initial Review(类型:llm)— 使用 LLM 对论文进行评分并选择排名前三的论文(Top 3)。

输出要求:

  • 干净的 JSON 数组格式
  • 保留所有原始字段
  • 输出排名前三的论文

步骤 9 — JSON 解析(代码节点)

节点名称:JSON Parse(类型:code)— 容错解析 LLM 输出,将其转换为规范化的论文列表。

核心逻辑:

  • 处理嵌套 JSON
  • 支持 paperstop_papers 字段
  • 容错处理

步骤 10 — 迭代节点

节点名称:Iteration — 顺序处理每篇选定的论文(解包、记录到 Supabase、OCR PDF、使用 LLM 分析、组装最终对象)。

配置:

  • 输入top_papers(论文数组)
  • 输出merged_paper(处理后的论文对象)
  • 并行模式:关闭(顺序执行)
  • 错误处理:遇到错误停止

迭代内部流程

节点名称 类型 功能
1 DataUnpack code 将迭代项解包为单独的变量
2 Create a Row tool 将 arxiv_id 记录到 Supabase 以防止重复
3 Document Parsing tool PaddleOCR 解析 PDF 以提取文本
4 get_footnote_text code 提取脚注信息(用于识别机构)
5 truncated_text code 截断 OCR 文本(控制 LLM 输入长度)
6 Analysis llm 深度分析以提取关键信息
7 Data Assembly code 组装最终论文对象
#### 10.1 DataUnpack(代码节点)

将迭代项解包为单独的变量。

输出:

  • title_str:论文标题
  • pdf_url:PDF链接
  • summary_str:摘要
  • published:发表日期
  • authors:作者
  • arxiv_id:ArXiv ID

10.2 创建行(Supabase 节点)

将论文的 ArXiv ID 记录到数据库,以防止重复推送。

配置:

  • 表名:来自配置节点
  • 数据:{\"arxiv_id\": \"{{arxiv_id}}\"}

10.3 文档解析(PaddleOCR 节点)

节点名称:Document Parsing(类型:tool - PaddleOCR)

使用 PaddleOCR(非 LLM)解析论文 PDF 并通过 OCR 提取文本内容。

配置:

  • file:PDF URL
  • fileType:0(PDF文件)
  • useLayoutDetection:true(启用布局检测)
  • prettifyMarkdown:true(美化输出)

10.4 get_footnote_text(代码节点)

从 OCR 文本中提取脚注信息,用于后续的机构识别。

10.5 truncated_text(代码节点)

截断 OCR 文本以控制 LLM 输入长度,避免超出 token 限制。

10.6 分析(LLM 节点)

节点名称:Analysis(类型:llm

对论文进行深度分析,提取关键信息。

提取字段:

  1. One_Liner:一句话痛点与解决方案
  2. Architecture:模型架构和关键创新
  3. Dataset:数据来源和规模
  4. Metrics:核心性能指标
  5. Affiliation:作者机构
  6. Code_Url:代码仓库链接

核心原则:

  • 无冗余:直接陈述具体方法
  • 深入细节:总结算法逻辑、损失函数设计
  • 数据优先:展示相对于 SOTA 的改进
  • 无 N/A:进行合理推断

输出格式: 纯 JSON 对象

10.7 数据组装(代码节点)

节点名称:Data Assembly(类型:code

将所有信息组装成结构化的论文对象。

核心功能:

  1. 解析发表状态(识别顶会论文)
  2. 解析 LLM 输出 JSON
  3. 提取代码链接
  4. 组装最终论文对象

输出字段:

  • title:标题
  • authors:作者
  • affiliation:机构
  • pdf_url:PDF链接
  • summary:英文摘要
  • published:发表状态
  • github_stats:代码状态
  • code_url:代码链接
  • ai_evaluation:AI分析结果

步骤 11 — 模板转换

节点名称:Template Transform(类型:template-transform

使用 Jinja2 模板将论文数据转换为格式化的电子邮件内容。

模板结构:

📅 PaperEssence Daily
Based on your specified research topic "{{ raw_topic }}", here are the top 3 papers selected from ArXiv updates in recent times.
--------------------------------------------------
--------------------------------------------------
⚠️ Note: Content is AI-generated and for academic reference only. Please verify by checking the original PDF before citing or conducting in-depth research.
Date: {{ items.target_date | default('Today') }}
==================================================

{# Automatically adapt data structure #}
{% set final_list = items.paper | default(items) %}

{% for item in final_list %}
📄 [{{ loop.index }}] {{ item.title }}
--------------------------------------------------
👤 Authors: {{ item.authors }}
🏢 Affiliation: {{ item.affiliation }}
🔗 PDF: {{ item.pdf_url }}
📅 Status: {{ item.published }}
{% if item.code_url and item.code_url != 'N/A' %}
📦 Code: {{ item.github_stats }}
   🔗 {{ item.code_url }}
{% else %}
📦 Code: {{ item.github_stats }}
{% endif %}
Abstract:
{{ item.summary | replace('\n', ' ') }}

🚀 Core Innovation:
{{ item.ai_evaluation.One_Liner }}

📊 Summary:
{# Use newlines and indentation for hierarchy, not relying on HTML tags #}
--------------------------------------------------
🏗️ Architecture:
{{ item.ai_evaluation.Architecture | replace('\n- ', '\n\n   🔹 ') | replace('- ', '   🔹 ') }}

💾 Dataset:
{{ item.ai_evaluation.Dataset | replace('\n- ', '\n\n   🔹 ') | replace('- ', '   🔹 ') }}

📈 Metrics:
{{ item.ai_evaluation.Metrics | replace('\n- ', '\n\n   🔹 ') | replace('- ', '   🔹 ') }}

==================================================
{% else %}
⚠️ No new papers today.
{% endfor %}

步骤 12 — 发送邮件(163 SMTP)

节点名称:163 SMTP Email Sender(类型:tool - 163-smtp-send-mail)

配置:

  • username_send:发件人邮箱(通过 SMTP_USER 从环境变量获取)
  • authorization_code:邮箱授权码(通过 SMTP_PASSWORD 从环境变量获取)
  • username_recv:收件人邮箱(来自配置节点)
  • subjectPaperEssence-{{cutoff_str}}-{{today_str}}
  • content:来自模板转换的内容

注意:这些参数名称(username_sendauthorization_codeusername_recv)是 163 SMTP 插件特有的。


步骤 13 — 输出节点

节点名称:Output(类型:end

输出最终结果用于调试和验证。


:outbox_tray: 发布并获取工作流 API

在测试并确认工作流正常运行后,点击右上角的“发布”按钮。

记录以下信息:

  • API 端点https://api.dify.ai/v1/workflows/run (用于 Dify 云部署) 或您的私有部署 URL (例如,http://localhost/v1/workflows/run)
  • API 密钥app-xxxxxxxxxxxx

:alarm_clock: 替代方案:本地计划任务触发(Windows 任务计划程序)

如果 Dify 云调度在免费层级受限,您可以使用 Windows 任务计划程序通过 curl POST 触发工作流。

前提条件:安装 Git for Windows

此解决方案使用 Git Bash 执行 curl 命令,因此您需要先安装 Git for Windows(搜索“Git for Windows”下载)。

安装注意事项:

  • 建议使用默认安装路径(例如,C:\\Program Files\\Git)或自定义路径(例如,D:\\ProgramFiles\\Git
  • 确保在安装过程中勾选“Git Bash Here”

配置 Windows 任务计划程序

  1. Win + R → 输入 taskschd.msc → 回车
  2. 点击“创建任务”

常规选项卡:

  • 名称Paper-Essence Daily Run
  • 勾选“使用最高权限运行”

触发器选项卡:

  1. 点击“新建”
  2. 选择“按计划”
  3. 选择“每天”,设置时间(建议与 Dify 工作流定时器匹配,例如 20:55
  4. 点击“确定”

操作选项卡:

  1. 点击“新建”

  2. 操作:“启动程序”

  3. 程序/脚本:输入您的 Git Bash 路径,例如:

    D:\ProgramFiles\Git\bin\bash.exe
    

    或默认安装路径:

    C:\Program Files\Git\bin\bash.exe
    
  4. 添加参数:使用 curl 命令 POST 到您的工作流 API 端点,并附带您的 API 密钥

    :warning: 注意:请将 API 端点和密钥替换为上一步中的实际值

条件选项卡(可选):

  • 您可以取消勾选“只有在计算机使用交流电源时才启动任务”,以确保笔记本电脑在电池供电时也能运行任务

设置选项卡(可选):

  • 勾选“如果任务失败,每隔”并设置重试间隔
  1. 点击“确定”保存任务

:test_tube: 测试与调试

手动测试

  1. 在工作流编辑器中点击“运行”(右上角)
  2. 观察节点执行和输出
  3. 验证每个节点的输出是否符合预期

成功结果

当工作流成功执行后,您将收到一封包含每日论文摘要的电子邮件。


:memo: 总结

本教程涵盖了构建一个完整的端到端管道:ArXiv 抓取 → PaddleOCR 解析 → LLM 分析 → Jinja2 模板化 → SMTP 投递,并结合了基于 Supabase 的去重和调度功能。该工作流涉及 YAML 节点配置、环境变量和 Supabase 集成,创建了一个从 ArXiv 检索到电子邮件投递的综合管道,并增强了去重和错误处理能力。

提供的 prj/Paper-Essence-CN.ymlprj/Paper-Essence-EN.yml 可以导入到 Dify 工作区以复现该工作流。


致谢

特别感谢 Alex Zhang、Guan Mu 和 Yang Youzhi 的指导。

1 个赞