可观测性
运行时可以追踪经过其 AI 服务的调用。插件也可以给这些调用外层的工作命名,例如一次智能体回合或辅助任务,让相关操作出现在同一棵追踪树中。记录功能默认关闭。
:::warning 启用前请先确认 追踪数据可能包含提示词、回答和其他私人文本。请选择你信任的接收端。如果来源中可能有凭据或其他机密,请先添加脱敏规则,再开启记录。 :::
运行时记录什么
| 调用 | 观测类型 | 记录的数据 |
|---|---|---|
| 语言模型请求 | generation | 消息、工具声明、合并后的采样参数、模型输出、工具调用、token 用量、首 token 耗时和结束原因 |
| 向量嵌入 | embedding | 输入文本,以及向量数量和维度;不保存向量本身 |
| 重排序 | span | 查询、文档和分数 |
| 图像生成 | span | 提示词、选项、媒体类型和图像大小;不保存图像字节 |
| 语音合成或转写 | span | 文本或音频大小,以及转写结果或媒体类型 |
| 决策 | span | 状态、问题和回答 |
错误会附在观测记录上,同时仍会返回给调用方。完成的观测先进入后台队列,因此写入追踪不在服务调用的响应路径上。如果接收端写入失败,受影响的批次会丢失,运行时只记录一次该错误。
提供方报告模型名称和 token 数量时,运行时会一并记录。插件创建外层观测时,还可以设置稳定的追踪名称、会话 ID、用户 ID 和标签。这些字段可用于 Langfuse 的筛选和会话分组;调用插件没有提供时,运行时不会自行编造。
配置记录
打开 设置 -> 可观测性。页面包含以下选项:
- 使用记录调用开启或关闭追踪。
- 在记录发送到中选择每日 JSONL 文件、Langfuse 接收端,或同时使用两者。
- 通过记录的内容保留完整输入输出或缩短后的摘要。每个值的摘要长度默认是 500 个字符。
- 开启保留原始请求后,运行时会保存语言模型提供方发出的请求体。此项默认关闭,而且可能显著增大追踪记录。
- 在隐藏匹配的内容中每行填写一个正则表达式。匹配内容会在截断或发送前替换为
[redacted]。无效表达式会被忽略,并写入 DSH 日志。
选择文件输出时,文件夹留空表示使用 DSH 主目录下的 traces。运行时每天创建一个 trace-<日期>.jsonl 文件,每行写入一条观测或评分记录。
Langfuse 区域需要服务器地址、可选的环境名称和两个凭据引用。默认引用为 AI_PROVIDERS_LANGFUSE_PUBLIC_KEY 和 AI_PROVIDERS_LANGFUSE_SECRET_KEY。密钥值保存在 DSH 的凭据存储中。由环境变量提供的值会显示为只读。
Langfuse 与兼容接收端
运行时通过 OpenTelemetry HTTP/JSON 把 span 发送到 <服务器>/api/public/otel/v1/traces,其中包含 Langfuse 观测属性和 v4 摄取请求头。评分发送到 <服务器>/api/public/scores。
这套方式适用于 Langfuse,也适用于明确实现了上述 Langfuse 摄取端点和属性的系统。普通 OTLP 收集器并不足够,除非它另外提供这层兼容。配置前请查看接收系统的文档。
在 Langfuse 中,语言模型调用显示为 generation,向量嵌入显示为 embedding。外层工作可以使用 agent、tool、span 或 event。观测名称应保持稳定,因为已保存视图、仪表盘和评估器都可以按名称和类型筛选。
重放一次语言模型请求
如果需要完整请求体,请开启 保留原始请求,并使用完整内容记录。然后运行:
node scripts/replay-trace.mjs <trace.jsonl>
脚本会列出记录下来的语言模型调用。添加 --span <id> --url <端点> 可再次发送其中一个请求。--set temperature=0 可以修改顶层字段,--times <次数> 可以重复请求。输出会报告结束原因、工具调用、文本长度和 token 数量。偶发失败需要重复多次,才能判断差异是否有意义。
重放功能会把记录的请求体发往你指定的 URL。发送前请先检查内容,尤其是在启用了完整内容或原始请求记录时。
从插件添加外层观测
ctx.aiTrace 只在记录开启时存在。请用 ctx.get('aiTrace') 查找,这样追踪关闭或运行时未安装时,插件仍能正常工作。
const tracer = ctx.get('aiTrace')
const turn = tracer?.start({
name: 'run-turn',
kind: 'agent',
input: text,
trace: { name: 'run-turn', sessionId: storyId },
})
const unlink = turn === undefined ? undefined : tracer?.link(chatId, turn.ref)
// 此后带有该聊天 ID 的模型调用会嵌套在这个回合下。
unlink?.()
turn?.end({ output: answer })
公开的追踪器提供四种常见用法:
run(start, work)在异步工作期间把 span 设为当前观测,并在工作结束时结束它。start(start)返回一个句柄,适合流式任务等稍后才结束的工作。调用方需要自行执行end()。link(key, span)为无法继承异步上下文的工作指定父观测。运行时把语言模型请求的会话 ID 用作这个 key。score(span, score)给某条追踪或观测附加数值、布尔值或分类评分。
没有外层观测的服务调用会自行创建一条追踪。