前言
💡 痛点:想用 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 模型:
- 访问
http://your-server-ip - 注册管理员账号
- 进入 设置 → 模型供应商
- 选择 Ollama
- 填写配置:
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
本地模型
操作步骤:
- 进入 知识库 → 创建知识库
- 上传文档(支持 PDF、Word、Markdown、TXT)
- 配置分段策略:
python
# 分段策略配置(通过 API)
SEGMENT_CONFIG = {
"mode": "parent_child", # 父子分段(推荐)
"parent_splitter": {
"type": "paragraph", # 按段落拆分
"max_length": 1000 # 父块最大长度
},
"child_splitter": {
"type": "token", # 按 token 拆分
"max_length": 200 # 子块最大长度
},
"overlap": 50 # 重叠长度
}
- 选择 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
系统提示词
关联知识库
步骤:
-
创建应用 :进入 应用 → 创建应用 → 聊天助手
-
配置提示词:
markdown
# 系统提示词模板
你是一个技术文档助手,专门回答关于 {domain} 的问题。
## 角色设定
- 你具有深厚的技术背景
- 回答要准确、详细、易懂
- 如果不确定,不要编造答案
## 回答规范
1. 先给出简洁的结论
2. 再提供详细的解释
3. 必要时提供代码示例
4. 引用知识库中的文档
## 注意事项
- 使用中文回答
- 代码要标注语言
- 复杂概念要用比喻
- 关联知识库 :
- 在 上下文 → 添加知识库 中选择已创建的知识库
- 配置检索参数:
yaml
检索模式: hybrid # 混合检索(向量 + 关键词)
Top K: 5
Score Threshold: 0.5
- 测试与发布 :
- 在右侧对话框中测试效果
- 满意后点击 发布
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 推理
输出结果
创建工作流应用:
-
创建应用 :应用 → 创建应用 → 工作流
-
添加节点:
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. 标注信息来源
"""
-
连接节点:拖拽连接各节点
-
测试运行 :点击 预览 进行测试
-
发布 :点击 发布
七、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 编写。不同版本配置可能略有差异,建议参考官方文档。如有问题欢迎评论区讨论!