最近一段时间我一直在本地折腾 DeepSeek、Qwen 和 Ollama 这套组合,结果桌面标签页越开越多:一个网页在聊 DeepSeek,一个控制台在跑 Ollama 命令,还有一个在翻 Qwen 的文档,API Key 散落在记事本里,会话记录也是一段一段的,中间串不起来,特别难受。后来我找到一个小众但很对味的方案——一个纯前端、零后端的本地优先大模型工作台,仓库代号就叫 Lab。它把 DeepSeek、Qwen、Ollama 和 Claude 全部收进同一个浏览器窗口,会话记录只存在本地,不用起任何后端服务,装完就是一套可以长期用的大模型工作台。
如果你平时主要用 ChatGPT 网页版或者某个平台自带页面,可能对这个项目没太大感觉。但如果你像我一样,手上有好几个模型的 API Key,又跑着本地 Ollama 模型,那你一定会理解“把所有模型塞进一个界面,还能统一管理会话”这件事有多爽。这篇文章我就从架构设计、核心功能拆解、部署配置到踩坑排查,完整讲一遍这类纯前端工作台到底怎么玩,适合哪些人,有哪些坑。
1. 为什么要选纯前端零后端的本地优先后端架构
1.1 传统大模型工具的架构代价
先说说市面上主流的大模型聊天工具是怎么做的。Open WebUI 是很优秀的项目,功能多、插件多、用户体系也完整,但它是典型的前后端一体架构,部署需要 Docker,底层还要起 Python 服务,数据默认放在数据库里。如果你想在多台设备上用,还得配反向代理、考虑认证,整套下来已经接近一个小型软件项目了。
LobeChat 也很出名,界面漂亮,插件生态丰富,但它的默认部署方式是 Next.js 前后端一体,至少需要一个 Node 服务在跑。Chatbox 这类桌面应用看起来是“装个 App 就能用”,实际上它内置了运行时,本质上是把一个后端进程打包进了客户端。不是说这些方案不好,而是对很多只是想“本地聊个模型、管理一下 API Key”的人来说,它们的架构成本明显偏高。
我个人的需求其实很朴素:不用装 Docker,不用维护数据库,不用注册服务器,打开浏览器就能用,会话记录我自己能控制。这种需求下,纯前端方案就是最优解,体积小、启动快、没有服务端可以崩,数据归属于浏览器本地,隐私性天然更好。
1.2 纯前端为什么也能驱动大模型
你可能会问,没有后端,浏览器怎么调大模型?这里的关键在于,几乎所有主流模型服务商都提供了 HTTP API,而浏览器本身就是一个 HTTP 客户端。当你把 API Key 配置好后,前端直接向模型的 API 端点发起请求,拿到响应渲染到页面上,逻辑上完全说得通。
但浏览器直连有一个前提,就是服务端必须允许跨域访问,也就是返回 CORS 响应头。好消息是,很多云服务商的 API 已经支持浏览器跨域,比如 DeepSeek 开放平台的接口、OpenRouter 这类聚合平台的接口,都能从浏览器直接调用。Ollama 是跑在本地的服务,默认本地监听,跨域策略也可以通过环境变量放开,所以纯前端方案在技术上完全可行。
这样一来,整个工作台可以做成完全静态的网站:一个 HTML 文件加一堆 JS 资源,构建完之后往任何静态托管平台一扔就能用。没有独立的 API 代理层,没有会话数据库,所有状态都落在浏览器自己的存储里。整个架构轻到令人发指,是我喜欢它的核心原因。
1.3 本地优先到底意味着什么
本地优先这个概念的含金量,用一次就懂。传统在线工具把对话记录存到服务端,你删除账号或者服务商跑路,数据说没就没。本地优先方案则把所有会话历史、Prompt 模板、模型配置全部保存在浏览器本地存储中,比如 IndexedDB 和 localStorage。你在本地聊了什么,模型厂商并不知道,因为聊天内容是以参数形式直接发出去的,并不会经过任何第三方服务器存储。
本地优先的另一个直接收益就是离线可用。你只要配好 Ollama 本地模型,把网线拔了照样能用,特别适合在飞机上、地铁里或者网络不稳定的场景。我自己经常在通勤路上用笔记本电脑继续处理之前的工作会话,完全不受网络影响。
当然,本地优先也有代价:换设备时配置和数据不会自动同步。我一般会在旧设备上把常用 Prompt 模板复制一份,新设备上重新粘贴配置。不过换个角度想,这也意味着你没有把数据交给任何人,隐私安全是自己掌控的,这在现在的环境里反而是一种难得的优点。
1.4 和主流方案的对比
| 方案 | 是否需要后端 | 数据存储位置 | 安装成本 | 适合人群 |
|---|---|---|---|---|
| Open WebUI | 需要 Docker + Python | 数据库 | 高 | 团队协作、功能需求全面 |
| LobeChat 自部署 | 默认需要 Node 服务 | 数据库/对象存储 | 中高 | 喜欢插件生态和精致 UI |
| Chatbox 桌面端 | 客户端内置运行时 | 本地数据库文件 | 中 | 喜欢独立 App 的用户 |
| 纯前端工作台(Lab 这类) | 不需要 | 浏览器本地存储 | 极低 | 个人日常、本地模型、隐私敏感场景 |
2. 深入拆解 Lab 工作台的核心能力
2.1 统一 Provider 抽象层,屏蔽所有模型差异
一个模型工作台如果只支持一个模型,那根本不需要特意做。Lab 这类项目真正的技术难点,是把差异巨大的各家 API 协议统一起来。DeepSeek、Qwen、Ollama 都遵循 OpenAI 的 /chat/completions 接口格式,请求体和响应结构基本一致,处理起来还算轻松。但 Claude 走的是 Anthropic Messages API,请求结构完全不同,连消息格式、流式事件类型都不一样。
所以项目内部一般会有一个 Provider 抽象层。前端统一维护一套内部的消息结构,比如数组里每项是角色加内容。发给各家模型时,再根据当前选择的 Provider 把内部消息转换成对应 API 的请求格式,响应回来时再反向解析成统一结构。这样你在界面上切换模型时,对话上下文格式不会有任何感知差异,用起来特别顺滑。
我自己在配置时最直观的感受是,同一个会话里想从 DeepSeek 切到 Ollama 继续聊,上下文依然是连贯的,因为底层消息历史是同一份,只是发送时协议转换方式变了。习惯了这种统一体验之后,再让我回各个平台分别聊,就会感觉很割裂。
2.2 流式输出是体验的核心,处理不好就是灾难
大模型响应动辄几百上千字,如果等完整返回再展示,用户体验是灾难性的。所以所有主流前端工作台都会做流式输出。这里用到的底层能力是 SSE 配合 fetch 的 ReadableStream,也就是浏览器收到的是分段抵达的文本流,前端每拿到一段就追加到对话气泡里,实现类似打字机的逐字输出效果。
Lab 这类纯前端项目对流式处理的精细程度,直接决定了使用体验。我上手之后发现的细节是,不同模型对流式的支持程度不一样:DeepSeek 的 deepseek-chat 流式返回比较标准,内容一段段来;DeepSeek 的 deepseek-reasoner 会在流式过程中先返回思考过程,再返回正式回答;Ollama 自带 OpenAI 兼容端点,流式格式也基本一致;Claude 则有自己的流式事件类型,比如 message_start、content_block_delta 这些,解析逻辑完全独立。
所以如果你看项目源码,会看到每个 Provider 都有单独的流式解析器,这就是为了应对这些差异。用户侧的感知是打字流畅、中断及时,而这些体验是靠大量细节堆出来的。
2.3 会话管理和 Prompt 模板的本地化存储
会话管理是工作台的基本功。纯前端项目一般会把每个会话保存为独立的记录,包含会话标题、消息列表、使用的模型配置、创建时间等信息,存储位置选 IndexedDB。IndexedDB 的好处是能存结构化对象,容量远大于 localStorage,适合存储长对话历史。
Prompt 模板这个功能我也非常依赖。我平时写文章、写代码、做翻译、做总结,每个场景都有固定的指令前缀。在 Lab 里,这些模板可以保存下来,新建会话时一键选择,不用每次重复输入。模板同样存在本地,不会上传,换模型也能复用。
这里有个小建议:如果你从别的工具迁移过来,先花半小时把你的常用 Prompt 模板整理好,再开始日常使用,后面的效率提升非常明显。我就是在迁移时顺手整理了大概十几个模板,现在工作流丝滑很多。
2.4 多模型会话切换与并发调用
既然把多个模型塞进了一个工作台,合理的操作逻辑应该是随时切换当前会话使用的模型,而不是每个模型开一个独立聊天窗口。Lab 这类项目一般会支持会话级别和全局级别两种模型选择方式:全局设置里配置好所有 Provider 和默认模型,新建会话时直接继承;单个会话内部也可以临时切换模型,切换后后续消息使用新模型,历史消息继续保留。
有些项目还支持把同一个 Prompt 并行发给多个模型,然后把所有回答同时渲染出来,方便横向对比。这个功能对做 prompt 评测或者模型选型的场景特别有用。我自己在对比 Qwen 和 DeepSeek 的中文写作能力时,就经常用这个功能,效率比开多个窗口高很多。
3. 从零部署到跑通四个模型
3.1 把项目跑起来
Lab 这类纯前端项目,交付形态通常是一个基于 Vite 的静态 Web 应用。你只需要把项目代码拿到本地,然后按常规前端项目流程启动即可。
# 拉取项目代码(以 Git 为例) git clone [项目地址] lab-workbench cd lab-workbench # 安装依赖 npm install # 本地开发模式启动 npm run devnpm run dev 启动后,终端会打印一个本地地址,一般是 http://localhost:5173。浏览器打开这个地址,工作台界面就出来了。
如果你不想动命令行,也有更省事的路径:项目发布时构建出来的 dist 目录是一堆纯静态文件,随便找个静态服务器,甚至双击 index.html 都可能直接打开(部分功能会受浏览器安全策略限制,建议还是用静态服务器方式)。我自己现在的用法是构建一次之后,放到树莓派上的 Nginx 静态目录里,全家设备都能通过局域网访问,体验和在线服务一样,但服务端只有一个几十兆的轻量 Web 服务,干净利落。
3.2 接入本地的 Ollama 模型
Lab 支持 Ollama 是它最吸引我的一点,因为 Ollama 是本地模型运行的事实标准之一。先确保你电脑上装好了 Ollama,然后拉取你需要的模型:
# 拉取 Qwen 2.5 7B 作为日常模型 ollama pull qwen2.5:7b # 再拉一个轻量的 DeepSeek R1 蒸馏版做测试 ollama pull deepseek-r1:7b接下来非常关键的一步:让浏览器能够访问 Ollama 的服务。Ollama 默认监听 http://localhost:11434,并且默认只允许来自本机的特定请求,浏览器页面直接调用可能会被跨域策略拦截。解决办法是给 Ollama 设置一个环境变量,让它接受浏览器来源的跨域请求。
在 macOS 或 Linux 下:
# 允许所有来源访问 Ollama export OLLAMA_ORIGINS="*" ollama serve在 Windows 下,可以通过系统环境变量添加 OLLAMA_ORIGINS,值为 *,然后重启 Ollama 服务。
设置好之后,在 Lab 的配置页面新建一个 Ollama Provider,API 地址填 http://localhost:11434/v1,模型列表会自动读取到本机已经拉取的模型。选好模型,直接就能本地对话,断网也能用。这个体验我建议每个人都试一次,真的会上瘾。
3.3 配置 DeepSeek 和 Qwen 云 API
DeepSeek 的接入比较简单。先去 DeepSeek 开放平台注册账号,创建 API Key,然后在 Lab 里选择添加 OpenAI 兼容 Provider:
- API 地址填 https://api.deepseek.com(部分环境需要填 https://api.deepseek.com/v1,两者等价)
- 模型名填 deepseek-chat 或 deepseek-reasoner
- API Key 粘贴你申请的 Key
deepseek-chat 是通用对话模型,日常写作、问答、翻译都够用。deepseek-reasoner 是深度思考模型,会在回答前生成一段推理内容,适合处理逻辑推理、复杂分析类任务。配置好之后,两个模型都能在同一个工作台里切换使用。
Qwen 这边,走的是阿里云百炼的 OpenAI 兼容接口。同样需要先开通百炼服务,拿到 API Key,然后配置 OpenAI 兼容 Provider:
- API 地址填 https://dashscope.aliyuncs.com/compatible-mode/v1
- 模型名填 qwen-plus 或 qwen-turbo,按需选择
- API Key 填百炼的密钥
有一点需要注意:Qwen 的模型名体系里,qwen-plus、qwen-turbo、qwen-max 这些是平台命名,跟你在 Ollama 本地看到的 qwen2.5:7b 不是一回事。云端 API 必须使用平台定义的模型标识,不要直接搬运本地模型名。
3.4 配置 Claude 时的 CORS 问题
Claude 的接入比较特殊。Anthropic 官方 API 使用的是自己的 Messages API,而不是 OpenAI 兼容格式,所以在选择 Provider 类型时,需要选择 Anthropic 类型而不是 OpenAI 兼容类型。API Key 在 Anthropic Console 创建,模型名类似 claude-sonnet-4-20250514 或者 claude-3-5-sonnet-20241022,以官方控制台给出的模型 ID 为准。
不过在实际使用中,浏览器直连 Anthropic 官方 API 可能会遇到 CORS 限制。如果你在 Lab 里配置完 Claude 后,发送消息报跨域错误,不要慌,一般有两条路:一是通过支持 CORS 的模型聚合服务去接 Claude,比如 OpenRouter 这类平台,这种方式在纯前端项目里非常常见;二是本地起一个极轻量的转发服务,把请求从浏览器转发到 Anthropic API,这就等于你给 Claude 单独配了一个本地跨域助手。
我个人目前的用法是:Ollama 本地模型做日常草稿和总结,DeepSeek 做主力日常问答,Claude 处理需要长上下文和精细化写作的任务。一个页面,四个模型,切换成本几乎为零。
3.5 构建发布成可长期使用的应用
配置好之后,最后一步是把工作台构建成正式版本,方便长期使用。Vite 项目的构建命令:
npm run build构建完成后,项目根目录下会生成一个 dist 文件夹,里面就是全部静态资源。你把这个文件夹扔到任意静态托管平台即可。比如用 GitHub Pages、Vercel 静态部署,或者在家里电脑、树莓派上装一个 Nginx / Caddy,把 dist 目录指过去,局域网内所有设备都能访问。
我自己现在是构建一次放到家里服务器上,手机、平板、工作电脑都能打开同一个地址使用。因为数据存储在各自的浏览器本地,所以每台设备上的会话记录是独立的,这个符合本地优先的设计哲学,不一定适合所有人,但对我这种单设备深度使用场景来说很合适。
4. 典型问题排查与避坑经验
4.1 CORS 跨域报错
这是纯前端方案绕不开的第一大坑。在浏览器控制台看到 Access-Control-Allow-Origin 相关的报错时,先确认你是不是访问的官方 API 域名的正确版本。Ollama 的跨域需要在 Ollama 服务端设置 OLLAMA_ORIGINS,云服务商的跨域则要看对方是否开放了浏览器跨域。DeepSeek 和 OpenRouter 这类平台实测可以直连,Anthropic 官方 API 在浏览器直连可能被限,建议改用聚合平台或本地转发。
4.2 Ollama 拉取模型速度慢
很多人卡在第一步,ollama pull 模型的时候速度感人。这个一般是网络环境造成的下载瓶颈,解决方案一般有两个方向:一是配置国内可用的镜像源,通过环境变量指向镜像地址再拉取;二是找一台网络条件好的机器先把模型拉下来,再通过离线方式导入。Ollama 社区对这个问题的讨论很多,不同网络环境下最优解不一样,需要自己实测几次。
4.3 流式输出中途断流
如果对话输出到一半突然停了,可能是网络不稳定导致连接中断。这时候工作台一般会显示重试或者继续生成的按钮,不会让你手动复制重来。我自己遇到过的另一个情况是,某些模型在长输出时响应时间太长,超过了浏览器的默认等待时间,这个建议到 Lab 的设置里把超时时间调大一点。我的经验值是把超时调整到 120 秒以上,基本能覆盖绝大多数场景。
4.4 API Key 的安全边界要清楚
纯前端工作台最需要注意的一点是:你的 API Key 保存在浏览器本地,真实存在于前端代码可访问的存储里。这本身不是问题,但意味着你不能把这个工作台随便部署到公网上让别人用,因为任何能打开页面的人,都可以从浏览器开发者工具里拿到你配置的 Key。如果你的工作台只给自己用,限制为本机访问或者局域网访问,风险是可控的。如果你非要部署到公网,建议使用短期额度受限的 API Key,或者干脆给工作台套一层访问认证(但这又违背了零后端的初衷)。很多纯前端项目其实默认就是这个定位,你一定心里要有数。
4.5 长会话带来的卡顿和上下文问题
对话越长,浏览器内存占用越高,这跟纯前端还是后端无关,主要是长文本渲染和大模型上下文窗口的物理限制。Lab 这类工作台一般会提供上下文长度限制设置,超过限制后自动截断早期消息。我遇到卡顿时一般会手动开一个新会话,或者把长会话里的关键结论复制出来存入模板,然后清空上下文继续。这个习惯能让你在任何模型工作台里都保持高效。
4.6 模型切换后答非所问
如果你在一个会话里从 DeepSeek 切换到 Ollama 本地模型,发现后面的回答质量骤降,不要急着怀疑工作台的问题。大概率是本地模型参数规模太小,接不住前面云模型的高复杂度上下文。我现在的做法是把复杂任务分到专用会话里,同一个会话内只用同类模型,避免因上下文风格混杂带来的效果下降。
根据我个人实际使用的体会,这类纯前端本地优先工作台最打动我的,不是某个花哨功能,而是它把主动权完全交还给了用户。你的 API Key 你自己管,你的数据在本地,你选择哪个模型就直连哪个模型,没有任何中间商。如果你也在多个模型平台之间来回切换,或者对对话数据的隐私比较敏感,真的建议花一个下午把这类工作台搭起来,配上 Ollama 和几个云端模型,体验一下所有入口统一、数据本地可控的感觉。这个投入,绝对值回票价。