首页
/ 使用 AI SDK DevTools 调试与检视 AI SDK 应用:遥测集成、数据流与源码级原理

使用 AI SDK DevTools 调试与检视 AI SDK 应用:遥测集成、数据流与源码级原理

2026-09-11 14:19:28作者:彭桢灵Jeremy

AI SDK DevTools 是 AI SDK(The AI Toolkit for TypeScript)生态中的本地开发调试工具,用于检视 AI SDK 应用的 LLM 请求、响应、工具调用与多步交互过程。本文以仓库中的 packages/devtools/README.md 为骨架,结合其源码实现,讲解如何安装、接入、运行 DevTools,深入剖析其数据捕获链路、存储结构与运行原理,并给出 monorepo、流式输出等实际场景下的使用建议。

适用前提:本包当前处于实验性阶段,仅用于本地开发调试,严禁在生产环境使用(源码在 integration.ts 中会在 NODE_ENV === 'production' 时直接抛错);要求 AI SDK v7 canary(ai@canary)与 Node.js 兼容运行时(包的 engines 声明为 node >= 22,见 package.json)。

一、安装与接入:两条捕获路径

1.1 安装

在项目根目录执行:

npm install @ai-sdk/devtools
# 或
pnpm add @ai-sdk/devtools

在 monorepo 场景下,请使用 pnpm add -w 或在运行 AI SDK 代码的同一 workspace 中安装。安装后包会暴露两个入口(见 src/index.ts):DevToolsTelemetry(遥测集成)与 devToolsMiddleware(模型中间件),同时注册 devtools 二进制命令(见 package.jsonbin/cli.js)。

1.2 路径一:全局注册遥测集成(推荐)

DevToolsTelemetry 挂接 AI SDK 的遥测生命周期,可自动捕获应用内所有 generateTextstreamTextgenerateObjectstreamObject 调用:

import { registerTelemetry } from 'ai';
import { DevToolsTelemetry } from '@ai-sdk/devtools';

registerTelemetry(DevToolsTelemetry());

注册后遥测自动生效,后续调用无需任何额外配置:

import { generateText } from 'ai';

const result = await generateText({
  model: yourModel,
  prompt: 'What cities are in the United States?',
});

需要注意,DevToolsTelemetry 会对 ai.embedai.embedManyai.rerank 等嵌入/重排操作直接忽略(见 integration.ts),因此捕获范围聚焦于文本生成与对象生成类调用。

1.3 路径二:按调用传入集成

如果不希望全局捕获,可将集成显式传给单次调用:

import { streamText } from 'ai';
import { DevToolsTelemetry } from '@ai-sdk/devtools';

const result = streamText({
  model: yourModel,
  prompt: 'Hello!',
  telemetry: {
    integrations: [DevToolsTelemetry()],
  },
});

1.4 路径三:语言模型中间件(面向流式调试)

除了遥测集成,包还导出 devToolsMiddleware,以 LanguageModelV4Middleware 形式包装模型,可在不依赖遥测系统的场景下捕获 generatestream 两个阶段:

import { streamText, wrapLanguageModel } from 'ai';
import { devToolsMiddleware } from '@ai-sdk/devtools';

const result = streamText({
  model: wrapLanguageModel({
    middleware: devToolsMiddleware(),
    model: yourModel,
  }),
  prompt: '...',
});

从源码看,该中间件会强制开启 includeRawChunks 以便收集 provider 原始分片,并区分三种结束路径——正常完成(flush)、流被取消(cancel)、抛出异常——分别写入不同的结果状态(见 middleware.ts)。生产环境下调用它会同样抛错拒绝。

1.5 runId 选项:关联跨请求的多步交互

DevToolsTelemetry 支持一个可选参数 runId,用于将多个 AI SDK 调用归并到同一条 DevTools run 中(见 integration.ts):

registerTelemetry(DevToolsTelemetry({ runId: 'my-session-1' }));

当传入 runId 时,源码会复用该 run 并依据已有步骤数设置 stepNumberOffset,保证续写交互的步骤编号连续(见 integration.ts)。在中断后恢复交互时,复用同一 runId 即可在视图中看到完整链路。

二、启动查看器(Viewer)

2.1 启动命令

npx @ai-sdk/devtools@latest

启动后打开 http://localhost:4983 即可查看 AI SDK 交互记录。CLI 实际是调用 startViewer(port) 启动 Hono 服务(见 bin/cli.js),默认端口为 4983。

端口可通过环境变量覆盖:

AI_SDK_DEVTOOLS_PORT=4984 npx @ai-sdk/devtools@latest

当端口被占用时,服务会给出明确报错并提示该用法(见 server.ts)。

2.2 界面与主题

查看器默认使用深色主题,可通过头部主题按钮切换深色/浅色,浏览器会记住同一 origin 下的选择(主题逻辑与测试见 theme.tstheme.test.ts)。

2.3 monorepo 使用建议

在 monorepo 中,应从运行 AI SDK 代码的同一 workspace 启动 DevTools。文档特别强调使用显式 @latest 标签:这能确保 npx 安装一个可执行副本,而不是选中某个传递依赖中的二进制文件(该依赖的 binary 未被链接进当前 workspace,会导致启动失败)。

2.4 开发模式

仓库内自带开发脚本(见 package.json):

pnpm install
pnpm dev        # 并发启动 API 与 Vite 客户端,UI 位于 http://localhost:5173

AI_SDK_DEVTOOLS_DEV=true 时 API 仅监听 4983 端口并重定向到 Vite dev server;未设置该标志时则直接托管构建好的 dist/client 静态产物(见 server.ts)。

三、工作原理:捕获、存储与实时推送

3.1 数据流

AI SDK call -> DevToolsTelemetry -> JSON file -> Hono API -> React UI

更精确地说,链路为:AI SDK 遥测事件 → 集成捕获并序列化 → 写入 .devtools/generations.json → 通过 HTTP 通知 Hono API → 服务端通过 SSE 广播 → React 查看器渲染。

3.2 本地存储与自愈机制

数据以 JSON 文件形式存储在项目根目录的 .devtools/generations.json(见 db.ts)。写入时有几个值得注意的实现细节:

  • 内存缓存dbCache 避免每次读写都解析整个文件,提升高频步骤写入性能(db.ts)。
  • 损坏自愈:若 JSON 解析失败则从空数据库重新开始(db.ts)。
  • gitignore 保护:首次创建 .devtools 目录时,若存在 .gitignore 且未包含 .devtools,会自动追加一行(db.ts),防止调试数据误提交。
  • 跨目录读取:notify 请求携带 dbPath,服务端校验其文件名与父目录必须严格匹配 .devtools/generations.json,且文件大小上限 100 MB,避免同步读卡死或 OOM(db.ts)。这使查看器即使从不同目录启动也能正确读取数据。
  • 进程退出兜底:集成与中间件都会注册 SIGINT/SIGTERM 处理器,进程退出前将仍在执行中的步骤标记为 Request aborted 并完成最后一次 notify(见 integration.ts)。

3.3 实时更新:SSE 推送

AI SDK 调用写入数据库后,通过 POST /api/notify 通知服务端重新加载数据库,并向所有已连接客户端广播 update 事件(server.ts)。客户端通过 /api/events 的 SSE 长连接接收更新,服务端每 30 秒发送一次心跳保活(server.ts)。此外 /api/runs/api/runs/:id/api/clear 分别提供运行列表、单条 run 详情(含递归子 run)与清空数据的能力,API 层同时校验 Host 与 Origin 白名单(server.ts)。

3.4 关键概念:Run 与 Step

  • Run:一次完整的、可能包含多步的 AI 交互,按初始 prompt 分组。每次 generateText/streamText 等顶层调用生成一个 run,run ID 由时间戳前缀 + UUID 片段构成,天然可按时间排序(integration.ts)。
  • Step:run 内的一次单次 LLM 调用。工具调用中嵌套的 generateText/streamText 会被关联为父 run 的子 run(源码通过 toolContextMap 跟踪嵌套上下文,见 integration.ts),查看器据此渲染父子层级。

四、捕获的数据内容

DevToolsTelemetry 为每个 step 捕获以下数据(见 integration.tsdb.ts):

类别 内容
输入参数与提示词 promptMessages/messages、工具定义(名称/描述/参数 schema)、toolChoice
生成设置 maxOutputTokenstemperaturetopPtopKpresencePenaltyfrequencyPenaltyseed
输出内容与工具调用 文本内容、finishReason、响应元信息(id/modelId/timestamp/messages)
用量与耗时 usage(token 用量 JSON)、duration_ms 耗时
Provider 原始数据 raw_request(请求 body)、raw_response(响应 body)、raw_chunks(流式原始分片)、provider_options
错误信息 error 字段记录异常消息

4.1 二进制媒体数据的序列化处理

消息中包含图片、音频等二进制内容时,直接 JSON.stringify 会产生大量乱码。仓库提供了专门的序列化工具 serializeForDevTools:它递归扫描消息结构,识别 filereasoning-fileimagemediafile-dataimage-data 等媒体承载字段,将其中 ArrayBuffer/TypedArray 转为 base64 保留,其余二进制值保持默认 JSON 表示(见 serialize.ts)。这意味着查看器中可以直接查看多模态消息的二进制附件。

4.2 流式输出如何被“收拢”

对于 streamText 这类流式调用,集成记录的是 step 开始时的输入;中间件路径下,流式分片通过 TransformStream 被汇总:text-delta 拼接成完整文本、reasoning-delta 拼接推理内容、tool-call 收集工具调用、finish 记录结束原因与用量,同时保存完整分片序列与原始分片供回放检视(见 middleware.ts)。

五、在 AI SDK 应用中的典型集成示例

仓库自带可运行的示例(examples/basic/index.ts),展示了带工具调用与 stopWhen 停止条件的多步交互:

import { gateway, isStepCount, registerTelemetry, streamText } from 'ai';
import { tools } from './tools';
import { DevToolsTelemetry } from '../../src';
import { print } from './utils';
import 'dotenv/config';

registerTelemetry(DevToolsTelemetry());

const result = streamText({
  model: gateway('anthropic/claude-haiku-4.5'),
  system: 'Always call the weather before recommending plans.',
  prompt: 'Whats the weather in SF and London in C?',
  tools,
  stopWhen: isStepCount(5),
  providerOptions: {
    anthropic: {
      thinking: {
        type: 'enabled',
        budgetTokens: 10000,
      },
    },
  },
});

print(await result.content);

运行该示例(pnpm exampletsx examples/basic/index.ts)后,在查看器中即可看到:一个 run 下包含多次 step——首轮调用返回工具调用,随后每轮工具结果回填触发新一轮 LLM 调用,直到满足 isStepCount(5) 停止条件。这正是调试多步 Agent 工作流时最常用的检视场景。

六、常见问题与注意事项

  • 生产环境误用DevToolsTelemetrydevToolsMiddlewareNODE_ENV === 'production' 下都会直接抛错,构建生产包前必须移除遥测注册或中间件包装。
  • 端口冲突:4983 被占用时服务会提示“DevTools is already running”,改用 AI_SDK_DEVTOOLS_PORT 指定新端口即可。
  • 查看器与应用目录不一致:得益于 notify 携带并校验 dbPath 的设计,查看器可从任意目录启动并读取正确数据;数据文件需位于以 .devtools/generations.json 结尾的路径,且不超过 100 MB。
  • 实验性状态:本包标注为实验性(见 README 顶部 Note),接口与行为可能随 AI SDK 演进调整,请以当前仓库实现为准。

七、进一步阅读

结合上述源码与测试,你可以在本地快速搭建起完整的 AI SDK 调用检视环境,定位多步 Agent 中工具调用、参数传递与原始 provider 数据的问题。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.16 K
2.78 K
kernelkernel
deepin linux kernel
C
34
18
docsdocs
暂无描述
Markdown
904
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
934
1.86 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
862
1.36 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.96 K
1.03 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.38 K
1.47 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
535
606
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
549
398
leetcodeleetcode
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Markdown
77
23