Dev.to AI 🤖 Ai 👁 0 📖 4 min read

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, an

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
    }
  }
}

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);
  }
}

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");

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
    }
  }
}

不要把 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);
  }
}

这个本地检查在真实请求之前就有价值,因为它能发现静默配置改动,也能让 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");

排查表

现象 优先检查
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

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.