ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Phoenix 生产链路 Trace 采样策略实战:基于 @arizeai/phoenix-client 的 TypeScript 采样指南

Phoenix 生产链路 Trace 采样策略实战:基于 @arizeai/phoenix-client 的 TypeScript 采样指南 可观测性AI 评测LLMOpsAI 应用人工智能【免费下载链接】phoenixAI Observability Evaluation项目地址https://gitcode.com/gh_mirrors/phoenix13/phoenix点击查看免费下载导读当 Phoenix 承载生产环境的大流量 LLM 应用时海量 span 会让人工审查、错误分析与黄金数据集构建变得不可持续。本文以.agents/skills/phoenix-evals/references/observe-sampling-typescript.md为骨架系统讲解如何在 TypeScript 项目中用arizeai/phoenix-client的getSpans、getTraces、getSpanAnnotations三个核心 API 实现失败优先采样、离群值采样、分层采样与指标引导采样并结合仓库源码深入剖析每个过滤参数的服务端语义、版本要求与分页机制最终落地一个可用的生产 review 队列。读完本文你将掌握一套少采样、精采样、可复现的生产可观测性数据采集方案。前置准备客户端初始化与服务端能力协商所有采样策略都建立在 Phoenix TypeScript 客户端之上。arizeai/phoenix-client提供了基于 openapi-fetch 的类型安全客户端可通过createClient工厂创建实例参见 client.tsimport { createClient } from arizeai/phoenix-client; const client createClient({ options: { baseUrl: http://localhost:6006, // 默认端口 6006 }, });从client.ts的配置合并逻辑getMergedOptions可以看出优先级为默认值 环境变量 显式传入的 options。如果baseUrl未显式指定客户端会自动读取环境变量配置。仓库中的可运行示例 get_spans.ts、get_traces.ts 均按此模式初始化。另一个关键机制是服务端能力协商capability negotiation客户端在发起带过滤条件的请求前会先检查 Phoenix 服务端版本是否支持对应参数。例如 getSpans 实现 中的ensureSpanFilterCapabilities会按参数分别校验过滤参数要求的最低服务端版本traceIdsPhoenix server 13.9.0spanIdsPhoenix server 19.6.0name/spanKind/statusCode需支持 span filtersGET_SPANS_FILTERSattributesPhoenix server 14.9.0getTraces则要求 Phoenix server 13.15.0其中filter表达式参数要求 20.12.0参见 getTraces.ts。这意味着采样的过滤逻辑是服务端下推的——只有被过滤条件选中的 span 才会跨网络传输这也是高效采样的根基。策略一失败优先采样最高优先级生产审查的第一要务永远是错误。与其拉取全量数据再在客户端过滤不如让服务端只返回你真正关心的 span。以下示例完整继承自原文档import { getSpans } from arizeai/phoenix-client/spans; // 服务端过滤 —— 只返回 ERROR 状态的 span const { spans: errors } await getSpans({ project: { projectName: my-project }, statusCode: ERROR, limit: 100, }); // 只拉取 LLM span const { spans: llmSpans } await getSpans({ project: { projectName: my-project }, spanKind: LLM, limit: 100, }); // 按 span 名称过滤 const { spans: chatSpans } await getSpans({ project: { projectName: my-project }, name: chat_completion, limit: 100, });这三个过滤参数的服务端语义可以从源码确认statusCode类型定义见 types/spans.ts取值限定为OK | ERROR | UNSET且支持传入数组进行多值过滤源码buildSpansQuery中Array.isArray(statusCode) ? statusCode : [statusCode]的处理。spanKindSpanKindFilter接受 OpenInference 标准 span kindLLM、CHAIN、TOOL、RETRIEVER等同时为了前向兼容也接受任意字符串。name支持单个字符串或字符串数组命中 span 名称精确匹配。用 attributes 精确锁定业务维度原文档之外的进阶能力是按属性过滤。getSpans的attributes参数以 AND 语义匹配 span 上的任意键值对且值的 JS 类型决定匹配方式{ user.id: 12345 }匹配存储为整数的属性{ user.id: 12345 }匹配存储为字符串的属性参见 getSpans.ts 与序列化逻辑serializeAttributeValue。注意布尔值会被 JSON 序列化、非有限数值会抛出RangeError空字符串则按字符串字面量处理// 只取某租户的失败调用 const { spans: tenantErrors } await getSpans({ project: { projectName: my-project }, statusCode: ERROR, attributes: { user.tenant_id: t-42 }, limit: 100, });配合startTime/endTime接受Date对象或 ISO 8601 字符串startTime为闭区间、endTime为开区间以及parentId传null只取根 span失败优先采样可以组合出非常精确的检索条件。策略二离群值采样按延迟排序错误之外的另一个高频信号是慢。离群值采样通过客户端排序找出延迟最高的 span适合定位性能瓶颈与超时问题const { spans } await getSpans({ project: { projectName: my-project }, limit: 200, }); const latency (s: (typeof spans)[number]) new Date(s.end_time).getTime() - new Date(s.start_time).getTime(); const sorted [...spans].sort((a, b) latency(b) - latency(a)); const slowResponses sorted.slice(0, 50);这里getSpans返回的 span 采用 Phoenix 标准格式start_time/end_time为人类可读时间戳源码注释明确说明返回值human-readable timestamps and simplified attribute structures。limit默认值为 100所以显式指定limit: 200能拿到更大的候选池。更高效的服务端排序方案getTraces 的 sort 参数如果慢链路分析需要整条 trace客户端排序只适用于单页候选集。生产场景更推荐使用getTraces内置的排序能力——sort字段支持start_time | latency_ms配合order: desc可让服务端直接返回最慢的 trace参考 getTraces.tsconst { traces: slowest } await getTraces({ project: { projectName: my-project }, sort: latency_ms, order: desc, includeSpans: true, limit: 50, });此外getTraces还提供minLatencyMs/maxLatencyMs延迟区间过滤源码中的validateLatencyBounds会在负值或区间倒置时抛出明确错误但注意这两个参数已在源码中标记为deprecated推荐改用更通用的filter: latency_ms N表达式详见下文策略四。策略三分层采样覆盖度均衡当目标是构建覆盖各类请求形态的评估样本时单纯取前 N 条会偏向高频路径。分层采样按业务维度分组、每组等量抽取保证罕见但重要的类型不被淹没// 从每个类别中均等采样 function stratifiedSampleT(items: T[], groupBy: (item: T) string, perGroup: number): T[] { const groups new Mapstring, T[](); for (const item of items) { const key groupBy(item); if (!groups.has(key)) groups.set(key, []); groups.get(key)!.push(item); } return [...groups.values()].flatMap((g) g.slice(0, perGroup)); } const { spans } await getSpans({ project: { projectName: my-project }, limit: 500, }); const byQueryType stratifiedSample(spans, (s) s.attributes?.[metadata.query_type] ?? unknown, 20);分层键的选择决定了采样的质量。常见分组维度包括业务语义属性如metadata.query_type上例、metadata.intent请求来源如user.tenant_id、user.countryspan 类型如spanKindLLM/RETRIEVER/TOOL时间桶按小时/天分桶后每组抽样兼顾不同时段的行为差异。attributes字段在 Phoenix span 中是开放的键值存储读写均由埋点侧决定因此在使用前需先确认你的应用确实写入了对应属性可通过 Phoenix UI 或getSpans无过滤拉取少量数据核对。策略四指标引导采样用评估结果反选样本Phoenix 的 span 可以携带注释annotations——即 LLM 评估器或人工审查产出的打分与标签。指标引导采样的核心思路是先拉取一批 span再批量读取其 annotation筛选出被评估器标记为有问题的样本形成评估结果驱动的采样闭环import { getSpanAnnotations } from arizeai/phoenix-client/spans; // 拉取 span 的注释再按标签过滤 const { annotations } await getSpanAnnotations({ project: { projectName: my-project }, spanIds: spans.map((s) s.context.span_id), includeAnnotationNames: [hallucination], }); const flaggedSpanIds new Set( annotations.filter((a) a.result?.label hallucinated).map((a) a.span_id) ); const flagged spans.filter((s) flaggedSpanIds.has(s.context.span_id));getSpanAnnotations 参数语义从 getSpanAnnotations 实现 可以确认以下行为spanIds必填一次性传入要查询的 span ID 列表接口为GET /v1/projects/{project_identifier}/span_annotationsincludeAnnotationNames白名单——只返回指定名称的 annotation省略时返回该 span 的全部 annotation源码注释明确不设置时不做任何名称排除excludeAnnotationNames黑名单排除指定名称limit默认 100支持cursor分页annotation 的result结构包含label如hallucinated与score也可以按score数值阈值筛选。仓库中的 span_annotations.ts 展示了完整的读写链路先用addSpanAnnotation写入quality-score、safety-check等评估结果再用getSpanAnnotations配合includeAnnotationNames读回非常适合作为指标引导采样的前置参考。用 filter 表达式替代已废弃参数在 trace 级别getTraces的filter参数接受服务端过滤表达式可与其它过滤条件按 AND 组合直接把评估/延迟/错误逻辑下推到服务端。源码示例getTraces.ts给出了典型用法// 只取既报错又超时的 trace const slowFailures await getTraces({ client, project: { projectName: my-project }, filter: error_count 0 and latency_ms 1000, });注意filter要求 Phoenix server 20.12.0error、minLatencyMs、maxLatencyMs三个旧参数均已被标记为deprecated新代码应统一使用filter表达式。策略五Trace 级采样整条请求当审查、黄金数据集构建或端到端评估需要完整请求上下文trace 内全部 span时必须使用getTraces而非getSpans——后者默认返回的只是扁平 span 列表无法还原整棵调用树import { getTraces } from arizeai/phoenix-client/traces; // 最近 100 条 trace附带完整 span 树 const { traces } await getTraces({ project: { projectName: my-project }, limit: 100, includeSpans: true, }); // 按会话过滤例如多轮对话 const { traces: sessionTraces } await getTraces({ project: { projectName: my-project }, sessionId: user-session-abc, includeSpans: true, }); // 时间窗口采样最近一小时 const { traces: recentTraces } await getTraces({ project: { projectName: my-project }, startTime: new Date(Date.now() - 60 * 60 * 1000), // 过去一小时 limit: 50, includeSpans: true, });三个参数的服务端语义includeSpans置为true时响应携带每条 trace 的完整 span 明细不设置则只返回 trace 元信息网络开销更小。判断是否需要整棵树时建议遵循先看元信息、命中再补全的两阶段策略sessionId接受单个或多个 session 标识session_id 字符串或 GlobalID在多轮对话、Agent 会话追踪场景下按用户会话聚合非常有用startTime/endTime与getSpans语义一致ISO 8601 或Datestart 闭、end 开实现滑动时间窗采样。分页方面getTraces同样返回nextCursor。仓库示例 get_traces.ts 演示了includeSpans: true配合sort: start_time, order: desc拉取最近 trace 的完整用法。实战构建生产 Review 队列将多种策略组合即可搭建一个覆盖错误 随机的日常人工审查队列。以下代码完整继承自原文档// 组合服务端过滤条件构建审查队列 const { spans: errorSpans } await getSpans({ project: { projectName: my-project }, statusCode: ERROR, limit: 30, }); const { spans: allSpans } await getSpans({ project: { projectName: my-project }, limit: 100, }); const random allSpans.sort(() Math.random() - 0.5).slice(0, 30); const combined [...errorSpans, ...random]; const unique [...new Map(combined.map((s) [s.context.span_id, s])).values()]; const reviewQueue unique.slice(0, 100);这段代码体现了三个工程要点错误全量 随机抽样errorSpans保证所有失败调用都会被覆盖审查的最高优先级随机样本则提供正常流量的基线视图防止只看错误造成的幸存者偏差按context.span_id去重通过Map以 span ID 为键合并两个来源避免同一 span 在队列中重复出现——context.span_id是 Phoenix span 的全局唯一标识后续做 annotation 关联、样本入库时也统一用它截断上限slice(0, 100)将单轮审查工作量控制在可接受范围与下文样本量指南中的初始探索 50–100呼应。在此基础上队列里的 span ID 可以直接喂给getSpanAnnotations做指标引导复核或用于构建黄金数据集golden dataset——这正是 Phoenix evals 工作流.agents/skills/phoenix-evals中观察 → 评估 → 沉淀数据环节的起点。样本量指南与饱和判定原文档给出了经过实践检验的样本量参考表这是设计任何采样策略前都应先确定的锚点用途样本量初始探索Initial exploration50–100错误分析Error analysis100直到饱和黄金数据集Golden dataset100–500评估器校准Judge calibration每类 100饱和Saturation判据当新采样的 trace 不再暴露新的失败模式而是反复复现同类问题如同样的检索缺失、同样的工具调用失败时即可判定当前问题集合已饱和可以停止继续扩样——继续采样只会线性增加标注成本而不会带来新的信息增益。饱和点通常出现在错误分析进行到中段因此建议分批采样每批 50–100 条每批结束后做一次失败模式聚类用getTraces的时间窗参数实现持续采样但只保留新模式的滚动队列在评估器校准阶段按类别label/class分别凑满 100避免低频类别样本不足导致校准偏差。采样策略选型速查场景推荐策略核心 API / 参数错误排查失败优先getSpansstatusCode: ERROR/attributes性能瓶颈定位离群值延迟getTracessort: latency_ms/filter: latency_ms N覆盖多样性的样本/黄金数据集分层采样getSpans 客户端stratifiedSample按业务属性分组评估结果反选指标引导getSpans→getSpanAnnotations→ 按label/score过滤多轮会话、Agent 全链路Trace 级getTracesincludeSpans: true/sessionId日常人工审查Review 队列错误 随机getSpans多条件组合 context.span_id去重小结生产环境下的 trace 采样不是随机碰运气而是一套可编排的策略组合失败优先保证错误零遗漏离群值聚焦性能退化分层确保覆盖均衡指标引导让评估结果反哺采样Trace 级采样保留完整上下文。arizeai/phoenix-client的getSpans、getTraces、getSpanAnnotations三个 API 全部支持服务端下推过滤与游标分页nextCursor配合客户端内置的服务端版本能力协商可以安全、高效地在生产流量上构建持续运转的采样与审查管线。相关实现与示例可进一步查阅 getSpans.ts、getTraces.ts、getSpanAnnotations.ts 及其测试用例getSpans.test.ts、getTraces.test.ts配合 Python 侧对应参考 observe-sampling-python.md 可构建跨语言的统一采样规范。赞分享可观测性AI 评测LLMOpsAI 应用人工智能【免费下载链接】phoenixAI Observability Evaluation项目地址https://gitcode.com/gh_mirrors/phoenix13/phoenix点击查看免费下载相关推荐Phoenix 生产环境 Trace 采样策略用 Python 高效抽取待审 Trace 的完整实战指南Phoenix 生产环境 Trace 采样策略用 Python 高效抽取待审 Trace 的完整实战指南 在 AI Observability 与 Evalu可观测性AI 评测LLMOpsAI 应用人工智能Phoenix TypeScript 环境搭建指南安装与配置 arizeai/phoenix-client、phoenix-evals 与 phoenix-otelPhoenix TypeScript 环境搭建指南安装与配置 arizeai/phoenix client、phoenix evals 与 phoenix可观测性AI 评测LLMOpsAI 应用人工智能解析 Cloud Databases Onboarding Skill 的三阶段数据库选型 Agent 指令从需求发现到 Plan-Validate-Execute 落地解析 Cloud Databases Onboarding Skill 的三阶段数据库选型 Agent 指令从需求发现到 Plan Validate Exec可观测性AI 评测LLMOpsAI 应用人工智能创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表