上周三我在 Windsurf 里用 Cascade 写一个 Node.js 的文件处理服务,想把后端模型从默认模型切成 DeepSeek——主要是代码补全场景下的上下文理解确实更对我胃口,而且 token 成本低不少。结果改完配置之后,Cascade 表现得跟没改一样,输出风格、响应速度都是老样子。折腾了大半天才发现:Windsurf 的 provider override 有三个字段填错了不会报错,直接静默 fallback 到默认模型。

如果你也在 Windsurf Cascade 里配自定义 API endpoint,重点检查三个地方:model alias 的精确拼写(不能用 display name)、base_url 末尾不能带 /chat/completions 路径、auth header 必须是 Bearer + 空格 + key 的格式。任何一处不对,Cascade 都不会报错,直接走内置模型。

先说结论

静默失效字段 错误写法 正确写法 现象
model alias deepseek-v3-pro(自造名)/ DeepSeek Chat 以所用平台实际 model id 为准(见下文) 返回结果但用的是默认模型
base_url https://api.xxx.io/v1/chat/completions https://api.xxx.io/v1 404 但 Cascade 吞掉错误
auth header ApiKey sk-xxx / sk-xxx(无前缀) Bearer sk-xxx 401 被静默处理,fallback

三个坑我全踩了一遍。下面详细拆。

环境准备

  • Windsurf 版本:请以官网当前发布版本为准
  • 操作系统:macOS Sonoma 14.5
  • 配置文件位置:~/.windsurf/settings.json 或 GUI → Settings → AI Provider
sequenceDiagram
 participant U as 你的 Windsurf
 participant C as Cascade Engine
 participant A as 自定义 API Endpoint
 participant D as 默认模型

 U->>C: 发起补全请求
 C->>C: 读取 provider override
 alt 配置验证通过
 C->>A: POST /v1/chat/completions
 A-->>C: 200 + 模型响应
 else 任一字段校验失败(静默)
 C->>D: fallback 到内置模型
 D-->>C: 200 + 默认模型响应
 end
 C-->>U: 返回补全结果(你分不出来)

关键问题就在这个 fallback 是静默的——没有 toast、没有日志警告、没有任何提示。

坑一:model alias 不是你以为的那个名字

这个最坑。DeepSeek 的模型在各家 API 的 model id 并不统一。我一开始填的是自己猜的名字,觉得很合理对吧?

实际上各平台的 model id 需要以该平台文档或模型列表页为准。以 DeepSeek 官方 API 为例,对话模型的 model id 是 deepseek-chat(服务端路由到当前最新对话模型版本)。如果你走聚合平台,model id 又不一样——比如 OpenRouter 上 DeepSeek 系列的 slug 随版本迭代会变化(如 deepseek/deepseek-chat 或带版本后缀的变体),建议直接在 OpenRouter 模型列表页确认当前可用的准确 id;ofox.io 等其他聚合平台同理,以其官网模型列表为准。

我当时的报错?没有报错。Cascade 收到一个它不认识的 model id,不会返回 model_not_found,而是直接 fallback。我是通过对比输出风格才发现不对劲的——切换成功后的输出明显更长更结构化,而我收到的还是默认模型风格的简短回复。

验证方法:在配置里加一个不存在的 model id 比如 test-nonexist-12345,如果 Cascade 还能正常工作,说明你的 override 压根没生效。

坑二:base_url 末尾多了路径

OpenAI 兼容协议的 base_url 应该只到 /v1,Cascade 内部会自己拼接 /chat/completions。但我之前从 Postman 测试的时候习惯性复制了完整 URL:

# 错误 ❌
https://api.ofox.io/v1/chat/completions

# 正确 ✅
https://api.ofox.io/v1

填了完整路径之后,实际请求会变成 https://api.ofox.io/v1/chat/completions/chat/completions,返回 404。但 Cascade 把这个 404 吞了,静默 fallback。

说实话这个设计挺烦人的。Windsurf 是真的一声不吭,建议配置后务必通过下文的验证脚本确认 endpoint 是否真正生效。

坑三:auth header 格式

这个更隐蔽。Windsurf 的 settings.json 里有个 apiKey 字段,你可能以为填进去就行了。但实际上 Cascade 组装 HTTP header 的逻辑是:

Authorization: Bearer {apiKey字段的值}

问题来了——如果你在 apiKey 字段里写了 Bearer sk-xxxx(带前缀),最终 header 会变成 Bearer Bearer sk-xxxx,直接 401。

反过来,如果你用的是某些需要 ApiKey 前缀的服务(比如 Azure OpenAI),在 Windsurf 里也会失败,因为它强制加 Bearer

我的最终配置长这样:

{
  "ai.provider": "custom",
  "ai.custom.baseUrl": "https://api.ofox.io/v1",
  "ai.custom.apiKey": "sk-your-actual-key-here",
  "ai.custom.model": "deepseek-chat"
}

apiKey 字段里只放纯 key,不带任何前缀。

完整配置示例:DeepSeek 接入 Windsurf Cascade

{
  "ai.provider": "custom",
  "ai.custom.baseUrl": "https://api.ofox.io/v1",
  "ai.custom.apiKey": "sk-xxxxxxxxxxxxxxxx",
  "ai.custom.model": "deepseek-chat",
  "ai.custom.maxTokens": 8192,
  "ai.custom.temperature": 0.3
}

注意:ai.custom.model 的值请以你所用平台的实际 model id 为准,上面的 deepseek-chat 对应 ofox.io 上的 DeepSeek 对话模型,其他平台请查阅对应文档。

配好之后重启 Windsurf(不是 reload window,是完全退出再开),然后验证:

# 快速验证脚本,不走 Windsurf,直接确认你的 key 和 endpoint 是通的
from openai import OpenAI

client = OpenAI(
    api_key="sk-xxxxxxxxxxxxxxxx",
    base_url="https://api.ofox.io/v1"
)

resp = client.chat.completions.create(
    model="deepseek-chat",  # 替换为你平台的实际 model id
    messages=[{"role": "user", "content": "用一句话介绍你自己的模型版本"}],
    max_tokens=100
)
print(resp.choices[0].message.content)
# 如果返回里提到 DeepSeek,说明 endpoint 和 model 都对了

关于平台选择:OpenRouter 和 ofox.io 都支持 DeepSeek 模型。各平台的手续费比例和定价策略会随时间调整,建议以各平台官网当前定价页为准再做选择。

怎么确认 Cascade 真的在用你的自定义模型

这是我折腾最久的部分。因为静默 fallback 的存在,你没法从 UI 上看出区别。我最后用了三个方法交叉验证:

方法一:看响应延迟

不同模型和不同平台的首 token 延迟存在差异,但具体数值受网络环境、服务器负载等因素影响较大,不适合作为硬性判断标准。如果切换后延迟风格明显不同,可以作为辅助参考。

方法二:问它是谁

在 Cascade 里直接输入"你是什么模型"。虽然不是 100% 可靠(有些模型会被 system prompt 覆盖),但 DeepSeek 模型通常会回复带有 "DeepSeek" 字样的内容。

方法三:看 API 后台的调用日志

这个最靠谱。如果你用的聚合平台有调用日志,直接看请求记录里的 model 字段。我在 ofox 后台能看到每一笔调用的模型、token 数、耗时,一眼就知道 Cascade 到底走的哪个模型。

小结

Windsurf Cascade 的 provider override 功能本身没问题,但它的错误处理太"温柔"了——静默 fallback 这个设计对开发者很不友好。三个字段(model alias 用 API 的实际 model id 而非显示名、base_url 只到 /v1、apiKey 不带 Bearer 前缀)任何一个错了都不会有任何提示。

我已经在 Windsurf 的 GitHub Discussion 里提了 issue,希望后续版本至少加个日志输出。目前的 workaround 就是先用 Python 脚本单独验证 endpoint 可达性,再填进 Windsurf 配置。

DeepSeek 作为 Cascade 后端体验确实不错,特别是写偏后端逻辑的代码时,上下文理解比默认模型好一截。就是配置过程太折腾了,希望这篇能帮你少踩几个小时的坑。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐