ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

VoltAgent × Vercel AI SDK:`@voltagent/vercel-ai` Provider 从 0.1.1 到 1.0.0 的演进与实现解析

VoltAgent × Vercel AI SDK:`@voltagent/vercel-ai` Provider 从 0.1.1 到 1.0.0 的演进与实现解析 VoltAgent × Vercel AI SDKvoltagent/vercel-aiProvider 从 0.1.1 到 1.0.0 的演进与实现解析【免费下载链接】voltagentAI Agent Engineering Platform built on an Open Source TypeScript AI Agent Framework项目地址: https://gitcode.com/gh_mirrors/vo/voltagent导读本文以 VoltAgent 仓库中归档的voltagent/vercel-ai包 CHANGELOG 为主线系统梳理该 LLM Provider 从首个版本到 Vercel AI SDK v5 大版本升级的技术演进脉络并结合provider.ts、utils.ts与测试用例深入解析 VoltAgent 如何将 Vercel AI SDK 的生成、流式、结构化输出与工具调用能力统一接入自有的LLMProvider抽象。读完本文你将掌握 Provider 的四类核心方法、Promise 化响应结构、UsageInfo 扩展字段、错误标准化机制以及 step 流映射原理并能独立完成基于 AI SDK v5 的 Provider 集成与迁移。一、包的定位为什么需要voltagent/vercel-aiVoltAgent 是一个开源的 TypeScript AI Agent 框架README.md。在框架设计中Agent 的智能来源于 LLM而 LLM 供应商五花八门OpenAI、Anthropic、Google 等。为了做到「灵活切换模型、避免锁定」voltagent/core定义了一套统一的LLMProvider接口任何供应商只需实现该接口即可接入 VoltAgent 的 Agent、工具、记忆与可观测体系。voltagent/vercel-ai正是这样一座桥梁它把 Vercel AI SDKai及ai-sdk/*生态封装成 VoltAgent 的LLMProvider从而让 VoltAgent Agent 可以复用 AI SDK 背后海量的模型提供方与稳定的流式协议。从包的演进史看这一封装经历了从「基础可用」到「与 SDK v5 深度对齐」的完整过程。在当前仓库中该包源码保存在 archive/deprecated-providers/vercel-ai 归档目录下其 package.jsonpackage.json声明了ai-sdk/openai、ai、ts-pattern、type-fest等依赖并以voltagent/core、zod为 peerDependencies。归档目录中的说明archive/deprecated-providers/README.md也印证了这一类 Provider 包的定位变化主代码库不再维护独立供应商包而是让 Vercel AI SDK 承担模型适配职责减少维护负担。二、核心架构VercelAIProvider与LLMProvider接口包的出口极为精简index.ts 仅导出VercelAIProvider一个类。该类在 provider.ts 中实现完整实现了 VoltAgent 的LLMProviderAIModel接口包含四个核心生成方法与两个辅助方法方法职责底层 SDK 调用generateText(options)一次性生成文本返回标准化文本响应ai/generateTextstreamText(options)流式生成文本返回textStream、fullStream与 Promise 化属性ai/streamTextgenerateObject(options)按 Zod schema 生成结构化对象ai/generateObjectstreamObject(options)流式生成结构化对象返回objectStreamai/streamObjectgetModelIdentifier(model)提取模型标识字符串或modelId—toMessage(message)将 VoltAgent 消息转换为 AI SDK 消息—在类型层面包通过Parameterstypeof generateText[0]推导出AIModel类型从而让模型参数与 AI SDK v5 的类型系统严格对齐这是 CHANGELOG 中「更好的 TypeScript 支持」的源码级体现。2.1 统一的消息与工具转换Provider 的输入输出均以 VoltAgent 类型为准。toMessage将BaseMessage直接映射为 AI SDK 的ModelMessage工具则通过 utils.ts 中的convertToolsForSDK转换export function convertToolsForSDK(tools: BaseTool[]): Recordstring, AiTool | undefined { if (!tools || tools.length 0) { return undefined; } return tools.reduceRecordstring, AiTool((acc, tool) { acc[tool.name] createTool({ description: tool.description, inputSchema: tool.parameters, outputSchema: tool.outputSchema, execute: tool.execute, }); return acc; }, {}); }它把 VoltAgent 的BaseTool含 Zod 参数 schema 与execute实现逐一对齐为 AI SDK 的tool()定义保证 Agent 的工具调用能力在 Provider 边界无损传递。2.2 响应标准化getUsageInfo与字段映射各方法返回前都会把 AI SDK 的结果映射为 VoltAgent 的标准响应。以generateText为例provider.tsreturn { provider: result, text: result.text || , usage: getUsageInfo(result.usage), toolCalls: result.toolCalls, toolResults: result.toolResults, finishReason: result.finishReason, reasoning: Array.isArray(result.reasoning) ? result.reasoning.map((r) r.text || ).join(\n) : result.reasoning, warnings: result.warnings, };其中getUsageInfo把 AI SDK 的LanguageModelUsageinputTokens/outputTokens/totalTokens映射为 VoltAgent 的UsageInfopromptTokens/completionTokens/totalTokens并在字段存在时透传cachedInputTokens与reasoningTokens详见第四节。三、版本演进主线从基础集成到 AI SDK v5CHANGELOG 完整记录了包的演进史梳理如下3.1 0.1.1包诞生首个版本随 VoltAgent 框架一同发布定位就是「与 Vercel AI SDK 的无缝集成」与voltagent/core、voltagent/voice、voltagent/xsai、voltagent/cli共同构成框架初期的工具链。3.2 0.1.4错误与结束处理的标准化该版本在voltagent/core中引入VoltAgentError、ToolErrorInfo、StreamOnErrorCallback以及StreamTextFinishResult、StreamObjectFinishResult等类型。VercelAIProvider随之把所有底层 SDK/API 错误包装为结构化VoltAgentError后交给onError回调或直接抛出流式完成时构造标准化的 finish result保证text/object、usage、finishReason在历史、事件与 hooks 中一致可用。这一设计让不同 LLM 提供商的错误与完成行为趋于一致是「可调试性」的基础。3.3 0.1.5消息内容格式标准化API/text、/stream、/object、/stream-object端点对数组形式input中的content字段做出严格约定只能是string或内容片段数组如[{ type: text, text: ... }]不再支持把单个内容对象直接作为content值。此前已在google-ai、groq-ai、xsai各 Provider 中统一。这为后续多模态文件/图片消息铺平了道路。3.4 0.1.7instructions字段取代description示例与文档全面改用instructions字段定义 Agent 行为指引为Agent类中description的弃用做准备。CHANGELOG 给出了清晰的 diffconst agent new Agent({ name: My Assistant, - description: A helpful assistant., instructions: A helpful assistant., llm: new VercelAIProvider(), model: openai(gpt-4o-mini), });这一 API 偏好沿用至今可参考 examples/with-vercel-ai/src/index.ts 中的实际 Agent 定义。3.5 0.1.12fullStream支持为满足生成式 UIgenerative UI应用对完整流式事件的诉求Provider 在streamText返回值中新增fullStream。其底层实现是 utils.ts 中的createMappedFullStream与mapToStreamPart把 AI SDK 的TextStreamPart逐一映射为 VoltAgent 标准的StreamPart详见第六节。3.6 0.1.13修复onStepFinishHandler阻断问题该版本修复了一个关键缺陷此前onStepFinish处理器会阻断工具调用与 Agent hooks 的正常执行导致 Agent 无法正确使用工具和触发生命周期 hooks。修复后step 级回调文本、工具调用、工具结果得以与 Agent 主流程正确协作。3.7 0.1.16Promise 化响应属性与 warnings为了让 Provider 返回结构与 Vercel AI SDK 的 API 对齐并提供更丰富的元数据该版本为四类响应都增加了可选属性streamObjectobject?: PromiseT、usage?: PromiseUsageInfo、warnings?: Promiseany[] | undefinedstreamTexttext?: Promisestring、finishReason?: Promisestring、usage?: PromiseUsageInfo、reasoning?: Promisestring | undefinedgenerateText/generateObjectreasoning?: string仅 generateText、warnings?: any[]CHANGELOG 给出了直接可用的用法示例// For streamObject const response await agent.streamObject(input, schema); const finalObject await response.object; // PromiseT const usage await response.usage; // PromiseUsageInfo // For streamText const response await agent.streamText(input); const fullText await response.text; // Promisestring const usage await response.usage; // PromiseUsageInfo // For generateText const response await agent.generateText(input); console.log(response.warnings); // Any provider warnings console.log(response.reasoning); // Models reasoning (if available)在 provider.ts 的streamText返回中可以看到这些 Promise 属性的落地如text: result.text、usage: result.usage、reasoning: result.reasoning.then(...)并在 provider.spec.ts 中通过「await Promise 属性」的测试用例验证其行为。3.8 1.0.0升级 Vercel AI SDK v5这是最重要的一次大版本升级PR #462核心变化包括依赖升级ai升至 v5.0.0ai-sdk/provider升至 v2.0.0ai-sdk/provider-utils升至 v3.0.0其余ai-sdk/*包统一升至 v2.0.0peer 依赖zod升至^3.25.0AI SDK v5 的要求。BreakingProvider 实现改用新的ai-sdk/providerv2.0.0 接口类型安全显著增强同时保持对既有 VoltAgent Agent 接口的向后兼容。流式改进所有流式方法采用改进后的 v5 流式协议错误处理更完善。统一 Provider API跨所有 AI Provider 保持一致接口。性能优化 token 使用与响应处理。3.9 1.0.0-next.0收尾阶段1.0.0-next.0仅包含依赖更新voltagent/core1.0.0-next.0说明 v1 主线已进入发布前的对齐阶段。四、UsageInfo 扩展cachedInputTokens与reasoningTokens在 1.0.0 的 Patch 中UsageInfo类型新增两个可选字段cachedInputTokens?: number跟踪从缓存命中的输入 token 数reasoningTokens?: number跟踪模型推理reasoning消耗的 token 数。这两个字段在底层 LLM Provider 支持时由 AI SDK 提供VercelAIProvider负责原样透传。从 provider.ts 的getUsageInfo实现可见function getUsageInfo(usage?: LanguageModelUsage): UsageInfo | undefined { return match(usage) .with({ inputTokens: P.number, outputTokens: P.number, totalTokens: P.number }, (u) ({ promptTokens: u.inputTokens, completionTokens: u.outputTokens, totalTokens: u.totalTokens, cachedInputTokens: u.cachedInputTokens, reasoningTokens: u.reasoningTokens, })) .otherwise(() undefined); }同样utils.ts 的mapToStreamPart在映射finish事件时也会把cachedInputTokens、reasoningTokens透传到标准StreamPart的 usage 中。这为成本审计缓存命中与推理开销分析提供了更细粒度的计量基础。五、错误处理机制VoltAgentError与错误阶段CHANGELOG 0.1.4 引入的结构化错误体系在 utils.ts 的createVoltagentErrorFromSdkError中实现。它支持五个错误阶段stagellm_generate文本生成llm_stream文本流式object_generate对象生成object_stream对象流式tool_execution工具执行转换逻辑首先从 SDK 错误对象中提取原始Error兼容{ error: Error }包装、Error实例与未知类型然后若错误带有toolCallId与toolName则构造包含toolCallId、toolName、toolArguments、toolExecutionError的ToolErrorInfo并将 stage 标记为tool_execution否则保留原始消息、code与传入的 stagetoolError置为undefined。测试用例utils.spec.ts覆盖了限流错误、网络超时、包装错误、未知类型与默认 stage 等场景例如工具执行错误会被规范化为Error during Vercel SDK operation (tool getWeather): API rate limit exceeded。各方法在调用 SDK 前后都统一使用该函数包装异常见generateText中的createVoltagentErrorFromSdkError(sdkError, llm_generate)provider.spec.ts 与 provider-custom.spec.ts 亦验证了错误按正确格式转发的行为。六、流式数据管线从TextStreamPart到统一StreamPart生成式 UI 与前端消费需要细粒度的流事件。voltagent/vercel-ai通过三个工具函数构建了从 AI SDK 到 VoltAgent 的流式管线utils.tsmapToStreamPart(part)将单个TextStreamPart映射为标准StreamPart支持的映射包括text-delta→text-deltareasoning-delta→reasoningsourceurl 类型→sourcetool-call→tool-calltool-result→tool-resultfinish→finish附 usageerror→error不支持的部件返回nullcreateMappedFullStream(originalStream)将原始AsyncIterableTextStreamPart包装为异步迭代器逐个映射并过滤不支持的事件供streamText的fullStream返回。createStepFromChunk(chunk)把 step 级事件文本、工具调用、工具结果转换为带id、role、usage的StepWithContent其中tool-call/tool-call与tool-result/tool_result两种命名都会被识别CHANGELOG 0.1.11 为 tool-result step 增加toolName字段正是为了让 hooks 与对话流中能准确区分每个工具的输出来源。streamText通过onChunk将 chunk 交给options.onChunk通过onFinish构造标准 finish result含text、usage、finishReason、warnings、providerResponseonStepFinish则把每步的文本与工具调用、结果拆分后逐一回调。测试 provider-custom.spec.ts 验证了fullStream输出、工具调用三步回调text → tool_call → tool_result与致命错误包装等行为。七、工程治理依赖、构建与发布质量CHANGELOG 中有大量篇幅记录工程治理层面的改进这些细节直接影响用户体验Zod 版本治理0.1.6 / 0.1.9 / 0.1.14 / 0.1.15多个 patch 版本 zod 共存会导致 TS 编译出现 Type instantiation is excessively deep and possibly infinite 错误。项目先后通过固定3.24.2、放宽为^3.24.2、最终在 0.1.14 将zod从直接依赖移入 peerDependencies避免重复安装同一依赖导致的语言服务性能下降1.0.0 随 AI SDK v5 将 peer 要求升级到^3.25.0。这一过程是「依赖治理影响开发体验」的典型范例。Node.js 版本0.1.100.1.10 起放弃 Node.js v18 支持。TypeScript 目标0.1.9tsconfig.json的target升级为ES2022。发布质量0.1.3 / 0.1.170.1.3 移除files中的src目录并补充显式exports字段0.1.17 起在 monorepo 中统一加入publint脚本、启用attwAre The Types Wrong类型导出校验、通过 Biome 修复大量 lint 问题。当前 package.json 中可见attw、publint、lint、test:coverage等脚本以及双格式ESM/CJS的exports配置。JSON.stringify清理0.1.18移除潜在有问题的JSON.stringify用法由safeStringify取代见 utils.ts。八、测试体系Mock 模型与行为验证包内测试由 provider.spec.ts、provider-custom.spec.ts 与 utils.spec.ts 组成。其关键设施是 testing.ts 的createMockModel基于 AI SDK 官方的MockLanguageModelV2构造可编程模型支持返回文本、消息序列、对象或抛出错误并模拟doGenerate/doStream两种路径。测试覆盖了文本与对象的生成/流式输出、响应结构与类型推断expectTypeOf、onStepFinish/onFinish/onChunk回调格式、Promise 属性可消费性、工具调用三步事件、错误阶段与消息格式以及convertToolsForSDK、mapToStreamPart、createMappedFullStream等纯函数的边界情况空数组、null、空流、不支持的事件类型等。其中streamObject的若干用例以it.skip标注注释揭示了原因——AI SDK 内部流处理与 mock 的兼容性限制属于测试层面的已知边界。九、快速上手在 VoltAgent 中使用该 Provider结合包 README 与 examples/with-vercel-ai/src/index.ts示例使用了openai/gpt-4o-mini模型字符串写法典型的 Agent 定义如下import { VoltAgent, Agent } from voltagent/core; import { VercelAIProvider } from voltagent/vercel-ai; import { openai } from ai-sdk/openai; // 示例模型 const agent new Agent({ name: my-agent, instructions: A helpful assistant that answers questions without using tools, llm: new VercelAIProvider(), model: openai(gpt-4o-mini), }); new VoltAgent({ agents: { agent }, });要点说明llm固定为new VercelAIProvider()model则可以是任意 AI SDK 模型ai-sdk/openai、ai-sdk/anthropic、ai-sdk/google等实现「Provider 固定、模型可换」Agent 定义优先使用instructions字段提供行为指引对应 0.1.7 的 API 演进启动后 VoltAgent 服务默认监听http://localhost:3141可通过 VoltOps 控制台与 Agent 对话、观察运行状态。十、结语从 0.1.1 的基础封装到 1.0.0 的 AI SDK v5 深度对齐voltagent/vercel-ai的演进史实际上回答了一个核心问题如何在保持自有LLMProvider抽象稳定的同时持续跟进上游 SDK 的能力与类型系统。Promise 化响应、fullStream、cachedInputTokens/reasoningTokens透传、结构化VoltAgentError、step 流映射这些能力最终沉淀为 VoltAgent Agent 可统一消费的标准化契约。对于希望为 VoltAgent 编写自定义 Provider 或理解其 LLM 适配层的开发者provider.ts 与 utils.ts 是最直接的参考实现而其测试套件则完整勾勒了 Provider 应有的行为边界。【免费下载链接】voltagentAI Agent Engineering Platform built on an Open Source TypeScript AI Agent Framework项目地址: https://gitcode.com/gh_mirrors/vo/voltagent创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进