
Opik Python SDK 的 OpenAI 集成用 track_openai 一行代码追踪 Chat Completions、流式与结构化输出【免费下载链接】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 集成文档展开讲解如何用track_openai装饰函数包装openai.OpenAI/openai.AsyncOpenAI客户端将每一次模型调用自动记录为 Opik 平台上的 trace/span。读完本文你将掌握集成的完整用法参数、支持的方法范围、provider 推断规则并理解底层补丁机制——包括流式响应的聚合逻辑与版本兼容分支——以便在排查“为什么我的流式调用 token 用量没记上”这类问题时能快速定位原因。一、基本用法包装客户端即开始记录官方文档 OpenAI 集成页 给出的核心用法只有四行代码用track_openai包住 OpenAI 客户端之后所有经过该客户端的调用都会被记录from opik.integrations.openai import track_openai from openai import OpenAI openai_client OpenAI() openai_client track_openai(openai_client) response openai_client.chat.completions.create( modelgpt-3.5-turbo, messages[{role: user, content: Hello, world!}], )两点需要注意track_openai不是装饰器而是客户端包装函数它接收一个openai.OpenAI或openai.AsyncOpenAI实例返回同一个被原地打补丁patched的实例类型定义见 opik_tracker.py。补丁在调用track_openai时就已生效但每次被包装的调用执行时会先检查opik.is_tracing_active()——追踪被关闭时调用照常执行只是不发 span/trace该行为写在 track_openai 的 docstring 中。这意味着你可以放心在启动阶段无条件包装客户端通过开关控制是否上报。二、track_openai 参数详解track_openai的完整签名见 opik_tracker.py#L24-L28def track_openai( openai_client: OpenAIClient, project_name: Optional[str] None, provider: Optional[Union[str, LLMProvider]] None, ) - OpenAIClient:参数默认值说明openai_client必填OpenAI或AsyncOpenAI实例project_nameNone数据上报到的 Opik 项目名称不传则沿用当前opik.track/上下文所在项目providerNone记录在每条 LLM span 上的模型供应商标识接受任意字符串或 opik.types.LLMProvider 枚举中的已识别供应商provider 的推断与覆盖OpenAI SDK 常被当作访问其他 OpenAI 兼容 APITogether、OpenRouter、vLLM、DeepSeek 等的通用客户端因此provider参数用来标注真实的模型供应商而不是 base URL 主机名不传provider时由 _get_provider 从客户端的base_url推断——host 为api.openai.com记为openai否则直接使用 host 字符串。传字符串时原样记录例如track_openai(client, providervllm)。传LLMProvider枚举时取.value归一化为纯字符串避免枚举成员本身泄漏到日志中。LLMProvider枚举中与成本追踪相关的取值包括openai、anthropic、google_vertexai、google_ai、groq、bedrock、anthropic_vertexai见 types.py#L20-L32。使用已识别的 provider 名可以让 Opik 按对应供应商的价格体系计算 token 成本。幂等性保护if hasattr(openai_client, opik_tracked): return openai_client openai_client.opik_tracked Truetrack_openai 的实现 用opik_tracked属性标记已包装的客户端重复调用会直接返回原对象不会双重包装。但要注意一个实现细节functools.wraps会把__wrapped__等属性复制到被装饰函数上因此 audio 补丁处专门调整了打补丁顺序with_streaming_response.create必须先于speech.create被包装否则幂等检查会误判跳过——见 源码注释。三、哪些 OpenAI 调用会被追踪track_openai按客户端实际具备的属性按需打补丁hasattr判断见 opik_tracker.py#L82-L91覆盖范围如下同样列在 docstring 中方法span 名称备注chat.completions.create()chat_completion_create含streamTrue流式模式beta.chat.completions.parse()chat_completion_parse结构化输出beta.chat.completions.stream()chat_completion_stream仅 OpenAI SDK ≥ 1.92.0 时单独包装chat.completions.parse()chat_completion_parse同上版本分支responses.create()/responses.parse()responses_create/responses_parseResponses APIvideos.create()/remix()/poll()/list()/delete()/create_and_poll()/download_content()videos.*retrieve有意不包装避免轮询期间产生过多 spanaudio.speech.create()audio.speech.createTTSaudio.speech.with_streaming_response.create()同名 span流式 TTS所有补丁后的 span 统一带有created_from: openai、type: openai_chatchat 类或openai_videos视频类的 metadata 与openai标签方便在 Opik 中按来源过滤。为什么 beta 分支与 OpenAI SDK 版本相关_patch_openai_chat_completions 中有明确的版本分支SDK 1.92.0beta.chat.completions.stream()底层调用chat.completions.create(streamTrue)装饰create就自动覆盖了 stream因此只需单独包装beta.chat.completions.parse。SDK ≥ 1.92.0OpenAI 重构了 beta API——chat.completions.stream仍走create无需重复装饰但beta.chat.completions.stream不再经过create必须显式包装同时parse同时出现在chat.completions与beta.chat.completions两个路径下两处都要装饰。版本判断使用SemanticVersion.parse(openai.__version__) 1.92.0完成所以升级 OpenAI SDK 大版本时追踪行为会自动切换无需改代码。四、span 记录了什么input、output 与 token 用量chat 类调用的 span 内容由 OpenaiChatCompletionsTrackDecorator 负责组装开始时_start_span_inputs_preprocessorinput仅取 kwargs 中的messages和function_call键KWARGS_KEYS_TO_LOG_AS_INPUTSmetadata其余 kwargs 全部归入 metadata并合并created_from/type标识model、provider、tags[openai]若streamTruespan 名自动改写为chat_completion_stream并过滤掉 OpenAI SDK 内部的NOT_GIVEN/Omit哨兵值_remove_not_given_sentinel_values避免无意义的占位参数进入日志。结束时_end_span_inputs_preprocessoroutput响应体中的choices其余字段进 metadatausage当响应含usage时用 OpenAI 格式的用量解析器构建 Opik 用量对象——注意这里的 openai 指的是用量 payload 格式与 span 上的 provider可能已被provider参数覆盖为别的供应商是两回事源码注释特别说明了这一点model取自响应体的model字段实际模型名而非请求时的别名。流式响应分块聚合再记录流式调用的难点在于 span 的 output 和 usage 只有在流读完之后才完整。实现分两层流补丁层stream_patchers.py替换openai.Stream.__iter__/openai.AsyncStream.__aiter__以及ChatCompletionStreamManager的__enter__/__aenter__在迭代过程中累积所有 chunk捕获中途异常作为error_info并在流耗尽或退出时结束对应 span/trace。四种流形态同步/异步 × 裸流/流管理器各有对应补丁函数分派逻辑见 _streams_handler。聚合层chat_completion_chunks_aggregator.pyaggregate()把一组ChatCompletionChunk还原为一个类ChatCompletion的 Pydantic 对象——拼接delta.content得到完整文本、保留首个 chunk 的id/model/created、取最后一个finish_reason和最后一个非空usage第 59-60 行。聚合失败时只记录错误日志并返回None不会打断业务调用。一个直接推论流式 span 的 output 和 token 用量要等生成器被完全消费或提前退出后才更新若你拿到流但从未迭代完span 可能停留在中间状态。这也是官方示例中建议开启stream_options{include_usage: True}的原因——否则流式响应里根本没有usage字段可聚合。五、完整可运行的参考示例仓库自带示例 openai_integration_example.py 覆盖了三种典型调用形态与四条 trace 的划分方式可直接复制改造from openai import OpenAI from opik import flush_tracker, track from opik.integrations.openai import opik_tracker from pydantic import BaseModel client OpenAI() client opik_tracker.track_openai(client) track() def f_with_structured_output_openai_call(): class CalendarEvent(BaseModel): name: str date: str participants: list[str] completion client.beta.chat.completions.parse( modelgpt-4o-2024-08-06, messages[ {role: system, content: Extract the event information.}, {role: user, content: Alice and Bob are going to a science fair on Friday.}, ], response_formatCalendarEvent, ) print(completion) track() def f_with_streamed_openai_call(): stream client.chat.completions.create( modelgpt-3.5-turbo, messages[{role: user, content: Tell a fact}], max_tokens10, streamTrue, stream_options{include_usage: True}, ) for item in stream: print(item) f_with_streamed_openai_call() # trace 1 f_with_structured_output_openai_call() # trace 2嵌套 span 挂在 track 之下 flush_tracker()示例展示了两个关键实践与track组合OpenAI 调用发生在track()装饰的函数内部时会作为嵌套 span挂到当前 trace 下示例注释明确写道 will create one more nested span脱离track上下文直接调用则各自成 trace示例第 76-83 行的裸调用即为独立 trace 4。进程退出前调用flush_tracker()确保缓冲中的 span/trace 全部发往 Opik 后端。六、适用前提与限制小结需要openai包已安装且版本语义可解析beta 相关追踪路径的行为随 OpenAI SDK 1.92.0 分界见第三节的版本分支说明。track_openai对responses、videos、audio等命名空间采用hasattr探测老版本 OpenAI SDK 上这些补丁会自动跳过只追踪 chat completions 部分。该集成会无条件上报一次analytics.track_event(integration, openai)匿名使用事件opik_tracker.py#L67 附近实际位于补丁前如介意可在配置层面关闭 Opik 的 analytics。视频retrieve方法有意不追踪、流式 span 需完整消费生成器后才落盘 output/usage——这两点都是源码中明确的取舍排查数据“缺失”时应优先核对此处。相关源码与文档入口集成文档、track_openai API 页该页通过autofunction直接从 opik_tracker.py 的 docstring 生成二者内容始终一致、集成示例。【免费下载链接】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),仅供参考