Dify AI应用开发平台完全教程
前言
在AI应用开发领域,如何快速将大语言模型的能力转化为可用的商业产品,一直是开发者面临的核心挑战。传统的AI应用开发需要深厚的机器学习知识、复杂的工程架构和大量的基础设施投入。而Dify的出现,彻底改变了这一局面。
Dify是一个开源的AI应用开发平台,它提供了可视化的编排界面、强大的工作流引擎和完善的API接口,让开发者无需深入底层技术细节,就能快速构建生产级的AI应用。
本教程将从零开始,系统性地讲解Dify平台的架构原理、核心功能、开发技巧,并通过一个完整的企业级智能客服系统实战项目,帮助你掌握Dify开发的全流程。
第一章:Dify平台概述与架构
1.1 什么是Dify
Dify(发音为"Define")是一个开源的LLM应用开发平台,其核心理念是通过可视化编排降低AI应用的开发门槛。它提供了以下核心能力:
- 可视化应用编排:通过拖拽式界面构建AI应用,无需编写代码
- 多模型支持:集成OpenAI、Anthropic、本地模型等多种LLM
- 知识库管理:支持文档上传、智能分段、向量检索
- 工作流引擎:支持复杂的业务逻辑编排
- API驱动:所有功能都可以通过API调用
- 插件生态:可扩展的插件系统
1.2 平台架构
Dify采用经典的分层架构设计:
┌─────────────────────────────────────────────────────────────┐
│ 前端层(Frontend) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 应用编排 │ │ 知识库 │ │ 模型管理 │ │ 数据分析 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────┬───────────────────────────────────┘
│ HTTP/WebSocket
┌─────────────────────────┴───────────────────────────────────┐
│ API层(API Server) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 应用API │ │ 知识库API│ │ 模型API │ │ 插件API │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────┬───────────────────────────────────┘
│
┌─────────────────────────┴───────────────────────────────────┐
│ 服务层(Service Layer) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 编排引擎 │ │ RAG引擎 │ │ 模型调度 │ │ 插件引擎 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────┬───────────────────────────────────┘
│
┌─────────────────────────┴───────────────────────────────────┐
│ 基础设施层(Infrastructure) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ PostgreSQL│ │ Redis │ │ 向量数据库│ │ 文件存储 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────┘
1.3 核心概念
在使用Dify之前,需要理解以下核心概念:
应用(Application) Dify中的基本单元。每个应用对应一个具体的AI功能,如聊天机器人、文本生成器、工作流等。
应用类型
- Chatflow(对话流):多轮对话应用,支持上下文记忆
- Workflow(工作流):单次执行的自动化流程
- Agent(智能体):具备工具调用和自主推理能力的应用
- 文本生成:单次文本生成应用
节点(Node) 工作流中的基本单元,每个节点执行一个特定的功能,如LLM调用、条件判断、工具调用等。
变量(Variable) 在工作流中传递数据的载体。包括环境变量、会话变量、节点输出变量等。
知识库(Knowledge Base) 存储和管理文档数据的模块,支持向量检索和全文检索。
第二章:Dify安装部署
2.1 环境要求
在安装Dify之前,确保你的系统满足以下要求:
- 操作系统:Linux(推荐Ubuntu 20.04+)、macOS、Windows(WSL2)
- Docker:20.10+
- Docker Compose:2.0+
- 内存:最低4GB,推荐8GB+
- 磁盘:最低20GB可用空间
- 网络:能够访问Docker Hub和模型API
2.2 Docker Compose本地部署
Dify官方推荐使用Docker Compose进行部署,这是最简单的方式。
第一步:克隆代码
# 克隆Dify仓库
git clone https://github.com/langgenius/dify.git
cd dify/docker
第二步:配置环境变量
# 复制环境变量模板
cp .env.example .env
# 编辑环境变量
vim .env
关键环境变量说明:
# 应用密钥(必须修改)
SECRET_KEY=your-random-secret-key-here
# 数据库配置
DB_USERNAME=postgres
DB_PASSWORD=your-db-password
DB_HOST=db
DB_PORT=5432
DB_DATABASE=dify
# Redis配置
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=your-redis-password
# 向量数据库(默认使用Weaviate)
VECTOR_STORE=weaviate
# 文件存储类型
STORAGE_TYPE=local
# 日志级别
LOG_LEVEL=INFO
第三步:启动服务
# 启动所有服务
docker compose up -d
# 查看服务状态
docker compose ps
# 查看日志
docker compose logs -f api
第四步:访问Dify
服务启动后,通过浏览器访问 http://localhost(默认端口80)。
首次访问需要设置管理员账号:
- 输入邮箱和密码
- 完成初始化配置
- 进入Dify控制台
2.3 使用Dify云服务
如果不想自行部署,可以直接使用Dify提供的云服务:
- 访问 https://cloud.dify.ai
- 注册账号
- 直接开始使用
云服务的优势:
- 无需维护基础设施
- 自动更新到最新版本
- 提供技术支持
- 按使用量付费
2.4 配置模型提供商
安装完成后,需要配置至少一个模型提供商:
- 进入 设置 → 模型供应商
- 添加模型提供商(如OpenAI、Anthropic等)
- 输入API Key
- 测试连接是否成功
# 如果使用OpenAI
export OPENAI_API_KEY=sk-your-api-key
# 如果使用自定义API端点
export OPENAI_API_BASE=https://your-custom-endpoint.com/v1
第三章:Chatflow对话流设计
3.1 什么是Chatflow
Chatflow是Dify中最常用的应用类型,用于构建多轮对话应用。它的核心特点:
- 支持上下文记忆
- 可视化节点编排
- 支持变量传递
- 支持条件分支
- 支持工具调用
3.2 创建Chatflow应用
- 在Dify控制台,点击 创建应用
- 选择 Chatflow 类型
- 输入应用名称和描述
- 进入可视化编辑器
3.3 核心节点详解
开始节点
每个Chatflow都从"开始"节点开始。在这里可以定义:
- 系统提示词(System Prompt):定义AI的角色和行为准则
- 变量:定义用户输入的变量
系统提示词示例:
你是一个专业的客户服务代表。请用友好、专业的语气回答用户的问题。
如果遇到无法回答的问题,请引导用户联系人工客服。
用户输入变量:
- user_query: 用户的问题(字符串类型)
- user_id: 用户ID(字符串类型,可选)
LLM节点
LLM节点是Chatflow的核心,用于调用大语言模型:
配置项:
- 模型:选择使用的模型(如gpt-4、gpt-3.5-turbo)
- 提示词:可以引用变量,如 {{user_query}}
- 温度:控制输出的随机性(0-1)
- 最大Token数:限制输出长度
- 上下文:选择是否包含对话历史
变量引用语法:
在提示词中引用变量使用双花括号:{{variable_name}}
示例提示词:
用户的问题是:{{user_query}}
请根据以下知识库内容回答:
{{#context#}}
如果知识库中没有相关信息,请告知用户你不确定。
条件分支节点
用于根据条件执行不同的逻辑:
条件配置示例:
- IF {{user_query}} 包含 "退款" → 进入退款处理分支
- ELSE IF {{user_query}} 包含 "投诉" → 进入投诉处理分支
- ELSE → 进入通用问答分支
知识检索节点
用于从知识库中检索相关信息:
配置项:
- 知识库:选择要检索的知识库
- 检索模式:
- 向量检索:基于语义相似度
- 全文检索:基于关键词匹配
- 混合检索:结合两者
- TopK:返回最相关的K条结果
- 相似度阈值:过滤低相关性的结果
代码节点
用于执行自定义代码逻辑:
# 代码节点示例:数据处理
def main(query: str, context: list) -> dict:
# 处理检索到的上下文
processed_context = []
for item in context:
if item.get("score", 0) > 0.7: # 只保留高相关性的结果
processed_context.append(item["content"])
return {
"processed_context": "\n".join(processed_context),
"has_results": len(processed_context) > 0
}
HTTP请求节点
用于调用外部API:
配置项:
- 方法:GET/POST/PUT/DELETE
- URL:API地址,支持变量插值
- Headers:请求头
- Body:请求体
- 超时:请求超时时间
结束节点
定义Chatflow的输出格式:
输出变量:
- answer: AI的回答
- sources: 引用的知识库来源(可选)
3.4 变量传递机制
变量是Chatflow中数据流转的核心。理解变量的作用域和传递规则非常重要:
节点输出变量
每个节点执行后都会产生输出变量,可以在后续节点中引用:
LLM节点输出:
- text: 生成的文本
- usage: Token使用量
知识检索节点输出:
- result: 检索结果列表
- 每个结果包含:content, score, metadata
代码节点输出:
- 由代码中的return语句定义
会话变量
会话变量在整个对话过程中持续存在:
# 设置会话变量
conversation_id = get_conversation_id()
set_variable("conversation_turn", get_variable("conversation_turn", 0) + 1)
# 使用会话变量实现上下文记忆
turn_count = get_variable("conversation_turn", 0)
if turn_count > 5:
# 超过5轮对话,建议转人工
suggest_human_agent()
3.5 实战:构建客服对话流
下面是一个完整的客服Chatflow设计:
[开始] → [意图识别LLM] → [条件分支]
├─ "订单问题" → [订单知识库检索] → [订单回复LLM] → [结束]
├─ "退款问题" → [退款政策检索] → [退款回复LLM] → [结束]
├─ "投诉" → [记录投诉HTTP] → [安抚回复LLM] → [结束]
└─ "其他" → [通用回复LLM] → [结束]
意图识别节点的提示词:
请分析用户的意图,并返回以下类别之一:
- order: 订单相关问题(查询、修改、取消订单)
- refund: 退款相关问题(退款流程、退款状态)
- complaint: 投诉(服务不满意、产品质量问题)
- other: 其他问题
用户输入:{{user_query}}
请只返回类别名称,不要添加其他内容。
第四章:Workflow工作流构建
4.1 Chatflow vs Workflow
| 特性 | Chatflow | Workflow |
|---|---|---|
| 交互方式 | 多轮对话 | 单次执行 |
| 上下文 | 保持对话历史 | 无上下文 |
| 适用场景 | 客服、聊天 | 数据处理、自动化 |
| 输入 | 用户消息 | 结构化参数 |
| 输出 | AI回复 | 执行结果 |
4.2 Workflow典型应用场景
- 数据处理流水线:批量处理文档、数据清洗
- 内容生成:自动生成文章、报告
- 信息提取:从非结构化文本中提取结构化数据
- 自动化决策:基于规则的自动审批、分类
- API编排:串联多个API实现复杂业务逻辑
4.3 构建数据处理Workflow
下面以"批量文章摘要生成"为例,展示Workflow的构建过程:
第一步:定义输入
输入变量:
- articles: 文章列表(数组类型)
- 每个元素包含:title, content, url
- language: 输出语言(字符串,默认"中文")
- max_length: 摘要最大长度(数字,默认200)
第二步:迭代处理节点
Dify的Workflow支持迭代节点,可以对数组中的每个元素执行相同的操作:
迭代节点配置:
- 输入数组:{{articles}}
- 迭代变量:current_article
子流程:
1. [LLM节点] 生成摘要
提示词:
请为以下文章生成摘要,语言为{{language}},长度不超过{{max_length}}字。
标题:{{current_article.title}}
内容:{{current_article.content}}
2. [代码节点] 格式化输出
代码:
def main(title: str, summary: str, url: str) -> dict:
return {
"formatted": f"## {title}\n\n{summary}\n\n来源:{url}\n"
}
第三步:聚合结果
代码节点:聚合所有摘要
def main(summaries: list) -> dict:
combined = "\n---\n".join(summaries)
return {
"final_output": f"# 文章摘要汇总\n\n共处理 {len(summaries)} 篇文章\n\n{combined}",
"count": len(summaries)
}
4.4 条件路由与错误处理
Workflow中需要考虑异常情况:
# 代码节点:错误处理
def main(article: dict) -> dict:
if not article.get("content"):
return {
"error": True,
"message": f"文章 '{article.get('title', '未知')}' 内容为空"
}
if len(article["content"]) < 100:
return {
"error": True,
"message": f"文章 '{article['title']}' 内容太短,跳过处理"
}
return {"error": False, "article": article}
4.5 Workflow调试技巧
- 逐步执行:Dify支持单步调试,可以查看每个节点的输入输出
- 日志查看:在运行日志中查看详细的执行过程
- 变量检查:在每个节点后检查变量值是否正确
- 错误追踪:当执行失败时,查看错误堆栈信息
第五章:知识库管理
5.1 知识库概述
知识库是RAG(检索增强生成)的核心组件。它允许AI基于你提供的文档来回答问题,而不是仅依赖模型的预训练知识。
Dify的知识库功能包括:
- 支持多种文档格式(PDF、Word、TXT、Markdown等)
- 智能文档分段
- 向量检索和全文检索
- 检索结果排序和过滤
5.2 创建知识库
- 在Dify控制台,点击 知识库
- 点击 创建知识库
- 输入知识库名称和描述
- 上传文档
5.3 文档分段策略
文档分段是知识库质量的关键。Dify提供多种分段策略:
自动分段
Dify会根据文档结构自动进行分段,适合大多数场景。
自定义分段
可以手动设置分段参数:
- 分段标识符:指定用什么字符来分割文档
- 最大分段长度:每个分段的最大字符数
- 分段重叠:相邻分段之间的重叠字符数
分段配置示例:
- 分段标识符:\n\n(按段落分割)
- 最大长度:500字符
- 重叠:50字符
这样可以确保:
1. 每个分段是一个完整的语义单元
2. 不会切断句子或段落
3. 重叠部分保持上下文连贯性
5.4 索引方法
Dify支持多种索引方法:
高质量索引
- 使用Embedding模型将文本转换为向量
- 支持语义检索
- 需要配置Embedding模型
- 检索效果更好
经济索引
- 使用关键词匹配
- 不需要Embedding模型
- 检索速度更快
- 成本更低
混合索引
- 结合向量检索和关键词检索
- 综合两者的优势
- 推荐在生产环境中使用
5.5 检索配置优化
# 推荐的检索配置
检索模式: 混合检索
向量检索权重: 0.7
关键词检索权重: 0.3
TopK: 5
相似度阈值: 0.5
Rerank模型: 启用
Rerank TopK: 3
5.6 知识库维护
更新文档
当源文档更新时,需要重新上传并建立索引:
- 选择要更新的文档
- 点击"重新上传"
- 等待索引重建完成
监控检索质量
定期检查检索结果的质量:
- 使用测试查询检查返回结果的相关性
- 如果结果不理想,调整分段策略或检索参数
- 考虑添加更多高质量的文档
第六章:Agent集成
6.1 Dify中的Agent
Dify的Agent应用类型允许创建具备自主推理和工具调用能力的AI应用。与Chatflow不同,Agent可以:
- 自主决定是否调用工具
- 多轮推理完成复杂任务
- 动态选择合适的工具
6.2 创建Agent应用
- 创建新应用,选择 Agent 类型
- 配置系统提示词
- 添加工具
- 设置推理模式
6.3 工具配置
Dify提供三类工具:
内置工具
Dify内置了多种常用工具:
- 网络搜索(Google、Bing等)
- 数学计算
- 代码执行
- 图片生成
- 更多...
自定义工具
可以通过OpenAPI Schema自定义工具:
{
"openapi": "3.0.0",
"info": {
"title": "订单查询API",
"version": "1.0.0"
},
"servers": [
{
"url": "https://api.example.com"
}
],
"paths": {
"/orders/{order_id}": {
"get": {
"summary": "查询订单详情",
"operationId": "getOrder",
"parameters": [
{
"name": "order_id",
"in": "path",
"required": true,
"schema": {
"type": "string"
},
"description": "订单ID"
}
],
"responses": {
"200": {
"description": "订单详情",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"status": {"type": "string"},
"total": {"type": "number"}
}
}
}
}
}
}
}
}
}
}
工作流工具
可以将Workflow封装为Agent可调用的工具。
6.4 推理模式
Dify的Agent支持多种推理模式:
Function Calling
利用模型原生的Function Calling能力,是推荐的模式。
ReAct
经典的推理-行动循环模式,兼容性更好。
6.5 Agent提示词设计
# 系统提示词示例
## 角色
你是一个专业的客户服务Agent,能够帮助用户查询订单、处理退款、解答问题。
## 能力
- 查询订单状态和详情
- 处理退款申请
- 解答产品相关问题
- 记录用户反馈
## 规则
1. 始终保持友好专业的语气
2. 需要用户提供订单号时,主动询问
3. 涉及金额操作时,需要用户确认
4. 无法处理的问题,引导联系人工客服
## 工具使用指南
- 使用 order_query 查询订单信息
- 使用 refund_apply 提交退款申请
- 使用 knowledge_search 搜索产品知识库
第七章:API集成与二次开发
7.1 Dify API概述
Dify提供完整的RESTful API,所有在界面上能做的操作都可以通过API完成。
API基础信息:
- 基础URL:
http://your-dify-host/v1 - 认证方式:Bearer Token
- 数据格式:JSON
7.2 对话型应用API
发送对话消息
curl -X POST 'http://your-dify-host/v1/chat-messages' \
-H 'Authorization: Bearer {api_key}' \
-H 'Content-Type: application/json' \
-d '{
"inputs": {},
"query": "我想查询我的订单状态",
"response_mode": "streaming",
"conversation_id": "",
"user": "user-123"
}'
Python SDK使用
import requests
import json
class DifyClient:
"""Dify API客户端"""
def __init__(self, api_key: str, base_url: str = "http://localhost/v1"):
self.api_key = api_key
self.base_url = base_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def chat(self, query: str, conversation_id: str = "", user: str = "default") -> dict:
"""发送对话消息"""
url = f"{self.base_url}/chat-messages"
data = {
"inputs": {},
"query": query,
"response_mode": "blocking",
"conversation_id": conversation_id,
"user": user
}
response = requests.post(url, headers=self.headers, json=data)
return response.json()
def chat_stream(self, query: str, conversation_id: str = "", user: str = "default"):
"""流式对话"""
url = f"{self.base_url}/chat-messages"
data = {
"inputs": {},
"query": query,
"response_mode": "streaming",
"conversation_id": conversation_id,
"user": user
}
response = requests.post(url, headers=self.headers, json=data, stream=True)
for line in response.iter_lines():
if line:
line = line.decode('utf-8')
if line.startswith('data: '):
event_data = json.loads(line[6:])
if event_data.get('event') == 'message':
yield event_data.get('answer', '')
def get_conversations(self, user: str = "default", limit: int = 20) -> dict:
"""获取对话列表"""
url = f"{self.base_url}/conversations"
params = {"user": user, "limit": limit}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
def get_messages(self, conversation_id: str, user: str = "default") -> dict:
"""获取对话消息"""
url = f"{self.base_url}/messages"
params = {"conversation_id": conversation_id, "user": user}
response = requests.get(url, headers=self.headers, params=params)
return response.json()
def upload_file(self, file_path: str, user: str = "default") -> dict:
"""上传文件"""
url = f"{self.base_url}/files/upload"
with open(file_path, 'rb') as f:
files = {'file': f}
data = {'user': user}
headers = {"Authorization": f"Bearer {self.api_key}"}
response = requests.post(url, headers=headers, files=files, data=data)
return response.json()
# 使用示例
client = DifyClient(api_key="app-your-api-key")
# 单轮对话
result = client.chat("你好,请问你们的营业时间是?")
print(result["answer"])
# 多轮对话
conv_id = ""
while True:
user_input = input("你: ")
if user_input.lower() in ['quit', 'exit']:
break
result = client.chat(user_input, conversation_id=conv_id)
conv_id = result.get("conversation_id", conv_id)
print(f"AI: {result['answer']}")
7.3 工作流API
执行工作流
class DifyWorkflowClient:
"""Dify工作流API客户端"""
def __init__(self, api_key: str, base_url: str = "http://localhost/v1"):
self.api_key = api_key
self.base_url = base_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def run_workflow(self, inputs: dict, user: str = "default",
response_mode: str = "blocking") -> dict:
"""执行工作流"""
url = f"{self.base_url}/workflows/run"
data = {
"inputs": inputs,
"response_mode": response_mode,
"user": user
}
response = requests.post(url, headers=self.headers, json=data)
return response.json()
def get_workflow_run(self, workflow_run_id: str) -> dict:
"""获取工作流运行状态"""
url = f"{self.base_url}/workflows/run/{workflow_run_id}"
response = requests.get(url, headers=self.headers)
return response.json()
# 使用示例
workflow_client = DifyWorkflowClient(api_key="app-your-workflow-api-key")
# 执行批量摘要工作流
result = workflow_client.run_workflow(
inputs={
"articles": [
{"title": "AI发展趋势", "content": "...", "url": "https://..."},
{"title": "LLM应用案例", "content": "...", "url": "https://..."}
],
"language": "中文",
"max_length": 200
}
)
print(result["data"]["outputs"]["final_output"])
7.4 知识库API
class DifyKnowledgeClient:
"""Dify知识库API客户端"""
def __init__(self, api_key: str, base_url: str = "http://localhost/v1"):
self.api_key = api_key
self.base_url = base_url
self.headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def create_dataset(self, name: str, description: str = "") -> dict:
"""创建知识库"""
url = f"{self.base_url}/datasets"
data = {"name": name, "description": description}
response = requests.post(url, headers=self.headers, json=data)
return response.json()
def upload_document(self, dataset_id: str, file_path: str,
indexing_technique: str = "high_quality") -> dict:
"""上传文档到知识库"""
url = f"{self.base_url}/datasets/{dataset_id}/document/create-by-file"
with open(file_path, 'rb') as f:
files = {'file': f}
data = {
'data': json.dumps({
"indexing_technique": indexing_technique,
"process_rule": {
"mode": "automatic"
}
}),
'type': 'text'
}
headers = {"Authorization": f"Bearer {self.api_key}"}
response = requests.post(url, headers=headers, files=files, data=data)
return response.json()
def search(self, dataset_id: str, query: str, top_k: int = 5) -> dict:
"""在知识库中搜索"""
url = f"{self.base_url}/datasets/{dataset_id}/retrieve"
data = {
"query": query,
"retrieval_model": {
"search_method": "hybrid_search",
"reranking_enable": True,
"top_k": top_k
}
}
response = requests.post(url, headers=self.headers, json=data)
return response.json()
第八章:插件开发与生态扩展
8.1 Dify插件系统概述
Dify的插件系统允许开发者扩展平台的功能。插件可以:
- 添加新的工具(Tool)
- 添加新的模型提供商(Model Provider)
- 添加新的数据源(Datasource)
8.2 插件开发基础
插件结构
my-plugin/
├── manifest.yaml # 插件清单
├── provider/
│ └── my_provider.yaml # 提供商定义
├── tools/
│ └── my_tool.yaml # 工具定义
└── src/
└── main.py # 插件代码
manifest.yaml示例
name: my-custom-plugin
version: 0.1.0
description: 自定义插件示例
author: Your Name
plugins:
tools:
- tools/my_tool.yaml
工具定义示例
# tools/my_tool.yaml
name: my_custom_tool
description: 自定义工具描述
parameters:
- name: input_text
type: string
required: true
description: 输入文本
- name: format
type: string
required: false
description: 输出格式
default: text
插件代码示例
# src/main.py
from typing import Any, Dict
class MyCustomTool:
"""自定义工具实现"""
def execute(self, input_text: str, format: str = "text") -> Dict[str, Any]:
"""执行工具逻辑"""
# 处理逻辑
result = self._process(input_text)
# 格式化输出
if format == "json":
return {"result": {"processed": result}}
else:
return {"result": result}
def _process(self, text: str) -> str:
"""实际处理逻辑"""
# 这里实现你的业务逻辑
return f"处理结果: {text}"
8.3 模型提供商插件
# provider/my_model_provider.yaml
name: my-model-provider
description: 自定义模型提供商
models:
- name: my-custom-model
model_type: llm
model_properties:
context_size: 8192
mode: chat
parameter_definitions:
temperature:
type: float
default: 0.7
min: 0
max: 2
max_tokens:
type: int
default: 2048
min: 1
max: 8192
8.4 插件发布与分享
开发完成后,可以通过以下方式分享插件:
- GitHub仓库:将插件代码发布到GitHub
- Dify插件市场:提交到官方插件市场(即将推出)
- 私有部署:在团队内部分享
第九章:实战项目——构建企业级智能客服系统
9.1 项目概述
我们将使用Dify构建一个完整的企业级智能客服系统,具备以下功能:
- 多轮对话:支持上下文记忆的多轮对话
- 意图识别:自动识别用户意图并路由到相应处理流程
- 知识库问答:基于企业知识库回答常见问题
- 订单查询:查询订单状态和详情
- 工单创建:自动创建客服工单
- 人工转接:无法处理时转接人工客服
9.2 系统架构
用户请求
│
▼
[入口Chatflow]
│
├─→ [意图识别节点]
│ │
│ ├─ "订单问题" → [订单处理Agent]
│ │ ├─ 查询订单
│ │ └─ 订单状态说明
│ │
│ ├─ "产品问题" → [知识库检索] → [产品回复LLM]
│ │
│ ├─ "退款问题" → [退款处理流程]
│ │ ├─ 退款政策说明
│ │ └─ 提交退款申请
│ │
│ ├─ "投诉" → [投诉处理流程]
│ │ ├─ 安抚话术
│ │ └─ 创建工单
│ │
│ └─ "其他" → [通用问答LLM]
│
└─→ [输出格式化] → [结束]
9.3 详细实现步骤
步骤1:创建知识库
首先,创建产品知识库,上传产品手册、FAQ等文档:
# 产品FAQ示例
## Q: 你们的产品有哪些?
A: 我们主要提供以下产品:
- 智能手表系列:X1、X2、X3
- 无线耳机系列:S1、S2
- 智能音箱系列:H1、H2
## Q: 产品保修政策是什么?
A: 所有产品享受1年质保服务。在保修期内,非人为损坏的产品可以免费维修或更换。
## Q: 如何联系客服?
A: 您可以通过以下方式联系我们:
- 在线客服:7×24小时
- 电话:400-xxx-xxxx(工作日9:00-18:00)
- 邮箱:support@example.com
## Q: 配送范围和时间?
A: 我们支持全国配送。
- 一般地区:3-5个工作日
- 偏远地区:5-7个工作日
- 支持顺丰、京东物流
步骤2:创建入口Chatflow
系统提示词:
# 角色
你是小智,一个专业、友好的客户服务代表。
# 职责
1. 识别用户意图
2. 根据意图提供相应的帮助
3. 保持友好、专业的语气
4. 记录重要信息
# 意图分类规则
请将用户的问题分类为以下类别之一:
- order: 订单相关(查询、修改、取消订单)
- product: 产品相关(功能、规格、使用方法)
- refund: 退款相关(退款流程、退款状态)
- complaint: 投诉(服务质量、产品质量)
- general: 其他问题
# 输出格式
请以JSON格式输出:
{"intent": "类别", "summary": "问题摘要", "key_info": "关键信息"}
# 注意事项
- 如果用户情绪激动,先安抚再处理
- 如果无法确定意图,归类为general
- 用中文回复
意图识别节点配置:
节点类型:LLM
模型:gpt-3.5-turbo(意图识别不需要太强的模型)
温度:0.1(保持稳定的分类结果)
提示词:{{intent_prompt}}
输出变量:intent_result
步骤3:条件分支路由
# 代码节点:解析意图
def main(intent_result: str) -> dict:
import json
try:
result = json.loads(intent_result)
intent = result.get("intent", "general")
except:
intent = "general"
return {
"intent": intent,
"summary": result.get("summary", ""),
"key_info": result.get("key_info", "")
}
条件分支配置:
条件1:{{intent}} == "order" → 订单处理分支
条件2:{{intent}} == "product" → 产品咨询分支
条件3:{{intent}} == "refund" → 退款处理分支
条件4:{{intent}} == "complaint" → 投诉处理分支
默认:→ 通用问答分支
步骤4:订单查询功能
创建订单查询Agent:
# 订单查询Agent系统提示词
你是一个订单查询助手。你的任务是帮助用户查询订单信息。
## 工作流程
1. 如果用户没有提供订单号,请友好地询问
2. 使用订单查询工具获取订单信息
3. 用清晰易懂的方式向用户说明订单状态
## 订单状态说明
- pending: 待支付
- paid: 已支付,待发货
- shipping: 运输中
- delivered: 已送达
- cancelled: 已取消
- refunded: 已退款
## 注意事项
- 保护用户隐私,不要透露完整手机号和地址
- 如果订单异常,建议用户联系人工客服
订单查询工具定义:
{
"openapi": "3.0.0",
"info": {"title": "订单系统API", "version": "1.0.0"},
"servers": [{"url": "https://api.example.com"}],
"paths": {
"/orders/{order_id}": {
"get": {
"summary": "查询订单详情",
"operationId": "getOrder",
"parameters": [{
"name": "order_id",
"in": "path",
"required": true,
"schema": {"type": "string"},
"description": "订单号"
}],
"responses": {
"200": {
"description": "订单信息",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"order_id": {"type": "string"},
"status": {"type": "string"},
"items": {"type": "array", "items": {"type": "object"}},
"total_amount": {"type": "number"},
"created_at": {"type": "string"},
"tracking_number": {"type": "string"}
}
}
}
}
}
}
}
}
}
}
步骤5:退款处理流程
# 退款处理节点提示词
根据用户的问题和订单信息,处理退款相关请求:
## 退款政策
1. 订单状态为"已支付"或"运输中"可以申请退款
2. 已送达的订单需要在7天内申请退款
3. 退款将在3-5个工作日内到账
## 处理规则
1. 先确认订单是否符合退款条件
2. 向用户说明退款政策
3. 如果用户确认退款,使用退款申请工具提交申请
4. 告知用户退款预计到账时间
## 订单信息
{{order_info}}
步骤6:投诉处理与工单创建
# 工单创建HTTP请求配置
POST https://api.example.com/tickets
Authorization: Bearer {{api_token}}
Content-Type: application/json
{
"customer_id": "{{user_id}}",
"type": "complaint",
"priority": "high",
"subject": "{{complaint_summary}}",
"description": "{{user_query}}",
"source": "ai_chatbot",
"metadata": {
"conversation_id": "{{conversation_id}}",
"detected_intent": "complaint"
}
}
投诉处理提示词:
# 投诉处理提示词
用户正在投诉。请按照以下流程处理:
## 处理步骤
1. **表达理解**:首先表示理解用户的感受
2. **收集信息**:了解具体问题和期望的解决方案
3. **记录投诉**:创建工单记录投诉内容
4. **承诺跟进**:告知用户会尽快处理
## 话术参考
- "非常抱歉给您带来了不好的体验..."
- "我完全理解您的心情..."
- "我会立即为您记录这个问题..."
- "我们的专业团队会在24小时内联系您..."
## 注意事项
- 不要推卸责任
- 不要承诺无法兑现的解决方案
- 保持冷静和专业
步骤7:对话记忆管理
在Chatflow中实现上下文记忆:
# 记忆管理节点
## 对话历史
{{#conversation_history#}}
## 用户信息
- 用户ID:{{user_id}}
- 会员等级:{{member_level}}
## 当前会话摘要
{{session_summary}}
## 指令
1. 参考对话历史,保持上下文连贯
2. 根据用户等级提供差异化服务
3. 如果用户之前提过的问题,不要重复询问
9.4 部署与上线
环境变量配置:
# .env
DIFY_API_KEY=app-your-api-key
DIFY_BASE_URL=https://your-dify-instance.com/v1
ORDER_API_KEY=your-order-api-key
TICKET_API_KEY=your-ticket-api-key
接入渠道集成:
# 接入微信公众号
from flask import Flask, request
import xml.etree.ElementTree as ET
app = Flask(__name__)
dify_client = DifyClient(api_key="your-api-key")
@app.route('/wechat', methods=['POST'])
def wechat():
xml_data = request.data
root = ET.fromstring(xml_data)
user_id = root.find('FromUserName').text
content = root.find('Content').text
# 调用Dify API
result = dify_client.chat(content, user=user_id)
reply = result.get('answer', '抱歉,暂时无法处理您的请求。')
# 返回微信消息格式
return f"""
<xml>
<ToUserName><![CDATA[{user_id}]]></ToUserName>
<FromUserName><![CDATA[gh_xxx]]></FromUserName>
<CreateTime>{int(time.time())}</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[{reply}]]></Content>
</xml>
"""
9.5 测试与优化
测试用例:
test_cases = [
{
"name": "订单查询",
"input": "我的订单 ORD-20240115-001 到哪了?",
"expected_intent": "order",
"should_contain": "物流"
},
{
"name": "退款申请",
"input": "我想退款,订单号是 ORD-20240110-002",
"expected_intent": "refund",
"should_contain": "退款"
},
{
"name": "产品咨询",
"input": "X3手表的电池能用多久?",
"expected_intent": "product",
"should_contain": "电池"
},
{
"name": "投诉",
"input": "你们的客服态度太差了,我要投诉!",
"expected_intent": "complaint",
"should_contain": "抱歉"
}
]
for test in test_cases:
result = dify_client.chat(test["input"])
print(f"测试: {test['name']}")
print(f" 输入: {test['input']}")
print(f" 输出: {result['answer'][:100]}...")
print(f" 通过: {test['should_contain'] in result['answer']}")
print()
性能优化建议:
模型选择优化
- 意图识别使用轻量模型(gpt-3.5-turbo)
- 复杂问答使用强力模型(gpt-4)
- 根据实际效果调整
知识库优化
- 定期更新知识库内容
- 优化分段策略提高检索精度
- 添加更多高质量的FAQ
缓存策略
- 对常见问题的回答进行缓存
- 缓存订单查询结果(短期)
监控指标
- 意图识别准确率
- 用户满意度评分
- 转人工率
- 平均响应时间
第十章:高级技巧与最佳实践
10.1 提示词工程
系统提示词模板:
# 角色定义
你是[角色名称],[角色描述]。
# 能力范围
1. [能力1]
2. [能力2]
3. [能力3]
# 行为规则
- [规则1]
- [规则2]
- [规则3]
# 输出格式
[定义期望的输出格式]
# 示例
用户: [示例输入]
助手: [示例输出]
10.2 工作流设计原则
- 单一职责:每个节点只做一件事
- 错误处理:每个关键节点都要有错误处理
- 日志记录:在关键节点记录日志
- 幂等设计:相同输入应产生相同输出
- 超时控制:为外部调用设置合理的超时时间
10.3 性能优化
# 并行执行多个知识库检索
from concurrent.futures import ThreadPoolExecutor
def search_multiple_knowledge_bases(query: str, kb_ids: list) -> list:
"""并行搜索多个知识库"""
with ThreadPoolExecutor(max_workers=3) as executor:
futures = [
executor.submit(search_knowledge_base, kb_id, query)
for kb_id in kb_ids
]
results = []
for future in futures:
results.extend(future.result())
# 去重和排序
results = deduplicate_results(results)
results.sort(key=lambda x: x["score"], reverse=True)
return results[:5] # 返回Top5
10.4 安全最佳实践
- 输入验证:对所有用户输入进行验证和清理
- 权限控制:不同用户组设置不同的访问权限
- API密钥管理:定期轮换API密钥
- 日志脱敏:敏感信息在日志中脱敏处理
- 速率限制:防止API被滥用
10.5 监控与告警
# 监控指标收集
class DifyMonitor:
"""Dify应用监控"""
def __init__(self):
self.metrics = {
"request_count": 0,
"error_count": 0,
"avg_response_time": 0,
"intent_distribution": {},
"satisfaction_rate": 0
}
def record_request(self, intent: str, response_time: float,
success: bool, satisfaction: float = None):
"""记录请求指标"""
self.metrics["request_count"] += 1
if not success:
self.metrics["error_count"] += 1
# 更新平均响应时间
n = self.metrics["request_count"]
self.metrics["avg_response_time"] = (
(self.metrics["avg_response_time"] * (n-1) + response_time) / n
)
# 更新意图分布
self.metrics["intent_distribution"][intent] = \
self.metrics["intent_distribution"].get(intent, 0) + 1
# 检查告警条件
self._check_alerts()
def _check_alerts(self):
"""检查是否需要告警"""
error_rate = self.metrics["error_count"] / self.metrics["request_count"]
if error_rate > 0.1: # 错误率超过10%
self._send_alert(f"警告:错误率过高 ({error_rate:.1%})")
if self.metrics["avg_response_time"] > 5: # 响应时间超过5秒
self._send_alert(f"警告:响应时间过长 ({self.metrics['avg_response_time']:.1f}秒)")
def _send_alert(self, message: str):
"""发送告警"""
print(f"🚨 告警: {message}")
# 实际实现中可以发送到钉钉、飞书等
总结
本教程系统性地讲解了Dify AI应用开发平台的核心功能和开发技巧:
- 平台架构:理解Dify的分层架构和核心概念
- 安装部署:Docker Compose部署和云服务使用
- Chatflow设计:可视化对话流编排和变量传递
- Workflow构建:复杂业务逻辑的自动化编排
- 知识库管理:文档分段、索引和检索优化
- Agent集成:工具配置和推理模式选择
- API集成:RESTful API和SDK的使用
- 插件开发:平台功能扩展
- 实战项目:企业级智能客服系统的完整实现
Dify极大地降低了AI应用的开发门槛,让开发者可以专注于业务逻辑,而不是底层技术细节。随着Dify生态的不断壮大,它将成为AI应用开发的重要平台。
建议读者在学习本教程后,选择一个具体的业务场景,动手构建一个完整的AI应用,在实践中加深理解。
本教程内容为原创撰写,如有疑问欢迎交流讨论。