Dify AI应用平台零基础入门教程

教程简介

零基础Dify AI应用平台入门教程,涵盖Dify简介与对比、快速开始(云端+本地Docker部署)、四种应用类型详解、知识库管理、Prompt工程、工作流编排、Agent模式开发、API集成、高级功能、部署与运维等核心技能,配有企业文档问答系统实战项目,适合AI开发者系统学习。

Dify AI 应用平台零基础入门教程

📘 本教程版本:基于 Dify v1.x 系列编写 🕐 预计学习时间:8-12 小时 🎯 适合人群:零基础开发者、AI 爱好者、产品经理、企业技术决策者


目录


第一章 Dify 简介

1.1 什么是 Dify

Dify 是一个开源的大语言模型(LLM)应用开发平台,致力于让每个人都能轻松构建和运营生成式 AI 原生应用。它的名字来源于 "Define" 和 "Simplify" 的组合,寓意"定义并简化 AI 应用开发"。

Dify 提供了从 Agent 构建到 AI workflow 编排、RAG 检索、模型管理等全方位能力,使开发者和非技术用户都能通过可视化界面快速搭建生产级的 AI 应用。与传统的 AI 开发方式相比,Dify 将原本需要数周甚至数月的开发周期压缩到数小时或数天。

Dify 的核心理念

Dify 的设计理念可以概括为以下几个方面:

  1. 可视化优先:所有操作都通过直观的图形界面完成,无需编写大量代码
  2. 模型无关:支持接入数十种主流大模型,包括 OpenAI、Anthropic、Google、百度文心、阿里通义等
  3. 生产就绪:内置 API 服务、监控、日志等企业级功能
  4. 开源开放:基于 Apache 2.0 协议开源,社区活跃

1.2 Dify 的核心功能

Dify 提供了一系列强大的核心功能模块:

1. 可视化 Prompt 编排

Dify 提供了直观的 Prompt 编辑器,支持变量绑定、上下文引用、模板管理等功能。用户可以通过拖拽和配置的方式,轻松设计复杂的提示词逻辑。编辑器支持实时预览,方便调试和优化。

2. 多模型支持

平台内置了对主流大语言模型的统一接入层,包括:

模型提供商 代表模型 特点
OpenAI GPT-4o、GPT-4、GPT-3.5-Turbo 综合能力最强
Anthropic Claude 3.5 Sonnet、Claude 3 Opus 长文本处理优秀
Google Gemini Pro、Gemini 1.5 Pro 多模态能力强
百度 文心一言 4.0 中文理解突出
阿里 通义千问 Max 性价比高
月之暗面 Kimi (Moonshot) 长上下文窗口
深度求索 DeepSeek V3 开源高性能
智谱 GLM-4 中文对话自然

3. RAG(检索增强生成)引擎

Dify 内置了完整的 RAG 管道,包括:

  • 文档导入与自动解析(支持 PDF、Word、Markdown、CSV 等格式)
  • 智能文本分段(自动/自定义分段策略)
  • 向量化索引构建(支持高质量和经济两种模式)
  • 多路召回与重排序
  • 引用溯源

4. Agent 智能体

支持构建具有自主推理和工具调用能力的 AI Agent,内置多种推理策略:

  • ReAct(推理-行动-观察循环)
  • Function Calling(函数调用)
  • 支持自定义工具扩展

5. 工作流编排

提供可视化的 DAG(有向无环图)工作流编辑器,支持:

  • LLM 节点、条件分支、代码执行、HTTP 请求等多种节点类型
  • 变量在节点间的传递与转换
  • 循环与错误处理机制
  • 工作流的导入与导出

6. 后端即服务(BaaS)

每个创建的应用都自动暴露标准的 RESTful API,支持:

  • 对话型 API(含会话管理)
  • 补全型 API
  • 流式输出(SSE)
  • 文件上传

1.3 Dify 与其他 AI 平台对比

在选择 AI 应用开发平台时,了解不同平台的特点至关重要。以下是 Dify 与两个主流竞品的详细对比:

Dify vs Coze(扣子)

对比维度 Dify Coze(扣子)
开源性 完全开源(Apache 2.0) 闭源
部署方式 支持本地/私有化部署 仅云端
模型选择 支持数十种模型自由切换 主要依赖字节系模型
数据隐私 数据可完全私有化 数据存储在字节服务器
工作流 功能强大,节点类型丰富 工作流能力较新,仍在完善
生态系统 开源社区活跃,插件丰富 依托字节跳动生态
适用场景 企业级应用、私有化部署 个人用户、轻量级应用
学习曲线 中等,文档齐全 较低,上手快
定价 开源免费,云版按用量 免费额度 + 付费

总结:如果你需要数据隐私、私有化部署或灵活的模型选择,Dify 是更好的选择。如果你是个人用户,想要快速搭建简单的聊天机器人且不介意数据存储在第三方,Coze 也是一个不错的选项。

Dify vs FastGPT

对比维度 Dify FastGPT
开源性 完全开源 开源(部分高级功能闭源)
核心优势 全栈 AI 应用开发平台 专注知识库问答
RAG 能力 完善,支持多种索引策略 非常强,知识库管理更精细
工作流 强大,节点类型多样 支持,但相对简单
Agent 内置多种推理策略 支持,但功能较基础
模型支持 广泛 广泛
社区规模 更大(GitHub 60k+ Stars) 较大(GitHub 20k+ Stars)
适用场景 通用 AI 应用开发 知识库问答为主
企业级功能 完善 基础

总结:如果你的核心需求是知识库问答,FastGPT 在这方面有独到的优势。如果你需要构建多样化的 AI 应用(Agent、工作流、文本生成等),Dify 的功能更全面。

1.4 Dify 的适用场景

Dify 适用于以下典型场景:

1. 企业知识库问答

  • 内部文档搜索与问答
  • 客户服务智能助手
  • 产品手册查询系统

2. 内容创作与处理

  • 文案生成、翻译、摘要
  • SEO 内容批量生产
  • 报告自动生成

3. 智能客服

  • 多轮对话管理
  • 工单自动分类与路由
  • 常见问题自动应答

4. 数据分析助手

  • 自然语言查询数据库
  • 数据可视化描述生成
  • 业务指标分析解读

5. 工作流自动化

  • 文档审核流程
  • 邮件自动分类与回复
  • 多步骤业务流程编排

6. AI Agent 应用

  • 自动化研究助手
  • 多工具协调的任务执行
  • 信息聚合与分析

1.5 Dify 的技术架构概览

Dify 采用前后端分离的架构设计:

┌─────────────────────────────────────────────┐
│                  前端 (Next.js)               │
│   可视化编辑器 / 应用管理 / 数据分析面板         │
├─────────────────────────────────────────────┤
│                  API 网关层                    │
│   认证 / 限流 / 路由 / 日志                    │
├─────────────────────────────────────────────┤
│               核心服务层 (Python/Flask)         │
│   应用编排 / RAG 引擎 / Agent / 模型调度        │
├─────────────────────────────────────────────┤
│               基础设施层                       │
│   PostgreSQL / Redis / Weaviate / Qdrant     │
│   Celery (异步任务) / Nginx (反向代理)         │
└─────────────────────────────────────────────┘

核心技术栈

  • 后端:Python 3.10+、Flask、Celery、SQLAlchemy
  • 前端:Next.js 14、React 18、TailwindCSS
  • 数据库:PostgreSQL(主数据库)、Redis(缓存与消息队列)
  • 向量数据库:Weaviate(默认)、Qdrant、Milvus、Pgvector 等
  • 搜索引擎:Elasticsearch(可选)

第二章 快速开始

2.1 云端注册与使用

对于零基础用户,最简单的方式是使用 Dify 的云端服务。

步骤一:访问 Dify 官网

打开浏览器,访问 Dify 官方网站 https://dify.ai。在首页可以了解 Dify 的主要功能和特性。点击页面右上角的"开始使用"或"Get Started"按钮。

步骤二:注册账号

Dify 云端支持以下注册方式:

  • 邮箱注册:输入邮箱地址,设置密码,完成邮箱验证
  • GitHub 登录:使用 GitHub 账号快速注册
  • Google 登录:使用 Google 账号快速注册

推荐使用 GitHub 登录,方便后续关联代码仓库。

步骤三:创建首个应用

注册完成后,系统会自动跳转到控制台首页。你会看到一个简洁的仪表板,展示当前的应用列表和使用统计。点击"创建应用"按钮,选择应用类型(如聊天助手),输入应用名称和描述,即可开始配置。

步骤四:配置模型

首次使用需要配置模型供应商的 API Key:

  1. 进入"设置" → "模型供应商"
  2. 选择你要使用的模型提供商(如 OpenAI)
  3. 输入 API Key
  4. 点击"保存"并验证连通性

提示:云端版本提供了免费的试用额度,无需立即配置自己的 API Key 即可体验基础功能。

2.2 本地部署(Docker Compose)

对于需要数据隐私或自定义配置的用户,推荐使用 Docker Compose 进行本地部署。

2.2.1 环境要求

在开始部署之前,请确保你的机器满足以下最低配置要求:

资源 最低要求 推荐配置
CPU 2 核 4 核及以上
内存 4 GB 8 GB 及以上
磁盘 20 GB 50 GB SSD
操作系统 Linux (Ubuntu 20.04+) Ubuntu 22.04 LTS
Docker 20.10+ 最新稳定版
Docker Compose 2.0+ 最新稳定版

2.2.2 安装 Docker 和 Docker Compose

如果你的机器还没有安装 Docker,可以按照以下步骤安装:

Ubuntu/Debian 系统:

# 更新包索引
sudo apt-get update

# 安装必要的系统工具
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common

# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 添加 Docker 软件源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 将当前用户添加到 docker 组(避免每次使用 sudo)
sudo usermod -aG docker $USER

# 验证安装
docker --version
docker compose version

macOS 系统:

推荐直接下载安装 Docker Desktop for Mac,它包含了 Docker Engine 和 Docker Compose。访问 Docker 官网下载对应芯片(Intel/Apple Silicon)的安装包。

2.2.3 克隆 Dify 仓库

# 克隆 Dify 代码仓库
git clone https://github.com/langgenius/dify.git

# 进入 Docker 部署目录
cd dify/docker

2.2.4 配置环境变量

# 复制环境变量模板文件
cp .env.example .env

使用你喜欢的编辑器打开 .env 文件,修改以下关键配置:

# 应用密钥(用于加密,请修改为随机字符串)
SECRET_KEY=your-random-secret-key-here

# 数据库密码
POSTGRES_PASSWORD=your-database-password

# Redis 密码
REDIS_PASSWORD=your-redis-password

# 应用访问端口
EXPOSE_NGINX_PORT=80
EXPOSE_NGINX_SSL_PORT=443

# 向量数据库类型(默认使用 weaviate)
VECTOR_STORE=weaviate

# 存储类型(local 表示本地文件存储)
STORAGE_TYPE=local

安全提示SECRET_KEY 和数据库密码必须修改为强随机字符串,不能使用默认值。可以使用 openssl rand -base64 42 命令生成随机密钥。

2.2.5 启动服务

# 拉取最新镜像并启动所有服务
docker compose up -d

首次启动需要下载镜像,根据网络情况可能需要 5-15 分钟。启动过程中可以使用以下命令查看日志:

# 查看所有服务的运行状态
docker compose ps

# 查看实时日志
docker compose logs -f

# 查看特定服务的日志
docker compose logs -f api
docker compose logs -f web

正常启动后,你应该看到类似以下的输出:

NAME                STATUS          PORTS
dify-api            Up (healthy)    0.0.0.0:5001->5001/tcp
dify-web            Up (healthy)    0.0.0.0:3000->3000/tcp
dify-worker         Up (healthy)
dify-db             Up (healthy)    0.0.0.0:5432->5432/tcp
dify-redis          Up (healthy)    0.0.0.0:6379->6379/tcp
dify-weaviate       Up (healthy)    0.0.0.0:8080->8080/tcp
dify-nginx          Up (healthy)    0.0.0.0:80->80/tcp

2.2.6 访问 Dify 控制台

打开浏览器,访问 http://localhost(如果修改了端口,使用 http://localhost:你设置的端口)。

首次访问会跳转到初始化页面:

  1. 设置管理员邮箱和密码
  2. 填写基本的站点信息
  3. 点击"初始化"完成安装

初始化完成后即可登录控制台开始使用。

2.2.7 常见部署问题排查

问题1:端口被占用

# 查看占用 80 端口的进程
sudo lsof -i :80

# 解决方案:修改 .env 中的 EXPOSE_NGINX_PORT 为其他端口
# 例如:EXPOSE_NGINX_PORT=8080

问题2:内存不足导致服务启动失败

# 检查可用内存
free -h

# 解决方案:增加 swap 空间
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

问题3:向量数据库连接失败

# 检查 Weaviate 服务状态
docker compose logs weaviate

# 如果持续失败,可以切换到 pgvector(使用内置 PostgreSQL)
# 修改 .env:VECTOR_STORE=pgvector

2.3 界面导览

登录 Dify 控制台后,你会看到一个功能丰富的管理界面。以下是主要区域的介绍:

2.3.1 顶部导航栏

顶部导航栏包含以下元素:

  • Logo 与名称:左上角显示 Dify 的 Logo 和当前工作空间名称
  • 工作空间切换:如果你属于多个工作空间,可以在此切换
  • 通知中心:显示系统通知和告警信息
  • 用户菜单:个人设置、API 密钥管理、团队管理、退出登录

2.3.2 左侧导航面板

左侧导航面板是主要的功能入口:

  • 🏠 首页(仪表板):展示应用统计、最近活动、快速入门指引
  • 📦 应用:应用列表,包含创建、编辑、删除等管理操作
  • 📚 知识库:知识库管理,包含文档上传、分段管理、检索测试
  • 🔧 工具:内置工具和自定义工具的管理
  • ⚙️ 设置:模型配置、成员管理、系统设置

2.3.3 应用编辑器

当你打开一个应用时,会进入应用编辑器界面。这是 Dify 最核心的操作界面:

左侧面板

  • Prompt 编排区域
  • 变量配置
  • 上下文引用设置
  • 对话开场白配置

中间区域

  • 编辑器主体(根据应用类型不同而变化)
  • 聊天测试面板(可以在此实时测试应用效果)

右侧面板

  • 模型选择与参数调节
  • 功能开关(如引用标记、内容审核等)
  • 发布设置

2.3.4 知识库界面

知识库界面分为以下几个部分:

  • 文档列表:显示已上传的文档,支持搜索和筛选
  • 分段预览:查看文档被自动分段后的结果
  • 检索测试:输入测试查询,查看检索效果
  • 设置面板:配置索引方式、分段策略等参数

2.3.5 工作流编辑器

工作流编辑器是一个可视化的画布区域:

  • 节点面板:左侧展示可拖拽的节点类型
  • 画布区域:中间的可视化编辑区域,支持缩放和拖拽
  • 节点配置:右侧展示选中节点的详细配置
  • 调试面板:底部展示运行日志和变量状态

2.4 快速创建第一个应用

让我们通过一个简单的例子来快速体验 Dify 的功能。

目标:创建一个 "英语学习助手" 聊天应用

第一步:创建应用

  1. 在控制台首页,点击"创建应用"
  2. 选择"聊天助手"类型
  3. 输入应用名称:英语学习助手
  4. 输入应用描述:帮助用户学习英语,纠正语法错误,提供例句和翻译
  5. 点击"创建"

第二步:编写 Prompt

在 Prompt 编辑区域,输入以下提示词:

你是一位专业的英语学习助手,具有以下能力:

1. **语法纠错**:当用户输入英语句子时,指出语法错误并给出正确写法
2. **词汇解释**:解释用户不理解的英语单词或短语,包含词性、释义和例句
3. **口语练习**:与用户进行英语对话练习,适时纠正表达
4. **翻译辅助**:帮助用户进行中英文互译,注意语境和地道表达

请始终使用简洁清晰的语言回复。在给出英语内容时,同时提供中文解释。
如果用户的英语有错误,先肯定正确的部分,再指出需要改进的地方。

第三步:选择模型

在右侧面板中:

  1. 选择模型提供商(如 OpenAI)
  2. 选择模型(如 GPT-4o)
  3. 保持默认参数或根据需要调整 Temperature(建议设置为 0.7)

第四步:测试应用

在右侧的预览面板中,输入测试内容:

I goes to school yesterday and goed to the library.

观察 AI 的回复是否正确识别了语法错误(went 而非 goed,go 而非 goes),并给出了详细的解释。

第五步:发布应用

确认效果满意后:

  1. 点击右上角的"发布"按钮
  2. 选择发布渠道(Web 应用 / API)
  3. 获取访问链接或 API 密钥

恭喜!你已经成功创建了第一个 Dify 应用。


第三章 应用类型详解

Dify 支持四种主要的应用类型,每种类型都有其独特的特点和适用场景。理解这些类型的区别,是高效使用 Dify 的基础。

3.1 聊天助手(Chat)

特点

聊天助手是 Dify 中最常用的应用类型,具有以下特点:

  • 多轮对话:支持上下文连续的多轮对话,AI 能够记住之前的对话内容
  • 对话记忆:可配置对话窗口大小(即 AI 能记住多少轮之前的对话)
  • 交互式界面:提供友好的聊天界面,支持 Markdown 渲染、代码高亮等
  • 开场白:可以设置对话开始时 AI 的主动发言内容
  • 建议问题:在对话过程中可以显示建议的后续问题

配置要点

在聊天助手的配置中,以下几个参数特别重要:

1. 对话窗口大小(Dialogue Turns)

这个参数决定了 AI 能"记住"多少轮历史对话。设置范围通常为 5-100 轮。

  • 设置过小:AI 会"失忆",忘记之前的对话内容
  • 设置过大:会消耗更多的 Token,增加成本和响应时间

建议值

  • 简单问答场景:5-10 轮
  • 复杂咨询场景:20-30 轮
  • 深度对话场景:50 轮以上

2. 对话开场白(Opening Statement)

开场白是 AI 在对话开始时主动发送的第一条消息,可以引导用户正确使用应用。

示例

👋 你好!我是你的英语学习助手。

我可以帮你:
• 🔍 纠正英语语法错误
• 📖 解释英语单词和短语
• 💬 进行英语口语练习
• 🌐 中英文翻译

请输入任何你想学习的英语内容,或者直接用英语和我聊天!

3. 建议问题(Suggested Questions)

在开场白之后显示的建议问题按钮,帮助用户快速开始对话。

示例设置:

  • "帮我检查一段英语作文"
  • "Explain the difference between 'affect' and 'effect'"
  • "我们来练习英语对话吧"

适用场景

  • 客户服务机器人
  • 教育辅导助手
  • 咨询顾问系统
  • 日常问答助手
  • 语言学习伙伴

3.2 文本生成(Completion)

特点

文本生成类型适用于单次输入、单次输出的场景:

  • 单轮交互:每次调用独立,不保留对话历史
  • 模板化输入:通过变量模板接收用户输入
  • 结构化输出:适合生成格式化的内容
  • 批量处理:易于进行批量文本处理

与聊天助手的区别

特性 聊天助手 文本生成
对话模式 多轮对话 单轮输入输出
上下文 保留历史 每次独立
输入方式 自由文本 变量模板
输出界面 聊天气泡 文本展示区
适用场景 对话交互 内容生成

变量模板示例

文本生成类型支持使用 {{变量名}} 来定义输入模板:

请将以下 {{source_language}} 文本翻译为 {{target_language}}:

原文:
{{text}}

翻译要求:
- 保持原文的语气和风格
- 使用地道的表达方式
- 如有专业术语,请在翻译后附上解释

用户在使用时,会看到对应的输入框,分别填写源语言、目标语言和要翻译的文本。

适用场景

  • 文案生成(广告、营销文案)
  • 文本翻译
  • 内容摘要
  • 数据格式转换
  • 代码生成
  • 批量文本处理

3.3 Agent(智能体)

特点

Agent 是 Dify 中最智能的应用类型,具有自主推理和工具使用能力:

  • 自主推理:AI 能够分析问题并制定解决方案
  • 工具调用:可以调用各种外部工具(搜索引擎、计算器、API 等)
  • 多步执行:能够自动分解复杂任务为多个步骤依次执行
  • 自我纠错:当工具调用失败时,能够调整策略重试

推理策略

Dify 提供两种主要的 Agent 推理策略:

1. ReAct 策略(推理-行动-观察)

ReAct 是一种经典的 Agent 推理模式,其执行循环如下:

思考(Thought)→ 行动(Action)→ 观察(Observation)→ 思考 → ...

示例流程:

用户问题:"今天北京的天气怎么样?适合户外运动吗?"

思考:用户想知道北京今天的天气,并询问是否适合户外运动。
      我需要先查询北京今天的天气信息。

行动:调用天气查询工具,查询北京天气

观察:北京今天晴,气温 28°C,空气质量良好,风力 2 级

思考:根据天气信息,今天北京天气不错,温度适中,适合户外运动。
      但需要注意防晒。

回答:北京今天天气晴朗,气温 28°C,空气质量良好,风力 2 级。
      非常适合户外运动!建议做好防晒措施,多补充水分。

2. Function Calling 策略

Function Calling 是 OpenAI 等模型提供商原生支持的工具调用方式:

  • 模型直接输出结构化的函数调用请求
  • 平台执行函数并返回结果
  • 模型基于结果生成最终回答

相比 ReAct,Function Calling 的优势在于:

  • 调用更精准,减少幻觉
  • 响应速度更快
  • 支持并行调用多个工具

内置工具

Dify 提供了丰富的内置工具:

工具名称 功能 来源
网页抓取 读取指定网页内容 内置
维基百科 搜索维基百科 内置
数学计算 执行数学表达式计算 内置
代码执行器 运行 Python 代码 内置
搜索引擎 联网搜索 需配置
DALL-E AI 图片生成 需配置 API
Stable Diffusion AI 图片生成 需配置
天气查询 查询天气信息 需配置 API

适用场景

  • 智能研究助手(搜索 + 分析 + 总结)
  • 数据查询与分析
  • 自动化任务执行
  • 多步骤问题求解
  • 信息聚合与报告生成

3.4 工作流(Workflow)

特点

工作流是 Dify 中最灵活的应用类型,适合构建复杂的自动化流程:

  • 可视化编排:拖拽式节点编辑器
  • DAG 架构:有向无环图结构,支持分支和并行
  • 变量系统:支持在节点间传递和转换数据
  • 两种子类型:工作流和对话流

工作流 vs 对话流

特性 工作流(Workflow) 对话流(Chatflow)
交互模式 单次运行 多轮对话
输入 一次性输入 持续交互
输出 一次性结果 多轮回复
适用场景 数据处理、报告生成 智能客服、引导式对话

节点类型总览

工作流支持以下主要节点类型:

  1. 开始节点:定义输入变量
  2. LLM 节点:调用大语言模型
  3. 知识库检索节点:从知识库中检索信息
  4. 条件分支节点:根据条件进行路由
  5. 代码执行节点:运行自定义 Python/JavaScript 代码
  6. HTTP 请求节点:调用外部 API
  7. 变量聚合节点:合并多路变量
  8. 模板转换节点:Jinja2 模板渲染
  9. 迭代节点:循环处理列表数据
  10. 参数提取节点:从文本中提取结构化参数
  11. 结束节点:定义输出结果

适用场景

  • 复杂的多步骤业务流程
  • 数据处理与转换管道
  • 条件化的内容生成
  • API 编排与集成
  • 自动化报告生成
  • 多模型协作流程

3.5 如何选择合适的应用类型

面对四种应用类型,可以参考以下决策流程:

你需要多轮对话吗?
├── 是 → 你需要使用外部工具吗?
│        ├── 是 → 选择 Agent
│        └── 否 → 选择 聊天助手
└── 否 → 你需要复杂的工作流程吗?
         ├── 是 → 选择 工作流
         └── 否 → 选择 文本生成

简单决策规则

  • 只是想和 AI 对话?→ 聊天助手
  • 需要 AI 搜索网页、计算数据?→ Agent
  • 需要批量生成内容、格式化处理?→ 文本生成
  • 需要多步骤、有条件分支的复杂流程?→ 工作流

第四章 知识库管理

4.1 知识库概述

知识库是 Dify 中 RAG(检索增强生成)功能的核心组件。它允许你将私有文档导入 Dify,在用户提问时自动检索相关文档片段,将其作为上下文提供给大模型,从而使 AI 能够基于你的专属知识回答问题。

知识库的工作原理

用户提问 → 文本向量化 → 向量相似度搜索 → 检索相关文档片段
                                    ↓
                              LLM 基于检索结果生成回答

核心流程分为三个阶段:

  1. 索引阶段(离线):文档导入 → 文本分段 → 向量化 → 存储到向量数据库
  2. 检索阶段(在线):用户提问 → 问题向量化 → 相似度搜索 → 返回 Top-K 结果
  3. 生成阶段(在线):将检索结果作为上下文,连同用户问题一起发送给 LLM 生成回答

4.2 创建知识库

步骤一:新建知识库

  1. 在左侧导航栏中点击"知识库"
  2. 点击"创建知识库"按钮
  3. 输入知识库名称(例如:产品文档
  4. 输入知识库描述(例如:包含所有产品的使用手册和 FAQ
  5. 点击"创建"

步骤二:上传文档

Dify 支持以下文档格式:

格式 扩展名 说明
文本文件 .txt, .markdown, .md 纯文本,最易处理
PDF .pdf 自动提取文本内容
Word .docx, .doc 自动提取文本内容
Excel .xlsx, .xls 按行/列解析
CSV .csv 按行列解析
HTML .html, .htm 提取正文内容
JSON .json 按结构解析
代码文件 .py, .js, .java 等 保留代码格式

上传步骤:

  1. 在知识库页面中,点击"添加文档"
  2. 选择"上传文件"或"从网页导入"
  3. 拖拽文件到上传区域,或点击选择文件
  4. 等待文件上传完成(支持批量上传)

文件大小限制:单个文件建议不超过 15MB,单次上传总大小不超过 50MB。如果文件过大,建议先进行拆分。

步骤三:配置分段策略

上传文件后,需要配置文本分段策略。这一步对检索效果至关重要。

4.3 文本分段策略

文本分段是将长文档切分为适合检索的小段落的过程。合理的分段策略能显著提升检索效果。

自动分段(推荐新手使用)

Dify 提供了智能自动分段功能,会根据文档结构自动选择最佳的分段方式:

  • 分段标识符:默认使用 \n\n(双换行符)作为段落分隔
  • 最大分段长度:默认 500 tokens
  • 分段重叠:默认 50 tokens

自定义分段

对于需要更精细控制的场景,可以自定义分段参数:

分段标识符(Chunk Separator)

常用的分段标识符:

  • \n\n:按段落分隔(最常用)
  • \n:按行分隔
  • :按句号分隔(中文文档)
  • .:按句号分隔(英文文档)
  • ##:按二级标题分隔(Markdown 文档)
  • ###:按三级标题分隔

可以组合使用,如 \n\n## 表示优先按二级标题分隔,其次按段落分隔。

最大分段长度(Max Tokens)

每个分段包含的最大 Token 数量:

  • 过小(<200):语义不完整,影响检索质量
  • 适中(300-800):大多数场景的最佳范围
  • 过大(>1000):包含过多噪音信息,降低精确度

建议设置: | 文档类型 | 建议分段长度 | 原因 | |---------|------------|------| | FAQ 文档 | 200-400 | 一问一答通常较短 | | 技术文档 | 400-600 | 需要包含足够的技术细节 | | 长篇文章 | 500-800 | 需要足够的上下文 | | 代码文档 | 300-500 | 代码块不宜过长 |

分段重叠(Chunk Overlap)

相邻分段之间的重叠 Token 数。重叠可以避免重要信息被切断在两个分段之间。

  • 建议设置为分段长度的 10%-20%
  • 例如:分段长度 500 → 重叠 50-100

分段预览与调整

配置完成后,Dify 会展示分段预览。你应该仔细检查:

  1. 每个分段是否语义完整
  2. 重要信息是否被切断
  3. 分段长度是否合理
  4. 是否有过多的空白或噪音内容

如果发现分段效果不理想,可以返回调整参数后重新分段。

4.4 索引方式

分段完成后,需要选择索引方式将文本转换为向量表示。Dify 提供两种索引模式:

高质量模式(High Quality)

  • 原理:使用 Embedding 模型将文本转换为高维向量
  • 特点
    • 语义理解能力强,支持同义词匹配
    • 检索精度高
    • 需要调用 Embedding 模型 API
    • 索引时间较长
    • 会消耗模型 Token 额度
  • 推荐场景:对检索质量要求高的正式应用

配置步骤:

  1. 选择"高质量"索引模式
  2. 选择 Embedding 模型(如 text-embedding-3-small、text-embedding-ada-002 等)
  3. 点击"开始索引"

经济模式(Economical)

  • 原理:使用关键词匹配(基于 TF-IDF 或 BM25 算法)
  • 特点
    • 不需要调用 Embedding 模型
    • 索引速度快
    • 不消耗模型 Token
    • 不支持语义理解,只支持关键词匹配
  • 推荐场景:预算有限、文档量大、对语义理解要求不高的场景

索引方式选择建议

场景 推荐模式 理由
正式产品应用 高质量 检索效果更好
快速原型验证 经济 成本低、速度快
技术文档查询 高质量 术语匹配需要语义理解
FAQ 常见问题 经济/高质量 关键词匹配已足够
大量文档(1000+) 经济 节省成本

4.5 检索测试

索引完成后,务必进行检索测试以验证效果。

测试步骤

  1. 在知识库页面中,点击"检索测试"
  2. 在输入框中输入测试问题
  3. 查看返回的文档片段和相似度分数

评估检索质量

好的检索结果应该满足:

  1. 相关性:返回的文档片段与问题高度相关
  2. 完整性:包含回答问题所需的完整信息
  3. 排序合理:最相关的排在最前面
  4. 数量适中:通常 Top 3-5 个结果足够

检索测试示例

假设你的知识库包含产品使用手册,测试如下:

测试问题:如何重置密码?

期望结果:返回的文档片段应该包含密码重置的具体步骤

如果结果不理想:
- 如果返回了不相关的内容 → 检查分段是否合理,考虑重新分段
- 如果没有返回相关内容 → 检查文档是否成功索引
- 如果相关内容排名靠后 → 考虑切换到高质量索引模式

4.6 知识库优化技巧

1. 文档预处理

上传前对文档进行预处理,可以显著提升效果:

  • 去除噪音:删除页眉页脚、页码、水印等无关内容
  • 统一格式:确保文档结构清晰,标题层级明确
  • 补充上下文:在段落前添加适当的标题或摘要

2. 分层索引

对于大型文档库,可以建立多层索引结构:

  • 父文档:包含完整的章节内容
  • 子文档:章节下的细分段落

这种方法被称为"Parent-Child Chunking",检索时先命中子文档,然后返回父文档的完整上下文。

3. 元数据标注

为文档添加元数据标签,可以提高检索的精确度:

文档类型:FAQ
产品名称:产品A
更新日期:2024-01-15
分类:账户管理

在检索时可以使用元数据进行过滤,缩小搜索范围。

4. 混合检索

Dify 支持同时使用向量检索和关键词检索,然后融合结果:

  • 向量检索:擅长语义匹配
  • 关键词检索:擅长精确匹配
  • 混合模式:结合两者优势

5. 定期更新

知识库需要定期维护和更新:

  • 及时上传最新的文档版本
  • 删除过时的文档
  • 重新索引修改过的文档
  • 定期进行检索测试,确保效果

4.7 在应用中使用知识库

创建好知识库后,需要将其关联到应用中:

  1. 打开应用编辑页面
  2. 在"上下文"区域,点击"添加"
  3. 选择要关联的知识库
  4. 配置检索参数:
    • Top-K:返回最相关的 K 个分段(建议 3-5)
    • Score 阈值:只返回相似度高于此阈值的结果(建议 0.5-0.7)
  5. 保存配置

在 Prompt 中引用知识库的上下文:

请根据以下参考资料回答用户的问题。如果参考资料中没有相关信息,请如实告知用户。

参考资料:
{{#context#}}

用户问题:
{{#question#}}

{{#context#}} 变量会自动填充检索到的文档片段。


第五章 Prompt 工程在 Dify 中的应用

5.1 Prompt 工程基础

Prompt 工程是与大语言模型交互的核心技术。一个好的 Prompt 能够显著提升 AI 的输出质量。在 Dify 中,Prompt 的设计尤为重要,因为它直接决定了你的应用表现。

Prompt 的基本结构

一个完整的 Prompt 通常包含以下要素:

1. 角色设定(System Role)
   └─ 定义 AI 的身份、能力范围和行为准则

2. 任务描述(Task Description)
   └─ 明确说明 AI 需要完成的任务

3. 输入格式(Input Format)
   └─ 定义用户输入的预期格式

4. 输出格式(Output Format)
   └─ 定义 AI 输出的期望格式

5. 约束条件(Constraints)
   └─ 设定 AI 行为的限制和边界

6. 示例(Examples)
   └─ 提供输入输出的参考示例

Dify 中的 Prompt 编辑器

Dify 提供了一个功能丰富的 Prompt 编辑器:

界面布局

  • 系统提示词区域:编写 System Prompt,定义 AI 的角色和行为
  • 变量列表:显示当前定义的所有变量
  • 预览面板:实时查看组装后的完整 Prompt
  • 测试面板:输入测试内容查看效果

5.2 变量绑定

变量是 Dify Prompt 系统的核心特性,允许你创建动态的、可复用的 Prompt 模板。

变量类型

Dify 支持以下变量类型:

变量类型 说明 使用场景
文本(Text) 单行文本输入 简短的问题、名称等
段落(Paragraph) 多行文本输入 长文本、文档内容等
下拉选择(Select) 预设选项列表 选择输出风格、语言等
数字(Number) 数字输入 设置数量、长度等

变量定义与使用

步骤一:定义变量

在应用编辑页面,找到"变量"配置区域:

  1. 点击"添加变量"
  2. 设置变量名称(如 user_name
  3. 选择变量类型(如 Text)
  4. 设置是否必填
  5. 填写默认值(可选)
  6. 添加变量描述/标签

步骤二:在 Prompt 中引用变量

使用双花括号 {{变量名}} 来引用变量:

你好,{{user_name}}!

我将用{{language}}为你解释以下概念:

概念:{{concept}}

请用简洁易懂的语言解释,适合{{level}}水平的学习者理解。

步骤三:测试变量

在预览面板中,你会看到变量被替换为输入框。填写不同的值来测试 Prompt 的效果。

变量的高级用法

1. 条件逻辑

在某些场景下,可以根据变量值调整 Prompt 内容。虽然 Dify 的标准 Prompt 编辑器不直接支持条件语法,但你可以通过巧妙的 Prompt 设计来实现:

请根据用户选择的输出格式生成内容:
- 如果格式为"详细":请提供全面深入的解释,包含多个示例
- 如果格式为"简洁":请用 2-3 句话概括核心要点
- 如果格式为"列表":请使用编号列表的形式组织回答

用户选择的格式:{{output_format}}

2. 变量组合

多个变量可以组合使用来构建复杂的 Prompt:

为{{target_audience}}写一篇关于{{topic}}的{{content_type}}。

要求:
- 字数:{{word_count}}字左右
- 语气:{{tone}}
- 语言:{{language}}
- 包含关键词:{{keywords}}

5.3 上下文引用

上下文引用允许你将知识库检索结果、对话历史等信息注入到 Prompt 中。

知识库上下文

当应用关联了知识库后,可以使用 {{#context#}} 变量引用检索结果:

你是一个专业的技术支持助手。请根据以下技术文档回答用户的问题。

重要规则:
1. 只基于提供的文档内容回答,不要编造信息
2. 如果文档中没有相关信息,明确告知用户
3. 回答时引用相关的文档来源

技术文档:
{{#context#}}

用户问题:{{query}}

对话历史

在聊天助手类型的应用中,对话历史会自动注入。你可以在 System Prompt 中引导 AI 如何利用历史对话:

你是一个智能客服助手。请注意以下事项:

1. 仔细阅读对话历史,了解用户之前的问题和已经提供的信息
2. 如果用户引用了之前的对话内容,请正确理解上下文
3. 如果发现用户的需求发生了变化,主动确认
4. 避免重复提供已经说过的信息

5.4 提示词模板

Dify 提供了内置的提示词模板库,帮助用户快速构建高质量的 Prompt。

使用内置模板

  1. 在 Prompt 编辑器中,点击"模板"按钮
  2. 浏览模板分类(对话、内容生成、数据分析等)
  3. 选择合适的模板
  4. 根据需要进行修改和调整

创建自定义模板

你也可以将自己编写的优质 Prompt 保存为模板:

  1. 完成 Prompt 编写和测试
  2. 点击"保存为模板"
  3. 填写模板名称、描述、分类
  4. 模板会保存到你的个人模板库

常用 Prompt 模式

1. CO-STAR 框架

C - Context(背景):提供任务的背景信息
O - Objective(目标):明确 AI 需要达成的目标
S - Style(风格):指定输出的写作风格
T - Tone(语气):设定输出的情感基调
A - Audience(受众):说明目标读者群体
R - Response(格式):定义输出的格式要求

2. 链式思考(Chain of Thought)

引导 AI 逐步推理:

请按照以下步骤分析这个问题:

1. 首先,理解问题的核心需求
2. 然后,列出相关的已知信息
3. 接着,分析可能的解决方案
4. 最后,给出你的结论和建议

请在回答中展示你的思考过程。

3. 少样本学习(Few-Shot Learning)

通过提供示例来引导 AI 的输出:

请根据以下示例的格式生成产品描述:

示例 1:
产品:无线蓝牙耳机
描述:采用最新蓝牙 5.3 技术,支持主动降噪,续航长达 30 小时。
     轻量设计仅重 5.2g,长时间佩戴无压力。IPX5 防水等级,
     适合运动使用。

示例 2:
产品:便携式充电宝
描述:20000mAh 超大容量,支持 65W 快充,可同时为 3 台设备充电。
     机身仅重 350g,轻松放入口袋。LED 电量显示,随时掌握电量。

现在请为以下产品生成描述:
产品:{{product_name}}

5.5 对话开场白设计

好的对话开场白能够提升用户体验,引导用户正确使用应用。

开场白设计原则

  1. 简洁明了:不要过于冗长,3-5 行即可
  2. 说明能力:让用户知道 AI 能做什么
  3. 引导使用:提供使用示例或建议问题
  4. 友好亲切:使用恰当的问候和表情符号

开场白示例

技术支持助手

你好!👋 我是技术支持助手。

我可以帮你解决产品使用中的各种问题,包括:
• 🔧 故障排查与解决
• 📖 功能使用指南
• ❓ 常见问题解答

请描述你遇到的问题,我会尽力帮助你!

写作助手

嗨!我是你的写作助手 ✍️

我能帮你:
• 📝 撰写各类文章和文案
• ✏️ 润色和改写现有文本
• 🌐 多语言翻译
• 💡 提供写作灵感和大纲

告诉我你想写什么,我们开始吧!

建议问题的设置

在开场白下方,可以设置 3-4 个建议问题,帮助用户快速开始:

建议问题:
1. "如何重置账号密码?"
2. "产品支持哪些文件格式?"
3. "怎么联系人工客服?"
4. "最新版本更新了什么功能?"

5.6 Prompt 优化技巧

1. 明确具体

❌ 模糊的 Prompt:帮我写一篇文章

✅ 明确的 Prompt:为 25-35 岁的职场女性写一篇 800 字左右的健康饮食建议文章,使用轻松活泼的语气,包含 3 个实用的食谱建议

2. 设定边界

重要限制:
- 不要编造不存在的数据或引用
- 如果不确定,请明确说明
- 不要提供医疗、法律方面的专业建议
- 涉及敏感话题时保持中立

3. 输出格式化

请使用以下 JSON 格式输出分析结果:
{
  "summary": "一句话总结",
  "key_points": ["要点1", "要点2", "要点3"],
  "sentiment": "正面/负面/中性",
  "confidence": 0.85
}

4. 迭代优化

Prompt 的优化是一个持续的过程:

  1. 编写初始版本
  2. 使用不同的输入测试
  3. 分析输出的质量和一致性
  4. 调整 Prompt 中的指令和约束
  5. 重复测试和优化

第六章 工作流编排

6.1 工作流基础

工作流是 Dify 中最灵活的应用构建方式。通过可视化编排不同的功能节点,你可以构建出复杂的 AI 应用流程。

创建工作流应用

  1. 在控制台点击"创建应用"
  2. 选择"工作流"类型
  3. 输入应用名称和描述
  4. 进入工作流编辑器

编辑器界面

工作流编辑器主要包含以下区域:

  • 节点面板(左侧):展示所有可用的节点类型,拖拽到画布即可添加
  • 画布区域(中间):可视化的工作流编辑区域,支持缩放、拖拽、框选
  • 节点配置(右侧):选中节点后,右侧显示该节点的详细配置面板
  • 工具栏(顶部):包含保存、运行、调试、撤销/重做等操作按钮

基本操作

添加节点

  • 从左侧节点面板拖拽节点到画布
  • 或者点击画布上的 + 按钮快速添加

连接节点

  • 从一个节点的输出端口拖拽连线到另一个节点的输入端口
  • 连线会自动吸附和弯曲

配置节点

  • 点击选中节点
  • 在右侧配置面板中设置参数

删除节点

  • 选中节点后按 Delete 键
  • 或右键选择删除

6.2 节点类型详解

6.2.1 开始节点

开始节点是工作流的入口,每个工作流有且只有一个开始节点。

配置内容

  • 输入变量:定义工作流接收的输入参数
  • 每个变量需要设置名称、类型(文本/段落/数字/文件)、是否必填

示例配置

变量1:query(文本,必填)- 用户的查询问题
变量2:language(下拉选择,默认"中文")- 输出语言
变量3:file(文件,选填)- 上传的附件

6.2.2 LLM 节点

LLM 节点是工作流中最核心的节点,用于调用大语言模型。

配置项

  • 模型选择:选择要使用的 LLM 模型
  • System Prompt:系统提示词
  • User Prompt:用户消息(支持变量引用)
  • Temperature:控制输出的随机性(0-1)
  • Max Tokens:最大输出长度
  • 输出变量:定义该节点的输出变量名

System Prompt 示例

你是一个专业的文档分析师。请根据提供的文档内容,提取关键信息并生成结构化的摘要。

输出格式要求:
1. 主题概括(一句话)
2. 关键要点(3-5 个要点)
3. 重要数据/指标(如有)

User Prompt 示例

请分析以下文档内容:

{{start_node.file_content}}

用户的关注点:{{start_node.query}}

6.2.3 知识库检索节点

知识库检索节点用于从指定知识库中检索相关文档。

配置项

  • 知识库选择:选择要检索的知识库(可选择多个)
  • 检索变量:指定用哪个变量作为查询文本
  • Top-K:返回最相关的 K 个结果
  • Score 阈值:相似度阈值过滤
  • 检索模式:向量检索 / 全文检索 / 混合检索

输出变量

  • result:检索到的文档片段列表
  • result[0].content:第一个结果的内容
  • result[0].title:第一个结果的标题
  • result[0].score:第一个结果的相似度分数

6.2.4 条件分支节点(IF/ELSE)

条件分支节点根据条件判断来决定工作流的执行路径。

配置项

  • 条件表达式:定义判断条件
  • 分支路径:满足条件和不满足条件的两条路径

支持的条件操作

  • 等于 / 不等于
  • 大于 / 小于
  • 包含 / 不包含
  • 为空 / 不为空
  • 开头是 / 结尾是
  • 正则匹配

示例

条件:{{llm_node.category}} == "技术问题"
├── 是 → 连接到"技术支持"LLM 节点
└── 否 → 连接到"通用客服"LLM 节点

6.2.5 代码执行节点

代码执行节点允许你在工作流中运行自定义代码,支持 Python 和 JavaScript。

使用场景

  • 数据格式转换
  • 复杂的逻辑计算
  • 字符串处理
  • JSON 解析与生成
  • 外部库调用

Python 示例 - JSON 解析

import json

def main(text: str) -> dict:
    try:
        data = json.loads(text)
        return {
            "result": data.get("key", "未找到"),
            "success": True
        }
    except json.JSONDecodeError:
        return {
            "result": "JSON 解析失败",
            "success": False
        }

Python 示例 - 文本处理

def main(text: str, max_length: int) -> dict:
    # 去除多余空白
    cleaned = " ".join(text.split())
    # 截断到指定长度
    if len(cleaned) > max_length:
        cleaned = cleaned[:max_length] + "..."
    # 统计字数
    word_count = len(cleaned)
    
    return {
        "cleaned_text": cleaned,
        "word_count": word_count,
        "is_truncated": len(text) > max_length
    }

6.2.6 HTTP 请求节点

HTTP 请求节点用于调用外部 API,实现与第三方服务的集成。

配置项

  • 请求方法:GET / POST / PUT / DELETE / PATCH
  • URL:请求地址(支持变量)
  • Headers:请求头
  • Body:请求体(POST/PUT 时使用)
  • 超时时间:请求超时设置
  • 输出变量:响应状态码、响应体等

POST 请求示例

方法:POST
URL:https://api.example.com/analyze
Headers:
  Content-Type: application/json
  Authorization: Bearer {{api_key}}
Body:
{
  "text": "{{llm_node.output}}",
  "language": "zh"
}

使用场景

  • 发送通知(邮件、Slack、企业微信)
  • 调用第三方 AI 服务
  • 数据存储到外部数据库
  • 触发 Webhook

6.2.7 变量聚合节点

当工作流有多条分支路径时,变量聚合节点用于将不同分支的输出合并为统一的变量。

使用场景

条件分支
├── 分支 A → 输出 result_a
├── 分支 B → 输出 result_b
└── 分支 C → 输出 result_c
         ↓
    变量聚合节点
    将 result_a / result_b / result_c 统一为 result
         ↓
    后续节点使用 {{aggregate.result}}

6.2.8 模板转换节点

模板转换节点使用 Jinja2 模板语法来格式化和组合变量。

示例模板

## 分析报告

**查询问题**:{{query}}

**分析结果**:
{{analysis_result}}

**参考来源**:
{% for source in sources %}
{{loop.index}}. {{source.title}} (相关度: {{source.score}})
{% endfor %}

---
生成时间:{{current_time}}

6.2.9 迭代节点

迭代节点用于对列表数据进行循环处理。

配置

  • 输入列表:指定要迭代的变量(必须是数组类型)
  • 迭代体:内部包含的子工作流
  • 输出:每次迭代的结果组成的数组

使用场景

  • 批量处理多篇文档
  • 对多个搜索结果逐一分析
  • 批量调用 API
  • 逐条处理数据库记录

6.2.10 参数提取节点

参数提取节点使用 LLM 从非结构化文本中提取结构化参数。

配置

  • 输入文本:要提取参数的文本
  • 参数定义:定义要提取的参数列表(名称、类型、描述、是否必填)
  • 模型:用于提取的 LLM 模型

示例

输入文本:"我想订一张明天从北京到上海的机票,经济舱,下午的航班"

参数定义:
- 出发城市(文本):出发地城市名称
- 到达城市(文本):目的地城市名称
- 出发日期(文本):出发日期
- 舱位等级(选择):经济舱/商务舱/头等舱
- 时间偏好(选择):上午/下午/晚上

提取结果:
{
  "出发城市": "北京",
  "到达城市": "上海",
  "出发日期": "明天",
  "舱位等级": "经济舱",
  "时间偏好": "下午"
}

6.2.11 结束节点

结束节点定义工作流的最终输出。

配置

  • 输出变量:选择要作为最终输出的变量
  • 可以输出多个变量

6.3 变量传递

变量在工作流节点间的传递是工作流的核心机制。

引用其他节点的变量

使用 {{节点名.变量名}} 的格式引用其他节点的输出:

{{start.query}}           → 开始节点的 query 变量
{{llm_1.text}}            → LLM 节点 llm_1 的输出
{{kb_search.result}}      → 知识库检索节点的结果
{{code_1.output}}         → 代码节点的输出
{{http_1.body}}           → HTTP 请求的响应体

变量类型转换

不同节点输出的变量类型可能不同,需要注意类型匹配:

  • LLM 节点输出:字符串类型
  • 代码节点输出:可以是任意类型(取决于代码的返回值)
  • HTTP 节点输出:字符串(JSON)类型
  • 条件分支输出:根据分支不同可能不同

6.4 错误处理

在工作流执行过程中,可能会遇到各种错误。Dify 提供了完善的错误处理机制。

常见错误类型

  1. LLM 调用失败:API 限流、模型不可用、Token 超限
  2. 知识库检索失败:向量数据库连接问题
  3. HTTP 请求失败:网络超时、接口返回错误
  4. 代码执行错误:代码异常、类型错误
  5. 变量缺失:引用了不存在的变量

错误处理策略

1. 节点级重试

对于 LLM 和 HTTP 节点,可以配置自动重试策略:

  • 最大重试次数:建议设置为 2-3 次
  • 重试间隔:建议使用指数退避(如 1s, 2s, 4s)

2. 异常分支

在可能失败的节点后添加条件分支,处理异常情况:

HTTP 请求节点
├── 成功 → 继续正常流程
└── 失败 → 连接到"错误处理"LLM 节点
          └── 生成友好的错误提示返回给用户

3. 默认值设置

为可能为空的变量设置默认值:

{{http_node.response | default("服务暂时不可用,请稍后再试")}}

6.5 工作流最佳实践

1. 模块化设计

将复杂的工作流拆分为多个子模块:

  • 主工作流:负责整体流程控制
  • 子工作流:处理特定的功能模块

2. 清晰的命名

为每个节点使用有意义的名称:

❌ 好的命名:LLM 节点 1、LLM 节点 2
✅ 好的命名:分析用户意图、生成回答、内容审核

3. 充分的测试

在发布前,使用多种输入测试工作流:

  • 正常输入
  • 边界情况
  • 异常输入(空值、超长文本等)
  • 特殊字符

4. 日志记录

在关键节点添加日志输出,方便调试和监控。

5. 性能优化

  • 减少不必要的 LLM 调用
  • 合理使用并行分支
  • 设置合理的超时时间
  • 控制变量传递的数据量

第七章 Agent 模式开发

7.1 Agent 概述

Agent 是 Dify 中最智能化的应用类型。与普通的聊天助手不同,Agent 具备自主推理、工具调用和多步执行的能力,能够处理更加复杂的任务。

Agent 与普通聊天助手的区别

特性 聊天助手 Agent
推理能力 被动回答 主动推理和规划
工具使用 支持多种工具调用
任务复杂度 单步回答 多步骤执行
外部交互 可以访问外部数据和服务
执行模式 即时响应 思考-行动-观察循环

7.2 创建 Agent 应用

步骤一:创建应用

  1. 点击"创建应用"
  2. 选择"Agent"类型
  3. 填写应用名称和描述
  4. 进入 Agent 配置界面

步骤二:编写系统提示词

Agent 的系统提示词需要明确定义其角色、能力和行为准则:

你是一个专业的研究助手 Agent。你的任务是帮助用户进行信息收集、分析和总结。

## 你的能力
- 搜索互联网获取最新信息
- 阅读和分析网页内容
- 进行数学和逻辑计算
- 执行代码进行数据处理

## 工作原则
1. 对于需要最新信息的问题,主动搜索互联网
2. 对于需要计算的问题,使用计算工具而非心算
3. 综合多个来源的信息,给出全面的回答
4. 始终引用信息来源
5. 如果无法找到可靠信息,如实告知用户

## 输出格式
- 先简要说明你的分析思路
- 然后给出详细的回答
- 最后列出参考来源

步骤三:选择推理策略

在 Agent 配置中,选择合适的推理策略:

ReAct 策略

  • 适合大多数场景
  • 思维链清晰可见
  • 执行过程透明

Function Calling 策略

  • 速度更快
  • 调用更精准
  • 需要模型支持(如 GPT-4、Claude 3 等)

7.3 工具配置

7.3.1 使用内置工具

Dify 提供了丰富的内置工具,可以直接在 Agent 中使用:

网页抓取工具

  • 功能:读取指定 URL 的网页内容
  • 适用场景:获取网页信息、阅读文章
  • 使用示例:用户问"帮我看看这个网页的内容",Agent 会调用网页抓取工具

维基百科搜索

  • 功能:搜索维基百科获取信息
  • 适用场景:查询百科知识
  • 使用示例:用户问"什么是量子计算",Agent 会搜索维基百科

数学计算器

  • 功能:执行数学表达式计算
  • 适用场景:数学计算、数据分析
  • 使用示例:用户问"计算 15% 的年化收益",Agent 会使用计算器

代码执行器

  • 功能:运行 Python 代码
  • 适用场景:数据处理、图表生成、复杂计算
  • 使用示例:用户问"帮我生成一个柱状图",Agent 会编写并执行 Python 代码

7.3.2 添加内置工具

在 Agent 配置界面:

  1. 找到"工具"配置区域
  2. 点击"添加工具"
  3. 从工具列表中选择需要的工具
  4. 按照提示完成配置(如 API Key 等)
  5. 保存配置

7.3.3 创建自定义工具

当内置工具无法满足需求时,你可以创建自定义工具:

方式一:通过 API Schema 创建

  1. 在"工具"页面,点击"创建自定义工具"
  2. 输入工具名称和描述
  3. 导入 API Schema(支持 OpenAPI/Swagger 格式)
  4. 配置认证方式(如 API Key、Bearer Token 等)
  5. 测试工具调用

OpenAPI Schema 示例

{
  "openapi": "3.0.0",
  "info": {
    "title": "天气查询 API",
    "version": "1.0.0"
  },
  "paths": {
    "/weather": {
      "get": {
        "summary": "查询天气信息",
        "description": "根据城市名称查询当前天气",
        "parameters": [
          {
            "name": "city",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "城市名称"
          }
        ],
        "responses": {
          "200": {
            "description": "天气信息",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "temperature": {"type": "number"},
                    "condition": {"type": "string"},
                    "humidity": {"type": "number"}
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

方式二:通过可视化界面创建

  1. 点击"创建自定义工具"
  2. 选择"可视化创建"
  3. 配置请求方法、URL、参数、认证等
  4. 测试并保存

7.4 推理策略详解

7.4.1 ReAct 策略

ReAct(Reasoning + Acting)策略的核心思想是让 AI 在"思考"和"行动"之间交替进行。

执行流程

用户输入
    ↓
[思考] 分析问题,确定需要哪些信息/工具
    ↓
[行动] 调用工具获取信息
    ↓
[观察] 分析工具返回的结果
    ↓
[判断] 信息是否足够?
    ├── 否 → 返回 [思考] 继续
    └── 是 → 生成最终回答

ReAct 的优势

  • 思维链清晰可见,用户可以看到 AI 的推理过程
  • 每一步都有明确的思考和行动
  • 容易调试和优化

ReAct 的限制

  • 执行速度相对较慢
  • 每次只调用一个工具
  • 可能需要多轮循环才能完成任务

7.4.2 Function Calling 策略

Function Calling 是模型提供商(如 OpenAI、Anthropic)提供的原生工具调用机制。

执行流程

用户输入 + 工具列表
    ↓
模型分析并输出函数调用请求(JSON 格式)
    ↓
平台执行函数
    ↓
返回结果给模型
    ↓
模型生成最终回答(可能再次调用函数)

Function Calling 的优势

  • 调用更精准,减少误调用
  • 支持并行调用多个工具
  • 响应速度更快
  • 与模型深度集成

Function Calling 的限制

  • 需要模型本身支持此功能
  • 不同模型的实现可能有差异
  • 调试相对困难

7.4.3 如何选择推理策略

场景 推荐策略 原因
需要透明的推理过程 ReAct 思维链清晰
追求响应速度 Function Calling 更快
需要调用多个工具 Function Calling 支持并行
使用较旧的模型 ReAct 兼容性更好
复杂的多步骤任务 ReAct 流程更可控
简单的工具调用 Function Calling 更高效

7.5 多工具协作

在实际应用中,Agent 往往需要协调使用多个工具来完成复杂任务。

示例:智能研究助手

假设用户问:"帮我研究一下 2024 年中国新能源汽车市场的发展趋势"

Agent 的执行过程可能是:

步骤 1 - 思考:
用户需要关于中国新能源汽车市场的最新信息。
我需要搜索互联网获取最新数据。

步骤 1 - 行动:
调用搜索引擎,查询"2024年中国新能源汽车市场发展趋势"

步骤 2 - 观察:
搜索返回了多条相关结果,包含市场数据和分析报告

步骤 2 - 思考:
我需要获取更详细的数据。让我抓取排名第一的网页内容。

步骤 2 - 行动:
调用网页抓取工具,读取详细报告页面

步骤 3 - 观察:
获取到了详细的市场数据,包括销量、增长率、主要厂商等

步骤 3 - 思考:
用户可能还需要一些数据计算。让我计算增长率等指标。

步骤 3 - 行动:
调用计算器工具,计算相关数据指标

步骤 4 - 思考:
我已经收集了足够的信息,可以给用户一个全面的回答了。

最终回答:
综合多个来源的信息,2024年中国新能源汽车市场呈现以下趋势...

7.6 Agent 调试与优化

7.6.1 调试技巧

1. 查看执行日志

Agent 的每次执行都会记录详细的日志:

  • 思考过程
  • 工具调用的输入输出
  • 执行时间
  • Token 消耗

2. 测试不同的输入

使用各种类型的输入测试 Agent:

  • 简单问题(不需要工具)
  • 中等问题(需要一个工具)
  • 复杂问题(需要多个工具协作)
  • 边界情况(工具无法获取信息)

3. 分析失败案例

当 Agent 执行失败或结果不理想时:

  • 检查推理链是否合理
  • 确认工具调用是否正确
  • 分析返回结果是否被正确利用

7.6.2 优化策略

1. 优化系统提示词

  • 明确 Agent 的能力边界
  • 提供清晰的工具使用指引
  • 设定回答质量标准

2. 工具描述优化

为每个工具提供详细准确的描述,帮助模型正确选择工具:

❌ 模糊的描述:搜索信息
✅ 清晰的描述:使用 Google 搜索引擎搜索互联网上的最新信息。适用于需要获取最新新闻、实时数据、产品信息等场景。输入应该是简洁的搜索关键词。

3. 限制执行步骤

设置最大执行步骤数,避免 Agent 陷入无限循环:

  • 建议设置 5-10 步
  • 对于特别复杂的任务,可以适当增加

4. 优化模型选择

选择对工具调用支持更好的模型:

  • GPT-4o / GPT-4:Function Calling 支持最好
  • Claude 3.5 Sonnet:推理能力强
  • 本地模型:可能需要使用 ReAct 策略

第八章 API 集成开发

8.1 API 概述

Dify 的一个重要特性是为每个应用自动生成标准的 RESTful API。这意味着你可以将 Dify 构建的 AI 能力无缝集成到任何现有的应用系统中。

API 的核心特性

  • 标准 RESTful 风格:遵循 REST 架构规范
  • 认证机制:基于 API Key 的 Bearer Token 认证
  • 流式输出:支持 Server-Sent Events (SSE) 实现流式响应
  • 会话管理:支持多轮对话的会话 ID 管理
  • 文件上传:支持在对话中上传文件

8.2 API 密钥管理

获取 API 密钥

  1. 打开你的应用
  2. 点击左侧菜单中的"访问 API"
  3. 在 API 密钥管理页面,点击"创建新密钥"
  4. 为密钥添加描述(如"生产环境-前端应用")
  5. 复制并安全保存生成的 API 密钥

安全提示:API 密钥只在创建时显示一次,请务必妥善保存。如果遗失,需要重新创建新的密钥。

API 密钥安全最佳实践

  1. 不要在前端代码中硬编码密钥:应通过后端服务代理 API 调用
  2. 定期轮换密钥:建议每 3-6 个月更换一次
  3. 不同环境使用不同密钥:开发、测试、生产环境分别使用独立密钥
  4. 监控密钥使用情况:定期检查 API 调用日志

API 基础信息

Dify API 的基础 URL 格式:

  • 云端版:https://api.dify.ai/v1
  • 本地部署:http://your-server-ip/v1

8.3 HTTP 调用示例

8.3.1 对话型 API(Chat API)

发送消息

curl -X POST 'http://your-server/v1/chat-messages' \
  -H 'Authorization: Bearer {api_key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "inputs": {},
    "query": "你好,请介绍一下你自己",
    "response_mode": "blocking",
    "user": "user-123"
  }'

请求参数说明

参数 类型 必填 说明
inputs object 输入变量(键值对)
query string 用户的输入内容
response_mode string "blocking"(阻塞)或"streaming"(流式)
conversation_id string 会话 ID(多轮对话时使用)
user string 用户唯一标识
files array 上传的文件列表

阻塞模式响应示例

{
  "event": "message",
  "message_id": "msg-abc123",
  "conversation_id": "conv-xyz789",
  "answer": "你好!我是一个AI助手,很高兴为你服务...",
  "created_at": 1700000000,
  "metadata": {
    "usage": {
      "prompt_tokens": 150,
      "completion_tokens": 200,
      "total_tokens": 350
    }
  }
}

8.3.2 流式输出(SSE)

流式输出可以让用户在 AI 生成回答的过程中实时看到内容,提升用户体验。

请求示例

curl -X POST 'http://your-server/v1/chat-messages' \
  -H 'Authorization: Bearer {api_key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "inputs": {},
    "query": "请详细解释量子计算的原理",
    "response_mode": "streaming",
    "user": "user-123"
  }'

流式响应示例

data: {"event": "message", "answer": "量子", "message_id": "msg-abc123"}

data: {"event": "message", "answer": "计算", "message_id": "msg-abc123"}

data: {"event": "message", "answer": "是一种", "message_id": "msg-abc123"}

data: {"event": "message", "answer": "利用量子力学原理", "message_id": "msg-abc123"}

...

data: {"event": "message_end", "message_id": "msg-abc123", "metadata": {"usage": {"prompt_tokens": 150, "completion_tokens": 500, "total_tokens": 650}}}

8.3.3 补全型 API(Completion API)

对于文本生成类型的应用,使用补全型 API:

curl -X POST 'http://your-server/v1/completion-messages' \
  -H 'Authorization: Bearer {api_key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "inputs": {
      "query": "人工智能",
      "language": "中文",
      "style": "学术"
    },
    "response_mode": "blocking",
    "user": "user-123"
  }'

8.3.4 文件上传

上传文件并在对话中使用:

curl -X POST 'http://your-server/v1/files/upload' \
  -H 'Authorization: Bearer {api_key}' \
  -F 'file=@/path/to/document.pdf' \
  -F 'user=user-123'

上传成功后,在发送消息时引用文件:

curl -X POST 'http://your-server/v1/chat-messages' \
  -H 'Authorization: Bearer {api_key}' \
  -H 'Content-Type: application/json' \
  -d '{
    "inputs": {},
    "query": "请总结这个文档的主要内容",
    "response_mode": "blocking",
    "user": "user-123",
    "files": [
      {
        "type": "document",
        "transfer_method": "local_file",
        "upload_file_id": "file-id-from-upload-response"
      }
    ]
  }'

8.4 Python SDK 使用

Dify 官方提供了 Python SDK,简化了 API 的调用过程。

安装 SDK

pip install dify-client

基本使用

from dify_client import DifyClient

# 初始化客户端
client = DifyClient(api_key="your-api-key")

# 发送消息(阻塞模式)
response = client.create_chat_message(
    inputs={},
    query="你好,请介绍一下机器学习的基本概念",
    user="user-123",
    response_mode="blocking"
)

# 获取回答
result = response.json()
print(result["answer"])
print(f"Token 使用量: {result['metadata']['usage']['total_tokens']}")

流式输出处理

from dify_client import DifyClient

client = DifyClient(api_key="your-api-key")

# 发送消息(流式模式)
response = client.create_chat_message(
    inputs={},
    query="请详细解释深度学习的原理",
    user="user-123",
    response_mode="streaming"
)

# 处理流式响应
for line in response.iter_lines():
    if line:
        line = line.decode("utf-8")
        if line.startswith("data: "):
            data = line[6:]
            import json
            event = json.loads(data)
            if event.get("event") == "message":
                print(event["answer"], end="", flush=True)
            elif event.get("event") == "message_end":
                print("\n--- 回答结束 ---")

多轮对话

from dify_client import DifyClient

client = DifyClient(api_key="your-api-key")
conversation_id = None  # 首次对话不设置

def chat(query):
    global conversation_id
    
    response = client.create_chat_message(
        inputs={},
        query=query,
        user="user-123",
        conversation_id=conversation_id,
        response_mode="blocking"
    )
    
    result = response.json()
    conversation_id = result["conversation_id"]  # 保存会话 ID
    return result["answer"]

# 多轮对话
print(chat("你好,我想学习Python"))
print(chat("我应该从哪里开始?"))
print(chat("推荐一些学习资源"))

错误处理

from dify_client import DifyClient
import requests

client = DifyClient(api_key="your-api-key")

try:
    response = client.create_chat_message(
        inputs={},
        query="测试消息",
        user="user-123",
        response_mode="blocking"
    )
    
    if response.status_code == 200:
        result = response.json()
        print(result["answer"])
    elif response.status_code == 401:
        print("错误:API 密钥无效")
    elif response.status_code == 429:
        print("错误:请求过于频繁,请稍后重试")
    else:
        print(f"错误:{response.status_code} - {response.text}")
        
except requests.exceptions.ConnectionError:
    print("错误:无法连接到 Dify 服务器")
except requests.exceptions.Timeout:
    print("错误:请求超时")
except Exception as e:
    print(f"未知错误:{str(e)}")

8.5 JavaScript SDK 使用

安装

npm install dify-client
# 或
yarn add dify-client

基本使用

import { DifyClient } from 'dify-client';

// 初始化客户端
const client = new DifyClient('your-api-key');

// 发送消息
async function chat(query) {
  try {
    const response = await client.createChatMessage({
      inputs: {},
      query: query,
      user: 'user-123',
      response_mode: 'blocking'
    });
    
    const result = response.data;
    console.log(result.answer);
    return result;
  } catch (error) {
    console.error('请求失败:', error.message);
  }
}

chat('你好,请介绍一下自然语言处理');

流式输出处理

import { DifyClient } from 'dify-client';

const client = new DifyClient('your-api-key');

async function chatStream(query) {
  try {
    const response = await client.createChatMessage({
      inputs: {},
      query: query,
      user: 'user-123',
      response_mode: 'streaming'
    });
    
    const reader = response.data.getReader();
    const decoder = new TextDecoder();
    
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      
      const text = decoder.decode(value);
      const lines = text.split('\n');
      
      for (const line of lines) {
        if (line.startsWith('data: ')) {
          const data = JSON.parse(line.slice(6));
          if (data.event === 'message') {
            process.stdout.write(data.answer);
          } else if (data.event === 'message_end') {
            console.log('\n--- 回答结束 ---');
          }
        }
      }
    }
  } catch (error) {
    console.error('流式请求失败:', error.message);
  }
}

chatStream('请详细解释机器学习的工作原理');

在前端应用中集成

<!DOCTYPE html>
<html>
<head>
  <title>Dify 聊天应用</title>
  <style>
    #chat-container {
      max-width: 600px;
      margin: 20px auto;
      font-family: Arial, sans-serif;
    }
    #messages {
      height: 400px;
      overflow-y: auto;
      border: 1px solid #ddd;
      padding: 10px;
      margin-bottom: 10px;
    }
    .message {
      margin: 5px 0;
      padding: 8px 12px;
      border-radius: 8px;
    }
    .user { background: #007bff; color: white; text-align: right; }
    .ai { background: #f1f1f1; }
    #input-area { display: flex; gap: 10px; }
    #input { flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
    button { padding: 10px 20px; background: #007bff; color: white; border: none; border-radius: 4px; cursor: pointer; }
  </style>
</head>
<body>
  <div id="chat-container">
    <h2>Dify AI 聊天</h2>
    <div id="messages"></div>
    <div id="input-area">
      <input type="text" id="input" placeholder="输入消息..." onkeypress="if(event.key==='Enter')sendMessage()">
      <button onclick="sendMessage()">发送</button>
    </div>
  </div>

  <script>
    const API_KEY = 'your-api-key';
    const API_URL = 'http://your-server/v1/chat-messages';
    let conversationId = null;

    async function sendMessage() {
      const input = document.getElementById('input');
      const query = input.value.trim();
      if (!query) return;
      
      // 显示用户消息
      addMessage(query, 'user');
      input.value = '';
      
      // 创建 AI 消息占位
      const aiMsg = addMessage('', 'ai');
      
      try {
        const body = {
          inputs: {},
          query: query,
          user: 'web-user',
          response_mode: 'streaming'
        };
        if (conversationId) body.conversation_id = conversationId;
        
        const response = await fetch(API_URL, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${API_KEY}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(body)
        });
        
        const reader = response.body.getReader();
        const decoder = new TextDecoder();
        
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          
          const text = decoder.decode(value);
          const lines = text.split('\n');
          
          for (const line of lines) {
            if (line.startsWith('data: ')) {
              try {
                const data = JSON.parse(line.slice(6));
                if (data.event === 'message') {
                  aiMsg.textContent += data.answer;
                }
                if (data.conversation_id) {
                  conversationId = data.conversation_id;
                }
              } catch (e) {}
            }
          }
        }
      } catch (error) {
        aiMsg.textContent = '请求失败: ' + error.message;
      }
    }

    function addMessage(text, type) {
      const messages = document.getElementById('messages');
      const div = document.createElement('div');
      div.className = `message ${type}`;
      div.textContent = text;
      messages.appendChild(div);
      messages.scrollTop = messages.scrollHeight;
      return div;
    }
  </script>
</body>
</html>

8.6 API 高级功能

8.6.1 会话管理

获取会话列表

GET /v1/conversations?user=user-123&limit=20&sort_by=-updated_at

获取会话消息历史

GET /v1/messages?user=user-123&conversation_id=conv-xyz789

删除会话

DELETE /v1/conversations/{conversation_id}?user=user-123

8.6.2 消息反馈

用户可以对 AI 的回答进行评价:

POST /v1/messages/{message_id}/feedbacks
{
  "rating": "like",  // "like" 或 "dislike"
  "user": "user-123",
  "content": "回答非常准确"
}

8.6.3 获取应用参数

获取应用的输入参数配置和工具信息:

GET /v1/parameters?user=user-123

响应示例:

{
  "opening_statement": "你好!我是AI助手...",
  "suggested_questions": ["问题1", "问题2", "问题3"],
  "suggested_questions_after_answer": {
    "enabled": true
  },
  "speech_to_text": {
    "enabled": false
  },
  "retriever_resource": {
    "enabled": true
  },
  "annotation_reply": {
    "enabled": false
  },
  "user_input_form": [
    {
      "text-input": {
        "variable": "query",
        "label": "查询内容",
        "required": true,
        "default": ""
      }
    }
  ]
}

第九章 高级功能

9.1 多模型切换

Dify 支持在一个应用中灵活切换不同的模型,这使得你可以根据需求选择最合适的模型。

模型配置

  1. 进入"设置" → "模型供应商"
  2. 添加不同的模型提供商和 API Key
  3. 在应用编辑中,点击模型选择器切换模型

模型选择策略

场景 推荐模型 原因
复杂推理任务 GPT-4o / Claude 3.5 Sonnet 推理能力强
简单问答 GPT-3.5-Turbo / DeepSeek V3 速度快、成本低
长文本处理 Claude 3 Opus / Kimi 上下文窗口大
代码生成 GPT-4o / DeepSeek Coder 代码能力突出
中文对话 通义千问 / 文心一言 中文优化

模型参数调优

Temperature(温度)

  • 范围:0-1
  • 低温度(0-0.3):输出更确定、更保守,适合事实性问答
  • 中温度(0.4-0.7):平衡创意和准确性,适合大多数场景
  • 高温度(0.8-1):输出更随机、更有创意,适合创作类任务

Top-P(核采样)

  • 范围:0-1
  • 与 Temperature 配合使用
  • 建议只调整其中一个参数

Max Tokens(最大 Token 数)

  • 控制 AI 的最大输出长度
  • 根据预期回答长度设置
  • 过小可能截断回答,过大浪费资源

Frequency Penalty(频率惩罚)

  • 范围:-2 到 2
  • 正值减少重复内容
  • 适合需要多样性的场景

Presence Penalty(存在惩罚)

  • 范围:-2 到 2
  • 正值鼓励谈论新话题
  • 适合对话和创意写作

9.2 内容审核

Dify 支持内容审核功能,确保 AI 的输出安全合规。

配置内容审核

  1. 在应用编辑页面,找到"功能"设置
  2. 开启"内容审核"功能
  3. 选择审核方式:
    • 内置审核:使用 Dify 内置的敏感词库
    • 自定义审核 API:接入第三方内容审核服务

自定义审核 API

你可以接入自己的内容审核服务:

{
  "type": "moderation",
  "config": {
    "provider": "api",
    "api_url": "https://your-moderation-api.com/check",
    "api_key": "your-key"
  }
}

审核 API 需要返回以下格式的响应:

{
  "flagged": true,
  "categories": {
    "hate": false,
    "violence": true,
    "sexual": false
  }
}

9.3 对话记忆管理

对话记忆是聊天类应用的核心功能。Dify 提供了灵活的记忆管理机制。

记忆窗口大小

  • 定义 AI 能"记住"多少轮对话
  • 设置方法:在应用配置中找到"对话轮数"参数
  • 建议值:10-30 轮

记忆压缩

对于长对话,Dify 支持记忆压缩功能:

  • 自动摘要:将较早的对话内容自动压缩为摘要
  • 保留关键信息:确保重要的上下文不丢失
  • 节省 Token:减少每次请求的 Token 消耗

记忆清理

用户可以通过以下方式清理对话记忆:

  • 开始新的对话(创建新的 conversation_id)
  • 通过 API 删除特定会话

9.4 标注与反馈

Dify 的标注功能允许你对 AI 的回答进行人工审核和优化。

开启标注功能

  1. 在应用编辑页面,找到"标注"功能
  2. 开启标注回复功能
  3. 配置标注参数

标注流程

  1. 用户与 AI 对话
  2. 在对话记录中,对不满意的回答进行标注
  3. 添加期望的正确回答
  4. 当相似问题再次出现时,AI 会优先使用标注的回答

反馈收集

  • 用户反馈:用户可以对 AI 回答点赞/踩
  • 反馈分析:在应用分析页面查看反馈统计
  • 持续优化:根据反馈数据优化 Prompt 和知识库

9.5 分析与监控

Dify 提供了丰富的数据分析功能,帮助你了解应用的使用情况。

核心指标

  • 总对话数:应用的累计对话次数
  • 活跃用户数:使用应用的独立用户数量
  • 平均对话轮数:每个会话的平均消息数
  • Token 消耗:模型调用的 Token 使用量
  • 用户满意度:基于用户反馈的评分

日志查看

在应用的"日志"页面,可以查看:

  • 每条对话的详细记录
  • 模型的输入输出
  • Token 使用量
  • 响应时间
  • 用户反馈

导出数据

支持导出对话日志和分析数据:

  • CSV 格式导出
  • JSON 格式导出
  • 自定义时间范围

第十章 部署与运维

10.1 Docker 生产环境部署

生产环境的部署需要考虑安全性、可靠性和性能。

10.1.1 生产环境配置

服务器推荐配置

组件 推荐配置
应用服务器 4 核 CPU, 8GB RAM, 100GB SSD
数据库服务器 4 核 CPU, 16GB RAM, 200GB SSD
向量数据库 4 核 CPU, 16GB RAM, 200GB SSD

对于小型团队或低并发场景,所有组件可以部署在同一台服务器上。

生产环境 .env 配置

# ==================== 安全配置 ====================
# 应用密钥(必须修改)
SECRET_KEY=<使用 openssl rand -base64 42 生成>

# ==================== 数据库配置 ====================
# PostgreSQL
POSTGRES_USER=dify
POSTGRES_PASSWORD=<强密码>
POSTGRES_DB=dify

# Redis
REDIS_PASSWORD=<强密码>

# ==================== 网络配置 ====================
EXPOSE_NGINX_PORT=443
EXPOSE_NGINX_SSL_PORT=443

# ==================== 存储配置 ====================
STORAGE_TYPE=s3  # 生产环境推荐使用 S3 兼容存储
S3_ENDPOINT=https://your-s3-endpoint
S3_BUCKET_NAME=dify-storage
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key

# ==================== 日志配置 ====================
LOG_LEVEL=WARNING
LOG_FILE=/var/log/dify/app.log

# ==================== 性能配置 ====================
# Worker 数量
API_WORKER_AMOUNT=4
CELERY_WORKER_AMOUNT=2

# 数据库连接池
DB_POOL_SIZE=20
DB_MAX_OVERFLOW=10

10.1.2 HTTPS 配置

生产环境必须使用 HTTPS:

方案一:使用 Nginx 反向代理 + Let's Encrypt

server {
    listen 80;
    server_name your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name your-domain.com;
    
    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
    
    location / {
        proxy_pass http://localhost:80;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # WebSocket 支持
    location /v1/chat-messages {
        proxy_pass http://localhost:80;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

方案二:使用云服务商的负载均衡器

大多数云服务商(如阿里云、腾讯云、AWS)都提供支持 HTTPS 的负载均衡器,可以直接在负载均衡器上配置 SSL 证书。

10.1.3 数据库优化

PostgreSQL 优化

-- 连接数配置
ALTER SYSTEM SET max_connections = 200;

-- 内存配置
ALTER SYSTEM SET shared_buffers = '4GB';
ALTER SYSTEM SET effective_cache_size = '12GB';
ALTER SYSTEM SET work_mem = '256MB';

-- WAL 配置
ALTER SYSTEM SET wal_buffers = '64MB';
ALTER SYSTEM SET checkpoint_completion_target = 0.9;

-- 重启 PostgreSQL 使配置生效
SELECT pg_reload_conf();

Redis 优化

# redis.conf 配置优化
maxmemory 2gb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000

10.2 环境变量完整配置

以下是 Dify 的主要环境变量及其说明:

核心配置

# 应用密钥
SECRET_KEY=your-secret-key

# 控制台管理员邮箱(首次初始化时使用)
INIT_PASSWORD=your-admin-password

# 应用 Web 前端 URL
CONSOLE_WEB_URL=https://dify.your-domain.com
APP_WEB_URL=https://app.your-domain.com

# API 服务 URL
API_URL=https://api.your-domain.com

模型配置

# OpenAI
OPENAI_API_KEY=your-openai-key
OPENAI_API_BASE=https://api.openai.com/v1

# Anthropic
ANTHROPIC_API_KEY=your-anthropic-key

# 通义千问
DASHSCOPE_API_KEY=your-dashscope-key

存储配置

# 本地存储
STORAGE_TYPE=local
STORAGE_LOCAL_PATH=storage

# S3 存储
STORAGE_TYPE=s3
S3_ENDPOINT=https://s3.amazonaws.com
S3_BUCKET_NAME=dify
S3_ACCESS_KEY=your-key
S3_SECRET_KEY=your-secret
S3_REGION=us-east-1

# Azure Blob 存储
STORAGE_TYPE=azure-blob
AZURE_BLOB_ACCOUNT_NAME=your-account
AZURE_BLOB_ACCOUNT_KEY=your-key
AZURE_BLOB_CONTAINER_NAME=dify

向量数据库配置

# Weaviate(默认)
VECTOR_STORE=weaviate
WEAVIATE_ENDPOINT=http://weaviate:8080

# Qdrant
VECTOR_STORE=qdrant
QDRANT_URL=http://qdrant:6333
QDRANT_API_KEY=your-key

# Milvus
VECTOR_STORE=milvus
MILVUS_URI=http://milvus:19530

# Pgvector(使用内置 PostgreSQL)
VECTOR_STORE=pgvector

10.3 数据备份

10.3.1 数据库备份

PostgreSQL 备份脚本

#!/bin/bash
# dify-backup.sh

BACKUP_DIR="/backup/dify"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/dify_db_$DATE.sql"

# 创建备份目录
mkdir -p $BACKUP_DIR

# 执行数据库备份
docker exec dify-db pg_dump -U dify dify > $BACKUP_FILE

# 压缩备份文件
gzip $BACKUP_FILE

# 删除 30 天前的备份
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete

echo "备份完成: ${BACKUP_FILE}.gz"

设置定时备份

# 编辑 crontab
crontab -e

# 添加每天凌晨 2 点执行备份
0 2 * * * /path/to/dify-backup.sh >> /var/log/dify-backup.log 2>&1

10.3.2 文件存储备份

如果使用本地存储,需要备份上传的文件:

#!/bin/bash
# 文件存储备份

BACKUP_DIR="/backup/dify/files"
DATE=$(date +%Y%m%d_%H%M%S)
SOURCE_DIR="/path/to/dify/docker/volumes/app/storage"

mkdir -p $BACKUP_DIR

# 使用 rsync 增量备份
rsync -av --delete $SOURCE_DIR/ $BACKUP_DIR/current/

# 创建压缩快照
tar -czf $BACKUP_DIR/files_$DATE.tar.gz -C $BACKUP_DIR current/

# 删除 30 天前的快照
find $BACKUP_DIR -name "files_*.tar.gz" -mtime +30 -delete

10.3.3 数据恢复

PostgreSQL 恢复

# 解压备份文件
gunzip dify_db_20240101_020000.sql.gz

# 停止 Dify 服务
docker compose stop api worker

# 恢复数据库
cat dify_db_20240101_020000.sql | docker exec -i dify-db psql -U dify dify

# 重启服务
docker compose start api worker

10.4 监控告警

10.4.1 服务健康检查

检查脚本

#!/bin/bash
# dify-healthcheck.sh

# 检查 API 服务
API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:80/v1/health)
if [ "$API_STATUS" != "200" ]; then
    echo "ERROR: API 服务异常 (HTTP $API_STATUS)"
    # 发送告警通知
fi

# 检查数据库
DB_STATUS=$(docker exec dify-db pg_isready -U dify)
if [ $? -ne 0 ]; then
    echo "ERROR: 数据库连接异常"
fi

# 检查 Redis
REDIS_STATUS=$(docker exec dify-redis redis-cli -a $REDIS_PASSWORD ping)
if [ "$REDIS_STATUS" != "PONG" ]; then
    echo "ERROR: Redis 连接异常"
fi

# 检查磁盘空间
DISK_USAGE=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 85 ]; then
    echo "WARNING: 磁盘使用率过高 ($DISK_USAGE%)"
fi

# 检查内存使用
MEM_USAGE=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
if (( $(echo "$MEM_USAGE > 90" | bc -l) )); then
    echo "WARNING: 内存使用率过高 ($MEM_USAGE%)"
fi

10.4.2 使用 Prometheus + Grafana 监控

Dify 的 API 服务暴露了 Prometheus 指标端点:

Prometheus 配置

# prometheus.yml
scrape_configs:
  - job_name: 'dify-api'
    static_configs:
      - targets: ['dify-api:5001']
    metrics_path: '/metrics'

Grafana Dashboard

推荐监控以下指标:

  • API 请求量(QPS)
  • API 响应时间(P50/P95/P99)
  • 错误率
  • 活跃连接数
  • Token 使用量
  • 模型调用延迟

10.5 性能优化

10.5.1 应用层优化

1. Prompt 优化

  • 精简不必要的 Prompt 内容
  • 合理设置 Max Tokens
  • 使用较低的 Temperature 减少生成时间

2. 知识库优化

  • 合理设置 Top-K(通常 3-5 足够)
  • 使用 Score 阈值过滤低质量结果
  • 定期清理过时文档

3. 缓存策略

  • 启用 Redis 缓存
  • 对频繁查询的结果设置缓存
  • 合理设置缓存过期时间

10.5.2 基础设施优化

1. 水平扩展

# docker-compose.yml - 扩展 API Worker
services:
  api:
    deploy:
      replicas: 4  # 根据负载调整
  
  worker:
    deploy:
      replicas: 2

2. 数据库优化

  • 定期执行 VACUUM 和 ANALYZE
  • 优化慢查询
  • 添加适当的索引

3. 负载均衡

使用 Nginx 或云负载均衡器分发请求:

upstream dify_api {
    server api-1:5001;
    server api-2:5001;
    server api-3:5001;
    server api-4:5001;
}

server {
    listen 80;
    location /v1/ {
        proxy_pass http://dify_api;
    }
}

10.5.3 成本优化

1. 模型选择策略

  • 简单任务使用低成本模型
  • 复杂任务使用高能力模型
  • 建立模型路由规则

2. Token 优化

  • 精简 System Prompt
  • 控制对话历史长度
  • 合理设置 Max Tokens

3. 缓存利用

  • 对相同或相似的查询使用缓存结果
  • 减少重复的模型调用

4. 预算管理

  • 设置 API 调用预算告警
  • 监控每日 Token 消耗
  • 分析高消耗应用并优化

第十一章 实战项目:构建企业级智能文档问答系统

11.1 项目概述

在本章中,我们将从零开始构建一个完整的企业级智能文档问答系统。这个系统将综合运用前面学到的所有知识点,包括知识库管理、Prompt 工程、工作流编排、API 集成等。

系统功能

  • 支持多种格式的企业文档导入(PDF、Word、Markdown)
  • 智能问答,基于文档内容生成准确回答
  • 引用溯源,标注回答的文档来源
  • 多轮对话,支持追问和上下文理解
  • API 接口,可集成到企业内部系统
  • 反馈机制,持续优化回答质量

技术架构

┌──────────────────────────────────────────────┐
│                    前端界面                     │
│           (Web Chat / 企业内部系统)              │
├──────────────────────────────────────────────┤
│                    API 层                      │
│         (Dify RESTful API + 流式输出)           │
├──────────────────────────────────────────────┤
│                  工作流引擎                     │
│    查询分类 → 知识库检索 → 回答生成 → 质量检查     │
├──────────────────────────────────────────────┤
│                  知识库引擎                     │
│    文档解析 → 分段 → 向量化 → 存储 → 检索         │
├──────────────────────────────────────────────┤
│                  基础设施                      │
│    PostgreSQL / Redis / Weaviate / Nginx      │
└──────────────────────────────────────────────┘

11.2 准备工作

11.2.1 环境准备

确保你已经完成了以下准备工作:

  1. Dify 已成功部署并可以访问
  2. 至少配置了一个模型供应商的 API Key(推荐 OpenAI GPT-4o)
  3. 准备好需要导入的企业文档

11.2.2 文档准备

准备以下类型的测试文档:

  • 产品手册:产品功能说明、操作指南
  • FAQ 文档:常见问题与解答
  • 政策文件:公司制度、流程规范
  • 技术文档:系统架构、API 文档

建议先用 5-10 个文档进行测试,验证效果后再批量导入。

11.3 创建知识库

步骤一:创建产品知识库

  1. 进入"知识库"页面
  2. 点击"创建知识库"
  3. 名称:企业文档知识库
  4. 描述:包含产品手册、FAQ、政策文件等企业内部文档

步骤二:上传文档

将准备好的文档逐一上传:

  1. 点击"添加文档"
  2. 选择"上传文件"
  3. 拖拽或选择文件
  4. 等待上传完成

步骤三:配置分段策略

对于不同类型的企业文档,建议使用不同的分段策略:

产品手册(Markdown/Word):

  • 分段标识符:\n\n##(按二级标题分段)
  • 最大分段长度:600 tokens
  • 分段重叠:100 tokens

FAQ 文档

  • 分段标识符:\n\n(按段落分段)
  • 最大分段长度:400 tokens
  • 分段重叠:50 tokens

政策文件(PDF):

  • 分段标识符:\n\n(按段落分段)
  • 最大分段长度:500 tokens
  • 分段重叠:80 tokens

步骤四:选择索引方式

选择"高质量"索引模式:

  • Embedding 模型:text-embedding-3-small(性价比最高)
  • 等待索引完成(根据文档量大小,可能需要几分钟到几十分钟)

步骤五:检索测试

进行多轮检索测试:

测试 1:产品有哪些功能?
→ 期望返回产品功能相关文档

测试 2:如何重置密码?
→ 期望返回密码重置相关的 FAQ

测试 3:请假流程是什么?
→ 期望返回人事政策相关文档

测试 4:API 的认证方式是什么?
→ 期望返回 API 技术文档

根据测试结果调整分段策略和索引参数。

11.4 创建问答应用

步骤一:选择应用类型

创建一个新的"聊天助手"类型应用:

  • 名称:企业智能文档问答系统
  • 描述:基于企业文档的智能问答助手

步骤二:设计 System Prompt

编写高质量的 System Prompt:

你是一个专业的"企业智能文档问答系统"。你的任务是基于企业内部文档,为员工提供准确、专业的回答。

## 你的角色
- 你是公司的智能知识助手
- 你对企业的产品、政策、流程非常熟悉
- 你始终基于提供的文档内容回答问题

## 回答原则
1. **准确性优先**:只基于提供的参考资料回答,绝不编造信息
2. **引用来源**:回答时明确标注参考的文档来源
3. **简洁明了**:使用清晰简洁的语言,避免冗长
4. **结构化输出**:适当使用标题、列表、表格等格式组织回答
5. **主动引导**:如果文档中没有直接答案,建议用户联系相关部门

## 回答格式
回答时请遵循以下格式:

### 回答
(基于文档内容的详细回答)

### 参考来源
- (文档名称 / 章节)

### 相关建议
- (如有需要,提供进一步的建议或联系方式)

## 特殊情况处理
- 如果文档中没有相关信息:明确告知用户"根据现有文档,未找到相关信息",并建议联系对应部门
- 如果信息可能已过时:提醒用户确认信息的时效性
- 如果问题涉及机密信息:礼貌拒绝并说明原因

## 禁止行为
- 不要编造文档中不存在的信息
- 不要猜测或推测
- 不要透露系统的技术实现细节
- 不要回答与企业文档无关的问题

步骤三:关联知识库

  1. 在"上下文"配置区域,点击"添加"
  2. 选择刚创建的"企业文档知识库"
  3. 配置检索参数:
    • Top-K:5
    • Score 阈值:0.5
    • 检索模式:混合检索

步骤四:配置变量

添加以下变量:

变量名 类型 必填 说明
department 下拉选择 用户所在部门(用于筛选更相关的结果)

下拉选项:技术部、产品部、市场部、人事部、财务部、其他

步骤五:设置对话开场白

👋 你好!我是企业智能文档问答助手。

我可以帮你查询:
• 📦 产品功能和使用方法
• ❓ 常见问题解答
• 📋 公司政策和流程
• 🔧 技术文档和 API 接口

你可以直接输入问题,或者尝试以下问题:

建议问题:

  • "产品有哪些主要功能?"
  • "如何申请年假?"
  • "API 的认证方式是什么?"

步骤六:优化 Prompt 中的上下文引用

在 System Prompt 中添加上下文引用:

## 参考资料

以下是与用户问题相关的企业文档内容。请基于这些资料回答问题:

{{#context#}}

步骤七:选择模型并调优

  • 选择模型:GPT-4o(推荐,效果最好)
  • Temperature:0.3(事实性问答,需要较低的随机性)
  • Max Tokens:2000(足够生成详细的回答)

11.5 构建高级工作流(可选)

如果你需要更复杂的处理逻辑,可以创建一个工作流版本:

工作流设计

开始节点(接收用户查询)
    ↓
知识库检索节点(检索相关文档)
    ↓
条件分支节点(判断是否有检索结果)
├── 有结果 → LLM 节点(基于文档生成回答)
│              ↓
│         代码节点(格式化输出,添加引用)
└── 无结果 → LLM 节点(生成无结果提示)
              ↓
         结束节点(输出回答)

详细配置

1. 开始节点

输入变量:
- query:文本,必填,用户的查询问题
- department:文本,选填,用户所在部门

2. 知识库检索节点

知识库:企业文档知识库
检索变量:{{start.query}}
Top-K:5
Score 阈值:0.5
检索模式:混合检索

3. 条件分支节点

条件:{{kb_search.result}} 不为空
├── 是 → 连接到"基于文档回答"LLM 节点
└── 否 → 连接到"无结果提示"LLM 节点

4. "基于文档回答" LLM 节点

System Prompt:

你是一个企业文档问答助手。请根据以下参考资料,准确回答用户的问题。

回答要求:
1. 只基于参考资料回答,不要编造信息
2. 回答要结构化,使用标题和列表
3. 在回答末尾列出参考来源

参考资料:
{{kb_search.result}}

User Prompt:

用户问题:{{start.query}}

5. "无结果提示" LLM 节点

System Prompt:

用户的问题在企业文档中没有找到相关内容。请礼貌地告知用户,并建议他们:
1. 换一种方式提问
2. 联系对应的部门获取帮助

请根据问题内容推荐可能负责的部门。

6. 代码节点(格式化输出)

def main(llm_output: str, search_results: list) -> dict:
    # 添加引用信息
    references = []
    for i, result in enumerate(search_results[:3], 1):
        references.append(f"{i}. {result.get('title', '未知文档')}")
    
    formatted_output = llm_output
    if references:
        formatted_output += "\n\n### 参考来源\n" + "\n".join(references)
    
    return {
        "answer": formatted_output,
        "has_references": len(references) > 0
    }

7. 结束节点

输出:{{format_node.answer}}

11.6 API 集成

将问答系统集成到企业内部系统中。

创建 API 密钥

  1. 进入应用的"访问 API"页面
  2. 创建新密钥,命名为"内部系统集成"
  3. 复制并保存密钥

后端集成代码

"""
企业文档问答系统 - 后端集成示例
"""
import requests
import json
from flask import Flask, request, jsonify, Response

app = Flask(__name__)

DIFY_API_URL = "http://your-dify-server/v1"
DIFY_API_KEY = "your-api-key"

@app.route("/api/ask", methods=["POST"])
def ask():
    """接收前端请求,转发到 Dify API"""
    data = request.json
    query = data.get("query", "")
    user_id = data.get("user_id", "anonymous")
    conversation_id = data.get("conversation_id")
    
    # 构建请求体
    body = {
        "inputs": {},
        "query": query,
        "user": user_id,
        "response_mode": "streaming"  # 使用流式输出
    }
    if conversation_id:
        body["conversation_id"] = conversation_id
    
    # 调用 Dify API
    headers = {
        "Authorization": f"Bearer {DIFY_API_KEY}",
        "Content-Type": "application/json"
    }
    
    def generate():
        """流式输出生成器"""
        with requests.post(
            f"{DIFY_API_URL}/chat-messages",
            headers=headers,
            json=body,
            stream=True
        ) as response:
            for line in response.iter_lines():
                if line:
                    yield line.decode("utf-8") + "\n"
    
    return Response(generate(), mimetype="text/event-stream")

@app.route("/api/feedback", methods=["POST"])
def feedback():
    """提交用户反馈"""
    data = request.json
    message_id = data.get("message_id")
    rating = data.get("rating")  # "like" 或 "dislike"
    
    headers = {
        "Authorization": f"Bearer {DIFY_API_KEY}",
        "Content-Type": "application/json"
    }
    
    response = requests.post(
        f"{DIFY_API_URL}/messages/{message_id}/feedbacks",
        headers=headers,
        json={
            "rating": rating,
            "user": data.get("user_id", "anonymous")
        }
    )
    
    return jsonify(response.json())

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

前端集成示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>企业智能文档问答</title>
  <style>
    * { box-sizing: border-box; margin: 0; padding: 0; }
    body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; background: #f5f5f5; }
    .container { max-width: 800px; margin: 0 auto; padding: 20px; }
    h1 { text-align: center; color: #333; margin-bottom: 20px; }
    .chat-box { background: white; border-radius: 12px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); overflow: hidden; }
    .messages { height: 500px; overflow-y: auto; padding: 20px; }
    .msg { margin-bottom: 16px; display: flex; }
    .msg.user { justify-content: flex-end; }
    .msg .bubble { max-width: 70%; padding: 12px 16px; border-radius: 12px; line-height: 1.6; }
    .msg.user .bubble { background: #007bff; color: white; border-bottom-right-radius: 4px; }
    .msg.ai .bubble { background: #f0f0f0; color: #333; border-bottom-left-radius: 4px; }
    .msg .feedback { margin-top: 8px; font-size: 12px; }
    .msg .feedback button { background: none; border: none; cursor: pointer; font-size: 16px; padding: 2px 6px; }
    .input-area { display: flex; padding: 16px; border-top: 1px solid #eee; gap: 10px; }
    .input-area input { flex: 1; padding: 12px; border: 1px solid #ddd; border-radius: 8px; font-size: 14px; }
    .input-area button { padding: 12px 24px; background: #007bff; color: white; border: none; border-radius: 8px; cursor: pointer; font-size: 14px; }
    .input-area button:disabled { background: #ccc; }
    .sources { margin-top: 8px; font-size: 12px; color: #666; }
  </style>
</head>
<body>
  <div class="container">
    <h1>📚 企业智能文档问答</h1>
    <div class="chat-box">
      <div class="messages" id="messages">
        <div class="msg ai">
          <div class="bubble">
            👋 你好!我是企业智能文档问答助手。<br><br>
            我可以帮你查询产品文档、公司政策、常见问题等。<br>
            请输入你的问题吧!
          </div>
        </div>
      </div>
      <div class="input-area">
        <input type="text" id="queryInput" placeholder="输入你的问题..." 
               onkeypress="if(event.key==='Enter')askQuestion()">
        <button id="sendBtn" onclick="askQuestion()">发送</button>
      </div>
    </div>
  </div>

  <script>
    const API_URL = '/api/ask';
    let conversationId = null;

    async function askQuestion() {
      const input = document.getElementById('queryInput');
      const query = input.value.trim();
      if (!query) return;

      // 显示用户消息
      addMessage(query, 'user');
      input.value = '';
      document.getElementById('sendBtn').disabled = true;

      // 创建 AI 消息占位
      const aiBubble = addMessage('', 'ai');
      const sourcesDiv = document.createElement('div');
      sourcesDiv.className = 'sources';

      try {
        const body = { query, user_id: 'web-user' };
        if (conversationId) body.conversation_id = conversationId;

        const response = await fetch(API_URL, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(body)
        });

        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;

          const text = decoder.decode(value);
          const lines = text.split('\n');

          for (const line of lines) {
            if (line.startsWith('data: ')) {
              try {
                const data = JSON.parse(line.slice(6));
                if (data.event === 'message') {
                  aiBubble.innerHTML += data.answer;
                }
                if (data.conversation_id) {
                  conversationId = data.conversation_id;
                }
                if (data.event === 'message_end' && data.metadata?.retriever_resources) {
                  const refs = data.metadata.retriever_resources;
                  if (refs.length > 0) {
                    sourcesDiv.innerHTML = '📖 参考来源:' + 
                      refs.map(r => r.dataset_name).join('、');
                    aiBubble.parentNode.appendChild(sourcesDiv);
                  }
                }
              } catch (e) {}
            }
          }
        }
      } catch (error) {
        aiBubble.textContent = '请求失败,请稍后重试。';
      }

      document.getElementById('sendBtn').disabled = false;
      document.getElementById('messages').scrollTop = document.getElementById('messages').scrollHeight;
    }

    function addMessage(text, type) {
      const messages = document.getElementById('messages');
      const div = document.createElement('div');
      div.className = `msg ${type}`;
      const bubble = document.createElement('div');
      bubble.className = 'bubble';
      bubble.innerHTML = text || '...';
      div.appendChild(bubble);
      messages.appendChild(div);
      messages.scrollTop = messages.scrollHeight;
      return bubble;
    }
  </script>
</body>
</html>

11.7 测试与优化

11.7.1 功能测试

进行全面的功能测试:

基本问答测试

测试 1:产品支持哪些操作系统?
→ 验证是否正确回答并引用文档来源

测试 2:如何申请年假?
→ 验证是否返回正确的流程说明

测试 3:API 的限流策略是什么?
→ 验证技术文档的检索和回答质量

多轮对话测试

第 1 轮:产品有哪些功能?
第 2 轮:其中 XX 功能如何使用?
第 3 轮:这个功能有什么限制?
→ 验证对话历史是否正确维护

边界测试

测试 1:输入空字符串
测试 2:输入超长文本
测试 3:输入与文档无关的问题
测试 4:输入特殊字符和表情

11.7.2 效果优化

根据测试结果进行优化:

检索效果不佳

  • 调整分段策略
  • 增加文档覆盖范围
  • 优化 Embedding 模型选择
  • 尝试混合检索模式

回答质量不高

  • 优化 System Prompt
  • 调整 Temperature 参数
  • 增加示例和约束
  • 优化上下文引用格式

响应速度慢

  • 减少 Top-K 值
  • 优化 Prompt 长度
  • 使用更快的模型
  • 启用缓存

11.7.3 持续优化机制

建立持续优化的闭环:

  1. 收集用户反馈:通过 API 的反馈功能收集用户评价
  2. 分析日志:定期查看对话日志,发现共性问题
  3. 更新知识库:及时添加新文档,删除过时内容
  4. 优化 Prompt:根据反馈不断调优提示词
  5. 监控指标:跟踪满意度、准确率等核心指标

11.8 部署上线

11.8.1 上线检查清单

在正式上线前,完成以下检查:

  • 所有文档已正确导入和索引
  • 检索测试结果满意
  • Prompt 优化完成
  • API 接口测试通过
  • 前端界面功能正常
  • 错误处理机制完善
  • 安全配置检查(HTTPS、API Key 保护)
  • 性能测试通过(并发、响应时间)
  • 备份策略已配置
  • 监控告警已设置

11.8.2 灰度发布

建议采用灰度发布策略:

  1. 先在小范围(如技术团队)内试用
  2. 收集反馈并优化
  3. 逐步扩大使用范围
  4. 全面上线

11.8.3 运维监控

上线后需要持续监控:

  • 使用统计:每日活跃用户、对话量、问题类型分布
  • 质量指标:用户满意度、回答准确率
  • 性能指标:响应时间、错误率
  • 成本指标:Token 消耗、模型调用费用

11.9 扩展功能

系统上线后,可以考虑以下扩展:

1. 多语言支持

在 Prompt 中添加多语言处理指令,支持中英文混合的文档和问答。

2. 图片理解

集成多模态模型,支持对文档中图片内容的理解和回答。

3. 自动摘要

添加文档自动摘要功能,在回答时提供简要概述。

4. 知识图谱

构建企业知识图谱,实现更深层次的知识关联和推理。

5. 多 Agent 协作

针对不同领域(技术、人事、财务等)创建专门的 Agent,通过路由分发实现专业回答。


总结

恭喜你完成了 Dify AI 应用平台零基础入门教程的全部学习!

让我们回顾一下你学到的关键知识点:

  1. Dify 基础:了解了 Dify 的核心功能、技术架构和适用场景
  2. 快速上手:掌握了云端注册和本地部署的方法
  3. 应用类型:理解了聊天助手、文本生成、Agent、工作流四种类型的区别和适用场景
  4. 知识库管理:学会了文档上传、分段策略、索引方式和检索优化
  5. Prompt 工程:掌握了变量绑定、上下文引用、模板设计等技巧
  6. 工作流编排:学会了使用各种节点类型构建复杂的工作流程
  7. Agent 开发:掌握了工具配置、推理策略和多工具协作
  8. API 集成:学会了通过 API 将 Dify 能力集成到外部系统
  9. 高级功能:了解了多模型切换、内容审核、标注反馈等高级特性
  10. 部署运维:掌握了生产环境部署、数据备份、监控告警的方法
  11. 实战项目:完成了一个完整的企业级智能文档问答系统的构建

下一步学习建议

  1. 深入学习:阅读 Dify 官方文档,了解更多高级功能
  2. 动手实践:尝试构建更多类型的 AI 应用
  3. 社区参与:加入 Dify 社区,与其他开发者交流经验
  4. 持续关注:Dify 正在快速迭代,关注最新的功能更新

学习资源

  • Dify 官方文档:https://docs.dify.ai
  • Dify GitHub 仓库:https://github.com/langgenius/dify
  • Dify 社区论坛:https://community.dify.ai
  • Dify 官方博客:https://dify.ai/blog

📝 版权声明:本教程由 AI 辅助创作,所有内容原创,不涉及任何版权内容。你可以自由使用、修改和分享本教程。

🕐 最后更新:2025 年 5 月

内容声明

本文内容为AI技术学习教程,仅供学习参考。如涉及技术问题,欢迎通过 xurj005@163.com 与我们交流。

目录