prompteval-delta 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.
Files changed (29) hide show
  1. prompteval_delta-0.1.0/PKG-INFO +247 -0
  2. prompteval_delta-0.1.0/README.md +219 -0
  3. prompteval_delta-0.1.0/pyproject.toml +104 -0
  4. prompteval_delta-0.1.0/pyproject.toml.orig +106 -0
  5. prompteval_delta-0.1.0/src/prompteval/__init__.py +87 -0
  6. prompteval_delta-0.1.0/src/prompteval/cli.py +378 -0
  7. prompteval_delta-0.1.0/src/prompteval/compare/__init__.py +38 -0
  8. prompteval_delta-0.1.0/src/prompteval/compare/core.py +635 -0
  9. prompteval_delta-0.1.0/src/prompteval/compare/gates.py +153 -0
  10. prompteval_delta-0.1.0/src/prompteval/cost/__init__.py +30 -0
  11. prompteval_delta-0.1.0/src/prompteval/cost/compute.py +138 -0
  12. prompteval_delta-0.1.0/src/prompteval/cost/models.py +168 -0
  13. prompteval_delta-0.1.0/src/prompteval/cost/pricing.yaml +69 -0
  14. prompteval_delta-0.1.0/src/prompteval/eval/__init__.py +58 -0
  15. prompteval_delta-0.1.0/src/prompteval/eval/judge.py +107 -0
  16. prompteval_delta-0.1.0/src/prompteval/eval/persistence.py +99 -0
  17. prompteval_delta-0.1.0/src/prompteval/eval/runner.py +407 -0
  18. prompteval_delta-0.1.0/src/prompteval/eval/scorer.py +92 -0
  19. prompteval_delta-0.1.0/src/prompteval/eval/stock.py +183 -0
  20. prompteval_delta-0.1.0/src/prompteval/init/__init__.py +11 -0
  21. prompteval_delta-0.1.0/src/prompteval/init/bootstrap.py +80 -0
  22. prompteval_delta-0.1.0/src/prompteval/init/templates/__init__.py +2 -0
  23. prompteval_delta-0.1.0/src/prompteval/init/templates/dataset.jsonl +5 -0
  24. prompteval_delta-0.1.0/src/prompteval/init/templates/env.example +4 -0
  25. prompteval_delta-0.1.0/src/prompteval/init/templates/eval.py +63 -0
  26. prompteval_delta-0.1.0/src/prompteval/init/templates/prompts/v1.txt +11 -0
  27. prompteval_delta-0.1.0/src/prompteval/init/templates/prompts/v2.txt +9 -0
  28. prompteval_delta-0.1.0/src/prompteval/py.typed +0 -0
  29. prompteval_delta-0.1.0/src/prompteval/version.py +8 -0
@@ -0,0 +1,247 @@
1
+ Metadata-Version: 2.3
2
+ Name: prompteval-delta
3
+ Version: 0.1.0
4
+ Summary: LLM eval framework with first-class token-cost tracking. Did your prompt change save money without losing quality?
5
+ Keywords: llm,evaluation,evals,prompt-engineering,openai,gpt-4,cost-tracking,token-cost,ai-quality,regression-detection
6
+ Author: Anuj Mahajan
7
+ Author-email: Anuj Mahajan <mahajananuj07@gmail.com>
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
15
+ Classifier: Topic :: Software Development :: Quality Assurance
16
+ Classifier: Topic :: Software Development :: Testing
17
+ Requires-Dist: openai>=1.50.0
18
+ Requires-Dist: click>=8.1.7
19
+ Requires-Dist: pydantic>=2.9.0
20
+ Requires-Dist: pyyaml>=6.0
21
+ Requires-Dist: numpy>=1.26
22
+ Requires-Dist: scipy>=1.13
23
+ Requires-Python: >=3.12
24
+ Project-URL: Homepage, https://github.com/mahAnuj/prompteval
25
+ Project-URL: Repository, https://github.com/mahAnuj/prompteval
26
+ Project-URL: Issues, https://github.com/mahAnuj/prompteval/issues
27
+ Description-Content-Type: text/markdown
28
+
29
+ # prompteval
30
+
31
+ **Paired cost-and-quality delta reports for LLM prompts — so you can ship the cheaper version without guessing.**
32
+
33
+ > _Did your prompt change save money without losing quality?_
34
+
35
+ prompteval is **pytest for LLM prompts**. You define a small golden test set and one or more scorers. You run it against your v1 prompt, then your v2 prompt, then ask it to compare. You get back a single report:
36
+
37
+ ```
38
+ v1 v2 Δ 95% CI p
39
+ ─────────────────────────────────────────────────────────────────────────────
40
+ mentions_required_terms 0.84 0.79 −0.05 [−0.13, +0.03] 0.21
41
+ professional_tone 0.81 0.83 +0.02 [−0.05, +0.09] 0.58
42
+ ─────────────────────────────────────────────────────────────────────────────
43
+ total cost $0.158 $0.099 −37% [−42%, −32%] <0.001
44
+ avg latency 1.4s 1.1s −21% [−28%, −14%] <0.001
45
+
46
+ Quality verdict: no significant regression
47
+ Cost verdict: significant 37% reduction
48
+ Recommendation: ship v2 — cost savings real, quality holds
49
+ ```
50
+
51
+ Existing eval tools (Braintrust, Langfuse, promptfoo, Phoenix) track cost as a metric you graph; prompteval treats it as a **comparison axis** alongside quality. See [docs/competitor-scan.md](docs/competitor-scan.md) for verified evidence.
52
+
53
+ > ⚠️ **Alpha — v0.1.0.** The PyPI package is **`prompteval-delta`** (first
54
+ > release pending; until then, install from source). **Do not
55
+ > `pip install prompteval`** — that name on PyPI belongs to an unrelated
56
+ > project. The import and the command are still `prompteval`. The public API
57
+ > may still change before 1.0. Stars and issues welcome.
58
+
59
+ ---
60
+
61
+ ## What prompteval is, and is not
62
+
63
+ | ✅ It is | ❌ It is not |
64
+ |---|---|
65
+ | An **offline** eval framework (think pytest for prompts) | A runtime proxy or LLM gateway |
66
+ | Run from your CLI or your CI | Sitting in your prod request path |
67
+ | Compares two prompt versions on quality **and** cost | Caching prod LLM calls |
68
+ | Statistical significance built in | Replacing Helicone / Portkey / LiteLLM |
69
+ | Honest about scorer methodology | A black-box "AI judges your AI" |
70
+
71
+ **Closest neighbors:** pytest, [Braintrust Experiments](https://braintrust.dev/), [promptfoo](https://promptfoo.dev/), [Inspect AI](https://inspect.aisi.org.uk/).
72
+
73
+ **Not what we do:** [Helicone](https://helicone.ai/), [Portkey](https://portkey.ai/), [LiteLLM](https://github.com/BerriAI/litellm), [LangChain](https://langchain.com/).
74
+
75
+ ---
76
+
77
+ ## User journey (v1)
78
+
79
+ Eight steps. ~30 minutes the first time. ~5 minutes every time after.
80
+
81
+ ### 1. Install
82
+
83
+ ```bash
84
+ uv add prompteval-delta # or: pip install prompteval-delta
85
+ prompteval --version
86
+ ```
87
+
88
+ ### 2. Bootstrap an evals folder
89
+
90
+ ```bash
91
+ cd ~/my-app
92
+ prompteval init
93
+ ```
94
+
95
+ Creates:
96
+ ```
97
+ evals/
98
+ ├── prompts/
99
+ │ ├── v1.txt # paste your current prompt
100
+ │ └── v2.txt # paste the variant you want to test
101
+ ├── dataset.jsonl # one example pre-filled
102
+ ├── eval.py # pre-filled with 3 scorer examples
103
+ └── .env.example # OPENAI_API_KEY=...
104
+ ```
105
+
106
+ ### 3. Bring your prompts + a few examples
107
+
108
+ Paste prompts into `prompts/v1.txt` and `prompts/v2.txt`. Add 10–30 examples to `dataset.jsonl`:
109
+
110
+ ```jsonl
111
+ {"id": "refund-1", "input": "My item arrived broken, refund please", "expected": {"must_mention": ["30-day refund"], "tone": "empathetic"}}
112
+ {"id": "refund-2", "input": "Refund request 45 days after purchase", "expected": {"must_mention": ["30-day", "outside policy"], "tone": "polite"}}
113
+ ```
114
+
115
+ The `expected` field is whatever your scorers want — there's no fixed schema.
116
+
117
+ ### 4. Define what "good" means for your use case (scorers)
118
+
119
+ `eval.py` ships with three example scorers. Edit them, write new ones, or copy from templates:
120
+
121
+ ```python
122
+ from prompteval import Eval, scorer, llm_judge
123
+
124
+ @scorer
125
+ def mentions_required_terms(output: str, expected: dict) -> float:
126
+ """Hard scorer: did the reply contain required phrases?"""
127
+ must = expected.get("must_mention", [])
128
+ if not must:
129
+ return 1.0
130
+ return sum(1 for t in must if t.lower() in output.lower()) / len(must)
131
+
132
+ @scorer
133
+ def professional_tone(output: str, expected: dict) -> float:
134
+ """LLM-as-judge: rate professionalism 0-1."""
135
+ return llm_judge(
136
+ rubric="Rate the tone of this support reply 0-1. 1=empathetic+professional, 0=rude.",
137
+ text=output,
138
+ )
139
+
140
+ eval = Eval(
141
+ name="support-assistant",
142
+ dataset="dataset.jsonl",
143
+ scorers=[mentions_required_terms, professional_tone],
144
+ )
145
+ ```
146
+
147
+ Don't know where to start? `prompteval scorer list` shows 6–8 templates (regex match, JSON-schema valid, contains-substring, exact-match, LLM-judge factuality, LLM-judge tone). `prompteval scorer copy <name>` drops one into your `eval.py`.
148
+
149
+ > **Honest caveat that matters:** prompteval doesn't define quality for your business — you do, by writing scorers. Get this part right and the tool earns its keep. Get it wrong and the tool will tell you wrong things confidently. **Every report shows which scorers ran on how many examples — methodology is always visible.** See [docs/writing-scorers.md](docs/writing-scorers.md) (coming v0.1) for guidance.
150
+
151
+ ### 5. Run baseline (v1)
152
+
153
+ ```bash
154
+ prompteval run --prompt prompts/v1.txt --tag baseline
155
+ ```
156
+
157
+ ```
158
+ Running 20 examples × 1 prompt against gpt-4o...
159
+ refund-1 ✓ mentions_required_terms=1.00 professional_tone=0.85
160
+ refund-2 ✓ mentions_required_terms=0.50 professional_tone=0.90
161
+ ...
162
+ === baseline ===
163
+ mentions_required_terms: 0.84 (n=20)
164
+ professional_tone: 0.81 (n=20)
165
+ total cost: $0.158 (avg $0.0079/call)
166
+ avg latency: 1.4s
167
+ saved to: .prompteval/runs/baseline-2026-06-26T1240.json
168
+ ```
169
+
170
+ ### 6. Run the variant (v2)
171
+
172
+ ```bash
173
+ prompteval run --prompt prompts/v2.txt --tag short-prompt
174
+ ```
175
+
176
+ ### 7. Compare — the moment of truth
177
+
178
+ ```bash
179
+ prompteval compare baseline short-prompt
180
+ ```
181
+
182
+ You get the report shown at the top of this README — paired quality and cost deltas with 95% CIs, p-values, and a plain-English recommendation.
183
+
184
+ ### 8. (Optional but the moat) Lock it into CI
185
+
186
+ A copy-and-paste GitHub Actions workflow lives at [`examples/github-actions/prompteval.yml`](examples/github-actions/prompteval.yml). The core of it:
187
+
188
+ ```yaml
189
+ - run: prompteval run --prompt /tmp/baseline.txt --tag baseline
190
+ - run: prompteval run --prompt evals/prompts/v1.txt --tag candidate
191
+ - run: prompteval compare baseline candidate --html report.html --fail-on cost+10%,quality-5%
192
+ ```
193
+
194
+ Any future prompt change gets gated. PR fails if cost regresses >10% or any
195
+ scorer drops >5 percentage points (only statistically significant breaches
196
+ trip the gate). The `--html` report is uploaded as a build artifact and
197
+ linked from the PR's Checks tab.
198
+
199
+ See [`examples/github-actions/README.md`](examples/github-actions/README.md)
200
+ for setup steps, required secrets, and how to tune the gate.
201
+
202
+ ---
203
+
204
+ ## Status, scope, and roadmap
205
+
206
+ Living source of truth lives in **[IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md)** —
207
+ week-by-week status table, decisions log, explicit non-goals, and post-v1 roadmap.
208
+ That file is updated the same commit any code ships; this README only summarises.
209
+
210
+ **As of 31 Aug 2026 — the tool works end to end.** Everything needed to run a
211
+ comparison has shipped and is tested: `init`, `run`, `compare`, `models` and
212
+ `scorer` CLIs; the cost model; 9 stock scorers plus `llm_judge`; paired deltas
213
+ with bootstrap CIs and significance; plain-English verdicts; the HTML report;
214
+ and the `--fail-on` CI gate with a GitHub Actions template. **210/210 tests
215
+ green.**
216
+
217
+ **What is left is packaging, not capability:** a scorer-writing guide, an API
218
+ stability sweep, and the first PyPI release (as `prompteval-delta`). Until that
219
+ release is live, install from source — and treat the public API as still
220
+ movable.
221
+
222
+ Original plan was 10 weeks with a 2026-08-16 review point. That date has passed
223
+ with the build ahead of where it needed to be, so the project continues; the
224
+ week-by-week table in the plan is the live record.
225
+
226
+ ---
227
+
228
+ ## Development
229
+
230
+ ```bash
231
+ # Install (creates a venv via uv, pulls Python 3.12)
232
+ uv sync
233
+
234
+ # Full quality gate
235
+ uv run ruff check . # lint
236
+ uv run ruff format --check . # format
237
+ uv run mypy src tests # types (strict)
238
+ uv run pytest # tests
239
+ uv run prompteval --version # CLI smoke
240
+
241
+ # One-liner
242
+ uv run pytest && uv run mypy src tests && uv run ruff check .
243
+ ```
244
+
245
+ ## License
246
+
247
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,219 @@
1
+ # prompteval
2
+
3
+ **Paired cost-and-quality delta reports for LLM prompts — so you can ship the cheaper version without guessing.**
4
+
5
+ > _Did your prompt change save money without losing quality?_
6
+
7
+ prompteval is **pytest for LLM prompts**. You define a small golden test set and one or more scorers. You run it against your v1 prompt, then your v2 prompt, then ask it to compare. You get back a single report:
8
+
9
+ ```
10
+ v1 v2 Δ 95% CI p
11
+ ─────────────────────────────────────────────────────────────────────────────
12
+ mentions_required_terms 0.84 0.79 −0.05 [−0.13, +0.03] 0.21
13
+ professional_tone 0.81 0.83 +0.02 [−0.05, +0.09] 0.58
14
+ ─────────────────────────────────────────────────────────────────────────────
15
+ total cost $0.158 $0.099 −37% [−42%, −32%] <0.001
16
+ avg latency 1.4s 1.1s −21% [−28%, −14%] <0.001
17
+
18
+ Quality verdict: no significant regression
19
+ Cost verdict: significant 37% reduction
20
+ Recommendation: ship v2 — cost savings real, quality holds
21
+ ```
22
+
23
+ Existing eval tools (Braintrust, Langfuse, promptfoo, Phoenix) track cost as a metric you graph; prompteval treats it as a **comparison axis** alongside quality. See [docs/competitor-scan.md](docs/competitor-scan.md) for verified evidence.
24
+
25
+ > ⚠️ **Alpha — v0.1.0.** The PyPI package is **`prompteval-delta`** (first
26
+ > release pending; until then, install from source). **Do not
27
+ > `pip install prompteval`** — that name on PyPI belongs to an unrelated
28
+ > project. The import and the command are still `prompteval`. The public API
29
+ > may still change before 1.0. Stars and issues welcome.
30
+
31
+ ---
32
+
33
+ ## What prompteval is, and is not
34
+
35
+ | ✅ It is | ❌ It is not |
36
+ |---|---|
37
+ | An **offline** eval framework (think pytest for prompts) | A runtime proxy or LLM gateway |
38
+ | Run from your CLI or your CI | Sitting in your prod request path |
39
+ | Compares two prompt versions on quality **and** cost | Caching prod LLM calls |
40
+ | Statistical significance built in | Replacing Helicone / Portkey / LiteLLM |
41
+ | Honest about scorer methodology | A black-box "AI judges your AI" |
42
+
43
+ **Closest neighbors:** pytest, [Braintrust Experiments](https://braintrust.dev/), [promptfoo](https://promptfoo.dev/), [Inspect AI](https://inspect.aisi.org.uk/).
44
+
45
+ **Not what we do:** [Helicone](https://helicone.ai/), [Portkey](https://portkey.ai/), [LiteLLM](https://github.com/BerriAI/litellm), [LangChain](https://langchain.com/).
46
+
47
+ ---
48
+
49
+ ## User journey (v1)
50
+
51
+ Eight steps. ~30 minutes the first time. ~5 minutes every time after.
52
+
53
+ ### 1. Install
54
+
55
+ ```bash
56
+ uv add prompteval-delta # or: pip install prompteval-delta
57
+ prompteval --version
58
+ ```
59
+
60
+ ### 2. Bootstrap an evals folder
61
+
62
+ ```bash
63
+ cd ~/my-app
64
+ prompteval init
65
+ ```
66
+
67
+ Creates:
68
+ ```
69
+ evals/
70
+ ├── prompts/
71
+ │ ├── v1.txt # paste your current prompt
72
+ │ └── v2.txt # paste the variant you want to test
73
+ ├── dataset.jsonl # one example pre-filled
74
+ ├── eval.py # pre-filled with 3 scorer examples
75
+ └── .env.example # OPENAI_API_KEY=...
76
+ ```
77
+
78
+ ### 3. Bring your prompts + a few examples
79
+
80
+ Paste prompts into `prompts/v1.txt` and `prompts/v2.txt`. Add 10–30 examples to `dataset.jsonl`:
81
+
82
+ ```jsonl
83
+ {"id": "refund-1", "input": "My item arrived broken, refund please", "expected": {"must_mention": ["30-day refund"], "tone": "empathetic"}}
84
+ {"id": "refund-2", "input": "Refund request 45 days after purchase", "expected": {"must_mention": ["30-day", "outside policy"], "tone": "polite"}}
85
+ ```
86
+
87
+ The `expected` field is whatever your scorers want — there's no fixed schema.
88
+
89
+ ### 4. Define what "good" means for your use case (scorers)
90
+
91
+ `eval.py` ships with three example scorers. Edit them, write new ones, or copy from templates:
92
+
93
+ ```python
94
+ from prompteval import Eval, scorer, llm_judge
95
+
96
+ @scorer
97
+ def mentions_required_terms(output: str, expected: dict) -> float:
98
+ """Hard scorer: did the reply contain required phrases?"""
99
+ must = expected.get("must_mention", [])
100
+ if not must:
101
+ return 1.0
102
+ return sum(1 for t in must if t.lower() in output.lower()) / len(must)
103
+
104
+ @scorer
105
+ def professional_tone(output: str, expected: dict) -> float:
106
+ """LLM-as-judge: rate professionalism 0-1."""
107
+ return llm_judge(
108
+ rubric="Rate the tone of this support reply 0-1. 1=empathetic+professional, 0=rude.",
109
+ text=output,
110
+ )
111
+
112
+ eval = Eval(
113
+ name="support-assistant",
114
+ dataset="dataset.jsonl",
115
+ scorers=[mentions_required_terms, professional_tone],
116
+ )
117
+ ```
118
+
119
+ Don't know where to start? `prompteval scorer list` shows 6–8 templates (regex match, JSON-schema valid, contains-substring, exact-match, LLM-judge factuality, LLM-judge tone). `prompteval scorer copy <name>` drops one into your `eval.py`.
120
+
121
+ > **Honest caveat that matters:** prompteval doesn't define quality for your business — you do, by writing scorers. Get this part right and the tool earns its keep. Get it wrong and the tool will tell you wrong things confidently. **Every report shows which scorers ran on how many examples — methodology is always visible.** See [docs/writing-scorers.md](docs/writing-scorers.md) (coming v0.1) for guidance.
122
+
123
+ ### 5. Run baseline (v1)
124
+
125
+ ```bash
126
+ prompteval run --prompt prompts/v1.txt --tag baseline
127
+ ```
128
+
129
+ ```
130
+ Running 20 examples × 1 prompt against gpt-4o...
131
+ refund-1 ✓ mentions_required_terms=1.00 professional_tone=0.85
132
+ refund-2 ✓ mentions_required_terms=0.50 professional_tone=0.90
133
+ ...
134
+ === baseline ===
135
+ mentions_required_terms: 0.84 (n=20)
136
+ professional_tone: 0.81 (n=20)
137
+ total cost: $0.158 (avg $0.0079/call)
138
+ avg latency: 1.4s
139
+ saved to: .prompteval/runs/baseline-2026-06-26T1240.json
140
+ ```
141
+
142
+ ### 6. Run the variant (v2)
143
+
144
+ ```bash
145
+ prompteval run --prompt prompts/v2.txt --tag short-prompt
146
+ ```
147
+
148
+ ### 7. Compare — the moment of truth
149
+
150
+ ```bash
151
+ prompteval compare baseline short-prompt
152
+ ```
153
+
154
+ You get the report shown at the top of this README — paired quality and cost deltas with 95% CIs, p-values, and a plain-English recommendation.
155
+
156
+ ### 8. (Optional but the moat) Lock it into CI
157
+
158
+ A copy-and-paste GitHub Actions workflow lives at [`examples/github-actions/prompteval.yml`](examples/github-actions/prompteval.yml). The core of it:
159
+
160
+ ```yaml
161
+ - run: prompteval run --prompt /tmp/baseline.txt --tag baseline
162
+ - run: prompteval run --prompt evals/prompts/v1.txt --tag candidate
163
+ - run: prompteval compare baseline candidate --html report.html --fail-on cost+10%,quality-5%
164
+ ```
165
+
166
+ Any future prompt change gets gated. PR fails if cost regresses >10% or any
167
+ scorer drops >5 percentage points (only statistically significant breaches
168
+ trip the gate). The `--html` report is uploaded as a build artifact and
169
+ linked from the PR's Checks tab.
170
+
171
+ See [`examples/github-actions/README.md`](examples/github-actions/README.md)
172
+ for setup steps, required secrets, and how to tune the gate.
173
+
174
+ ---
175
+
176
+ ## Status, scope, and roadmap
177
+
178
+ Living source of truth lives in **[IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md)** —
179
+ week-by-week status table, decisions log, explicit non-goals, and post-v1 roadmap.
180
+ That file is updated the same commit any code ships; this README only summarises.
181
+
182
+ **As of 31 Aug 2026 — the tool works end to end.** Everything needed to run a
183
+ comparison has shipped and is tested: `init`, `run`, `compare`, `models` and
184
+ `scorer` CLIs; the cost model; 9 stock scorers plus `llm_judge`; paired deltas
185
+ with bootstrap CIs and significance; plain-English verdicts; the HTML report;
186
+ and the `--fail-on` CI gate with a GitHub Actions template. **210/210 tests
187
+ green.**
188
+
189
+ **What is left is packaging, not capability:** a scorer-writing guide, an API
190
+ stability sweep, and the first PyPI release (as `prompteval-delta`). Until that
191
+ release is live, install from source — and treat the public API as still
192
+ movable.
193
+
194
+ Original plan was 10 weeks with a 2026-08-16 review point. That date has passed
195
+ with the build ahead of where it needed to be, so the project continues; the
196
+ week-by-week table in the plan is the live record.
197
+
198
+ ---
199
+
200
+ ## Development
201
+
202
+ ```bash
203
+ # Install (creates a venv via uv, pulls Python 3.12)
204
+ uv sync
205
+
206
+ # Full quality gate
207
+ uv run ruff check . # lint
208
+ uv run ruff format --check . # format
209
+ uv run mypy src tests # types (strict)
210
+ uv run pytest # tests
211
+ uv run prompteval --version # CLI smoke
212
+
213
+ # One-liner
214
+ uv run pytest && uv run mypy src tests && uv run ruff check .
215
+ ```
216
+
217
+ ## License
218
+
219
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,104 @@
1
+ [project]
2
+ name = "prompteval-delta"
3
+ version = "0.1.0"
4
+ description = "LLM eval framework with first-class token-cost tracking. Did your prompt change save money without losing quality?"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ keywords = [
8
+ "llm",
9
+ "evaluation",
10
+ "evals",
11
+ "prompt-engineering",
12
+ "openai",
13
+ "gpt-4",
14
+ "cost-tracking",
15
+ "token-cost",
16
+ "ai-quality",
17
+ "regression-detection",
18
+ ]
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Developers",
22
+ "License :: OSI Approved :: MIT License",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
26
+ "Topic :: Software Development :: Quality Assurance",
27
+ "Topic :: Software Development :: Testing",
28
+ ]
29
+ dependencies = [
30
+ "openai>=1.50.0",
31
+ "click>=8.1.7",
32
+ "pydantic>=2.9.0",
33
+ "pyyaml>=6.0",
34
+ "numpy>=1.26",
35
+ "scipy>=1.13",
36
+ ]
37
+
38
+ [project.license]
39
+ text = "MIT"
40
+
41
+ [[project.authors]]
42
+ name = "Anuj Mahajan"
43
+ email = "mahajananuj07@gmail.com"
44
+
45
+ [project.urls]
46
+ Homepage = "https://github.com/mahAnuj/prompteval"
47
+ Repository = "https://github.com/mahAnuj/prompteval"
48
+ Issues = "https://github.com/mahAnuj/prompteval/issues"
49
+
50
+ [project.scripts]
51
+ prompteval = "prompteval.cli:main"
52
+
53
+ [dependency-groups]
54
+ dev = [
55
+ "mypy>=1.11.0",
56
+ "pytest>=8.3.0",
57
+ "pytest-asyncio>=0.24.0",
58
+ "ruff>=0.6.9",
59
+ "types-pyyaml>=6.0",
60
+ ]
61
+
62
+ [build-system]
63
+ requires = ["uv_build>=0.11.7,<0.12.0"]
64
+ build-backend = "uv_build"
65
+
66
+ [tool.uv.build-backend]
67
+ module-name = "prompteval"
68
+
69
+ [tool.ruff]
70
+ line-length = 100
71
+ target-version = "py312"
72
+ extend-exclude = ["src/prompteval/init/templates"]
73
+
74
+ [tool.ruff.lint]
75
+ select = [
76
+ "E",
77
+ "F",
78
+ "I",
79
+ "B",
80
+ "UP",
81
+ "SIM",
82
+ "RUF",
83
+ ]
84
+ ignore = []
85
+
86
+ [tool.ruff.lint.per-file-ignores]
87
+ "tests/**/*" = ["S101"]
88
+
89
+ [tool.mypy]
90
+ python_version = "3.12"
91
+ strict = true
92
+ warn_unreachable = true
93
+ pretty = true
94
+ show_error_codes = true
95
+ exclude = ["src/prompteval/init/templates/.*"]
96
+
97
+ [tool.pytest.ini_options]
98
+ testpaths = ["tests"]
99
+ addopts = [
100
+ "-ra",
101
+ "--strict-markers",
102
+ "--strict-config",
103
+ ]
104
+ asyncio_mode = "auto"
@@ -0,0 +1,106 @@
1
+ [project]
2
+ # Distribution name. "prompteval" on PyPI belongs to an unrelated project, so
3
+ # this one installs as prompteval-delta; the import and the CLI stay
4
+ # `prompteval` (module-name below).
5
+ name = "prompteval-delta"
6
+ version = "0.1.0"
7
+ description = "LLM eval framework with first-class token-cost tracking. Did your prompt change save money without losing quality?"
8
+ readme = "README.md"
9
+ license = { text = "MIT" }
10
+ authors = [{ name = "Anuj Mahajan", email = "mahajananuj07@gmail.com" }]
11
+ requires-python = ">=3.12"
12
+ keywords = [
13
+ "llm",
14
+ "evaluation",
15
+ "evals",
16
+ "prompt-engineering",
17
+ "openai",
18
+ "gpt-4",
19
+ "cost-tracking",
20
+ "token-cost",
21
+ "ai-quality",
22
+ "regression-detection",
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 3 - Alpha",
26
+ "Intended Audience :: Developers",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Programming Language :: Python :: 3.13",
30
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
31
+ "Topic :: Software Development :: Quality Assurance",
32
+ "Topic :: Software Development :: Testing",
33
+ ]
34
+ dependencies = [
35
+ "openai>=1.50.0",
36
+ "click>=8.1.7",
37
+ "pydantic>=2.9.0",
38
+ "pyyaml>=6.0",
39
+ "numpy>=1.26",
40
+ "scipy>=1.13",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/mahAnuj/prompteval"
45
+ Repository = "https://github.com/mahAnuj/prompteval"
46
+ Issues = "https://github.com/mahAnuj/prompteval/issues"
47
+
48
+ [project.scripts]
49
+ prompteval = "prompteval.cli:main"
50
+
51
+ [dependency-groups]
52
+ dev = [
53
+ "mypy>=1.11.0",
54
+ "pytest>=8.3.0",
55
+ "pytest-asyncio>=0.24.0",
56
+ "ruff>=0.6.9",
57
+ "types-pyyaml>=6.0",
58
+ ]
59
+
60
+ [build-system]
61
+ requires = ["uv_build>=0.11.7,<0.12.0"]
62
+ build-backend = "uv_build"
63
+
64
+ [tool.uv.build-backend]
65
+ # uv_build would otherwise look for a `prompteval_delta` module.
66
+ module-name = "prompteval"
67
+
68
+ # ---------- ruff ----------
69
+ [tool.ruff]
70
+ line-length = 100
71
+ target-version = "py312"
72
+ # Templates ship as resource files copied verbatim by `prompteval init`.
73
+ # They reference v0.1 public API that doesn't exist yet (Week 3-4 work),
74
+ # so linting them creates false positives. Treated as data, not code.
75
+ extend-exclude = ["src/prompteval/init/templates"]
76
+
77
+ [tool.ruff.lint]
78
+ # Start strict; prune later only if a rule is more noise than value.
79
+ select = [
80
+ "E", # pycodestyle errors
81
+ "F", # pyflakes
82
+ "I", # isort (import order)
83
+ "B", # bugbear (likely bugs)
84
+ "UP", # pyupgrade (modern syntax)
85
+ "SIM", # simplify
86
+ "RUF", # ruff-specific
87
+ ]
88
+ ignore = []
89
+
90
+ [tool.ruff.lint.per-file-ignores]
91
+ "tests/**/*" = ["S101"] # `assert` is fine in tests
92
+
93
+ # ---------- mypy ----------
94
+ [tool.mypy]
95
+ python_version = "3.12"
96
+ strict = true
97
+ warn_unreachable = true
98
+ pretty = true
99
+ show_error_codes = true
100
+ exclude = ["src/prompteval/init/templates/.*"]
101
+
102
+ # ---------- pytest ----------
103
+ [tool.pytest.ini_options]
104
+ testpaths = ["tests"]
105
+ addopts = ["-ra", "--strict-markers", "--strict-config"]
106
+ asyncio_mode = "auto"