过去大半年,我所在的小团队一直在折腾大语言模型的本地化落地。跟很多人一样,最早接触的是 Ollama,因为一条命令就能把模型跑起来;后来产品要接并发请求,开始研究 vLLM;再后来要给业务方搭知识库问答,又引入了 Dify。这三个名字经常出现在同一篇文章里,但真正上手后才发现,它们在生态里扮演的角色完全不同:一个管模型怎么跑,一个管服务怎么扛住压力,一个管业务怎么接进来。这篇文章我就把三者拆开讲清楚,再分享一套我们自己验证过的组合方案。无论你是刚入门、想在笔记本上跑通一个对话 Demo,还是已经要搭一个面向团队内部的 AI 应用,这篇内容应该都能帮你少走点弯路。
1. 大模型落地前,先想清楚三层问题
很多人一上来就到处找"最强模型",但其实模型本身只是起点。作为一个在基础设施方向待了很多年的人,我见过太多项目倒在同一个问题上:模型选好了,却在"用起来"这个环节卡了一个月。要理解 Ollama、Dify 和 vLLM 的关系,必须先看清大模型应用落地时绕不开的三个环节。
1.1 模型文件只是起点:推理、服务、应用是三个环节
一个开源大模型下载下来,本质上只是一堆权重文件。要让业务真正用到它,至少要经过三层处理:
第一层是推理。模型文件不会自己说话,你需要一个运行时把权重加载进显存,执行前向计算,把用户的输入变成输出。这一层决定的是一个模型"能不能跑"、跑得快不快、显存占用多少。
第二层是服务。就算模型能跑,你也得考虑多个用户同时请求怎么办。是排成一个队列逐个处理,还是通过批处理机制把多个请求凑在一起算?这层决定的是系统"能扛多少并发"。
第三层是应用。模型和服务都有了,距离业务可用还差很多。你需要处理用户对话里的多轮记忆,需要从自己的文档里检索答案,需要让模型调用内部工具,还要管理不同用户权限和界面。这层解决的是"怎么把模型能力包装成产品"。
网上很多教程把这三层混在一起讲,导致初学者以为选了 Ollama 就等于完成了部署,或者以为引入 Dify 后就万事大吉。实际上,这是一个类似"发动机、变速箱和车身"的关系——每个环节解决不同的问题,也各有各的坑。
1.2 用一张分工图理解三者关系
我见过比较清晰的理解方式是这样的:
- Ollama同时覆盖第一层和第二层,但它更强调"本地推理的轻量体验"。它把模型下载、量化、启动、API 暴露打包成一件事,适合个人开发、小团队内部使用、低并发的场景。
- vLLM专注于第二层,也就是"高性能服务"。它在推理引擎层做了大量优化,能够把 GPU 的吞吐能力压榨到极致,适合生产环境、高并发调用、服务端部署。
- Dify位于第三层,是一个应用编排平台。它本身不运行模型,而是把 Ollama、vLLM 或者其他模型服务当作"上游"接进来,再帮你完成知识库、工作流、Agent 等应用层功能。
换句话说,Ollama 和 vLLM 是平级的选择关系,Dify 则是它们上层的消费方。Dify 可以同时对接多个模型服务,你可以把 Ollama 接进去做开发测试,把 vLLM 接进去做生产流量,两者互不影响。
1.3 我见过最多的一种错误理解
有一次同事跟我讨论架构,说"我们用 Dify 跑模型,不需要 Ollama 了"。这句话其实混淆了职责。Dify 自己并不提供模型运行时,它默认也会尝试对接各种模型 API。你可以让它对接云上的服务,也可以对接本地自建的 Ollama 或 vLLM。所以准确的说法是:"我们用 Dify 做应用层,用 Ollama 做本地模型推理。"
还有一个常见误区是认为 Ollama 和 vLLM 只能二选一。实际项目中两者经常共存:开发环境用 Ollama 快速验证,生产环境用 vLLM 提供稳定服务,Dify 在不同的工作流里分别调用。理解了这层分工,后面所有配置和架构选择都会变得顺理成章。
2. Ollama:本地推理的"模型管家",也是开发调试的第一站
如果说大模型应用是一场戏,Ollama 就像是后台的"道具管家"——你告诉它要哪个模型,它负责下载、启动、暴露接口,尽量不让你碰底层细节。这一节我会讲清楚它到底做了什么、真正动手时要注意什么。
2.1 一条命令的魔法:ollama run 背后的模型管理机制
我第一次在笔记本上跑ollama run llama3.1的时候,确实被震撼到了——不需要安装 Python 依赖,不需要写推理脚本,甚至不需要手动下载模型文件。命令执行后,Ollama 会自动从模型仓库拉取对应的 GGUF 格式模型,然后进行量化加载,默认利用本机 GPU 进行加速,如果显存不够还会自动回退到 CPU 推理。
它背后的核心设计是模型文件管理和运行时解耦。你可以用ollama pull qwen2.5:7b预先拉取某个模型,也可以直接ollama run让它按需下载。下载好的模型存放在本机的模型目录里,运行时通过ollama list可以查看。
这里有一个值得新手注意的点:模型名后面的标签代表具体版本。比如llama3.1:8b表示 8B 参数的基础版,qwen2.5:7b-instruct-q4_K_M则表示 Qwen 2.5 7B 指令微调版基于 Q4_K_M 量化后的版本。同一个模型,不同标签占用的磁盘和显存可能差好几倍。你如果只写ollama run qwen2.5,它会拉取一个默认标签,不一定是你想要的那个。
2.2 量化与显存估算:动手前先算笔账
我见过不少朋友兴冲冲拉了一个 70B 模型,然后看着CUDA out of memory发呆。在本地跑模型之前,建议先学会估算显存。
一个简单的经验公式:显存占用约等于 参数量 × 每个参数占用的字节数。FP16 精度下每个参数占 2 字节,7B 模型大约需要 14GB 显存;INT4 量化后每个参数约 0.5~0.6 字节,7B 模型降到 4GB 左右。所以 Ollama 里常见的 Q4_K_M 量化版本,8B 模型大约占用 5GB 显存,13B 约 8GB,70B 则接近 40GB,即便量化后也基本告别普通消费级显卡。
这还没算 KV Cache 的开销。KV Cache 是模型在生成过程中缓存的历史计算中间结果,它的大小跟上下文长度成正比,跟并发数成正比。上下文越长、同时处理的请求越多,显存占用越大。实测下来,一个 8B 量化模型在 8GB 显存的显卡上,默认 4K 上下文跑得比较稳,如果硬要把上下文拉到 32K,生成速度会明显下降甚至直接爆显存。Ollama 可以通过环境变量OLLAMA_CONTEXT_LENGTH调整默认上下文大小,但改之前一定先确认显存够不够。
2.3 Ollama 的 API 接入细节与并发瓶颈
Ollama 启动后会监听本机 11434 端口,同时提供两类接口:一类是它原生的/api/generate和/api/chat,另一类是兼容 OpenAI 格式的/v1/chat/completions。后者非常关键,因为 Dify 以及其他很多开源工具默认都是按 OpenAI 兼容协议来对接模型的,直接用这个地址就能少掉很多适配工作。
配置上其实只有三个关键信息:
- 接口地址:
http://<服务器IP>:11434/v1 - 模型名称:必须和
ollama list里显示的名字完全一致 - API Key:Ollama 本身不做鉴权,随便填一个占位符就行
不过要把丑话说在前面:Ollama 在并发上并不算强。它内部默认对单模型请求做排队处理,多用户同时问的时候,后面的请求会阻塞等待,每个请求生成时间长的话,整体响应会非常慢。实测下来,8B 模型在 8GB 显存上,3~5 个并发同时请求就开始出现明显排队。所以它适合开发调试、个人助手、或者内部十来个人的低频使用,不适合直接对生产环境开放高并发接口。
3. vLLM:面向生产环境的吞吐型推理引擎
如果说 Ollama 是"傻瓜相机",那 vLLM 就是"专业电影机"。它不追求上手门槛低,追求的是在 GPU 资源不变的情况下,把每秒能处理的请求数和生成 token 数推到极限。很多团队第一次接触 vLLM,是因为 Ollama 扛不住并发,或者 GPU 利用率一直上不去。
3.1 PagedAttention 和连续批处理:vLLM 提速的两个核心
要理解 vLLM 为什么快,得先说它解决的两个问题。
第一个问题是显存管理。大模型生成时每处理一个 token,都要把之前所有 token 的 KV Cache 保留在显存里。传统推理框架会为每个请求预先分配一整块连续的显存空间来存放 KV Cache,但请求的实际用量很难预测,导致大量显存被闲置浪费。vLLM 借鉴了操作系统虚拟内存的分页思想,把 KV Cache 切成固定大小的块(page),按需分配,不够用时再去取新的块。这就是PagedAttention这个名字的由来。它能够大幅提高显存利用率,同样的 GPU 上可以塞进更多的并发请求。
第二个问题是请求调度。传统框架通常采用"静态批处理":一批请求同时进来,一起计算,等这批全部结束后再接收下一批。如果某个请求特别长,整批请求都要等它。vLLM 则实现了连续批处理(continuous batching):每个 token 生成完成后,这个请求就可以离开批次,新请求无缝加入,GPU 几乎一直在满负荷计算,不会出现"一个人拖垮一车人"的局面。
这两个机制叠加的效果非常直接。我自己的实测对比中,同样的 7B 模型、同样的显卡,vLLM 的吞吐量可以到 Ollama 的 3~5 倍,并发越高差距越明显。
3.2 启动一个 OpenAI 兼容服务需要关注的关键参数
vLLM 部署起来比 Ollama 多几个步骤,因为它需要你明确指定模型路径、模型格式、显存占用比例等。一个典型的启动命令长这样:
vllm serve /data/models/qwen2.5-7b-instruct \ --served-model-name qwen2.5-7b \ --tensor-parallel-size 1 \ --gpu-memory-utilization 0.85 \ --max-model-len 8192 \ --port 8000这里解释一下几个关键参数的含义:
- 模型路径:可以是本地目录,也可以是模型仓库里的模型 ID。生产环境建议先把模型下载到本地目录再启动,避免启动时网络波动导致加载失败。
--served-model-name:这个参数很实用。它决定了通过 API 访问时模型叫什么名字。哪怕你的目录叫长串路径,对外暴露的名字也可以很干净。Dify 接入时填的模型名必须跟这里一致。--gpu-memory-utilization:告诉 vLLM 最多使用多少比例的显存。默认是 0.9,如果你的 GPU 还要跑其他任务,建议调低到 0.5~0.7,否则容易把显存占满导致其他进程崩掉。--max-model-len:最大上下文长度。它直接影响 KV Cache 预留空间,设得过大,显存被 Cache 抢占,能支撑的并发量反而下降。要根据业务实际需要来设,不是越大越好。
启动成功后会监听 8000 端口,访问/v1/models可以看到服务信息,访问/v1/chat/completions就能正常对话。
3.3 vLLM 的显存规划与 OOM 实战排查
用 vLLM 的过程中,最常遇到的就是启动时直接 OOM 或者模型加载到一半被杀。这类问题大多出在显存规划上,我建议按这个顺序排查:
先用nvidia-smi看 GPU 当前占用。很多人忽略的是,哪怕 vLLM 还没启动,其他进程也可能已经占用了显存。有个项目曾经在 GPU 上跑着一个嵌入模型,结果 vLLM 怎么启动都报显存不足,查了半天才发现是那个嵌入模型占了 6GB。
再确认模型权重本身的大小。7B FP16 模型权重约 14GB,如果你用 16GB 显存的显卡,即便 vLLM 的gpu-memory-utilization设成 0.9,也只有大约 14.4GB 可用,刚好卡在边缘。安全做法是给权重预留 15% 的余量,或者直接使用 AWQ/GPTQ 量化版模型,把权重降一半,腾出更多空间给 KV Cache。
最后看日志里的 KV Cache 分配信息。vLLM 启动后会在日志里打印类似"Available KV cache memory"的信息,如果这个数值很小,说明显存大部分被权重吃掉了,并发能力会非常有限。此时可以调整--max-model-len缩短上下文,或者换更小的模型版本。
我之前在一张 24GB 显卡上跑 13B 模型,gpu-memory-utilization=0.9、上下文 8192,KV Cache 大概能支撑十几个并发,吞吐比 Ollama 好了太多。如果只有 8GB 显存,跑 13B 权重基本就把显存吃满了,建议老老实实用 7B 或 8B 量化模型。
4. Dify:模型与应用之间的"编排层"
接入了模型服务、能并发响应了,业务团队来找你要"一个能回答规章制度问题的机器人"——这时候你就会发现,还缺一层东西。Dify 就是为解决这个"缺一层"而生的。
4.1 裸模型 API 为什么不够用
很多人第一次对接模型 API 后都会疑惑:模型明明会说话,为什么没法直接交付给业务?答案在于,一个可用的 AI 应用还需要解决这些问题:
- 多轮记忆:模型 API 是无状态的,每次调用都要把历史对话打包传过去。手动管理会话历史又啰嗦又容易超长。
- 知识库:业务问的问题涉及内部文档,模型训练时根本没见过这些内容。你需要把文档切片、向量化、检索,把结果塞进模型上下文。
- 工作流:有的流程不是"一问一答",而是先判断意图、再查数据库、再生成答案,中间还可能有审批或人工干预。
- 权限和管理:谁能用这个机器人、用在哪个应用里、日志如何留存,这些模型 API 全都管不了。
Dify 把这些能力做成了可视化的平台。你可以在界面里配置知识库、拖拽工作流、设置模型参数,不需要从零写代码就能搭出一个完整的 AI 应用,同时它也提供了 API 接口,方便嵌入到现有业务系统里。
4.2 Dify 接入 Ollama/vLLM 的配置要点
Dify 本身不运行模型,所以第一步永远是先给它配好模型供应商。它内置支持很多云服务商,但对本地部署团队来说,最常用的方式是使用"兼容 OpenAI 格式的自定义模型"。
在 Dify 的模型供应商设置里,选择添加自定义兼容接口,然后填写:
- API 地址:如果是 Ollama,填
http://<Ollama主机IP>:11434/v1;如果是 vLLM,填http://<vLLM主机IP>:8000/v1 - API Key:Ollama 填任意字符串即可;vLLM 默认不校验,除非你自己加了鉴权
- 模型名称:必须跟 Ollama 的
ollama list或 vLLM 的/v1/models返回的名称逐字匹配
这里有两个很隐蔽的坑。第一个是IP 别写成 localhost。Dify 如果跑在 Docker 容器里,localhost指的是容器自己,必须写成宿主机的局域网 IP 或者 Docker 网络内的服务名。第二个是模型名带版本标签,比如 Ollama 里的模型名可能写的是qwen2.5:7b-instruct-q4_K_M,Dify 里填错一个字符都识别不了。
另外,Dify 里除了对话模型,还要单独配置嵌入模型(Embedding Model)。知识库要先把文档向量化,检索时也要向量化查询,这两个动作都需要嵌入模型。很多团队只配了对话模型就去做知识库,结果一直报"embedding 模型未配置"。本地环境可以用 bge 系列的嵌入模型跑在另一个服务里,也可以让 Ollama 加载一个嵌入模型,再把地址配到 Dify 的 Embedding 设置里。
4.3 RAG 工作流和 Agent:Dify 最常用的两类玩法
Dify 里最常用到的两类能力,我个人体感是 RAG 知识库和 Agent 工作流。
做知识库问答时,Dify 会先把文档分段,再用嵌入模型生成向量存入向量数据库。实际配置中有几个参数很影响效果:分块大小(chunk size)和重叠长度(overlap)。分块太大会导致每段内容主题混杂,检索命中不精准;分块太小又会让上下文碎片化,模型看不到完整信息。我一般从 512 字符起步,重叠 50~80 字符,再根据实际问答效果调整。检索策略上,如果文档主题明确,用向量检索就够了;如果涉及大量专业术语,建议开启"全文检索 + 向量检索"混合模式,效果会更稳。
Agent 玩法则适合需要让模型"动手干活"的场景。比如用户问"帮我查一下上季度某产品的销量并生成一段总结",Agent 会先解析意图,然后调用你配置好的工具 API 去查询数据,再基于返回结果生成回答。Dify 内置了工具调用框架,也可以接入自建的 HTTP API。需要注意的一点是,Agent 的稳定性跟底层模型的工具调用能力强相关。小参数模型经常会"忘记"该传什么参数,实测中 7B 级别模型做复杂 Agent 会有点吃力,至少 14B 以上,或者采用比较简单的工具定义、限制工具数量不超过 5 个。
5. 三件套组合:我给内部团队搭的本地知识问答系统
讲完三个组件的定位,我分享一个真实落地的组合案例。我们团队规模不大,数据敏感度比较高,不能把内部文档直接传到外部服务,所以选择了完全本地化部署:一台工作站 + Ollama + vLLM + Dify,给业务方提供规章制度问答和数据处理辅助。
5.1 硬件配置与选型判断
机器配置是一张 24GB 显存的 GPU,搭配 64GB 内存和一块 2TB SSD。选这套配置的原因很简单:24GB 显存刚好能跑 13B 级模型的 FP16 权重,也可以跑 7B 模型的超高并发;64GB 内存是为了让 Dify 的中间件、向量数据库以及多个容器同时跑而不互相挤兑。
模型选择上,对话模型用了 13B 级别的指令微调模型,量化精度选 INT4,显存占用大约 10GB,剩下来的空间给 KV Cache 和并发请求。嵌入模型单独跑一个轻量的 bge 系列模型,额外占 2GB 左右。整体跑起来后,GPU 占用率稳定在 85% 上下,显存还剩约 4GB 余量,这样的配置既不浪费资源,又给了突发流量一点缓冲空间。
5.2 完整部署链路与联通逻辑
整个系统的链路是这样的:
用户请求 -> Dify 应用界面/API -> Dify 编排层 -> 知识库检索(向量库 + 嵌入模型) -> 模型调用(Ollama/vLLM 的 OpenAI 兼容接口) -> 生成回答 -> 返回用户具体到部署动作,我建议按照这个顺序:
第一步,先在宿主机上装好 Ollama 和 vLLM。Ollama 负责开发调试用的模型,vLLM 负责生产模型。为了让两者互不干扰,我给 vLLM 设了gpu-memory-utilization=0.55,剩下的显存留给 Ollama 和嵌入模型。如果后面发现 Ollama 基本用不到,可以把它停掉,把 vLLM 的显存利用率调回到 0.85。
第二步,用 Docker Compose 启动 Dify。Dify 的默认编排文件里已经包含了 API 服务、Worker、向量数据库、Redis 等组件,docker compose up -d直接就能跑起来。
第三步,在 Dify 后台配置模型供应商。我建了两个供应商:一个指向 Ollama,用于测试新模型的工作流;一个指向 vLLM,用于正式环境。同时在 Embedding 设置里配置嵌入模型。
第四步,创建知识库。把内部文档传上去,设置 512 字符分块、50 字符重叠,选择一个混合检索策略,然后保存并索引。索引完成后,我建议先用几条真实业务问题做验证,看检索出来的片段是否对得上问题的意图,不对就调整分块大小或检索权重。
第五步,把调试好的应用发布成 API 服务。业务方通过 Dify 提供的 API 接入他们的内部系统,应用界面上还能看到调用日志和标注数据,方便持续优化。
5.3 面向不同规模团队的选择矩阵
并不是所有团队都需要"三件套全上"。以下是我根据实际经验整理的选型矩阵,可以直接抄作业:
| 场景 | 推荐组合 | 理由 |
|---|---|---|
| 个人电脑跑个 Demo、研究提示词 | Ollama | 一条命令启动,零配置负担 |
| 小团队内部 5~10 人用,非核心业务 | Ollama + Dify | Ollama 扛低频足够,Dify 补上应用能力 |
| 内部工具面向几十人,有并发要求 | vLLM + Dify | vLLM 保障吞吐,Dify 统一应用管理 |
| 生产环境、高并发、严格 SLA | vLLM 集群 + Dify | 可加多卡张量并行,必要时横向扩展多实例 |
| 数据敏感、完全隔离内网 | 全本地三件套 | 模型、推理、应用全部本地化 |
如果你只是想快速验证某个模型的效果,不需要 Dify 那一层;如果你已经有成熟的模型调用链,只是缺一个知识库管理界面,Dify 也可以单独接进来。先想清楚业务瓶颈在哪里,再决定引入哪个组件,这是我这半年最深的体会。
6. 几个反复踩的坑和值得长期保留的习惯
最后分享几个实际运维中踩过的坑,以及我现在已经养成的一些习惯。这些细节在官方文档里都不太起眼,但每一个都曾经让我们排查过半天。
6.1 上下文长度与分段策略
上下文长度是影响系统稳定性的一个隐形变量。Ollama 默认上下文只有 2K 到 4K 级别,如果你在 Dify 里配置了复杂的提示词和大量知识库片段,一上来就可能截断。我在 Dify 的提示词里加了一段"如果给定内容不足以回答,请明确说明"的兜底指令,同时把 Ollama 的上下文调到 8K,效果好了很多。
知识库检索出来的内容会塞进上下文,参考片段数量也会叠加佔用。Dify 里"检索召回条数"默认值是 3 条,每条约 512 字,加上用户问题和历史对话,8K 上下文其实很快就不够用了。建议优先把单条语料控制在 400~600 字,召回调到 3~5 条,再根据回答质量权衡上下文和耗时的关系。
另外,换模型版本之后,嵌入维度可能会变。如果换了一个维度不同的嵌入模型,之前向量库里已经索引过的数据全部作废,需要重新索引。这个坑我们踩过:换嵌入模型后第一次问答报告找不到向量库索引,数据库里全是废数据,只能全部重建。建议在固定好嵌入模型之前,不要急着灌大规模文档。
6.2 嵌入模型是 RAG 效果的分水岭
很多团队把精力全花在选对话模型上,却忽略嵌入模型。我自己的经验是:在知识库问答里,嵌入模型对效果的影响不亚于对话模型。一个领域匹配度的嵌入模型和一个通用嵌入模型的差距,在垂直文档检索上非常明显。
判断嵌入模型是否合适,可以在 Dify 里打开"检索测试"功能,手动输入几个核心问题,看返回的片段是不是真的跟问题相关。如果返回结果表面相关但语义上不对,大概率是嵌入模型不够贴合领域。这时候可以考虑换一个领域微调过的嵌入模型,或者把分块粒度调小、增加重叠长度。在没确认检索质量之前,不要指望对话模型能"力挽狂澜"——喂进去的上下文本身不对,再强的生成能力也白搭。
6.3 监控、日志与模型替换的日常习惯
部署稳定之后,日常维护其实就三件事:看显存、看响应时间、看日志。
显存用nvidia-smi定期看,但更建议盯一个指标:GPU 利用率是否长期偏低。如果 GPU 利用率不到 30%,而显存几乎占满,大概率是模型太大导致 KV Cache 空间不足,并发都排队堵住了。这时候换更小的量化模型或者缩短上下文,比增加请求超时时间更有效。
vLLM 访问日志默认会打在标准输出。我会用一行命令把/v1/chat/completions的响应耗时统计出来,一旦出现大量超过 5 秒的长尾请求,就去查当时的并发数和模型上下文长度。Ollama 没有自带像样的监控,依赖进程日志,所以生产流量尽量走 vLLM,这本身也是一种运维上的取舍。
模型替换也是很有讲究的一件事。先在 Ollama 里拉一个新模型,用 Dify 的工作流做一轮影子测试,再切到 vLLM 生产。千万不要直接在生产环境vllm serve一个没验证过的模型。我们内部已经形成了一条流程:模型进 Ollama 做功能验证,满意的版本再下载到本地目录、在 vLLM 上做压力测试,最后才在 Dify 里切换模型供应商,全程业务无感。这套流程下来,模型升级基本没出过线上事故。
这三件套的组合,最大的价值在于每一层都可以独立替换、独立优化。模型不行换模型,并发不够调 vLLM 参数,应用逻辑复杂就在 Dify 里改工作流。对于那些既想留住数据隐私、又想把大模型真正用起来的团队来说,这套组合应该是目前最省心的一条路了。