OSW

OSW

把你手上所有的大模型渠道,合成一个本地地址。当前渠道挂了,自动换下一个。

English | 简体中文

CI 构建状态 测试覆盖率 最新版本 许可证:PolyForm Noncommercial 1.0.0 累计下载量 GitHub 收藏数 最近提交

Node.js >=22 pnpm 12.14.0 支持平台:macOS、Windows、Linux

所有模型,一个地址:跨供应商自动故障转移

OSW 在本机跑一个代理服务。你把能用的渠道都配进来(不同供应商、不同账号、不同模型),排好优先级,然后让所有 AI 客户端统一指向一个本地地址。剩下的事它自己做:识别协议、按顺序挑渠道、把请求送出去、失败就换下一个,并把真实发生的一切记录清楚。 于是客户端只会看到成功的那一次。 **OSW 是 One Switch 的简称。** 名字就是产品本身:给你手上所有渠道装一个开关 —— 入口只有一个本地地址,供应商只需配在这一处,哪个渠道挂了就拨到下一个。 --- ## 功能特性 - **一个入口,配一次就够。** 所有客户端只认一个本地地址,供应商、账号、模型都在它后面换:以后改哪一项都只动 OSW,不用再去翻每个工具的设置。 - **故障是常态。** 网络抖动、连接超时、限流、额度耗尽、密钥失效、上游 5xx —— 渠道会挂是预期内的事,不是意外,请求会自动换到下一个渠道,让你在渠道挂掉时继续干活是产品该做的。已经开始流式的响应不会被中途拼接成两份:宁可报失败,也不给你混杂的回答。 - **默认透传。** 不解析协议、不改写、不转换,除非你明确要求。最安全也最快的请求,是代理几乎没碰过的那一个。 - **每个请求都查得到真相。** 实际走了哪个供应商、哪个模型、第几次尝试才成功、耗时多少、首字多快、每秒多少 Token、缓存命中了多少 —— 全都落库可查。 - **不同供应商的小脾气,不用写代码。** 需要补一个 `User-Agent`、删掉一个 Header、把某个字段固定成 `0.7`?用请求重写规则配出来就行,编辑器里还能直接对着用例验证。 - **默认只在本地。** 只监听 `127.0.0.1`,密钥交给系统加密存储,请求只发往你配置的上游:没有账号体系、没有云同步、没有中转服务器。唯一一处例外是默认开启的匿名使用统计,它不携带任何请求内容(口径见 [apps/docs/specs/operations/telemetry.md](./apps/docs/specs/operations/telemetry.md))。 - **中英文界面**,亮色 / 暗色 / 跟随系统随便切,常驻系统托盘,支持开机自启和自动更新。 --- ## 安装 到 [最新版本](https://github.com/yinxulai/osw/releases/latest) 下载对应平台的安装包。产物命名统一是 `OSW-<版本>-<平台>-<架构>.<后缀>`,每个安装包都配一个 `.sha256` 校验文件。 | 平台 | 架构 | 下载哪个文件 | | --- | --- | --- | | macOS | Apple Silicon | `OSW-<版本>-mac-arm64.dmg` | | macOS | Intel | `OSW-<版本>-mac-x64.dmg` | | Windows | x64 | `OSW-<版本>-win-x64.exe` | | Windows | ARM64 | `OSW-<版本>-win-arm64.exe` | | Linux | x64 | `OSW-<版本>-linux-x86_64.AppImage` | | Linux | ARM64 | `OSW-<版本>-linux-arm64.AppImage` | 1. **macOS** —— 打开 `.dmg`,把 **OSW** 拖进「应用程序」。构建目前是 ad-hoc 签名且未公证,首次打开若被系统拦下,去「系统设置 → 隐私与安全性」放行,或在 Finder 里右键应用选「打开」。 2. **Windows** —— 直接运行 `.exe`。若 SmartScreen 提示未知发布者,点「更多信息 → 仍要运行」。 3. **Linux** —— 给 AppImage 加执行权限再运行: ```bash chmod +x OSW-*-linux-*.AppImage ./OSW-*-linux-*.AppImage ``` 装好后 OSW 常驻系统托盘,并会自己检查更新。Windows / Linux 上是下载后就地安装;macOS 因为签名状态,只能检查更新并跳到 DMG 下载页。 装完接着看下面的[三步上手](#三步上手)。想按功能逐项了解,见 [`apps/docs`](./apps/docs) 使用手册(基于 [Clarify](https://github.com/taicode-labs/clarify) 构建)。 ## 界面预览 下面的截图会跟随 GitHub 主题在暗色与亮色之间切换,界面语言是中文。 渠道队列:拖拽排优先级,每个模型旁边是它最近的真实表现。 逻辑模型:渠道队列与实时指标 路由工作台:页头就能在节点图与一张从上往下读的规则表之间切换,两种模式回答同一个问题——「什么样的请求,落到哪个渠道组」;每次保存留一个版本,随时回滚。 智能路由:节点图与请求命中判定 请求日志:每次请求一行,展开就是完整的执行详情和原始用量。 请求日志:尝试级别详情与 Usage 统计分析:成功率、延迟、TTFT、TPS、缓存命中、模型排行、失败原因。 统计分析:指标卡、用量分布与模型排行 请求重写:统计卡、规则列表,以及「新建规则」里的模板菜单。 请求重写:规则列表与模板菜单 客户端配置:哪些客户端已经指向 OSW、哪些还需要改,能照抄的地址与密钥,以及每个客户端会动到哪些文件 —— 每次生成都是一个可回退的版本。 客户端配置:客户端列表、可复制的地址与密钥、生成文件的版本 ## 三步上手 ### 1. 添加渠道 打开 **模型管理** → 新增供应商,填名称、API Key、超时时间,以及这家供应商各协议的默认接口地址。 再在供应商下面添加真实模型 ID(例如 `gpt-4.1-mini`、`deepseek-reasoner`、`claude-sonnet-4`),并勾选它支持哪些协议。一个模型即使同时支持多个协议,在队列里也只占一行。 ### 2. 排优先级 进入 **逻辑模型**,把刚加的模型拖成你想要的顺序,启停不想参与路由的项。 顺手能做的事: - 每个模型旁边都能看到它最近一次成功的时间、连续失败次数,以及 TPS 和 TTFT,用来决定谁该排在前面。 - 逻辑模型卡片可以切到 **手动指定**,把请求钉死在某一个上游模型上(该行标出「当前指定」,其余显示「待命」)。 - 想知道渠道到底通不通:**模型管理** 右上角的 **连接测试** 能一次勾选多个渠道和协议并发验证,跑完直接给一份连通性报告。它会向每个目标发一次最小的真实请求,可能产生少量费用,也会记进请求日志。 ### 3. 改客户端地址 控制台的 **引导第二步** 就是本机服务的说明书:一条客户端该指向的地址、一张「本服务接受的接口」表。地址按当前监听端口实时拼出来,点一下就复制 —— 页面上只摆**一条**地址,另一种写法(带不带 `/v1`)降级成一句说明,因为两条只差一个 `/v1` 的地址并排摆,抄错行是这里最贵的错误。接口表直接铺开 —— 它本身就是这张参考表,收起来再让人点开只会白多一步。 同一步还就地嵌了**配置编辑器**:选一个在用的工具,在它**配置内容**卡头右边点**生成配置**(按内置默认模型改写)再按**保存内容**直接把它自己的配置改成指向本机服务,改错了**撤销改动**;机器上已经装了客户端的,也可以去[客户端配置](./apps/docs/source/zh/getting-started/client-config.mdx)点**全部生成配置并应用**,OSW 会改那个客户端自己的配置文件,并且每次改动前先留一份可回退的版本。 地址卡上只有这一条地址与一句说明:API Key 与模型名都不是要抄的值(前者填任意非空字符串即可,后者任意非空名字都受理),摆在这里只会让人以为「这里真有两个值要抄」。 | 你的客户端 | Base URL 填 | | --- | --- | | OpenAI 兼容(Chat Completions / Responses) | `http://127.0.0.1:9300/v1` | | Anthropic Messages | `http://127.0.0.1:9300` | > ⚠️ 这里最容易踩的坑:Anthropic 客户端自己会拼 `/v1/messages`,所以 Base URL **只要到端口为止**。如果多写了 `/v1`,最终请求会变成 `/v1/v1/messages`,代理认不出这条路径,只能给你 404。 模型名随便填 —— `default` 或任何非空名字都行,OSW 会在转发时替换成当前选中渠道的真实模型 ID。要求填 API Key 的客户端,填个任意占位值即可,真实密钥由 OSW 按供应商注入。 验证一下服务是通的: ```bash curl http://127.0.0.1:9300/v1/models ``` 监听地址和端口可以在 **设置 → 网络 → 监听服务** 里改,保存后代理就换到新端口了。 ## 深入细节 下面是这些承诺背后的细节 —— 按需扫一眼即可,每一块在[使用手册](./apps/docs)里都有更完整的展开。 ### 故障转移规则 | 上游发生了什么 | OSW 怎么做 | | --- | --- | | 网络错误、连接超时、流式空闲超时 | 换下一个渠道 | | `401`、`403` | 换下一个渠道,并累计该供应商的失败状态 | | `408`、`429` | 换下一个渠道 | | `5xx` | 换下一个渠道 | | 其他 `4xx`(比如参数写错) | 直接返回给你,不切换 —— 换渠道也救不了 | | 已经开始把响应传给你之后断开 | 终止这次请求,不拼接另一个渠道的输出 | 默认是连续失败 3 次进入冷却、首轮冷却 30 秒(每次失败递增,最长 5 分钟)、流式响应 30 秒没有新数据算超时。这三个数字都在 **设置 → 可靠性 → 故障转移** 里调。 ### 支持哪些协议 | 协议 | 本地路径 | 典型上游 | | --- | --- | --- | | OpenAI Chat Completions | `/v1/chat/completions` | OpenAI、DeepSeek、火山方舟、OpenRouter、Ollama 等一切 OpenAI 兼容服务 | | OpenAI Responses | `/v1/responses` | 支持 Responses API 的服务 | | Anthropic Messages | `/v1/messages` | Claude 及兼容服务 | 上面这些路径带不带 `/v1` 前缀都能识别。`GET /v1/models` 由 OSW 本地提供,返回统一的模型名,不会转发给上游。 **关于协议转换**:默认不做任何转换,请求原样透传 —— 这是最安全也最快的做法。如果你确实需要让 Claude 的客户端去打一个只支持 OpenAI 格式的渠道,可以在端点绑定上单独开启转换。转换是尽力而为的兼容层,部分参数可能丢失,一次故障转移只会尝试原生匹配或你已经明确开启转换的渠道。 ### 智能路由(路由工作台) 装好就是默认首页。它回答一个问题:**什么样的请求,该落到哪个渠道组。** 两种模式,页头一键切换,同一时刻只有一种在生效,且谁也不会改写对方的定义: - **工作流图**(默认):把策略画成节点图。 - 内置四个现成策略,点一下就能套用到画布上:**逻辑模型命中**(命中就直连,没命中回落默认)、**UA 区分来源**(认得出 Cursor / Claude CLI 就分流,认不出的回落默认)、**LLM 分析请求复杂度**(让模型自己判断难易,复杂走高性能落点、其余走快而便宜的)、**JS 脚本处理请求**(沙箱脚本按请求规模打分分档)。 - 也可以自己拖节点搭:输入 → 协议发现 → 条件判断 → 逻辑模型选择 → 输出,每个节点只做一件事。 - **规则表**:简单场景更省事 —— 一张从上往下读的规则清单,一条规则一个条件、一个落点。第一条「既命中又给得出落点」的规则胜出,表尾一行兜底,改优先级就是把行拖到想要的位置。条件用的就是图里那一套,所以同一条策略不会在这个模式下是 A、换个模式变成 B。 两种模式各自独立版本化,开箱状态下的日常行为也一致。 - 点 **测试运行**,把一段真实请求体丢进去,看它走到哪个分支、每个节点输出了什么;规则表模式下则逐条列出每条规则「命中 / 不命中 / 已停用」以及每条条件的实时取值 —— 这一步不转发给上游。 - 每次保存都会留下一个版本,选错了随时回滚。 内置的 `default` 是兜底渠道组:没有被任何路由命中的请求,最后都落到它这里。 ### 请求重写 在 **请求重写** 页面维护规则,用于抹平供应商之间的轻量差异: - 匹配条件只有两个:客户端协议、上游协议。留空表示都适用;不需要先想清楚一张协议矩阵。 - 动作分请求 / 响应两个阶段:Header 可以设置、追加、移除;JSON Body 可以按 `$.path` 设值、删除、字符串替换(支持正则)。 - 规则可以设为全局(对所有渠道生效),也可以绑到具体模型上并调整执行顺序。 - 编辑器里自带测试用例,改完动作立刻能看到效果,不用发真实请求。 内置三个模板,覆盖最常见的那几件事:**修改 User-Agent**(默认值就是 `OSW/<版本号>`)、**移除请求头**、**设置请求字段**。 新建的规则是启用的,不想用就在列表里停用它。所有改动都是结构化的增删改写,不执行任何脚本;响应阶段的动作只处理完整的非流式 JSON,流式响应的正文不会被改写。 ## 数据与隐私 - 代理默认监听 `127.0.0.1`,不会主动暴露到局域网。 - API Key 用系统加密存储保存在本地。导出供应商配置时有一个 **包含明文 API Key** 的开关(默认勾选)—— 带上密钥的导出文件等同于可用凭据,请只在设备之间私传,不要传到公开渠道。 配置、日志和请求元数据都放在用户主目录下的一个隐藏目录里,且拆成两个 SQLite 文件: | 文件 | 内容 | | --- | --- | | `~/.osw/config-v1.db` | 供应商、模型、路由与改写规则 —— **你的配置,值得单独备份** | | `~/.osw/data-v1.db` | 请求日志、正文、用量与健康状态 —— **可以随时删**,只丢历史统计 | 开发版跑的是 `~/.osw-development`,不会碰到你真实的数据。 还有几件事值得你知道: - **正文捕获默认开启**,本机会保存完整的请求、响应和流式内容(包括协议转换前后的内容)。其中 Header 会自动脱敏(`authorization`、`x-api-key`、`cookie` 等),正文不会 —— 所以它能让你排查任何一次请求,也意味着日志里可能有敏感内容。正文默认只保留 7 天(请求记录本身默认永久保留),不想要的话可以在 **设置 → 数据 → 请求日志** 里关掉采集、调整保留天数,或立刻清理历史。 - 为了完整支持超长上下文,代理和正文记录都不限制单次正文大小,会在内存里完整读一遍请求体 —— 极大正文会明显吃内存和磁盘,这是当前版本有意为之的取舍。 - OSW 没有云同步、账号体系或远程中转,请求只会发往你配置的上游地址。 ## 现在还不支持 先把边界说清楚,省得你白折腾: - 不接管系统全局代理 —— 需要在每个 AI 工具里单独改 Base URL。 - 不支持 Gemini 的 `/v1beta/models/*`。 - 不提供团队协作、多用户权限、云同步或远程访问。 - 单次请求的故障转移只会在「协议一致」或「你已明确开启转换」的渠道里挑,不做跨协议的猜测。 ## 本地开发 需要 Node.js 22+ 和 pnpm 12(确切版本由根 `package.json` 的 `packageManager` 钉住,`corepack` 会自动装好): ```bash pnpm install pnpm dev ``` 常用命令: ```bash pnpm dev # 开发会话:Electron + 它加载的控制台 dev server pnpm dev:all # 全部:应用 + 官网 + 文档站 pnpm dev:preview # 只起控制台,在浏览器里看界面 pnpm dev:www # 只起官网 pnpm dev:docs # 只起文档站 pnpm typecheck # TypeScript 类型检查 pnpm lint # ESLint + 分层守卫 + 包边界守卫 pnpm test # 全部测试 pnpm build # 编译各包产物(不打包安装包) pnpm release:mac # 构建 macOS arm64 / x64 安装包 pnpm release:win # 构建 Windows arm64 / x64 安装包 pnpm release:linux # 构建 Linux arm64 / x64 安装包 ``` 仓库是 pnpm workspace:`packages/{contracts,core,console}` 是可被单独消费的库包,`packages/toolkit` 收纳跨包开发脚本,`apps/app` 是桌面宿主,`apps/docs` 是面向使用者的手册与仓库文档根(Clarify 站点,`pnpm dev:docs`),任务编排交给 Turborepo。技术栈是 Electron + React + TypeScript + Vite + Drizzle ORM + SQLite。 设计目标、行为契约和验收标准的唯一权威在 [`apps/docs/specs/`](./apps/docs/specs/README.md),构建与打包细节见 [packaging.md](./apps/docs/specs/platform/packaging.md);上游 API 的逐字快照见 [`apps/docs/upstream/`](./apps/docs/upstream/)。`apps/docs` 自身的布局(`source/`、`specs/`、`upstream/`、`assets/` 各放什么)见 [`apps/docs/README.md`](./apps/docs/README.md)。 ## 赞助商 ### 顶级赞助商

七牛云
七牛云

感谢 [七牛云](https://www.qiniu.com) 对 OSW 的顶级赞助。七牛云提供对象存储、CDN 与大模型推理等云服务,其 AI 推理服务已内置为 OSW 的供应商预设 —— 在 **模型管理** 里选择七牛云、填入 API Key,即可开箱使用。 --- ## 反馈 有问题或想法欢迎开 [Issue](https://github.com/yinxulai/osw/issues)。附上版本号、操作系统、请求协议和脱敏后的运行日志会好定位很多 —— 但请**不要**贴 API Key、完整提示词或其他敏感内容。 日常提问、想法交流欢迎加入我们的 [Discord 社区](https://discord.gg/7TcyC2Bmy)。 --- ## 贡献者 [![贡献者](https://contrib.rocks/image?repo=yinxulai/osw)](https://github.com/yinxulai/osw/graphs/contributors) 感谢每一位为 OSW 出过力的人 —— 写代码、提 Issue、提想法、修文档,都算。 --- ## 许可 OSW 采用 [PolyForm Noncommercial License 1.0.0](./LICENSE) 发布。 - **个人及非商业用途免费。** 研究、学习、业余项目,以及慈善、教育、公共科研、公共安全与卫生、环保和政府机构的使用,都属于允许用途。 - **不可商用。** 如需商业使用,请联系作者另行取得授权。 - **许可证必须随代码一起保留。** 任何拿到副本的人(无论是否修改)都必须同时拿到许可证全文和 [`LICENSE`](./LICENSE) 里的 `Required Notice:` 行;不得以其他协议对本项目再授权或转授权。 --- ## 友链 - [LINUX DO](https://linux.do/) —— 中文技术社区,新的理想型社区。