Opik Python SDK BaseMetric 完全解析:编写、追踪与调用自定义 LLM 评估指标
发布时间:2026/9/13 15:03:23来源:尧图网络
Opik Python SDK BaseMetric 完全解析编写、追踪与调用自定义 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本文围绕 Opik Python SDK 文档中的BaseMetric参考页展开讲清它是 Opik 评估体系中所有指标的抽象基类你将学会其构造参数name、track、project_name的精确语义、返回值契约ScoreResult的字段定义、如何继承实现一个可独立调用又可接入evaluate()流程的自定义指标以及从源码层面看清指标在评估引擎中从参数校验、评分到异常兜底的完整调用链。BaseMetric 在指标体系中的位置在 BaseMetric.rst 文档页中Opik 官方文档通过 Sphinx 的autoclass指令渲染opik.evaluation.metrics.BaseMetric类的完整文档字符串并标注了:members:与:inherited-members:——这意味着该类自身方法score、ascore与其继承自_opik._base_metric.BaseMetric的构造逻辑共同构成文档内容。从源码结构看BaseMetric是整个评估指标层sdks/python/src/opik/evaluation/metrics/的统一入口内置启发式指标Contains、Equals、IsJson、LevenshteinRatio、Rouge、Bleu等全部继承自它内置 LLM Judge 指标AnswerRelevance、Hallucination、ContextPrecision、ContextRecall、GEval、Moderation等同样继承自它用户编写自定义指标时官方推荐的方式就是继承BaseMetric并实现score方法。文档字符串base_metric.py给出的定义即所有指标的抽象基类。创建新指标时应当继承该类并实现抽象方法。两层类结构轻量 ABC 与 SDK 侧增强Opik 的BaseMetric实际上由两层组成理解这一点有助于理解参数默认行为与追踪行为的来源。第一层无依赖的轻量抽象基类_opik/_base_metric.py 定义了一个零重量版本其模块文档字符串明确写着Lightweight BaseMetric ABC with no heavy dependenciesclass BaseMetric(abc.ABC): def __init__( self, name: Optional[str] None, track: bool True, project_name: Optional[str] None, ) - None: self.name name if name is not None else self.__class__.__name__ self.track track self.project_name project_name abc.abstractmethod def score(self, *args: Any, **kwargs: Any) - Union[ScoreResult, List[ScoreResult]]: ... async def ascore(self, *args: Any, **kwargs: Any): import asyncio return await asyncio.to_thread(self.score, *args, **kwargs)这一层承载了三个关键设计name缺省回退未传name时使用类名作为指标显示名score是抽象方法子类必须实现签名接受任意位置/关键字参数返回单个ScoreResult或ScoreResult列表ascore默认实现通过asyncio.to_thread把阻塞式score放进工作线程执行避免阻塞调用方的事件循环源码注释说明仅当指标有真正的异步实现时才需要覆写该方法且import asyncio被刻意延迟到方法体内以降低该模块的导入时间。第二层带追踪能力的 SDK 子类base_metric.py 中的BaseMetric继承上述轻量类并在__init__中叠加了 SDK 行为def __init__( self, name: Optional[str] None, track: bool True, project_name: Optional[str] None, ) - None: _track_metric_creation(type(self)) super().__init__(namename, tracktrack, project_nameproject_name) config opik_config.OpikConfig() if not track and project_name is not None: raise ValueError(project_name can be set only when track is set to True) if track and config.check_for_known_misconfigurations() is False: track_decorator opik.track(nameself.name, project_nameproject_name) self.score track_decorator(self.score) self.ascore track_decorator(self.ascore)这段构造逻辑解释了三个构造参数的真实约束与行为正好对应文档字符串中Args部分的描述参数类型默认值语义与约束nameOptional[str]None指标显示名为None时回退为类名如MyCustomMetrictrackboolTrue是否将指标的评分行为追踪到 Opik。开启且配置检查通过时score/ascore会被opik.track装饰器包裹每次评分自动产生 spanproject_nameOptional[str]None当不存在父级 span/trace 可继承项目名时指定追踪结果归属的项目。仅当trackTrue时允许设置否则抛出ValueErrorbase_metric.py#L77-L78两点值得注意的实现细节追踪是有条件启用的只有当config.check_for_known_misconfigurations()判定当前 Opik 配置无已知误配置时score与ascore才会被opik.track(nameself.name, project_nameproject_name)包裹。也就是说追踪行为既取决于track参数也取决于全局配置是否健康。埋点统计构造时_track_metric_creation会上报metric_created事件但源码特意处理了一个防污染问题——用户自定义类可以任意命名因此_is_opik_metric会回查类所声称的模块只把 Opik 官方自带指标的名字上报用户自定义指标统一记为custom。返回值契约ScoreResultscore方法必须返回ScoreResult或ScoreResult列表。ScoreResult是定义于 _opik/_score_result.py 的 dataclass经 score_result.py 对外导出字段如下字段类型默认值说明namestr必填产出该结果的指标名通常传入self.name用于在 Opik 界面中区分多个指标的评分列valuefloat必填数值化评分如 0.0 / 1.0 或 0–1 之间的连续分值reasonOptional[str]None人类可读的评分理由LLM Judge 类指标常在此输出判分依据category_nameOptional[str]None可选的类别标签metadataOptional[Dict[str, Any]]None附加元数据评估引擎在评分失败时会在此写入error_info结构化错误信息scoring_failedboolFalse标记该次评分未能正常完成引擎捕获score抛出的异常时置为True这个契约是指标可被evaluate()统一消费的基础无论指标是纯启发式规则还是调用大模型判分引擎只认ScoreResult结构。编写自定义指标完整可运行示例文档字符串内置了一个最小示例base_metric.py#L45-L59这里将其扩展为参数完整、可直接复制运行的版本并补齐注释from typing import Any from opik.evaluation.metrics import base_metric, score_result class MyCustomMetric(base_metric.BaseMetric): 自定义指标例如校验输出是否以特定标记开头。 def __init__( self, name: str my_custom_metric, track: bool True, project_name: str | None None, ): # 必须调用 super().__init__否则 name/track 等属性与 # track 包装逻辑均不会生效 super().__init__(namename, tracktrack, project_nameproject_name) def score(self, input: str, output: str, **ignored_kwargs: Any): # 你的评分逻辑参数名由你自行定义 # 引擎会按数据集项/任务输出的键名把值映射进来 passed output.startswith([OK]) return score_result.ScoreResult( value1.0 if passed else 0.0, nameself.name, # 与指标名保持一致 reasonOutput starts with [OK] if passed else Missing [OK] prefix, ) metric MyCustomMetric() result metric.score(inputq, output[OK] done) print(result.value, result.reason)编写时遵循的要点均来自源码与内置指标的通行做法构造函数务必以super().__init__(name..., track...)收尾内置的 Contains 与 Equals 均严格遵循此模式先透传基类参数再保存自己的私有配置。score的签名自由但要有兜底内置指标普遍使用**ignored_kwargs吸收引擎可能注入但本指标不关心的参数避免意外的TypeError。入参缺失要显式报错Contains在拿不到参考字符串时抛出ValueError并给出明确指引Either passreferencetoscore()or set a default reference when creating the metricEquals则抛出MetricComputationError说明缺少哪个参数。返回单个结果或多个结果均可引擎侧_compute_metric_scores会判断返回值是否为 list 并分别累加metrics_evaluator.py#L326-L329因此一个指标一次产出多个维度的评分是被支持的。独立调用score 与 ascore由于score是普通公开方法文档字符串称之为Public method that can be called independently自定义指标可以在不经过evaluate()的情况下直接用于脚本或单元测试——如上面示例中对metric.score(...)的裸调用。ascore则是其异步变体默认实现把阻塞的score调度到线程池base_metric.py#L93-L103在异步评估场景如并发评分、evaluate内部异步路径中不会卡死事件循环如果你的指标本身要发起异步 LLM 调用则应覆写ascore提供真正的异步实现。内置指标作为参考模板学习自定义指标最快的方式是读一个最简单的内置实现。Contains 是一个完整的可复制模板class Contains(base_metric.BaseMetric): def __init__( self, case_sensitive: bool False, reference: Optional[str] None, name: str contains_metric, track: bool True, project_name: Optional[str] None, ): super().__init__(namename, tracktrack, project_nameproject_name) self._case_sensitive case_sensitive self._default_reference reference def score(self, output: str, reference: Optional[str] None, **ignored_kwargs: Any): ref reference if reference is not None else self._default_reference if ref is None: raise ValueError(No reference string provided. ...) if ref : raise ValueError(Invalid reference string provided. ...) value output if self._case_sensitive else output.lower() ref ref if self._case_sensitive else ref.lower() if ref in value: return score_result.ScoreResult(value1.0, nameself.name) return score_result.ScoreResult(value0.0, nameself.name)它的文档字符串还给出了可运行的 doctest 风格示例Contains(referenceworld).score(Hello, World!)返回value1.0在score时覆盖 reference 为there则返回0.0。这展示了自定义指标的一个良好实践——构造期默认值 评分期可覆盖的两段式参数设计。Equals 则演示了另一种细节输入先经str()归一化再做比较以便兼容数字等非字符串类型同时对None输入抛出带上下文的MetricComputationError。在 evaluate() 中的调用链从 MetricsEvaluator 看引擎如何消费指标自定义指标被传入opik.evaluate(metrics[...])后会进入 MetricsEvaluator 的统一处理流程。理解这条链路能解释自定义指标在什么情况下会被自动追踪、如何接收参数、失败时如何兜底。参数准备与校验每次评分前引擎会执行_prepare_score_arguments通过arguments_validator.validate_score_arguments校验指标参数是否齐备通过arguments_helpers.select_score_arguments按score的函数签名挑选出实际需要的位置参数与关键字参数——这就是自定义指标只需声明自己关心的参数即可工作的原因数据集中与任务输出中的键经scoring_key_mapping映射后引擎只把签名匹配的参数传给score其余通过**ignored_kwargs或过滤机制消化对签名中显式声明或接受**kwargs的指标额外注入trace_tool_context供 agentic judge 使用。regular 与 task span 两类指标的分流引擎会按签名特征把指标分为两类split_into_regular_and_task_span_metricsregular metricsscore签名中不含task_span参数按数据集项内容与任务输出评分——绝大多数自定义指标属于此类task span metricsscore签名中声明了task_span参数引擎会额外注入任务执行产生的 span 模型含 token、延迟等 LLM 调用元数据用于对模型行为本身做评分。若你希望自定义指标基于 token 用量、延迟等元数据打分只需在score签名中加入task_span参数无需其他注册动作——分流完全由签名检查驱动。异常兜底与评分失败标记_compute_metric_scores对每个指标的score调用都包在 try/except 中score抛出任何异常时引擎不会中断整批评估在默认错误容忍度下而是构造一个失败评分_build_failed_score_result生成value0.0、reason异常消息、scoring_failedTrue的ScoreResult并把结构化错误信息写入metadata[error_info]若识别为大模型服务商限流错误还会输出针对性的错误提示日志。这意味着自定义指标的score抛异常在工程上是安全的它会被记录为失败评分而不是让整个evaluate()崩溃前提是错误容忍度允许可通过ErrorTolerance调节ALL_SCORING_ERRORS级别下连参数缺失类错误也会被降级为失败评分而非抛出。小结一份自定义指标检查清单继承opik.evaluation.metrics.base_metric.BaseMetric构造函数透传name/track/project_name给super().__init__实现score(self, ..., **ignored_kwargs)参数名与数据集项/任务输出的键名或scoring_key_mapping映射后的名字对齐需要 token/延迟等元数据时在签名中声明task_span参数返回ScoreResult(value..., nameself.name, reason...)多指标维度时返回列表有真正的异步逻辑再覆写ascore否则默认实现已保证不阻塞事件循环需要把评分结果归属到特定项目且没有父级 span/trace 时设置project_name注意此时track必须为True。参考文件索引文档页 BaseMetric.rst核心实现 base_metric.py、_base_metric.py返回值定义 _score_result.py参考实现 contains.py、equals.py评估引擎 metrics_evaluator.py。【免费下载链接】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),仅供参考
网站建设高端定制企业官网