AI SDK 仓库测试指南:手动验证、Provider 测试夹具的生成与加载

发布时间:2026/11/9 4:30:35

AI SDK 仓库测试指南:手动验证、Provider 测试夹具的生成与加载 AI SDK 仓库测试指南手动验证、Provider 测试夹具的生成与加载【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai本文基于 AI SDKThe AI Toolkit for TypeScript仓库的贡献者测试指南整理系统讲解该仓库的测试方法论如何利用examples/ai-functions与examples/ai-e2e-next完成generateText、streamText与 Web UI 的手动回归以及如何为各 Provider 的响应解析测试生成真实响应夹具Test Fixtures并在单元测试中按不同的 SSE 格式加载这些夹具。读完本文你将掌握一套可复用的真实响应 → 夹具化 → 离线断言的测试工作流能够为新增或修改的 Provider 功能补齐全链路验证。一、手动测试三条必测路径仓库贡献指南要求任何变更或新功能至少覆盖三类手动测试场景分别对应 CLI 与 Web UI 两条通道场景通道验证目标generateText测试命令行一次性文本生成的结果正确性streamText测试命令行流式输出的逐块正确性UI 测试含追问Web UI助手回复后发送 follow-up message确保上下文能正确回传给 LLM这三类场景可直接使用仓库中的两个示例工程examples/ai-functions纯命令行/脚本式示例集覆盖generate-text、stream-text、embed-many、generate-image、generate-speech、transcribe、upload-file、workflow-agent等大量子目录是生成夹具与手动冒烟测试的主战场examples/ai-e2e-next基于 Next.js 的端到端示例app/下包含完整的 UI 页面agent/下是 Agent 相关实现用于验证带 UI 的多轮对话链路。第三类 UI 测试的核心在于回复一轮还不够必须在助手输出之后再发送一条追问以此确认多轮消息messages 数组能正确、完整地作为上下文返回给 LLM——这是许多仅测单轮的功能最容易出问题的地方。二、Provider 单元测试与测试夹具体系2.1 为什么坚持真实响应夹具对于 Provider 响应解析类测试仓库的硬性约定是测试夹具必须来自 Provider 的真实响应除非响应体过大此时允许做不改变语义的裁剪。这条约定写在 contributing/testing.md 的 Test Fixtures 一节目的是避免用手工捏造的响应来测试解析逻辑——只有真实响应才能暴露字段缺失、格式漂移等只在生产环境出现的问题。夹具统一存放在各包内的__fixtures__子目录中例如OpenAI Responses APIpackages/openai/src/responses/__fixtures__/从该目录的文件名如openai-client-tool-search.1.json、openai-client-tool-search.1.chunks.txt、parallel-tool-call-wrapper.1.chunks.txt可以看出命名约定名称.序号.后缀测试辅助代码的写法以packages/openai/src/responses/openai-responses-language-model.test.ts为范本。2.2 三种方式生成夹具指南给出了三种生成夹具的典型方式对应ai包的三种核心 API。下面逐一展开并补充仓库中的底层实现佐证。generateText直接落盘响应体对于非流式生成把原始响应 body 打印到控制台再复制进新的夹具文件即可import { openai } from ai-sdk/openai; import { generateText } from ai; import { run } from ../lib/run; run(async () { const result await generateText({ model: openai(gpt-5-nano), prompt: Invent a new holiday and describe its traditions., }); console.log(JSON.stringify(result.response.body, null, 2)); });上述代码中的run辅助函数实现在 examples/ai-functions/src/lib/run.ts它执行传入的异步函数若结果可被录制即同时满足包含fullStream或steps字段这一结构特征见 examples/ai-functions/src/lib/record-fixture.ts 的isRecordableResult就会自动调用recordFixture把响应体写入output/目录出错时则打印错误并输出请求体、响应体便于定位问题。streamTextincludeRawChunkssaveRawChunks流式场景必须拿到未被 SSE 解包前的原始 chunk因此需要开启原始块透传选项并借助专门的saveRawChunks辅助函数import { openai } from ai-sdk/openai; import { streamText } from ai; import { run } from ../lib/run; import { saveRawChunks } from ../lib/save-raw-chunks; run(async () { const result streamText({ model: openai(gpt-5-nano), prompt: Invent a new holiday and describe its traditions., includeRawChunks: true, }); await saveRawChunks({ result, filename: openai-gpt-5-nano }); });运行方式在examples/ai-functions目录下执行pnpm tsx src/stream-text/script-name.ts生成结果会写入examples/ai-functions/output目录将其复制到目标包的__fixtures__目录并按约定重命名即可。关于底层机制两点值得展开saveRawChunks的实现examples/ai-functions/src/lib/save-raw-chunks.ts遍历result.stream只收集type raw的 chunk 的rawValue每行序列化一个 JSON 对象写入output/filename.chunks.txt——注意这里不包含任何 SSE 信封无data:前缀、无[DONE]还原工作由测试侧的加载器完成。API 的新旧两种写法本文档示例中的includeRawChunks: true是流式选项的既有形式而仓库较新的代码已支持include: { rawChunks: true }的写法。例如 packages/ai/src/agent/tool-loop-agent.test.ts 中即通过include: { rawChunks: true }断言doStreamOptions.includeRawChunks trueexamples/ai-functions/src/e2e/raw-chunks.test.ts 也用该写法对 OpenAI、Anthropic、Google 三个 Provider 做了端到端验证开启时流中恰好出现 1 个rawchunk关闭时为 0。写新代码时建议优先采用include: { rawChunks: true }。embedMany注意复数responses字段向量化接口的夹具采集有一个易错点embedMany返回的是responses复数数组不是responseimport { openai } from ai-sdk/openai; import { embedMany } from ai; import { run } from ../lib/run; run(async () { const result await embedMany({ model: openai.embedding(text-embedding-3-small), values: [sunny day at the beach, rainy day in the city], }); console.log(JSON.stringify(result.responses?.[0]?.body, null, 2)); });同时由于 embedding 向量通常体积巨大指南建议只保留每个向量前几个数值例如 5 个用于夹具其余结构保持不变从而在保真与体积之间取得平衡。2.3 自动录制recordFixture 的约定除了手动打印/复制仓库还提供了一套自动化录制逻辑examples/ai-functions/src/lib/record-fixture.ts其行为与上述约定严格一致夹具文件名取自被执行的示例脚本文件名path.basename(process.argv[1])去掉扩展名按请求序号生成.1、.2…… 多个文件streamText产生name.n.chunks.txt按start-step分组、每个 step 一个文件generateText产生name.n.json每个 step 的response.body一个文件输出目录为output/已被 gitignore首次运行时会自动mkdirSync创建。这套逻辑让跑一次示例即得一套夹具成为可能命名天然与单元测试的读取路径对应。三、在单元测试中加载夹具按 SSE 格式还原流saveRawChunks写出的文件是每行一个 JSON 对象没有 SSE 信封。因此测试侧的 chunk loader 必须根据 Provider 实际使用的 SSE 协议把原始 chunk 重新包装回 Provider 期望的格式。不同 Provider 的差异正是这里的关键。3.1 OpenAI 风格 SSEdata:前缀 [DONE]哨兵OpenAI、DeepSeek、Groq、xAI 等 Provider 使用标准的data:前缀并以[DONE]作为流结束哨兵。加载器实现如下节选自 packages/openai/src/responses/openai-responses-language-model.test.tsfunction prepareChunksFixtureResponse(filename: string) { const chunks fs .readFileSync(src/__fixtures__/${filename}.chunks.txt, utf8) .split(\n) .filter(line line.trim().length 0) .map(line data: ${line}\n\n); chunks.push(data: [DONE]\n\n); server.urls[api-url].response { type: stream-chunks, chunks, }; }要点逐行读取、过滤空行、为每行补上data:前缀与空行分隔最后追加data: [DONE]\n\n。随后将组装好的 chunk 数组挂到server.urls[api-url]的响应上由ai-sdk/test-server提供的createTestServer以stream-chunks类型逐块吐出驱动被测模型的流式解析逻辑。3.2 事件类型 SSE从 chunk 的type提取event:字段以 Cohere 为代表的部分 Provider 使用带事件类型的 SSE需要从每个 chunk 的type属性还原event:字段function prepareChunksFixtureResponse(filename: string) { const chunks fs .readFileSync(src/__fixtures__/${filename}.chunks.txt, utf8) .split(\n) .filter(line line.trim() ! ) .map(line { const parsed JSON.parse(line); return event: ${parsed.type}\ndata: ${line}\n\n; }); server.urls[api-url].response { type: stream-chunks, chunks, }; }两种加载器一对比即可看出核心差异OpenAI 风格只包data:事件风格还要额外带event: type行——type来自 JSON chunk 解析后的type属性。3.3 如何确认 Provider 用的是哪种格式指南给出了一个非常实用的判别方法查看 Provider 的doStream实现看它用的是哪个 SSE 解析器。在 AI SDK 的 Provider 包中流式响应统一通过createEventSourceResponseHandler等处理器构建例如 OpenAI Responses 的流式成功响应处理器即位于 packages/openai/src/responses/openai-responses-language-model.tscreateEventSourceResponseHandler的导入见该文件第 20 行。加载器必须与 Provider 侧使用的解析器格式一一对应否则解包会错位、解析直接失败。四、测试基础设施速览夹具加载离不开测试服务器。上述示例中的server来自ai-sdk/test-servermonorepo 中的 packages/test-server配合 vitest 使用时可从ai-sdk/test-server/with-vitest导入createTestServer与TestResponseController再结合ai-sdk/provider-utils/test的convertReadableStreamToArray、mockId等工具完成流断言。该模式在openai-responses-language-model.test.ts等文件中被反复使用是编写新 Provider 解析测试时的标准样板。此外仓库还在 examples/ai-functions/src/e2e 维护了一批真实联网的端到端测试如openai.test.ts、anthropic.test.ts、cohere.test.ts、raw-chunks.test.ts等它们依赖.env中的 API Key通过dotenv/config加载适合在 CI 有凭证时做全链路冒烟而__fixtures__夹具测试则完全离线、稳定可重复两者互补。五、实践清单给贡献者一份可照做的操作清单功能改动前先在examples/ai-functions下跑通generateText/streamText/embedMany三类示例验证真实 Provider 行为生成夹具generateText打印并保存response.bodystreamText开启include: { rawChunks: true }或includeRawChunks: true后由saveRawChunks落盘embedMany记得取responses[0].body并裁剪向量入库夹具按名称.序号.json|chunks.txt命名放入packages/provider/src/.../__fixtures__/编写加载器先读目标 Provider 的doStream确认 SSE 格式OpenAI 风格 vs 事件风格再套用对应的prepareChunksFixtureResponse样板离线断言通过createTestServer的stream-chunks响应驱动解析配合快照__snapshots__与convertReadableStreamToArray校验输出回归 UI 链路在examples/ai-e2e-next中验证回复 → 追问 → 上下文正确回传的多轮闭环。这套流程的价值在于真实响应保证了解析逻辑的保真度夹具化让测试彻底离线、可重复、可 diff而手动测试则兜底覆盖了单元测试难以触及的 UI 与多轮交互链路——三者共同构成 AI SDK 各 Provider 包的质量防线。延伸阅读贡献总览CONTRIBUTING.md构建新功能时的测试要求contributing/building-new-features.md新增 Provider 指南contributing/add-new-provider.md测试基础设施包packages/test-server核心工具包含测试辅助packages/provider-utils【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/8 11:28:05

CNN特征提取与SVM/GentleBoost混合分类实战

简介:本资源是一份面向高校机器学习课程学习者与初学者的完整实践项目包,聚焦卷积神经网络(CNN)在图像场景分类任务中的Matlab实现。资源包含可直接运行的CNN训练与测试源码、覆盖15类典型室内外场景的标注图像数据集,…

2026/10/30 17:21:54

AI重塑电影视觉叙事:从概念到成片的人机协作实战

1. 从一场大师分享说起:AI如何悄悄改写电影制作的底层逻辑前阵子听了一位英国导演Eran Creevy的分享,主题是AI、情感与视觉叙事的关系。这位导演你可能不太熟悉,但他拍过《车手》和《欢迎来到庞奇》,在商业片和独立项目之间来回切…

2026/10/24 20:20:47

Typst 安装部署指南:10 分钟从零编译出第一份 PDF

Typst 安装部署指南:10 分钟从零编译出第一份 PDF 【免费下载链接】typst A markup-based typesetting system that is powerful and easy to learn. 项目地址: https://gitcode.com/GitHub_Trending/ty/typst Typst 是一个用标记语言写文档的排版系统&#…

2026/11/9 9:59:52

工地太忙根本没时间复习考试?邹城高压电工证多少钱保姆级教程来了

工地太忙根本没时间复习考试?邹城高压电工证多少钱保姆级教程来了 工地太忙根本没时间复习考试,高压电工证又得年审,这事儿我太懂了。我之前在信阳当过几年的电焊工,后来转岗当电工,最头疼的就是证书的事情,尤其是高压电工证。现在在邹城,很多人和我一…

2026/11/9 9:59:52

苏家屯电工证报名真实经历:证书过期了不知道怎么复审延期怎么办

苏家屯电工证报名真实经历:证书过期了不知道怎么复审延期怎么办 证书过期了不知道怎么复审延期,这事儿真不是小事。上周我接到一个漯河本地施工企业的负责人,他手里的低压电工证已经过了有效期,现在项目上需要用到,结果一查才发现不能用了,整个人都慌了…

2026/11/9 9:59:52

广州哪报名考电工证上岗必备全流程详解

广州哪报名考电工证上岗必备全流程详解 你是不是也遇到过这样的问题: 不知道去哪报名怕被中介坑 ?特别是在广州这种外来务工人员众多的城市,很多工程类岗位都要求必须持有 上岗必备…

2026/11/9 9:59:52

湛江电工证考试简单?全国通用的证书怎么考?

湛江电工证考试简单?全国通用的证书怎么考? 你是不是也担心不知道去哪报名,怕被中介坑?尤其是像湛江这样的地方,很多电工朋友想考证,但又怕被坑钱、被忽悠。湛江电工证考试简单,但你得选对渠道。别担心,这篇文章帮你理清楚怎么报名、怎么备考,还能让…

2026/11/9 9:54:52

河津初级电工证怎么考考前押题全攻略

河津初级电工证怎么考考前押题全攻略 工地太忙根本没时间复习考试,这是很多一线电工朋友的真实写照,尤其是像你在河津这种施工企业密集的地区,项目一个接一个,电工岗位成了刚需,但证书考试和复习却被一再拖延,最后只能临时抱佛脚,甚至走捷径。别急,今…

2026/11/9 0:37:55

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/9 0:03:09

建设厅的特种工有哪些含金量高?别交完钱考不过

建设厅的特种工有哪些含金量高?别交完钱考不过 怕考不过白交培训费?别急,先搞清楚建设厅的特种工有哪些含金量高的证,再决定是不是值得投入时间和金钱。 建设厅的特种工证是建筑行业里最基础、也最实用的证书之一,涉及多个作业类别,每种证的 含金量…

2026/11/9 0:03:09

荆门市电工证报名怎么考才靠谱 全国通用证别交冤枉钱

荆门市电工证报名怎么考才靠谱 全国通用证别交冤枉钱 怕考不过白交培训费?荆门市电工证报名前必须知道这些避坑指南。别看网上一堆培训机构广告,真要报个电工证,很多人被坑得一塌糊涂。特别是那些打着“包过”旗号的,最后不是考试不过,就是证不是全国通…

2026/11/9 0:03:09

高空电工作业过程通过率揭秘:怎么选靠谱机构不被坑

高空电工作业过程通过率揭秘:怎么选靠谱机构不被坑 不知道去哪报名怕被中介坑?你不是一个人。现在特种作业证报名渠道五花八门,从线下培训机构到线上代理,真假难辨。尤其是像高空电工作业这类高风险、高门槛的作业类型,证书含金量和考试通过率直接影响你…

2026/11/9 6:30:27

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/7 14:50:12

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑