背景
自从dify升级到1.0以后,所有的工具和模型都改成了插件化,需要进行插件的安装。在手撕Dify1.x插件报错!从配置到网络到Pip镜像,一条龙排雷实录 已经指出了dify在线安装插件的各种问题。
在前面的几个版本中,dify是从https://raw.githubusercontent.com
扫描获取模型插件的信息。因为网络的问题,导致好多用户感觉卡顿。不过后面升级以后,这块已经没有了。
在最开始的时候配置文件中有一个MARKETPLACE_API_URL=https://marketplace.dify.ai
插件市场的配置的。这个配置允许我们自己搭建插件市场。
在dify的github仓库中,有两个项目dify-official-plugins
和dify-plugins
,存放的是官方和其他人发布的插件,理论上,我们都下载这两个目录,通过本地上传的方式都能安装上去。
但是插件安装的过程中收到机器、网络等原因,好多人安装插件超时,然后失败。
官方在在3月9日
的提交中增加了PLUGIN_PYTHON_ENV_INIT_TIMEOUT
和PLUGIN_MAX_EXECUTION_TIMEOUT
来增加python环境初始化超时时间和插件最大执行超时时间来解决。
但是有的插件安装的时候依赖一些python组件,需要通过pip
安装,默认pip
安装都是走的pip官方的。国内安装一直存在卡顿的问题。
在3月10日
的代码提交中,官方支持自定义pip安装镜像地址。解决了插件依赖网络的问题。
官方基本上一步一步的在解决国内安装插件的问题。
本地安装
我们打开https://marketplace.dify.ai/
插件市场,根据分类,找到自己想要安装的插件。
ps:在官方的两个仓库中查找,也可以的,但是没有分类。
比如我们拿ollama举例,在插件市场找到ollama,然后打开
1
标识的是插件开发商以及插件名称。在官方库里能找到对应的源码。- 点击
2
箭头指向的下载按钮。下载插件
下载以后是一个difypkg
文件。
在自己的dify应用中,点击插件,打开安装插件的本地插件,上传。
选择刚下载的插件。
选择完以后,就会提示安装或更新。
官方有个提示
可信源
安装插件,这块需注意下,不要随意安装别人分享的插件,上传到插件市场的插件,官方应该都会过一遍,要不然也不能叫可信源。
我们在官方的查看中可以查看,简单的一个ollama都需要安装依赖环境。如果一般内网都有自己的镜像源,替换下自己的镜像源,在dify的配置文件中改成自己的镜像源即可。
无网安装
有些用户说内网不能联网,没法安装,但是我想说的是,一般内网隔离,一般都会有一些自己的镜像源。如果内网环境不提供镜像源,那都是在耍流氓。
网上也有一个解决办法。在github上,有个哥们分享了一个项目https://github.com/junjiem/dify-plugin-repackaging
这个可以将dify的插件以及相关的依赖打包成离线的插件包。我先用deepseek-v3
帮我画一个流程图
从流程图上可以看到这个脚本,支持从dify market
、github
、local
这3个地方打包。
- 主要是将插件依赖的包,下载到
wheels
包中 - 然后打包
这个脚本在centos
中是可以直接运行的。可以看下面的代码。其他的环境需要改造下。
install_unzip(){
rpms=(`rpm -q unzip`)
if [ ${#rpms[@]} -ne 1 ]; then
echo "Installing unzip ..."
yum -y install unzip
if [ $? -ne 0 ]; then
echo "Install unzip failed."
exit 1
fi
fi
}
win11环境
我以win11
环境为示例演示下。
下载项目
git clone https://github.com/junjiem/dify-plugin-repackaging.git
脚本生成
首先我让deepseek-v3
模型帮我生成一个兼容win11的脚本。
<#
.SYNOPSIS
Dify 插件下载和重新打包工具(Windows PowerShell 版本)
.DESCRIPTION
提供三种方式获取和重新打包 Dify 插件:
1. 从 Dify 官方市场下载
2. 从 GitHub 仓库下载
3. 使用本地已有的插件包
.NOTES
作者: yxkong
版本: 1.0
#>
# 全局变量
$GITHUB_API_URL = "https://github.com"
$MARKETPLACE_API_URL = "https://marketplace.dify.ai"
$PIP_MIRROR_URL = "https://mirrors.aliyun.com/pypi/simple"
# 获取当前脚本所在目录
$CURR_DIR = $PSScriptRoot
if (-not $CURR_DIR) {
$CURR_DIR = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
}
# 主函数
function Main {
param (
[string]$Command,
[string[]]$Arguments
)
switch ($Command.ToLower()) {
"market" {
Market @Arguments
}
"github" {
GitHub @Arguments
}
"local" {
Local @Arguments
}
default {
ShowHelp
exit 1
}
}
}
# 显示帮助信息
function ShowHelp {
Write-Host @"
用法: .\$($MyInvocation.MyCommand.Name) {market|github|local} [参数]
命令:
market 从 Dify 官方市场下载插件
示例: .\$($MyInvocation.MyCommand.Name) market junjiem mcp_sse 0.0.1
github 从 GitHub 仓库下载插件
示例: .\$($MyInvocation.MyCommand.Name) github junjiem/dify-plugin-tools-dbquery v0.0.2 db_query.difypkg
local 使用本地已有的插件包
示例: .\$($MyInvocation.MyCommand.Name) local ./db_query.difypkg
"@
}
# 从 Dify 市场下载
function Market {
param (
[string]$pluginAuthor,
[string]$pluginName,
[string]$pluginVersion
)
if (-not $pluginAuthor -or -not $pluginName -or -not $pluginVersion) {
Write-Host "参数错误!用法: .\$($MyInvocation.MyCommand.Name) market [插件作者] [插件名称] [插件版本]"
exit 1
}
Write-Host "从 Dify 市场下载插件..."
$pluginPackagePath = Join-Path $CURR_DIR "${pluginAuthor}-${pluginName}_${pluginVersion}.difypkg"
$pluginDownloadUrl = "${MARKETPLACE_API_URL}/api/v1/plugins/${pluginAuthor}/${pluginName}/${pluginVersion}/download"
try {
Write-Host "正在下载 ${pluginDownloadUrl} ..."
Invoke-WebRequest -Uri $pluginDownloadUrl -OutFile $pluginPackagePath -UseBasicParsing
Write-Host "下载成功。"
Repackage $pluginPackagePath
}
catch {
Write-Host "下载失败: $_"
exit 1
}
}
# 从 GitHub 下载
function GitHub {
param (
[string]$repo,
[string]$releaseTitle,
[string]$assetsName
)
if (-not $repo -or -not $releaseTitle -or -not $assetsName) {
Write-Host "参数错误!用法: .\$($MyInvocation.MyCommand.Name) github [GitHub 仓库] [发布标题] [资源文件名]"
exit 1
}
Write-Host "从 GitHub 下载插件..."
if (-not $repo.StartsWith($GITHUB_API_URL)) {
$repo = "${GITHUB_API_URL}/${repo}"
}
$pluginName = $assetsName -replace '\.difypkg$', ''
$pluginPackagePath = Join-Path $CURR_DIR "${pluginName}-${releaseTitle}.difypkg"
$pluginDownloadUrl = "${repo}/releases/download/${releaseTitle}/${assetsName}"
try {
Write-Host "正在下载 ${pluginDownloadUrl} ..."
Invoke-WebRequest -Uri $pluginDownloadUrl -OutFile $pluginPackagePath -UseBasicParsing
Write-Host "下载成功。"
Repackage $pluginPackagePath
}
catch {
Write-Host "下载失败: $_"
exit 1
}
}
# 使用本地插件包
function Local {
param (
[string]$packagePath
)
if (-not $packagePath) {
Write-Host "参数错误!用法: .\$($MyInvocation.MyCommand.Name) local [插件包路径]"
exit 1
}
$fullPath = Resolve-Path $packagePath -ErrorAction SilentlyContinue
if (-not $fullPath) {
Write-Host "文件不存在: $packagePath"
exit 1
}
Repackage $fullPath.Path
}
# 重新打包插件
function Repackage {
param (
[string]$packagePath
)
$packageNameWithExt = [System.IO.Path]::GetFileName($packagePath)
$packageName = [System.IO.Path]::GetFileNameWithoutExtension($packagePath)
$extractDir = Join-Path $CURR_DIR $packageName
Write-Host "解压中..."
try {
# 确保解压目录存在
if (Test-Path $extractDir) {
Remove-Item $extractDir -Recurse -Force
}
New-Item -ItemType Directory -Path $extractDir | Out-Null
# 使用内置解压功能
Expand-Archive -Path $packagePath -DestinationPath $extractDir -Force
Write-Host "解压成功。"
}
catch {
Write-Host "解压失败: $_"
exit 1
}
Write-Host "重新打包中..."
try {
# 进入解压目录
Push-Location $extractDir
# 创建 wheels 目录
$wheelsDir = Join-Path $extractDir "wheels"
if (-not (Test-Path $wheelsDir)) {
New-Item -ItemType Directory -Path $wheelsDir | Out-Null
}
# 下载依赖
if (Test-Path "requirements.txt") {
Write-Host "正在下载依赖..."
python -m pip download -r requirements.txt -d $wheelsDir --index-url $PIP_MIRROR_URL
# 修改 requirements.txt
$requirementsContent = "--no-index --find-links=./wheels/`r`n" + (Get-Content "requirements.txt" -Raw)
$requirementsContent | Set-Content "requirements.txt"
}
# 更新 .difyignore 文件
if (Test-Path ".difyignore") {
$difyIgnoreContent = Get-Content ".difyignore" | Where-Object { $_ -notmatch "^wheels/" }
$difyIgnoreContent | Set-Content ".difyignore"
}
# 返回原始目录
Pop-Location
# 检查打包工具是否存在
$packageTool = Join-Path $CURR_DIR "dify-plugin-windows-amd64-5g.exe"
if (-not (Test-Path $packageTool)) {
Write-Host "错误: 找不到打包工具 $packageTool"
exit 1
}
# 执行打包
$outputPackage = Join-Path $CURR_DIR "${packageName}-offline.difypkg"
& $packageTool plugin package $extractDir -o $outputPackage
Write-Host "重新打包成功。输出文件: $outputPackage"
}
catch {
Write-Host "重新打包失败: $_"
exit 1
}
finally {
Pop-Location -ErrorAction SilentlyContinue
}
}
# 入口点
if ($args.Count -eq 0) {
ShowHelp
exit 1
}
Main $args[0] $args[1..($args.Count-1)]
- 保存为
dify-plugin-helper.ps1
文件 - 在 PowerShell 中运行(可能需要先执行
Set-ExecutionPolicy RemoteSigned
) - 其他环境类似,直接让deepseek生成对应平台的脚步即可
命令执行
我们在插件市场取这上图的3个参数。然后执行下面的命令
#示例
.\dify-plugin-helper.ps1 market 参数1 参数2 参数3
# 具体命令
.\dify-plugin-helper.ps1 market langgenius ollama 0.0.5
- 建议直接从
market
下载,如果想从github或local下载,自行实验
从上面的日志中我们可以看出,在下载相关依赖。
对应的目录中也有对应的包了。
我们可以看到相关的依赖包都是对应环境的依赖包。到这一步,可以将这个包目录复制到容器中,进行手动执行了。
因为我对打包这个没研究,最后一步报错了。项目中dify-plugin-linux-amd64-5g
是一个二进制文件,我先不研究这个怎么来的。我在官方仓库里搜索了下,也有这个打包脚本。都和操纵系统挂钩。
打包以后,会打包一个带有相关依赖的离线包,我们直接上传安装即可。
注意事项
需要注意的是,由于自己打的包,没有经过dify官方的审核,所以需要修改下配置。打包以后依赖的相关包比较多,附件会比较大,也需要修改下配置(ollama打包以后十几mb)。
- 在 .env 配置文件将
FORCE_VERIFYING_SIGNATURE
改为false
,Dify 平台将允许安装所有未在 Dify Marketplace 上架(审核)的插件。 - 在 .env 配置文件将
PLUGIN_MAX_PACKAGE_SIZE
增大为524288000
,Dify 平台将允许安装 500M 大小以内的插件。 - 在 .env 配置文件将
NGINX_CLIENT_MAX_BODY_SIZE
增大为500M
,Nginx客户端将允许上传 500M 大小以内的内容。
配置修改以后,不生效,需要先
docker compose down
然后docker compose up -d
在打包的时候,最好找一台和内网环境类似的操作系统,特别是
系统架构
和python版本
,有些依赖是适配到python版本的。
相关资料
deepseek相关资料
https://pan.quark.cn/s/faa9d30fc2bd
https://pan.baidu.com/s/10vnv9jJJCG-KKY8f_e-wLw?pwd=jxxv
群友分享的一些dify工作流
https://pan.baidu.com/s/1aNne8dLz6YxoKhCwJclV5g?pwd=p4xc
https://pan.quark.cn/s/243a0de062e5
系列文档:
DeepSeek本地部署相关
ollama+deepseek本地部署
局域网或断网环境下安装DeepSeek
vlllm部署deepseek基准测试
DeepSeek个人应用
不要浪费deepseek的算力了,DeepSeek提示词库指南
服务器繁忙,电脑配置太低,别急deepseek满血版来了
DeepSeek+本地知识库:真的太香了(修订版)
DeepSeek+本地知识库:真是太香了(企业方案)
deepseek一键生成小红书爆款内容,排版下载全自动!睡后收入不是梦
最轻量级的deepseek应用,支持联网和知识库
当我把公众号作为知识库塞进了智能体后
个人神级知识库DeepSeek+ima 个人学习神器
dify相关
DeepSeek+dify 本地知识库:真的太香了
Deepseek+Dify本地知识库相关问题汇总
dify的sandbox机制,安全隔离限制
DeepSeek+dify 本地知识库:高级应用Agent+工作流
DeepSeek+dify知识库,查询数据库的两种方式(api+直连)
DeepSeek+dify 工作流应用,自然语言查询数据库信息并展示
聊聊dify权限验证的三种方案及实现
dify1.0.0版本升级及新功能预览
Dify 1.1.0史诗级更新!新增"灵魂功能"元数据,实测竟藏致命Bug?手把手教你避坑
【避坑血泪史】80次调试!我用Dify爬虫搭建个人知识库全记录
手撕Dify1.x插件报错!从配置到网络到Pip镜像,一条龙排雷实录
dify1.2.0升级,全新循环节点优化,长文写作案例
ragflow相关
DeepSeek+ragflow构建企业知识库:突然觉的dify不香了(1)
DeepSeek+ragflow构建企业知识库之工作流,突然觉的dify又香了
DeepSeek+ragflow构建企业知识库:高级应用篇,越折腾越觉得ragflow好玩
RAGFlow爬虫组件使用及ragflow vs dify 组件设计对比
从8550秒到608秒!RAGFlow最新版本让知识图谱生成效率狂飙,终于不用通宵等结果了
以为发现的ragflow的宝藏接口,其实是一个天坑、Chrome/Selenium版本地狱
NLTK三重降噪内幕!RAGFlow检索强悍竟是靠这三板斧
从代码逆向RAGFlow架构:藏在18张表里的AI知识库设计哲学
解剖RAGFlow!全网最硬核源码架构解析
扣子(coze)
AI开发新选择:扣子平台功能详解与智能体拆解
AI开发新选择:扣子平台工作流基础节点介绍
模型微调相关
📢【三连好运 福利拉满】📢
🌟 若本日推送有收获:
👍 点赞 → 小手一抖,bug没有
📌 在看 → 一点扩散,知识璀璨
📥 收藏 → 代码永驻,防止迷路
📤 分享 → 传递战友,功德+999
🔔 关注 → 关注5ycode,追更不迷路,干货永同步
💬 若有槽点想输出:
👉 评论区已铺好红毯,等你来战!