在 Cursor 中接入本地模型:使用 `transformers serve` + ngrok 搭建 OpenAI 兼容推理服务
在 Cursor 中接入本地模型:使用 transformers serve + ngrok 搭建 OpenAI 兼容推理服务
本文基于本仓库文档 docs/source/en/serve-cli/cursor.md 编写,讲解如何把 Transformers 自带的本地推理服务(
transformers serve)接入 AI 代码编辑器 Cursor。你将掌握三件事:如何用一行命令启动本地模型服务并开启 CORS、如何借助 ngrok 让公网可访问的 Cursor 触达你的本地端口,以及如何在 Cursor 设置中以 OpenAI 兼容方式配置模型并完成验证。
一、背景:为什么需要在 Cursor 中接入本地服务
Cursor 是一款 AI 驱动的代码编辑器,内置了 Sonnet、Gemini、GPT 等云端模型,但用户也可以把它指向自定义的模型服务端点——这正是接入 transformers serve 的场景。通过这种方式,你可以把仓库中的开源模型(例如 Qwen/Qwen3-4B)跑在自己的机器上,再通过 Cursor 的代码补全与对话界面直接使用,适合实验、评测以及隐私敏感的本地化开发环境。
从仓库入口看,transformers serve 是 Transformers CLI 的一个子命令(注册位置见 src/transformers/cli/transformers.py),它基于 FastAPI 启动一个 OpenAI 兼容的 HTTP 服务。完整命令能力可参见姊妹文档 docs/source/en/serve-cli/serving.md。
二、第一步:安装依赖并启动本地服务
serve 需要额外的运行时依赖(FastAPI 与 Uvicorn),先执行安装:
pip install transformers[serving]
启动一个最基础的服务:
transformers serve
默认监听 localhost:8000。启动后,模型并不是一次性全部加载,而是按请求自动加载、空闲后按超时自动卸载(见 Serve 类 docstring:src/transformers/cli/serve.py)。服务暴露的核心端点包括:
POST /v1/chat/completions— 聊天补全(支持流式与非流式)POST /v1/completions— 传统自由文本补全GET /v1/models— 列出当前可用模型GET /health— 健康检查
这些路由的定义可以在 src/transformers/cli/serving/server.py 中直接查到。
关键:开启 CORS
文档明确指出,浏览器端的第三方应用(Cursor 在此即属于此类)访问本地模型服务时需要开启 CORS,而它出于安全考虑默认是关闭的。因此启动命令必须加上 --enable-cors:
transformers serve --enable-cors
从源码可以看出这一点:在 src/transformers/cli/serve.py 中,enable_cors 参数的默认值是 False;只有当其为 True 时,server.py 才会为 FastAPI 应用挂载 CORSMiddleware,其配置为 allow_origins=["*"](允许所有来源),并同时打印一条警告日志:"CORS allow origin is set to *. Not recommended for production."——这再次印证了该选项面向本地/开发用途,不应在生产环境不加约束地开启。
三、第二步:用 ngrok 打通公网访问
Cursor 应用运行在公网环境中,它要求一个公开可访问的地址才能连接到你的本地服务器。而 serve 默认只监听 localhost,本机之外无法直连。解决方案是使用 ngrok 这类隧道工具,把本地端口映射成一个公网 HTTPS 地址。
操作流程:
- 到 ngrok 官网注册账号;
- 在本机完成 ngrok 的认证(
ngrok config add-authtoken <你的令牌>,按官方指引执行); - 运行隧道命令,把本地 8000 端口暴露出去:
ngrok http localhost:8000
启动后 ngrok 会输出一个形如 https://xxxx-xxxx.ngrok-free.app 的 Forwarding 地址,这就是 Cursor 后续要访问的公网入口。注意保持隧道与 transformers serve 两个进程同时运行,隧道只是端口转发,真正承载模型推理的仍是本地的 serve 进程。
四、第三步:在 Cursor 中配置模型
打开 Cursor,依次进入 Settings > Cursor Settings > Models > API Keys,然后按以下顺序操作:
- 反选(取消勾选)模型列表中的所有默认模型,避免 Cursor 继续调用其内置云端模型;
- 添加你想要的模型,输入模型名称,例如文档中使用的
Qwen/Qwen3-4B; - 在 OpenAI API Key 字段填入任意文本(该字段为必填,serve 服务本身并不校验真实 Key);
- 将 ngrok 输出的 Forwarding 地址粘贴到 Override OpenAI Base URL,并在 URL 末尾追加
/v1,得到形如https://xxxx-xxxx.ngrok-free.app/v1的完整地址; - 点击 Verify 验证连通性。
验证通过后,模型即可在 Cursor 中直接使用。
底层原理:为什么 URL 要拼 /v1
追加 /v1 并非随意约定,而是因为 Cursor 使用 OpenAI SDK 协议访问服务端。OpenAI SDK 约定 base_url 形如 http://localhost:8000/v1,而 serve 的所有 OpenAI 兼容路由都挂在 /v1 前缀之下:聊天补全位于 POST /v1/chat/completions,模型列表位于 GET /v1/models(见 server.py)。Base URL 不拼 /v1 时,SDK 发出的请求会落到不存在的路径上,Verify 自然失败。
另外值得说明的是,步骤 2 填入的模型名会作为请求体中的 model 字段发送给服务端。服务端采用按需加载策略——首次请求该模型时才会真正加载权重,之后在一定超时内复用。因此,即使服务启动时没有预加载任何模型,Cursor 侧 Verify/对话第一次触发时也会自动完成加载(只是首次响应可能较慢,属正常现象)。如果你希望服务启动时就预加载固定模型,可使用 transformers serve --force-model <模型名>;对于 GGUF 权重,模型名需写成 <repo>:<file>.gguf 的形式(见 serve.py)。
五、配置核对与常见问题排查
整个链路包含三层,逐层验证可以快速定位问题:
1. 本地服务是否存活
curl http://localhost:8000/health
返回 {"status":"ok"} 即正常。
2. 模型是否已可用
curl http://localhost:8000/v1/models
该接口返回服务端当前可用的生成模型列表,对应 GET /v1/models 路由的实现(见 server.py)。CORS 未开启时,可以在启动命令中补上 --enable-cors 后重启。
3. 用 curl 走一遍完整链路
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "Qwen/Qwen3-4B", "messages": [{"role": "user", "content": "Hello"}]}'
如果这一步成功而 Cursor 端失败,问题基本出在隧道或 Cursor 配置上:
| 现象 | 排查方向 |
|---|---|
| Cursor Verify 失败 | 确认 Base URL 是否已追加 /v1;确认 ngrok 进程存活且地址未过期 |
| 提示 CORS/连接被拒 | 确认服务以 --enable-cors 启动(默认关闭);确认 API Key 字段已填写任意文本 |
| 首次对话很慢 | 属按需加载的正常现象;可改用 --force-model 预加载 |
| 隧道地址变了 | 免费版 ngrok 每次启动地址会变化,需在 Cursor 中同步更新 Base URL |
六、运行调优与安全提示
常用启动参数
transformers serve 的参数定义集中在 src/transformers/cli/serve.py,按需组合即可:
transformers serve --enable-cors \
--host 0.0.0.0 \
--port 8000 \
--force-model Qwen/Qwen3-4B \
--device cuda:0 \
--dtype auto
--host/--port:监听地址与端口,默认localhost:8000;--force-model:启动即预加载指定模型,忽略空闲卸载超时;--model-timeout:空闲模型卸载前的等待秒数,默认 300 秒;--device:推理设备,如auto、cuda:0、cpu,默认auto;--dtype:覆盖模型精度,默认auto(由权重自动推导);--continuous-batching:启用分页注意力下的连续批处理,可用--cb-*系列参数(块大小、块数量、单批最大 token、KV 缓存显存占比、CUDA Graph)进一步调优;--compile:启用torch.compile加速推理;--quantization bnb-4bit|bnb-8bit则可用 bitsandbytes 做量化加载。
安全提示
- 本方案的 ngrok 隧道会把你的本地服务公网暴露,而
serve默认不做鉴权(API Key 仅作为占位必填项)。请勿在共享或生产环境中不加防护地长期开放,建议用毕即关、只对可信来源开放隧道,或通过 ngrok 的访问控制能力限制来源。 --enable-cors会以allow_origins=["*"]放行所有来源(server.py),源码注释也明确提示这不推荐用于生产。接入 Cursor 属于本地开发场景,使用时保持警惕即可。
参考阅读
- 服务端整体能力与 API 使用示例:docs/source/en/serve-cli/serving.md
- serve CLI 入口与全部参数:src/transformers/cli/serve.py
- 路由与 CORS 中间件实现:src/transformers/cli/serving/server.py
- 同一体系的其他客户端接入指南:本目录下的 docs/source/en/serve-cli/(如 Jan、Open WebUI 等)
更多推荐
所有评论(0)