|
1 | 1 | # ghostrun |
2 | 2 |
|
3 | | -> pytest for LLMs: deterministic HTTP record/replay, local LLM-as-judge semantic assertions, and prompt-version regression diffing for testing GenAI applications in Python. |
4 | | - |
5 | | -ghostrun solves two problems that make LLM applications hard to test with |
6 | | -ordinary `assert`: non-deterministic output (the same prompt returns different |
7 | | -text every run) and cost/latency (every test run would otherwise hit a paid, |
8 | | -slow API). It intercepts LLM provider HTTP calls at the transport layer |
9 | | -(httpx) — not by monkey-patching the OpenAI/Anthropic SDKs — so the first test |
10 | | -run records a real response and every run after replays it in milliseconds |
11 | | -with no API key, no network call, and no cost. Semantic assertions |
12 | | -(`ghostrun.expect(reply).contains_intent("apology")`) are graded by a judge — |
13 | | -by default a local Ollama model, so prompts and responses never leave the |
14 | | -machine — and judge verdicts are themselves cached with an optional |
15 | | -majority-of-k voting mode, benchmarked against a real judge rather than |
16 | | -assumed to work (see the benchmark write-up below). `ghostrun diff` compares |
17 | | -two recorded runs to flag which assertions regressed, which fixed, and which |
18 | | -LLM outputs drifted, even when they still pass. |
19 | | - |
20 | | -It is a Python package (`pip install ghostrun`), a pytest plugin (auto-registers |
21 | | -via the `pytest11` entry point, no conftest wiring needed), and a CLI |
22 | | -(`ghostrun list|show|diff|doctor|init`). It is not a hosted SaaS, not an |
23 | | -observability platform, and not a cross-model benchmarking tool — see the |
24 | | -comparison document below for how it relates to DeepEval, Promptfoo, Ragas, |
25 | | -vcr-langchain, and other tools in this space. |
| 3 | +> CI-native LLM evals for real applications: record LLM API calls once, replay them deterministically in pytest, and catch semantic regressions before they ship. |
| 4 | + |
| 5 | +ghostrun is a Python package, pytest plugin, and CLI for app-native LLM regression testing. It is built for developers who want LLM evals inside the software test suite instead of a separate dataset, dashboard, YAML workflow, or one-off script. |
| 6 | + |
| 7 | +ghostrun tests the real Python code path your users hit. The first run records live OpenAI, Anthropic, Gemini, Bedrock, Ollama, or other LLM provider HTTP calls at the transport layer. Later runs replay those calls deterministically in pytest and CI, so evals are fast, repeatable, and cheap enough to run on every pull request. |
| 8 | + |
| 9 | +Important search phrases: LLM evals in CI, LLM regression testing, pytest LLM evals, deterministic LLM tests, prompt regression testing, semantic assertions for LLM apps, testing OpenAI apps with pytest, testing Anthropic apps with pytest, app-native LLM evals, GenAI testing, AI testing, prompt testing, and record/replay LLM API calls. |
| 10 | + |
| 11 | +Semantic assertions such as `ghostrun.expect(reply).contains_intent("apology")` grade meaning rather than exact text. Judge verdicts are cached, and optional majority-of-k voting is available for higher-signal semantic checks. `ghostrun diff` compares recorded runs to flag assertion regressions, fixes, stable checks, removed checks, and LLM output drift. |
| 12 | + |
| 13 | +ghostrun is not a hosted SaaS, not an observability platform, and not a cross-model leaderboard. Compared with DeepEval, Promptfoo, Ragas, Langfuse, Braintrust, and LangSmith, ghostrun's focused wedge is app-native regression evals in normal pytest: real code, real LLM calls, deterministic replay, semantic assertions, and CI-friendly failure output. |
26 | 14 |
|
27 | 15 | ## Core documentation |
28 | 16 |
|
29 | | -- [README](README.md): what it is, install, quickstart, documentation index |
30 | | -- [Recording and replay](doc/guide/recording.md): HTTP-transport interception, judge-verdict caching, supported providers, secret redaction, parallel test runs |
31 | | -- [Semantic assertions](doc/guide/assertions.md): `expect()` API, measured judge reliability (~90% on hand-labeled cases), majority-vote verdicts, tool-call assertions |
32 | | -- [Prompt regression tracking](doc/guide/regression-tracking.md): run snapshots, `ghostrun diff`, CI/PR integration (GitHub Actions, JUnit XML) |
| 17 | +- [README](README.md): install, quickstart, positioning, and documentation index |
| 18 | +- [LLM regression testing](site/guide/llm-regression-testing.html): CI-native LLM evals for catching semantic and prompt regressions in real app code |
| 19 | +- [Pytest LLM evals](site/guide/pytest-llm-evals.html): write LLM evals as normal pytest tests |
| 20 | +- [Test OpenAI apps offline](site/guide/test-openai-apps-offline.html): record/replay OpenAI and Anthropic API calls so CI does not repeat live model calls |
| 21 | +- [Recording and replay](doc/guide/recording.md): HTTP transport interception, judge-verdict caching, supported providers, secret redaction, parallel test runs |
| 22 | +- [Semantic assertions](doc/guide/assertions.md): `expect()` API, judge reliability, majority-vote verdicts, tool-call assertions |
| 23 | +- [Prompt regression tracking](doc/guide/regression-tracking.md): run snapshots, `ghostrun diff`, CI/PR integration, GitHub Actions, JUnit XML |
33 | 24 | - [Configuration](doc/guide/configuration.md): `.ghostrun.yaml`, environment variables, `ghostrun doctor`, `ghostrun init` |
34 | 25 | - [API reference](doc/guide/api-reference.md): every public function, class, and config field |
35 | 26 |
|
36 | 27 | ## Research and rationale |
37 | 28 |
|
38 | | -- [Why not just ask an LLM to write this?](doc/guide/why-not-diy.md): concrete bugs found in this project's own development (thread-safety races, secret-redaction false positives, non-monotonic majority voting) as the case for a maintained package over a generated script |
39 | | -- [Judge-voting benchmark](doc/judge-voting-benchmark.md): full methodology and results for whether majority-vote judge caching actually improves reliability (answer: it's a better detector of unreliable assertions than a fix for them) |
40 | | -- [Comparison with other tools](doc/comparison.md): researched, sourced comparison against DeepEval, Promptfoo, Ragas, vcr-langchain, Langfuse, Braintrust, LangSmith, Giskard, and others |
41 | | - |
42 | | -## Project status |
43 | | - |
44 | | -- [Changelog](CHANGELOG.md): release notes |
| 29 | +- [Why not just ask an LLM to write this?](doc/guide/why-not-diy.md): concrete bugs found in this project's own development |
| 30 | +- [Judge-voting benchmark](doc/judge-voting-benchmark.md): methodology and results for majority-vote judge caching |
| 31 | +- [Comparison with other tools](doc/comparison.md): sourced comparison against DeepEval, Promptfoo, Ragas, vcr-langchain, Langfuse, Braintrust, LangSmith, Giskard, and others |
45 | 32 |
|
46 | | -## Optional |
| 33 | +## Project links |
47 | 34 |
|
48 | | -- [Bundled example](examples/README.md): a runnable customer-support test with a pre-recorded cache, plus a live-API smoke test |
| 35 | +- Website: https://ghostrun.parthmax.in |
| 36 | +- Source: https://github.com/parthmax2/ghostrun |
| 37 | +- PyPI: https://pypi.org/project/ghostrun/ |
| 38 | +- Changelog: CHANGELOG.md |
| 39 | +- License: MIT |
0 commit comments