nishanttyagi-agenteval 0.1.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.
- nishanttyagi_agenteval-0.1.0/LICENSE +21 -0
- nishanttyagi_agenteval-0.1.0/PKG-INFO +290 -0
- nishanttyagi_agenteval-0.1.0/README.md +263 -0
- nishanttyagi_agenteval-0.1.0/__init__.py +3 -0
- nishanttyagi_agenteval-0.1.0/__main__.py +6 -0
- nishanttyagi_agenteval-0.1.0/adapters/__init__.py +15 -0
- nishanttyagi_agenteval-0.1.0/adapters/agentic_data_analyst.py +155 -0
- nishanttyagi_agenteval-0.1.0/adapters/base.py +90 -0
- nishanttyagi_agenteval-0.1.0/adapters/contract_shield.py +14 -0
- nishanttyagi_agenteval-0.1.0/adapters/data_analyst.py +9 -0
- nishanttyagi_agenteval-0.1.0/adapters/scheme_saathi.py +14 -0
- nishanttyagi_agenteval-0.1.0/agents.yaml +77 -0
- nishanttyagi_agenteval-0.1.0/baselines/data_analyst.json +35 -0
- nishanttyagi_agenteval-0.1.0/cli.py +484 -0
- nishanttyagi_agenteval-0.1.0/core/__init__.py +1 -0
- nishanttyagi_agenteval-0.1.0/core/ci_matrix.py +49 -0
- nishanttyagi_agenteval-0.1.0/core/ci_preflight.py +28 -0
- nishanttyagi_agenteval-0.1.0/core/compare.py +263 -0
- nishanttyagi_agenteval-0.1.0/core/config.py +66 -0
- nishanttyagi_agenteval-0.1.0/core/flakiness.py +256 -0
- nishanttyagi_agenteval-0.1.0/core/generator.py +174 -0
- nishanttyagi_agenteval-0.1.0/core/judge.py +78 -0
- nishanttyagi_agenteval-0.1.0/core/metrics.py +574 -0
- nishanttyagi_agenteval-0.1.0/core/provenance.py +52 -0
- nishanttyagi_agenteval-0.1.0/core/registry.py +216 -0
- nishanttyagi_agenteval-0.1.0/core/runner.py +276 -0
- nishanttyagi_agenteval-0.1.0/core/schema.py +228 -0
- nishanttyagi_agenteval-0.1.0/core/store.py +223 -0
- nishanttyagi_agenteval-0.1.0/core/trajectory.py +134 -0
- nishanttyagi_agenteval-0.1.0/dashboard/__init__.py +1 -0
- nishanttyagi_agenteval-0.1.0/dashboard/app.py +907 -0
- nishanttyagi_agenteval-0.1.0/nishanttyagi_agenteval.egg-info/PKG-INFO +290 -0
- nishanttyagi_agenteval-0.1.0/nishanttyagi_agenteval.egg-info/SOURCES.txt +90 -0
- nishanttyagi_agenteval-0.1.0/nishanttyagi_agenteval.egg-info/dependency_links.txt +1 -0
- nishanttyagi_agenteval-0.1.0/nishanttyagi_agenteval.egg-info/entry_points.txt +2 -0
- nishanttyagi_agenteval-0.1.0/nishanttyagi_agenteval.egg-info/requires.txt +6 -0
- nishanttyagi_agenteval-0.1.0/nishanttyagi_agenteval.egg-info/top_level.txt +1 -0
- nishanttyagi_agenteval-0.1.0/pyproject.toml +64 -0
- nishanttyagi_agenteval-0.1.0/setup.cfg +4 -0
- nishanttyagi_agenteval-0.1.0/tests/golden/analyst_cases.yaml +234 -0
- nishanttyagi_agenteval-0.1.0/tests/test_adapter_contract.py +47 -0
- nishanttyagi_agenteval-0.1.0/tests/test_adapter_usage.py +32 -0
- nishanttyagi_agenteval-0.1.0/tests/test_agentic_data_analyst_trajectory.py +137 -0
- nishanttyagi_agenteval-0.1.0/tests/test_ci_matrix.py +15 -0
- nishanttyagi_agenteval-0.1.0/tests/test_ci_workflow.py +24 -0
- nishanttyagi_agenteval-0.1.0/tests/test_cli_agents.py +80 -0
- nishanttyagi_agenteval-0.1.0/tests/test_compare.py +158 -0
- nishanttyagi_agenteval-0.1.0/tests/test_config.py +38 -0
- nishanttyagi_agenteval-0.1.0/tests/test_dashboard_flakiness.py +88 -0
- nishanttyagi_agenteval-0.1.0/tests/test_dashboard_run_selection.py +114 -0
- nishanttyagi_agenteval-0.1.0/tests/test_dashboard_trajectory.py +80 -0
- nishanttyagi_agenteval-0.1.0/tests/test_flakiness.py +140 -0
- nishanttyagi_agenteval-0.1.0/tests/test_flakiness_store.py +188 -0
- nishanttyagi_agenteval-0.1.0/tests/test_generator.py +81 -0
- nishanttyagi_agenteval-0.1.0/tests/test_metrics_integrity.py +106 -0
- nishanttyagi_agenteval-0.1.0/tests/test_packaging.py +41 -0
- nishanttyagi_agenteval-0.1.0/tests/test_provenance.py +25 -0
- nishanttyagi_agenteval-0.1.0/tests/test_registry.py +126 -0
- nishanttyagi_agenteval-0.1.0/tests/test_repeat_cli.py +184 -0
- nishanttyagi_agenteval-0.1.0/tests/test_runner_trajectory.py +168 -0
- nishanttyagi_agenteval-0.1.0/tests/test_schema_trajectory.py +76 -0
- nishanttyagi_agenteval-0.1.0/tests/test_store_git_sha.py +42 -0
- nishanttyagi_agenteval-0.1.0/tests/test_trajectory.py +130 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nishant Tyagi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nishanttyagi-agenteval
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CI-integrated evaluation harness for LLM agents
|
|
5
|
+
Author: Nishant Tyagi
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/nishanttyagi28/agenteval
|
|
8
|
+
Project-URL: Repository, https://github.com/nishanttyagi28/agenteval
|
|
9
|
+
Project-URL: Issues, https://github.com/nishanttyagi28/agenteval/issues
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Testing
|
|
18
|
+
Requires-Python: >=3.10
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Requires-Dist: PyYAML<7,>=6.0
|
|
22
|
+
Requires-Dist: pandas<4,>=2.2
|
|
23
|
+
Requires-Dist: streamlit<2,>=1.59
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest<9,>=8; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# AgentEval
|
|
29
|
+
|
|
30
|
+
[](https://github.com/nishanttyagi28/agenteval/actions/workflows/eval.yml)
|
|
31
|
+
[](LICENSE)
|
|
32
|
+
[](pyproject.toml)
|
|
33
|
+
[](https://agenteval-6honbe24hradazngswxkrq.streamlit.app/)
|
|
34
|
+
|
|
35
|
+
**CI for AI agents — pytest and GitHub Actions style evaluation for LLM systems.**
|
|
36
|
+
|
|
37
|
+
AgentEval runs an agent against YAML golden suites, scores five reliability metrics, compares results with a versioned baseline, and turns regressions into a reviewable CI decision.
|
|
38
|
+
|
|
39
|
+
**[Open the live dashboard](https://agenteval-6honbe24hradazngswxkrq.streamlit.app/)**
|
|
40
|
+
|
|
41
|
+
## Why AgentEval
|
|
42
|
+
|
|
43
|
+
LLM agents are probabilistic. A prompt, model, or tool change can improve one answer while silently reducing correctness elsewhere, increasing hallucinations, or raising latency and cost. Traditional unit tests remain useful for deterministic code, but they do not fully cover model outputs, tool routing, or quality drift across versions.
|
|
44
|
+
|
|
45
|
+
AgentEval adds the missing evaluation layer:
|
|
46
|
+
|
|
47
|
+
- YAML-defined golden test cases
|
|
48
|
+
- deterministic-first scoring with an LLM judge only for open-ended answers
|
|
49
|
+
- baseline comparison and configurable regression gates
|
|
50
|
+
- explicit agent, evaluator, missing-case, and skipped-case failures
|
|
51
|
+
- a Streamlit dashboard for summary, regression, and case-level inspection
|
|
52
|
+
- GitHub Actions automation with a six-case smoke suite and optional 21-case full suite
|
|
53
|
+
- reviewable adversarial variants that remain outside blocking CI until approved
|
|
54
|
+
|
|
55
|
+
## Evaluation flow
|
|
56
|
+
|
|
57
|
+
```mermaid
|
|
58
|
+
flowchart TD
|
|
59
|
+
Cases["YAML golden cases"] --> Runner["Agent runner"]
|
|
60
|
+
Runner --> Metrics["Five metrics"]
|
|
61
|
+
Metrics --> Gate["Baseline regression gate"]
|
|
62
|
+
Gate --> CI["GitHub Actions report"]
|
|
63
|
+
Gate --> Dashboard["Streamlit dashboard"]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
1. Define the prompt, ground truth, required tools, and tolerance in YAML.
|
|
67
|
+
2. Run each case through an adapter for the agent under test.
|
|
68
|
+
3. Score the output and store a provenance-linked JSON run.
|
|
69
|
+
4. Compare the current report with a versioned baseline.
|
|
70
|
+
5. Fail CI when configured quality gates or case-integrity checks are violated.
|
|
71
|
+
6. Inspect suite and case-level evidence in the dashboard.
|
|
72
|
+
|
|
73
|
+
## Five metrics
|
|
74
|
+
|
|
75
|
+
| Metric | What it evaluates | Implementation |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| **Correctness** | Whether the answer matches the expected result | Exact, contains, numeric, numeric-table, or LLM-judge checks |
|
|
78
|
+
| **Hallucination rate** | Unsupported numeric or factual claims | Deterministic ground-truth comparison |
|
|
79
|
+
| **Tool-call accuracy** | Whether the required tools were invoked | Precision, recall, and suite-level F1 |
|
|
80
|
+
| **Latency** | Response-time distribution | p50 and p95 wall-clock latency |
|
|
81
|
+
| **Cost** | Estimated or provider-reported usage cost | Per-case and suite-level USD estimate |
|
|
82
|
+
|
|
83
|
+
Correctness uses the exact tolerance configured in YAML. Hallucination detection applies a separate minimum absolute tolerance of 0.01 for harmless numeric formatting noise; that floor cannot convert an incorrect answer into a correctness pass.
|
|
84
|
+
|
|
85
|
+
## Failure taxonomy and gate integrity
|
|
86
|
+
|
|
87
|
+
AgentEval distinguishes output quality from execution and evaluation failures:
|
|
88
|
+
|
|
89
|
+
| Status | Meaning | Quality denominators | Default gate behaviour |
|
|
90
|
+
|---|---|---:|---|
|
|
91
|
+
| `failed` | The agent ran but failed an expectation | Included | Can fail metric gates |
|
|
92
|
+
| `agent_error` | Provider, ingestion, SQL, adapter, or execution failure | Excluded | Fails loudly |
|
|
93
|
+
| `evaluator_error` | The evaluator or LLM judge could not produce a valid decision | Excluded | Fails loudly |
|
|
94
|
+
| `skipped` | A case produced no scored result | Excluded | Fails loudly |
|
|
95
|
+
| `missing` | A baseline case is absent from the current run | Not applicable | Fails loudly |
|
|
96
|
+
|
|
97
|
+
Infrastructure failures are not counted as incorrect or hallucinated answers, so provider outages do not corrupt quality rates. They remain visible and fail the regression gate by default. Missing and skipped cases are also gated to prevent an incomplete run from appearing healthy.
|
|
98
|
+
|
|
99
|
+
## Flakiness detection
|
|
100
|
+
|
|
101
|
+
LLM agents can produce different answers for the same prompt even when the code and inputs have not changed. AgentEval's opt-in repeat mode separates two different problems: an agent can be **consistently wrong** (the same failing verdict every time) or **flaky** (the verdict or comparable numeric value changes across observations). The report stores both consistency and pass rate so repeatability is never mistaken for correctness.
|
|
102
|
+
|
|
103
|
+
Run the normal suite once and repeat only explicitly selected cases:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
python -m agenteval run \
|
|
107
|
+
--agent agentic_data_analyst \
|
|
108
|
+
--repeat 5 \
|
|
109
|
+
--repeat-case total_customers \
|
|
110
|
+
--repeat-case avg_monthly_charges
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`--repeat 5` means five total observations for each selected case: the primary suite result plus four additional invocations. Requiring explicit `--repeat-case` values prevents an accidental N-times increase in API calls across the full suite. The default `--repeat 1` follows the existing single-pass path without creating flakiness evidence.
|
|
114
|
+
|
|
115
|
+
| Classification | Consistency score |
|
|
116
|
+
|---|---:|
|
|
117
|
+
| `stable` | `1.0` |
|
|
118
|
+
| `flaky` | `0.80` to `<1.0` |
|
|
119
|
+
| `unstable` | `<0.80` |
|
|
120
|
+
|
|
121
|
+
These labels are documented defaults rather than information-losing buckets: every artifact retains the raw consistency fraction, such as `4/5`, so thresholds can be adjusted later.
|
|
122
|
+
|
|
123
|
+
Scalar numeric cases use `largest_complete_link_cluster`. Values cluster when the difference between the cluster maximum and minimum remains within the case's existing `numeric_tolerance`; the largest same-verdict cluster wins, and the primary observation receives no special preference. Exact, contains, and LLM-judge cases use verdict consistency. Ambiguous scalar numeric answers and numeric-table cases also fall back to verdict-only consistency.
|
|
124
|
+
|
|
125
|
+
Flakiness is observability-only in this phase. It does not affect the regression gate or baseline comparison. Evidence is stored separately under `runs/<agent>/flakiness/<run_id>.json`, keeping repeated latency, cost, answers, and verdicts isolated from the primary run report.
|
|
126
|
+
|
|
127
|
+
## Trajectory scoring
|
|
128
|
+
|
|
129
|
+
Trajectory scoring adds step-level evidence about how an agent reached its answer. A golden case can optionally declare the expected ordered events alongside its existing output expectations:
|
|
130
|
+
|
|
131
|
+
```yaml
|
|
132
|
+
- id: total_customers
|
|
133
|
+
prompt: "How many customers are in the dataset?"
|
|
134
|
+
expects:
|
|
135
|
+
correctness_type: numeric
|
|
136
|
+
ground_truth: 7043
|
|
137
|
+
expected_trajectory: ["route:sql", "agent:sql"]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
AgentEval compares `expected_trajectory` with the adapter's actual `nodes_fired` sequence using a longest common subsequence (LCS). The matched subsequence produces precision (matched steps divided by actual steps), recall (matched steps divided by expected steps), and their F1 score, while preserving evidence about exact match, ordering, missing steps, and extra steps. Duplicate steps retain their multiplicity.
|
|
141
|
+
|
|
142
|
+
The field is optional and backward compatible: cases without it are scored and serialized exactly as before. Trajectory scoring is observability-only in v1 and does not affect correctness, existing metrics, baseline comparison, or CI gates.
|
|
143
|
+
|
|
144
|
+
## Golden case example
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
- id: avg_tenure_months
|
|
148
|
+
prompt: "What is the average tenure in months?"
|
|
149
|
+
expects:
|
|
150
|
+
correctness_type: numeric
|
|
151
|
+
must_call_tools: [sql_agent]
|
|
152
|
+
must_not_hallucinate: true
|
|
153
|
+
ground_truth: 25.23
|
|
154
|
+
numeric_tolerance: 0.05
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
The current analyst suite contains 21 hand-written cases grounded in the demonstration dataset.
|
|
158
|
+
|
|
159
|
+
## Dashboard evidence
|
|
160
|
+
|
|
161
|
+
AgentEval is integrated with [Agentic Data Analyst](https://github.com/nishanttyagi28/agentic-data-analyst), a modular application that routes natural-language questions to SQL, ML, statistics, forecasting, reporting, and RAG components.
|
|
162
|
+
|
|
163
|
+
### Historical run summary
|
|
164
|
+
|
|
165
|
+

|
|
166
|
+
|
|
167
|
+
The screenshot records a specific historical run; it is evidence from that run, not a claim about the current deployment state.
|
|
168
|
+
|
|
169
|
+
### Regression trade-off
|
|
170
|
+
|
|
171
|
+

|
|
172
|
+
|
|
173
|
+
The comparison view exposes trade-offs instead of collapsing health into one number. In the recorded example, correctness improved from 85.7% to 95.2%, while p95 latency and estimated cost both increased.
|
|
174
|
+
|
|
175
|
+
### Failure drill-down
|
|
176
|
+
|
|
177
|
+

|
|
178
|
+
|
|
179
|
+
A numeric answer of approximately 25 months failed against a ground truth of 25.23 with a tolerance of 0.05. The ground truth was intentionally preserved rather than loosened to produce a green result.
|
|
180
|
+
|
|
181
|
+
## Quickstart
|
|
182
|
+
|
|
183
|
+
Python 3.12 is used by the CI workflow.
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Keep both repositories as siblings
|
|
187
|
+
git clone https://github.com/nishanttyagi28/agentic-data-analyst
|
|
188
|
+
git clone https://github.com/nishanttyagi28/agenteval
|
|
189
|
+
|
|
190
|
+
python -m pip install -r agenteval/requirements.txt
|
|
191
|
+
python -m pip install -r agentic-data-analyst/requirements.txt
|
|
192
|
+
|
|
193
|
+
export AGENTIC_ANALYST_PATH="$PWD/agentic-data-analyst"
|
|
194
|
+
|
|
195
|
+
# Run all golden cases
|
|
196
|
+
python -m agenteval run
|
|
197
|
+
|
|
198
|
+
# Compare a current report with the versioned baseline
|
|
199
|
+
python -m agenteval compare \
|
|
200
|
+
--baseline agenteval/baselines/data_analyst.json \
|
|
201
|
+
--current agenteval/runs/<run>.json
|
|
202
|
+
|
|
203
|
+
# Launch the dashboard
|
|
204
|
+
python -m streamlit run agenteval/dashboard/app.py
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The repositories must share the same parent directory so Python can resolve the `agenteval` package and the sibling agent dependency.
|
|
208
|
+
|
|
209
|
+
## GitHub Actions
|
|
210
|
+
|
|
211
|
+
`.github/workflows/eval.yml` runs on pull requests and manual dispatch:
|
|
212
|
+
|
|
213
|
+
- deterministic unit tests and CLI validation run first
|
|
214
|
+
- an internal pull request or manual dispatch can run the live evaluation
|
|
215
|
+
- pull requests use six selected smoke cases
|
|
216
|
+
- manual dispatch with `full_suite=true` runs all 21 golden cases
|
|
217
|
+
- the current report is compared with the versioned baseline
|
|
218
|
+
- evidence is uploaded as a workflow artifact
|
|
219
|
+
- a generated Markdown report is created or updated on the pull request
|
|
220
|
+
- missing `GROQ_API_KEY` produces an explicit skipped-evaluation summary
|
|
221
|
+
- concurrency cancellation and job timeouts prevent stale or runaway runs
|
|
222
|
+
|
|
223
|
+
## Adversarial robustness
|
|
224
|
+
|
|
225
|
+
Generate reviewable, expectation-preserving candidates:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
python -m agenteval generate \
|
|
229
|
+
--cases agenteval/tests/golden/analyst_cases.yaml \
|
|
230
|
+
--variants 3 \
|
|
231
|
+
--output agenteval/tests/adversarial/candidates.yaml
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Each candidate retains its parent case, ground truth, tool expectations, and mutation type. New variants start with `review_status: candidate` and are not added to the blocking golden gate until reviewed.
|
|
235
|
+
|
|
236
|
+
## Project structure
|
|
237
|
+
|
|
238
|
+
```text
|
|
239
|
+
agenteval/
|
|
240
|
+
├── agents.yaml # Registered agents, adapters, suites, and gate defaults
|
|
241
|
+
├── adapters/ # Agent interface and concrete adapter
|
|
242
|
+
├── core/
|
|
243
|
+
│ ├── schema.py # Test-case and run-report models
|
|
244
|
+
│ ├── runner.py # Suite execution
|
|
245
|
+
│ ├── flakiness.py # Repeat consistency analysis and classification
|
|
246
|
+
│ ├── trajectory.py # Step-sequence evaluation and evidence
|
|
247
|
+
│ ├── metrics.py # Correctness, hallucination, tools, latency, cost
|
|
248
|
+
│ ├── judge.py # LLM judge for open-ended correctness
|
|
249
|
+
│ ├── compare.py # Baseline comparison and CI decision
|
|
250
|
+
│ ├── provenance.py # Reproducibility metadata
|
|
251
|
+
│ └── store.py # JSON run persistence
|
|
252
|
+
├── dashboard/app.py # Streamlit dashboard
|
|
253
|
+
├── tests/golden/ # Hand-written YAML suite
|
|
254
|
+
├── baselines/ # Versioned baseline reports
|
|
255
|
+
├── runs/ # Standard single-pass run artifacts
|
|
256
|
+
│ └── <agent>/
|
|
257
|
+
│ └── flakiness/ # Isolated repeated-run evidence by run_id
|
|
258
|
+
└── .github/workflows/ # CI regression workflow
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Testing
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
python -m pip install -r requirements-dev.txt
|
|
265
|
+
python -m pytest -q
|
|
266
|
+
python -m agenteval --help
|
|
267
|
+
python -m agenteval compare --help
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Deterministic tests cover schema and metrics behaviour, error handling, baseline comparison, missing/skipped-case gates, adversarial generation, provenance, and CLI paths without requiring a live provider call.
|
|
271
|
+
|
|
272
|
+
## Current limitations
|
|
273
|
+
|
|
274
|
+
- The included adapter and golden suite are demonstrated primarily with Agentic Data Analyst.
|
|
275
|
+
- Live evaluation requires the sibling agent repository, its runtime dependencies, and `GROQ_API_KEY`.
|
|
276
|
+
- LLM-judge correctness is reserved for open-ended cases and introduces provider dependence.
|
|
277
|
+
- Adversarial candidates require human review before entering blocking evaluation.
|
|
278
|
+
- Cost falls back to a character-based token estimate when provider usage is unavailable.
|
|
279
|
+
- Flakiness is not yet part of CI gating and has no cross-agent comparison view.
|
|
280
|
+
- Numeric-table flakiness currently compares verdicts only rather than extracting and clustering each table cell.
|
|
281
|
+
- The smoke suite's only scalar numeric case currently falls back to verdict consistency because its answer restates the same count; `largest_complete_link_cluster` is covered deterministically but has not yet been exercised by a live CI repeat run.
|
|
282
|
+
- Current trajectory depth is limited to the adapter's shallow `route → agent` sequence (typically two events); instrumenting deeper orchestrator events is a candidate for future enrichment.
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
AgentEval is available under the [MIT License](LICENSE).
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
Built by [Nishant Tyagi](https://github.com/nishanttyagi28).
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
# AgentEval
|
|
2
|
+
|
|
3
|
+
[](https://github.com/nishanttyagi28/agenteval/actions/workflows/eval.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](pyproject.toml)
|
|
6
|
+
[](https://agenteval-6honbe24hradazngswxkrq.streamlit.app/)
|
|
7
|
+
|
|
8
|
+
**CI for AI agents — pytest and GitHub Actions style evaluation for LLM systems.**
|
|
9
|
+
|
|
10
|
+
AgentEval runs an agent against YAML golden suites, scores five reliability metrics, compares results with a versioned baseline, and turns regressions into a reviewable CI decision.
|
|
11
|
+
|
|
12
|
+
**[Open the live dashboard](https://agenteval-6honbe24hradazngswxkrq.streamlit.app/)**
|
|
13
|
+
|
|
14
|
+
## Why AgentEval
|
|
15
|
+
|
|
16
|
+
LLM agents are probabilistic. A prompt, model, or tool change can improve one answer while silently reducing correctness elsewhere, increasing hallucinations, or raising latency and cost. Traditional unit tests remain useful for deterministic code, but they do not fully cover model outputs, tool routing, or quality drift across versions.
|
|
17
|
+
|
|
18
|
+
AgentEval adds the missing evaluation layer:
|
|
19
|
+
|
|
20
|
+
- YAML-defined golden test cases
|
|
21
|
+
- deterministic-first scoring with an LLM judge only for open-ended answers
|
|
22
|
+
- baseline comparison and configurable regression gates
|
|
23
|
+
- explicit agent, evaluator, missing-case, and skipped-case failures
|
|
24
|
+
- a Streamlit dashboard for summary, regression, and case-level inspection
|
|
25
|
+
- GitHub Actions automation with a six-case smoke suite and optional 21-case full suite
|
|
26
|
+
- reviewable adversarial variants that remain outside blocking CI until approved
|
|
27
|
+
|
|
28
|
+
## Evaluation flow
|
|
29
|
+
|
|
30
|
+
```mermaid
|
|
31
|
+
flowchart TD
|
|
32
|
+
Cases["YAML golden cases"] --> Runner["Agent runner"]
|
|
33
|
+
Runner --> Metrics["Five metrics"]
|
|
34
|
+
Metrics --> Gate["Baseline regression gate"]
|
|
35
|
+
Gate --> CI["GitHub Actions report"]
|
|
36
|
+
Gate --> Dashboard["Streamlit dashboard"]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
1. Define the prompt, ground truth, required tools, and tolerance in YAML.
|
|
40
|
+
2. Run each case through an adapter for the agent under test.
|
|
41
|
+
3. Score the output and store a provenance-linked JSON run.
|
|
42
|
+
4. Compare the current report with a versioned baseline.
|
|
43
|
+
5. Fail CI when configured quality gates or case-integrity checks are violated.
|
|
44
|
+
6. Inspect suite and case-level evidence in the dashboard.
|
|
45
|
+
|
|
46
|
+
## Five metrics
|
|
47
|
+
|
|
48
|
+
| Metric | What it evaluates | Implementation |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| **Correctness** | Whether the answer matches the expected result | Exact, contains, numeric, numeric-table, or LLM-judge checks |
|
|
51
|
+
| **Hallucination rate** | Unsupported numeric or factual claims | Deterministic ground-truth comparison |
|
|
52
|
+
| **Tool-call accuracy** | Whether the required tools were invoked | Precision, recall, and suite-level F1 |
|
|
53
|
+
| **Latency** | Response-time distribution | p50 and p95 wall-clock latency |
|
|
54
|
+
| **Cost** | Estimated or provider-reported usage cost | Per-case and suite-level USD estimate |
|
|
55
|
+
|
|
56
|
+
Correctness uses the exact tolerance configured in YAML. Hallucination detection applies a separate minimum absolute tolerance of 0.01 for harmless numeric formatting noise; that floor cannot convert an incorrect answer into a correctness pass.
|
|
57
|
+
|
|
58
|
+
## Failure taxonomy and gate integrity
|
|
59
|
+
|
|
60
|
+
AgentEval distinguishes output quality from execution and evaluation failures:
|
|
61
|
+
|
|
62
|
+
| Status | Meaning | Quality denominators | Default gate behaviour |
|
|
63
|
+
|---|---|---:|---|
|
|
64
|
+
| `failed` | The agent ran but failed an expectation | Included | Can fail metric gates |
|
|
65
|
+
| `agent_error` | Provider, ingestion, SQL, adapter, or execution failure | Excluded | Fails loudly |
|
|
66
|
+
| `evaluator_error` | The evaluator or LLM judge could not produce a valid decision | Excluded | Fails loudly |
|
|
67
|
+
| `skipped` | A case produced no scored result | Excluded | Fails loudly |
|
|
68
|
+
| `missing` | A baseline case is absent from the current run | Not applicable | Fails loudly |
|
|
69
|
+
|
|
70
|
+
Infrastructure failures are not counted as incorrect or hallucinated answers, so provider outages do not corrupt quality rates. They remain visible and fail the regression gate by default. Missing and skipped cases are also gated to prevent an incomplete run from appearing healthy.
|
|
71
|
+
|
|
72
|
+
## Flakiness detection
|
|
73
|
+
|
|
74
|
+
LLM agents can produce different answers for the same prompt even when the code and inputs have not changed. AgentEval's opt-in repeat mode separates two different problems: an agent can be **consistently wrong** (the same failing verdict every time) or **flaky** (the verdict or comparable numeric value changes across observations). The report stores both consistency and pass rate so repeatability is never mistaken for correctness.
|
|
75
|
+
|
|
76
|
+
Run the normal suite once and repeat only explicitly selected cases:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
python -m agenteval run \
|
|
80
|
+
--agent agentic_data_analyst \
|
|
81
|
+
--repeat 5 \
|
|
82
|
+
--repeat-case total_customers \
|
|
83
|
+
--repeat-case avg_monthly_charges
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`--repeat 5` means five total observations for each selected case: the primary suite result plus four additional invocations. Requiring explicit `--repeat-case` values prevents an accidental N-times increase in API calls across the full suite. The default `--repeat 1` follows the existing single-pass path without creating flakiness evidence.
|
|
87
|
+
|
|
88
|
+
| Classification | Consistency score |
|
|
89
|
+
|---|---:|
|
|
90
|
+
| `stable` | `1.0` |
|
|
91
|
+
| `flaky` | `0.80` to `<1.0` |
|
|
92
|
+
| `unstable` | `<0.80` |
|
|
93
|
+
|
|
94
|
+
These labels are documented defaults rather than information-losing buckets: every artifact retains the raw consistency fraction, such as `4/5`, so thresholds can be adjusted later.
|
|
95
|
+
|
|
96
|
+
Scalar numeric cases use `largest_complete_link_cluster`. Values cluster when the difference between the cluster maximum and minimum remains within the case's existing `numeric_tolerance`; the largest same-verdict cluster wins, and the primary observation receives no special preference. Exact, contains, and LLM-judge cases use verdict consistency. Ambiguous scalar numeric answers and numeric-table cases also fall back to verdict-only consistency.
|
|
97
|
+
|
|
98
|
+
Flakiness is observability-only in this phase. It does not affect the regression gate or baseline comparison. Evidence is stored separately under `runs/<agent>/flakiness/<run_id>.json`, keeping repeated latency, cost, answers, and verdicts isolated from the primary run report.
|
|
99
|
+
|
|
100
|
+
## Trajectory scoring
|
|
101
|
+
|
|
102
|
+
Trajectory scoring adds step-level evidence about how an agent reached its answer. A golden case can optionally declare the expected ordered events alongside its existing output expectations:
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
- id: total_customers
|
|
106
|
+
prompt: "How many customers are in the dataset?"
|
|
107
|
+
expects:
|
|
108
|
+
correctness_type: numeric
|
|
109
|
+
ground_truth: 7043
|
|
110
|
+
expected_trajectory: ["route:sql", "agent:sql"]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
AgentEval compares `expected_trajectory` with the adapter's actual `nodes_fired` sequence using a longest common subsequence (LCS). The matched subsequence produces precision (matched steps divided by actual steps), recall (matched steps divided by expected steps), and their F1 score, while preserving evidence about exact match, ordering, missing steps, and extra steps. Duplicate steps retain their multiplicity.
|
|
114
|
+
|
|
115
|
+
The field is optional and backward compatible: cases without it are scored and serialized exactly as before. Trajectory scoring is observability-only in v1 and does not affect correctness, existing metrics, baseline comparison, or CI gates.
|
|
116
|
+
|
|
117
|
+
## Golden case example
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
- id: avg_tenure_months
|
|
121
|
+
prompt: "What is the average tenure in months?"
|
|
122
|
+
expects:
|
|
123
|
+
correctness_type: numeric
|
|
124
|
+
must_call_tools: [sql_agent]
|
|
125
|
+
must_not_hallucinate: true
|
|
126
|
+
ground_truth: 25.23
|
|
127
|
+
numeric_tolerance: 0.05
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The current analyst suite contains 21 hand-written cases grounded in the demonstration dataset.
|
|
131
|
+
|
|
132
|
+
## Dashboard evidence
|
|
133
|
+
|
|
134
|
+
AgentEval is integrated with [Agentic Data Analyst](https://github.com/nishanttyagi28/agentic-data-analyst), a modular application that routes natural-language questions to SQL, ML, statistics, forecasting, reporting, and RAG components.
|
|
135
|
+
|
|
136
|
+
### Historical run summary
|
|
137
|
+
|
|
138
|
+

|
|
139
|
+
|
|
140
|
+
The screenshot records a specific historical run; it is evidence from that run, not a claim about the current deployment state.
|
|
141
|
+
|
|
142
|
+
### Regression trade-off
|
|
143
|
+
|
|
144
|
+

|
|
145
|
+
|
|
146
|
+
The comparison view exposes trade-offs instead of collapsing health into one number. In the recorded example, correctness improved from 85.7% to 95.2%, while p95 latency and estimated cost both increased.
|
|
147
|
+
|
|
148
|
+
### Failure drill-down
|
|
149
|
+
|
|
150
|
+

|
|
151
|
+
|
|
152
|
+
A numeric answer of approximately 25 months failed against a ground truth of 25.23 with a tolerance of 0.05. The ground truth was intentionally preserved rather than loosened to produce a green result.
|
|
153
|
+
|
|
154
|
+
## Quickstart
|
|
155
|
+
|
|
156
|
+
Python 3.12 is used by the CI workflow.
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# Keep both repositories as siblings
|
|
160
|
+
git clone https://github.com/nishanttyagi28/agentic-data-analyst
|
|
161
|
+
git clone https://github.com/nishanttyagi28/agenteval
|
|
162
|
+
|
|
163
|
+
python -m pip install -r agenteval/requirements.txt
|
|
164
|
+
python -m pip install -r agentic-data-analyst/requirements.txt
|
|
165
|
+
|
|
166
|
+
export AGENTIC_ANALYST_PATH="$PWD/agentic-data-analyst"
|
|
167
|
+
|
|
168
|
+
# Run all golden cases
|
|
169
|
+
python -m agenteval run
|
|
170
|
+
|
|
171
|
+
# Compare a current report with the versioned baseline
|
|
172
|
+
python -m agenteval compare \
|
|
173
|
+
--baseline agenteval/baselines/data_analyst.json \
|
|
174
|
+
--current agenteval/runs/<run>.json
|
|
175
|
+
|
|
176
|
+
# Launch the dashboard
|
|
177
|
+
python -m streamlit run agenteval/dashboard/app.py
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The repositories must share the same parent directory so Python can resolve the `agenteval` package and the sibling agent dependency.
|
|
181
|
+
|
|
182
|
+
## GitHub Actions
|
|
183
|
+
|
|
184
|
+
`.github/workflows/eval.yml` runs on pull requests and manual dispatch:
|
|
185
|
+
|
|
186
|
+
- deterministic unit tests and CLI validation run first
|
|
187
|
+
- an internal pull request or manual dispatch can run the live evaluation
|
|
188
|
+
- pull requests use six selected smoke cases
|
|
189
|
+
- manual dispatch with `full_suite=true` runs all 21 golden cases
|
|
190
|
+
- the current report is compared with the versioned baseline
|
|
191
|
+
- evidence is uploaded as a workflow artifact
|
|
192
|
+
- a generated Markdown report is created or updated on the pull request
|
|
193
|
+
- missing `GROQ_API_KEY` produces an explicit skipped-evaluation summary
|
|
194
|
+
- concurrency cancellation and job timeouts prevent stale or runaway runs
|
|
195
|
+
|
|
196
|
+
## Adversarial robustness
|
|
197
|
+
|
|
198
|
+
Generate reviewable, expectation-preserving candidates:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
python -m agenteval generate \
|
|
202
|
+
--cases agenteval/tests/golden/analyst_cases.yaml \
|
|
203
|
+
--variants 3 \
|
|
204
|
+
--output agenteval/tests/adversarial/candidates.yaml
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Each candidate retains its parent case, ground truth, tool expectations, and mutation type. New variants start with `review_status: candidate` and are not added to the blocking golden gate until reviewed.
|
|
208
|
+
|
|
209
|
+
## Project structure
|
|
210
|
+
|
|
211
|
+
```text
|
|
212
|
+
agenteval/
|
|
213
|
+
├── agents.yaml # Registered agents, adapters, suites, and gate defaults
|
|
214
|
+
├── adapters/ # Agent interface and concrete adapter
|
|
215
|
+
├── core/
|
|
216
|
+
│ ├── schema.py # Test-case and run-report models
|
|
217
|
+
│ ├── runner.py # Suite execution
|
|
218
|
+
│ ├── flakiness.py # Repeat consistency analysis and classification
|
|
219
|
+
│ ├── trajectory.py # Step-sequence evaluation and evidence
|
|
220
|
+
│ ├── metrics.py # Correctness, hallucination, tools, latency, cost
|
|
221
|
+
│ ├── judge.py # LLM judge for open-ended correctness
|
|
222
|
+
│ ├── compare.py # Baseline comparison and CI decision
|
|
223
|
+
│ ├── provenance.py # Reproducibility metadata
|
|
224
|
+
│ └── store.py # JSON run persistence
|
|
225
|
+
├── dashboard/app.py # Streamlit dashboard
|
|
226
|
+
├── tests/golden/ # Hand-written YAML suite
|
|
227
|
+
├── baselines/ # Versioned baseline reports
|
|
228
|
+
├── runs/ # Standard single-pass run artifacts
|
|
229
|
+
│ └── <agent>/
|
|
230
|
+
│ └── flakiness/ # Isolated repeated-run evidence by run_id
|
|
231
|
+
└── .github/workflows/ # CI regression workflow
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Testing
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
python -m pip install -r requirements-dev.txt
|
|
238
|
+
python -m pytest -q
|
|
239
|
+
python -m agenteval --help
|
|
240
|
+
python -m agenteval compare --help
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Deterministic tests cover schema and metrics behaviour, error handling, baseline comparison, missing/skipped-case gates, adversarial generation, provenance, and CLI paths without requiring a live provider call.
|
|
244
|
+
|
|
245
|
+
## Current limitations
|
|
246
|
+
|
|
247
|
+
- The included adapter and golden suite are demonstrated primarily with Agentic Data Analyst.
|
|
248
|
+
- Live evaluation requires the sibling agent repository, its runtime dependencies, and `GROQ_API_KEY`.
|
|
249
|
+
- LLM-judge correctness is reserved for open-ended cases and introduces provider dependence.
|
|
250
|
+
- Adversarial candidates require human review before entering blocking evaluation.
|
|
251
|
+
- Cost falls back to a character-based token estimate when provider usage is unavailable.
|
|
252
|
+
- Flakiness is not yet part of CI gating and has no cross-agent comparison view.
|
|
253
|
+
- Numeric-table flakiness currently compares verdicts only rather than extracting and clustering each table cell.
|
|
254
|
+
- The smoke suite's only scalar numeric case currently falls back to verdict consistency because its answer restates the same count; `largest_complete_link_cluster` is covered deterministically but has not yet been exercised by a live CI repeat run.
|
|
255
|
+
- Current trajectory depth is limited to the adapter's shallow `route → agent` sequence (typically two events); instrumenting deeper orchestrator events is a candidate for future enrichment.
|
|
256
|
+
|
|
257
|
+
## License
|
|
258
|
+
|
|
259
|
+
AgentEval is available under the [MIT License](LICENSE).
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
Built by [Nishant Tyagi](https://github.com/nishanttyagi28).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Agent adapters for AgentEval."""
|
|
2
|
+
|
|
3
|
+
from agenteval.adapters.base import AgentAdapter, AgentResponse, AgentRun
|
|
4
|
+
from agenteval.adapters.agentic_data_analyst import (
|
|
5
|
+
AgenticDataAnalystAdapter,
|
|
6
|
+
DataAnalystAdapter,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"AgentAdapter",
|
|
11
|
+
"AgentResponse",
|
|
12
|
+
"AgentRun",
|
|
13
|
+
"AgenticDataAnalystAdapter",
|
|
14
|
+
"DataAnalystAdapter",
|
|
15
|
+
]
|