Skip to content
This repository was archived by the owner on Jul 17, 2026. It is now read-only.

Commit 7816680

Browse files
feat: expose LLM evaluator row statuses
1 parent 9da306b commit 7816680

4 files changed

Lines changed: 35 additions & 3 deletions

File tree

haystack/components/evaluators/llm_evaluator.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def validate_init_parameters(
175175
)
176176
raise ValueError(msg)
177177

178-
@component.output_types(results=list[dict[str, Any]])
178+
@component.output_types(results=list[dict[str, Any]], evaluation_statuses=list[str])
179179
def run(self, **inputs: Any) -> dict[str, Any]:
180180
"""
181181
Run the LLM evaluator.
@@ -204,6 +204,7 @@ def run(self, **inputs: Any) -> dict[str, Any]:
204204
list_of_input_names_to_values = [dict(zip(input_names, v, strict=True)) for v in values]
205205

206206
results: list[dict[str, Any] | None] = []
207+
evaluation_statuses: list[str] = []
207208
metadata = []
208209
errors = 0
209210
for input_names_to_values in tqdm(list_of_input_names_to_values, disable=not self.progress_bar):
@@ -216,6 +217,7 @@ def run(self, **inputs: Any) -> dict[str, Any]:
216217
raise ValueError(f"Error while generating response for prompt: {prompt}. Error: {e}") from e
217218
logger.warning("Error while generating response for prompt: {prompt}. Error: {e}", prompt=prompt, e=e)
218219
results.append(None)
220+
evaluation_statuses.append("error")
219221
errors += 1
220222
continue
221223

@@ -224,9 +226,11 @@ def run(self, **inputs: Any) -> dict[str, Any]:
224226
)
225227
if parsed_result is None:
226228
results.append(None)
229+
evaluation_statuses.append("error")
227230
errors += 1
228231
else:
229232
results.append(parsed_result)
233+
evaluation_statuses.append("evaluated")
230234

231235
if result["replies"][0].meta:
232236
metadata.append(result["replies"][0].meta)
@@ -238,7 +242,7 @@ def run(self, **inputs: Any) -> dict[str, Any]:
238242
len=len(list_of_input_names_to_values),
239243
)
240244

241-
return {"results": results, "meta": metadata or None}
245+
return {"results": results, "meta": metadata or None, "evaluation_statuses": evaluation_statuses}
242246

243247
def prepare_template(self) -> str:
244248
"""

test/components/evaluators/test_context_relevance_evaluator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ def chat_generator_run(self, *args, **kwargs):
169169
"score": 0.5,
170170
"meta": None,
171171
"individual_scores": [1, 0],
172+
"evaluation_statuses": ["evaluated", "evaluated"],
172173
}
173174

174175
def test_run_no_statements_extracted(self, monkeypatch):
@@ -198,6 +199,7 @@ def chat_generator_run(self, *args, **kwargs):
198199
"score": 0.5,
199200
"meta": None,
200201
"individual_scores": [1, 0],
202+
"evaluation_statuses": ["evaluated", "evaluated"],
201203
}
202204

203205
def test_run_missing_parameters(self, monkeypatch):
@@ -237,6 +239,7 @@ def chat_generator_run(self, *args, **kwargs):
237239
assert results["results"][0] == {"relevant_statements": ["c", "d"], "score": 1}
238240
assert results["results"][1]["relevant_statements"] == []
239241
assert math.isnan(results["results"][1]["score"])
242+
assert results["evaluation_statuses"] == ["evaluated", "error"]
240243

241244
@pytest.mark.skipif(
242245
not os.environ.get("OPENAI_API_KEY", None),

test/components/evaluators/test_faithfulness_evaluator.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ def chat_generator_run(self, *args, **kwargs):
207207
],
208208
"score": 0.75,
209209
"meta": None,
210+
"evaluation_statuses": ["evaluated", "evaluated"],
210211
}
211212

212213
def test_run_no_statements_extracted(self, monkeypatch):
@@ -245,6 +246,7 @@ def chat_generator_run(self, *args, **kwargs):
245246
],
246247
"score": 0.25,
247248
"meta": None,
249+
"evaluation_statuses": ["evaluated", "evaluated"],
248250
}
249251

250252
def test_run_missing_parameters(self, monkeypatch):
@@ -294,6 +296,7 @@ def chat_generator_run(self, *args, **kwargs):
294296
assert results["results"][1]["statements"] == []
295297
assert results["results"][1]["statement_scores"] == []
296298
assert math.isnan(results["results"][1]["score"])
299+
assert results["evaluation_statuses"] == ["evaluated", "error"]
297300

298301
@pytest.mark.skipif(
299302
not os.environ.get("OPENAI_API_KEY", None),

test/components/evaluators/test_llm_evaluator.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ def chat_generator_run(self, *args, **kwargs):
332332
monkeypatch.setattr("haystack.components.evaluators.llm_evaluator.OpenAIChatGenerator.run", chat_generator_run)
333333

334334
results = component.run(questions=["What is the capital of Germany?"], predicted_answers=["Berlin"])
335-
assert results == {"results": [{"score": 0.5}], "meta": None}
335+
assert results == {"results": [{"score": 0.5}], "meta": None, "evaluation_statuses": ["evaluated"]}
336336

337337
def test_prepare_template(self, monkeypatch):
338338
monkeypatch.setenv("OPENAI_API_KEY", "test-api-key")
@@ -433,6 +433,28 @@ def chat_generator_run(self, *args, **kwargs):
433433

434434
result = component.run(predicted_answers=["answer"])
435435
assert result["results"] == [None]
436+
assert result["evaluation_statuses"] == ["error"]
437+
438+
def test_run_returns_error_status_raise_on_failure_false(self, monkeypatch):
439+
monkeypatch.setenv("OPENAI_API_KEY", "test-api-key")
440+
component = LLMEvaluator(
441+
instructions="test-instruction",
442+
inputs=[("predicted_answers", list[str])],
443+
outputs=["score"],
444+
examples=[
445+
{"inputs": {"predicted_answers": "Football is the most popular sport."}, "outputs": {"score": 0}}
446+
],
447+
raise_on_failure=False,
448+
)
449+
450+
def chat_generator_run(self, *args, **kwargs):
451+
raise Exception("OpenAI API request failed.")
452+
453+
monkeypatch.setattr("haystack.components.evaluators.llm_evaluator.OpenAIChatGenerator.run", chat_generator_run)
454+
455+
result = component.run(predicted_answers=["answer"])
456+
assert result["results"] == [None]
457+
assert result["evaluation_statuses"] == ["error"]
436458

437459
def test_output_invalid_json_raise_on_failure_true(self, monkeypatch):
438460
monkeypatch.setenv("OPENAI_API_KEY", "test-api-key")

0 commit comments

Comments
 (0)