From 325fdf2247241cea377ee36e45055bf0b3a2a7fd Mon Sep 17 00:00:00 2001 From: usegitdivyansh Date: Fri, 21 Aug 2026 18:52:34 +0530 Subject: [PATCH] fix(evals): StepEfficiency negative score on redundant calls within a step Redundancy was counted per tool call but normalized by step count, so a single step with multiple redundant calls could push redundancy_ratio below 0 and produce a negative score, out of the documented 0 to 1 range. Divide by total tool calls instead, matching the failure calculation in the same method. The per-call denominator keeps the ratio bounded by construction, so no clamp is needed. Adds a test covering multiple redundant calls within a single step. Fixes #60 --- python/fi/evals/metrics/agents/metrics.py | 4 ++-- python/tests/sdk/test_agents.py | 25 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/python/fi/evals/metrics/agents/metrics.py b/python/fi/evals/metrics/agents/metrics.py index a90b008b..14357e02 100644 --- a/python/fi/evals/metrics/agents/metrics.py +++ b/python/fi/evals/metrics/agents/metrics.py @@ -249,7 +249,8 @@ def compute_one(self, inputs: AgentTrajectoryInput) -> Dict[str, Any]: else: seen_signatures.add(call_sig) - redundancy_ratio = 1.0 - (redundant_count / total_steps) if total_steps > 0 else 1.0 + total_calls = sum(len(step.tool_calls) for step in inputs.trajectory) + redundancy_ratio = 1.0 - (redundant_count / total_calls) if total_calls > 0 else 1.0 redundancy_score = redundancy_ratio * self.redundancy_weight details["redundant_steps"] = redundant_count @@ -259,7 +260,6 @@ def compute_one(self, inputs: AgentTrajectoryInput) -> Dict[str, Any]: for tc in step.tool_calls if not tc.success ) - total_calls = sum(len(step.tool_calls) for step in inputs.trajectory) failure_ratio = 1.0 - (failed_calls / total_calls) if total_calls > 0 else 1.0 failure_score = failure_ratio * self.failure_weight details["failed_calls"] = failed_calls diff --git a/python/tests/sdk/test_agents.py b/python/tests/sdk/test_agents.py index dfb17ceb..992d2502 100644 --- a/python/tests/sdk/test_agents.py +++ b/python/tests/sdk/test_agents.py @@ -164,6 +164,31 @@ def test_redundant_steps(self): result = metric.compute_one(input_data) assert result["details"]["redundant_steps"] >= 3 + def test_redundant_calls_within_single_step(self): + """Multiple redundant calls in one step must not push the score below 0.""" + metric = StepEfficiency() + step = AgentStep( + step_number=1, + thought="Repeating the same call", + tool_calls=[ + ToolCall( + name="search", + arguments={"query": "test"}, + result="result", + success=True, + ) + for _ in range(5) + ], + is_final=True, + ) + input_data = AgentTrajectoryInput( + trajectory=[step], + task=TaskDefinition(description="Search for something") + ) + result = metric.compute_one(input_data) + assert 0.0 <= result["output"] <= 1.0 + assert result["details"]["redundant_steps"] == 4 + def test_failed_tool_calls(self): """Test trajectory with failed tool calls.""" metric = StepEfficiency()