尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Opik Python 集成开发指南:从 track_xxx() 到 LLM 可观测性(comet-llm)

Opik Python 集成开发指南:从 track_xxx() 到 LLM 可观测性(comet-llm) Opik Python 集成开发指南从 track_xxx() 到 LLM 可观测性comet-llm【免费下载链接】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导读本文以 comet-llm 仓库中sdks/python/src/opik/integrations/目录下的 Python 集成Integration体系为蓝本系统讲解如何为 LLM 框架与模型提供方 SDK 构建 Opik 追踪集成。你将掌握四种集成机制方法打补丁、纯回调、混合、OTel的适用场景、track_name()入口的标准化写法、span 预处理器的实现要点、流式聚合与 token 用量归一化以及集成测试与 CI 注册的完整流程可直接用于为任意 Python LLM 框架编写新的 Opik 集成。集成形态总览四种机制模板Opik Python SDK 的集成统一放在 sdks/python/src/opik/integrations/ 目录下每个集成以name/子目录承载。在动手之前先根据目标库的接口形态决定采用哪种机制机制适用场景仓库内规范模板方法打补丁Method patchingSDK 是带有待包装方法的客户端对象绝大多数模型提供方integrations/openai/纯回调Pure callback框架自身暴露了回调 / tracer 接口integrations/langchain/混合Hybrid回调不可靠、还需要方法级钩子integrations/adk/OTel框架已经会发出 OpenTelemetry spanintegrations/otel/选择原则优先复用现成模板而不是从零发明。几乎所有提供方 SDK 都是客户端 方法形态因此方法打补丁是默认选项只有当框架提供回调/tracer 接口时才走纯回调当回调体系不完整、无法覆盖全部调用路径时才考虑在回调之外叠加方法钩子形成混合方案。目录骨架每个集成固定四件套无论采用哪种机制Python 集成的文件布局都遵循统一骨架参考 python.mdsdks/python/src/opik/integrations/name/ ├── __init__.py # 只导出公共入口不导出其他任何符号 ├── opik_tracker.py # 入口track_name()打补丁或 tracer 类 ├── name_decorator.py # BaseTrackDecorator 子类 —— 打补丁类集成 └── name_chunks_aggregator.py # 将流式 chunk 合并为完整响应 —— 仅流式场景方法打补丁类集成opik_tracker.py存放track_name()入口name_decorator.py存放BaseTrackDecorator子类流式场景再配一个 chunk 聚合器。以 OpenAI 集成为例openai/ 下的chat_completion_chunks_aggregator.py、openai_chat_completions_decorator.py、opik_tracker.py、stream_patchers.py四件套结构清晰。回调类集成把装饰器文件替换为opik_tracer.py其中持有BaseTracer子类及辅助模块。LangChain 集成就是典型langchain/opik_tracer.py、langchain/run_parse_helpers.py 以及provider_usage_extractors/、response_cost_extractors/两个提取器包。混合类集成在骨架之上额外增加patchers/包与回调注入器。ADK 集成即如此adk/ 下既有opik_tracer.py、legacy_opik_tracer.py也有patchers/、recursive_callback_injector.py等打补丁与注入组件。方法打补丁最常见机制的完整解剖入口函数的标准形态打补丁类集成的入口是track_name(client, project_nameNone, providerNone)它原地修改客户端并原样返回。以 OpenAI 集成的 opik_tracker.py 为规范模板结构如下def track_name(client, project_nameNone, providerNone): if hasattr(client, opik_tracked): # 幂等保护重复调用直接返回 return client client.opik_tracked True # 解析 provider然后通过装饰器工厂逐个 patch 方法 _patch_name(client, provider, project_name) return client几个值得注意的细节均有源码佐证幂等保护hasattr(client, opik_tracked)检查保证同一个客户端被track_name()重复调用时只打一次补丁。OpenAI 源码中还有一个微妙的坑audio.speech.with_streaming_response是cached_property会在初始化时通过functools.wraps捕获speech.create因此代码特意先 patch 流式响应、再 patch 同步speech.create避免opik_trackedTrue被复制到流式包装器上导致幂等检查误跳过见 opik_tracker.py 的注释。provider 解析OpenAI 集成通过base_url.host推断 provider——api.openai.com记为openai否则记为 base URL 的主机名从而天然支持 Together、OpenRouter、vLLM、DeepSeek 等 OpenAI 兼容端点LLMProvider枚举成员会规范化为其字符串值避免裸枚举值泄漏到 span 中见 opik_tracker.py。追踪开关感知客户端总是被 patch但每个被包装的调用在调用时刻检查opik.is_tracing_active()——追踪关闭时底层调用照常执行只是不发送任何 span/trace。这保证了集成在追踪关闭时完全透明、零开销之外无副作用。两个预处理器span 生命周期裁剪每个被 patch 的方法都由一个BaseTrackDecorator子类包装。子类只需实现两个预处理器其余span/trace 创建、上下文嵌套、错误捕获、生成器处理全部继承自基类。以 openai_chat_completions_decorator.py 为模板_start_span_inputs_preprocessor(...)→ 返回StartSpanParameterstype、name、input、metadata、tags、model、provider。Mistral 集成把messages拆入 input、其余 kwargs 并进 metadata并写入created_frommistral、typemistral_chat见 mistral_decorator.py。_end_span_inputs_preprocessor(...)→ 返回EndSpanParametersoutput、usage、model、provider、metadata。响应对象先model_dump(modejson)再按 key 拆出 output 与 metadatausage字段存在时交给统一的 usage 归一化函数处理见 mistral_decorator.py。流式处理三种迭代形态都要覆盖流式场景下装饰器把generations_aggregator传给.track(...)并重写 stream handler使 chunk 被累积、span 在迭代结束后才 finalize。同步迭代器、异步迭代器、流式上下文管理器各有各的 patch 方式OpenAI 集成在 stream_patchers.py 中分别处理了openai.Stream、openai.AsyncStream、ChatCompletionStreamManager、AsyncChatCompletionStreamManager四种对象见 openai_chat_completions_decorator.py。委托方法只 patch 原语绝不双打这是整个文档中最重要的一条工程纪律。当高层方法会调用你已 patch 的低层方法时例如 Mistral 的chat.parse→chat.complete、parse_stream→streamOpenAI 旧版beta…stream→create不要两个都 patch——那会产生两个 span 并重复计费。正确做法是只 patch 原语委托调用自然透过原语形成单个 spanspan 以原语命名chat.complete→chat_completion_create、chat.stream→chat_completion_stream通过track_options.name/func.__name__实现委托调用如parse共享该名称结构化 JSON 仍在输出内容中只是缺少反序列化后的.parsed字段只使用现有track()API——不需要可重入标志、不需要contextvars、不需要进程级且存在竞态的set_tracing_active。Mistral 集成正是如此实现的仅 patchchat.complete/complete_async/stream/stream_async四个原语parse系列自动获得单个 span见 opik_tracker.py。span 重命名的红线不要用 kwarg 重命名 span除非该 kwarg 对原语的每一个调用者都忠实标识其模式。OpenAI 的if kwargs.get(stream) is True: name chat_completion_stream是安全的因为create上streamTrue永远意味着流式但对 Mistral 的response_format用同样的技巧是错误的——直接的chat.complete(response_format…)是合法的结构化输出调用而非parse按response_format命名会错误归类这是 Mistral PR 评审中真实发现的问题。当判别式无法区分委托调用与对同一原语的直接调用时不要重命名保留原语名称。OpenAI 源码在streamTrue时还会额外剔除NOT_GIVEN哨兵值避免把 SDK 内部透传的无意义参数记入 input见 openai_chat_completions_decorator.py。环境变量不匹配的坑部分提供方 SDK 的客户端不会自动读取自己的 API Key 环境变量例如mistralai.Mistral()忽略MISTRAL_API_KEY。在测试与示例中必须显式传 keyMistral(api_keyos.environ[MISTRAL_API_KEY])不要依赖裸构造函数。OpenTelemetry 路线后端优先当目标框架已经能发出 OTel span 时大部分工作发生在后端Opik 暴露 OTLP 摄取端点将 OTel span 映射为 Opik trace。因此很多 OTel集成其实只有文档、没有代码——用户只需把框架的 OTLP exporter 指向 Opik 并附上认证头即可无需写任何 SDK 代码。动笔前永远先确认这条路是否够用。只有需要塑造后端收到的内容设置 Opik 语义、重映射属性、桥接无法发出原始 OTLP 的框架时才写客户端代码。基础构件是 integrations/otel/OpikSpanProcessor——用户注册到TracerProvider上的 OTelSpanProcessor用于转发/注解 span分布式追踪辅助——attach_to_parent、extract_opik_distributed_trace_attributes。更重的变体是框架专属的 OTeltracer 包装器见 adk/patchers/adk_otel_tracer/用于拦截框架自身的 tracer 而非注册通用 processor。共享核心这些永远不要重写无论哪种机制span/trace 创建、错误捕获、用量归一化都来自 SDK 共享核心新集成严禁重新推导关注点模块装饰器基类opik/decorator/base_track_decorator.py遵循上下文的 span/trace 创建opik/decorator/span_creation_handler.pyStart/End span 数据类opik/decorator/arguments_helpers.py错误捕获exception_type、tracebackopik/decorator/error_info_collector.py生成器/流包装opik/decorator/generator_wrappers.pyToken 用量归一化opik/llm_usage.py →try_build_opik_usage_or_log_error(provider..., usage...)已识别提供方成本追踪opik/types.py →LLMProvider全局客户端opik/api_objects/opik_client.py →get_global_client()上下文栈opik/context_storage.py回调类集成的 span/trace 创建同样走span_creation_handler把框架的每个 run id 映射到SpanData/TraceData并设置metadata[created_from] name。专属用量格式绝不蹭别人的解析器即使某提供方的 token 用量载荷长得像 OpenAI 格式也必须在llm_usage命名空间中建立自己的格式而不是向try_build_opik_usage_or_log_error传providerLLMProvider.OPENAI。复用他人转换器会把你耦合到对方的 schema 变更并错误归属解析出的形状。以 Mistral 为工作示例标准步骤是新增llm_usage/name_usage.py定义class NameUsage(BaseOriginalProviderUsage)声明 token 字段含嵌套 details 类与from_original_usage_dict——仓库中已有 mistral_usage.py把它加入ProviderUsage联合类型并在llm_usage/opik_usage.py中添加OpikUsage.from_name_dictclassmethod在 llm_usage/opik_usage_factory.py 注册LLMProvider.NAME: [OpikUsage.from_name_dict]装饰器中以providerLLMProvider.NAME解析。非整数字段如prompt_audio_seconds会被后端 flat dict 自动丢弃。单元测试放在tests/unit/llm_usage/test_name_usage.py覆盖解析器与build_opik_usage工厂路径。依赖与导入纪律框架库只在集成模块内部导入import mistralai写在opik_tracker.py顶部。这之所以安全是因为该模块只会在用户执行from opik.integrations.name import ...时被触达。永远不要在opik包顶层导入任何集成。不要把框架加入install_requires除非它已是核心依赖openai 与 litellm 是其余大多不是。用户自行安装框架。integrations/name/__init__.py只导出公共入口。多版本兼容如果集成必须支持多个互不兼容的框架版本就在导入时用opik.semantic_version分支。ADK 集成即是范例adk/init.py 根据google.adk.__version__ 1.3.0在LegacyOpikTracer与新版OpikTracer之间切换。只导入框架公共 API绝不触碰内部模块。私有路径如mistralai.utils.eventstreaming.EventStream、mistralai.models.chatcompletionresponse.…会在版本更迭间移动并破坏集成。优先用顶层导出from mistralai import Mistral, ChatCompletionResponse用hasattr(pkg, name)检查可见性。当需要的类未被导出例如流类型时不要导入它——改用协议检测hasattr(output, __anext__)→ 异步流hasattr(output, __next__)→ 同步流pydantic 响应模型有__iter__但两者皆无。确需 patch 其 dunder 方法时对type(output)操作。Mistral 装饰器正是这么做的见 mistral_decorator.py这也是 Mistral PR 的真实评审发现。守护最低框架版本测试requirements.txt中钉住下限libX,next-major并在track_name()中加运行时检查抛出自解释错误——fOpik supports libX, but {installed} is installed…——让版本不兼容的用户看到明确信息而不是晦涩的AttributeError/ImportError。用importlib.metadata.version(lib)读取已装版本更健壮某些版本不暴露lib.__version__经opik.semantic_version.SemanticVersion.parse(...)比较。地板值靠实证确定——二分安装到依赖的公共 API 首次出现的那个版本对 Mistral 而言EventStream在 1.3.0 落地。Mistral 集成完整实现了这套检查见 opik_tracker.py。测试fake_backend 与 CI 双保险集成测试位于sdks/python/tests/library_integration/name/采用fake_backend与testlib的TraceModel/SpanModel树配合ANY_*匹配器断言。以 Mistral 测试 test_mistral.py 为参考happy-flow 测试形态如下def test_name_method__happyflow(fake_backend): client track_name(lib.Client()) response client.method(...) # 真实调用由 env fixture 门控 opik.flush_tracker() EXPECTED TraceModel( idANY_BUT_NONE, name..., inputANY_DICT.containing({...}), outputANY_BUT_NONE, tags[name], spans[ SpanModel( idANY_BUT_NONE, typellm, name..., usage..., modelANY_STRING.starting_with(...), providername, spans[], ) ], ) assert len(fake_backend.trace_trees) 1 assert_equal(EXPECTED, fake_backend.trace_trees[0])测试规范要点真实 API 调用用ensure_name_configuredfixture 门控key 缺失则跳过在conftest.py中镜像ensure_openai_configured添加覆盖面必须完整happy flow、流式、parse/结构化输出含其单 span / 不重复计费断言、自定义provider、嵌套在track之下、以及一个错误用例模型 id 集中到 tests/llm_constants.py测试目录内放requirements.txt声明框架包mistral/requirements.txt导入统一走from tests.testlib import TraceModel, SpanModel, ANY_BUT_NONE, ANY_DICT, ANY_STRING, assert_equal必须接入 CI创建.github/workflows/lib-name-tests.yml默认单 Python 版本并在lib-integration-tests-runner.yml中注册——未注册的测试永远不会运行。完整流程见 workflow.md 的 Phase 6。集成实战Mistral 端到端示例结合源码一个完整可运行的 Mistral 集成使用示例是import os from mistralai import Mistral from opik.integrations.mistral import track_mistral client Mistral(api_keyos.environ[MISTRAL_API_KEY]) # 显式传 key tracked_client track_mistral(client) # 原地 patch 并返回 resp tracked_client.chat.complete( modelmistral-large-latest, messages[{role: user, content: Hello!}], ) # 流式调用同样被追踪chunk 会被聚合为完整响应 for chunk in tracked_client.chat.stream( modelmistral-large-latest, messages[{role: user, content: Hi}], ): pass opik.flush_tracker()该调用链路产生的 span 树chat.complete→ spanchat_completion_createtypellmprovidermistraltags[mistral]usage 由LLMProvider.MISTRALAI专属格式解析chat.parse走同一原语得到单个chat_completion_createspan成本不重复计算流式调用得到chat_completion_streamspan。结语Opik 的 Python 集成体系用一套严格的骨架与纪律把接入一个新 LLM 框架从一次性的 hack 变成了可复制的工程流程四种机制模板按需选择、共享核心绝不重写、委托方法只 patch 原语、用量格式专属化、导入与版本守护到位、fake_backend 测试 CI 注册双保险。沿着本文给出的模板与 workflow.md 的八阶段流程即可为任意 Python LLM 框架产出与 OpenAI、Mistral、LangChain 同等质量的 Opik 集成。【免费下载链接】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),仅供参考
返回列表