AgentEvalTool/backend/agenteval/evaluation/rules/base.py
sinohqb a29f78ff4b
All checks were successful
CI / test (pull_request) Successful in 4m9s
feat(llm_score): 支持多维度独立评分
扩展 llm_score 规则,支持通过 dimensions 参数配置多个评分维度,
每个维度独立评分 0-10 分。

- RuleResult 新增 details 字段存储结构化多维度分数
- 向后兼容:原有 criteria 单维度模式继续有效
- 多维度模式下各维度并行调用 LLM,返回平均分和明细
- 新增 4 项单元测试

Closes #19
2026-08-25 14:17:49 +08:00

67 lines
1.8 KiB
Python

"""Base class for evaluation rules."""
from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Optional
from agenteval.models import Case, Turn
if TYPE_CHECKING:
from agenteval.model_gateway import ModelGateway
from agenteval.services.model_configs import ModelRuntimeConfig
@dataclass
class RuleResult:
"""Result of applying an evaluation rule."""
passed: bool
score: Optional[float] = None
reason: str = ""
details: Optional[dict[str, Any]] = None
class EvalRule(ABC):
"""Abstract evaluation rule. All implementations must be async."""
name: str = ""
def __init__(
self,
params: dict[str, Any],
model_config: "ModelRuntimeConfig | None" = None,
gateway: "ModelGateway | None" = None,
):
self.params = params
self.model_config = model_config
self.gateway = gateway
@abstractmethod
async def evaluate(self, case: Case, dialog: list[Turn]) -> RuleResult:
"""Evaluate the dialog against the case expectation."""
...
_RULE_REGISTRY: dict[str, type[EvalRule]] = {}
def register_rule(rule_cls: type[EvalRule]) -> type[EvalRule]:
_RULE_REGISTRY[rule_cls.name] = rule_cls
return rule_cls
def get_rule(
rule_type: str,
params: dict[str, Any],
model_config: "ModelRuntimeConfig | None" = None,
gateway: "ModelGateway | None" = None,
) -> EvalRule:
"""Instantiate a rule by type name."""
if rule_type not in _RULE_REGISTRY:
raise ValueError(f"unknown rule type: {rule_type}. Available: {list(_RULE_REGISTRY.keys())}")
return _RULE_REGISTRY[rule_type](params, model_config=model_config, gateway=gateway)
def list_rule_types() -> list[str]:
return list(_RULE_REGISTRY.keys())