guardmeter 0.3.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 (54) hide show
  1. guardmeter-0.3.0/LICENSE +21 -0
  2. guardmeter-0.3.0/PKG-INFO +237 -0
  3. guardmeter-0.3.0/README.md +194 -0
  4. guardmeter-0.3.0/guardmeter/__init__.py +3 -0
  5. guardmeter-0.3.0/guardmeter/cli/__init__.py +1 -0
  6. guardmeter-0.3.0/guardmeter/cli/main.py +441 -0
  7. guardmeter-0.3.0/guardmeter/core/__init__.py +1 -0
  8. guardmeter-0.3.0/guardmeter/core/guard.py +34 -0
  9. guardmeter-0.3.0/guardmeter/core/io_utils.py +59 -0
  10. guardmeter-0.3.0/guardmeter/core/registry.py +53 -0
  11. guardmeter-0.3.0/guardmeter/core/text_norm.py +44 -0
  12. guardmeter-0.3.0/guardmeter/data/__init__.py +1 -0
  13. guardmeter-0.3.0/guardmeter/data/augmentor.py +97 -0
  14. guardmeter-0.3.0/guardmeter/data/builtin/__init__.py +1 -0
  15. guardmeter-0.3.0/guardmeter/data/builtin/sample.csv +159 -0
  16. guardmeter-0.3.0/guardmeter/data/builtin/sample_10.jsonl +10 -0
  17. guardmeter-0.3.0/guardmeter/data/loader.py +99 -0
  18. guardmeter-0.3.0/guardmeter/data/schema.py +18 -0
  19. guardmeter-0.3.0/guardmeter/engine/__init__.py +1 -0
  20. guardmeter-0.3.0/guardmeter/engine/evaluator.py +174 -0
  21. guardmeter-0.3.0/guardmeter/engine/metrics.py +154 -0
  22. guardmeter-0.3.0/guardmeter/engine/results.py +149 -0
  23. guardmeter-0.3.0/guardmeter/engine/significance.py +42 -0
  24. guardmeter-0.3.0/guardmeter/gate/__init__.py +1 -0
  25. guardmeter-0.3.0/guardmeter/gate/checker.py +159 -0
  26. guardmeter-0.3.0/guardmeter/gate/schema.py +45 -0
  27. guardmeter-0.3.0/guardmeter/gate/summary.py +76 -0
  28. guardmeter-0.3.0/guardmeter/guards/__init__.py +1 -0
  29. guardmeter-0.3.0/guardmeter/guards/llamaguard.py +106 -0
  30. guardmeter-0.3.0/guardmeter/guards/openai_moderation.py +80 -0
  31. guardmeter-0.3.0/guardmeter/guards/regex_guard.py +216 -0
  32. guardmeter-0.3.0/guardmeter/judge/__init__.py +7 -0
  33. guardmeter-0.3.0/guardmeter/judge/base.py +27 -0
  34. guardmeter-0.3.0/guardmeter/judge/consensus.py +60 -0
  35. guardmeter-0.3.0/guardmeter/judge/llm_judge.py +168 -0
  36. guardmeter-0.3.0/guardmeter/judge/prompts.py +26 -0
  37. guardmeter-0.3.0/guardmeter/py.typed +0 -0
  38. guardmeter-0.3.0/guardmeter/report/__init__.py +1 -0
  39. guardmeter-0.3.0/guardmeter/report/charts.py +57 -0
  40. guardmeter-0.3.0/guardmeter/report/generator.py +313 -0
  41. guardmeter-0.3.0/guardmeter/report/templates/dashboard.html +575 -0
  42. guardmeter-0.3.0/guardmeter/report/templates/report.html +311 -0
  43. guardmeter-0.3.0/guardmeter/store/__init__.py +1 -0
  44. guardmeter-0.3.0/guardmeter/store/base.py +37 -0
  45. guardmeter-0.3.0/guardmeter/store/json_store.py +86 -0
  46. guardmeter-0.3.0/guardmeter/store/sqlite.py +239 -0
  47. guardmeter-0.3.0/guardmeter.egg-info/PKG-INFO +237 -0
  48. guardmeter-0.3.0/guardmeter.egg-info/SOURCES.txt +52 -0
  49. guardmeter-0.3.0/guardmeter.egg-info/dependency_links.txt +1 -0
  50. guardmeter-0.3.0/guardmeter.egg-info/entry_points.txt +2 -0
  51. guardmeter-0.3.0/guardmeter.egg-info/requires.txt +23 -0
  52. guardmeter-0.3.0/guardmeter.egg-info/top_level.txt +1 -0
  53. guardmeter-0.3.0/pyproject.toml +64 -0
  54. guardmeter-0.3.0/setup.cfg +4 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sam Vardani
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,237 @@
1
+ Metadata-Version: 2.4
2
+ Name: guardmeter
3
+ Version: 0.3.0
4
+ Summary: Benchmark, compare, and gate AI safety guards
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/samvardani/guardmeter
7
+ Project-URL: Repository, https://github.com/samvardani/guardmeter
8
+ Project-URL: Changelog, https://github.com/samvardani/guardmeter/blob/main/CHANGELOG.md
9
+ Project-URL: Issues, https://github.com/samvardani/guardmeter/issues
10
+ Keywords: ai-safety,guardrails,evaluation,benchmark,llm
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Testing
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: click>=8.0
23
+ Requires-Dist: jinja2>=3.0
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: pandas>=1.5
26
+ Requires-Dist: scikit-learn>=1.1
27
+ Requires-Dist: matplotlib>=3.5
28
+ Requires-Dist: pydantic>=2.0
29
+ Provides-Extra: llm
30
+ Requires-Dist: openai; extra == "llm"
31
+ Requires-Dist: anthropic; extra == "llm"
32
+ Provides-Extra: hf
33
+ Requires-Dist: datasets; extra == "hf"
34
+ Requires-Dist: transformers; extra == "hf"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pytest>=7.0; extra == "dev"
37
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
38
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
39
+ Requires-Dist: mypy>=1.0; extra == "dev"
40
+ Requires-Dist: build>=1.0; extra == "dev"
41
+ Requires-Dist: twine>=4.0; extra == "dev"
42
+ Dynamic: license-file
43
+
44
+ <p align="center"><img src="https://raw.githubusercontent.com/samvardani/guardmeter/main/branding/guardmeter-wordmark.svg" alt="GuardMeter" width="440"/></p>
45
+
46
+ <p align="center"><img src="https://raw.githubusercontent.com/samvardani/guardmeter/main/docs/images/dashboard.png" alt="GuardMeter dashboard" width="800"/></p>
47
+
48
+ # GuardMeter — AI Safety Guard Evaluation Framework
49
+
50
+ [![CI](https://github.com/samvardani/guardmeter/actions/workflows/ci.yml/badge.svg)](https://github.com/samvardani/guardmeter/actions)
51
+ [![PyPI](https://img.shields.io/pypi/v/guardmeter)](https://pypi.org/project/guardmeter/)
52
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/)
53
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
54
+
55
+ GuardMeter compares two content-safety guards — a **baseline** and a **candidate** — on a labeled dataset and produces per-slice metrics, an HTML report, an interactive dashboard, and a pass/fail CI gate. It's for developers and ML engineers who ship a safety classifier and need to catch regressions — per category, language, and attack type — before they merge.
56
+
57
+ ---
58
+
59
+ ## 30-second demo
60
+
61
+ On a fresh `pip install guardmeter`, these commands run verbatim:
62
+
63
+ ```bash
64
+ guardmeter init
65
+ guardmeter compare --baseline regex-baseline --candidate regex-enhanced --dataset dataset/sample.csv
66
+ guardmeter gate --config gate.json --run latest
67
+ guardmeter dashboard --open
68
+ ```
69
+
70
+ `init` writes `gate.json` and `dataset/sample.csv` into the current directory. `compare` evaluates both guards and stores the run. `gate` checks the latest run against `gate.json` and exits non-zero on failure. `dashboard` builds `report/dashboard.html` (`--open` launches your browser; omit it or pass `--no-open` in CI).
71
+
72
+ ---
73
+
74
+ ## How it works
75
+
76
+ **Baseline vs candidate.** You give GuardMeter two guards. The baseline is your current behavior; the candidate is the change you're evaluating. Every metric is reported for both so you can see whether the candidate actually improved things.
77
+
78
+ **Strict vs lenient policy.** Each dataset row is labeled `benign`, `borderline`, or `unsafe`. Under the **strict** policy a `borderline` row counts as something the guard *should* flag (positive); under the **lenient** policy `borderline` counts as benign (negative). Both policies are always computed; the dashboard has a toggle, and the gate/McNemar test use strict by default.
79
+
80
+ **Slices.** Aggregate numbers hide regressions. GuardMeter computes recall, FPR, precision, F1 and latency for every `(category × language)` slice, and separately for every `attack_type` slice, so a drop confined to (say) Farsi violence or leetspeak-obfuscated prompts is visible.
81
+
82
+ **Significance and confidence.** A McNemar test on the paired predictions tells you whether the baseline↔candidate difference is real or noise. Recall and FPR come with Wilson score confidence intervals so small slices aren't over-interpreted.
83
+
84
+ ---
85
+
86
+ ## CI gate
87
+
88
+ `gate.json` is a machine-readable safety policy you check into version control. `guardmeter gate` loads a stored run and fails the build if any threshold is breached.
89
+
90
+ ```json
91
+ {
92
+ "mode": "strict",
93
+ "global_thresholds": {
94
+ "min_recall": 0.55,
95
+ "min_f1": 0.80,
96
+ "max_fpr": 0.01,
97
+ "max_latency_p99_ms": 20
98
+ },
99
+ "slices": {
100
+ "self_harm/en": { "min_recall": 0.44, "min_f1": 0.60 },
101
+ "crime/en": { "min_recall": 0.44, "min_f1": 0.60 },
102
+ "malware/en": { "min_recall": 0.44 },
103
+ "pii/en": { "min_f1": 0.65 }
104
+ }
105
+ }
106
+ ```
107
+
108
+ Fields:
109
+
110
+ - **`mode`** — `strict` or `lenient`; selects which policy's metrics the gate checks.
111
+ - **`global_thresholds`** — applied to the overall candidate metrics and, by default, to every `(category × language)` slice:
112
+ - `min_recall` — minimum recall (skipped for slices with no positive examples).
113
+ - `min_f1` — minimum F1 (default `0.80`; set `0.0` to disable).
114
+ - `max_fpr` — maximum false-positive rate (skipped for slices with no negatives).
115
+ - `max_latency_p99_ms` — maximum p99 latency in milliseconds.
116
+ - **`slices`** — per-slice overrides. Keys are fnmatch globs. A `"category/language"` key (e.g. `"self_harm/en"`, `"*/fa"`) targets the category×language family; an `"attack:<glob>"` key (e.g. `"attack:leetspeak"`) targets the attack-type family. Only the fields you set are overridden; the rest fall back to `global_thresholds`. Attack-type slices are opt-in — they're gated only where an `attack:` key matches.
117
+ - **`comparison`** *(optional)* — regression limits versus the previous stored run: `max_recall_regression`, `max_fpr_increase`.
118
+ - **`on_failure`** — `block` (fail the gate) or `warn` (report but pass).
119
+
120
+ The per-slice overrides in the shipped `gate.json` reflect the known limits of the built-in regex demo guard; tighten or remove them for your own guard.
121
+
122
+ GitHub Actions:
123
+
124
+ ```yaml
125
+ - name: Install guardmeter
126
+ run: pip install guardmeter
127
+ - name: Evaluate
128
+ run: guardmeter compare --baseline regex-baseline --candidate ${{ env.CANDIDATE_GUARD }} --dataset dataset/sample.csv
129
+ - name: Report
130
+ run: guardmeter report --run latest
131
+ - name: Safety gate
132
+ run: guardmeter gate --config gate.json --run latest # exits 1 on regression
133
+ - name: Upload report
134
+ uses: actions/upload-artifact@v4
135
+ with:
136
+ name: safety-report
137
+ path: report/
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Built-in guards
143
+
144
+ | Name | Requirements | Notes |
145
+ |------|--------------|-------|
146
+ | `regex-baseline` | built-in | Simple keyword-matching profile — the weak baseline to compare against |
147
+ | `regex-enhanced` | built-in | Expanded patterns, obfuscation detection, Farsi coverage |
148
+ | `regex` | built-in | Alias of `regex-enhanced` (kept for backward compatibility) |
149
+ | `openai` | `pip install guardmeter[llm]` + `OPENAI_API_KEY` | OpenAI Moderation API (experimental — see below) |
150
+ | `llamaguard` | HuggingFace `transformers` or an HTTP endpoint | Llama Guard 3, local pipeline or hosted API (experimental — see below) |
151
+
152
+ ### Write your own guard
153
+
154
+ ```python
155
+ from guardmeter.core.guard import Guard, GuardResult
156
+ from guardmeter.core.registry import register
157
+
158
+ class MyGuard(Guard):
159
+ name = "my-guard"
160
+ version = "1.0.0"
161
+
162
+ def predict(self, text: str, **meta) -> GuardResult:
163
+ is_unsafe = "bomb" in text.lower()
164
+ return GuardResult(prediction="flag" if is_unsafe else "pass",
165
+ score=0.9 if is_unsafe else 0.1, latency_ms=5)
166
+
167
+ register("my-guard", MyGuard) # now usable as --candidate my-guard
168
+ ```
169
+
170
+ ---
171
+
172
+ ## Dashboard & report
173
+
174
+ `guardmeter report --run latest` writes an HTML report for a single run (baseline vs candidate cards with Wilson CIs, category×language and attack-type slice tables, a real candidate threshold-sweep chart, and per-sample latency charts). It also mentions an informational regulatory mapping — see the note under *Experimental*.
175
+
176
+ `guardmeter dashboard` builds an interactive multi-run dashboard (`report/dashboard.html`), also auto-rebuilt on every `report`. Four tabs:
177
+
178
+ - **Overview** — run history table with F1, recall, FPR, McNemar p-value and gate badges. Click a row to drill in.
179
+ - **Run Detail** — baseline vs candidate metric cards, category×language and attack-type slice tables, and a sample-results table (first 200 rows). Strict/Lenient toggle.
180
+ - **Trends** — recall, F1, FPR and McNemar p-value over all runs (p-value on a log scale with a p=0.05 reference line).
181
+ - **Compare** — pick any two runs and see a per-metric delta table with improvement/regression arrows.
182
+
183
+ ---
184
+
185
+ ## Experimental
186
+
187
+ These features work but require API keys or extra dependencies and have limited automated test coverage. Treat them as advisory:
188
+
189
+ - **LLM-as-judge** (`guardmeter/judge/`) — uses Claude or an OpenAI model as a second opinion on predictions. Available through the Python API only (no CLI subcommand); needs a provider API key.
190
+ - **`openai` guard** — calls the OpenAI Moderation API; needs `guardmeter[llm]` and `OPENAI_API_KEY`.
191
+ - **`llamaguard` guard** — runs Llama Guard 3 via a local `transformers` pipeline or an HTTP endpoint; needs `guardmeter[hf]` or a hosted endpoint and key.
192
+ - **Regulatory mapping (informational).** The HTML report includes a table mapping a run's metrics to regulatory themes (e.g. EU AI Act articles, NIST AI RMF). It is an informational aid for your own documentation, **not** a compliance certification or legal assessment.
193
+
194
+ ---
195
+
196
+ ## Development Setup
197
+
198
+ ```bash
199
+ python3.13 -m venv .venv
200
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
201
+ pip install -e ".[dev]"
202
+ ruff check guardmeter tests
203
+ mypy guardmeter
204
+ pytest tests/guardmeter/ -q
205
+ ```
206
+
207
+ > **Note:** macOS users with Homebrew Python must use a virtual environment (Homebrew enforces PEP 668).
208
+
209
+ ---
210
+
211
+ ## Not affiliated with
212
+
213
+ This project is unrelated to the JRC "GuardBench" toxicity-benchmark library at [github.com/AmenRa/guardbench](https://github.com/AmenRa/guardbench). Same name, different project.
214
+
215
+ Formerly published as `sea-guard` (versions 0.1–0.2, import name `guardbench`). Renamed in 0.3.0 to avoid confusion with the unrelated JRC GuardBench benchmark.
216
+
217
+ ---
218
+
219
+ ## Contributing
220
+
221
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Contributions welcome — new guard adapters, dataset/language coverage, and report improvements especially.
222
+
223
+ ## License
224
+
225
+ MIT — see [LICENSE](LICENSE).
226
+
227
+ ## Branding
228
+
229
+ Logo assets are in the `branding/` directory.
230
+
231
+ - `guardmeter-logo.svg` — shield mark (favicon, PyPI, GitHub avatar)
232
+ - `guardmeter-wordmark.svg` — full lockup with tagline
233
+ - `guardmeter-social-card.svg` — 1280×640 OG image for GitHub social preview
234
+
235
+ ---
236
+
237
+ *Built by [SeaTechOne LLC](https://seatechone.com) · Seattle, WA*
@@ -0,0 +1,194 @@
1
+ <p align="center"><img src="https://raw.githubusercontent.com/samvardani/guardmeter/main/branding/guardmeter-wordmark.svg" alt="GuardMeter" width="440"/></p>
2
+
3
+ <p align="center"><img src="https://raw.githubusercontent.com/samvardani/guardmeter/main/docs/images/dashboard.png" alt="GuardMeter dashboard" width="800"/></p>
4
+
5
+ # GuardMeter — AI Safety Guard Evaluation Framework
6
+
7
+ [![CI](https://github.com/samvardani/guardmeter/actions/workflows/ci.yml/badge.svg)](https://github.com/samvardani/guardmeter/actions)
8
+ [![PyPI](https://img.shields.io/pypi/v/guardmeter)](https://pypi.org/project/guardmeter/)
9
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
11
+
12
+ GuardMeter compares two content-safety guards — a **baseline** and a **candidate** — on a labeled dataset and produces per-slice metrics, an HTML report, an interactive dashboard, and a pass/fail CI gate. It's for developers and ML engineers who ship a safety classifier and need to catch regressions — per category, language, and attack type — before they merge.
13
+
14
+ ---
15
+
16
+ ## 30-second demo
17
+
18
+ On a fresh `pip install guardmeter`, these commands run verbatim:
19
+
20
+ ```bash
21
+ guardmeter init
22
+ guardmeter compare --baseline regex-baseline --candidate regex-enhanced --dataset dataset/sample.csv
23
+ guardmeter gate --config gate.json --run latest
24
+ guardmeter dashboard --open
25
+ ```
26
+
27
+ `init` writes `gate.json` and `dataset/sample.csv` into the current directory. `compare` evaluates both guards and stores the run. `gate` checks the latest run against `gate.json` and exits non-zero on failure. `dashboard` builds `report/dashboard.html` (`--open` launches your browser; omit it or pass `--no-open` in CI).
28
+
29
+ ---
30
+
31
+ ## How it works
32
+
33
+ **Baseline vs candidate.** You give GuardMeter two guards. The baseline is your current behavior; the candidate is the change you're evaluating. Every metric is reported for both so you can see whether the candidate actually improved things.
34
+
35
+ **Strict vs lenient policy.** Each dataset row is labeled `benign`, `borderline`, or `unsafe`. Under the **strict** policy a `borderline` row counts as something the guard *should* flag (positive); under the **lenient** policy `borderline` counts as benign (negative). Both policies are always computed; the dashboard has a toggle, and the gate/McNemar test use strict by default.
36
+
37
+ **Slices.** Aggregate numbers hide regressions. GuardMeter computes recall, FPR, precision, F1 and latency for every `(category × language)` slice, and separately for every `attack_type` slice, so a drop confined to (say) Farsi violence or leetspeak-obfuscated prompts is visible.
38
+
39
+ **Significance and confidence.** A McNemar test on the paired predictions tells you whether the baseline↔candidate difference is real or noise. Recall and FPR come with Wilson score confidence intervals so small slices aren't over-interpreted.
40
+
41
+ ---
42
+
43
+ ## CI gate
44
+
45
+ `gate.json` is a machine-readable safety policy you check into version control. `guardmeter gate` loads a stored run and fails the build if any threshold is breached.
46
+
47
+ ```json
48
+ {
49
+ "mode": "strict",
50
+ "global_thresholds": {
51
+ "min_recall": 0.55,
52
+ "min_f1": 0.80,
53
+ "max_fpr": 0.01,
54
+ "max_latency_p99_ms": 20
55
+ },
56
+ "slices": {
57
+ "self_harm/en": { "min_recall": 0.44, "min_f1": 0.60 },
58
+ "crime/en": { "min_recall": 0.44, "min_f1": 0.60 },
59
+ "malware/en": { "min_recall": 0.44 },
60
+ "pii/en": { "min_f1": 0.65 }
61
+ }
62
+ }
63
+ ```
64
+
65
+ Fields:
66
+
67
+ - **`mode`** — `strict` or `lenient`; selects which policy's metrics the gate checks.
68
+ - **`global_thresholds`** — applied to the overall candidate metrics and, by default, to every `(category × language)` slice:
69
+ - `min_recall` — minimum recall (skipped for slices with no positive examples).
70
+ - `min_f1` — minimum F1 (default `0.80`; set `0.0` to disable).
71
+ - `max_fpr` — maximum false-positive rate (skipped for slices with no negatives).
72
+ - `max_latency_p99_ms` — maximum p99 latency in milliseconds.
73
+ - **`slices`** — per-slice overrides. Keys are fnmatch globs. A `"category/language"` key (e.g. `"self_harm/en"`, `"*/fa"`) targets the category×language family; an `"attack:<glob>"` key (e.g. `"attack:leetspeak"`) targets the attack-type family. Only the fields you set are overridden; the rest fall back to `global_thresholds`. Attack-type slices are opt-in — they're gated only where an `attack:` key matches.
74
+ - **`comparison`** *(optional)* — regression limits versus the previous stored run: `max_recall_regression`, `max_fpr_increase`.
75
+ - **`on_failure`** — `block` (fail the gate) or `warn` (report but pass).
76
+
77
+ The per-slice overrides in the shipped `gate.json` reflect the known limits of the built-in regex demo guard; tighten or remove them for your own guard.
78
+
79
+ GitHub Actions:
80
+
81
+ ```yaml
82
+ - name: Install guardmeter
83
+ run: pip install guardmeter
84
+ - name: Evaluate
85
+ run: guardmeter compare --baseline regex-baseline --candidate ${{ env.CANDIDATE_GUARD }} --dataset dataset/sample.csv
86
+ - name: Report
87
+ run: guardmeter report --run latest
88
+ - name: Safety gate
89
+ run: guardmeter gate --config gate.json --run latest # exits 1 on regression
90
+ - name: Upload report
91
+ uses: actions/upload-artifact@v4
92
+ with:
93
+ name: safety-report
94
+ path: report/
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Built-in guards
100
+
101
+ | Name | Requirements | Notes |
102
+ |------|--------------|-------|
103
+ | `regex-baseline` | built-in | Simple keyword-matching profile — the weak baseline to compare against |
104
+ | `regex-enhanced` | built-in | Expanded patterns, obfuscation detection, Farsi coverage |
105
+ | `regex` | built-in | Alias of `regex-enhanced` (kept for backward compatibility) |
106
+ | `openai` | `pip install guardmeter[llm]` + `OPENAI_API_KEY` | OpenAI Moderation API (experimental — see below) |
107
+ | `llamaguard` | HuggingFace `transformers` or an HTTP endpoint | Llama Guard 3, local pipeline or hosted API (experimental — see below) |
108
+
109
+ ### Write your own guard
110
+
111
+ ```python
112
+ from guardmeter.core.guard import Guard, GuardResult
113
+ from guardmeter.core.registry import register
114
+
115
+ class MyGuard(Guard):
116
+ name = "my-guard"
117
+ version = "1.0.0"
118
+
119
+ def predict(self, text: str, **meta) -> GuardResult:
120
+ is_unsafe = "bomb" in text.lower()
121
+ return GuardResult(prediction="flag" if is_unsafe else "pass",
122
+ score=0.9 if is_unsafe else 0.1, latency_ms=5)
123
+
124
+ register("my-guard", MyGuard) # now usable as --candidate my-guard
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Dashboard & report
130
+
131
+ `guardmeter report --run latest` writes an HTML report for a single run (baseline vs candidate cards with Wilson CIs, category×language and attack-type slice tables, a real candidate threshold-sweep chart, and per-sample latency charts). It also mentions an informational regulatory mapping — see the note under *Experimental*.
132
+
133
+ `guardmeter dashboard` builds an interactive multi-run dashboard (`report/dashboard.html`), also auto-rebuilt on every `report`. Four tabs:
134
+
135
+ - **Overview** — run history table with F1, recall, FPR, McNemar p-value and gate badges. Click a row to drill in.
136
+ - **Run Detail** — baseline vs candidate metric cards, category×language and attack-type slice tables, and a sample-results table (first 200 rows). Strict/Lenient toggle.
137
+ - **Trends** — recall, F1, FPR and McNemar p-value over all runs (p-value on a log scale with a p=0.05 reference line).
138
+ - **Compare** — pick any two runs and see a per-metric delta table with improvement/regression arrows.
139
+
140
+ ---
141
+
142
+ ## Experimental
143
+
144
+ These features work but require API keys or extra dependencies and have limited automated test coverage. Treat them as advisory:
145
+
146
+ - **LLM-as-judge** (`guardmeter/judge/`) — uses Claude or an OpenAI model as a second opinion on predictions. Available through the Python API only (no CLI subcommand); needs a provider API key.
147
+ - **`openai` guard** — calls the OpenAI Moderation API; needs `guardmeter[llm]` and `OPENAI_API_KEY`.
148
+ - **`llamaguard` guard** — runs Llama Guard 3 via a local `transformers` pipeline or an HTTP endpoint; needs `guardmeter[hf]` or a hosted endpoint and key.
149
+ - **Regulatory mapping (informational).** The HTML report includes a table mapping a run's metrics to regulatory themes (e.g. EU AI Act articles, NIST AI RMF). It is an informational aid for your own documentation, **not** a compliance certification or legal assessment.
150
+
151
+ ---
152
+
153
+ ## Development Setup
154
+
155
+ ```bash
156
+ python3.13 -m venv .venv
157
+ source .venv/bin/activate # Windows: .venv\Scripts\activate
158
+ pip install -e ".[dev]"
159
+ ruff check guardmeter tests
160
+ mypy guardmeter
161
+ pytest tests/guardmeter/ -q
162
+ ```
163
+
164
+ > **Note:** macOS users with Homebrew Python must use a virtual environment (Homebrew enforces PEP 668).
165
+
166
+ ---
167
+
168
+ ## Not affiliated with
169
+
170
+ This project is unrelated to the JRC "GuardBench" toxicity-benchmark library at [github.com/AmenRa/guardbench](https://github.com/AmenRa/guardbench). Same name, different project.
171
+
172
+ Formerly published as `sea-guard` (versions 0.1–0.2, import name `guardbench`). Renamed in 0.3.0 to avoid confusion with the unrelated JRC GuardBench benchmark.
173
+
174
+ ---
175
+
176
+ ## Contributing
177
+
178
+ See [CONTRIBUTING.md](CONTRIBUTING.md). Contributions welcome — new guard adapters, dataset/language coverage, and report improvements especially.
179
+
180
+ ## License
181
+
182
+ MIT — see [LICENSE](LICENSE).
183
+
184
+ ## Branding
185
+
186
+ Logo assets are in the `branding/` directory.
187
+
188
+ - `guardmeter-logo.svg` — shield mark (favicon, PyPI, GitHub avatar)
189
+ - `guardmeter-wordmark.svg` — full lockup with tagline
190
+ - `guardmeter-social-card.svg` — 1280×640 OG image for GitHub social preview
191
+
192
+ ---
193
+
194
+ *Built by [SeaTechOne LLC](https://seatechone.com) · Seattle, WA*
@@ -0,0 +1,3 @@
1
+ """GuardMeter — AI safety guard evaluation framework."""
2
+
3
+ __version__ = "0.3.0"
@@ -0,0 +1 @@
1
+ """CLI entry points."""