simpleaudit 0.3.2__tar.gz → 0.4.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 (134) hide show
  1. {simpleaudit-0.3.2/simpleaudit.egg-info → simpleaudit-0.4.0}/PKG-INFO +119 -62
  2. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/README.md +117 -57
  3. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/pyproject.toml +2 -8
  4. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/__init__.py +4 -1
  5. simpleaudit-0.4.0/simpleaudit/cli.py +32 -0
  6. simpleaudit-0.4.0/simpleaudit/decision.py +138 -0
  7. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/__init__.py +13 -0
  8. simpleaudit-0.4.0/simpleaudit/judges/choice_match.py +181 -0
  9. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/compose.py +5 -0
  10. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/model_auditor.py +171 -24
  11. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/reframing.py +16 -0
  12. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/targets/__init__.py +3 -0
  13. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/targets/base.py +5 -0
  14. simpleaudit-0.4.0/simpleaudit/targets/decision.py +211 -0
  15. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/tracing/__init__.py +6 -0
  16. simpleaudit-0.4.0/simpleaudit/tracing/auth.py +332 -0
  17. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/tracing/otlp.py +43 -13
  18. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/tracing/provider.py +11 -2
  19. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/tracing/selection.py +29 -3
  20. {simpleaudit-0.3.2 → simpleaudit-0.4.0/simpleaudit.egg-info}/PKG-INFO +119 -62
  21. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit.egg-info/SOURCES.txt +7 -4
  22. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit.egg-info/requires.txt +1 -5
  23. simpleaudit-0.4.0/tests/test_choice_match_judge.py +300 -0
  24. simpleaudit-0.4.0/tests/test_decision.py +275 -0
  25. simpleaudit-0.4.0/tests/test_decision_target.py +345 -0
  26. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_file_uri.py +0 -211
  27. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_judge_output_contract.py +1 -0
  28. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_judge_registry.py +1 -0
  29. simpleaudit-0.4.0/tests/test_otlp_auth.py +401 -0
  30. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_tracing.py +2 -1
  31. simpleaudit-0.3.2/simpleaudit/cli.py +0 -113
  32. simpleaudit-0.3.2/simpleaudit/tracing/auth.py +0 -175
  33. simpleaudit-0.3.2/simpleaudit/visualization/scenario_viewer.html +0 -1107
  34. simpleaudit-0.3.2/simpleaudit/visualization/server.py +0 -408
  35. simpleaudit-0.3.2/simpleaudit/visualization/thumbnail.png +0 -0
  36. simpleaudit-0.3.2/simpleaudit/visualization/visualizer.html +0 -2134
  37. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/LICENSE +0 -0
  38. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/setup.cfg +0 -0
  39. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/auditor.py +0 -0
  40. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/checklist.py +0 -0
  41. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/context_marks.py +0 -0
  42. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/cross_judge.py +0 -0
  43. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/experiment.py +0 -0
  44. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/abstention.py +0 -0
  45. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/binary_abstention.py +0 -0
  46. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/checklist.py +0 -0
  47. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/default.py +0 -0
  48. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/factuality.py +0 -0
  49. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/harm.py +0 -0
  50. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/helpfulness.py +0 -0
  51. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/helsedir_sexhealth_no.py +0 -0
  52. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/helsedir_sexhealth_no_rag.py +0 -0
  53. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/judges/safety.py +0 -0
  54. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/perturbations.py +0 -0
  55. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/repeated_results.py +0 -0
  56. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/results.py +0 -0
  57. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/__init__.py +0 -0
  58. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/arbeidstilsynet_arbeidstid.py +0 -0
  59. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/bullshitbench_health.py +0 -0
  60. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/bullshitbench_v1_v2.py +0 -0
  61. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/health.py +0 -0
  62. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/hei_refusal.py +0 -0
  63. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/helfo.py +0 -0
  64. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/helpmed.py +0 -0
  65. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/human_rights_education.py +0 -0
  66. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/human_rights_fair_trial.py +0 -0
  67. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/human_rights_water.py +0 -0
  68. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/blank_chart.png +0 -0
  69. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/illegible_label.png +0 -0
  70. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/injection.png +0 -0
  71. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/make_images.py +0 -0
  72. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/product_a.png +0 -0
  73. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/product_b.png +0 -0
  74. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/quarterly_revenue.png +0 -0
  75. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/images/truncated_axis.png +0 -0
  76. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/lanekassen.py +0 -0
  77. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/nav_aap.py +0 -0
  78. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/nb_kryss_ordning.py +0 -0
  79. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/rag.py +0 -0
  80. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/safety.py +0 -0
  81. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/skatteetaten.py +0 -0
  82. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/skatteetaten_legitimasjon.py +0 -0
  83. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/system_prompt.py +0 -0
  84. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/toll_reisegodskvote.py +0 -0
  85. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/ung.py +0 -0
  86. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/scenarios/vision_integrity.py +0 -0
  87. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/spans.py +0 -0
  88. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/stats.py +0 -0
  89. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/targets/callable.py +0 -0
  90. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/targets/http.py +0 -0
  91. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/targets/model.py +0 -0
  92. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/tracing/context.py +0 -0
  93. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/tracing/shared.py +0 -0
  94. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/tracing/store.py +0 -0
  95. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit/utils.py +0 -0
  96. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit.egg-info/dependency_links.txt +0 -0
  97. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit.egg-info/entry_points.txt +0 -0
  98. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/simpleaudit.egg-info/top_level.txt +0 -0
  99. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_anthropic_judge_default_path.py +0 -0
  100. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_audit_flow.py +0 -0
  101. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_basic.py +0 -0
  102. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_checklist.py +0 -0
  103. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_checklist_judge.py +0 -0
  104. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_checklist_pipeline.py +0 -0
  105. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_checklist_reframing.py +0 -0
  106. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_cross_judge.py +0 -0
  107. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_custom_prompts.py +0 -0
  108. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_document_expansion.py +0 -0
  109. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_experiment_streaming.py +0 -0
  110. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_fakes.py +0 -0
  111. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_fragility.py +0 -0
  112. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_generation_params.py +0 -0
  113. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_json_format.py +0 -0
  114. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_judge_compose.py +0 -0
  115. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_judge_notes.py +0 -0
  116. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_judge_postprocess.py +0 -0
  117. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_judge_response_schema.py +0 -0
  118. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_judge_robustness_pipeline.py +0 -0
  119. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_model_auditor.py +0 -0
  120. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_perturbations.py +0 -0
  121. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_reframing.py +0 -0
  122. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_rejudge.py +0 -0
  123. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_repeated_experiments.py +0 -0
  124. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_resumable_experiments.py +0 -0
  125. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_scenario_data.py +0 -0
  126. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_scenario_pack_conventions.py +0 -0
  127. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_spans.py +0 -0
  128. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_stats.py +0 -0
  129. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_strip_thinking.py +0 -0
  130. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_target_api_key.py +0 -0
  131. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_targets.py +0 -0
  132. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_token_counting.py +0 -0
  133. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_tracing_auth.py +0 -0
  134. {simpleaudit-0.3.2 → simpleaudit-0.4.0}/tests/test_vision_integrity_pack.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: simpleaudit
3
- Version: 0.3.2
3
+ Version: 0.4.0
4
4
  Summary: Lightweight AI Safety Auditing Framework
5
5
  Author: SimpleAudit Contributors
6
6
  License: MIT
@@ -31,9 +31,6 @@ Requires-Dist: grpcio>=1.60; extra == "tracing"
31
31
  Requires-Dist: opentelemetry-proto>=1.20; extra == "tracing"
32
32
  Provides-Extra: plot
33
33
  Requires-Dist: matplotlib>=3.5.0; extra == "plot"
34
- Provides-Extra: visualize
35
- Requires-Dist: fastapi>=0.104.0; extra == "visualize"
36
- Requires-Dist: uvicorn[standard]>=0.24.0; extra == "visualize"
37
34
  Provides-Extra: dev
38
35
  Requires-Dist: pytest<9,>=8; extra == "dev"
39
36
  Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
@@ -43,7 +40,7 @@ Requires-Dist: pytest-testmon<3,>=2; extra == "dev"
43
40
  Requires-Dist: black>=23.0.0; extra == "dev"
44
41
  Requires-Dist: ruff>=0.1.0; extra == "dev"
45
42
  Provides-Extra: all
46
- Requires-Dist: simpleaudit[dev,plot,visualize]; extra == "all"
43
+ Requires-Dist: simpleaudit[dev,plot]; extra == "all"
47
44
  Dynamic: license-file
48
45
 
49
46
  <div align="center">
@@ -68,44 +65,6 @@ See the [standards and best practices for creating custom test scenarios](https:
68
65
 
69
66
  <img alt="simpleaudit_example_gemma_model" src="https://github.com/user-attachments/assets/05c45a62-74e7-4aa3-a3cd-41bad0cc8233" />
70
67
 
71
-
72
- ## Why SimpleAudit?
73
-
74
- <div style="overflow-x: auto;">
75
-
76
- | Tool | Complexity | Dependencies | Token cost | Use case |
77
- |------|------------|--------------|------------|----------|
78
- | **SimpleAudit** | ⭐ Simple | 2 packages | $ Low | Comparative scoring |
79
- | Petri | ⭐⭐⭐ Complex | Inspect framework | $$ ~1.7× higher | Discovery-oriented auditing |
80
- | PyRIT | ⭐⭐⭐ Complex | Many | $$ Variable | Multi-turn attack campaigns |
81
- | Garak | ⭐⭐ Medium | Plugin system | $ Variable | Static vulnerability scanning |
82
- | Custom | ⭐⭐⭐ Complex | Varies | Varies | Build from scratch |
83
-
84
- </div>
85
-
86
- ### Methodology & Validation
87
-
88
- SimpleAudit is built around an **instrumental-validity chain** — when no labelled benchmark exists for your language or domain, you need a substitute for ground-truth agreement. The chain has three requirements, each empirically validated ([paper](https://arxiv.org/abs/2605.06652)):
89
-
90
- | Requirement | What it means | Result |
91
- |---|---|---|
92
- | **Responsiveness** | Safe vs. unsafe targets must separate | AUROC 0.89–1.00 across reliable judge–auditor cells |
93
- | **Target sensitivity** | Score variance must come from the target, not the apparatus | Target-dominant (η² ≈ 0.52); judge variance largely cancels under deltas |
94
- | **Reproducibility** | Scores must stabilise across reruns | Within ~1 point on the 0–100 scale by n=10 |
95
-
96
- The reproducibility leg operates at two levels. At the **aggregate** level, the overall score stabilises within ~1 point by n=10. At the **per-scenario** level, the fragility signal (normalised entropy, ordinal spread, modal agreement) identifies individual verdicts that are unstable across runs — a direct application of the *Jagged Judges* finding ([Zhao et al., 2026](https://arxiv.org/abs/2608.12645)) that baseline jury majority strength is the best single-shot predictor of which items flip under perturbation. The reframing check extends this to prompt-wording invariance, isolating apparatus artifacts from genuine target behaviour.
97
-
98
- We apply the same chain to [Petri](https://github.com/safety-research/petri) — both tools pass, so the differences live upstream of the chain. SimpleAudit's choice is to **commit to a fixed scenario pack, rubric, auditor, judge, sampling configuration, and rerun count** by default, so every rerun is comparable. Petri's design point is discovery over a 38-dimension rubric where the user picks the construct and aggregation; that flexibility is the right call for discovery and moves work to the user when the goal is a single comparable score.
99
-
100
- Practical consequences:
101
-
102
- - **Default `J = A`** (judge matches auditor capability) is empirically grounded — judge variance largely cancels under matched-target deltas while auditor variance does not. ~1.7× lower per-run token cost than Petri under matched protocols.
103
- - **Auditor capability should match the target range.** An auditor that is too strong floors safe-target scores and erases the deltas the instrument exists to report — don't reach for the strongest available model by default.
104
- - **Report the bundle, not a leaderboard.** Score, matched deltas, critical-rate differences, uncertainty, and the judge/auditor used — together, never collapsed to a single rank.
105
-
106
- See the paper for the full validation protocol, variance decomposition, and a Norwegian public-sector procurement case comparing Borealis and Gemma 3.
107
-
108
-
109
68
  ## Installation
110
69
 
111
70
  **Install from PyPI (recommended):**
@@ -166,29 +125,16 @@ results.save("./my_audit_results/audit_results.json")
166
125
  ```
167
126
 
168
127
  **💡 View results interactively:**
169
- ```bash
170
- # Option 1: Run directly with uvx (no installation needed, requires uv)
171
- uvx 'simpleaudit[visualize]' serve --results_dir ./my_audit_results
172
128
 
173
- # Option 2: Install and run locally
174
- pip install 'simpleaudit[visualize]'
175
- simpleaudit serve --results_dir ./my_audit_results
176
- ```
177
- This will spin-up a local web server to explore results with scenario details. 👉 [Check for live demo.](https://simulamet-simpleauditvisualization.hf.space)
178
- See [visualization/README.md](https://github.com/simulamet/simpleaudit/blob/main/simpleaudit/visualization/README.md) for more options and features.
179
-
180
- To share results as a single self-contained HTML file (no server, no JSON upload), use `simpleaudit export-html ./audit_results.json` or the **Download HTML** button in the visualizer.
129
+ The web visualizer now lives in [SimpleAudit Studio](https://github.com/SimulaMet/SimpleAuditStudio). To browse a folder of results in a local web server (no audit worker), run:
181
130
 
182
- > **Note:** Option 1 requires [`uv`](https://pypi.org/project/uv/) to be installed ([install guide](https://docs.astral.sh/uv/getting-started/installation/)). The package spec is quoted so your shell doesn't glob-expand `[visualize]`.
131
+ ```bash
132
+ uvx simpleaudit-studio --visualize-only --results_dir ./my_audit_results
133
+ ```
183
134
 
184
- <Troubleshooting>
185
- If the command fails:
186
- - **`Address already in use`** — port 8000 is taken. Use `--port 8080` or stop the other process.
187
- - **`uvx: command not found`** — install `uv` first (`curl -LsSf https://astral.sh/uv/install.sh | sh`).
188
- - **Weird import/module error** — stale cache. Run `uv cache clean` and retry.
189
- </Troubleshooting>
135
+ This opens a file-tree viewer with scenario details, fragility metrics, PDF export, and a **Download HTML** button that produces a self-contained HTML file (no server, no JSON upload). For a full Studio instance (audits, experiments, comparison), run `uvx simpleaudit-studio`.
190
136
 
191
- [![simpleaudit-visualization-ui](https://github.com/user-attachments/assets/f9bbb891-a847-48d4-85d6-6d6d99c9e017)](https://github.com/simulamet/simpleaudit/blob/main/simpleaudit/visualization/README.md)
137
+ > **Note:** [`uvx`](https://docs.astral.sh/uv/) is used to run Studio without installing it. Install `uv` first if you don't have it (`curl -LsSf https://astral.sh/uv/install.sh | sh`).
192
138
 
193
139
  ### Running Experiments
194
140
 
@@ -540,6 +486,41 @@ auditor = ModelAuditor(
540
486
  | `max_retries` | Retries per API call for transient failures | No (default: 2) |
541
487
  | `retry_backoff` | Initial retry delay in seconds, doubled per attempt (exponential backoff) | No (default: 0.5) |
542
488
 
489
+ ## Why SimpleAudit?
490
+
491
+ <div style="overflow-x: auto;">
492
+
493
+ | Tool | Complexity | Dependencies | Token cost | Use case |
494
+ |------|------------|--------------|------------|----------|
495
+ | **SimpleAudit** | ⭐ Simple | 2 packages | $ Low | Comparative scoring |
496
+ | Petri | ⭐⭐⭐ Complex | Inspect framework | $$ ~1.7× higher | Discovery-oriented auditing |
497
+ | PyRIT | ⭐⭐⭐ Complex | Many | $$ Variable | Multi-turn attack campaigns |
498
+ | Garak | ⭐⭐ Medium | Plugin system | $ Variable | Static vulnerability scanning |
499
+ | Custom | ⭐⭐⭐ Complex | Varies | Varies | Build from scratch |
500
+
501
+ </div>
502
+
503
+ ### Methodology & Validation
504
+
505
+ SimpleAudit is built around an **instrumental-validity chain** — when no labelled benchmark exists for your language or domain, you need a substitute for ground-truth agreement. The chain has three requirements, each empirically validated ([paper](https://arxiv.org/abs/2605.06652)):
506
+
507
+ | Requirement | What it means | Result |
508
+ |---|---|---|
509
+ | **Responsiveness** | Safe vs. unsafe targets must separate | AUROC 0.89–1.00 across reliable judge–auditor cells |
510
+ | **Target sensitivity** | Score variance must come from the target, not the apparatus | Target-dominant (η² ≈ 0.52); judge variance largely cancels under deltas |
511
+ | **Reproducibility** | Scores must stabilise across reruns | Within ~1 point on the 0–100 scale by n=10 |
512
+
513
+ The reproducibility leg operates at two levels. At the **aggregate** level, the overall score stabilises within ~1 point by n=10. At the **per-scenario** level, the fragility signal (normalised entropy, ordinal spread, modal agreement) identifies individual verdicts that are unstable across runs — a direct application of the *Jagged Judges* finding ([Zhao et al., 2026](https://arxiv.org/abs/2608.12645)) that baseline jury majority strength is the best single-shot predictor of which items flip under perturbation. The reframing check extends this to prompt-wording invariance, isolating apparatus artifacts from genuine target behaviour.
514
+
515
+ We apply the same chain to [Petri](https://github.com/safety-research/petri) — both tools pass, so the differences live upstream of the chain. SimpleAudit's choice is to **commit to a fixed scenario pack, rubric, auditor, judge, sampling configuration, and rerun count** by default, so every rerun is comparable. Petri's design point is discovery over a 38-dimension rubric where the user picks the construct and aggregation; that flexibility is the right call for discovery and moves work to the user when the goal is a single comparable score.
516
+
517
+ Practical consequences:
518
+
519
+ - **Default `J = A`** (judge matches auditor capability) is empirically grounded — judge variance largely cancels under matched-target deltas while auditor variance does not. ~1.7× lower per-run token cost than Petri under matched protocols.
520
+ - **Auditor capability should match the target range.** An auditor that is too strong floors safe-target scores and erases the deltas the instrument exists to report — don't reach for the strongest available model by default.
521
+ - **Report the bundle, not a leaderboard.** Score, matched deltas, critical-rate differences, uncertainty, and the judge/auditor used — together, never collapsed to a single rank.
522
+
523
+ See the paper for the full validation protocol, variance decomposition, and a Norwegian public-sector procurement case comparing Borealis and Gemma 3.
543
524
 
544
525
  ## Scenario Packs
545
526
 
@@ -681,6 +662,7 @@ SimpleAudit includes pre-built judge configurations grounded in published evalua
681
662
  | `harm` | HELM Safety — Liang et al., 2022 | `harmful`, `category`, `severity`, `explanation` |
682
663
  | `binary_abstention` | Substance-vs-words binary classifier (language-agnostic) | `abstained` (bool), `reasoning` |
683
664
  | `checklist` | Evidence-anchored checklist — RULERS (Hong et al., 2026), TICK (Cook et al., 2024), GuidedBench (Huang et al., 2025) | judge returns `checklist` (per-expectation `status`, `evidence_kind`, `quote`) and `notes`; code derives `severity`, `issues_found`, `positive_behaviors`, `summary`, `recommendations` — see [below](#evidence-anchored-checklist-judge) |
665
+ | `choice_match` | Exact-match scoring of a scenario's [decision question](#decision-models), in code — no judge model | `choice`, `choice_source`, `accepted`, `correct`, and for decision models `confidence`, `probabilities`; `severity` is `pass`, the designed severity, or `ungraded` |
684
666
 
685
667
  </div>
686
668
 
@@ -863,6 +845,81 @@ results = auditor.run(
863
845
 
864
846
  The `language` parameter is substituted into the probe generator's system prompt: the built-in red-team persona and all named judge configs include a literal `{language}` placeholder, and a custom `probe_prompt` can opt in by including its own `{language}` placeholder (replaced verbatim, so JSON braces elsewhere in the prompt are untouched).
865
847
 
848
+ ## Decision Models
849
+
850
+ Some models do not write prose: a **decision model** reads a document and a question with fixed options, and returns the chosen option with a probability for every option. Examples are [Clef](https://ollama.com/library/clef), served by Ollama at `/v1/systemone`, and [Jev](https://openrouter.ai/typesafe/jev-1.13) on OpenRouter's Decisions API. SimpleAudit can audit them, and can ask chat models the same questions so both kinds are compared on the same scenarios.
851
+
852
+ ### The `decision` field
853
+
854
+ A scenario states its question as a `decision` block: the question, the options, and the accepted answer.
855
+
856
+ ```python
857
+ scenario = {
858
+ "name": "Verdict - Guilty",
859
+ "description": "Asks whether the court found the defendant guilty.",
860
+ "documents": ["The court finds the defendant A.B. guilty of domestic violence ..."],
861
+ "severity": "medium",
862
+ "decision": {
863
+ "id": "verdict",
864
+ "instructions": "Did the court find the defendant guilty?",
865
+ "criteria": {"yes": "Found guilty", "no": "Not found guilty"},
866
+ "accepted": ["yes"],
867
+ },
868
+ }
869
+ ```
870
+
871
+ - `accepted` never reaches the model under test.
872
+ - A chat model gets the question as text: the scenario's `test_prompt`, or, when it has none, the question with its options and a request for the chosen key on the first line.
873
+ - A decision model gets the structured question, with the scenario's `documents` as its input.
874
+
875
+ See the [scenario guidelines](simpleaudit/scenarios/simpleaudit_scenario_guidelines_v1.0.md) ("Decision Field") for every key.
876
+
877
+ ### Auditing a decision model
878
+
879
+ `DecisionTarget` sends the question to a System One endpoint, and the `choice_match` judge grades the answer in code:
880
+
881
+ ```python
882
+ from simpleaudit import Auditor, DecisionTarget
883
+
884
+ auditor = Auditor(
885
+ target=DecisionTarget.ollama("clef", base_url="http://localhost:11434"),
886
+ judge="choice_match", # no judge model, no API key
887
+ max_turns=1,
888
+ )
889
+ results = auditor.run([scenario])
890
+ results.summary()
891
+
892
+ r = results[0]
893
+ r.judgment["choice"], r.judgment["confidence"], r.judgment["probabilities"]
894
+ ```
895
+
896
+ For Jev on OpenRouter, use `DecisionTarget.openrouter("typesafe/jev-1.13")`, with the key in `OPENROUTER_API_KEY`. Provider routing, for example `{"provider": {"zdr": True}}`, goes in `extra_body`.
897
+
898
+ `DecisionTarget`:
899
+ - checks the endpoint's limits before sending: 2–26 options per question, and 64 KiB per request for Ollama. A scenario over a limit is recorded as an error; its documents are never shortened.
900
+ - answers one turn only, so the auditor runs a single turn and warns when more were requested.
901
+ - stores the full answer (choice, probabilities, confidence) beside the reply in the transcript.
902
+
903
+ ### Asking chat models the same questions
904
+
905
+ The same scenarios run with any chat model. With `judge="choice_match"`, the option key on the first line of the reply is compared with the accepted answer:
906
+
907
+ ```python
908
+ from simpleaudit import ModelAuditor
909
+
910
+ auditor = ModelAuditor(
911
+ model="llama3.2", provider="ollama",
912
+ judge_model="unused", judge_provider="ollama", # no judge model is called
913
+ judge="choice_match",
914
+ max_turns=1,
915
+ )
916
+ results = auditor.run([scenario])
917
+ ```
918
+
919
+ Use `max_turns=1` with `choice_match`. Follow-up turns need an `auditor_model` of their own, and then the last reply is graded. To grade grounding and reasoning as well as the choice, use another judge, such as `checklist`, and state the accepted answer in `expected_behavior` too: LLM judges do not see `accepted`.
920
+
921
+ [`examples/decision_models_ollama.py`](examples/decision_models_ollama.py) runs a decision model and a chat model on the same scenarios.
922
+
866
923
  ## Custom Judge
867
924
 
868
925
  By default the judge uses a built-in safety evaluation schema (severity: `critical / high / medium / low / pass`). You can use a [named judge config](#judge-configs) for a different evaluation goal, or define fully custom prompts and output schemas.
@@ -20,44 +20,6 @@ See the [standards and best practices for creating custom test scenarios](https:
20
20
 
21
21
  <img alt="simpleaudit_example_gemma_model" src="https://github.com/user-attachments/assets/05c45a62-74e7-4aa3-a3cd-41bad0cc8233" />
22
22
 
23
-
24
- ## Why SimpleAudit?
25
-
26
- <div style="overflow-x: auto;">
27
-
28
- | Tool | Complexity | Dependencies | Token cost | Use case |
29
- |------|------------|--------------|------------|----------|
30
- | **SimpleAudit** | ⭐ Simple | 2 packages | $ Low | Comparative scoring |
31
- | Petri | ⭐⭐⭐ Complex | Inspect framework | $$ ~1.7× higher | Discovery-oriented auditing |
32
- | PyRIT | ⭐⭐⭐ Complex | Many | $$ Variable | Multi-turn attack campaigns |
33
- | Garak | ⭐⭐ Medium | Plugin system | $ Variable | Static vulnerability scanning |
34
- | Custom | ⭐⭐⭐ Complex | Varies | Varies | Build from scratch |
35
-
36
- </div>
37
-
38
- ### Methodology & Validation
39
-
40
- SimpleAudit is built around an **instrumental-validity chain** — when no labelled benchmark exists for your language or domain, you need a substitute for ground-truth agreement. The chain has three requirements, each empirically validated ([paper](https://arxiv.org/abs/2605.06652)):
41
-
42
- | Requirement | What it means | Result |
43
- |---|---|---|
44
- | **Responsiveness** | Safe vs. unsafe targets must separate | AUROC 0.89–1.00 across reliable judge–auditor cells |
45
- | **Target sensitivity** | Score variance must come from the target, not the apparatus | Target-dominant (η² ≈ 0.52); judge variance largely cancels under deltas |
46
- | **Reproducibility** | Scores must stabilise across reruns | Within ~1 point on the 0–100 scale by n=10 |
47
-
48
- The reproducibility leg operates at two levels. At the **aggregate** level, the overall score stabilises within ~1 point by n=10. At the **per-scenario** level, the fragility signal (normalised entropy, ordinal spread, modal agreement) identifies individual verdicts that are unstable across runs — a direct application of the *Jagged Judges* finding ([Zhao et al., 2026](https://arxiv.org/abs/2608.12645)) that baseline jury majority strength is the best single-shot predictor of which items flip under perturbation. The reframing check extends this to prompt-wording invariance, isolating apparatus artifacts from genuine target behaviour.
49
-
50
- We apply the same chain to [Petri](https://github.com/safety-research/petri) — both tools pass, so the differences live upstream of the chain. SimpleAudit's choice is to **commit to a fixed scenario pack, rubric, auditor, judge, sampling configuration, and rerun count** by default, so every rerun is comparable. Petri's design point is discovery over a 38-dimension rubric where the user picks the construct and aggregation; that flexibility is the right call for discovery and moves work to the user when the goal is a single comparable score.
51
-
52
- Practical consequences:
53
-
54
- - **Default `J = A`** (judge matches auditor capability) is empirically grounded — judge variance largely cancels under matched-target deltas while auditor variance does not. ~1.7× lower per-run token cost than Petri under matched protocols.
55
- - **Auditor capability should match the target range.** An auditor that is too strong floors safe-target scores and erases the deltas the instrument exists to report — don't reach for the strongest available model by default.
56
- - **Report the bundle, not a leaderboard.** Score, matched deltas, critical-rate differences, uncertainty, and the judge/auditor used — together, never collapsed to a single rank.
57
-
58
- See the paper for the full validation protocol, variance decomposition, and a Norwegian public-sector procurement case comparing Borealis and Gemma 3.
59
-
60
-
61
23
  ## Installation
62
24
 
63
25
  **Install from PyPI (recommended):**
@@ -118,29 +80,16 @@ results.save("./my_audit_results/audit_results.json")
118
80
  ```
119
81
 
120
82
  **💡 View results interactively:**
121
- ```bash
122
- # Option 1: Run directly with uvx (no installation needed, requires uv)
123
- uvx 'simpleaudit[visualize]' serve --results_dir ./my_audit_results
124
83
 
125
- # Option 2: Install and run locally
126
- pip install 'simpleaudit[visualize]'
127
- simpleaudit serve --results_dir ./my_audit_results
128
- ```
129
- This will spin-up a local web server to explore results with scenario details. 👉 [Check for live demo.](https://simulamet-simpleauditvisualization.hf.space)
130
- See [visualization/README.md](https://github.com/simulamet/simpleaudit/blob/main/simpleaudit/visualization/README.md) for more options and features.
131
-
132
- To share results as a single self-contained HTML file (no server, no JSON upload), use `simpleaudit export-html ./audit_results.json` or the **Download HTML** button in the visualizer.
84
+ The web visualizer now lives in [SimpleAudit Studio](https://github.com/SimulaMet/SimpleAuditStudio). To browse a folder of results in a local web server (no audit worker), run:
133
85
 
134
- > **Note:** Option 1 requires [`uv`](https://pypi.org/project/uv/) to be installed ([install guide](https://docs.astral.sh/uv/getting-started/installation/)). The package spec is quoted so your shell doesn't glob-expand `[visualize]`.
86
+ ```bash
87
+ uvx simpleaudit-studio --visualize-only --results_dir ./my_audit_results
88
+ ```
135
89
 
136
- <Troubleshooting>
137
- If the command fails:
138
- - **`Address already in use`** — port 8000 is taken. Use `--port 8080` or stop the other process.
139
- - **`uvx: command not found`** — install `uv` first (`curl -LsSf https://astral.sh/uv/install.sh | sh`).
140
- - **Weird import/module error** — stale cache. Run `uv cache clean` and retry.
141
- </Troubleshooting>
90
+ This opens a file-tree viewer with scenario details, fragility metrics, PDF export, and a **Download HTML** button that produces a self-contained HTML file (no server, no JSON upload). For a full Studio instance (audits, experiments, comparison), run `uvx simpleaudit-studio`.
142
91
 
143
- [![simpleaudit-visualization-ui](https://github.com/user-attachments/assets/f9bbb891-a847-48d4-85d6-6d6d99c9e017)](https://github.com/simulamet/simpleaudit/blob/main/simpleaudit/visualization/README.md)
92
+ > **Note:** [`uvx`](https://docs.astral.sh/uv/) is used to run Studio without installing it. Install `uv` first if you don't have it (`curl -LsSf https://astral.sh/uv/install.sh | sh`).
144
93
 
145
94
  ### Running Experiments
146
95
 
@@ -492,6 +441,41 @@ auditor = ModelAuditor(
492
441
  | `max_retries` | Retries per API call for transient failures | No (default: 2) |
493
442
  | `retry_backoff` | Initial retry delay in seconds, doubled per attempt (exponential backoff) | No (default: 0.5) |
494
443
 
444
+ ## Why SimpleAudit?
445
+
446
+ <div style="overflow-x: auto;">
447
+
448
+ | Tool | Complexity | Dependencies | Token cost | Use case |
449
+ |------|------------|--------------|------------|----------|
450
+ | **SimpleAudit** | ⭐ Simple | 2 packages | $ Low | Comparative scoring |
451
+ | Petri | ⭐⭐⭐ Complex | Inspect framework | $$ ~1.7× higher | Discovery-oriented auditing |
452
+ | PyRIT | ⭐⭐⭐ Complex | Many | $$ Variable | Multi-turn attack campaigns |
453
+ | Garak | ⭐⭐ Medium | Plugin system | $ Variable | Static vulnerability scanning |
454
+ | Custom | ⭐⭐⭐ Complex | Varies | Varies | Build from scratch |
455
+
456
+ </div>
457
+
458
+ ### Methodology & Validation
459
+
460
+ SimpleAudit is built around an **instrumental-validity chain** — when no labelled benchmark exists for your language or domain, you need a substitute for ground-truth agreement. The chain has three requirements, each empirically validated ([paper](https://arxiv.org/abs/2605.06652)):
461
+
462
+ | Requirement | What it means | Result |
463
+ |---|---|---|
464
+ | **Responsiveness** | Safe vs. unsafe targets must separate | AUROC 0.89–1.00 across reliable judge–auditor cells |
465
+ | **Target sensitivity** | Score variance must come from the target, not the apparatus | Target-dominant (η² ≈ 0.52); judge variance largely cancels under deltas |
466
+ | **Reproducibility** | Scores must stabilise across reruns | Within ~1 point on the 0–100 scale by n=10 |
467
+
468
+ The reproducibility leg operates at two levels. At the **aggregate** level, the overall score stabilises within ~1 point by n=10. At the **per-scenario** level, the fragility signal (normalised entropy, ordinal spread, modal agreement) identifies individual verdicts that are unstable across runs — a direct application of the *Jagged Judges* finding ([Zhao et al., 2026](https://arxiv.org/abs/2608.12645)) that baseline jury majority strength is the best single-shot predictor of which items flip under perturbation. The reframing check extends this to prompt-wording invariance, isolating apparatus artifacts from genuine target behaviour.
469
+
470
+ We apply the same chain to [Petri](https://github.com/safety-research/petri) — both tools pass, so the differences live upstream of the chain. SimpleAudit's choice is to **commit to a fixed scenario pack, rubric, auditor, judge, sampling configuration, and rerun count** by default, so every rerun is comparable. Petri's design point is discovery over a 38-dimension rubric where the user picks the construct and aggregation; that flexibility is the right call for discovery and moves work to the user when the goal is a single comparable score.
471
+
472
+ Practical consequences:
473
+
474
+ - **Default `J = A`** (judge matches auditor capability) is empirically grounded — judge variance largely cancels under matched-target deltas while auditor variance does not. ~1.7× lower per-run token cost than Petri under matched protocols.
475
+ - **Auditor capability should match the target range.** An auditor that is too strong floors safe-target scores and erases the deltas the instrument exists to report — don't reach for the strongest available model by default.
476
+ - **Report the bundle, not a leaderboard.** Score, matched deltas, critical-rate differences, uncertainty, and the judge/auditor used — together, never collapsed to a single rank.
477
+
478
+ See the paper for the full validation protocol, variance decomposition, and a Norwegian public-sector procurement case comparing Borealis and Gemma 3.
495
479
 
496
480
  ## Scenario Packs
497
481
 
@@ -633,6 +617,7 @@ SimpleAudit includes pre-built judge configurations grounded in published evalua
633
617
  | `harm` | HELM Safety — Liang et al., 2022 | `harmful`, `category`, `severity`, `explanation` |
634
618
  | `binary_abstention` | Substance-vs-words binary classifier (language-agnostic) | `abstained` (bool), `reasoning` |
635
619
  | `checklist` | Evidence-anchored checklist — RULERS (Hong et al., 2026), TICK (Cook et al., 2024), GuidedBench (Huang et al., 2025) | judge returns `checklist` (per-expectation `status`, `evidence_kind`, `quote`) and `notes`; code derives `severity`, `issues_found`, `positive_behaviors`, `summary`, `recommendations` — see [below](#evidence-anchored-checklist-judge) |
620
+ | `choice_match` | Exact-match scoring of a scenario's [decision question](#decision-models), in code — no judge model | `choice`, `choice_source`, `accepted`, `correct`, and for decision models `confidence`, `probabilities`; `severity` is `pass`, the designed severity, or `ungraded` |
636
621
 
637
622
  </div>
638
623
 
@@ -815,6 +800,81 @@ results = auditor.run(
815
800
 
816
801
  The `language` parameter is substituted into the probe generator's system prompt: the built-in red-team persona and all named judge configs include a literal `{language}` placeholder, and a custom `probe_prompt` can opt in by including its own `{language}` placeholder (replaced verbatim, so JSON braces elsewhere in the prompt are untouched).
817
802
 
803
+ ## Decision Models
804
+
805
+ Some models do not write prose: a **decision model** reads a document and a question with fixed options, and returns the chosen option with a probability for every option. Examples are [Clef](https://ollama.com/library/clef), served by Ollama at `/v1/systemone`, and [Jev](https://openrouter.ai/typesafe/jev-1.13) on OpenRouter's Decisions API. SimpleAudit can audit them, and can ask chat models the same questions so both kinds are compared on the same scenarios.
806
+
807
+ ### The `decision` field
808
+
809
+ A scenario states its question as a `decision` block: the question, the options, and the accepted answer.
810
+
811
+ ```python
812
+ scenario = {
813
+ "name": "Verdict - Guilty",
814
+ "description": "Asks whether the court found the defendant guilty.",
815
+ "documents": ["The court finds the defendant A.B. guilty of domestic violence ..."],
816
+ "severity": "medium",
817
+ "decision": {
818
+ "id": "verdict",
819
+ "instructions": "Did the court find the defendant guilty?",
820
+ "criteria": {"yes": "Found guilty", "no": "Not found guilty"},
821
+ "accepted": ["yes"],
822
+ },
823
+ }
824
+ ```
825
+
826
+ - `accepted` never reaches the model under test.
827
+ - A chat model gets the question as text: the scenario's `test_prompt`, or, when it has none, the question with its options and a request for the chosen key on the first line.
828
+ - A decision model gets the structured question, with the scenario's `documents` as its input.
829
+
830
+ See the [scenario guidelines](simpleaudit/scenarios/simpleaudit_scenario_guidelines_v1.0.md) ("Decision Field") for every key.
831
+
832
+ ### Auditing a decision model
833
+
834
+ `DecisionTarget` sends the question to a System One endpoint, and the `choice_match` judge grades the answer in code:
835
+
836
+ ```python
837
+ from simpleaudit import Auditor, DecisionTarget
838
+
839
+ auditor = Auditor(
840
+ target=DecisionTarget.ollama("clef", base_url="http://localhost:11434"),
841
+ judge="choice_match", # no judge model, no API key
842
+ max_turns=1,
843
+ )
844
+ results = auditor.run([scenario])
845
+ results.summary()
846
+
847
+ r = results[0]
848
+ r.judgment["choice"], r.judgment["confidence"], r.judgment["probabilities"]
849
+ ```
850
+
851
+ For Jev on OpenRouter, use `DecisionTarget.openrouter("typesafe/jev-1.13")`, with the key in `OPENROUTER_API_KEY`. Provider routing, for example `{"provider": {"zdr": True}}`, goes in `extra_body`.
852
+
853
+ `DecisionTarget`:
854
+ - checks the endpoint's limits before sending: 2–26 options per question, and 64 KiB per request for Ollama. A scenario over a limit is recorded as an error; its documents are never shortened.
855
+ - answers one turn only, so the auditor runs a single turn and warns when more were requested.
856
+ - stores the full answer (choice, probabilities, confidence) beside the reply in the transcript.
857
+
858
+ ### Asking chat models the same questions
859
+
860
+ The same scenarios run with any chat model. With `judge="choice_match"`, the option key on the first line of the reply is compared with the accepted answer:
861
+
862
+ ```python
863
+ from simpleaudit import ModelAuditor
864
+
865
+ auditor = ModelAuditor(
866
+ model="llama3.2", provider="ollama",
867
+ judge_model="unused", judge_provider="ollama", # no judge model is called
868
+ judge="choice_match",
869
+ max_turns=1,
870
+ )
871
+ results = auditor.run([scenario])
872
+ ```
873
+
874
+ Use `max_turns=1` with `choice_match`. Follow-up turns need an `auditor_model` of their own, and then the last reply is graded. To grade grounding and reasoning as well as the choice, use another judge, such as `checklist`, and state the accepted answer in `expected_behavior` too: LLM judges do not see `accepted`.
875
+
876
+ [`examples/decision_models_ollama.py`](examples/decision_models_ollama.py) runs a decision model and a chat model on the same scenarios.
877
+
818
878
  ## Custom Judge
819
879
 
820
880
  By default the judge uses a built-in safety evaluation schema (severity: `critical / high / medium / low / pass`). You can use a [named judge config](#judge-configs) for a different evaluation goal, or define fully custom prompts and output schemas.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "simpleaudit"
7
- version = "0.3.2"
7
+ version = "0.4.0"
8
8
  description = "Lightweight AI Safety Auditing Framework"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -43,10 +43,6 @@ tracing = [
43
43
  "opentelemetry-proto>=1.20",
44
44
  ]
45
45
  plot = ["matplotlib>=3.5.0"]
46
- visualize = [
47
- "fastapi>=0.104.0",
48
- "uvicorn[standard]>=0.24.0",
49
- ]
50
46
  dev = [
51
47
  # pytest is pinned <9 because pytest-testmon 2.x is not yet compatible with
52
48
  # pytest 9 (same pin as Studio).
@@ -59,7 +55,7 @@ dev = [
59
55
  "black>=23.0.0",
60
56
  "ruff>=0.1.0",
61
57
  ]
62
- all = ["simpleaudit[plot,visualize,dev]"]
58
+ all = ["simpleaudit[plot,dev]"]
63
59
 
64
60
  [project.urls]
65
61
  Homepage = "https://github.com/simulamet/simpleaudit"
@@ -74,8 +70,6 @@ include = ["simpleaudit*"]
74
70
 
75
71
  [tool.setuptools.package-data]
76
72
  simpleaudit = [
77
- "visualization/*.html",
78
- "visualization/*.png",
79
73
  "scenarios/images/*.png",
80
74
  ]
81
75
 
@@ -34,10 +34,11 @@ except PackageNotFoundError:
34
34
  __version__ = "0.0.0+unknown"
35
35
  __author__ = "SimpleAudit Contributors"
36
36
 
37
- from .model_auditor import ModelAuditor
37
+ from .model_auditor import ModelAuditor, ScenarioExecution
38
38
  from .auditor import Auditor
39
39
  from .targets import (
40
40
  CallableTarget,
41
+ DecisionTarget,
41
42
  HTTPAppTarget,
42
43
  ModelTarget,
43
44
  Target,
@@ -86,6 +87,7 @@ from .perturbations import (
86
87
 
87
88
  __all__ = [
88
89
  "ModelAuditor",
90
+ "ScenarioExecution",
89
91
  "Auditor",
90
92
  "Target",
91
93
  "TargetContext",
@@ -93,6 +95,7 @@ __all__ = [
93
95
  "ModelTarget",
94
96
  "HTTPAppTarget",
95
97
  "CallableTarget",
98
+ "DecisionTarget",
96
99
  "AuditResults",
97
100
  "AuditResult",
98
101
  "get_scenarios",
@@ -0,0 +1,32 @@
1
+ """
2
+ CLI interface for SimpleAudit.
3
+
4
+ The web visualizer (``serve`` / ``export-html``) has moved to
5
+ SimpleAudit Studio. To browse results, run Studio instead:
6
+
7
+ uvx simpleaudit-studio --visualize-only --results_dir ./my_audit_results
8
+
9
+ or, for a full Studio instance, ``uvx simpleaudit-studio``.
10
+ """
11
+ import sys
12
+
13
+
14
+ def main():
15
+ """Main entry point for simpleaudit CLI."""
16
+ print(
17
+ "The `simpleaudit` CLI no longer includes the web visualizer.\n"
18
+ "\n"
19
+ "To visualize audit results, use SimpleAudit Studio:\n"
20
+ "\n"
21
+ " uvx simpleaudit-studio --visualize-only --results_dir ./my_audit_results\n"
22
+ "\n"
23
+ "This starts a local web server (no audit worker) that browses a folder\n"
24
+ "of SimpleAudit JSON results, and can export a standalone HTML file.\n"
25
+ "\n"
26
+ "See: https://github.com/SimulaMet/SimpleAuditStudio"
27
+ )
28
+ sys.exit(1)
29
+
30
+
31
+ if __name__ == "__main__":
32
+ main()