LibreChat — 让一份聊天 UI 同时连 OpenAI / Anthropic / Google / 本地模型,对话留在自己的服务器
是什么
LibreChat 是一个开源的”自己装一台 ChatGPT”——你 docker compose 起来,浏览器打开就是熟悉的聊天界面,但你能自由切换底层用哪家 LLM:OpenAI、Anthropic、Google、AWS Bedrock、本地 Ollama,甚至任何”OpenAI 兼容的 API 地址”。
日常类比:像一台通用遥控器——同一份按键面板(聊天 UI),后面接的电视可以是索尼、三星、海信。你按”换台”,遥控器内部翻译成各家厂商的红外协议,但你不需要知道。
它解决的不是”我想用 ChatGPT”——那直接去 chat.openai.com 就行。它解决的是”我们公司 50 个人想共用一个内部 ChatGPT,对话不能上传到 OpenAI 服务器,要能切 Claude,要能接公司内部的工具”。所以它有真后端(Express)、真数据库(MongoDB)、真鉴权(JWT + 多用户权限),不是一个浏览器扩展。
GitHub 上 37k stars,MIT 协议,可以直接 fork 改名卖钱。技术栈是 TypeScript + JavaScript 双栈(packages/ 全 TS,api/server/ 仍是 JS 在迁移中),前端 React 19 + Vite,后端 Express + Mongoose,搜索 Meilisearch,可选 Redis 做多副本。
为什么重要
不理解 LibreChat 的设计,下面这些事都没法解释:
- 为什么”多家 LLM 切换”这件事用抽象基类继承会越写越糟,正确做法反而是每家写一个独立函数
- 为什么浏览器刷新一下,正在生成的回答还能接着看——传统 SSE 流明明刷新就丢
- 为什么 plugin 生态可以外包给 MCP 协议而不必自己定义一套(对比 Dify 自研 plugin daemon)
- 为什么”自托管 ChatGPT”这件事不是一个项目,而是 Dify / Lobe Chat / Open WebUI / LibreChat 四种心智模型的拉锯
- 为什么 Express 这种”老派”框架在 2026 年还能撑起 37k stars 的产品——关键在于中间件链式架构和职责分层
核心要点
LibreChat 的工程价值压在 三个核心抽象 上:
-
per-provider 翻译函数(不是抽象基类):每家 LLM 写一个独立的
getLLMConfig(credentials, options)函数,返回该 provider 真实 SDK 需要的客户端选项。类比:每家厂商一份翻译手册,而不是逼所有厂商遵守同一个接口规范——因为它们本来就长得不一样。代码层面 OpenAI / Anthropic / Google / Bedrock 各自一个独立目录,平级,没人继承谁。 -
可恢复 SSE(GenerationJobManager):把流式输出拆成三层——
jobStore持久化已生成的 chunks、eventTransport做 pub/sub、runtime持有不可序列化的 abort 控制器。浏览器刷新后用streamId重新订阅,把已生成内容重放一遍再续上。类比:直播 + 时移功能。单进程默认 InMemory,多副本切 Redis 后主代码无改动。 -
MCP 作为 plugin 抽象:放弃自研 plugin 协议,直接接 Anthropic 推的 MCP(Model Context Protocol)开源标准。Claude Desktop / Cursor 装的 MCP server 直接能用。类比:不自己造 USB 协议,直接支持 USB-C。代价是丢失协议层定制权,收益是与生态共振——MCP 标准升级 LibreChat 跟着升 SDK 即可。
实践案例
案例 1:docker compose 起全栈,UI 里切换 provider
完整命令清单(约 3 分钟拉镜像 + 启动):
git clone --depth 1 https://github.com/danny-avila/LibreChat.gitcd LibreChatcp .env.example .env # 编辑填 OPENAI_API_KEY 和 ANTHROPIC_API_KEYcp librechat.example.yaml librechat.yamldocker compose up -d # 起 mongo + meilisearch + librechat 三个容器docker compose ps # 应该看到 4 个 service runningopen http://localhost:3080 # 注册第一个账号自动成为 admin进 UI 后发一条消息走 OpenAI,再用顶部的 EndpointMenu 切到 Anthropic 继续聊——同一对话窗口、不同模型,消息历史完整保留。这是因为 messages 在 MongoDB 里按 conversation 维度存,不绑 endpoint。如果你想接团队的其他成员,注册新账号即可,admin 用户能在 UI 里管理 quota 和封禁。
案例 2:用 console.log 验证抽象边界
在 packages/api/src/endpoints/anthropic/llm.ts 的 getLLMConfig 函数末尾、return 语句之前加一行:
console.log('[ANTHROPIC]', { model: requestOptions.model, hasThinking: requestOptions.thinking != null, hasVertex: typeof requestOptions.createClient === 'function',})UI 里发 3 条消息:第 1 条用 OpenAI、第 2 条切 Anthropic、第 3 条切 Anthropic + thinking。看后端日志(docker compose logs librechat | grep ANTHROPIC)——只有第 2、3 条出现 [ANTHROPIC],第 1 条根本不走这个文件。这就证明了 controller 代码对 provider 完全无知,“我现在调谁”这个信息只在 endpoints/<provider>/ 这一层存在。这种用扰动法验证抽象边界的小实验,比读 100 行架构图都更有效。
案例 3:浏览器刷新看 resumable SSE
让 Anthropic 写一段 500 字回答,写到一半时按浏览器刷新。新页面打开后,前端会带 streamId 重新连 /chat/stream/:id,后端把已生成 chunks 从 jobStore 重放一遍,然后把后续的实时 chunks 续上——你看到回答从开头出现,到刷新前的位置时速度变慢(实时 token),整段不丢。
要让这一切工作,SSE 入口必须设三个 header:Content-Type: text/event-stream、Cache-Control: no-cache, no-transform、X-Accel-Buffering: no(专门告诉 Nginx 别缓冲)。少一个都会导致 chunk 在中间某层被攒起来,体验直接退回到”等几秒一卡顿”。
如果你切到 Redis transport(多副本部署),chunk 不在内存而在 Redis Stream 里,新订阅者可以是另一台机器——这就是为什么 LibreChat 不需要 sticky session 也能横扩。
踩过的坑
- provider 抽象用基类继承会腐烂:OpenAI 有
reasoning_effort,Anthropic 有thinking,Google 要 service account JSON 凭证,硬塞class LLMClient抽象基类最终会逼出extraOptions: Record<string, any>后门,基类成空壳。LibreChat 的解法是根本不抽象,每家一个独立函数,签名一致但函数体完全自由。 - SSE 直接挂在
res上 = 浏览器刷新就丢消息:传统做法是res自己持有 EventEmitter、断开就emit('close'),这样无法 resumable。必须把 chunks 写到jobStore,res只是订阅者,下个新订阅者还能拿到。 - Nginx 反代下 SSE 会卡顿:必须设
X-Accel-Buffering: no+Connection: keep-alive,否则 Nginx 缓冲 chunks 等到一定大小再发,SSE 流变成”几秒一卡顿”。这种坑只有踩过的项目才会写在中间件里,新人独立写很难提前想到。 - MCP 双层连接的优先级陷阱:
getConnection先查 app-level 命中即返回。如果 app-level 是公共 readonly token、user-level 才是用户 OAuth 私库 token,这个查找顺序会让用户期望的”用我的 token”被覆盖——配置 librechat.yaml 时要小心顺序。
适用 vs 不适用场景
适用:
- 团队 50 人共用一个内部 ChatGPT,要 OpenAI + Anthropic 混用 + 数据留在自己 MongoDB
- 想给业务系统暴露 OpenAI 兼容的
/v1/chat/completionsendpoint,用 LibreChat 做网关 + logging + quota(业务侧 SDK 改 baseURL 就能接入) - 接团队私有的 MCP server(如内部数据库、Slack、GitHub)让 agent 调用
- 需要”浏览器刷新不丢消息”的可恢复流式输出
- 单实例 < 100 用户的中等规模——稳定,docker compose 一键起;超过这个量级要自己上 Redis + Nginx + Mongo replica
不适用:
- 个人 BYO key 重 UI 美学 → 用 Lobe Chat(前端做得最漂亮,后端最薄)
- 主要跑 Ollama 本地模型 → 用 Open WebUI(Ollama 团队主推,本地模型一等公民)
- PM / 设计师不写代码做 LLM 应用 + RAG → 用 dify(visual workflow 平台派,重 10 倍但定位是”做应用”而非”做 chat”)
- 极简部署 + Vercel 一键 → 用 NextChat(无后端、零运维)
- 真正的多租户 SaaS(给 100 个企业用)→ LibreChat 的
tenantId校验是 row-level 不是物理隔离,需自己加额外保护
历史小故事(可跳过)
- 2023-02:danny-avila fork 自 ChatGPT-Clone(一个早期开源 ChatGPT UI),最初只有单 provider
- 2023 年中:加入 Anthropic / Google 支持,开始做”多 provider”定位,区分自己和 NextChat 等单 provider 项目
- 2024 年:开放赞助 + 企业咨询商业化路线,contributors 700+ 但核心 5 人;选 MIT 协议而非 Apache + brand 限制(Dify 路线),换更广的采用
- 2024-11:Anthropic 发布 MCP 协议,LibreChat 是最早接入的开源 chat 之一,
packages/api/src/mcp/目录成型 - 2025 年:
GenerationJobManager三层架构上线,从单进程 SSE 升级到 Redis 可恢复多副本,单进程 / 多副本切换变成一行配置 - 2026 上半年:OpenAI Responses API 兼容层加入,Code Interpreter 支持 7 种语言(Python / Node.js / Go / Java / Rust 等)
- 2026-05:v0.8.6-rc1 发布,37k stars 稳定爬升,与 Lobe Chat / Open WebUI 同梯队
学到什么
- “多 backend variant”不要套抽象基类——当 N 种实现真实差异巨大,写 N 个独立函数 + 调用方拿 config 后统一实例化,比继承更不容易在长期演进里腐烂成
extraOptions: any后门 - 资源所有权要和 pub/sub 解耦——把”谁产生数据”和”谁消费数据”拆开,单进程是 InMemory transport、多副本切 Redis transport,主代码无需改动;这是大型 Node.js 应用的通用范式
- 协议外包优于自研——能用业界共识的开源协议(MCP)就别自己造一套(plugin daemon RPC),代价是丢失协议层定制权,收益是与生态共振
- license 是商业模式选择——MIT 完全开放靠企业咨询变现 vs Apache + brand 限制靠协议变现,两条路都成立但战术差异巨大,选错了会反噬
- 小扰动验证抽象边界——给 anthropic/llm.ts 加一个 console.log 就能证明 controller 对 provider 无知,比读架构图有效得多
延伸阅读
- LibreChat GitHub 主仓 —— README / 配置示例 / 部署文档
- LibreChat 官方文档 —— self-host 教程 + librechat.yaml 配置参考
- MCP 协议规范 —— 想理解 plugin 抽象层就要读这份
- Anthropic Vertex AI deployment 指南 —— 解释 LibreChat 为什么要在 anthropic/llm.ts 里搞 Vertex 双路径
- dify —— 平台派对照组:visual workflow + 多租户 + plugin daemon RPC,定位”做应用”而非”做 chat”
- continue —— IDE 派对照组:编辑器内嵌 + 本地 + 远端模型混合
- claude-code —— Anthropic 官方 CLI agent,与 LibreChat 都重度依赖 MCP 但形态完全不同
关联
- dify —— 同 Season AI 应用范式三角的”平台派”,与 LibreChat 的”通用 chat 派”形成对照
- continue —— 同三角的”IDE 派”,三家心智模型互相参照才能看清解空间
- mcp-ts-sdk —— LibreChat plugin 生态的协议底座,由 Anthropic 维护
- langchain —— LibreChat 的 agent 子模块(@librechat/agents)封装了 LangGraph
- express —— LibreChat 后端框架,中间件链式架构是它的工程范式
- mongodb —— LibreChat 的对话存储,messages / convos / agents 都在这里
- react —— LibreChat 前端,ChatView / Endpoints / Agents 组件树跑在 React 19
- redis —— 多副本部署时 SSE 走 Redis Stream + Pub/Sub,单进程默认 InMemory
- meilisearch —— LibreChat 的全文搜索引擎,对话历史中文分词友好
- claude-code —— Anthropic 官方 CLI,同样深度依赖 MCP 协议但形态完全不同
反向链接
- claude-code —— Claude Code — Anthropic 终端编程助手
- continue —— Continue — 让 AI code review 跑成 git 跟踪的 PR status check
- express —— Express — Node.js 最经典的 Web 框架
- librechat —— LibreChat — 让一份聊天 UI 同时连 OpenAI / Anthropic / Google / 本地模型,对话留在自己的服务器
- mcp-ts-sdk —— MCP TS SDK — Model Context Protocol TypeScript 实现
- meilisearch —— MeiliSearch — 开发者友好的搜索引擎
- mongodb —— MongoDB — 文档型 NoSQL 数据库
- react —— React UI 组件库
- redis —— Redis — 内存键值数据库