Many teams verify a shared OpenAI-compatible API gateway with a single non-streaming request, then later discover that one client is using streaming, another is not, and a third hides the raw response. The result can look like a provider outage even when the Base URL, API Key, and model name are mostly correct.
This DEV tutorial uses Vector Engine as the shared LLM API provider layer and shows how to test the same route in both modes before wiring it into Dify, Cursor, and a Node.js application.
Start with one known route
Use the same three values everywhere:
Base URL: https://api.vectorengine.cn/v1
API Key: stored in VECTOR_ENGINE_API_KEY
model name: gpt-4o-mini
Do not test streaming and routing at the same time. If the model name is wrong, model_not_found will hide the streaming question. Confirm the model route with a plain request, then test streaming.
Plain Node.js request
Create plain-check.mjs:
const baseUrl = "https://api.vectorengine.cn/v1";
const model = "gpt-4o-mini";
const res = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.VECTOR_ENGINE_API_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Return plain-ok." }],
stream: false
})
});
const body = await res.text();
console.log(res.status);
console.log(body);
Run:
node plain-check.mjs
If this fails, pause. Check the Base URL, API Key, and model name before opening Dify or Cursor.
Streaming Node.js request
Create stream-check.mjs:
const baseUrl = "https://api.vectorengine.cn/v1";
const model = "gpt-4o-mini";
const res = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.VECTOR_ENGINE_API_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Stream three short words." }],
stream: true
})
});
console.log("status", res.status);
if (!res.ok || !res.body) {
console.log(await res.text());
process.exit(1);
}
const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
process.stdout.write(decoder.decode(value));
}
Run:
node stream-check.mjs
You are not checking the answer quality here. You are checking whether the route can return streamed chunks through Vector Engine.
Dify settings to compare
In Dify, compare the provider configuration against the Node.js script:
| Field | Expected value |
|---|---|
| Provider type | OpenAI-compatible |
| Base URL | https://api.vectorengine.cn/v1 |
| API Key | same secret as VECTOR_ENGINE_API_KEY
|
| model name | same string as the Node.js script |
| streaming | match the workflow mode you want to use |
If Dify fails only when streaming is enabled, capture that difference separately from model_not_found. A routing error and a stream parsing issue point to different fixes.
Cursor settings to compare
For Cursor, keep a small note next to the team setup guide:
Provider: Vector Engine
Base URL: https://api.vectorengine.cn/v1
model name: gpt-4o-mini
streaming: enabled only after plain-check passes
Cursor may abstract part of the transport. The Node.js scripts give you a raw reference so the team can tell whether the problem is the shared gateway route or the client behavior.
Troubleshooting table
| Symptom | Likely area to inspect |
|---|---|
model_not_found in all clients |
model name or route permission |
| Plain request works, stream fails | streaming support or client parser |
| Node.js works, Dify fails | Dify provider settings |
| Dify works, Cursor fails | Cursor custom provider fields |
| All clients fail with 401 | API Key handling |
Registration URL: https://api.vectorengine.cn/register?aff=Igym
The useful habit is to separate routing, authentication, and streaming into separate checks. Once the raw Node.js checks pass, Dify and Cursor troubleshooting becomes much smaller.
很多团队会先用一次非流式请求验证共享的 OpenAI-compatible API gateway,后面才发现一个客户端使用 streaming,另一个客户端不使用,还有一个客户端隐藏了原始响应。结果看起来像 provider 故障,但 Base URL、API Key、model name 可能大体没有问题。
这里把向量引擎API中转站作为共享入口来看,也就是团队常说的向量引擎中转站:它承担 API中转站 的路由、鉴权和响应转发职责。
这篇 DEV 教程把向量引擎作为共享的 LLM API provider layer,演示如何在接入 Dify、Cursor 和 Node.js 应用前,同时验证同一条路由的非流式和流式模式。
从一条已知路由开始
所有地方使用同一组三项配置:
Base URL: https://api.vectorengine.cn/v1
API Key: stored in VECTOR_ENGINE_API_KEY
model name: gpt-4o-mini
不要把 streaming 和路由问题混在一起测。如果模型名称错误,model_not_found 会掩盖 streaming 的问题。先用普通请求确认模型路由,再测试 streaming。
普通 Node.js 请求
创建 plain-check.mjs:
const baseUrl = "https://api.vectorengine.cn/v1";
const model = "gpt-4o-mini";
const res = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.VECTOR_ENGINE_API_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Return plain-ok." }],
stream: false
})
});
const body = await res.text();
console.log(res.status);
console.log(body);
运行:
node plain-check.mjs
如果这里失败,先停下来检查 Base URL、API Key 和 model name,再打开 Dify 或 Cursor。
流式 Node.js 请求
创建 stream-check.mjs:
const baseUrl = "https://api.vectorengine.cn/v1";
const model = "gpt-4o-mini";
const res = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${process.env.VECTOR_ENGINE_API_KEY}`
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Stream three short words." }],
stream: true
})
});
console.log("status", res.status);
if (!res.ok || !res.body) {
console.log(await res.text());
process.exit(1);
}
const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
process.stdout.write(decoder.decode(value));
}
运行:
node stream-check.mjs
这里不是在评估回答质量,而是在检查这条路由是否能通过向量引擎返回流式片段。
对照 Dify 设置
在 Dify 中,把 provider 配置与 Node.js 脚本对齐:
| 字段 | 期望值 |
|---|---|
| Provider type | OpenAI-compatible |
| Base URL | https://api.vectorengine.cn/v1 |
| API Key | 与 VECTOR_ENGINE_API_KEY 相同的密钥 |
| model name | 与 Node.js 脚本相同的字符串 |
| streaming | 与工作流实际需要的模式一致 |
如果 Dify 只在开启 streaming 后失败,要把这个差异和 model_not_found 分开记录。路由错误和流式解析问题对应不同修复方向。
对照 Cursor 设置
对于 Cursor,可以在团队配置说明里保留一小段:
Provider: Vector Engine
Base URL: https://api.vectorengine.cn/v1
model name: gpt-4o-mini
streaming: enabled only after plain-check passes
Cursor 可能会抽象一部分传输细节。Node.js 脚本能提供原始参照,帮助团队判断问题来自共享网关路由,还是来自客户端行为。
排查表
| 现象 | 优先检查区域 |
|---|---|
所有客户端都有 model_not_found
|
模型名称或路由权限 |
| 普通请求可用,stream 失败 | streaming 支持或客户端解析 |
| Node.js 可用,Dify 失败 | Dify provider 设置 |
| Dify 可用,Cursor 失败 | Cursor 自定义 provider 字段 |
| 所有客户端 401 | API Key 处理 |
注册地址:https://api.vectorengine.cn/register?aff=Igym
有价值的习惯是把路由、鉴权、streaming 拆成独立检查。原始 Node.js 检查通过后,Dify 和 Cursor 的排查范围会小很多。
Top comments (0)