2026/10/10 17:02:51

改个 base_url 就能用:Edge0 本地 35B 秒变 OpenAI 兼容服务

改个 base_url 就能用:Edge0 本地 35B 秒变 OpenAI 兼容服务 改个 base_url 就能用Edge0 本地 35B 秒变 OpenAI 兼容服务【免费下载链接】Edge0-35B-A3B-preview项目地址: https://ai.gitcode.com/hf_mirrors/Edge0/Edge0-35B-A3B-preview本地跑大模型最大的痛点从来不是能不能跑而是跑起来之后怎么用。大多数端侧推理方案都止步于一个命令行交互窗口想接进自己写的应用、接进已经成熟的工具链还得自己写胶水层。Edge0 的做法是直接把模型目录变成一个 OpenAI 兼容的 HTTP 服务一条edge0 serve命令起服务/v1/chat/completions端点、SSE 流式输出、请求参数透传全套就位任何按 OpenAI API 写的应用改一行base_url就能把请求打到这台本地 35B 模型服务器上——不需要 GPU 集群、不需要 Docker、不需要改业务代码。这篇文章基于 Edge0-35B-A3B-preview 模型仓库README.md与 edge0 框架服务层源码拆解一键起服务的完整链路从启动姿势、接口验证到 SDK 接入实操最后讲清楚服务层单槽 FIFO 队列这个设计取舍——它决定了这台本地 OpenAI 服务的并发边界也恰恰是它在 3GB 内存跑 35B 模型时能保持稳定的原因。一、一键起服务的启动姿势Edge0 的定位是模型 框架一体本仓库就是一个完整的、可直接运行的模型目录基模 checkpoint 和训练好的适配器放在同一个目录里一次下载即开箱即用。目录结构里可以看到这套开箱即用的布局config.json模型架构声明Qwen3_5MoeForConditionalGeneration40 层256 个专家hidden size 2048并带完整的 4-bit affine 量化配置group_size 64所有层 4-bit各层 gate 与共享专家 gate 用 8-bit 保住路由精度model-00001-of-00004.safetensors~model-00004-of-00004.safetensors4-bit 权重分片索引文件 model.safetensors.index.json 记录的权重总量约 20.4 GB配合 README 中完整 4-bit checkpoint 约 23GB的口径lora_edge0_35b.safetensors 与 prerouter_edge0_35b.safetensorsRecover-LoRA 适配器和 prerouter 路由预测头与基模同目录edge0 自动加载无需手动 mergechat_template.jinja带 thinking 模式think推理块与工具调用格式的对话模板generation_config.json默认采样参数temperature 1.0、top_k 20、top_p 0.95。对应的启动流程只有三步。先装框架再下载模型本仓库即下载产物最后起服务# 1. 安装 edge0 框架Apple Silicon Mac pip install -e githttps://github.com/Edge0-AI/edge0.git#eggedge0[fetch] # 2. 下载模型到本地目录本仓库即该下载的产物 huggingface-cli download Edge0/Edge0-35b-a3b-preview --local-dir ./Edge0-35b-a3b-preview # 3. 指定模型目录并起 OpenAI 兼容服务 export EDGE0_35B_MODEL$PWD/Edge0-35b-a3b-preview edge0 serve --name edge0-35b --port 8085服务默认监听127.0.0.1:8000--port可改。也可以完全不设环境变量直接传目录框架会从 checkpoint 的config.json自动识别档位edge0 serve models/edge0-35b。值得强调的是自动加载背后的机制edge0 在推理时把专家权重从 SSD 按需 mmap 流式读取SSD expert offload内存只装当前激活的专家集峰值 active 内存压到 2.9 GiBprerouter 用训练好的路由预测头提前一步预取专家让磁盘读取与前向计算重叠解码速度实测 14.9–17.7 tok/s、长 prompt prefill 吞吐 113/140 tok/s冷/热。也就是说这个服务的内存画像接近一台内存占用 3GB 量级的本地模型服务而不是35B 参数全量常驻内存的庞然大物。二、/chat/completions 与 SSE 流式响应的验证服务起来后先别急着接 SDK用 curl 把协议面探一遍。edge0 服务层暴露的路由是标准的 OpenAI 形状路由方法行为/healthzGET健康检查返回{status:ok,model:edge0-35b}/v1/modelsGET模型列表返回{object:list,data:[{id, object, owned_by}]}/v1/chat/completionsPOST对话补全streamtrue时走 SSE/v1/completionsPOST显式返回 400文本补全不支持引导使用 chat 端点非流式请求直接验证curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: edge0-35b, messages: [{role: user, content: Hello!}], max_tokens: 32 }响应体是标准chat.completion结构choices[0].message携带role/content并附usageprompt_tokens / completion_tokens / total_tokens。流式请求把stream置为 true服务端返回text/event-stream每个 token 一个chat.completion.chunk事件curl -N http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: edge0-35b, messages: [{role: user, content: 用一句话解释流式推理}], stream: true, max_tokens: 64 }流式输出形如data: {…choices:[{delta:{content:推理}}]…}每个 chunk 只带增量 delta以data: [DONE]收尾——这与 OpenAI 官方流式协议逐字节对齐客户端无需任何适配。服务层的参数透传也相当完整。请求里的temperature、top_p、top_k、max_tokens、seed会被逐一映射到生成配置未显式传参时回落到 generation_config.json 的默认值enable_thinking控制是否开启思考模式——开启时服务端会把think推理块拆进reasoning_content字段正文则进content二者分离返回tools/tool_choice则透传给 chat_template.jinja 渲染工具调用格式模型输出的tool_call块会被服务端解析成标准的message.tool_calls结构。换言之这不仅是接口长得像 OpenAI连 thinking 与 function calling 这两个高阶能力也对齐了协议。三、接入任意 OpenAI SDK 应用的操作步骤协议面验证通过后接入存量应用就是纯改配置的活。核心只有两处base_url指向本机服务http://127.0.0.1:8000/v1model填edge0-35b以/v1/models返回的id为准--name可自定义。以 Python 生态最常用的openai官方 SDK 为例非流式from openai import OpenAI client OpenAI( base_urlhttp://127.0.0.1:8000/v1, # 只改这一行 api_keyedge0-local, # 本地服务不校验占位即可 ) resp client.chat.completions.create( modeledge0-35b, messages[{role: user, content: 帮我写一个 Python 快速排序}], max_tokens256, ) print(resp.choices[0].message.content)流式SSE 增量stream client.chat.completions.create( modeledge0-35b, messages[{role: user, content: 讲一个冷笑话}], streamTrue, ) for chunk in stream: if chunk.choices[0].delta.content: print(chunk.choices[0].delta.content, end, flushTrue)只要是按 OpenAI 协议写的应用——ChatGPT-Next-Web 一类的聊天前端、LangChain / LlamaIndex 一类的 Agent 框架、各类 IDE AI 插件——把服务地址换成这个本地端点即可业务代码零改动。SDK 层面唯一需要留意的差异是本地服务没有 key 校验与计费逻辑api_key字段传任意非空值即可满足 SDK 的参数要求。配合 thinking 模式代码里还能这样消费思考过程resp client.chat.completions.create( modeledge0-35b, messages[{role: user, content: 鸡兔同笼35 个头 94 只脚各几只}], enable_thinkingTrue, ) msg resp.choices[0].message print(推理过程:, msg.reasoning_content) print(最终回答:, msg.content)这套接入能力背后的质量底气来自模型本身edge0 的 int4 Recover-LoRA prerouter 管线相对 fp16 基座平均只掉 3.9 分AIME 2026 86.6 vs 92.7、HumanEval 90.9 vs 95.1、MMLU-Pro 81.0 vs 84.6也就是说你接到本地服务的这个 35B不是阉割版而是量化损失已被 LoRA 蒸馏基本补偿回的可推理模型。四、单槽 FIFO 队列并发边界与取舍把服务跑起来、把应用接进去之后就该聊聊这台本地 OpenAI 服务的并发画像了——这是它和云端服务最大的不同也是 edge0 服务层最刻意的设计。edge0 服务层python/src/edge0/server/的QueueServer是一个明确的单槽模型所有请求通过一把线程锁串行化chat()方法内部是with self._lock:的互斥区。服务层注释把设计动机写得很直白引擎在同一时刻只服务一个请求——单个 MLX 进程流式生成一个序列没有问题但并发请求会反复搅动专家缓存thrash the expert cache请求在锁上排队每个生成任务通过 SSE 逐 token 流式输出队列按 FIFO 顺序消费。这个取舍要结合推理架构来理解。Edge0 的内存优势峰值 2.9 GiB 跑 35B建立在专家权重按需从 SSD 流式加载 页缓存驻留之上不同请求会激活不同的专家子集如果两个生成并发推进各自需要换入的专家集合互相驱逐SSD 随机读放大、页缓存命中率崩坏最终两个请求都会变慢吞吐反而不如串行。单槽 FIFO 牺牲了并发度换来的是内存占用有硬边界、每个请求的吞吐可预期、SSD 读取模式线性化。作为交换代价是明确的排队延迟。以 35B 档 15–18 tok/s 的解码速度估算一个 200 token 的生成大约耗时 11–13 秒第 N 个排队请求的等待时间约等于前面 N−1 个请求的生成时长之和。所以这个服务形态的适用边界很清晰个人/小团队私有网关给 IDE 插件、聊天前端、脚本任务提供统一入口同一时刻通常只有一个人在对话体验完全无感单机 batch servingREADME 明确给出的用例之一——一份只读基模服务多套 LoRA 适配器适合离线批量任务按 FIFO 逐个消化不适合高并发在线服务多用户同时密集调用时排队延迟会线性增长需要并发能力请走云端或 GPU 集群方案。对使用者来说正确的姿势是把并发的预期对齐到排队上把服务当作一台单用户的私有推理机而不是多租户 API。如果你在 SDK 接入后遇到响应变慢先检查是否有多处调用在同时挤这一个槽——这是单槽 FIFO 设计下唯一需要调优的变量。小结从edge0 serve一条命令到 curl 验证、SDK 接入、并发边界评估Edge0 把本地 35B 模型真正做成了一个可消费的软件形态内存占用 3GB 量级、解码 15–18 tok/s、int4 质量只掉 3.9 分对外却是一个协议完备的 OpenAI 兼容服务。对开发者而言它意味着本地私有模型第一次可以像调用云端 API 一样被接入任意工具链——改一行base_url35B 模型即刻上岗。当然也要记住它的边界MLX 后端目前面向 Apple Silicon服务层是单槽 FIFO定位是个人与单机的私有推理服务。它的下一个里程碑统一推理框架、CUDA 后端已经在路线图上届时这套 OpenAI 兼容接入方式大概率会原样继承——协议一旦对齐迁移成本就只剩换一个地址而已。【免费下载链接】Edge0-35B-A3B-preview项目地址: https://ai.gitcode.com/hf_mirrors/Edge0/Edge0-35B-A3B-preview创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考