@dxv-系统/ai
DXV AI 网关的 App客户端 (/api/ai/v1:一个标准的OpenAI客户端,一个Vercel AI SDK提供商,Kennisbank Ask和代理运行,都带有应用程序自己的证书和每个地物的标签.
只有服务器. 帮助者使用网关证书. 在浏览器捆绑中导入软件包是一个错误: 每个厂家丢 AiConfigError 何时 window 已存在。 从路由处理器,服务器动作和任务中调用它.
安装
npm install @dxv-systems/ai # ask() and runs
npm install openai # only for @dxv-systems/ai/openai
npm install @ai-sdk/openai-compatible ai # only if you use the AI SDK subpath
openai 财务报告和审定财务报表 @ai-sdk/openai-compatible 是可选的对等依赖性:安装您使用的一个. openai() 住在这里 @dxv-systems/ai/openai 财务报告和审定财务报表 aiSdk() 内 @dxv-systems/ai/ai-sdk,将输入点分开,这样捆绑者就不会解决你没有安装的软件包。 主条目ask, (中文(简体) ), createRuns错误, isAiUnavailable进口或进口.
环境
| 变量 | 含义 |
|---|---|
DXV_AI_GATEWAY_URL | 全网关基地. 默认 https://platform.dxvagentic.com/api/ai/v1。 。 。 . |
DXV_AI_GATEWAY_TOKEN | 网关标志. 当它被设置的时候,它将被派遣为传人. |
VERCEL_OIDC_TOKEN | 使用时 DXV_AI_GATEWAY_TOKEN 未设置。 读取 @vercel/oidc 打开 每个请求 (它刷新;导入时没有缓存). |
AI_PROVIDER | dxv (违约), openai, (中文(简体) ), anthropic 或者说 openrouter交换 仅推断,见下文. |
AI_MODEL_LOW AI_MODEL_MEDIUM AI_MODEL_HIGH AI_MODEL_MAX (单位:千美元)AI_MODEL_AUTO(中文(简体) ) | 各种型号 dxv/* 在非 dxv 提供者下另名地图. |
OPENAI_API_KEY OPENROUTER_API_KEY ANTHROPIC_API_KEY | 交换给提供者的密钥 . |
全权证书
软件包在每次请求中都按此顺序寻找证书:
DXV_AI_GATEWAY_TOKEN,当设置.- Vercel OIDC标志 在Vercel的部署中 它被注射给你。 当地运行
vercel env pull在应用中:它写着VERCEL_OIDC_TOKEN改为.env.local。该符号寿命短;过期时再次拉出.
既无消息源,电话就发出 AiConfigError 命名这些变量 vercel env pull。 。 。 .
从不把提供者的密钥放进应用程序 除非你设定 AI_PROVIDER 用来交换DXV。 与默认的提供者一起,网关持有密钥,预算和使用记录;一个应用程序持有的密钥绕过它的全部.
特征
每一个工厂都要 { feature },网关使用和AI特性注册中出现的标签(X-DXV-Feature) (中文(简体) ). 它必须匹配 ^[A-Za-z0-9._:-]{1,100}$,否则工厂抛出 AiConfigError每个产品特征使用稳定的密钥(search.summary),从来不是一个每个用户值.
OpenAI 客户端
import { openai } from "@dxv-systems/ai/openai";
const client = openai({ feature: "support.reply" });
const res = await client.chat.completions.create({
model: "dxv/medium", // dxv/low | dxv/medium | dxv/high | dxv/max | dxv/auto
messages: [{ role: "user", content: "Summarise this ticket" }],
});
openai() 返回平面 OpenAI 实例 openai 软件包。 基准 URL 、 每名请求持有人以及 X-DXV-Feature 为您设定; API 密钥是网关忽略的占位符。 报复是SDK自己的(网关) x-should-retry 停止对预算错误的重审)。 错误保留 SDK 错误 (APIError, (中文(简体) ), RateLimitError(中文(简体) ).
openai({ feature, context }) 发送 X-DXV-Context (大多数为2000个字符,拉丁-1,没有控制字符),用于有检索功能的特性.
图像
网关生成图像. 使用 SDK 自己的 images.generate()数字 :
import { openai } from "@dxv-systems/ai/openai";
const res = await openai({ feature: "content.image" }).images.generate({
model: "google/gemini-3.1-flash-image",
prompt: "A red bicycle against a white wall",
aspect_ratio: "4:5", // a gateway field, not in the SDK's types
} as never);
const image = Buffer.from(res.data![0].b64_json!, "base64");
model是一个精确的图像模型 ID。 A 类dxv/*化名或文本模型为400.- 网关向前
prompt, (中文(简体) ),n(1至10个),resolution, (中文(简体) ),aspect_ratio, (中文(简体) ),size, (中文(简体) ),quality, (中文(简体) ),output_format, (中文(简体) ),background, (中文(简体) ),output_compression财务报告和审定财务报表input_references(1至8个源图像进行编辑,每张){ type: "image_url", image_url: { url } }带有data:或者说https://URL) (中文(简体) ). 其他领域,例如SDK'sresponse_format,不拒绝. stream: true4MB以上的请求体是413.- 跟另一个
AI_PROVIDER模型标识和额外字段是供应商的.
维塞尔 AI SDK
import { generateText } from "ai";
import { aiSdk } from "@dxv-systems/ai/ai-sdk";
const dxv = aiSdk({ feature: "support.reply" });
const { text } = await generateText({ model: dxv.chatModel("dxv/high"), prompt: "..." });
询问
import { ask } from "@dxv-systems/ai";
const r = await ask({ feature: "faq", question: "What are the opening hours?", endUser: session?.userId ?? null });
r.answer; r.sources; r.needsHuman; r.insufficientContext; r.reviewRequired;
endUser 需要(string | null:它缩小了网关的人均限制. path 可选缩小搜索范围:一个文件夹或文档,或一个 1-10 的列表作为一组搜索(例如用户角色可能读取的文件夹)。 每个条目必须位于特性的已注册文件夹内,否则网关回答400(AiRequestError) (中文(简体) ).
访问组
当谁可能看到文档时, 您的应用程序中的数据( 每个文档中的任务集) , 请将您的作用映射到访问组 。 Kennisbank从未见过你的用户或角色,只有这些密钥.
import { ask, setDocumentGroups, syncAccess } from "@dxv-systems/ai";
// After each deploy and nightly: the whole state. Groups and labels left out are removed.
await syncAccess({
feature: "assistent",
groups: roles.map((r) => ({ key: `role_${r.id}`, name: r.name })),
documents: docs.map((d) => ({ path: d.kennisbankPath, groups: d.roleIds.map((id) => `role_${id}`) })),
});
// When an admin changes one document's roles.
await setDocumentGroups({ feature: "assistent", path: doc.kennisbankPath, groups: ["role_17"] });
// Ask for a user: only documents labelled with one of their groups are searched.
await ask({ feature: "assistent", question, groups: [`role_${user.roleId}`], endUser: user.id });
组密钥为您自己的稳定 ID( R)A-Za-z0-9._:-, 1-100 个字符); 仅重命名一个角色 name。一个没有组合的文档,或者一个从未定义的组合,则不给出任何信息: 发送这样的组合,例如 everyone 向每个用户提供所有文件。 无 groups, (中文(简体) ), ask() 搜索特性文件夹中的每个文档。 绑定的路径必须位于这些文件夹内。 预览片除了制作外,还有自己的组,所以在那里同步.
通过和阅读
对于一个拥有自己的模型循环(工具)的应用程序,在没有答案的情况下检索,范围完全类似 ask()数字 :
import { passages, read } from "@dxv-systems/ai";
const hits = await passages({ feature: "assistent", question, groups, limit: 8 }); // [{ id, path, version, heading, page, text }]
const page = await read({ feature: "assistent", path: hits[0].path, offset: 0, groups }); // { excerpt, offset, totalChars, truncated, ... }
read() 与 groups 回答一个文件,其中没有一个文件可视为404(AiRequestError),和缺失的一样.
代理运行
import { createRuns } from "@dxv-systems/ai";
const runs = createRuns({ feature: "intake" });
const { id, duplicate } = await runs.fireRun(agentUuid, { requestId: 12 }, { eventKey: "request:12" });
const state = await runs.pollRun(id, { deadlineMs: 120_000 }); // { id, status, createdAt, updatedAt, result, error? }
const many = await runs.pollMany([id1, id2], { deadlineMs: 120_000 }); // one shared deadline
fireRun(agentUuid, input, { eventKey?, replyTo?, timeoutMs = 15000 }): 1 POST, 无重试, 重定向从未遵循( a 3xx srows)RunRefusedError,所以该符号不能被发送到别处). 202 给{ id, duplicate: false }; 200 (韩语)skipped: "duplicate"(同样的)eventKey在24小时之内{ id, duplicate: true }; 任何其他 2xx 形状RunRefusedError。 。 。 .eventKey使用特性字符集。 超时抛出RunNoAnswerError: 运行 可能已经开始了,所以不要盲目重新发送没有eventKey。 。 。 .- 回复回落(明显行为): 如果请求 与
replyTo被回答 400 或 404(网关无法放置回复,例如父运行未知),它被重置 一次没有replyTo并开始新的运行。 没有其他要求被重审;没有replyTo永远不能重新同意. getRun(id): 404读作:{ status: "failed", error: "not found" }。 。 。 .pollRun(id, { deadlineMs, intervalMs = 3000 }): 民调至completed, (中文(简体) ),failed或者说cancelled。在最后期限时,它返回最后一个状态(从未丢入最后期限)。 简介AiUnavailable编号 :AiRateLimited投票时的blip被容忍;如果没有读到任何州,最后的错误会被抛出.pollMany(ids, { deadlineMs, intervalMs? }):所有运行都有一个最后期限.RunStatus = "pending" | "implementing" | "completed" | "failed" | "cancelled"。 。 。 .
捣毁供应商
AI_PROVIDER 变动 仅推断 (单位:千美元)openai() 财务报告和审定财务报表 aiSdk():
AI_PROVIDER | 基础 URL | 密钥 |
|---|---|---|
openai | https://api.openai.com/v1 | OPENAI_API_KEY |
openrouter | https://openrouter.ai/api/v1 | OPENROUTER_API_KEY |
anthropic | https://api.anthropic.com/v1/ (开放AI兼容端点) | ANTHROPIC_API_KEY |
dxv/* 模式 id 重写为 id 在 AI_MODEL_LOW|MEDIUM|HIGH|MAX (单位:千美元)dxv/auto 用途 AI_MODEL_AUTO,则 AI_MODEL_MEDIUM) (中文(简体) ). 没有绘图的别名是 AiConfigError (通过) openai() sDK表面显示为400 BadRequestError 带有相同信息,所以不重审; 模型代号不是 dxv/* 别名通过。 没有 X-DXV-* 信头发出. ask(), (中文(简体) ), passages(), (中文(简体) ), read(), (中文(简体) ), syncAccess(), (中文(简体) ), setDocumentGroups() 财务报告和审定财务报表 createRuns() 仅存在于 DXV 网关并丢出 AiConfigError 在另一个供应商之下.
错误
导出类, 每类都有可选 status 财务报告和审定财务报表 code。信件中从未包含任何符号.
| 错误 | 何时 | 怎么办 |
|---|---|---|
AiUnavailable | 503,任意5xx,网络故障 | 已退化模式:显示倒置,稍后重试. |
AiBudgetExceeded | 429个 budget_exceeded (已经) retryAfterSeconds(中文(简体) ) | 该应用的月盖已达. 不要在环中重试; 降解并告诉 DXV . |
AiRateLimited | 其他429个(已) retryAfterSeconds(中文(简体) ) | 退后点 retryAfterSeconds。 。 。 . |
AiRequestError | 其他 4xx(出入口) message 财务报告和审定财务报表 code(中文(简体) ) | 错误或错误输入; 修复调用 . |
AiConfigError | 不良特性, 缺少证书, 错误的内存, 浏览器使用, 未放大的化名 | 修复配置. |
RunNoAnswerError | fireRun 超时 | 运行可能存在。 只用一个 eventKey。 。 。 . |
RunRefusedError | fireRun 有3xx或出乎意料的2xx | 报告; 不重试 . |
openai() 丢弃 OpenAI SDK 自己的错误 。 使用 isAiUnavailable(err) 要处理这个包的 AiUnavailable sDK的5xx和连接错误作为一个已退化的模式:
try {
await client.chat.completions.create(...);
} catch (err) {
if (isAiUnavailable(err)) return fallback();
throw err;
}