@yeepay/ai-core
v1.0.1
Published
易宝公司级 Node.js / TypeScript 通用 AI SDK
Keywords
Readme
@yeepay/ai-core
易宝公司级 Node.js / TypeScript 服务端 AI SDK。核心返回 Vercel AI SDK 原生 LanguageModel,不替换 generateText、streamText、tool、ToolLoopAgent 等能力。
适用于需要在 Node.js 服务端统一管理 Provider、协议、模型别名、认证、超时、重试和安全遥测的项目。不适用于浏览器直连、密钥托管、业务 Agent/Prompt、跨 Provider 自动切换或 AI Gateway。
安装与兼容性
要求 Node.js >=20,包为 ESM-only。开发验证锁定 [email protected]、@ai-sdk/[email protected]、@ai-sdk/[email protected]、[email protected]。消费方需提供 ai >=7 <8、zod >=4 <5;生产建议应用自行锁定并验证 AI SDK 主版本。
npm install @yeepay/ai-core ai zod最小示例:Responses
import { generateText } from 'ai';
import { createYeepayAI } from '@yeepay/ai-core';
const ai = createYeepayAI({
appId: 'my-service',
providers: {
primary: {
type: 'openai', protocol: 'responses',
baseURL: process.env.AI_BASE_URL!,
apiKey: process.env.AI_API_KEY!
}
},
models: { general: { provider: 'primary', modelId: process.env.AI_MODEL! } }
});
const result = await generateText({ model: ai.model('general'), prompt: '用一句话介绍 TypeScript。', maxRetries: 0 });
console.log(result.text, result.usage);传入 API 基础 URL(通常截至 /v1),不要传完整 /responses 路由。末尾误带 /responses 时会被移除。
Chat Completions、自定义端点与隔离
const ai = createYeepayAI({
appId: 'service-a',
providers: {
openaiChat: { type: 'openai', protocol: 'chat-completions', baseURL: 'https://api.openai.com/v1', apiKey: process.env.OPENAI_KEY! },
vendor: { type: 'openai-compatible', protocol: 'chat-completions', baseURL: process.env.VENDOR_BASE_URL!, apiKey: process.env.VENDOR_KEY!, headers: { 'x-tenant': 'team-a' } }
},
models: {
fast: { provider: 'vendor', modelId: 'vendor-fast', capabilities: { toolCalling: true, vision: false } },
accurate: { provider: 'openaiChat', modelId: 'gpt-4.1', capabilities: { vision: true, structuredOutput: true } }
},
timeoutMs: 60_000,
maxRetries: 2
});
const fastModel = ai.model('fast');每个服务自行从环境或密钥系统读取配置并创建实例。SDK 不读取环境变量,也不跨实例共享 Key、别名或 Provider。V1 的 openai-compatible 仅支持 Chat Completions。
流式输出
import { streamText } from 'ai';
const result = streamText({ model: ai.model('fast'), prompt: '逐步解释事件循环。', abortSignal: request.signal });
for await (const chunk of result.textStream) process.stdout.write(chunk);结构化输出
import { generateText, Output } from 'ai';
import { z } from 'zod';
const result = await generateText({
model: ai.model('accurate'),
output: Output.object({ schema: z.object({ title: z.string(), score: z.number() }) }),
prompt: '给一个简短标题和 0 到 1 的评分。'
});
console.log(result.output);AI SDK 会验证结构化结果并在格式错误时抛出解析/验证错误;端点是否遵从 JSON Schema 取决于模型能力。
Tool Calling 与多步骤
import { generateText, stepCountIs, tool } from 'ai';
import { z } from 'zod';
const result = await generateText({
model: ai.model('accurate'),
tools: { add: tool({ inputSchema: z.object({ a: z.number(), b: z.number() }), execute: async ({ a, b }) => a + b }) },
stopWhen: stepCountIs(4),
prompt: '计算 18 + 24。'
});
console.log(result.text, result.steps.length);工具函数由业务代码执行;必须自行授权、设置工具级超时、审计并考虑幂等。stopWhen 限制多轮模型/工具步骤。
图片输入
import { generateText } from 'ai';
const result = await generateText({
model: ai.model('accurate'),
messages: [{ role: 'user', content: [{ type: 'text', text: '描述图片内容' }, { type: 'image', image: new URL('https://example.com/image.png') }] }]
});包不剥离官方 AI SDK 的图片内容,但视觉能力必须由具体模型和端点支持;该示例不代表所有 Provider 已联调。
错误、超时、重试与用量
timeoutMs 默认 120 秒;客户端 maxRetries 默认 2,表示最多 maxRetries + 1 次 fetch 尝试,对 408、425、429、5xx 和网络错误有限指数退避;认证和一般 4xx 不重试。AI SDK 的 generateText/streamText 默认也会重试 2 次,因此为使客户端重试次数成为唯一总尝试次数,调用时应显式传 maxRetries: 0(示例均如此);否则两层重试会相乘。AbortSignal 由 AI SDK 调用参数传入并向 fetch 传递。错误可用 classifyError() 分类,YeepayAIError.cause 保留底层原因。
AI SDK 原样返回 Provider usage;部分端点可能缺失 usage。Logger 默认只记录重试状态和状态码,不记录 Prompt、请求体、响应体、URL 或 Header。Telemetry Hook 仅包含 app/request/provider/protocol/status/duration 等安全字段;不内置价格表或估算成本。
Axios 迁移
只将模型 HTTP 调用替换为 generateText 或 streamText;业务 Axios 请求继续保留。详见 docs/migration-from-axios.md。
开发与发布
npm ci
npm run typecheck
npm run lint
npm test
npm run build
npm run consumer:test
npm run pack:check真实服务检查仅在用户显式设置 AI_LIVE=1 并提供测试凭据后运行 npm run test:live。私有 Registry 发布流程与人工确认清单见 docs/release.md。本包不会自动发布。架构、Provider、安全和排查说明见 docs/。
