中文 / EN
按键盘 ↓ 查看详情

从 Low-Code 到 Pro-Code

程序员如何驾驭 Dify 进行 LLM 应用开发

Dify x PUPU · 开源、可观测、可扩展的智能工作流与插件生态。

郑立 · Dify 开源生态负责人
2025 / Sharing Deck

Agenda

Low‑CodePro‑Code: 把编排、工程护栏、生态扩展、事件驱动与可观测性串成生产闭环。

Part 模块 关注点
01 破局 现状痛点 · 技术定位 · 为什么是现在
02 融合 Visual DSL ↔ Pro‑Code 分工 · 调试视图 · 协作机制
03 扩展 Plugins & Marketplace · 工具安全 · 可复用资产
04 连接 Trigger 自动化闭环 · 类型与矩阵 · 实战案例
05 洞察 OTEL 全链路 · 多库适配 · 成本与性能可视化
06 总结 进化路径 · Call for Action

破局 · 下一代 LLM 应用开发范式

从痛点切入,思考 Dify 的技术定位。

范式转移示意图

Community-Driven · 全球认可

开源生态驱动,Top 100 GitHub 仓库。

Install 1M+ Powered by Dify
Popularity 120K+ GitHub Stars
Global Reach 150+ Countries
Enterprise 60+ Industries
Contributors 1000+ Contributors
Downloads 550M+ Total downloads

1.0 数据流动画 · 从 Chaos 到 Clarity

输入
  • 原始日志 / 文档流
  • 实时事件 Payload
  • 自定义特征 (country, ua...)
Normalize → Vectorize → Route
Guardrail + Policy Check
输出
  • 响应体 / 回调
  • 指标:p99, token, 成本
  • Trace 链路:APM & Log

1.1 现状痛点

表面是“能力拼图”,本质是“工程断层”。

接口碎片化
调用 / 计费 / 监控
迭代周期慢
隔离 / 灰度 / 回滚
协作难
资产库 / 复用 / 共享
工程缺口
审计 / 重试 / 配额
痛点示意图

1.2 Dify 的技术定位

一站式 LLM 应用平台:从构建、编排到运行。

编排

Workflow / Prompt Studio / RAG 管道。

工程化

重试、分支、配额、环境隔离。

扩展

Plugin & Tooling,开放能力对接外部系统。

可观测

Tracing / Token / 成本可视,保障生产稳定。

Dify 定位图

1.3 为什么是现在?

技术临界点已至:算力、模型与数据三大要素齐备。

2017
Transformer
Attention is all you need
2020
GPT-3
Few-shot learning 涌现
2025.2
Dify v1.0
LLM 应用中间件诞生
2025.11
Pro-Code
工程化、生产级、标准化

1.4 传统开发 vs LLM 原生开发

从确定性编程向概率性工程的思维转变。

传统软件开发
  • 核心逻辑 确定性 (Deterministic)
    If-Then-Else 严密控制
  • 数据处理 结构化 (SQL/JSON)
    Schema 定义先行
  • 测试方法 单元测试 (Pass/Fail)
    逻辑覆盖率
Next Gen
LLM 原生开发
  • 核心逻辑 概率性 (Probabilistic)
    Prompt + Context 引导
  • 数据处理 非结构化 (Embedding)
    语义检索与理解
  • 测试方法 评估 (Eval)
    准确率、幻觉率、相关性

1.5 Dify 生态全景

作为 LLM 应用开发的“操作系统”,链接模型与业务。

End Users
External Systems
Chat Bots
Agent Assistants
Workflow Automation
Dify Core Engine
Orchestration
RAG Pipeline
Plugin Runtime
Observability
LLMs
Vector DBs
Compute

融合 · 打破“低代码”的刻板印象

不仅是降低门槛,更是高阶工程能力的“可视化映射”。

可视化DSL与可观测性示意图

2.1 可视化的辩证统一

高低代码都离不开可视化,但核心目的不同:

Low‑Code Pro‑Code
可视化的角色 编程语言 抽象理解 & 调试视图
核心目标 降低认知负荷
可解释、可教学
加速复杂 DSL 理解
可比较、可复盘
交付形态 可视逻辑可直接“运行” 让工程事实显性化
(Trace / Token / 变量)
看得懂、比得出、说得清、做得快
工作流即DSL

2.1 双轨示例:DSL ↔ Code Node

同一逻辑,两种形态,协同演进。

Workflow 画布
  • 变量映射:检索结果 → LLM → 条件分支
  • 可视断点:节点级耗时、重试、采样率
  • 业务可读:交付给运营/产品共建
Code Node (Python)
def handler(payload):
    country = payload["country"]
    score = risk_model.predict(payload)
    if country == "US" and score < 0.2:
        return {"route": "fast-lane"}
    return {"route": "human-review", "score": score}
输出变量 auto-bind → 下游节点

2.2 最佳实践:高密度开发模式

利用 Dify 的可视化 DSL 处理 80% 的胶水逻辑,用 Pro-Code 解决 20% 的核心计算。

可视编排 (DSL)

处理分支、循环、RAG 检索管道,利用可视化界面快速对齐业务需求。

代码节点 (Code Node)

在工作流中嵌入 Python/Node.js 脚本,处理数据清洗与复杂数学计算。

观测闭环 (Feedback)

利用 Trace ID 串联会话日志,反向优化 Prompt 与 代码逻辑。

2.3 调试视图 · 变量+日志

变量快照

节点级输入/输出对比,diff 高亮。

user_id: 91283 → 91283
country: CN → US (flag)
Token & 成本
  • Prompt Tokens: 320
  • Completion Tokens: 88
  • 成本: $0.0009 / req
日志 & Trace

点击 Trace ID 跳转至 Jaeger / SLS。

trace_id=wf-1827 span=llm.call status=ok p95=180ms

2.4 Prompt Engineering as Code

像管理代码一样管理 Prompt:版本控制与差异对比。

prompts/customer_service.yaml v2.1.0
system_prompt: |
You are a helpful assistant.
# Context variables
Current User: {{ user_name }}
History: {{ conversation_history }}
parameters:
temperature: 0.7
model: gpt-4-turbo
Version Diff
- model: gpt-3.5-turbo
+ model: gpt-4-turbo
Updated by @zhengli 2 hours ago

2.5 团队协作机制

明确分工,打破 Prompt 工程师与开发者的壁垒。

Admin

基础设施负责人

  • • 模型供应商配置
  • • API Key 管理
  • • 向量数据库维护
Builder

应用开发者

  • • Prompt 编排与调试
  • • Workflow 逻辑设计
  • • 发布与版本管理
Operator

业务运营

  • • 日志查看与标注
  • • 效果反馈
  • • 知识库数据上传

2.6 复杂逻辑编排能力

不仅是线性流,支持循环、迭代与条件判断。

Start
Input Check
Iteration Node
Item A
LLM Process
Result
If / Else
Pass Fail

扩展 · 构建你的军火库

Marketplace & Plugins:把 Dify 当成“平台的基础设施”。

插件市场

3.1 Dify Plugin 架构解析

标准化接口、鉴权与多语言运行时。

Runtime

隔离执行环境,控制超时与重试。

Auth

支持 API Key / OAuth / 内部凭据。

Billing

调用计费与配额管理可插拔。

Packaging

Marketplace 发布与版本化。

插件架构图

3.1 调用示例:Slack Bot Plugin

请求示例 (cURL)
curl -X POST https://api.dify.ai/plugins/slack_bot \\
  -H "Authorization: Bearer <token>" \\
  -d '{
    "channel_id": "ops-alert",
    "text": "Build passed ✅",
    "bot_token": "******"
  }'
响应 & 观测
  • status: success
  • message_ts: 171103.23
  • trace_id: plugin-9821 (跳转日志)
180ms
p95
0.0003
Cost $
99.9%
成功率

3.2 发布流水线 · 4 步上线

1
定义

manifest + schema

2
开发

code node / runtime

3
验证

本地 + 沙箱

4
发布

Marketplace / 内部

3.2 实战:开发 Slack Bot 插件

以开发一个 Slack 消息发送工具为例,演示 Dify 插件的“定义即开发”流程。

🗂️ Manifest 定义 (YAML): 定义插件元数据(Identity)和 Tool 参数(如 bot_token, channel_id)。
💻 代码实现 (Python): 继承 Tool 类,在 _invoke 方法中调用 Slack SDK 发送消息。
调试与发布: 本地验证 invoke 结果,打包发布至 Dify Marketplace。
manifest.yaml
main.py
identity:
name: slack_bot
label: { en_US: Slack Bot }
parameters:
# 定义输入参数: Token (Secret) & Channel
- name: bot_token
type: secret-input
- name: channel_id
type: string
- name: text
type: string
// main.py Preview
class SlackBotTool(Tool):
def _invoke(self, params: dict):
# 1. 获取凭据与参数
token = params.get('bot_token')
client = WebClient(token=token)
# 2. 执行业务逻辑 (Call SDK)
res = client.chat_postMessage(
channel=params.get('channel_id'),
text=params.get('text')
)
return { "result": res.data }

3.3 工具安全与沙箱机制

不信任任何第三方代码,确保主程序安全稳定。

Unsafe Zone

第三方 Plugin 代码
任意网络请求
高资源消耗

gRPC / Socket

Safe Sandbox

Namespace 隔离
资源配额限制
网络白名单

3.4 进阶:工具逆向调用 Workflow

Agentic Behavior: 插件不仅仅是执行者,也可以是决策者。

# plugin_logic.py: Plugin decides to call another workflow

def _invoke(self, params):
    user_intent = analyze_intent(params['input'])
    
    if user_intent == 'complex_task':
        # Reverse call back to Dify API
        response = dify_client.run_workflow(
            workflow_id="wf-sub-task-001",
            inputs={"query": params['input']},
            user_id=params['user_id']
        )
        return {"result": response['data'], "delegated": True}
        
    return {"result": simple_process(params), "delegated": False}
                            

3.5 插件市场经济展望

连接开发者与企业用户,共建价值闭环。

👩‍💻

Creators

开发高质量插件
发布到 Marketplace
获得收益分成

🚀

Platform

提供分发渠道
处理计费与结算
保障安全审核

🏢

Consumers

一键安装能力
按需付费订阅
解决业务痛点

连接 · 事件驱动的自动化

Trigger 让应用从“被动问答”迈向“主动执行”。

事件驱动自动化

4.1 Trigger 的本质

  • Passive Response:等待用户提问,缺少上下文与时效。
  • Active Execution:事件驱动,自动拉起 Workflow 完成动作。
事件触发流程

4.1 自动化动画:事件 → Workflow

事件源
  • Webhook: /orders/created
  • Plugin: GitHub PR
  • Schedule: cron(0/10 * * *)
事件 → 变量映射 → 条件路由
LLM 选择模型 · 自动重试
回调 / 写库 / 通知
可观测
  • Trace ID: trig-2039
  • p95: 420ms
  • Drools/Rules: version v2.1

4.2 场景演示

外部 Webhook -> Dify 解析 Payload -> LLM 决策 -> 输出结果。

Webhook

接收外部事件,校验签名。

LLM Routing

基于上下文选择模型与链路。

Action

调用 Plugin/Tool,写入结果。

Observe

Tracing + Token 成本监控。

触发器工作流界面

4.3 为什么需要 Trigger?

把“何时启动”收回到编排层,统一治理与回放。

没有 Trigger 有 Trigger
入口分散:按钮 / Cron / 直调 入口统一:事件源 → 变量映射 → 路由
难治理:缺 Trace、难排查 可治理:可回放、可观测、可审计
启动条件散落在代码/脚本 启动条件由 Workflow 编排决定
多条触发逻辑难复用 一张画布:先分支后汇合

4.4 Trigger 类型(v1.10.0)

覆盖定时、第三方事件和自建系统三大场景。

Schedule Trigger

按固定节奏启动:日报、数据清理、健康检查等可预测任务。

Plugin Trigger

第三方事件驱动:PR 更新、工单变更、文档改动等。插件负责订阅和解析结构化 Payload,可一份订阅驱动多条 Workflow。

Webhook Trigger

面向自有/遗留系统。为每个 Trigger 生成唯一 HTTP URL,Query/Header/Body 直接转为变量;可将 Workflow 结果回传调用方。

4.4 用例矩阵

实时
高复杂
批量
标准化
监控告警
Prom → Trigger → Slack
代码审查
PR → Plugin Trigger → 摘要
RAG 回放
KB 更新 → 重跑 → Diff
CRM 自动化
线索 → Workflow → 邮件/工单
内容审核
Webhook → 多模态 → 封禁
电商履约
订单 → LLM 路由 → 仓储

4.5 实战示例:GitHub PR 自动审查

结合 Plugin Trigger 与 LLM,让代码变更自动进入智能审查流程。

🛰️ 订阅事件
GitHub Trigger 订阅非 Draft、目标 main 的 PR 事件。
t0
📥 变量入流
解析 payload → action/pull_request/repo/sender
t0+30ms
🤖 LLM 审查与反馈
生成审查摘要,条件判断:自动评论 / 请求变更 / 触发 CI。
t0+180ms

4.6 技术揭秘:高并发事件总线架构

如何确保海量 Trigger 事件不丢失、不阻塞。

External Sources
API Gateway
Validation & Auth
MQ
Redis Broker
FIFO Queue
Celery Worker
Workflow Execution

4.7 真实案例:智能客服工单路由

从邮件接收到自动分类、回复草拟的全流程。

1

Email Trigger

客户发送邮件至 support@company.com → Webhook 触发 Dify。

2

Intent Classification (LLM)

分析邮件内容:是 "退款请求"、"技术故障" 还是 "一般咨询"?

退款
调用 Stripe 插件查询订单状态
技术
检索 RAG 知识库匹配解决方案
3

Human-in-the-loop

生成草稿回复 → 发送至 Slack 供人工审核 → 点击确认发送。

洞察 · 开源社区的极客精神

透明、可观测、可移植的工程能力。

开源洞察

5.1 OTEL 全链路追踪实战

不仅是日志,更是贯穿 LLM 与 Infra 的“上帝视角”。

Trace Link
Workflow App
Trace ID: T-1001
HTTP Header
Propagation
API / Worker
● Monkey Patch
Plugin Daemon
● Compile Probe
Redis PostgreSQL VectorDB

技术内幕:无侵入探针

面对 Dify 频繁的迭代,我们不能修改源码。 方案:Monkey Patch (Python)Compile-time Instrumentation (Go)

接入方案概览

  • API / Worker (Python): 使用 aliyun-bootstrap 动态劫持 Flask/Celery 入口,注入 Trace 上下文。
  • Plugin-Daemon (Go): 修改 Dockerfile,在 go build 阶段注入 instgo 工具,自动插桩。
  • Trace Link: 在 HTTP Header 中透传 TraceID,串联业务日志与基础设施。
entrypoint.sh
# 1. Python 启动脚本劫持
if [ "$DEBUG" = "true" ]; then
exec flask run ...
else
# 注入 aliyun-instrument
exec aliyun-instrument gunicorn \
--bind ... \
--workers ... \
app:app
fi

// 2. Go Dockerfile 编译插桩
RUN wget .../instgo-linux-amd64 -O instgo
RUN ./instgo go build -o main cmd/server/main.go

5.1 技术深潜:Python Monkey Patch 原理

aliyun-instrument 的核心在于使用 wrapt 库在运行时劫持 Dify 关键方法。

核心机制拆解

  • 动态替换: 模块加载时,定位目标函数(如 WorkflowRunner.run),替换为 Wrapper。
  • 上下文透明: wrapt 确保原函数的元数据(如 __name__)保持不变,对上层业务透明。
  • 异常穿透: 捕获异常记录到 Span Event,随后原样抛出,不影响业务流。
# Pseudo-code: Dify Instrumentation Logic
import wrapt
from opentelemetry import trace

def _instrument(self, **kwargs):
# 1. 定位并劫持目标函数
wrapt.wrap_function_wrapper(
"dify.core.workflow.runner", # Module
"WorkflowRunner.run", # Method
self._trace_wrapper # Hook
)

def _trace_wrapper(self, wrapped, instance, args, kwargs):
tracer = trace.get_tracer("aliyun.dify")
# 2. 开启 Span
with tracer.start_as_current_span("workflow.run") as span:
# 3. 记录输入参数
span.set_attribute("user_id", kwargs.get("user_id"))

# 4. 执行原业务逻辑
result = wrapped(*args, **kwargs)

# 5. 记录结果并返回
return result

5.1 采样与限流策略

动态采样

按 Span 类型设置采样率:LLM 20%,向量检索 50%,关键交易 100%。

Token 限流

结合队列长度与 TPS,动态调节 prompt 长度与并发窗口。

异常升级

捕获错误率>1% 时提升采样到 100%,自动打开调试日志。

实战案例:定位“幽灵”报错

场景:前端显示正常,RAG 检索结果却为空,Dify 业务日志无报错。

🛑
发现异常

查看 Workflow Trace,发现 Retriever 节点耗时极短,且 Output 为空字符串。

output: ""
🔗
Trace Link

点击 Span 详情中的 "Infrastructure Link" 按钮,携带 Trace ID 跳转至 SLS/Jaeger。

🐞
根因定位

在 Worker 的底层 Span 中捕获到未抛出的异常堆栈,发现向量库版本不兼容。

ValueError: Weaviate version 1.19.0 not supported...

5.2 数据库适配:架构解耦 (Schema)

  • DB_TYPE 支持: DatabaseConfig 新增类型选择,支持 PostgreSQL, MySQL, OceanBase。
  • 动态引擎: SQLAlchemy URI 与 Engine Options 根据类型动态调整。
  • 配置更新: 移除 OceanBase 向量配置,统一管理。

配置示例 (.env)

# Select Database Type
DB_TYPE=mysql
# MySQL Configuration
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=dify_user
Dify API / Worker
SQLAlchemy Engine Factory
Postgres
MySQL
OceanBase

5.2 性能指标看板

410 ms
p95 延迟
0.0021
$/Request
含 RAG 检索 & LLM
99.96%
成功率
过去 7d
热点 Span
  • workflow.run → 35%
  • retriever.query → 22%
  • llm.call → 18%
优化动作
  • 分片向量库,减少 tail latency
  • Prompt 缓存命中率提升 12%
  • 异步回调降低 API 阻塞

5.3 质量保障:差异化 CI/CD

为了保障 Schema 在不同数据库方言下的兼容性,引入了针对 MySQL 的独立迁移测试。

  • GitHub Actions 改造: 区分 Postgres 与 MySQL Service。
  • Migration Test Job: 针对 MySQL 运行完整的 Alembic 迁移脚本,确保无语法错误。
  • 兼容性红线: 任何 Schema 变更必须同时通过双库测试。
Pull Request
Matrix Strategy
Job: test-api (Postgres)
Job: migration-test (MySQL)

5.4 代码重构:SQL 兼容性抽象

用 Python Helper 与 ORM 方法替代方言特定的 Raw SQL。

Portable Date Functions

convert_datetime_to_date 封装了不同数据库的日期截断逻辑 (Postgres date_trunc vs MySQL date_format)。

# api/controllers/console/app/statistic.py
def convert_datetime_to_date(column):
if db.engine.name == 'postgresql':
return func.date_trunc('day', column)
return func.date(column)

Metadata Filter Standardization

dataset_retrieval.py 移除 Raw SQL 片段,使用 SQLAlchemy JSON 方法增强类型安全。

- sql += f"meta->>'{key}' = '{value}'"
+ filter_conditions.append(
+ Dataset.meta[key].as_string() == value
+ )

5.5 成本分析与优化

精细化运营:知道每一分钱花在哪里。

Total Cost $4,281
LLM Inference
GPT-4, Claude 3 (60%)
$2,568
Vector DB
Storage & Indexing (25%)
$1,070
Embedding
Text-to-Vector (15%)
$643

总结 · LLM 应用开发的进化路径

以统一编排为核心,叠加工程护栏、生态扩展与事件驱动,构建可观测、可演进的生产级 AI 应用。

阶段 1 · 范式升级
低代码编排 + Pro-Code 深逻辑,压缩从想法到上线。
Week 1
阶段 2 · 工程护栏
重试、分支、配额、可观测性与治理策略,守护可靠性。
Week 2
阶段 3 · 生态扩展 & 事件驱动
Marketplace / Plugin / Trigger 打通外部能力,形成资产库。
Week 3
阶段 4 · 数据透明与演进
OTEL 全链路 + 多库抽象,持续优化性能与成本。
持续

Thank You

Call for Action: 欢迎提交 PR,贡献插件、案例与最佳实践,共建 Dify 生态。
banana@dify.ai
小红书 QR Code
小红书
哔哩哔哩 QR Code
哔哩哔哩