Dify 低代码 Agent 开发:Workflow、知识库与 Agent 编排一站式实战

导读: 不是每个团队都有精力从零搭建 LangChain/LangGraph 代码栈。Dify 作为国内最活跃的开源 LLM 应用平台,提供了可视化工作流编排、知识库管理、Agent 策略配置三大核心能力。本文将从 Workflow 节点拆解、知识库 RAG 原理、Agent 编排策略三个维度,带你用"低代码"的方式构建生产级 AI 应用。


目录

  1. Dify 是什么?为什么选择它?
  2. Dify 核心架构速览
  3. Workflow:可视化编排 LLM 工作流
  4. 知识库:从文档到 RAG 的全链路
  5. Agent 编排:Function Calling 与策略配置
  6. 实战一:构建智能客服系统(Workflow + 知识库)
  7. 实战二:构建数据分析 Agent(代码执行 + 多工具)
  8. 实战三:通过 API 将 Dify 嵌入业务系统
  9. 进阶:插件开发与私有化部署
  10. 总结与选型建议

一、Dify 是什么?为什么选择它?

1.1 Dify 的定位

┌─────────────────────────────────────────────────────────┐
│                    LLM 应用开发方式                        │
│                                                          │
│  纯代码                         低代码           无代码    │
│  ────────────┬──────────────┬──────────────┬───────────  │
│  LangChain   │  LangGraph   │    Dify      │   Coze     │
│  LlamaIndex  │  CrewAI      │  (开源/云)    │  (扣子)    │
│              │              │              │            │
│  最大灵活性   │              │  平衡效率与   │  最快上手   │
│  最多代码     │              │  灵活性       │  最少控制   │
└──────────────────────────────────────────────────────────┘

Dify 的核心价值主张是:用可视化编排 + 配置驱动,覆盖 80% 的 LLM 应用场景,同时保留 API 和插件扩展能力来覆盖剩下的 20%。

1.2 Dify vs 纯代码框架

维度 Dify LangChain/LangGraph
开发效率 ⭐⭐⭐⭐⭐ 拖拽式编排 ⭐⭐ 需要编写大量代码
灵活性 ⭐⭐⭐ 受限于平台能力 ⭐⭐⭐⭐⭐ 完全自由
知识库/RAG 内置可视化配置 需要手动集成
多模型管理 统一管理,一键切换 代码中切换
运维监控 内置日志、费用统计 需要 LangSmith 等
协作 多人协作、权限管理 Git 协作
私有化部署 社区版免费部署 无额外依赖
适合人群 产品/运营/全栈 资深开发者

二、Dify 核心架构速览

2.1 四大核心模块

┌─────────────────────────────────────────────────────────┐
│                     Dify 平台                             │
│                                                          │
│  ┌──────────────┐  ┌──────────────┐  ┌───────────────┐  │
│  │  应用层       │  │   Workflow   │  │   知识库       │  │
│  │              │  │              │  │               │  │
│  │ • 聊天助手    │  │ • 可视化编排  │  │ • 文档导入     │  │
│  │ • Agent      │  │ • 节点系统   │  │ • Embedding   │  │
│  │ • 文本生成    │  │ • 变量管理   │  │ • 向量检索     │  │
│  │ • API 服务   │  │ • 调试工具   │  │ • 分段策略     │  │
│  └──────┬───────┘  └──────┬───────┘  └───────┬───────┘  │
│         │                 │                   │          │
│         └─────────────────┼───────────────────┘          │
│                           │                              │
│  ┌────────────────────────┴──────────────────────────┐  │
│  │              模型供应商层                            │  │
│  │  OpenAI │ 通义千问 │ 文心一言 │ DeepSeek │ 本地模型  │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

2.2 应用类型

Dify 支持四种应用类型,按灵活性递增排列:

类型 适用场景 灵活性
聊天助手 简单的对话机器人
Agent 需要调用工具的智能助手 ⭐⭐⭐
文本生成 翻译、摘要、写作等单次任务
Workflow 复杂的多步骤业务流程 ⭐⭐⭐⭐⭐

三、Workflow:可视化编排 LLM 工作流

Workflow 是 Dify 最强大的功能。它允许你通过拖拽节点、连线、配置参数来构建复杂的 LLM 应用。

3.1 节点类型全览

┌─────────────────────────────────────────────────────────┐
│                 Dify Workflow 节点分类                    │
│                                                          │
│  【开始/结束】                                            │
│  ├── Start:定义输入变量                                 │
│  └── End:定义输出变量                                   │
│                                                          │
│  【LLM 相关】                                             │
│  ├── LLM:调用大语言模型                                 │
│  ├── Knowledge Retrieval:从知识库检索                   │
│  └── Question Classifier:问题分类                       │
│                                                          │
│  【逻辑控制】                                             │
│  ├── IF/ELSE:条件分支                                  │
│  ├── Iteration:循环(遍历数组)                         │
│  └── Variable Aggregator:变量聚合                      │
│                                                          │
│  【工具调用】                                             │
│  ├── Code:执行 Python/JS 代码                          │
│  ├── HTTP Request:调用外部 API                         │
│  ├── Tool:使用内置/自定义工具                          │
│  └── Parameter Extractor:从文本中提取结构化参数        │
│                                                          │
│  【数据处理】                                             │
│  ├── Template:Jinja-2 模板转换                         │
│  ├── Variable Assigner:变量赋值                        │
│  └── Doc Extractor:文档内容提取                        │
└─────────────────────────────────────────────────────────┘

3.2 核心节点深度解析

LLM 节点

这是最核心的节点,配置要点:

┌─────────────────────────────────────────┐
│           LLM 节点配置面板                │
│                                          │
│  模型:[下拉选择] GPT-4 / Qwen / ...     │
│                                          │
│  SYSTEM Prompt:                         │
│  ┌──────────────────────────────────┐   │
│  │ 你是一位{{role}},擅长{{skill}}。  │   │
│  │ 请用{{language}}回答。            │   │
│  │              ↑ 变量引用           │   │
│  └──────────────────────────────────┘   │
│                                          │
│  USER Prompt:                           │
│  ┌──────────────────────────────────┐   │
│  │ {{#context#}}  ← 上下文(知识库)   │   │
│  │                                   │   │
│  │ 用户问题:{{#sys.query#}}         │   │
│  └──────────────────────────────────┘   │
│                                          │
│  Memory:[开启] 窗口大小:10 轮          │
│  Temperature:[0.7          ]           │
└─────────────────────────────────────────┘

Prompt 中的变量引用语法:

{# 输入变量 #}
{{#sys.query#}}              {# 用户原始输入 #}
{{#sys.files#}}              {# 用户上传的文件 #}

{# 上游节点输出 #}
{{#node_name.output_field#}} {# 引用特定节点的输出 #}

{# 会话变量 #}
{{#conversation_id#}}        {# 当前会话 ID #}

{# 环境变量 #}
{{#env.API_KEY#}}            {# 平台级环境变量 #}
Code 节点

Code 节点让你在 Workflow 中执行自定义 Python/JavaScript 代码,是扩展 Workflow 能力的关键:

# Dify Code 节点的 Python 代码示例
# 输入变量:上游节点传递的 data
# 输出:通过 return 返回

import json
from datetime import datetime

def main(data: dict) -> dict:
    """
    data 包含:
    - llm_output: LLM 节点的输出文本
    - user_info: 用户信息
    """
    # 解析 LLM 输出
    llm_text = data.get("llm_output", "")
    
    # 提取结构化信息
    result = {
        "processed": True,
        "timestamp": datetime.now().isoformat(),
        "word_count": len(llm_text),
        "summary": llm_text[:200] if len(llm_text) > 200 else llm_text,
    }
    
    # 尝试提取 JSON
    try:
        # 假设 LLM 输出中包含 JSON
        import re
        json_match = re.search(r'\{.*?\}', llm_text, re.DOTALL)
        if json_match:
            result["extracted_data"] = json.loads(json_match.group())
    except:
        result["extracted_data"] = None
    
    return result
HTTP Request 节点

将外部 API 的能力引入 Workflow:

# HTTP Request 节点配置示例

# 请求配置:
# Method: POST
# URL: https://api.weather.com/v1/forecast
# Headers: {"Authorization": "Bearer {{#env.WEATHER_API_KEY}}"}
# Body:
{
    "city": "{{#start.city}}",
    "date": "{{#start.date}}",
    "units": "metric"
}

# 响应处理:
# 响应会被自动解析为 JSON,下游节点可以用 {{#http_node.body.temperature}} 引用
IF/ELSE 条件节点
                 ┌──────────┐
                 │   LLM    │  (回答用户问题)
                 └────┬─────┘
                      │
              ┌───────┴───────┐
              │ IF/ELSE       │
              │               │
              │ 条件1:        │
              │ {{#llm.output │
              │  .contains(   │
              │  "投诉")}}    │
              │               │
              ├─── 是 ────────▶ [转人工客服]
              │               │
              │ 条件2:        │
              │ {{#llm.output │
              │  .contains(   │
              │  "购买")}}    │
              │               │
              ├─── 是 ────────▶ [创建订单]
              │               │
              └─── 否 ────────▶ [正常回复]
Iteration 循环节点
# Iteration 节点内的处理逻辑

# 输入:一个数组 ["Python", "JavaScript", "Go"]
# 每次迭代,当前元素通过 {{#iteration.item}} 引用

# 在迭代体中:
# LLM 节点 Prompt:请用一句话介绍 {{#iteration.item}} 语言。
# 输出收集到数组中,通过 Variable Aggregator 聚合

3.3 变量系统

Dify Workflow 的变量系统分为三层:

┌──────────────────────────────────────────────────────┐
│                  Dify 变量作用域                       │
│                                                       │
│  【环境变量】(全局)                                   │
│  ├── API Keys                                         │
│  ├── 系统配置常量                                       │
│  └── 通过 {{#env.NAME}} 引用                          │
│                                                       │
│  【会话变量】(跨轮次)                                  │
│  ├── 对话历史                                          │
│  ├── 用户身份信息                                       │
│  └── 通过会话变量节点设置/读取                           │
│                                                       │
│  【节点变量】(单次运行)                                │
│  ├── 各节点的输入/输出                                  │
│  └── 通过 {{#node_name.field}} 引用                   │
└──────────────────────────────────────────────────────┘

四、知识库:从文档到 RAG 的全链路

知识库是 Dify 解决 LLM 幻觉问题的核心武器。它让 LLM 能够基于你的私有文档回答问题。

4.1 知识库工作原理

┌─────────────────────────────────────────────────────────┐
│                   Dify 知识库全链路                        │
│                                                          │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌───────┐ │
│  │ 文档导入  │──▶│ 文本分段  │──▶│ 向量化   │──▶│ 索引  │ │
│  │          │   │          │   │          │   │       │ │
│  │ • PDF    │   │ • 自动分段│   │ • Embed  │   │• 向量  │ │
│  │ • Word   │   │ • 自定义  │   │ • 模型   │   │  数据库│ │
│  │ • Markdown│  │   分隔符  │   │   选择   │   │       │ │
│  │ • TXT    │   │ • 分段长度│   │          │   │       │ │
│  │ • 网页   │   │ • 重叠   │   │          │   │       │ │
│  └──────────┘   └──────────┘   └──────────┘   └───────┘ │
│                                                          │
│  检索阶段:                                               │
│  ┌──────────┐   ┌──────────┐   ┌──────────┐             │
│  │ 用户问题  │──▶│ 向量化    │──▶│ 相似度    │             │
│  │          │   │ (Embed)  │   │ 搜索 TopK │             │
│  └──────────┘   └──────────┘   └────┬─────┘             │
│                                     │                    │
│                                     ▼                    │
│                              ┌──────────┐               │
│                              │ 重排序    │ (Rerank)      │
│                              │ (可选)   │               │
│                              └────┬─────┘               │
│                                   │                      │
│                                   ▼                      │
│                           返回最相关的文档片段            │
└─────────────────────────────────────────────────────────┘

4.2 分段策略:知识库效果的"胜负手"

分段(Chunking)是知识库最关键的配置,直接影响检索质量:

策略 适用场景 示例
自动分段 通用文档 按段落、标题自动切分
自定义分隔符 结构化文档 \n\n(段落)、###(Markdown 标题)
固定长度 代码、日志 每 500 token 一段,重叠 50 token
递归分段 复杂嵌套文档 先按大标题分,再按小标题分
# Dify 知识库 API 调用示例
import requests

API_BASE = "https://your-dify-instance.com/v1"
API_KEY = "dataset-xxx"

# 方式1: 通过 API 上传文档
def upload_document(file_path: str, dataset_id: str):
    """上传文档到知识库"""
    url = f"{API_BASE}/datasets/{dataset_id}/document/create-by-file"
    
    headers = {"Authorization": f"Bearer {API_KEY}"}
    
    with open(file_path, "rb") as f:
        files = {"file": f}
        # 注意:嵌套配置需要 JSON 序列化后作为表单字段传递
        import json
        data = {
            "indexing_technique": "high_quality",
            "process_rule": json.dumps({
                "mode": "custom",
                "rules": {
                    "segmentation": {
                        "separator": "\n",
                        "max_tokens": 500,
                        "chunk_overlap": 50,
                    }
                }
            })
        }
        response = requests.post(url, headers=headers, files=files, data=data)
    
    return response.json()


# 方式2: 直接通过文本创建
def create_document_by_text(text: str, dataset_id: str, title: str):
    """通过文本内容创建知识库文档"""
    url = f"{API_BASE}/datasets/{dataset_id}/document/create-by-text"
    
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    }
    
    payload = {
        "name": title,
        "text": text,
        "indexing_technique": "high_quality",
        "process_rule": {
            "mode": "automatic",
        }
    }
    
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

4.3 检索模式对比

Dify 支持三种检索模式,按精确度递增:

经济模式(Economy)               高质量模式(High Quality)
───────────────                 ────────────────
关键词匹配(BM25)               向量检索 + Rerank
模糊匹配,速度快                 语义匹配,更精准
适合:FAQ、精确匹配              适合:长文档、语义理解

4.4 知识库 Workflow 配置示例

在 Workflow 中使用知识库节点时的配置:

# 知识库检索节点配置(逻辑示意)
节点类型: Knowledge Retrieval
配置:
  知识库: [选择已创建的知识库]
  检索模式: high_quality
  查询变量: "{{#llm_query_node.output}}"  # 用 LLM 改写后的查询
  TopK: 5                                    # 返回最相关的 5 段
  分数阈值: 0.6                              # 低于此分数的结果丢弃
  重排序: 启用                                # 使用 Rerank 模型

# 在 LLM 节点中使用检索结果:
# {{#knowledge_node.result}}  → 包含检索到的文档片段列表

五、Agent 编排:Function Calling 与策略配置

Dify 的 Agent 应用类型,本质上是ReAct + Function Calling 的可视化配置版本。

5.1 Agent 策略选择

Dify Agent 提供两种核心策略:

策略 全称 适用场景
ReAct Reasoning + Acting 通用场景,兼容性好
Function Calling 原生函数调用 模型本身支持 FC(GPT-4, Qwen-Max 等)
ReAct vs Function Calling 的差异:

ReAct:
  LLM 输出格式:Thought → Action → Action Input
  Prompt 工程驱动,所有模型通用
  输出格式可能不稳定(解析错误)

Function Calling:
  LLM 直接输出结构化的 tool_calls
  模型原生支持,格式可靠
  需要模型支持(不是所有模型都支持)

5.2 工具配置

在 Dify Agent 中可以配置三类工具:

┌──────────────────────────────────────────────────────┐
│                 Dify Agent 工具面板                    │
│                                                       │
│  【内置工具】                                          │
│  ├── 知识库检索(关联已创建的知识库)                    │
│  ├── 代码执行(Python/JS Sandbox)                    │
│  ├── 图片生成(DALL-E / Stable Diffusion)            │
│  └── 网页搜索(SerpAPI / Bing / Google)              │
│                                                       │
│  【自定义 API 工具】                                   │
│  ├── HTTP Request 工具                               │
│  └── OpenAPI / Swagger 导入                          │
│                                                       │
│  【自定义插件工具】                                     │
│  ├── 安装社区插件                                      │
│  └── 开发自定义插件(见第九节)                         │
└──────────────────────────────────────────────────────┘

5.3 Agent 配置最佳实践

# Dify Agent 的推荐配置(逻辑示意)
Agent 配置:
  模型: "qwen-max"              # 强力模型,Agent 对推理能力要求高
  策略: "Function Calling"      # 首选 FC,失败时降级到 ReAct
  
  工具:
    - knowledge_search:         # 知识库检索
        关联知识库: ["产品文档", "FAQ"]
        最大召回数: 5
    
    - code_executor:            # 代码执行
        语言: Python
        超时: 30s
    
    - custom_api:               # 自定义 API
        name: "查询订单"
        method: GET
        url: "https://api.example.com/orders/{{order_id}}"
        
  System Prompt: |
    你是羽哥电商的智能客服助手。
    
    处理流程:
    1. 如果用户询问产品信息,先检索知识库
    2. 如果用户询问订单状态,调用订单查询 API
    3. 如果需要计算(如折扣、运费),使用代码执行器
    4. 回复时引用来源,保持友好专业的语气
    
  Memory: 20 轮
  Temperature: 0.1              # Agent 建议低温

六、实战一:构建智能客服系统(Workflow + 知识库)

6.1 业务场景

为一个电商平台构建智能客服,需求如下:

  1. 用户询问产品信息 → 从知识库检索回答
  2. 用户询问订单状态 → 调用订单 API
  3. 用户投诉或要求退款 → 转人工客服
  4. 用户要求计算折扣 → 使用代码节点计算

6.2 Workflow 设计

                    ┌────────────┐
                    │   Start    │
                    │ user_query │
                    └─────┬──────┘
                          │
                          ▼
                  ┌───────────────┐
                  │   问题分类     │
                  │ (LLM节点)     │
                  │               │
                  │ 输出:         │
                  │ category:     │
                  │ product/order │
                  │ /complaint    │
                  │ /calculation  │
                  └───────┬───────┘
                          │
                ┌─────────┴─────────┐
                │   IF/ELSE         │
                │                   │
      ┌─────────┤ category=product  ├─────────┐
      │         │ category=order    │         │
      │         │ category=complaint│         │
      │         │ category=calc     │         │
      ▼         └───────────────────┘         │
┌──────────┐                                  │
│ 知识库检索│     ...  (其他分支)               │
└────┬─────┘                                  │
     │                                        │
     ▼                                        │
┌──────────┐                                  │
│ LLM:     │◀─────────────────────────────────┘
│ 回答问题  │    所有分支最终汇聚到这里
└────┬─────┘
     │
     ▼
┌──────────┐
│  End     │
└──────────┘

6.3 Step-by-Step 配置

Step 1:创建知识库

# 1. 在 Dify 界面:知识库 → 创建知识库
# 2. 上传文件:product_manual.pdf, faq.xlsx, shipping_policy.md
# 3. 设置分段策略:
#    - 模式:高质量
#    - 分隔符:\n\n### 
#    - 最大 token:500
#    - 重叠:50
# 4. 等待索引完成

Step 2:构建 Workflow

以下是具体节点的配置(代码形式展示,实际在 UI 中配置):

# === 节点1:Start ===
输入变量:
  user_query: text     # 用户问题
  user_id: text        # 用户 ID(可选)

# === 节点2:LLM 分类器 ===
# 模型:qwen-plus (temperature=0.1)
SYSTEM:
"""
你是一个问题分类专家。请将用户问题分类为以下之一:
- product:关于产品信息、功能、价格的问题
- order:关于订单状态、物流、退换货的问题
- complaint:投诉、不满、要求人工服务
- calculation:需要数学计算的问题(折扣、总价等)

只返回分类结果,不要解释。
"""

USER:
"""
用户问题:{{#start.user_query}}
"""

# === 节点3:IF/ELSE 分支 ===
条件:
  - IF {{#classifier.text}} contains "product"
    → 进入知识库检索分支
  - ELIF {{#classifier.text}} contains "order"  
    → 进入订单查询分支
  - ELIF {{#classifier.text}} contains "complaint"
    → 进入转人工分支
  - ELSE
    → 进入计算分支

# === 节点4a:知识库检索 ===
配置:
  知识库:电商产品知识库
  检索模式:高质量
  查询变量:{{#start.user_query}}
  TopK:5
  分数阈值:0.6

# === 节点4b:HTTP Request (订单查询) ===
Method: GET
URL: https://your-api.com/orders?user_id={{#start.user_id}}
Headers: {"Authorization": "Bearer {{#env.ORDER_API_KEY}}"}

# === 节点4c:转人工 ===
Template 节点:
"""
已为您转接人工客服。
用户问题:{{#start.user_query}}
用户ID:{{#start.user_id}}
请稍候,客服人员将很快为您服务。
"""

# === 节点5:LLM 回答生成 ===
SYSTEM:
"""
你是羽哥电商的客服助手。

使用以下检索到的信息回答问题:
{{#knowledge_retrieval.result}}

使用以下订单信息(如有):
{{#order_query.body}}

要求:
1. 基于提供的资料回答,不要编造
2. 回答简洁友好,200字以内
3. 如果是产品推荐,给出2-3个选项
"""

6.4 通过 API 测试 Workflow

import requests

# Workflow API 调用
def test_customer_service_workflow(user_query: str, user_id: str = "guest"):
    url = "https://your-dify-instance.com/v1/workflows/run"
    
    headers = {
        "Authorization": "Bearer app-xxx",  # Workflow 应用的 API Key
        "Content-Type": "application/json",
    }
    
    payload = {
        "inputs": {
            "user_query": user_query,
            "user_id": user_id,
        },
        "response_mode": "blocking",  # 同步模式
        "user": user_id,
    }
    
    response = requests.post(url, headers=headers, json=payload)
    return response.json()


# 测试
test_cases = [
    ("你们的蓝牙耳机续航多久?", "user_001"),
    ("订单 #12345 到哪了?", "user_002"),
    ("我要投诉,产品质量太差了!", "user_003"),
    ("买2件打8折,原价299,省了多少钱?", "user_004"),
]

for query, uid in test_cases:
    print(f"\n👤 用户:{query}")
    result = test_customer_service_workflow(query, uid)
    print(f"🤖 客服:{result.get('data', {}).get('outputs', {}).get('text', '无响应')}")

七、实战二:构建数据分析 Agent(代码执行 + 多工具)

7.1 场景设计

构建一个数据分析 Agent,能够:

  1. 接收用户上传的 CSV/Excel 文件
  2. 自动理解数据结构
  3. 根据用户需求执行 Python 分析代码
  4. 生成可视化图表
  5. 输出分析报告

7.2 Agent 配置

# Agent 应用配置

应用类型: Agent
模型: qwen-max (Function Calling 模式)

System Prompt: |
  你是一个数据分析专家 Agent。
  
  你可以使用以下工具:
  1. 代码执行器 - 运行 Python 代码进行数据分析
  2. 知识库检索 - 查找数据分析方法的最佳实践
  
  工作流程:
  1. 用户上传数据文件后,先用代码执行器查看数据结构
  2. 根据用户的分析需求,编写并执行 Python 代码
  3. 如果需要可视化,使用 matplotlib 生成图表
  4. 总结分析结果并给出建议
  
  重要规则:
  - 分析代码要包含错误处理
  - 图表保存后告知用户路径
  - 数据分析要严谨,标明数据的局限性

工具:
  - 代码执行器 (Python)
      超时: 120s
      预装库: pandas, numpy, matplotlib, seaborn, scipy
      
  - 知识库检索
      关联知识库: [数据分析方法知识库]
      TopK: 3
      
  - 自定义 API 工具 (可选):
      name: "查询行业基准数据"
      url: "https://api.benchmark.com/{{industry}}/{{metric}}"

7.3 知识库准备

为 Agent 准备一个"数据分析方法"知识库:

# 数据分析知识库文档示例


## 缺失值处理
- df.isnull().sum() 查看缺失值
- df.dropna() 删除含缺失值的行
- df.fillna(df.mean()) 用均值填充缺失值

## 异常值检测
- IQR 方法:Q1 - 1.5*IQR < normal < Q3 + 1.5*IQR
- Z-score 方法:|z| > 3 视为异常

## 常用分析方法
- df.describe() 描述性统计
- df.corr() 相关性分析
- df.groupby('column').agg(['mean', 'sum', 'count']) 分组聚合

## 可视化最佳实践
- 趋势用折线图:plt.plot()
- 分布用直方图:plt.hist()
- 类别对比用柱状图:plt.bar()
- 相关性用热力图:sns.heatmap()

7.4 与 Agent 交互示例

用户:上传了 sales_2024.csv,请帮我分析销售趋势

Agent:
💭 Thought: 用户上传了销售数据,我需要先查看数据结构。
🔧 Action: code_executor
📝 Code:
```python
import pandas as pd
df = pd.read_csv('sales_2024.csv')
print("数据概况:")
print(f"行数:{len(df)},列数:{len(df.columns)}")
print(f"列名:{list(df.columns)}")
print(f"数据类型:\n{df.dtypes}")
print(f"\n前5行:\n{df.head()}")
print(f"\n描述性统计:\n{df.describe()}")

👁️ Observation: …
💭 Thought: 数据包含日期、销售额、产品类别等字段。让我分析趋势。
🔧 Action: code_executor
📝 Code:

import pandas as pd
import matplotlib.pyplot as plt
# ... 趋势分析代码

👁️ Observation: 图表已保存

📝 Final Answer:
根据对 sales_2024.csv 的分析,发现以下关键趋势:

  1. 全年销售额呈上升趋势,Q4环比增长35%
  2. 电子产品类目贡献了60%的营收
  3. 12月销售额达到峰值,与促销季吻合
    建议:加大Q4库存准备,重点推广电子产品。

---

## 八、实战三:通过 API 将 Dify 嵌入业务系统

Dify 的每个应用都自动生成 API 端点,可以直接嵌入到你的业务系统中。

### 8.1 API 类型

| API 类型 | 端点 | 适用场景 |
|---------|------|---------|
| Chat (流式) | `POST /v1/chat-messages` | 对话应用,支持 SSE 流式输出 |
| Workflow (同步) | `POST /v1/workflows/run` | 工作流应用,一次性返回 |
| Completion | `POST /v1/completion-messages` | 文本生成应用 |
| Files | `POST /v1/files/upload` | 上传文件到应用 |

### 8.2 完整的 API 集成示例

```python
"""
Dify 业务集成 SDK 封装
适用于将 Dify 应用嵌入到 Flask/FastAPI/Django 项目中
"""
import requests
import json
from typing import Optional, Dict, Any, Generator


class DifyClient:
    """Dify API 客户端封装"""
    
    def __init__(self, base_url: str, api_key: str):
        self.base_url = base_url.rstrip('/')
        self.api_key = api_key
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        })
    
    # ========== 对话应用 ==========
    def chat(
        self,
        query: str,
        user: str,
        conversation_id: Optional[str] = None,
    ) -> Dict[str, Any]:
        """发送对话消息(阻塞模式)"""
        url = f"{self.base_url}/v1/chat-messages"
        
        payload = {
            "inputs": {},
            "query": query,
            "response_mode": "blocking",
            "user": user,
        }
        
        if conversation_id:
            payload["conversation_id"] = conversation_id
        
        resp = self.session.post(url, json=payload)
        resp.raise_for_status()
        return resp.json()
    
    def chat_stream(
        self,
        query: str,
        user: str,
        conversation_id: Optional[str] = None,
    ) -> Generator[str, None, None]:
        """发送对话消息(流式模式)"""
        url = f"{self.base_url}/v1/chat-messages"
        
        payload = {
            "inputs": {},
            "query": query,
            "response_mode": "streaming",
            "user": user,
        }
        
        if conversation_id:
            payload["conversation_id"] = conversation_id
        
        resp = self.session.post(url, json=payload, stream=True)
        resp.raise_for_status()
        
        for line in resp.iter_lines():
            if line:
                line_str = line.decode('utf-8')
                if line_str.startswith('data: '):
                    data = json.loads(line_str[6:])
                    if data.get('event') == 'message':
                        yield data.get('answer', '')
    
    # ========== Workflow 应用 ==========
    def run_workflow(
        self,
        inputs: Dict[str, Any],
        user: str,
        response_mode: str = "blocking",
    ) -> Dict[str, Any]:
        """运行 Workflow"""
        url = f"{self.base_url}/v1/workflows/run"
        
        payload = {
            "inputs": inputs,
            "response_mode": response_mode,
            "user": user,
        }
        
        resp = self.session.post(url, json=payload)
        resp.raise_for_status()
        return resp.json()
    
    # ========== 文件上传 ==========
    def upload_file(
        self,
        file_path: str,
        user: str,
    ) -> Dict[str, Any]:
        """上传文件(用于多模态应用)"""
        url = f"{self.base_url}/v1/files/upload"
        
        headers = {"Authorization": f"Bearer {self.api_key}"}
        # 注意:文件上传不用 Content-Type: application/json
        
        with open(file_path, 'rb') as f:
            files = {'file': f}
            data = {'user': user}
            resp = requests.post(url, headers=headers, files=files, data=data)
        
        resp.raise_for_status()
        return resp.json()
    
    # ========== 知识库管理 ==========
    def list_datasets(self, page: int = 1, limit: int = 20) -> Dict[str, Any]:
        """获取知识库列表"""
        url = f"{self.base_url}/v1/datasets"
        params = {"page": page, "limit": limit}
        resp = self.session.get(url, params=params)
        resp.raise_for_status()
        return resp.json()
    
    def search_knowledge(
        self,
        dataset_id: str,
        query: str,
        top_k: int = 5,
    ) -> Dict[str, Any]:
        """直接搜索知识库(不经过 LLM)"""
        url = f"{self.base_url}/v1/datasets/{dataset_id}/retrieve"
        
        payload = {
            "query": query,
            "retrieval_model": {
                "search_method": "hybrid_search",
                "top_k": top_k,
                "score_threshold": 0.5,
            }
        }
        
        resp = self.session.post(url, json=payload)
        resp.raise_for_status()
        return resp.json()


# ========== 在 FastAPI 中集成 ==========
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse

app = FastAPI()

# 初始化 Dify 客户端
dify_customer_service = DifyClient(
    base_url="https://your-dify.com",
    api_key="app-xxxx",
)

dify_data_analyst = DifyClient(
    base_url="https://your-dify.com",
    api_key="app-yyyy",
)


@app.post("/api/cs/chat")
async def customer_service_chat(query: str, user_id: str):
    """客服对话接口"""
    try:
        result = dify_customer_service.chat(query=query, user=user_id)
        return {
            "answer": result["answer"],
            "conversation_id": result.get("conversation_id"),
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@app.post("/api/cs/chat/stream")
async def customer_service_chat_stream(query: str, user_id: str):
    """客服对话接口(流式)"""
    def generate():
        try:
            for chunk in dify_customer_service.chat_stream(query, user_id):
                yield f"data: {json.dumps({'content': chunk})}\n\n"
            yield "data: [DONE]\n\n"
        except Exception as e:
            yield f"data: {json.dumps({'error': str(e)})}\n\n"
    
    return StreamingResponse(generate(), media_type="text/event-stream")


@app.post("/api/analyst/analyze")
async def analyze_data(file_url: str, question: str, user_id: str):
    """数据分析接口"""
    result = dify_data_analyst.run_workflow(
        inputs={
            "file_url": file_url,
            "user_question": question,
        },
        user=user_id,
    )
    return result


# 运行:uvicorn app:app --reload

九、进阶:插件开发与私有化部署

9.1 Dify 插件开发

Dify 支持通过插件扩展 Tool 能力。以下是开发一个自定义 Tool 插件的基本流程:

# dify_plugin/weather_tool.py
"""
Dify 自定义工具插件示例:天气查询工具

打包后上传到 Dify 平台即可在 Agent 中使用。
"""
from typing import Any, Dict
from dify_plugin import ToolProvider


class WeatherTool(ToolProvider):
    """天气查询工具"""
    
    name = "weather_query"
    
    # 工具参数定义
    @property
    def parameters(self) -> Dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "城市名称,例如:北京、上海",
                },
                "date": {
                    "type": "string",
                    "description": "日期,格式 YYYY-MM-DD,默认为今天",
                },
            },
            "required": ["city"],
        }
    
    # 工具描述(LLM 据此判断何时使用)
    @property
    def description(self) -> Dict[str, Any]:
        return {
            "zh_Hans": "查询指定城市的天气情况,包括温度、湿度、天气状况、风力。",
            "en_US": "Query weather information for a specified city.",
        }
    
    # 工具执行逻辑
    def _invoke(self, parameters: Dict[str, Any]) -> str:
        city = parameters.get("city")
        date = parameters.get("date", "today")
        
        # 调用真实的天气 API
        import requests
        api_key = self.credentials.get("weather_api_key")
        
        response = requests.get(
            "https://api.weatherapi.com/v1/forecast.json",
            params={"key": api_key, "q": city, "dt": date},
        )
        
        data = response.json()
        current = data.get("current", {})
        
        return (
            f"城市:{city}\n"
            f"日期:{date}\n"
            f"天气:{current.get('condition', {}).get('text')}\n"
            f"温度:{current.get('temp_c')}℃\n"
            f"湿度:{current.get('humidity')}%\n"
            f"风力:{current.get('wind_kph')} km/h"
        )


# 注册插件
def register():
    return WeatherTool()

9.2 Docker 私有化部署

# 1. 克隆项目
git clone https://github.com/langgenius/dify.git
cd dify/docker

# 2. 配置环境变量
cp .env.example .env
# 编辑 .env,配置必要的密钥和数据库连接

# 3. 启动服务
docker compose up -d

# 4. 访问
# http://localhost:3000  → Web 控制台
# http://localhost:5001  → API 服务

# 5. 生产环境注意事项:
# - 配置 HTTPS
# - 使用外部 PostgreSQL / Redis
# - 配置对象存储(S3/MinIO)替代本地存储
# - 设置资源限制(特别是 Sandbox 容器)

十、总结与选型建议

10.1 本文回顾

知识点 核心要点
Workflow 可视化编排的核心,掌控 10+ 节点类型构建复杂流程
知识库 分段策略(分隔符/长度/重叠)是检索质量的生死线
Agent Function Calling 模式优先,System Prompt 设计是关键
API 集成 每个应用自动生成 REST API,支持同步/流式
插件开发 自定义 Tool 扩展 Agent 能力,弥补低代码的灵活性短板

10.2 Dify 最适合的场景

Dify 特别适合:
✅ 需要快速原型验证的 LLM 项目
✅ 业务人员参与配置的 AI 应用
✅ 知识库 + 对话的企业内部应用
✅ 多模型统一管理的平台
✅ 需要私有化部署的开源方案

Dify 不太适合:
❌ 需要非常复杂的自定义控制流(考虑 LangGraph)
❌ 多 Agent 协作场景(考虑 CrewAI / AutoGen)
❌ 需要深度定制的训练/微调流程
❌ 对延迟有极致要求的实时场景(考虑直接调用 API)

💡 核心心法:Dify 解决的不是"能不能做"的问题(代码都能做),而是"做多快"和"谁来做"的问题。 对于中小团队,用 Dify 一天能上线的应用,纯代码开发可能需要一周。但当你的业务逻辑超出 Dify 节点的表达能力时,果断回到代码方案(LangChain/LangGraph),不要强行在 UI 上绕弯路。


本文基于 Dify v0.6+ 编写,部分界面和 API 可能随版本更新调整。建议结合 Dify 官方文档 获取最新信息。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐