DEV Community

Jia
Jia

Posted on

Build a Small Node.js Provider Adapter for Vector Engine Before Adding More LLM Tools

A team can connect Dify, Cursor, and a backend service to an LLM in an afternoon. Keeping those connections consistent for months is harder. The practical solution is to create a small provider adapter before every tool invents its own Base URL, API Key, and model name rules.

This article shows how to use Vector Engine as an OpenAI-compatible API gateway and wrap it as a tiny LLM API provider layer in Node.js. The same contract can then guide Dify and Cursor configuration, while giving engineers a clear place to debug model_not_found.

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

Adapter goal

The adapter has four jobs:

Job Why it helps
Read Base URL from configuration Avoid hard-coded provider URLs in business code
Read API Key from secret storage Keep keys out of source control
Read model name from configuration Make model changes reviewable
Normalize errors Turn provider failures into useful debugging signals

Vector Engine uses the OpenAI-compatible Base URL pattern:

https://api.vectorengine.cn/v1
Enter fullscreen mode Exit fullscreen mode

Use that value for OpenAI SDK clients, Dify provider settings, and Cursor custom endpoint settings.

Node.js adapter

Create llmProvider.js:

import OpenAI from "openai";

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`${name} is required`);
  return value;
}

const client = new OpenAI({
  apiKey: required("VECTOR_ENGINE_API_KEY"),
  baseURL: process.env.VECTOR_ENGINE_BASE_URL || "https://api.vectorengine.cn/v1",
});

export async function generateText(messages, options = {}) {
  try {
    const response = await client.chat.completions.create({
      model: options.model || required("VECTOR_ENGINE_MODEL"),
      messages,
      temperature: options.temperature ?? 0.2,
    });

    return response.choices[0]?.message?.content ?? "";
  } catch (error) {
    const message = String(error?.message || error);
    if (message.includes("model_not_found")) {
      throw new Error("model_not_found: check the configured model name and key permission");
    }
    throw error;
  }
}
Enter fullscreen mode Exit fullscreen mode

Then call it from a route or job:

import { generateText } from "./llmProvider.js";

const answer = await generateText([
  { role: "system", content: "Answer with a concise engineering note." },
  { role: "user", content: "Summarize today's failed LLM checks." },
]);

console.log(answer);
Enter fullscreen mode Exit fullscreen mode

Environment file for local testing

Use an explicit local environment file:

VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn/v1
VECTOR_ENGINE_API_KEY=replace-with-local-test-key
VECTOR_ENGINE_MODEL=replace-with-enabled-model-id
Enter fullscreen mode Exit fullscreen mode

The point is not only convenience. It gives reviewers a stable place to inspect provider behavior before a deployment.

Dify mapping

After the Node.js adapter works, map the same fields into Dify:

Adapter field Dify field
VECTOR_ENGINE_BASE_URL Base URL
VECTOR_ENGINE_API_KEY API Key
VECTOR_ENGINE_MODEL Model

If Dify fails but Node.js works, compare the three values. Most problems are still configuration drift, not framework behavior.

Cursor mapping

Cursor should use a dedicated API Key, but the same provider shape:

Cursor field Value
Custom endpoint type OpenAI-compatible
Base URL https://api.vectorengine.cn/v1
API Key A key created for Cursor
Model The model ID used for coding assistance

This makes Cursor easy to isolate if a key needs rotation or usage investigation.

Debug table

Failure Likely cause Action
model_not_found in Node.js only Wrong environment variable Print the configured model name in a non-secret startup check
model_not_found in every tool Model not enabled or typo reused everywhere Confirm the exact enabled model ID
Dify request path error Full endpoint pasted into Base URL Use only the /v1 Base URL
Cursor works but backend fails Different key or deployment secret Compare key owner and deployment environment
Usage is hard to explain One key shared by many tools Split keys by Dify, Cursor, backend, and experiments

Rollout pattern

Start with the Node.js adapter, then configure Dify, then configure Cursor. After each step, record the Base URL, API Key owner, and model name. With Vector Engine behind that consistent provider adapter, each new LLM tool joins the same operating model instead of creating another exception.


增加更多 LLM 工具前,先为向量引擎写一个小型 Node.js Provider Adapter

一个团队可以在一个下午把 Dify、Cursor 和后端服务接到 LLM 上。真正困难的是几个月后仍然保持这些连接一致。更稳妥的做法,是在每个工具各自定义 Base URL、API Key 和模型名规则之前,先写一个小型 provider adapter。

本文展示如何把向量引擎作为 OpenAI 兼容的 API中转站,并在 Node.js 中封装成一个很小的 LLM API provider layer。相同的契约也可以指导 Dify 和 Cursor 配置,并让工程师有一个清楚的位置排查 model_not_found

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

Adapter 目标

这个 adapter 只做四件事:

目标 作用
从配置读取 Base URL 避免业务代码里写死 provider 地址
从密钥系统读取 API Key 避免 key 进入代码仓库
从配置读取 model name 让模型变更可以被 review
统一错误信息 把 provider 失败转成可排查的信号

向量引擎使用 OpenAI-compatible Base URL 模式:

https://api.vectorengine.cn/v1
Enter fullscreen mode Exit fullscreen mode

这个值可以用于 OpenAI SDK 客户端、Dify provider 配置,也可以用于 Cursor 自定义 endpoint。

Node.js adapter

创建 llmProvider.js

import OpenAI from "openai";

function required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`${name} is required`);
  return value;
}

const client = new OpenAI({
  apiKey: required("VECTOR_ENGINE_API_KEY"),
  baseURL: process.env.VECTOR_ENGINE_BASE_URL || "https://api.vectorengine.cn/v1",
});

export async function generateText(messages, options = {}) {
  try {
    const response = await client.chat.completions.create({
      model: options.model || required("VECTOR_ENGINE_MODEL"),
      messages,
      temperature: options.temperature ?? 0.2,
    });

    return response.choices[0]?.message?.content ?? "";
  } catch (error) {
    const message = String(error?.message || error);
    if (message.includes("model_not_found")) {
      throw new Error("model_not_found: check the configured model name and key permission");
    }
    throw error;
  }
}
Enter fullscreen mode Exit fullscreen mode

然后在路由或任务里调用:

import { generateText } from "./llmProvider.js";

const answer = await generateText([
  { role: "system", content: "Answer with a concise engineering note." },
  { role: "user", content: "Summarize today's failed LLM checks." },
]);

console.log(answer);
Enter fullscreen mode Exit fullscreen mode

本地测试环境变量

本地使用明确的环境文件:

VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn/v1
VECTOR_ENGINE_API_KEY=replace-with-local-test-key
VECTOR_ENGINE_MODEL=replace-with-enabled-model-id
Enter fullscreen mode Exit fullscreen mode

这不仅是为了方便开发,也是为了让 review 时能稳定检查 provider 行为。

Dify 映射

Node.js adapter 跑通之后,再把同样的字段映射到 Dify:

Adapter 字段 Dify 字段
VECTOR_ENGINE_BASE_URL Base URL
VECTOR_ENGINE_API_KEY API Key
VECTOR_ENGINE_MODEL Model

如果 Dify 失败而 Node.js 正常,就对比这三个值。大多数问题仍然是配置漂移,而不是框架本身。

Cursor 映射

Cursor 建议使用单独的 API Key,但 provider 形状保持一致:

Cursor 字段
Custom endpoint type OpenAI-compatible
Base URL https://api.vectorengine.cn/v1
API Key 专门给 Cursor 创建的 key
Model 用于编码辅助的模型 ID

这样当需要轮换 key 或分析用量时,Cursor 可以被单独隔离。

排错表

故障 可能原因 操作
只有 Node.js 返回 model_not_found 环境变量错误 在非敏感启动检查中打印当前模型名
所有工具都返回 model_not_found 模型未开通或错误拼写被复用 确认准确的可用模型 ID
Dify 出现请求路径错误 把完整接口地址填进 Base URL 只使用 /v1 层级的 Base URL
Cursor 正常但后端失败 key 或部署密钥不同 对比 key 归属和部署环境
用量很难解释 多个工具共用同一个 key 按 Dify、Cursor、后端和实验拆分 key

推进方式

先跑通 Node.js adapter,再配置 Dify,然后配置 Cursor。每完成一步,都记录 Base URL、API Key 归属和模型名。把向量引擎API中转站放在这个一致的 provider adapter 后面,新的 LLM 工具就能加入同一套运行模型,而不是再增加一个例外。

向量引擎中转站适合放在这样的工程边界里:配置明确、key 分离、模型可审计、故障可对比。这样团队接入 API中转站时,更容易把注意力放在业务效果和运行质量上。

Top comments (0)