agento11y-deepeval 0.18.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ SPDX-License-Identifier: Apache-2.0
2
+
3
+ See /LICENSE at repository root for full license text.
@@ -0,0 +1,213 @@
1
+ Metadata-Version: 2.4
2
+ Name: agento11y-deepeval
3
+ Version: 0.18.0
4
+ Summary: DeepEval experiment publishing for the Grafana Agent Observability Python SDK
5
+ License: SPDX-License-Identifier: Apache-2.0
6
+
7
+ See /LICENSE at repository root for full license text.
8
+
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: agento11y>=0.18.0
13
+ Requires-Dist: deepeval<5.0.0,>=4.2.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: pytest>=8.2.0; extra == "dev"
16
+ Dynamic: license-file
17
+
18
+ # DeepEval integration
19
+
20
+ `agento11y-deepeval` supports live target execution with native DeepEval metrics,
21
+ and publication of completed native evaluation results. Both use the existing
22
+ Agent Observability experiment lifecycle.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install agento11y agento11y-deepeval
28
+ ```
29
+
30
+ Set `AGENTO11Y_ENDPOINT`, `AGENTO11Y_AUTH_TOKEN`, and, when required by your
31
+ stack, `AGENTO11Y_AUTH_TENANT_ID`. Set `AGENTO11Y_GRAFANA_URL` for experiment
32
+ deep links.
33
+
34
+ ## Live runner
35
+
36
+ `run_deepeval` registers the planned count before invoking the target and exports
37
+ each case as it completes. Configure your OTel TracerProvider/exporter once;
38
+ the runner activates suite and trial spans around your instrumented target.
39
+
40
+ ```python
41
+ from agento11y_deepeval import run_deepeval
42
+ from deepeval.metrics import ExactMatchMetric
43
+ from deepeval.test_case import LLMTestCase
44
+
45
+ run = run_deepeval(
46
+ [LLMTestCase(input="2+2?", actual_output="", expected_output="4")],
47
+ lambda case, trial: instrumented_agent(case.input),
48
+ [ExactMatchMetric()],
49
+ experiment_name="Live regression",
50
+ )
51
+ print(run.url)
52
+ ```
53
+
54
+ The target receives the trial for conversation binding when needed. Execution
55
+ is sequential, with a fresh copy of each metric per case. Target and metric
56
+ exceptions mark the trial errored and retain successful siblings. Target duration
57
+ excludes grading. `record_io=False` avoids extra anchor generations by default.
58
+ Native batch scheduling, caching, and pytest can continue using the
59
+ completed-result importers below.
60
+
61
+ For `ConversationalTestCase`, the same target receives a private copy of the
62
+ case and must return the completed ordered `Sequence[Turn]`. The single-turn
63
+ `target(case, trial) -> str` contract is unchanged. Returning turns instead of
64
+ mutating the case keeps caller-owned cases reusable:
65
+
66
+ ```python
67
+ from deepeval.metrics import ConversationCompletenessMetric
68
+ from deepeval.test_case import ConversationalTestCase, Turn
69
+
70
+ case = ConversationalTestCase(turns=[Turn(role="user", content="Can I return this?")])
71
+
72
+ def chat(case, trial):
73
+ return [*case.turns, Turn(role="assistant", content="Yes, within 30 days.")]
74
+
75
+ run_deepeval(
76
+ [case],
77
+ chat,
78
+ [ConversationCompletenessMetric()],
79
+ experiment_name="Live support conversations",
80
+ record_io=True,
81
+ )
82
+ ```
83
+
84
+ With `record_io=True`, each assistant turn is exported as one generation using
85
+ all preceding turns as structured input. Assistant generations share one stable
86
+ conversation id and form a parent chain. A final user turn is retained as a
87
+ chained input-only generation awaiting a response. If the target already emitted
88
+ its own telemetry, bind that conversation on `trial` and leave `record_io=False`.
89
+
90
+ ## Evaluate existing outputs and publish afterward
91
+
92
+ `evaluate_with_agento11y` below waits for the whole native batch before creating
93
+ the Grafana experiment. Use `run_deepeval` for live target execution/progress.
94
+
95
+ ```python
96
+ from deepeval.metrics import AnswerRelevancyMetric, FaithfulnessMetric
97
+ from deepeval.test_case import LLMTestCase
98
+ from agento11y_deepeval import evaluate_with_agento11y
99
+
100
+ test_cases = [
101
+ LLMTestCase(
102
+ name="refund-policy",
103
+ input="Can I return an opened item?",
104
+ actual_output=run_agent("Can I return an opened item?"),
105
+ expected_output="Opened items can be returned within 30 days.",
106
+ retrieval_context=["Opened products may be returned within 30 days."],
107
+ metadata={"agento11y.test_case_id": "refund-policy"},
108
+ )
109
+ ]
110
+
111
+ run = evaluate_with_agento11y(
112
+ test_cases,
113
+ [AnswerRelevancyMetric(), FaithfulnessMetric()],
114
+ experiment_name="Checkout agent regression",
115
+ primary_metric="Answer Relevancy",
116
+ suite_id="checkout-regression",
117
+ suite_version="v1",
118
+ )
119
+ print(run.published.url)
120
+ ```
121
+
122
+ Each DeepEval test result becomes one trial. The metric named by
123
+ `primary_metric` is the one `primary_verdict`; every other metric is a
124
+ `diagnostic`. If all results contain exactly one metric name, the adapter selects
125
+ it automatically. With multiple metrics, the explicit selection is required and
126
+ validated before the experiment is written.
127
+
128
+ Conversational results preserve their ordered public `Turn` fields in the test
129
+ case snapshot. With `record_io=True`, each assistant response becomes a separate
130
+ generation; preceding user and assistant turns remain structured messages, not a
131
+ flattened transcript. Whole-conversation metric scores attach to the typed trial
132
+ and conversation, not to the final assistant generation.
133
+
134
+ ```python
135
+ from deepeval import evaluate
136
+ from deepeval.metrics import ConversationCompletenessMetric
137
+ from deepeval.test_case import ConversationalTestCase, Turn
138
+
139
+ conversation = ConversationalTestCase(
140
+ turns=[
141
+ Turn(role="user", content="Can I return an opened item?"),
142
+ Turn(role="assistant", content="Yes, within 30 days."),
143
+ ],
144
+ expected_outcome="The return policy is explained.",
145
+ )
146
+ result = evaluate(test_cases=[conversation], metrics=[ConversationCompletenessMetric()])
147
+ publish_deepeval_results(result, experiment_name="Support conversations")
148
+ ```
149
+
150
+ Only public DeepEval `user` and `assistant` turns with non-blank string content are
151
+ accepted. Malformed turns fail validation before the remote experiment is
152
+ created. Turn order, user id, retrieval context, tool/MCP call details, audio,
153
+ latency, interruption state, comments, and custom metadata are retained in the
154
+ case snapshot and generation metadata. Text roles/content and user id also map
155
+ to their native Agent Observability fields.
156
+
157
+ Metric errors make the trial operationally failed and remain unrated; valid
158
+ sibling results are still published. Native duration can be supplied as
159
+ `metadata={"agento11y.duration_ms": 12345}`. Missing duration remains unknown.
160
+
161
+ Metric scores, pass/fail values, reasons, thresholds, model identity, evaluator
162
+ cost, and evaluator token counts are preserved. Evaluator cost and tokens remain
163
+ score metadata rather than candidate trial usage, because they describe the
164
+ grader rather than the agent under test.
165
+
166
+ ## Publish a result you already evaluated
167
+
168
+ ```python
169
+ from deepeval import evaluate
170
+ from agento11y_deepeval import publish_deepeval_results
171
+
172
+ result = evaluate(test_cases=test_cases, metrics=metrics)
173
+ published = publish_deepeval_results(
174
+ result,
175
+ experiment_name="Existing DeepEval run",
176
+ primary_metric="Answer Relevancy",
177
+ )
178
+ ```
179
+
180
+ ## Generation and conversation correlation
181
+
182
+ The adapter records each single-turn result as one anchor generation by default;
183
+ conversational results produce one generation per assistant turn. If the
184
+ evaluated target already emits Agent Observability telemetry, use that telemetry
185
+ instead:
186
+
187
+ ```python
188
+ published = publish_deepeval_results(
189
+ result,
190
+ experiment_name="Instrumented target",
191
+ primary_metric="Answer Relevancy",
192
+ record_io=False,
193
+ resolve_conversation_id=lambda item: item.metadata["conversation_id"],
194
+ resolve_generation_id=lambda item: item.metadata["generation_id"],
195
+ )
196
+ ```
197
+
198
+ Without resolver functions, metadata keys `agento11y.conversation_id`,
199
+ `agento11y.generation_id`, and `agento11y.trace_id` are recognized. A stable case
200
+ id can be supplied as `agento11y.test_case_id`. For conversational results, a
201
+ resolved conversation id suppresses generation export even when `record_io=True`;
202
+ the optional generation id is not attached to whole-conversation scores.
203
+
204
+ To publish browsable cases, pass `test_suites_client` and explicitly choose
205
+ `suite_publication_policy="subset"` to retain remote-only cases or `"replace"`
206
+ to prune them. Trial snapshots use the canonical server-returned cases and
207
+ record digests when sanitization changed the executed case.
208
+
209
+ This adapter does not create or invoke Agent Observability stored evaluators.
210
+ DeepEval runs metrics locally (including model-backed metrics) and the adapter
211
+ publishes their scores.
212
+
213
+ See the [runnable deterministic example](../../examples/experiments/deepeval/README.md).
@@ -0,0 +1,196 @@
1
+ # DeepEval integration
2
+
3
+ `agento11y-deepeval` supports live target execution with native DeepEval metrics,
4
+ and publication of completed native evaluation results. Both use the existing
5
+ Agent Observability experiment lifecycle.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pip install agento11y agento11y-deepeval
11
+ ```
12
+
13
+ Set `AGENTO11Y_ENDPOINT`, `AGENTO11Y_AUTH_TOKEN`, and, when required by your
14
+ stack, `AGENTO11Y_AUTH_TENANT_ID`. Set `AGENTO11Y_GRAFANA_URL` for experiment
15
+ deep links.
16
+
17
+ ## Live runner
18
+
19
+ `run_deepeval` registers the planned count before invoking the target and exports
20
+ each case as it completes. Configure your OTel TracerProvider/exporter once;
21
+ the runner activates suite and trial spans around your instrumented target.
22
+
23
+ ```python
24
+ from agento11y_deepeval import run_deepeval
25
+ from deepeval.metrics import ExactMatchMetric
26
+ from deepeval.test_case import LLMTestCase
27
+
28
+ run = run_deepeval(
29
+ [LLMTestCase(input="2+2?", actual_output="", expected_output="4")],
30
+ lambda case, trial: instrumented_agent(case.input),
31
+ [ExactMatchMetric()],
32
+ experiment_name="Live regression",
33
+ )
34
+ print(run.url)
35
+ ```
36
+
37
+ The target receives the trial for conversation binding when needed. Execution
38
+ is sequential, with a fresh copy of each metric per case. Target and metric
39
+ exceptions mark the trial errored and retain successful siblings. Target duration
40
+ excludes grading. `record_io=False` avoids extra anchor generations by default.
41
+ Native batch scheduling, caching, and pytest can continue using the
42
+ completed-result importers below.
43
+
44
+ For `ConversationalTestCase`, the same target receives a private copy of the
45
+ case and must return the completed ordered `Sequence[Turn]`. The single-turn
46
+ `target(case, trial) -> str` contract is unchanged. Returning turns instead of
47
+ mutating the case keeps caller-owned cases reusable:
48
+
49
+ ```python
50
+ from deepeval.metrics import ConversationCompletenessMetric
51
+ from deepeval.test_case import ConversationalTestCase, Turn
52
+
53
+ case = ConversationalTestCase(turns=[Turn(role="user", content="Can I return this?")])
54
+
55
+ def chat(case, trial):
56
+ return [*case.turns, Turn(role="assistant", content="Yes, within 30 days.")]
57
+
58
+ run_deepeval(
59
+ [case],
60
+ chat,
61
+ [ConversationCompletenessMetric()],
62
+ experiment_name="Live support conversations",
63
+ record_io=True,
64
+ )
65
+ ```
66
+
67
+ With `record_io=True`, each assistant turn is exported as one generation using
68
+ all preceding turns as structured input. Assistant generations share one stable
69
+ conversation id and form a parent chain. A final user turn is retained as a
70
+ chained input-only generation awaiting a response. If the target already emitted
71
+ its own telemetry, bind that conversation on `trial` and leave `record_io=False`.
72
+
73
+ ## Evaluate existing outputs and publish afterward
74
+
75
+ `evaluate_with_agento11y` below waits for the whole native batch before creating
76
+ the Grafana experiment. Use `run_deepeval` for live target execution/progress.
77
+
78
+ ```python
79
+ from deepeval.metrics import AnswerRelevancyMetric, FaithfulnessMetric
80
+ from deepeval.test_case import LLMTestCase
81
+ from agento11y_deepeval import evaluate_with_agento11y
82
+
83
+ test_cases = [
84
+ LLMTestCase(
85
+ name="refund-policy",
86
+ input="Can I return an opened item?",
87
+ actual_output=run_agent("Can I return an opened item?"),
88
+ expected_output="Opened items can be returned within 30 days.",
89
+ retrieval_context=["Opened products may be returned within 30 days."],
90
+ metadata={"agento11y.test_case_id": "refund-policy"},
91
+ )
92
+ ]
93
+
94
+ run = evaluate_with_agento11y(
95
+ test_cases,
96
+ [AnswerRelevancyMetric(), FaithfulnessMetric()],
97
+ experiment_name="Checkout agent regression",
98
+ primary_metric="Answer Relevancy",
99
+ suite_id="checkout-regression",
100
+ suite_version="v1",
101
+ )
102
+ print(run.published.url)
103
+ ```
104
+
105
+ Each DeepEval test result becomes one trial. The metric named by
106
+ `primary_metric` is the one `primary_verdict`; every other metric is a
107
+ `diagnostic`. If all results contain exactly one metric name, the adapter selects
108
+ it automatically. With multiple metrics, the explicit selection is required and
109
+ validated before the experiment is written.
110
+
111
+ Conversational results preserve their ordered public `Turn` fields in the test
112
+ case snapshot. With `record_io=True`, each assistant response becomes a separate
113
+ generation; preceding user and assistant turns remain structured messages, not a
114
+ flattened transcript. Whole-conversation metric scores attach to the typed trial
115
+ and conversation, not to the final assistant generation.
116
+
117
+ ```python
118
+ from deepeval import evaluate
119
+ from deepeval.metrics import ConversationCompletenessMetric
120
+ from deepeval.test_case import ConversationalTestCase, Turn
121
+
122
+ conversation = ConversationalTestCase(
123
+ turns=[
124
+ Turn(role="user", content="Can I return an opened item?"),
125
+ Turn(role="assistant", content="Yes, within 30 days."),
126
+ ],
127
+ expected_outcome="The return policy is explained.",
128
+ )
129
+ result = evaluate(test_cases=[conversation], metrics=[ConversationCompletenessMetric()])
130
+ publish_deepeval_results(result, experiment_name="Support conversations")
131
+ ```
132
+
133
+ Only public DeepEval `user` and `assistant` turns with non-blank string content are
134
+ accepted. Malformed turns fail validation before the remote experiment is
135
+ created. Turn order, user id, retrieval context, tool/MCP call details, audio,
136
+ latency, interruption state, comments, and custom metadata are retained in the
137
+ case snapshot and generation metadata. Text roles/content and user id also map
138
+ to their native Agent Observability fields.
139
+
140
+ Metric errors make the trial operationally failed and remain unrated; valid
141
+ sibling results are still published. Native duration can be supplied as
142
+ `metadata={"agento11y.duration_ms": 12345}`. Missing duration remains unknown.
143
+
144
+ Metric scores, pass/fail values, reasons, thresholds, model identity, evaluator
145
+ cost, and evaluator token counts are preserved. Evaluator cost and tokens remain
146
+ score metadata rather than candidate trial usage, because they describe the
147
+ grader rather than the agent under test.
148
+
149
+ ## Publish a result you already evaluated
150
+
151
+ ```python
152
+ from deepeval import evaluate
153
+ from agento11y_deepeval import publish_deepeval_results
154
+
155
+ result = evaluate(test_cases=test_cases, metrics=metrics)
156
+ published = publish_deepeval_results(
157
+ result,
158
+ experiment_name="Existing DeepEval run",
159
+ primary_metric="Answer Relevancy",
160
+ )
161
+ ```
162
+
163
+ ## Generation and conversation correlation
164
+
165
+ The adapter records each single-turn result as one anchor generation by default;
166
+ conversational results produce one generation per assistant turn. If the
167
+ evaluated target already emits Agent Observability telemetry, use that telemetry
168
+ instead:
169
+
170
+ ```python
171
+ published = publish_deepeval_results(
172
+ result,
173
+ experiment_name="Instrumented target",
174
+ primary_metric="Answer Relevancy",
175
+ record_io=False,
176
+ resolve_conversation_id=lambda item: item.metadata["conversation_id"],
177
+ resolve_generation_id=lambda item: item.metadata["generation_id"],
178
+ )
179
+ ```
180
+
181
+ Without resolver functions, metadata keys `agento11y.conversation_id`,
182
+ `agento11y.generation_id`, and `agento11y.trace_id` are recognized. A stable case
183
+ id can be supplied as `agento11y.test_case_id`. For conversational results, a
184
+ resolved conversation id suppresses generation export even when `record_io=True`;
185
+ the optional generation id is not attached to whole-conversation scores.
186
+
187
+ To publish browsable cases, pass `test_suites_client` and explicitly choose
188
+ `suite_publication_policy="subset"` to retain remote-only cases or `"replace"`
189
+ to prune them. Trial snapshots use the canonical server-returned cases and
190
+ record digests when sanitization changed the executed case.
191
+
192
+ This adapter does not create or invoke Agent Observability stored evaluators.
193
+ DeepEval runs metrics locally (including model-backed metrics) and the adapter
194
+ publishes their scores.
195
+
196
+ See the [runnable deterministic example](../../examples/experiments/deepeval/README.md).
@@ -0,0 +1,17 @@
1
+ """Publish DeepEval evaluation results as Agent Observability experiments."""
2
+
3
+ from .integration import (
4
+ DeepEvalRun,
5
+ PublishedDeepEvalRun,
6
+ evaluate_with_agento11y,
7
+ publish_deepeval_results,
8
+ run_deepeval,
9
+ )
10
+
11
+ __all__ = [
12
+ "DeepEvalRun",
13
+ "PublishedDeepEvalRun",
14
+ "evaluate_with_agento11y",
15
+ "publish_deepeval_results",
16
+ "run_deepeval",
17
+ ]