Opiktrack_openai详解一行代码将 OpenAI 客户端接入全链路追踪从参数语义到流式聚合实现【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llm本文基于 Opik Python SDK 的 OpenAI 集成 API 文档opik.integrations.openai.track_openai完整讲解该函数的参数语义、覆盖的全部受追踪调用Chat Completions、Responses、Videos、Audio、provider 推断与 cost 归因机制并结合 opik_tracker.py、openai_chat_completions_decorator.py 等源码说明 span 记录与流式聚合的底层实现帮助你在 LLM 应用中以最小侵入方式接入可观测性。文档定位一个由源码 docstring 自动生成的 API 参考页官方 API 文档页 track_openai.rst 本身只有两行 Sphinx 指令track_openai .. autofunction:: opik.integrations.openai.track_openaiautofunction指令会把 opik_tracker.py 中track_openai函数的 docstring 完整渲染成 API 参考。因此该文档的全部技术内容就是函数签名与文档字符串本文将其逐条继承并结合实现展开。基本用法track_openai接收一个已创建的 OpenAI 客户端返回同一个被“打补丁”后的客户端实例from openai import OpenAI from opik.integrations.openai import opik_tracker client OpenAI() client opik_tracker.track_openai(client)该函数在 opik_tracker.py#L24-L93 中定义类型标注OpenAIClient TypeVar(OpenAIClient, openai.OpenAI, openai.AsyncOpenAI)L14表明它同时支持同步OpenAI与异步AsyncOpenAI客户端。仓库中的完整示例 openai_integration_example.py 演示了普通调用、流式调用、结构化输出beta.chat.completions.parse三种场景。函数签名与参数语义def track_openai( openai_client: OpenAIClient, project_name: Optional[str] None, provider: Optional[Union[str, LLMProvider]] None, ) - OpenAIClient参数说明继承自文档字符串参数类型说明openai_clientopenai.OpenAI/openai.AsyncOpenAI要包装的 OpenAI 客户端实例project_nameOptional[str]数据写入的 Opik 项目名providerOptional[str / LLMProvider]记录到每个 LLM span 上的供应商名用于成本归因关于provider的关键细节源码 L27-L30、L73-L80为什么不传 provider 时仍会自动推断OpenAI SDK 常被用作访问其他 OpenAI 兼容 APITogether、OpenRouter、vLLM、DeepSeek 等的客户端。未显式传入provider时_get_providerL17-L21从客户端base_url推断host 为api.openai.com时记为openai否则直接取 base URL 的 host 作为 provider 名。支持opik.LLMProvider枚举可传任意字符串也可以传 Opik 为成本追踪识别的枚举值openai、anthropic、google_vertexai、google_ai、groq、bedrock、anthropic_vertexai。传入枚举成员时会被归一化为其字符串值避免LLMProvider.OPENAI这样的表示泄漏进日志和 spanL75-L78 注释。幂等性函数会给客户端打上opik_tracked True标记重复调用track_openai会直接返回原客户端而不会二次包装L68-L71。总是打补丁、按调用时刻决定是否上报文档字符串明确说明——客户端一旦被包装即被 patch但每个被包装的调用在执行前会检查opik.is_tracing_active()若调用时刻追踪处于关闭状态函数照常执行只是不发送 span/trace。首次包装时还会上报一次analytics.track_event(integration, openai)集成使用事件L67。覆盖的受追踪调用清单文档字符串列出的追踪范围如下与源码逐项对应openai_client.chat.completions.create()包括streamTrue模式openai_client.beta.chat.completions.parse()openai_client.beta.chat.completions.stream()openai_client.responses.create()openai_client.videos.create()、create_and_poll()、poll()、list()、delete()、remix()、download_content()以及下载内容的write_to_file()openai_client.audio.speech.create()与audio.speech.with_streaming_response.create()。源码中补丁是按能力条件挂载的L82-L91chat completions 总是补丁responses、videos、audio三个模块仅在客户端上存在对应属性时才补丁。从源码结构看这意味着不同版本的openai包缺少新模块时都能安全接入不会出现 AttributeError。Chat Completions 的版本分支行为_patch_openai_chat_completions中有一个以openai1.92.0为界的分支L128-L150openai 低于 1.92.0beta.chat.completions.stream()底层调用chat.completions.create(streamTrue)因此只需装饰create即可连带覆盖stream此时补丁beta.chat.completions.parseopenai 1.92.0 及以上OpenAI 重构了 beta APIbeta.chat.completions.stream不再走create必须单独装饰同时chat.completions.parse与beta.chat.completions.parse都会被装饰。三个装饰器分别生成名为chat_completion_create、chat_completion_parse、chat_completion_stream的 span并统一注入流式聚合器chat_completion_chunks_aggregator.aggregateL106-L123。每次调用会记录什么span 字段的生产逻辑Chat Completions 的具体字段组装在 openai_chat_completions_decorator.py 的OpenaiChatCompletionsTrackDecorator中span 命名与流式识别_start_span_inputs_preprocessorL46-L89在kwargs[stream] is True时把 span 名改为chat_completion_stream并调用_remove_not_given_sentinel_valuesL191-L201剔除 OpenAI SDK 内部的NOT_GIVEN/Omit哨兵值保证输入记录干净。输入记录仅messages与function_call两个 kwargs 记为 span inputKWARGS_KEYS_TO_LOG_AS_INPUTSL28其余参数并入 metadatametadata 统一追加{created_from: openai, type: openai_chat}tags 固定为[openai]model取自kwargs[model]provider取包装时解析出的值。输出记录_end_span_inputs_preprocessorL91-L131从响应的model_dump中把choices拆为 span output其余字段进 metadata。token 用量响应中的usage用 OpenAI 格式的转换器解析L110-L119。源码注释特别强调此处的openai指usage 载荷的格式而非 span 的 provider——即使客户端指向 OpenAI 兼容 API、provider 被覆盖usage 仍按 OpenAI 格式解析这是成本统计正确性的关键。流式追踪的实现stream patcher 与 chunk 聚合流式调用是 OpenAI 集成的难点span 无法在create()返回时结束必须等流被消费完。装饰器通过重写_streams_handlerL133-L188区分四类流对象并交给 stream_patchers.py 对应处理openai.Stream/openai.AsyncStream普通streamTrueChatCompletionStreamManager/AsyncChatCompletionStreamManagerbeta.chat.completions.stream()。补丁后的流在迭代过程中把每个 chunk 交给聚合器 chat_completion_chunks_aggregator.py 的aggregate()函数L22-L73它从首个 chunk 取id/created/model/system_fingerprint逐个拼接delta.content捕获finish_reason与usage最后一个 chunk 携带最终组装成与ChatCompletion结构同构的ChatCompletionChunksAggregatedL12-L19。聚合失败时记录错误日志并返回None不会中断业务调用。这与官方示例 openai_integration_example.py 中流式用例的注释一致流式调用“会多创建一个嵌套 span其 output 会在流生成器被耗尽时更新”——即 span 结束由流的finally回调finally_callbackself._after_call触发若你只拿到流却从不迭代span 也就不会关闭。Responses API 的流式事件则由 response_events_aggregator.py 聚合responses.create/responses.parse的 span 名分别为responses_create/responses_parseopik_tracker.py#L153-L188。Videos 与 Audio补丁取舍的细节Videos_patch_openai_videosvideos.create/videos.remix使用专用的VideosCreateTrackDecoratorcreate_and_poll、poll、delete、list直接用opik.track包装统一带 tags[openai]与 metadata{created_from: openai, type: openai_videos}源码注释明确说明videos.retrieve故意不补丁L231-L232因为轮询期间它会被高频调用全部记录会产生过多 spandownload_content返回惰性响应对象真正的下载发生在write_to_file()因此补丁同时覆盖两者L252-L262。Audio_patch_openai_audioaudio.speech.with_streaming_response是cached_property初始化时通过functools.wraps捕获当时的speech.create。如果先补丁speech.createfunctools.wraps会把opik_trackedTrue复制到流式包装器上导致幂等性检查误跳过它。因此源码刻意先补丁流式、后补丁同步L289-L303 注释。与track的组合嵌套 span 与独立 trace文档字符串指出track_openai“可以在其他 Opik 被追踪函数内使用”。仓库示例 openai_integration_example.py 给出了典型模式from opik import flush_tracker, track from opik.integrations.openai import opik_tracker client opik_tracker.track_openai(OpenAI()) track() def f_with_streamed_openai_call(): # 在 track 函数内调用LLM 调用成为当前 trace 下的嵌套 span stream client.chat.completions.create( modelgpt-3.5-turbo, messagesmessages, max_tokens10, streamTrue, stream_options{include_usage: True}, ) for item in stream: print(item)在track()装饰的函数内调用被包装的客户端时OpenAI 调用作为嵌套 span挂入当前 trace在追踪上下文之外调用示例 L76-L83每次调用自动成为一条独立 trace流式示例中stream_options{include_usage: True}保证最后一个 chunk 携带 usage从而让流式 span 也能记录 token 用量退出前调用flush_tracker()确保数据上报。测试验证与适用前提仓库为各追踪面提供了 library_integration 级别的测试可作为行为依据test_openai_chat_completions.py普通/流式 Chat Completionstest_openai_chat_completions_beta_api.pybeta 流式与 parsetest_openai_responses.pyResponses APItest_openai_videos.py视频生成全链路test_openai_audio_tts.pyTTS 同步与流式。适用前提与限制客户端必须是openai.OpenAI或openai.AsyncOpenAI实例补丁基于运行时属性替换依赖openai包的模块结构openai1.92.0与更早版本的行为差异已由源码分支处理见上文版本分支一节追踪是否实际产生 span/trace 取决于调用时刻opik.is_tracing_active()的状态接入 Opik 服务的前提配置 Opik 端点、opik.init()等不在本函数职责内若你的客户端指向 OpenAI 兼容端点且希望成本按真实供应商归因建议显式传入provider否则 provider 会是 base URL 的 host。小结track_openai的价值在于“一次包装、多 API 覆盖、行为透明”它按能力条件为 Chat Completions含流式与 beta parse/stream、Responses、Videos、Audio 四类接口挂载追踪装饰器span 的输入/输出/usage 字段有明确的组装规则流式 span 通过 stream patcher chunk 聚合器在流耗尽时正确关闭provider参数与 base URL 推断机制保证了 OpenAI 兼容场景下的成本归因。配合track即可在 LLM 应用中形成从业务函数到模型调用的完整 trace 树。【免费下载链接】comet-llmDebug, evaluate, and monitor your LLM applications, RAG systems, and agentic workflows with comprehensive tracing, automated evaluations, and production-ready dashboards.项目地址: https://gitcode.com/GitHub_Trending/co/comet-llm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考