AI SDK 集成
evlog/ai 通过中间件包装你的模型,为你提供完整的 AI 可观测性。Token 使用量、工具调用、流式性能、缓存命中、推理 token 和成本估算——全部会自动捕获到宽事件中。
使用 evlog 添加 AI 可观测性
安装
将 AI SDK 作为依赖添加:
pnpm add ai
bun add ai
yarn add ai
npm install ai
快速开始
ai sdk · streamText·idle
call timeline
- streamText()
model wrapped, request sent
- first chunk
msToFirstChunk: 234
- streaming…
output tokens flowing
- tool: getWeather
paris
- tool result
22°C, sunny
- streaming…
final answer being generated
- stream finish
finishReason: stop · msToFinish: 4500
wide event · ai field
{
model:"claude-sonnet-4.6"
provider:"anthropic"
inputTokens:0
outputTokens:0
totalTokens:0
reasoningTokens:225
tools:[]
msToFirstChunk:234
msToFinish:4500
tokensPerSecond:0
finishReason:"stop"
estimatedCost:$0.0000
}
tokens0
tools0
duration—
cost$0.0000
需要添加两行,修改一个参数:
export default defineEventHandler(async (event) => {
const result = streamText({
model: 'anthropic/claude-sonnet-4.6',
messages,
})
return result.toTextStreamResponse()
})
import { useLogger } from 'evlog'
import { createAILogger } from 'evlog/ai'
export default defineEventHandler(async (event) => {
const log = useLogger(event)
const ai = createAILogger(log)
const result = streamText({
model: ai.wrap('anthropic/claude-sonnet-4.6'),
messages,
})
return result.toTextStreamResponse()
})
你的宽事件现在包括:
Wide Event
{
"method": "POST",
"path": "/api/chat",
"status": 200,
"duration": "4.5s",
"ai": {
"calls": 1,
"model": "claude-sonnet-4.6",
"provider": "anthropic",
"inputTokens": 3312,
"outputTokens": 814,
"totalTokens": 4126,
"reasoningTokens": 225,
"finishReason": "stop",
"msToFirstChunk": 234,
"msToFinish": 4500,
"tokensPerSecond": 180
}
}
工作原理
createAILogger(log, options?) 会返回一个 AILogger,包含以下方法:
| 方法 | 描述 |
|---|---|
wrap(model) | 使用中间件包装一个语言模型。接受模型字符串(例如 'anthropic/claude-sonnet-4.6')或 LanguageModelV3 对象。适用于 generateText、streamText 和 ToolLoopAgent。 |
captureEmbed(result) | 从 embed() 或 embedMany() 的结果中手动捕获 token 使用量、模型信息和维度。 |
getMetadata() | 返回当前执行元数据的快照。参见 访问元数据。 |
getEstimatedCost() | 在配置了 cost 映射时,返回当前以美元计的估算成本。 |
onUpdate(callback) | 订阅元数据更新。每一步、embed、错误和集成完成时都会触发。 |
该中间件在提供方层拦截调用。它不会触碰你的回调、提示词或响应。捕获的数据会通过正常的 evlog 管道流动(采样、增强器、drain),并落入 Axiom、Better Stack 或你输出到的任何地方。
下一步
适用于所有框架
evlog/ai 适用于 evlog 支持的任何框架:
import { useLogger } from 'evlog'
import { createAILogger } from 'evlog/ai'
const log = useLogger(event)
const ai = createAILogger(log)
import { withEvlog, useLogger } from '@/lib/evlog'
import { createAILogger } from 'evlog/ai'
export const POST = withEvlog(async () => {
const log = useLogger()
const ai = createAILogger(log)
// ...
})
import { createAILogger } from 'evlog/ai'
app.post('/api/chat', (req, res) => {
const ai = createAILogger(req.log)
// ...
})
import { createAILogger } from 'evlog/ai'
app.post('/api/chat', (c) => {
const ai = createAILogger(c.get('log'))
// ...
})
import { createAILogger } from 'evlog/ai'
app.post('/api/chat', async (request) => {
const ai = createAILogger(request.log)
// ...
})
import { useLogger } from 'evlog/nestjs'
import { createAILogger } from 'evlog/ai'
const log = useLogger()
const ai = createAILogger(log)
import { createLogger } from 'evlog'
import { createAILogger } from 'evlog/ai'
const log = createLogger()
const ai = createAILogger(log)
// ...
log.emit()