DEV Community

Jia
Jia

Posted on

Add a parameter drift probe for Vector Engine calls from Dify, Cursor, and Node.js

When Dify, Cursor, and a Node.js service share Vector Engine, the Base URL and model name may be correct while the request still behaves differently. One client streams, another does not. One sends a high temperature, another adds a JSON response format, and a backend service changes max_tokens during deployment. The result can be blamed on the OpenAI-compatible API gateway even when the drift is in client parameters.

This tutorial builds a parameter drift probe for Vector Engine. It checks the LLM API provider layer from the client side: Base URL, API Key presence, model name, stream mode, temperature, token limit, and the expected model_not_found branch.

Define the intended route

Create vector-engine-params.json:

{
  "provider": "Vector Engine",
  "baseUrl": "https://api.vectorengine.cn/v1",
  "model": "gpt-4o-mini",
  "clients": {
    "Dify": {
      "temperature": 0.2,
      "stream": true,
      "max_tokens": 600
    },
    "Cursor": {
      "temperature": 0.2,
      "stream": true,
      "max_tokens": 600
    },
    "Node.js": {
      "temperature": 0.2,
      "stream": true,
      "max_tokens": 600
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Do not store the API Key in this file. Store only the public shape of the provider route and the expected client defaults.

Compare parameters locally

Create probe-parameter-drift.js:

import fs from "node:fs";

const config = JSON.parse(fs.readFileSync("vector-engine-params.json", "utf8"));
const expected = config.clients["Node.js"];

function diffClient(name, actual) {
  const drift = [];
  for (const key of ["temperature", "stream", "max_tokens"]) {
    if (actual[key] !== expected[key]) {
      drift.push({ field: key, expected: expected[key], actual: actual[key] });
    }
  }
  return { name, drift };
}

for (const [name, actual] of Object.entries(config.clients)) {
  const result = diffClient(name, actual);
  if (result.drift.length) {
    console.warn("Parameter drift", result);
  } else {
    console.log("Parameter contract OK", name);
  }
}
Enter fullscreen mode Exit fullscreen mode

This local check is useful before a live call because it catches silent configuration edits. It also gives Dify, Cursor, and Node.js owners a shared vocabulary for the route.

Add a live Node.js request

After the local check passes, send one controlled request through Vector Engine:

const baseUrl = process.env.VECTOR_ENGINE_BASE_URL || config.baseUrl;
const apiKey = process.env.VECTOR_ENGINE_API_KEY;
const model = process.env.VECTOR_ENGINE_MODEL || config.model;

if (!apiKey) {
  throw new Error("Missing API Key for Vector Engine");
}

const request = {
  model,
  messages: [
    { role: "system", content: "Answer in one short sentence." },
    { role: "user", content: "Say that the parameter probe is ready." }
  ],
  temperature: expected.temperature,
  stream: expected.stream,
  max_tokens: expected.max_tokens
};

const response = await fetch(`${baseUrl.replace(/\/$/, "")}/chat/completions`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${apiKey}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(request)
});

if (!response.ok) {
  const body = await response.json().catch(() => ({}));
  console.error({
    status: response.status,
    model,
    code: body.error?.code || body.code || "unknown",
    hint: body.error?.code === "model_not_found"
      ? "Check the model name and key permission in Vector Engine"
      : "Check Base URL, API Key, and request shape"
  });
  process.exit(1);
}

console.log("Vector Engine parameter probe accepted");
Enter fullscreen mode Exit fullscreen mode

Troubleshooting table

Symptom Likely check
Dify responds differently from Node.js Compare temperature, stream mode, and token limit
Cursor works but service fails Check whether the service sends a different model name
model_not_found appears only in one client Confirm the model name and API Key permission for that client
A streamed client hangs Test the same route with stream: false and compare headers
Costs change without a release Review max_tokens, retries, and tool-specific defaults

The probe does not make Vector Engine responsible for every client-side choice. It makes the OpenAI-compatible API gateway visible enough that Dify, Cursor, and Node.js owners can compare the same request contract.

Registration URL: https://api.vectorengine.cn/register?aff=Igym


Dify、Cursor 和 Node.js 服务共享向量引擎时,Base URL 和 model name 可能都正确,但请求行为仍然不同。一个客户端启用 streaming,另一个没有启用;一个设置较高 temperature,另一个附加 JSON response format;后端服务又在部署时改了 max_tokens。结果可能被误判为 OpenAI-compatible API gateway 的问题,但漂移实际发生在客户端参数里。

这篇教程为向量引擎构建一个参数漂移探测脚本。它从客户端角度检查 LLM API provider layer:Base URL、API Key 是否存在、model name、stream mode、temperature、token limit,以及预期中的 model_not_found 分支。

定义预期路由

创建 vector-engine-params.json

{
  "provider": "Vector Engine",
  "baseUrl": "https://api.vectorengine.cn/v1",
  "model": "gpt-4o-mini",
  "clients": {
    "Dify": {
      "temperature": 0.2,
      "stream": true,
      "max_tokens": 600
    },
    "Cursor": {
      "temperature": 0.2,
      "stream": true,
      "max_tokens": 600
    },
    "Node.js": {
      "temperature": 0.2,
      "stream": true,
      "max_tokens": 600
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

不要把 API Key 存进这个文件。这里只保存 provider route 的公开形态和客户端默认参数。

本地比较参数

创建 probe-parameter-drift.js

import fs from "node:fs";

const config = JSON.parse(fs.readFileSync("vector-engine-params.json", "utf8"));
const expected = config.clients["Node.js"];

function diffClient(name, actual) {
  const drift = [];
  for (const key of ["temperature", "stream", "max_tokens"]) {
    if (actual[key] !== expected[key]) {
      drift.push({ field: key, expected: expected[key], actual: actual[key] });
    }
  }
  return { name, drift };
}

for (const [name, actual] of Object.entries(config.clients)) {
  const result = diffClient(name, actual);
  if (result.drift.length) {
    console.warn("Parameter drift", result);
  } else {
    console.log("Parameter contract OK", name);
  }
}
Enter fullscreen mode Exit fullscreen mode

这个本地检查在真实请求之前就有价值,因为它能发现静默配置改动,也能让 Dify、Cursor 和 Node.js 负责人用同一组词讨论路由。

加入实时 Node.js 请求

本地检查通过后,再通过向量引擎发送一个受控请求:

const baseUrl = process.env.VECTOR_ENGINE_BASE_URL || config.baseUrl;
const apiKey = process.env.VECTOR_ENGINE_API_KEY;
const model = process.env.VECTOR_ENGINE_MODEL || config.model;

if (!apiKey) {
  throw new Error("Missing API Key for Vector Engine");
}

const request = {
  model,
  messages: [
    { role: "system", content: "Answer in one short sentence." },
    { role: "user", content: "Say that the parameter probe is ready." }
  ],
  temperature: expected.temperature,
  stream: expected.stream,
  max_tokens: expected.max_tokens
};

const response = await fetch(`${baseUrl.replace(/\/$/, "")}/chat/completions`, {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${apiKey}`,
    "Content-Type": "application/json"
  },
  body: JSON.stringify(request)
});

if (!response.ok) {
  const body = await response.json().catch(() => ({}));
  console.error({
    status: response.status,
    model,
    code: body.error?.code || body.code || "unknown",
    hint: body.error?.code === "model_not_found"
      ? "Check the model name and key permission in Vector Engine"
      : "Check Base URL, API Key, and request shape"
  });
  process.exit(1);
}

console.log("Vector Engine parameter probe accepted");
Enter fullscreen mode Exit fullscreen mode

排查表

现象 优先检查
Dify 和 Node.js 返回差异明显 比较 temperature、stream mode 和 token limit
Cursor 可用但服务失败 检查服务端是否发送了不同 model name
model_not_found 只出现在一个客户端 确认该客户端的 model name 和 API Key 权限
streaming 客户端卡住 stream: false 测同一路由并对比 headers
成本没有发布变更却上升 检查 max_tokens、重试逻辑和工具默认值

这个探测脚本不是把每个客户端选择都归因给向量引擎,而是让 OpenAI-compatible API gateway 变得足够可见,使 Dify、Cursor 和 Node.js 负责人能够比较同一个 request contract。对中文团队来说,这也是把向量引擎API中转站、向量引擎中转站和 API中转站 的参数默认值放在同一张表里,而不是分散在各个工具界面里。

注册地址:https://api.vectorengine.cn/register?aff=Igym

Top comments (0)