Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/strands_evals/cli/commands/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def _run(args: argparse.Namespace) -> int:
experiment: Experiment = Experiment.from_file(args.experiment_file, custom_evaluators=custom_evaluators)

case_count = len(experiment.cases)
evaluator_names = [evaluator.get_type_name() for evaluator in experiment.evaluators]
evaluator_names = [evaluator.get_name() for evaluator in experiment.evaluators]
Comment thread
poshinchen marked this conversation as resolved.

fmt = resolve_format(args)
if fmt == "json":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.version = version
default_prompt = get_template(version).SYSTEM_PROMPT
self.system_prompt = system_prompt if system_prompt is not None else default_prompt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.version = version
default_prompt = get_template(version).SYSTEM_PROMPT
self.system_prompt = system_prompt if system_prompt is not None else default_prompt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.version = version
default_prompt = get_template(version).SYSTEM_PROMPT
self.system_prompt = system_prompt if system_prompt is not None else default_prompt
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/coherence_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str | None = None,
include_inputs: bool = True,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt or get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/conciseness_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str | None = None,
include_inputs: bool = True,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt or get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/correctness_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str | None = None,
reference_system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.reference_system_prompt = (
reference_system_prompt
Expand Down
13 changes: 10 additions & 3 deletions src/strands_evals/evaluators/deterministic/environment_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ def _find_state_by_name(states: list[EnvironmentState], name: str) -> Environmen


class StateEquals(Evaluator[InputT, OutputT]):
"""Checks if a named environment state matches an expected value."""
"""Checks if a named environment state matches an expected value.

The `name` arg doubles as the state key in `EnvironmentState` and the
instance-level evaluator name surfaced through `get_name()`, so two
`StateEquals(name="cart")` / `StateEquals(name="balance")` instances
are naturally distinguishable in `EvaluationReport.cases`.
"""

name: str # required, not Optional — narrows the base class annotation

def __init__(self, name: str, value: Any | None = None):
super().__init__()
self.name = name
super().__init__(name=name)
self.value = value

def evaluate(self, evaluation_case: EvaluationData[InputT, OutputT]) -> list[EvaluationOutput]:
Expand Down
12 changes: 6 additions & 6 deletions src/strands_evals/evaluators/deterministic/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
class Equals(Evaluator[InputT, OutputT]):
"""Checks if actual_output equals an expected value."""

def __init__(self, value: Any | None = None):
super().__init__()
def __init__(self, value: Any | None = None, name: str | None = None):
super().__init__(name=name)
self.value = value

def evaluate(self, evaluation_case: EvaluationData[InputT, OutputT]) -> list[EvaluationOutput]:
Expand All @@ -29,8 +29,8 @@ async def evaluate_async(self, evaluation_case: EvaluationData[InputT, OutputT])
class Contains(Evaluator[InputT, OutputT]):
"""Checks if actual_output contains a substring."""

def __init__(self, value: str, case_sensitive: bool = True):
super().__init__()
def __init__(self, value: str, case_sensitive: bool = True, name: str | None = None):
super().__init__(name=name)
self.value = value
self.case_sensitive = case_sensitive

Expand All @@ -56,8 +56,8 @@ async def evaluate_async(self, evaluation_case: EvaluationData[InputT, OutputT])
class StartsWith(Evaluator[InputT, OutputT]):
"""Checks if actual_output starts with a prefix."""

def __init__(self, value: str, case_sensitive: bool = True):
super().__init__()
def __init__(self, value: str, case_sensitive: bool = True, name: str | None = None):
super().__init__(name=name)
self.value = value
self.case_sensitive = case_sensitive

Expand Down
4 changes: 2 additions & 2 deletions src/strands_evals/evaluators/deterministic/trajectory.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
class ToolCalled(Evaluator[InputT, OutputT]):
"""Checks if a specific tool was called in the trajectory."""

def __init__(self, tool_name: str):
super().__init__()
def __init__(self, tool_name: str, name: str | None = None):
super().__init__(name=name)
self.tool_name = tool_name

def evaluate(self, evaluation_case: EvaluationData[InputT, OutputT]) -> list[EvaluationOutput]:
Expand Down
22 changes: 21 additions & 1 deletion src/strands_evals/evaluators/evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,22 @@ class Evaluator(Generic[InputT, OutputT]):
evaluation_level: EvaluationLevel | None = None
_trace_extractor: TraceExtractor | None = None

def __init__(self, trace_extractor: TraceExtractor | None = None):
def __init__(self, trace_extractor: TraceExtractor | None = None, name: str | None = None):
"""Initialize evaluator with optional custom trace extractor.

Args:
trace_extractor: Custom trace extractor. If None and evaluation_level is set,
a default TraceExtractor will be created.
name: Instance-level identifier used as the evaluator tag in
`EvaluationReport.cases[i]["evaluator"]` and as
`gen_ai.evaluation.name` on emitted spans/logs. When two
instances of the same class run in one experiment (e.g.,
`Contains(value="x")` and `Contains(value="y")`), distinct
names keep their results from colliding. Defaults to the
class name when unset.
"""
self.aggregator = self._default_aggregator
self.name = name
if trace_extractor:
self._trace_extractor = trace_extractor
elif self.evaluation_level:
Expand Down Expand Up @@ -264,6 +272,18 @@ def get_type_name(cls) -> str:
"""
return cls.__name__

def get_name(self) -> str:
"""Get the instance-level evaluator name, falling back to the class name.

Used for the per-row `evaluator` tag in `EvaluationReport` and the
`gen_ai.evaluation.name` OTel attribute. `get_type_name()` is still
used for class-keyed lookups such as `from_dict` registry resolution.

Returns:
str: The instance name if set, otherwise the class name.
"""
return self.name or self.get_type_name()

def to_dict(self) -> dict:
"""
Convert the evaluator into a dictionary.
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/faithfulness_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str | None = None,
assertion_system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.assertion_system_prompt = (
assertion_system_prompt
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/harmfulness_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/helpfulness_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str | None = None,
include_inputs: bool = True,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/interactions_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str = SYSTEM_PROMPT,
include_inputs: bool = True,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.rubric = rubric
self.interaction_description = interaction_description
self.model = model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def __init__(
system_prompt: str | None = None,
reference_suffix: str | None = None,
uses_environment_state: bool = False,
name: str | None = None,
):
super().__init__(
rubric=rubric if rubric is not None else CORRECTNESS_RUBRIC_V0,
Expand All @@ -32,4 +33,5 @@ def __init__(
system_prompt=system_prompt,
reference_suffix=reference_suffix,
uses_environment_state=uses_environment_state,
name=name,
)
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def __init__(
system_prompt: str | None = None,
reference_suffix: str | None = None,
uses_environment_state: bool = False,
name: str | None = None,
):
super().__init__(
rubric=rubric if rubric is not None else FAITHFULNESS_RUBRIC_V0,
Expand All @@ -31,4 +32,5 @@ def __init__(
system_prompt=system_prompt,
reference_suffix=reference_suffix,
uses_environment_state=uses_environment_state,
name=name,
)
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def __init__(
system_prompt: str | None = None,
reference_suffix: str | None = None,
uses_environment_state: bool = False,
name: str | None = None,
):
super().__init__(
rubric=rubric if rubric is not None else INSTRUCTION_FOLLOWING_RUBRIC_V0,
Expand All @@ -31,4 +32,5 @@ def __init__(
system_prompt=system_prompt,
reference_suffix=reference_suffix,
uses_environment_state=uses_environment_state,
name=name,
)
2 changes: 2 additions & 0 deletions src/strands_evals/evaluators/multimodal_output_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,15 @@ def __init__(
system_prompt: str | None = None,
reference_suffix: str | None = None,
uses_environment_state: bool = False,
name: str | None = None,
):
super().__init__(
rubric=rubric,
model=model,
system_prompt=system_prompt if system_prompt is not None else MLLM_JUDGE_SYSTEM_PROMPT,
include_inputs=include_inputs,
uses_environment_state=uses_environment_state,
name=name,
)
self.reference_suffix = reference_suffix if reference_suffix is not None else self.DEFAULT_REFERENCE_SUFFIX

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def __init__(
system_prompt: str | None = None,
reference_suffix: str | None = None,
uses_environment_state: bool = False,
name: str | None = None,
):
super().__init__(
rubric=rubric if rubric is not None else OVERALL_QUALITY_RUBRIC_V0,
Expand All @@ -42,4 +43,5 @@ def __init__(
system_prompt=system_prompt,
reference_suffix=reference_suffix if reference_suffix is not None else _OVERALL_QUALITY_REFERENCE_SUFFIX,
uses_environment_state=uses_environment_state,
name=name,
)
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/output_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ def __init__(
system_prompt: str = SYSTEM_PROMPT,
include_inputs: bool = True,
uses_environment_state: bool = False,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.rubric = rubric
self.model = model
self.include_inputs = include_inputs
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/refusal_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str | None = None,
include_inputs: bool = True,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt or get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/stereotyping_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ def __init__(
version: str = "v0",
model: Model | str | None = None,
system_prompt: str | None = None,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.system_prompt = system_prompt if system_prompt is not None else get_template(version).SYSTEM_PROMPT
self.version = version
self.model = model
Expand Down
3 changes: 2 additions & 1 deletion src/strands_evals/evaluators/trajectory_evaluator.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ def __init__(
model: Model | str | None = None,
system_prompt: str = SYSTEM_PROMPT,
include_inputs: bool = True,
name: str | None = None,
):
super().__init__()
super().__init__(name=name)
self.rubric = rubric
self.trajectory_description = trajectory_description
self.model = model
Expand Down
Loading
Loading