基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
  • 知识卡片碎片时间过考点
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
    • AI 热点每日 AI 资讯与动向
AI 工作台
简历
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
技术实践2026-11-02 15:57

16GB笔记本搭建本地大模型服务平台

dev.to · AI#本地部署#模型服务#接口网关
Editor brief · 编辑速览

作者在 M1 Pro、16GB 内存的笔记本上,用 Ollama、LiteLLM 和 Open WebUI 搭建开放权重模型服务。平台包含用户密钥、模型访问限制、限流及数据库请求日志。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

在 16 GB 内存的 MacBook Pro M1 Pro 上搭一套本地 ChatGPT,模型能回答只是起点。作者做的 OzAI,还要提供独立密钥、限流、用量记录和 IDE 接入。真正花时间的,是排查那些请求成功、答案却不对劲的问题。

这篇实践最有价值的结论是:自托管 LLM 既要管 API,也要检查模型实际吃进了什么、用户等了多久。提示词被截断、推理耗尽输出预算、后台任务抢占资源,都可能不报错,却让产品变得难用。

一台笔记本,能撑起多大的服务

OzAI 没有训练新模型,而是用 Ollama 运行 Qwen3 8B 和 Qwen2.5-Coder 3B,再用 LiteLLM 提供兼容 OpenAI 的网关。Open WebUI 负责聊天,SearXNG 提供搜索,Postgres 保存请求日志,Grafana 展示指标。

OzAI 的客户端、网关与本地模型调用关系

除 Ollama 外,组件都运行在 Docker Compose 中,仅绑定 127.0.0.1,尚未开放互联网访问。Ollama 原生运行在 macOS,通过 Metal 使用 Apple GPU;容器通过 host.docker.internal:11434 访问它。作者这样部署,是因为其 macOS Docker 环境中的 Linux VM 无法访问 Apple GPU,容器里的 Ollama 只能使用 CPU。

先看作者的单请求测试:最大输出 200 tokens,没有并发。

模型 磁盘占用 冷加载 提示词处理 生成速度
qwen2.5-coder:3b(Q4) 1.9 GB 2.1 秒 120 tok/s 53.3 tok/s
qwen3:8b(Q4_K_M) 5.2 GB 3.9 秒 87 tok/s 22.4 tok/s

作者用内存带宽解释速度差异:生成每个 token 都要读取权重,模型约大 2.7 倍,速度约慢 2.4 倍。Q4_K_M 大致用每个权重 4 bits 存储,才让 8B 模型压到 5.2 GB;未量化的权重约需 16 GB,已经占满这台机器的内存。

但单人可用,不代表多人可用。另一组测试通过 Python 线程发送流式请求,每次要求 128 tokens:

并发用户 首 token 时间 p50 最慢首 token 时间 单用户 tok/s 总 tok/s
1 0.3 秒 0.3 秒 19.5 19.5
2 3.4 秒 6.7 秒 14.5 19.7
4 9.3 秒 18.6 秒 8.7 20.8
8 21.3 秒 43.3 秒 4.7 20.7

总吞吐一直在约 20 tok/s,多出来的用户主要是在排队。作者计划后续用 vLLM 的连续批处理,让多个请求在同一轮模型计算中推进,但本文没有给出迁移后的实测。

网关管得住请求,也要管住额外开销

LiteLLM 把真实模型映射成客户端使用的名称,还能为不同密钥配置模型白名单和限流。下面这段配置同时解决普通聊天、深度推理和代码模型的路由:

model_list:
  - model_name: ozai            # 快速聊天
    litellm_params:
      model: ollama_chat/qwen3:8b
      api_base: http://host.docker.internal:11434
      reasoning_effort: none
      num_ctx: 8192
  - model_name: ozai-think      # 同一模型,开启推理
    litellm_params:
      model: ollama_chat/qwen3:8b
      api_base: http://host.docker.internal:11434
      num_ctx: 8192
  - model_name: ozai-coder
    litellm_params:
      model: ollama_chat/qwen2.5-coder:3b
      api_base: http://host.docker.internal:11434

关键是 reasoning_effort: none:默认聊天关闭推理,需要时再选择 ozai-think。作者曾看到一道简单问题在正文出现前输出超过 600 个推理流片段,完整响应约两分钟,其中还包含等待另一请求的时间。max_tokens 太小时,预算甚至全被推理消耗,最终答案为空。

创建用户密钥时,可以直接限制可用模型和每分钟请求数:

curl localhost:4000/key/generate \
  -H "Authorization: Bearer $LITELLM_MASTER_KEY" \
  -d '{"key_alias":"demo-friend","models":["ozai"],"rpm_limit":10}'

注意 models 和 rpm_limit 两项。作者验证了无密钥返回 401,越权访问 ozai-coder 返回 403;一分钟内发出 12 次请求时,先有 9 次 200,随后触发 429,因为同一窗口已有一次请求。

预算也有陷阱。max_budget: 0 不代表本地免费模型可以随便调用:检查条件是 spend >= budget,0 ≥ 0 会直接拦截。作者建议不设置预算,或配置自定义 token 价格,让预算有实际含义。

另一笔开销来自 UI。Open WebUI 在回答后,还会请求模型生成标题、标签和后续问题。作者把后台任务切到 3B 的 ozai-coder,关闭标签和后续建议后,体感响应明显改善,但没有提供前后延迟对照。

没报错的请求,为什么仍然答错

状态码正常,只能证明调用完成,不能证明上下文完整。

作者接入搜索后,SearXNG 明明返回了结果,模型仍说无法获取实时信息。线索藏在日志里:无论问题长短、是否搜索,提示词数量都固定在 2,050 tokens。

他发送约 5,000 tokens 的文本,在末尾放入暗号,模型答出了 BANANA,但日志仍显示 prompt_tokens: 2050。末尾保住了,开头却被截掉;Open WebUI 恰好把搜索结果放在开头。

在网关配置加入 num_ctx: 8192 后,作者把暗号移到开头重测,得到 prompt_tokens: 5430,模型仍能答出暗号。内存占用从 5.6 GB 增至 6.2 GB。这比单看「搜索成功」更能验证整条链路。

扩大上下文后,OzAI 使用搜索结果回答 2026 年 F1 问题

上下文完整也不等于事实可靠。按原文给出的文档对照,KEDA Kafka scaler 的默认 lagThreshold 是 10,模型却自信回答 1000。它还自报知识截止于 October 2023,但这只是模型的回答,不能当作经过验证的训练信息。

作者称,后续加入文档检索增强生成(RAG)后,10 道 KEDA 问题的正确数从 1/10 提升到 8/10。本文尚未展开题目、评判标准和完整实验,能确认的是作者报告了这组结果。

IDE 接入则暴露了协议细节。VS Code 的 Continue 扩展可以通过网关聊天和修改代码,但自动补全使用中间填充(FIM),需要光标前后的代码。作者发现网关的 completions 端点丢失了 suffix、raw 参数,代码模型于是开始解释斐波那契数列,而不是补函数。

最终方案是聊天经过网关,自动补全直连 Ollama,代价是补全不再进入网关用量日志。Cursor 的自定义模型调用来自其服务器,无法访问本机 localhost;Cloudflare Tunnel 和 Access 是作者后续计划,本文尚未实现。

我的判断

这套实践最值得借鉴的是排查方法:先测吞吐,再查请求日志,再用暗号验证上下文是否真的抵达模型。它把「模型感觉不聪明」拆成了能定位的工程问题。

但几处结论需要保留边界。每个模型只有一次单请求测速,并发测试也只覆盖这台机器和当前配置,不能据此认定所有 LLM 服务都只能串行工作。作者提到的 vLLM 连续批处理,正是另一种服务方式。

同样,关闭推理、减少后台任务,是响应速度与功能之间的取舍。作者没有提供回答质量或延迟分布的完整对照,这部分属于经验之谈。

与直接调用托管 API 相比,OzAI 更适合学习推理服务、验证本地工具链。它证明了笔记本可以搭起完整调用路径,还没有证明自托管更便宜、更准确或更适合生产。搜索接入也只说明没有把查询交给第三方 AI 提供商,不等于查询不会离开本机。

能拿来做什么

  • 给前端或 Node 聊天应用接本地模型时,可以先固定兼容 OpenAI 的调用入口,再通过模型别名区分快速聊天和推理模式,并验证当前客户端是否正确传递参数。
  • 排查搜索或 RAG「接上却没效果」时,可以在长上下文的开头、末尾分别放入测试暗号,同时检查 prompt_tokens,确认内容没有在中间环节被截断。
  • 验证多人可用性时,可以复用 1、2、4、8 并发的测试思路,同时记录首 token 时间和总 tok/s,避免只凭单人聊天体验判断容量。
  • 接入 IDE 自动补全时,应单独验证 FIM 的 suffix、raw 是否抵达 Ollama;如果采用直连方案,也要明确哪些请求不会进入网关日志。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Agent上下文未满,工具结果为何仍被截断
下一篇
RAG 文档处理:先保留结构,再切分

资讯速览

dev.to · AI · 2026-11-02 15:57

AI 评分 8.0 / 10

相关标签

#本地部署#模型服务#接口网关

继续阅读

  • 游戏实验揭示多智能体协作的协调成本
  • Agent上下文未满,工具结果为何仍被截断
  • RAG 文档处理:先保留结构,再切分
  • 英伟达开源语义层库,为智能体SQL提供依据
  • 代理安全不能只依赖用户点击批准