ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Mac上搭建Dify+DeepSeek本地AI工作流实战指南

Mac上搭建Dify+DeepSeek本地AI工作流实战指南 我前后在Mac上折腾了好几个月的本地AI工作流中间踩过不少坑也重装过好几遍Dify最后总算把一套能日常用的组合跑通了。这套组合的核心就两个东西Dify做应用编排和知识库管理DeepSeek做底层推理Mac做本地载体三个环节只要串起来基本就是一个能落地的私有AI助手。这篇文章就把我实际搭建的过程、踩过的坑、以及一些关键参数怎么调完整写出来给想在Mac上自己跑一套AI工作流的朋友做个参考。先说清楚这套方案解决了什么问题。Dify是一个开源的大模型应用开发平台支持工作流编排、知识库RAG、Agent、插件等能力相当于一个可视化的LLM应用“组装车间”。DeepSeek则是国内开源的大语言模型有云端API也可以本地部署。两者结合等于把模型的推理能力通过Dify的流程编排变成真正能用的业务工具比如知识库问答、报告生成、专利辅助撰写、合同审核、代码分析等等。整条链路都跑在本地Mac上数据不出机器可控性高自由度和隐私性都比直接用在线SaaS好很多。这篇文章适合三类人看一类是想在Mac上部署Dify但卡在网络、Docker环境的初学者一类是已经跑起来但不知道如何把DeepSeek接进去、工作流不会搭的人还有一类是需要一个私有知识库问答系统但不想买服务器、不想上云的人。下面按我实际操作的顺序来写从环境准备到最终跑通一个完整工作流每一步都会说明为什么这么操作。1. 开工前先把底子打好方案选型与Mac环境准备1.1 为什么选Dify配DeepSeek而不是其他组合在确定这套方案之前我对比过几类工具直接写Python调用API、用LangChain自己搭链、用FastGPT还有用Dify。直接写代码最灵活但开发成本高LangChain灵活性高但调试链路的复杂度也高FastGPT在某些场景体验不错但社区生态和模型接入方面没有Dify顺滑。最终选择Dify主要看中三点第一可视化工作流编排拖拽节点就能搭一个Agent应用后续改逻辑不用改代码第二内置完整的RAG知识库能力从文档解析、分段、向量化到检索都帮你做了第三模型供应商接入做得非常规整DeepSeek这类模型只需要填Key就能用也可以对接Ollama本地模型。DeepSeek作为模型层性价比是核心考量。云端API的定价相比其他主流模型要低不少而开源权重模型可以用Ollama等工具跑在本地完全离线使用。我日常会把不敏感、需要高质量长文本生成的任务走API调用把涉及内部资料的问答走本地模型两条路都在Dify里配置好按场景切换非常灵活。1.2 Mac需要什么配置才能扛住这套链路Dify本体是一组Docker容器包括API服务、Worker、Web前端、PostgreSQL、Redis、Weaviate或Qdrant向量库等。如果只跑Dify加云端APIM1芯片8GB内存的MacBook Air其实勉强能跑但会很吃力建议至少16GB内存。如果还要在本地跑DeepSeek模型那内存就是最大的瓶颈32GB起步比较舒服。我实测的环境是一台M1 Pro 16GB内存的MacBook Pro日常跑Dify全套容器加一个小参数的本地模型内存压力大概在13GB左右已经比较紧了。如果你的目标只是接DeepSeek云端API内存压力会小很多。硬盘方面Dify镜像加容器数据大约占5GB本地模型看选择7B量级的量化模型大约要5GB所以建议预留60GB以上空闲空间给临时镜像和日志增长留余地。M系列芯片没有独立GPU显存模型推理靠统一内存所以不要指望在Mac上本地跑大参数模型有多快7B模型的速度还凑合14B以上就明显吃力了。1.3 装Homebrew的时候翻车多是这两个原因Mac上很多基础工具我都习惯用Homebrew管理Docker Desktop、Ollama、Git这些都用它装。但Homebrew安装本身在首次运行时经常出问题我在新机器上就翻过车最后总结下来无非两类原因。第一类是网络问题导致安装脚本或更新失败。Homebrew默认从GitHub拉取仓库国内网络环境下经常中断。解决办法是给终端配置好代理或者直接把Homebrew源换成国内镜像。这里推荐中科大或清华的镜像源设置方式很简单# 设置brew和core的远程仓库为国内镜像 export HOMEBREW_BREW_GIT_REMOTEhttps://mirrors.ustc.edu.cn/brew.git export HOMEBREW_CORE_GIT_REMOTEhttps://mirrors.ustc.edu.cn/homebrew-core.git export HOMEBREW_API_DOMAINhttps://mirrors.ustc.edu.cn/homebrew-bottles/api export HOMEBREW_BOTTLE_DOMAINhttps://mirrors.ustc.edu.cn/homebrew-bottles这些环境变量写在~/.zshrc里每次终端启动会自动生效。第二类是Command Line Tools没有安装完整。Homebrew依赖Xcode Command Line Tools如果系统里缺少这个组件安装时会在等待软件更新的环节卡很久。解决办法是提前手动触发安装xcode-select --install装完之后再跑Homebrew的安装脚本就顺畅了。1.4 Docker Desktop装好之后先把镜像加速配上Dify的部署方式就是Docker Compose所以Docker Desktop是必须的。M系列芯片安装Docker Desktop时选择Apple Silicon版本下载dmg后拖入Applications即可。安装完后在Docker Desktop的Settings里把资源调高一些我一般给Docker分配8GB内存CPU不限制这样Dify的多容器运行才不卡。镜像加速的配置在Docker Desktop的Settings里不是那么直观它藏在Docker Engine的JSON配置里。打开Settings - Docker Engine在registry-mirrors字段里加上国内镜像地址{ registry-mirrors: [ https://docker.m.daocloud.io ] }添加后点击Apply Restart。这一步非常关键Dify首次部署要拉十来个镜像如果镜像加速没配置好大概率会卡在“拉取镜像失败”的环节。实际使用中我也遇到过即便配置了镜像加速某些镜像标签仍然拉不下来的情况这个后文专门讲。2. Dify本地部署从拉取项目到容器跑起来2.1 下载Dify项目版本选择有讲究Dify的部署方式是从GitHub拉取官方仓库然后在docker目录下用Compose启动。操作很简单git clone https://github.com/langgenius/dify.git cd dify/docker cp .env.example .env docker compose up -d但版本这块要提醒一下不要一上来就git clone最新的main分支。Dify的版本更新很快某些中间版本可能存在兼容问题。我是建议直接checkout到最新的稳定release版本。比如我写这篇文章时Dify社区版已经发布到1.17.1那么就这样操作git clone https://github.com/langgenius/dify.git cd dify git checkout 1.17.1 cd docker cp .env.example .env docker compose up -d为什么要固定版本因为Dify的Compose配置、数据库迁移脚本、环境变量在不同版本之间可能有变化直接拉最新main分支今天能跑不代表三天后还能跑固定版本能减少很多莫名其妙的错误。如果你的网络环境连GitHub都拉不动可以用Gitee上的镜像仓库。把上面的github.com/langgenius/dify.git替换成gitee.com/mirrors/dify.git即可仓库结构一致。2.2 Compose启动全流程第一次等久是正常的docker compose up -d执行后Docker会拉取postgres、redis、weaviate、sandbox、api、web等镜像。如果是第一次启动拉镜像的时间取决于网络情况慢的话二三十分钟都有可能。这时候别急着判断卡死可以先看容器状态docker compose ps正常情况所有容器状态应该是Up或running。如果某个容器反复重启用日志查原因docker compose logs -f api启动完成后浏览器访问http://localhost默认端口80就能进入Dify的初始化页面。第一次访问会让你设置管理员邮箱和密码设置完成之后会跳转到登录页。端口这块注意Dify默认使用80端口如果Mac上的80端口被占用了比如Nginx或者Apache占住启动会报端口冲突。解决方式有两个一是停掉占用端口的程序二是在.env里修改EXPOSE_NGINX_PORT比如改成8000然后重新启动docker compose up -d这种情况下访问地址就变成http://localhost:8000。2.3 拉取镜像失败这些办法我实测过管用拉取镜像失败是Dify本地部署最常遇到的问题。前面配置了镜像加速之后大部分镜像能正常拉取但偶尔还是会有个别镜像标签在加速器上同步不及时出现manifest unknown或pull access denied的报错。我遇到过好几次总结下来有三个可用的处理思路。第一个思路是切换镜像源。国内能用的Docker镜像加速地址一直在变化一个不行就换另一个。比较常见的有DaoCloud、阿里云个人镜像加速、南京大学镜像等。阿里云的加速地址需要在容器镜像服务的控制台里生成格式是https://xxxx.mirror.aliyuncs.com每个人不一样用同一个公共地址不生效。第二个思路是手动指定镜像的完整地址。有时候Docker默认的拉取逻辑会优先访问Docker Hub导致超时我们可以直接在Compose文件里把镜像的源地址改为加速地址。这个操作比较麻烦因为Dify的docker-compose.yaml里定义了十几个镜像每个都要改而且更新Dify时改动会被覆盖。我的经验是尽量不手动改Compose优先用registry-mirrors全局配置。第三个思路是换一台网络环境正常的机器在执行docker pull拉取所有镜像后用docker save打成tar包再传到Mac上docker load导入。这个方法比较笨重但在极端情况下确实能解决。如果只是缺一两个镜像也可以单独找一台机器执行docker pull langgenius/dify-api:1.17.1 docker save langgenius/dify-api:1.17.1 -o dify-api.tar然后把tar包传到Mac上docker load -i dify-api.tar2.4 已有旧版本Dify如何平滑升级到1.17.x如果你已经跑过一个旧版Dify想升级到新版千万不要直接在原目录docker compose up -d因为新版可能会有数据库结构迁移直接启动很可能出现表结构对不上的错误。安全升级步骤是备份数据。Dify的数据在PostgreSQL容器里把整个数据目录备份一下最简单。找到.env里配置的LOCAL_DATA目录默认是./data直接复制整个目录到一个安全位置。停掉当前的容器栈。如果用的是git拉取的仓库先git pull拉新代码如果你之前固定了版本直接git fetch后再git checkout目标版本。检查.env.example和当前.env的差异。新版可能会有新增的环境变量。对照docker-compose.yaml里引用的环境变量把缺失的配置补到.env里。重新启动。docker compose down git pull git checkout 1.17.1 cp .env.example .env cp .env .env.backup # 手动比对 .env.example 和 .env补充新增项 docker compose up -d升级后进入系统如果界面没变化或者报错先看api容器日志docker compose logs -f api一般常见问题是数据库迁移失败报错信息里会提示哪个表或字段有问题。这时候不要手动改数据库最好的办法是恢复备份数据然后重新检查路径是否错了。3. DeepSeek模型接入云端API和本地部署都跑通3.1 两条路线分别适合什么场景DeepSeek在Dify里接入有两条路线一条是调用DeepSeek云端API另一条是在本地部署DeepSeek模型后通过Ollama接入。这两条路线不是二选一实际使用中我建议两个都配好按场景切换。云端API的优点是不占用本地硬件资源响应速度快模型能力强适合对质量和速度要求高的核心业务场景比如长文档总结、代码生成、复杂推理。缺点是需要联网且数据会经过第三方服务器对隐私敏感的场景不合适。本地部署的优点是数据完全离线可控性最强适合处理内部资料、不可外传的文档。缺点是受Mac硬件限制跑不了大参数模型推理速度一般输出质量也比云端差一截。我日常的做法是通用对话和写作任务走云端API涉及内部知识库问答时走本地模型这样既保质量又保安全。3.2 把DeepSeek配置成Dify的模型供应商配置云端API是最快的。先到DeepSeek开放平台注册账户并创建API Key然后在Dify界面右上角点头像进入设置选择模型供应商找到DeepSeek点击添加模型填入API Key。Dify会自动拉取模型列表通常能看到deepseek-chat对应DeepSeek-V3系列和deepseek-reasoner对应DeepSeek-R1系列。没有特殊需求的话默认配置就够了Base URL留空即可Dify内置了默认地址。如果你需要自定义API地址可以在添加模型时手动填入https://api.deepseek.com。多租户环境就要注意一点Dify社区版对多租户的支持不够完善不同用户共用一套模型供应商配置。如果在团队里使用最好由管理员统一配置好Key而不是每个人各填各的否则后面换Key要一台一台去改。3.3 让DeepSeek“开口说话”语音交互配置很多人不知道Dify里其实能把语音对话也做起来。Dify在聊天应用里支持ASR语音转文字和TTS文字转语音配置好之后对话就不只是打字了。ASR方面可以选择云厂商的语音识别服务也可以通过OpenAI兼容接口接入TTS方面可以接入Azure TTS、OpenAI TTS等也可以使用一些国内服务商的接口。实际调用流程是用户语音输入 - ASR转成文字 - DeepSeek生成回答 - TTS把回答转成语音播放。Dify的前端界面在对话输入框旁边会有麦克风按钮配置好之后点击就能语音输入非常直观。如果你想做一个语音助手类的应用这个功能直接用省掉自己写语音转写服务的麻烦。3.4 本地部署DeepSeek用Ollama跑通离线链路要在Mac上本地部署DeepSeek我推荐Ollama安装简单、模型管理方便、自带OpenAI兼容接口。安装后直接在终端拉取模型brew install ollama ollama pull deepseek-r1:7b拉取完之后启动服务默认自动运行在11434端口可以用ollama list确认模型已经在本地。然后在Dify的设置 - 模型供应商里选择Ollama添加模型Base URL填http://host.docker.internal:11434模型名称选择刚才拉取的模型名。这里有个Docker特有的坑Dify跑在容器里容器内部不能直接用localhost访问Mac宿主机而是要使用host.docker.internal这个特殊地址。本地模型的推理参数量要按内存选。7B模型用Q4量化大概占4到5GB内存14B模型大概要9到10GB。16GB内存的Mac跑7B是能用的上限再往上就会开始用swap速度会严重劣化。M系列芯片内存带宽高7B模型推理速度大概在每秒10到20个token之间看具体芯片型号。另外需要提醒Dify里的每个对话都会触发模型推理如果同时多个会话并发内存飙升得非常快所以本地模型只建议自己用不要刮分给多人同时使用。3.5 N8N、Codex这些工具接入DeepSeek作为扩展Dify本身已经把模型管理集中化了但实际使用中经常还需要其他工具调用DeepSeek。比如N8N做自动化工作流时可以用DeepSeek做文本处理节点Codex CLI类的编程助手也可以配置为使用DeepSeek模型。这两种情况下都是把DeepSeek当成一个OpenAI兼容的API来访问配置时指向https://api.deepseek.com或本地Ollama的http://localhost:11434/v1即可。这类集成和Dify互不冲突可以作为Dify之外的补充能力。我现在的日常就是Dify负责知识库和对话应用N8N负责定时任务和消息推送两者通过Webhook联动DeepSeek则在两端都被调用。4. 搭建一个真实可用的知识库问答工作流4.1 场景选择为什么要拿“专利辅助撰写”来练手纸上谈兵没意思我拿一个具体的业务场景来演示专利辅助撰写。为什么选这个场景因为专利文档有固定的格式要求、专业术语多、对表述严谨度要求高非常适合体现知识库加模型协同的价值。往大了说这也是检索增强生成RAG的一个标准应用场景把已有的专利文档、技术交底书灌进知识库模型回答问题时先检索相关文档再基于检索结果进行生成而不是凭空想象大大降低了幻觉。如果你的场景是技术文档问答、员工手册问答、合同审核思路完全一样只是换一套文档。4.2 创建知识库文档分段和向量化是第一步在Dify里知识库功能在左侧导航栏。点击创建知识库把准备好的专利文档支持PDF、Word、Markdown、TXT等格式上传。上传完会进入分段设置页面这里有两个关键参数分段长度Chunk Size和分段重叠Chunk Overlap。分段的逻辑是把一篇长文档切成一节一节的小文本块每一块单独做向量化存储。分段太短会丢失上下文太长又会让检索精度下降。专利文档我的经验是分段长度控制在300到500个token之间重叠部分50左右。Dify里可以直接预览切分效果能看到每段的内容和字数如果切出来的段落有明显语义断裂就调大重叠部分。向量化时Dify会调用嵌入模型Embedding Model。如果你已经接入了DeepSeekDify里有内置的文本嵌入模型选项也可以使用本地的Ollama嵌入模型。向量模型的选择会影响检索质量如果不是特别在意成本我建议用效果更好的在线embedding接口。上传完成后Dify会自动把文档分段并向量化存入向量数据库。4.3 工作流串联知识检索与回答生成的关键配置知识库建好之后创建应用时选择“工作流”类型而不是直接选“聊天助手”。工作流的核心节点是这样串联的开始节点声明输入参数默认就是用户输入的sys.query。知识检索节点选择刚才创建的知识库把查询变量绑定为sys.query设置检索的TopK和Score阈值。LLM节点绑定DeepSeek模型在上下文Context变量里引用知识检索节点的输出在系统提示词里写明“仅基于提供的资料回答”。结束节点把LLM节点的输出作为最终回复。TopK的意思是从知识库里召回最相关的多少个分段。我一般设置为4也就是每次回答问题最多参考4段文档。Score阈值是召回结果的最低相关度分数低于阈值的段落会被过滤掉。这个值需要实际跑几轮来调设置太高会导致回答“不知道”设置太低会把不相关的内容带进来生成一些似是而非的答案。专利问答建议从0.4开始试根据实际效果微调。LLM节点的系统提示词是整个工作流效果好坏的关键。写提示词有一个技巧把知识检索到的内容用明确的标识符包围起来模型就知道哪些是参考资料、哪些是用户问题不会混淆。我的提示词模板是这样的你是一名专利撰写助理请基于以下资料回答用户问题。 资料内容 documents {{#context#}} /documents 要求 1. 回答时优先使用资料中的信息引用资料中的术语和表述。 2. 如果资料中没有相关信息请明确告诉用户“当前知识库中没有找到相关内容”。 3. 输出内容要求逻辑清晰、专业规范。这里{{#context#}}是Dify工作流变量会自动替换为知识检索结果。注意变量名的大小写和实际场景保持一致不同版本的Dify变量命名规则略有差异在节点配置面板里可以看到当前节点的变量列表。4.4 调优实测温度参数与检索阈值的组合拳这个工作流跑通之后调优才是最花时间的地方。以我实际测试一个“如何撰写专利权利要求书”的问题为例第一次测试时我把Score阈值设为0.3TopK设为6结果模型回答引用了很多不相关的段落甚至把背景技术里的内容当成了权利要求书的撰写要点。之后我把Score阈值调高到0.45TopK降到4再测就显得准确了很多。原因是专利文档相似度本来就高阈值太低时召回结果太杂。Temperature参数也很关键。DeepSeek在Dify里的默认Temperature是0.7对专利这种严谨性要求高的场景太高了。我实际调整到0.2输出更稳定不容易出现发散性的表述。如果做创意写作可以调高但只要是文档生成或者知识库问答类场景Temperature不建议超过0.4。整个调优流程其实就是跑一个测试问题 - 看知识检索节点实际召回了哪些段落 - 看Score值 - 看模型回答质量 - 调整Threshold和Temperature - 再测。多试几个不同类型的问法就能找到那组最优参数。5. 常见问题与排查技巧实录5.1 访问不了Dify界面先查容器状态再查端口如果启动后访问http://localhost显示无法访问先别急着重装。第一步看容器状态第二步看日志第三步查端口占用docker compose ps docker compose logs -f nginx lsof -i :80docker compose ps能看到每个容器的状态如果nginx容器显示Exit或Restarting大概率是端口冲突或配置问题。lsof -i :80可以查到80端口被哪个进程占用。我之前遇到过一次是Mac自带的Apache占用了80端口停掉Apache之后Dify就正常了。如果是端口占用也可以修改.env里的EXPOSE_NGINX_PORT避开冲突。5.2 Docker容器老被杀死或卡死多半是内存不够跑Dify全套容器平时内存占用并不低我观察过总共要占4到5GB如果再叠加本地模型推理16GB内存的Mac确实会吃紧。容器突然卡死或者被自动杀掉查docker stats能看到内存占用情况docker stats如果观察到内存使用量接近Mac物理内存上限说明资源分配不足或在发生swap。处理办法是调整Docker Desktop的硬件资源配额给Docker更多内存同时关闭不用的前端应用释放内存。还有一个技巧给Docker Desktop设置内存上限时留出至少4GB给macOS系统本身否则系统会频繁杀进程。5.3 M系列芯片跑Dify注意当前Docker镜像的架构M系列芯片是ARM架构Dify的大多数镜像都提供了arm64版本docker compose会自动拉取适配架构的镜像一般不用手动干预。但有部分工具或自定义脚本中可能会用到x86_64架构的镜像比如某些向量库的特定版本。遇到这种问题可以显式指定平台参数拉取arm64版本docker pull --platform linux/arm64 镜像名:tag如果你看到容器日志里有exec format error基本可以判断是架构不匹配。另外安装Ollama后默认运行的是原生arm64版本这和Dify的容器架构没有冲突但要注意Ollama只监听localhost时Dify容器内要用host.docker.internal访问。5.4 Mac系统数据越来越大可能是Docker和模型缓存在膨胀有读者问过Mac的系统数据占用空间暴涨怎么办这个和Dify的关系很直接Docker的镜像、容器日志、卷数据都算在系统数据里。查看占用可以用df -h逐目录排查但最有效的方法是让Docker自己清理docker system df docker system prune -adocker system df可以看具体占了多少空间docker system prune -a会清掉所有未被使用的中止容器、无用网络、构建缓存和未被使用的镜像。这个命令要慎用它会把本地的镜像全清掉下次启动Dify时还要重新拉取。另一种情况是macOS的Time Machine本地快照占空间可以查看并清理tmutil listlocalsnapshots / tmutil deletelocalsnapshots 日期时间戳我之前遇到过系统数据占了上百GB一查是Time Machine的本地快照加Docker镜像叠加造成的清理完快照再删掉不用的镜像马上释放了几十GB空间。5.5 最终运行效果与参数速查表把整套环境跑通之后我最终稳定的配置组合如下供直接参考配置项参数/方案备注Dify版本1.17.1固定release版本兼容性更好模型策略通用对话走DeepSeek云端API质量高、速度快本地模型deepseek-r1:7b (Ollama)离线知识库问答备选知识库分段300-500 token重叠50专利文档的合适参数TopK4召回分段数Score阈值0.45低于此值的不参与回答Temperature0.2严谨场景用低值Docker内存8GB16GB内存Mac的推荐值5.6 跨平台迁移和备份的小建议这套方案只在Mac上跑之后如果想迁移到其他机器或者担心数据丢失备份的重点是Dify的./data目录。整个目录打包拷贝到新机器重新部署Dify后把data目录放回去再执行一次docker compose up -d就能恢复之前的知识库和应用配置。还有模型供应商的API Key这些配置存在Dify数据库里也会随data目录一起备份所以这个目录是整个方案里最需要珍惜的东西。我个人在实际操作中还有一个习惯每个版本升级之前先把知识库里的文档导出一份应用的DSL文件每个应用在Dify里都可以导出为YAML/JSON文件也定期备份。这样即便数据库出了严重问题文档还在、应用的流程定义还在重新搭建的成本就低很多。最后再分享一个小技巧Dify工作流节点之间的变量贯通是最容易让人困惑的地方。调试的时候别急着看最终回答先把中间节点的输出打开一步步看。比如知识检索节点返回了什么内容LLM节点最终的Prompt是什么这些在Dify的调试面板里都看得清清楚楚。等你在Mac上把这套组合跑顺了再回头去看那些复杂的LLM应用基本都能拆解成“检索加生成”的组合拳。这套本地工作流值得你花一个周末折腾一下。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进