Dify + Ollama + DeepSeek:本地部署完全指南

前言

💡 痛点:想用 AI 但不想数据上云?API 调用成本高?模型响应慢?隐私数据不能出内网?

🎯 解决方案Dify + Ollama + DeepSeek 本地部署方案,完全离线运行,数据不出本地,成本为零。

组合优势:
#mermaid-svg-8tW6AW231FuFJIn5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-8tW6AW231FuFJIn5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-8tW6AW231FuFJIn5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-8tW6AW231FuFJIn5 .error-icon{fill:#552222;}#mermaid-svg-8tW6AW231FuFJIn5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8tW6AW231FuFJIn5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-8tW6AW231FuFJIn5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8tW6AW231FuFJIn5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8tW6AW231FuFJIn5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-8tW6AW231FuFJIn5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8tW6AW231FuFJIn5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8tW6AW231FuFJIn5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8tW6AW231FuFJIn5 .marker.cross{stroke:#333333;}#mermaid-svg-8tW6AW231FuFJIn5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8tW6AW231FuFJIn5 p{margin:0;}#mermaid-svg-8tW6AW231FuFJIn5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8tW6AW231FuFJIn5 .cluster-label text{fill:#333;}#mermaid-svg-8tW6AW231FuFJIn5 .cluster-label span{color:#333;}#mermaid-svg-8tW6AW231FuFJIn5 .cluster-label span p{background-color:transparent;}#mermaid-svg-8tW6AW231FuFJIn5 .label text,#mermaid-svg-8tW6AW231FuFJIn5 span{fill:#333;color:#333;}#mermaid-svg-8tW6AW231FuFJIn5 .node rect,#mermaid-svg-8tW6AW231FuFJIn5 .node circle,#mermaid-svg-8tW6AW231FuFJIn5 .node ellipse,#mermaid-svg-8tW6AW231FuFJIn5 .node polygon,#mermaid-svg-8tW6AW231FuFJIn5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8tW6AW231FuFJIn5 .rough-node .label text,#mermaid-svg-8tW6AW231FuFJIn5 .node .label text,#mermaid-svg-8tW6AW231FuFJIn5 .image-shape .label,#mermaid-svg-8tW6AW231FuFJIn5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-8tW6AW231FuFJIn5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-8tW6AW231FuFJIn5 .rough-node .label,#mermaid-svg-8tW6AW231FuFJIn5 .node .label,#mermaid-svg-8tW6AW231FuFJIn5 .image-shape .label,#mermaid-svg-8tW6AW231FuFJIn5 .icon-shape .label{text-align:center;}#mermaid-svg-8tW6AW231FuFJIn5 .node.clickable{cursor:pointer;}#mermaid-svg-8tW6AW231FuFJIn5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-8tW6AW231FuFJIn5 .arrowheadPath{fill:#333333;}#mermaid-svg-8tW6AW231FuFJIn5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8tW6AW231FuFJIn5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8tW6AW231FuFJIn5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8tW6AW231FuFJIn5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-8tW6AW231FuFJIn5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8tW6AW231FuFJIn5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-8tW6AW231FuFJIn5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8tW6AW231FuFJIn5 .cluster text{fill:#333;}#mermaid-svg-8tW6AW231FuFJIn5 .cluster span{color:#333;}#mermaid-svg-8tW6AW231FuFJIn5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8tW6AW231FuFJIn5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-8tW6AW231FuFJIn5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-8tW6AW231FuFJIn5 .icon-shape,#mermaid-svg-8tW6AW231FuFJIn5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-8tW6AW231FuFJIn5 .icon-shape p,#mermaid-svg-8tW6AW231FuFJIn5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-8tW6AW231FuFJIn5 .icon-shape .label rect,#mermaid-svg-8tW6AW231FuFJIn5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-8tW6AW231FuFJIn5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-8tW6AW231FuFJIn5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-8tW6AW231FuFJIn5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🚀 本地 AI 部署方案
🎨 Dify

可视化编排
🦙 Ollama

本地推理
🧠 DeepSeek

国产大模型
✅ 可视化工作流
✅ 知识库管理
✅ API 服务
✅ 一键部署
✅ 模型管理
✅ GPU 加速
✅ 中文能力强
✅ 推理速度快
✅ 完全免费

适用场景:

  • 🏢 企业内网部署(数据不出域)
  • 🔒 隐私敏感应用(医疗、金融、法律)
  • 💰 成本敏感项目(零 API 费用)
  • 🚀 需要定制化 AI 应用

一、架构设计

1.1 整体架构

#mermaid-svg-lGdoXRI8Eb045o78{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-lGdoXRI8Eb045o78 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-lGdoXRI8Eb045o78 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-lGdoXRI8Eb045o78 .error-icon{fill:#552222;}#mermaid-svg-lGdoXRI8Eb045o78 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-lGdoXRI8Eb045o78 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-lGdoXRI8Eb045o78 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-lGdoXRI8Eb045o78 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-lGdoXRI8Eb045o78 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-lGdoXRI8Eb045o78 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-lGdoXRI8Eb045o78 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-lGdoXRI8Eb045o78 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-lGdoXRI8Eb045o78 .marker.cross{stroke:#333333;}#mermaid-svg-lGdoXRI8Eb045o78 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-lGdoXRI8Eb045o78 p{margin:0;}#mermaid-svg-lGdoXRI8Eb045o78 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-lGdoXRI8Eb045o78 .cluster-label text{fill:#333;}#mermaid-svg-lGdoXRI8Eb045o78 .cluster-label span{color:#333;}#mermaid-svg-lGdoXRI8Eb045o78 .cluster-label span p{background-color:transparent;}#mermaid-svg-lGdoXRI8Eb045o78 .label text,#mermaid-svg-lGdoXRI8Eb045o78 span{fill:#333;color:#333;}#mermaid-svg-lGdoXRI8Eb045o78 .node rect,#mermaid-svg-lGdoXRI8Eb045o78 .node circle,#mermaid-svg-lGdoXRI8Eb045o78 .node ellipse,#mermaid-svg-lGdoXRI8Eb045o78 .node polygon,#mermaid-svg-lGdoXRI8Eb045o78 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-lGdoXRI8Eb045o78 .rough-node .label text,#mermaid-svg-lGdoXRI8Eb045o78 .node .label text,#mermaid-svg-lGdoXRI8Eb045o78 .image-shape .label,#mermaid-svg-lGdoXRI8Eb045o78 .icon-shape .label{text-anchor:middle;}#mermaid-svg-lGdoXRI8Eb045o78 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-lGdoXRI8Eb045o78 .rough-node .label,#mermaid-svg-lGdoXRI8Eb045o78 .node .label,#mermaid-svg-lGdoXRI8Eb045o78 .image-shape .label,#mermaid-svg-lGdoXRI8Eb045o78 .icon-shape .label{text-align:center;}#mermaid-svg-lGdoXRI8Eb045o78 .node.clickable{cursor:pointer;}#mermaid-svg-lGdoXRI8Eb045o78 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-lGdoXRI8Eb045o78 .arrowheadPath{fill:#333333;}#mermaid-svg-lGdoXRI8Eb045o78 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-lGdoXRI8Eb045o78 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-lGdoXRI8Eb045o78 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lGdoXRI8Eb045o78 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-lGdoXRI8Eb045o78 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lGdoXRI8Eb045o78 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-lGdoXRI8Eb045o78 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-lGdoXRI8Eb045o78 .cluster text{fill:#333;}#mermaid-svg-lGdoXRI8Eb045o78 .cluster span{color:#333;}#mermaid-svg-lGdoXRI8Eb045o78 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-lGdoXRI8Eb045o78 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-lGdoXRI8Eb045o78 rect.text{fill:none;stroke-width:0;}#mermaid-svg-lGdoXRI8Eb045o78 .icon-shape,#mermaid-svg-lGdoXRI8Eb045o78 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-lGdoXRI8Eb045o78 .icon-shape p,#mermaid-svg-lGdoXRI8Eb045o78 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-lGdoXRI8Eb045o78 .icon-shape .label rect,#mermaid-svg-lGdoXRI8Eb045o78 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-lGdoXRI8Eb045o78 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-lGdoXRI8Eb045o78 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-lGdoXRI8Eb045o78 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 用户
Dify Web
Dify API Server
Ollama
DeepSeek 模型
知识库
向量数据库

Weaviate
Dify Worker

组件说明:

组件 作用 端口
Dify Web 前端界面 80/443
Dify API 后端服务 5001
Dify Worker 异步任务 -
Ollama 模型推理 11434
Weaviate 向量数据库 8080

1.2 技术选型对比

方案 优点 缺点 推荐场景
Dify + Ollama 完全本地、易部署 需要 GPU 资源 企业生产
Dify + 商用 API 无需 GPU、响应快 有 API 成本 快速验证
纯 Ollama 最轻量 无可视化界面 开发测试
vLLM + Open-WebUI 性能最优 配置复杂 高并发场景

二、环境准备

2.1 硬件要求

#mermaid-svg-udIpOzmkqvZPw7DA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-udIpOzmkqvZPw7DA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-udIpOzmkqvZPw7DA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-udIpOzmkqvZPw7DA .error-icon{fill:#552222;}#mermaid-svg-udIpOzmkqvZPw7DA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-udIpOzmkqvZPw7DA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-udIpOzmkqvZPw7DA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-udIpOzmkqvZPw7DA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-udIpOzmkqvZPw7DA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-udIpOzmkqvZPw7DA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-udIpOzmkqvZPw7DA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-udIpOzmkqvZPw7DA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-udIpOzmkqvZPw7DA .marker.cross{stroke:#333333;}#mermaid-svg-udIpOzmkqvZPw7DA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-udIpOzmkqvZPw7DA p{margin:0;}#mermaid-svg-udIpOzmkqvZPw7DA .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-udIpOzmkqvZPw7DA .cluster-label text{fill:#333;}#mermaid-svg-udIpOzmkqvZPw7DA .cluster-label span{color:#333;}#mermaid-svg-udIpOzmkqvZPw7DA .cluster-label span p{background-color:transparent;}#mermaid-svg-udIpOzmkqvZPw7DA .label text,#mermaid-svg-udIpOzmkqvZPw7DA span{fill:#333;color:#333;}#mermaid-svg-udIpOzmkqvZPw7DA .node rect,#mermaid-svg-udIpOzmkqvZPw7DA .node circle,#mermaid-svg-udIpOzmkqvZPw7DA .node ellipse,#mermaid-svg-udIpOzmkqvZPw7DA .node polygon,#mermaid-svg-udIpOzmkqvZPw7DA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-udIpOzmkqvZPw7DA .rough-node .label text,#mermaid-svg-udIpOzmkqvZPw7DA .node .label text,#mermaid-svg-udIpOzmkqvZPw7DA .image-shape .label,#mermaid-svg-udIpOzmkqvZPw7DA .icon-shape .label{text-anchor:middle;}#mermaid-svg-udIpOzmkqvZPw7DA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-udIpOzmkqvZPw7DA .rough-node .label,#mermaid-svg-udIpOzmkqvZPw7DA .node .label,#mermaid-svg-udIpOzmkqvZPw7DA .image-shape .label,#mermaid-svg-udIpOzmkqvZPw7DA .icon-shape .label{text-align:center;}#mermaid-svg-udIpOzmkqvZPw7DA .node.clickable{cursor:pointer;}#mermaid-svg-udIpOzmkqvZPw7DA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-udIpOzmkqvZPw7DA .arrowheadPath{fill:#333333;}#mermaid-svg-udIpOzmkqvZPw7DA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-udIpOzmkqvZPw7DA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-udIpOzmkqvZPw7DA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-udIpOzmkqvZPw7DA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-udIpOzmkqvZPw7DA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-udIpOzmkqvZPw7DA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-udIpOzmkqvZPw7DA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-udIpOzmkqvZPw7DA .cluster text{fill:#333;}#mermaid-svg-udIpOzmkqvZPw7DA .cluster span{color:#333;}#mermaid-svg-udIpOzmkqvZPw7DA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-udIpOzmkqvZPw7DA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-udIpOzmkqvZPw7DA rect.text{fill:none;stroke-width:0;}#mermaid-svg-udIpOzmkqvZPw7DA .icon-shape,#mermaid-svg-udIpOzmkqvZPw7DA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-udIpOzmkqvZPw7DA .icon-shape p,#mermaid-svg-udIpOzmkqvZPw7DA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-udIpOzmkqvZPw7DA .icon-shape .label rect,#mermaid-svg-udIpOzmkqvZPw7DA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-udIpOzmkqvZPw7DA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-udIpOzmkqvZPw7DA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-udIpOzmkqvZPw7DA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 硬件配置
CPU
内存
GPU
存储
≥ 8 核
≥ 32GB
≥ RTX 3090

(24GB 显存)
≥ 100GB

最低配置 vs 推荐配置:

配置项 最低配置 推荐配置 说明
CPU 4 核 16 核 DeepSeek 需要
内存 16GB 64GB 加载模型需要
GPU 无需 RTX 3090 有 GPU 速度快 10 倍
存储 50GB 200GB 模型文件大
网络 10Mbps 100Mbps 下载模型用

2.2 软件环境

bash 复制代码
# 系统要求
✅ Ubuntu 20.04 / 22.04  (推荐)
✅ CentOS 7+ 
✅ Debian 11+
❌ Windows (不推荐,可用 WSL2)

# 依赖软件
✅ Docker 20.10+
✅ Docker Compose v2+
✅ NVIDIA Driver 525+ (有 GPU 时)
✅ CUDA 12.1+ (有 GPU 时)

检查环境:

bash 复制代码
#!/bin/bash
# check-env.sh - 环境检查脚本

echo "=== 系统信息 ==="
uname -a
cat /etc/os-release

echo -e "\n=== CPU 信息 ==="
lscpu | grep "CPU(s)"
free -h

echo -e "\n=== GPU 信息 ==="
if command -v nvidia-smi &> /dev/null; then
    nvidia-smi
else
    echo "未检测到 NVIDIA GPU"
fi

echo -e "\n=== Docker 信息 ==="
docker --version
docker compose version

echo -e "\n=== 磁盘空间 ==="
df -h /

echo -e "\n✅ 环境检查完成"

三、Ollama 安装与配置

3.1 Ollama 安装

bash 复制代码
# 方法 1:官方脚本安装(推荐)
curl -fsSL https://ollama.com/install.sh | sh

# 方法 2:手动下载安装
# 访问 https://github.com/ollama/ollama/releases
wget https://github.com/ollama/ollama/releases/download/v0.1.31/ollama-linux-amd64
chmod +x ollama-linux-amd64
sudo mv ollama-linux-amd64 /usr/local/bin/ollama

# 验证安装
ollama --version

3.2 配置 Ollama 服务

bash 复制代码
# 创建系统服务
sudo tee /etc/systemd/system/ollama.service <<EOF
[Unit]
Description=Ollama Service
After=network-online.target

[Service]
ExecStart=/usr/local/bin/ollama serve
User=root
Group=root
Restart=always
RestartSec=3
Environment="PATH=$PATH"
# 允许跨域访问(Dify 需要)
Environment="OLLAMA_ORIGINS=*"
# 监听所有网卡
Environment="OLLAMA_HOST=0.0.0.0:11434"
# GPU 层数(根据显存调整)
Environment="OLLAMA_NUM_GPU=999"

[Install]
WantedBy=default.target
EOF

# 启动服务
sudo systemctl daemon-reload
sudo systemctl enable ollama
sudo systemctl start ollama
sudo systemctl status ollama

关键配置说明:

环境变量 说明 推荐值
OLLAMA_ORIGINS 允许跨域的来源 * (生产环境应限制)
OLLAMA_HOST 监听地址 0.0.0.0:11434
OLLAMA_NUM_GPU GPU 加载层数 999 (全部)
OLLAMA_MAX_LOADED_MODELS 最多加载模型数 3

3.3 下载 DeepSeek 模型

bash 复制代码
# 下载 DeepSeek 模型(需要一段时间)
# deepseek-coder:6.7b - 代码模型(推荐)
ollama pull deepseek-coder:6.7b

# deepseek-v2:16b - 通用模型(效果更好,需要更大显存)
ollama pull deepseek-v2:16b

# 查看已下载模型
ollama list

# 测试运行
ollama run deepseek-coder:6.7b "写一个 Python 快速排序"

模型选择指南:
#mermaid-svg-KPtUyKUpa38AwR1F{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KPtUyKUpa38AwR1F .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KPtUyKUpa38AwR1F .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KPtUyKUpa38AwR1F .error-icon{fill:#552222;}#mermaid-svg-KPtUyKUpa38AwR1F .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KPtUyKUpa38AwR1F .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KPtUyKUpa38AwR1F .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KPtUyKUpa38AwR1F .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KPtUyKUpa38AwR1F .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KPtUyKUpa38AwR1F .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KPtUyKUpa38AwR1F .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KPtUyKUpa38AwR1F .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KPtUyKUpa38AwR1F .marker.cross{stroke:#333333;}#mermaid-svg-KPtUyKUpa38AwR1F svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KPtUyKUpa38AwR1F p{margin:0;}#mermaid-svg-KPtUyKUpa38AwR1F .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-KPtUyKUpa38AwR1F .cluster-label text{fill:#333;}#mermaid-svg-KPtUyKUpa38AwR1F .cluster-label span{color:#333;}#mermaid-svg-KPtUyKUpa38AwR1F .cluster-label span p{background-color:transparent;}#mermaid-svg-KPtUyKUpa38AwR1F .label text,#mermaid-svg-KPtUyKUpa38AwR1F span{fill:#333;color:#333;}#mermaid-svg-KPtUyKUpa38AwR1F .node rect,#mermaid-svg-KPtUyKUpa38AwR1F .node circle,#mermaid-svg-KPtUyKUpa38AwR1F .node ellipse,#mermaid-svg-KPtUyKUpa38AwR1F .node polygon,#mermaid-svg-KPtUyKUpa38AwR1F .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KPtUyKUpa38AwR1F .rough-node .label text,#mermaid-svg-KPtUyKUpa38AwR1F .node .label text,#mermaid-svg-KPtUyKUpa38AwR1F .image-shape .label,#mermaid-svg-KPtUyKUpa38AwR1F .icon-shape .label{text-anchor:middle;}#mermaid-svg-KPtUyKUpa38AwR1F .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KPtUyKUpa38AwR1F .rough-node .label,#mermaid-svg-KPtUyKUpa38AwR1F .node .label,#mermaid-svg-KPtUyKUpa38AwR1F .image-shape .label,#mermaid-svg-KPtUyKUpa38AwR1F .icon-shape .label{text-align:center;}#mermaid-svg-KPtUyKUpa38AwR1F .node.clickable{cursor:pointer;}#mermaid-svg-KPtUyKUpa38AwR1F .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KPtUyKUpa38AwR1F .arrowheadPath{fill:#333333;}#mermaid-svg-KPtUyKUpa38AwR1F .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KPtUyKUpa38AwR1F .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KPtUyKUpa38AwR1F .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KPtUyKUpa38AwR1F .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KPtUyKUpa38AwR1F .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KPtUyKUpa38AwR1F .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KPtUyKUpa38AwR1F .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KPtUyKUpa38AwR1F .cluster text{fill:#333;}#mermaid-svg-KPtUyKUpa38AwR1F .cluster span{color:#333;}#mermaid-svg-KPtUyKUpa38AwR1F div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KPtUyKUpa38AwR1F .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KPtUyKUpa38AwR1F rect.text{fill:none;stroke-width:0;}#mermaid-svg-KPtUyKUpa38AwR1F .icon-shape,#mermaid-svg-KPtUyKUpa38AwR1F .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KPtUyKUpa38AwR1F .icon-shape p,#mermaid-svg-KPtUyKUpa38AwR1F .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KPtUyKUpa38AwR1F .icon-shape .label rect,#mermaid-svg-KPtUyKUpa38AwR1F .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KPtUyKUpa38AwR1F .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KPtUyKUpa38AwR1F .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KPtUyKUpa38AwR1F :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 代码生成
通用对话
轻量部署
选择模型
用途?
deepseek-coder
deepseek-v2
deepseek-coder:1.3b
6.7b: 推荐

需要 12GB 显存
33b: 效果最好

需要 48GB 显存
16b: 推荐

需要 32GB 显存
236b: 顶级效果

需要多卡

模型 显存需求 内存需求 推荐 GPU 适用场景
deepseek-coder:1.3b 2GB 4GB 无需 GPU 轻量部署
deepseek-coder:6.7b 12GB 16GB RTX 3060 通用开发
deepseek-coder:33b 48GB 64GB A100 企业生产
deepseek-v2:16b 32GB 48GB A100 高质量对话

四、Dify 部署

4.1 Docker Compose 部署(推荐)

bash 复制代码
# 克隆 Dify 仓库
git clone https://github.com/langgenius/dify.git
cd dify/docker

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

# 编辑配置(关键配置如下)
vim .env

关键配置(.env 文件):

bash 复制代码
# ===== 基础配置 =====
# Dify 域名(本地部署可用 IP)
DIFY_WEB_URL=http://your-server-ip
DIFY_API_URL=http://your-server-ip/api

# ===== 模型配置 =====
# 启用 Ollama
OLLAMA_API_BASE_URL=http://host.docker.internal:11434

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

# ===== 存储配置 =====
# 存储路径
STORAGE_TYPE=local
STORAGE_LOCAL_PATH=./volumes/storage

# ===== 高级配置 =====
# 启用知识库
KNOWLEDGE_ENABLED=true
# 启用 Agent
AGENT_ENABLED=true
# 工作流并发数
MAX_WORKFLOW_RUNS=10

启动 Dify:

bash 复制代码
# 启动所有服务
docker compose up -d

# 查看运行状态
docker compose ps

# 查看日志
docker compose logs -f

# 停止服务
docker compose down

4.2 配置 Ollama 作为模型供应商

DeepSeek Ollama Dify 用户 DeepSeek Ollama Dify 用户 #mermaid-svg-C4mKeyiqnCWfRvOk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-C4mKeyiqnCWfRvOk .error-icon{fill:#552222;}#mermaid-svg-C4mKeyiqnCWfRvOk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-C4mKeyiqnCWfRvOk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-C4mKeyiqnCWfRvOk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-C4mKeyiqnCWfRvOk .marker.cross{stroke:#333333;}#mermaid-svg-C4mKeyiqnCWfRvOk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-C4mKeyiqnCWfRvOk p{margin:0;}#mermaid-svg-C4mKeyiqnCWfRvOk .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-C4mKeyiqnCWfRvOk text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-C4mKeyiqnCWfRvOk .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-C4mKeyiqnCWfRvOk .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-C4mKeyiqnCWfRvOk .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-C4mKeyiqnCWfRvOk .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-C4mKeyiqnCWfRvOk #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-C4mKeyiqnCWfRvOk .sequenceNumber{fill:white;}#mermaid-svg-C4mKeyiqnCWfRvOk #sequencenumber{fill:#333;}#mermaid-svg-C4mKeyiqnCWfRvOk #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-C4mKeyiqnCWfRvOk .messageText{fill:#333;stroke:none;}#mermaid-svg-C4mKeyiqnCWfRvOk .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-C4mKeyiqnCWfRvOk .labelText,#mermaid-svg-C4mKeyiqnCWfRvOk .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-C4mKeyiqnCWfRvOk .loopText,#mermaid-svg-C4mKeyiqnCWfRvOk .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-C4mKeyiqnCWfRvOk .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-C4mKeyiqnCWfRvOk .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-C4mKeyiqnCWfRvOk .noteText,#mermaid-svg-C4mKeyiqnCWfRvOk .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-C4mKeyiqnCWfRvOk .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-C4mKeyiqnCWfRvOk .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-C4mKeyiqnCWfRvOk .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-C4mKeyiqnCWfRvOk .actorPopupMenu{position:absolute;}#mermaid-svg-C4mKeyiqnCWfRvOk .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-C4mKeyiqnCWfRvOk .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-C4mKeyiqnCWfRvOk .actor-man circle,#mermaid-svg-C4mKeyiqnCWfRvOk line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-C4mKeyiqnCWfRvOk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 发送对话请求调用 Ollama API加载模型推理返回生成结果返回响应展示结果

在 Dify 中添加 Ollama 模型:

  1. 访问 http://your-server-ip
  2. 注册管理员账号
  3. 进入 设置 → 模型供应商
  4. 选择 Ollama
  5. 填写配置:
yaml 复制代码
# Ollama 配置
Model Name: deepseek-coder:6.7b
Base URL: http://host.docker.internal:11434
Model Type: LLM
Context Size: 16384  # DeepSeek 支持 16K 上下文

Python 脚本自动添加(可选):

python 复制代码
"""
自动添加 Ollama 模型到 Dify
"""
import requests

DIFY_API_BASE = "http://localhost/api"
ADMIN_TOKEN = "your-admin-token"  # 从 Dify 后台获取

def add_ollama_model():
    """添加 Ollama 模型"""
    
    url = f"{DIFY_API_BASE}/admin/workspaces/current/models"
    
    headers = {
        "Authorization": f"Bearer {ADMIN_TOKEN}",
        "Content-Type": "application/json"
    }
    
    payload = {
        "provider": "ollama",
        "model_name": "deepseek-coder:6.7b",
        "model_type": "llm",
        "config": {
            "base_url": "http://host.docker.internal:11434",
            "context_size": 16384
        }
    }
    
    response = requests.post(url, json=payload, headers=headers)
    
    if response.status_code == 201:
        print("✅ 模型添加成功")
    else:
        print(f"❌ 添加失败: {response.text}")

if __name__ == "__main__":
    add_ollama_model()

五、知识库配置

5.1 创建知识库

#mermaid-svg-SmuuC1Cw7r4CasZy{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-SmuuC1Cw7r4CasZy .error-icon{fill:#552222;}#mermaid-svg-SmuuC1Cw7r4CasZy .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-SmuuC1Cw7r4CasZy .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-SmuuC1Cw7r4CasZy .marker{fill:#333333;stroke:#333333;}#mermaid-svg-SmuuC1Cw7r4CasZy .marker.cross{stroke:#333333;}#mermaid-svg-SmuuC1Cw7r4CasZy svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-SmuuC1Cw7r4CasZy p{margin:0;}#mermaid-svg-SmuuC1Cw7r4CasZy .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-SmuuC1Cw7r4CasZy .cluster-label text{fill:#333;}#mermaid-svg-SmuuC1Cw7r4CasZy .cluster-label span{color:#333;}#mermaid-svg-SmuuC1Cw7r4CasZy .cluster-label span p{background-color:transparent;}#mermaid-svg-SmuuC1Cw7r4CasZy .label text,#mermaid-svg-SmuuC1Cw7r4CasZy span{fill:#333;color:#333;}#mermaid-svg-SmuuC1Cw7r4CasZy .node rect,#mermaid-svg-SmuuC1Cw7r4CasZy .node circle,#mermaid-svg-SmuuC1Cw7r4CasZy .node ellipse,#mermaid-svg-SmuuC1Cw7r4CasZy .node polygon,#mermaid-svg-SmuuC1Cw7r4CasZy .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-SmuuC1Cw7r4CasZy .rough-node .label text,#mermaid-svg-SmuuC1Cw7r4CasZy .node .label text,#mermaid-svg-SmuuC1Cw7r4CasZy .image-shape .label,#mermaid-svg-SmuuC1Cw7r4CasZy .icon-shape .label{text-anchor:middle;}#mermaid-svg-SmuuC1Cw7r4CasZy .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-SmuuC1Cw7r4CasZy .rough-node .label,#mermaid-svg-SmuuC1Cw7r4CasZy .node .label,#mermaid-svg-SmuuC1Cw7r4CasZy .image-shape .label,#mermaid-svg-SmuuC1Cw7r4CasZy .icon-shape .label{text-align:center;}#mermaid-svg-SmuuC1Cw7r4CasZy .node.clickable{cursor:pointer;}#mermaid-svg-SmuuC1Cw7r4CasZy .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-SmuuC1Cw7r4CasZy .arrowheadPath{fill:#333333;}#mermaid-svg-SmuuC1Cw7r4CasZy .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-SmuuC1Cw7r4CasZy .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-SmuuC1Cw7r4CasZy .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SmuuC1Cw7r4CasZy .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-SmuuC1Cw7r4CasZy .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SmuuC1Cw7r4CasZy .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-SmuuC1Cw7r4CasZy .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-SmuuC1Cw7r4CasZy .cluster text{fill:#333;}#mermaid-svg-SmuuC1Cw7r4CasZy .cluster span{color:#333;}#mermaid-svg-SmuuC1Cw7r4CasZy div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-SmuuC1Cw7r4CasZy .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-SmuuC1Cw7r4CasZy rect.text{fill:none;stroke-width:0;}#mermaid-svg-SmuuC1Cw7r4CasZy .icon-shape,#mermaid-svg-SmuuC1Cw7r4CasZy .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-SmuuC1Cw7r4CasZy .icon-shape p,#mermaid-svg-SmuuC1Cw7r4CasZy .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-SmuuC1Cw7r4CasZy .icon-shape .label rect,#mermaid-svg-SmuuC1Cw7r4CasZy .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-SmuuC1Cw7r4CasZy .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-SmuuC1Cw7r4CasZy .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-SmuuC1Cw7r4CasZy :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 上传文档
文本拆分
向量化
存储到 Weaviate
检索测试
④ 拆分策略
父子分段
按段落
固定长度
④ Embedding 模型
Ollama Embeddings
本地模型

操作步骤:

  1. 进入 知识库 → 创建知识库
  2. 上传文档(支持 PDF、Word、Markdown、TXT)
  3. 配置分段策略:
python 复制代码
# 分段策略配置(通过 API)
SEGMENT_CONFIG = {
    "mode": "parent_child",  # 父子分段(推荐)
    "parent_splitter": {
        "type": "paragraph",  # 按段落拆分
        "max_length": 1000     # 父块最大长度
    },
    "child_splitter": {
        "type": "token",       # 按 token 拆分
        "max_length": 200      # 子块最大长度
    },
    "overlap": 50             # 重叠长度
}
  1. 选择 Embedding 模型:
bash 复制代码
# 下载 Embedding 模型(Ollama)
ollama pull nomic-embed-text  # 推荐,效果好

# 或使用本地模型
# 需要在 Dify 配置中指定模型路径

5.2 知识库检索测试

python 复制代码
"""
测试知识库检索
"""
import requests

def test_knowledge_retrieval(query: str, dataset_id: str):
    """测试检索效果"""
    
    url = f"{DIFY_API_BASE}/datasets/{dataset_id}/retrieve"
    
    payload = {
        "query": query,
        "retrieval_model": {
            "top_k": 5,
            "score_threshold": 0.5
        }
    }
    
    response = requests.post(url, json=payload, headers=headers)
    
    if response.status_code == 200:
        results = response.json()["data"]["records"]
        print(f"查询:{query}")
        print(f"检索到 {len(results)} 条结果\n")
        
        for i, record in enumerate(results, 1):
            print(f"结果 {i}:")
            print(f"  内容:{record['segment']['content'][:100]}...")
            print(f"  得分:{record['score']:.3f}\n")
    else:
        print(f"❌ 检索失败: {response.text}")

# 使用
test_knowledge_retrieval(
    query="如何部署 Dify?",
    dataset_id="your-dataset-id"
)

六、构建 AI 应用

6.1 创建聊天助手

#mermaid-svg-g6cJB7BLkE5TkiFk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-g6cJB7BLkE5TkiFk .error-icon{fill:#552222;}#mermaid-svg-g6cJB7BLkE5TkiFk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-g6cJB7BLkE5TkiFk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-g6cJB7BLkE5TkiFk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-g6cJB7BLkE5TkiFk .marker.cross{stroke:#333333;}#mermaid-svg-g6cJB7BLkE5TkiFk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-g6cJB7BLkE5TkiFk p{margin:0;}#mermaid-svg-g6cJB7BLkE5TkiFk .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-g6cJB7BLkE5TkiFk .cluster-label text{fill:#333;}#mermaid-svg-g6cJB7BLkE5TkiFk .cluster-label span{color:#333;}#mermaid-svg-g6cJB7BLkE5TkiFk .cluster-label span p{background-color:transparent;}#mermaid-svg-g6cJB7BLkE5TkiFk .label text,#mermaid-svg-g6cJB7BLkE5TkiFk span{fill:#333;color:#333;}#mermaid-svg-g6cJB7BLkE5TkiFk .node rect,#mermaid-svg-g6cJB7BLkE5TkiFk .node circle,#mermaid-svg-g6cJB7BLkE5TkiFk .node ellipse,#mermaid-svg-g6cJB7BLkE5TkiFk .node polygon,#mermaid-svg-g6cJB7BLkE5TkiFk .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-g6cJB7BLkE5TkiFk .rough-node .label text,#mermaid-svg-g6cJB7BLkE5TkiFk .node .label text,#mermaid-svg-g6cJB7BLkE5TkiFk .image-shape .label,#mermaid-svg-g6cJB7BLkE5TkiFk .icon-shape .label{text-anchor:middle;}#mermaid-svg-g6cJB7BLkE5TkiFk .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-g6cJB7BLkE5TkiFk .rough-node .label,#mermaid-svg-g6cJB7BLkE5TkiFk .node .label,#mermaid-svg-g6cJB7BLkE5TkiFk .image-shape .label,#mermaid-svg-g6cJB7BLkE5TkiFk .icon-shape .label{text-align:center;}#mermaid-svg-g6cJB7BLkE5TkiFk .node.clickable{cursor:pointer;}#mermaid-svg-g6cJB7BLkE5TkiFk .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-g6cJB7BLkE5TkiFk .arrowheadPath{fill:#333333;}#mermaid-svg-g6cJB7BLkE5TkiFk .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-g6cJB7BLkE5TkiFk .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-g6cJB7BLkE5TkiFk .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-g6cJB7BLkE5TkiFk .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-g6cJB7BLkE5TkiFk .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-g6cJB7BLkE5TkiFk .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-g6cJB7BLkE5TkiFk .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-g6cJB7BLkE5TkiFk .cluster text{fill:#333;}#mermaid-svg-g6cJB7BLkE5TkiFk .cluster span{color:#333;}#mermaid-svg-g6cJB7BLkE5TkiFk div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-g6cJB7BLkE5TkiFk .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-g6cJB7BLkE5TkiFk rect.text{fill:none;stroke-width:0;}#mermaid-svg-g6cJB7BLkE5TkiFk .icon-shape,#mermaid-svg-g6cJB7BLkE5TkiFk .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-g6cJB7BLkE5TkiFk .icon-shape p,#mermaid-svg-g6cJB7BLkE5TkiFk .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-g6cJB7BLkE5TkiFk .icon-shape .label rect,#mermaid-svg-g6cJB7BLkE5TkiFk .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-g6cJB7BLkE5TkiFk .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-g6cJB7BLkE5TkiFk .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-g6cJB7BLkE5TkiFk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建工作流
添加 LLM 节点
配置 Prompt
添加知识库
测试发布
选择 deepseek-coder:6.7b
系统提示词
关联知识库

步骤:

  1. 创建应用 :进入 应用 → 创建应用 → 聊天助手

  2. 配置提示词

markdown 复制代码
# 系统提示词模板

你是一个技术文档助手,专门回答关于 {domain} 的问题。

## 角色设定
- 你具有深厚的技术背景
- 回答要准确、详细、易懂
- 如果不确定,不要编造答案

## 回答规范
1. 先给出简洁的结论
2. 再提供详细的解释
3. 必要时提供代码示例
4. 引用知识库中的文档

## 注意事项
- 使用中文回答
- 代码要标注语言
- 复杂概念要用比喻
  1. 关联知识库
    • 上下文 → 添加知识库 中选择已创建的知识库
    • 配置检索参数:
yaml 复制代码
检索模式: hybrid  # 混合检索(向量 + 关键词)
Top K: 5
Score Threshold: 0.5
  1. 测试与发布
    • 在右侧对话框中测试效果
    • 满意后点击 发布

6.2 创建工作流

#mermaid-svg-Cq5oGt1KBq7WwEhh{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Cq5oGt1KBq7WwEhh .error-icon{fill:#552222;}#mermaid-svg-Cq5oGt1KBq7WwEhh .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Cq5oGt1KBq7WwEhh .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .marker.cross{stroke:#333333;}#mermaid-svg-Cq5oGt1KBq7WwEhh svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Cq5oGt1KBq7WwEhh p{margin:0;}#mermaid-svg-Cq5oGt1KBq7WwEhh .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .cluster-label text{fill:#333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .cluster-label span{color:#333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .cluster-label span p{background-color:transparent;}#mermaid-svg-Cq5oGt1KBq7WwEhh .label text,#mermaid-svg-Cq5oGt1KBq7WwEhh span{fill:#333;color:#333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .node rect,#mermaid-svg-Cq5oGt1KBq7WwEhh .node circle,#mermaid-svg-Cq5oGt1KBq7WwEhh .node ellipse,#mermaid-svg-Cq5oGt1KBq7WwEhh .node polygon,#mermaid-svg-Cq5oGt1KBq7WwEhh .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Cq5oGt1KBq7WwEhh .rough-node .label text,#mermaid-svg-Cq5oGt1KBq7WwEhh .node .label text,#mermaid-svg-Cq5oGt1KBq7WwEhh .image-shape .label,#mermaid-svg-Cq5oGt1KBq7WwEhh .icon-shape .label{text-anchor:middle;}#mermaid-svg-Cq5oGt1KBq7WwEhh .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Cq5oGt1KBq7WwEhh .rough-node .label,#mermaid-svg-Cq5oGt1KBq7WwEhh .node .label,#mermaid-svg-Cq5oGt1KBq7WwEhh .image-shape .label,#mermaid-svg-Cq5oGt1KBq7WwEhh .icon-shape .label{text-align:center;}#mermaid-svg-Cq5oGt1KBq7WwEhh .node.clickable{cursor:pointer;}#mermaid-svg-Cq5oGt1KBq7WwEhh .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .arrowheadPath{fill:#333333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Cq5oGt1KBq7WwEhh .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Cq5oGt1KBq7WwEhh .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Cq5oGt1KBq7WwEhh .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Cq5oGt1KBq7WwEhh .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Cq5oGt1KBq7WwEhh .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Cq5oGt1KBq7WwEhh .cluster text{fill:#333;}#mermaid-svg-Cq5oGt1KBq7WwEhh .cluster span{color:#333;}#mermaid-svg-Cq5oGt1KBq7WwEhh div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Cq5oGt1KBq7WwEhh .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Cq5oGt1KBq7WwEhh rect.text{fill:none;stroke-width:0;}#mermaid-svg-Cq5oGt1KBq7WwEhh .icon-shape,#mermaid-svg-Cq5oGt1KBq7WwEhh .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Cq5oGt1KBq7WwEhh .icon-shape p,#mermaid-svg-Cq5oGt1KBq7WwEhh .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Cq5oGt1KBq7WwEhh .icon-shape .label rect,#mermaid-svg-Cq5oGt1KBq7WwEhh .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Cq5oGt1KBq7WwEhh .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Cq5oGt1KBq7WwEhh .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Cq5oGt1KBq7WwEhh :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 技术问题
闲聊
代码生成
开始
用户输入
意图识别
知识库检索
直接对话
代码助手
LLM 推理
输出结果

创建工作流应用:

  1. 创建应用应用 → 创建应用 → 工作流

  2. 添加节点

python 复制代码
# 节点 1:意图识别(LLM 节点)
INTENT_RECOGNITION_PROMPT = """
分析用户输入的意图,输出 JSON:

用户输入:{input}

输出格式:
{
    "intent": "tech_question | casual_chat | code_generation",
    "confidence": 0.0-1.0
}
"""

# 节点 2:知识库检索(知识库节点)
# 配置同上

# 节点 3:生成回答(LLM 节点)
ANSWER_GENERATION_PROMPT = """
基于以下上下文回答用户问题:

上下文:{context}
用户问题:{query}

要求:
1. 优先使用上下文中的信息
2. 如果上下文不足,可以基于你的知识回答
3. 标注信息来源
"""
  1. 连接节点:拖拽连接各节点

  2. 测试运行 :点击 预览 进行测试

  3. 发布 :点击 发布


七、API 集成

7.1 获取 API Key

python 复制代码
"""
获取 Dify API Key(通过界面)
"""
# 1. 进入应用
# 2. 点击「发布」→「访问 API」
# 3. 创建 API Key
# 4. 复制 API Key(格式:app-xxxxxxxx)

7.2 调用 API

python 复制代码
"""
调用 Dify API 进行对话
"""
import requests
from typing import 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.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
    
    def chat(
        self,
        query: str,
        conversation_id: str = None,
        user: str = "default-user"
    ) -> dict:
        """发送对话请求"""
        
        url = f"{self.base_url}/chat-messages"
        
        payload = {
            "inputs": {},
            "query": query,
            "response_mode": "blocking",  # blocking 或 streaming
            "user": user
        }
        
        if conversation_id:
            payload["conversation_id"] = conversation_id
        
        response = requests.post(
            url,
            json=payload,
            headers=self.headers
        )
        
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"API 调用失败: {response.text}")
    
    def chat_stream(
        self,
        query: str,
        user: str = "default-user"
    ) -> Generator[str, None, None]:
        """流式对话(SSE)"""
        
        url = f"{self.base_url}/chat-messages"
        
        payload = {
            "inputs": {},
            "query": query,
            "response_mode": "streaming",  # 流式模式
            "user": user
        }
        
        response = requests.post(
            url,
            json=payload,
            headers=self.headers,
            stream=True
        )
        
        for line in response.iter_lines():
            if line:
                line = line.decode('utf-8')
                if line.startswith('data: '):
                    data = line[6:]
                    if data != '[DONE]':
                        import json
                        chunk = json.loads(data)
                        yield chunk['answer']
    
    def get_conversations(self, user: str = "default-user") -> list:
        """获取会话列表"""
        
        url = f"{self.base_url}/conversations"
        params = {"user": user, "limit": 100}
        
        response = requests.get(
            url,
            params=params,
            headers=self.headers
        )
        
        if response.status_code == 200:
            return response.json()["data"]
        else:
            return []

# 使用示例
client = DifyClient(
    base_url="http://your-server-ip/v1",
    api_key="app-xxxxxxxxxxxxxxxx"
)

# 阻塞式调用
response = client.chat("如何在 Ubuntu 上安装 Docker?")
print(response["answer"])

# 流式调用
for chunk in client.chat_stream("写一个 Python 快速排序"):
    print(chunk, end="", flush=True)

7.3 集成到现有系统

python 复制代码
"""
将 Dify 集成到 FastAPI 应用
"""
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()
dify_client = DifyClient(
    base_url="http://localhost/v1",
    api_key="app-xxxxxxxx"
)

class ChatRequest(BaseModel):
    query: str
    user_id: str = "default"

@app.post("/api/chat")
async def chat(request: ChatRequest):
    """对话接口"""
    try:
        response = dify_client.chat(
            query=request.query,
            user=request.user_id
        )
        return {
            "success": True,
            "data": {
                "answer": response["answer"],
                "conversation_id": response["conversation_id"]
            }
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/api/conversations/{user_id}")
async def get_conversations(user_id: str):
    """获取会话列表"""
    conversations = dify_client.get_conversations(user=user_id)
    return {"success": True, "data": conversations}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

八、性能优化

8.1 Ollama 性能优化

bash 复制代码
# 1. 启用 GPU 加速(最关键)
# 确保 Ollama 能识别到 GPU
ollama run deepseek-coder:6.7b "测试"
# 看到 "gpu layers" 说明启用成功

# 2. 调整并发数
# 编辑 Ollama 服务配置
sudo vim /etc/systemd/system/ollama.service
# 添加:
Environment="OLLAMA_MAX_LOADED_MODELS=2"
Environment="OLLAMA_NUM_PARALLEL=2"

# 3. 使用更快的量化级别
# Q4_K_M: 推荐(速度最快,效果略降)
# Q5_K_M: 平衡
# Q8_0: 最高精度(慢)
ollama pull deepseek-coder:6.7b-q4_K_M

# 4. 预热模型(避免首次加载慢)
# 在服务器启动时预先加载
ollama run deepseek-coder:6.7b "warmup" &

性能对比:

配置 首 Token 延迟 生成速度 显存占用
CPU 模式 5-10s 5-10 tok/s 0GB
GPU (Q4) 0.5-1s 30-50 tok/s 8GB
GPU (Q8) 0.5-1s 20-30 tok/s 12GB
GPU (FP16) 0.3-0.5s 15-25 tok/s 24GB

8.2 Dify 性能优化

yaml 复制代码
# docker-compose.yml 性能优化

# 1. 增加 Worker 并发数
services:
  api:
    environment:
      # 工作流并发数
      - MAX_WORKFLOW_RUNS=20
      # Celery 并发数
      - CELERY_WORKER_PREFETCH_MULTIPLIER=10
  
  worker:
    deploy:
      replicas: 3  # 增加 Worker 实例数
    environment:
      - CELERY_WORKER_CONCURRENCY=10

# 2. 配置 Redis 缓存
  redis:
    command: redis-server --maxmemory 2gb --maxmemory-policy allkeys-lru

# 3. 使用外部向量数据库(生产环境)
  weaviate:
    profiles:
      - local  # 默认不启动,使用外部

九、常见问题排查

9.1 Ollama 问题

问题 原因 解决方案
无法启动 端口占用 sudo lsof -i :11434 然后 kill
模型加载慢 首次下载 等待下载完成,后续会快
GPU 未启用 驱动问题 运行 nvidia-smi 检查
显存不足 模型太大 换用更小的模型或 Q4 量化
响应慢 并发过高 降低 OLLAMA_MAX_LOADED_MODELS

调试命令:

bash 复制代码
# 查看 Ollama 日志
journalctl -u ollama -f

# 测试 API
curl http://localhost:11434/api/tags

# 查看模型信息
ollama show deepseek-coder:6.7b

# 性能测试
time ollama run deepseek-coder:6.7b "写一个快速排序"

9.2 Dify 问题

问题 原因 解决方案
无法访问 Web 端口占用 docker ps 查看端口映射
Ollama 连接失败 网络不通 检查 OLLAMA_API_BASE_URL
知识库检索慢 向量维度高 换用更快的 Embedding 模型
Worker 报错 依赖缺失 检查 Docker 日志
文件上传失败 存储权限 检查 volumes/storage 权限

调试命令:

bash 复制代码
# 查看 Dify 日志
cd dify/docker
docker compose logs -f api
docker compose logs -f worker

# 进入容器调试
docker compose exec api bash

# 检查网络连接
docker compose exec api curl http://host.docker.internal:11434/api/tags

# 重启服务
docker compose restart

十、生产环境部署

10.1 安全配置

#mermaid-svg-muveVaLHFB6iH8uZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-muveVaLHFB6iH8uZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-muveVaLHFB6iH8uZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-muveVaLHFB6iH8uZ .error-icon{fill:#552222;}#mermaid-svg-muveVaLHFB6iH8uZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-muveVaLHFB6iH8uZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-muveVaLHFB6iH8uZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-muveVaLHFB6iH8uZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-muveVaLHFB6iH8uZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-muveVaLHFB6iH8uZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-muveVaLHFB6iH8uZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-muveVaLHFB6iH8uZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-muveVaLHFB6iH8uZ .marker.cross{stroke:#333333;}#mermaid-svg-muveVaLHFB6iH8uZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-muveVaLHFB6iH8uZ p{margin:0;}#mermaid-svg-muveVaLHFB6iH8uZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-muveVaLHFB6iH8uZ .cluster-label text{fill:#333;}#mermaid-svg-muveVaLHFB6iH8uZ .cluster-label span{color:#333;}#mermaid-svg-muveVaLHFB6iH8uZ .cluster-label span p{background-color:transparent;}#mermaid-svg-muveVaLHFB6iH8uZ .label text,#mermaid-svg-muveVaLHFB6iH8uZ span{fill:#333;color:#333;}#mermaid-svg-muveVaLHFB6iH8uZ .node rect,#mermaid-svg-muveVaLHFB6iH8uZ .node circle,#mermaid-svg-muveVaLHFB6iH8uZ .node ellipse,#mermaid-svg-muveVaLHFB6iH8uZ .node polygon,#mermaid-svg-muveVaLHFB6iH8uZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-muveVaLHFB6iH8uZ .rough-node .label text,#mermaid-svg-muveVaLHFB6iH8uZ .node .label text,#mermaid-svg-muveVaLHFB6iH8uZ .image-shape .label,#mermaid-svg-muveVaLHFB6iH8uZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-muveVaLHFB6iH8uZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-muveVaLHFB6iH8uZ .rough-node .label,#mermaid-svg-muveVaLHFB6iH8uZ .node .label,#mermaid-svg-muveVaLHFB6iH8uZ .image-shape .label,#mermaid-svg-muveVaLHFB6iH8uZ .icon-shape .label{text-align:center;}#mermaid-svg-muveVaLHFB6iH8uZ .node.clickable{cursor:pointer;}#mermaid-svg-muveVaLHFB6iH8uZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-muveVaLHFB6iH8uZ .arrowheadPath{fill:#333333;}#mermaid-svg-muveVaLHFB6iH8uZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-muveVaLHFB6iH8uZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-muveVaLHFB6iH8uZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-muveVaLHFB6iH8uZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-muveVaLHFB6iH8uZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-muveVaLHFB6iH8uZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-muveVaLHFB6iH8uZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-muveVaLHFB6iH8uZ .cluster text{fill:#333;}#mermaid-svg-muveVaLHFB6iH8uZ .cluster span{color:#333;}#mermaid-svg-muveVaLHFB6iH8uZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-muveVaLHFB6iH8uZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-muveVaLHFB6iH8uZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-muveVaLHFB6iH8uZ .icon-shape,#mermaid-svg-muveVaLHFB6iH8uZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-muveVaLHFB6iH8uZ .icon-shape p,#mermaid-svg-muveVaLHFB6iH8uZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-muveVaLHFB6iH8uZ .icon-shape .label rect,#mermaid-svg-muveVaLHFB6iH8uZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-muveVaLHFB6iH8uZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-muveVaLHFB6iH8uZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-muveVaLHFB6iH8uZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 互联网
Nginx 反向代理
Dify Web
Dify API
内网
Ollama
Weaviate
HTTPS

SSL 证书
认证

JWT Token

Nginx 配置:

nginx 复制代码
# /etc/nginx/sites-available/dify
server {
    listen 80;
    server_name your-domain.com;
    
    # 重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com;
    
    # SSL 证书
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    # 安全头
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    
    # Dify Web
    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;
    }
    
    # Dify API
    location /api {
        proxy_pass http://localhost:5001;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
    # 限制上传大小
    client_max_body_size 50M;
}

10.2 监控与告警

python 复制代码
"""
简单的监控脚本
"""
import requests
import time
from datetime import datetime

def monitor_dify():
    """监控 Dify 服务状态"""
    
    services = {
        "Dify Web": "http://localhost",
        "Dify API": "http://localhost:5001/health",
        "Ollama": "http://localhost:11434/api/tags",
        "Weaviate": "http://localhost:8080/v1/meta"
    }
    
    while True:
        print(f"\n{'='*50}")
        print(f"监控时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        print(f"{'='*50}\n")
        
        for name, url in services.items():
            try:
                start = time.time()
                response = requests.get(url, timeout=5)
                latency = (time.time() - start) * 1000
                
                if response.status_code == 200:
                    print(f"✅ {name}: 正常 ({latency:.0f}ms)")
                else:
                    print(f"⚠️  {name}: 异常 (状态码: {response.status_code})")
            except Exception as e:
                print(f"❌ {name}: 无法访问 ({e})")
        
        # 每 60 秒检查一次
        time.sleep(60)

if __name__ == "__main__":
    monitor_dify()

十一、总结

#mermaid-svg-6200mZbizdZj2xvR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6200mZbizdZj2xvR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6200mZbizdZj2xvR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6200mZbizdZj2xvR .error-icon{fill:#552222;}#mermaid-svg-6200mZbizdZj2xvR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6200mZbizdZj2xvR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6200mZbizdZj2xvR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6200mZbizdZj2xvR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6200mZbizdZj2xvR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6200mZbizdZj2xvR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6200mZbizdZj2xvR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6200mZbizdZj2xvR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6200mZbizdZj2xvR .marker.cross{stroke:#333333;}#mermaid-svg-6200mZbizdZj2xvR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6200mZbizdZj2xvR p{margin:0;}#mermaid-svg-6200mZbizdZj2xvR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6200mZbizdZj2xvR .cluster-label text{fill:#333;}#mermaid-svg-6200mZbizdZj2xvR .cluster-label span{color:#333;}#mermaid-svg-6200mZbizdZj2xvR .cluster-label span p{background-color:transparent;}#mermaid-svg-6200mZbizdZj2xvR .label text,#mermaid-svg-6200mZbizdZj2xvR span{fill:#333;color:#333;}#mermaid-svg-6200mZbizdZj2xvR .node rect,#mermaid-svg-6200mZbizdZj2xvR .node circle,#mermaid-svg-6200mZbizdZj2xvR .node ellipse,#mermaid-svg-6200mZbizdZj2xvR .node polygon,#mermaid-svg-6200mZbizdZj2xvR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6200mZbizdZj2xvR .rough-node .label text,#mermaid-svg-6200mZbizdZj2xvR .node .label text,#mermaid-svg-6200mZbizdZj2xvR .image-shape .label,#mermaid-svg-6200mZbizdZj2xvR .icon-shape .label{text-anchor:middle;}#mermaid-svg-6200mZbizdZj2xvR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6200mZbizdZj2xvR .rough-node .label,#mermaid-svg-6200mZbizdZj2xvR .node .label,#mermaid-svg-6200mZbizdZj2xvR .image-shape .label,#mermaid-svg-6200mZbizdZj2xvR .icon-shape .label{text-align:center;}#mermaid-svg-6200mZbizdZj2xvR .node.clickable{cursor:pointer;}#mermaid-svg-6200mZbizdZj2xvR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6200mZbizdZj2xvR .arrowheadPath{fill:#333333;}#mermaid-svg-6200mZbizdZj2xvR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6200mZbizdZj2xvR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6200mZbizdZj2xvR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6200mZbizdZj2xvR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6200mZbizdZj2xvR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6200mZbizdZj2xvR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6200mZbizdZj2xvR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6200mZbizdZj2xvR .cluster text{fill:#333;}#mermaid-svg-6200mZbizdZj2xvR .cluster span{color:#333;}#mermaid-svg-6200mZbizdZj2xvR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6200mZbizdZj2xvR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6200mZbizdZj2xvR rect.text{fill:none;stroke-width:0;}#mermaid-svg-6200mZbizdZj2xvR .icon-shape,#mermaid-svg-6200mZbizdZj2xvR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6200mZbizdZj2xvR .icon-shape p,#mermaid-svg-6200mZbizdZj2xvR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6200mZbizdZj2xvR .icon-shape .label rect,#mermaid-svg-6200mZbizdZj2xvR .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6200mZbizdZj2xvR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6200mZbizdZj2xvR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6200mZbizdZj2xvR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 🎯 Dify + Ollama + DeepSeek

本地部署总结
✅ 优势
⚠️ 注意事项
🚀 下一步
数据完全本地
零 API 成本
完全可定制
离线可用
需要 GPU 资源
模型效果略逊商用
运维成本
添加更多模型
优化知识库
集成到业务系统
监控与告警

核心要点

要点 说明
部署难度 ⭐⭐⭐ (中等)
硬件成本 需要 GPU,约 2-5 万元
运维成本 需要专人维护
适用场景 数据敏感、成本敏感、定制需求
推荐指数 ⭐⭐⭐⭐ (企业内网部署推荐)

本文基于 Dify 0.6+、Ollama 0.1.31+、DeepSeek-Coder 6.7B 编写。不同版本配置可能略有差异,建议参考官方文档。如有问题欢迎评论区讨论!

相关推荐
企服AI产品测评局2 小时前
2026年Agent元年!深度解析实在Agent未来路线图:从自动化工具到全能数字员工的跃迁
运维·人工智能·ai·chatgpt·自动化
weixin_468466852 小时前
UNet 模型结构从零搭建与实战解析
人工智能·深度学习·算法·机器学习·ai·unet
小二·2 小时前
OpenAI API 实战指南
ai·openai·api
AI英德西牛仔2 小时前
Claude 导出 pdf 颜色不一样怎么办,选用 AI 导出鸭优化格式转换,多维度落地修正 PDF 色彩失真问题
javascript·人工智能·ai·chatgpt·pdf·deepseek·ai导出鸭
海绵宝宝de派小星2 小时前
MCP与A2A协议深度解析:Agent时代的“TCP/IP“如何诞生
arm开发·网络协议·tcp/ip·ai
ZFSS2 小时前
VS Code + Serp MCP:让 Copilot 实时上网查询
人工智能·ai·ai作画·copilot·ai编程·ai写作
装不满的克莱因瓶3 小时前
基于 Python 进行二维空间线性可分数据单/多层感知器实战
人工智能·python·深度学习·神经网络·ai·卷积
金融RPA机器人丨实在智能3 小时前
最终决定选择实在Agent的关键因素通常是什么?
人工智能·ai
土星云SaturnCloud3 小时前
边缘计算赋能烟草行业数字化转型
服务器·人工智能·ai·边缘计算