auditkit 1.0.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 (220) hide show
  1. auditkit-1.0.0/.github/workflows/patch-release.yml +376 -0
  2. auditkit-1.0.0/.gitignore +17 -0
  3. auditkit-1.0.0/AGENTS.md +94 -0
  4. auditkit-1.0.0/CITATION.cff +36 -0
  5. auditkit-1.0.0/LICENSE.md +92 -0
  6. auditkit-1.0.0/PKG-INFO +396 -0
  7. auditkit-1.0.0/README.md +232 -0
  8. auditkit-1.0.0/docs/BUGS.md +356 -0
  9. auditkit-1.0.0/docs/CNAME +1 -0
  10. auditkit-1.0.0/docs/COMPARISON.docx +0 -0
  11. auditkit-1.0.0/docs/GUIDE.md +1014 -0
  12. auditkit-1.0.0/docs/RELEASE.md +684 -0
  13. auditkit-1.0.0/docs/VLLM_KNOWN_ISSUES.md +312 -0
  14. auditkit-1.0.0/docs/about/glossary.md +20 -0
  15. auditkit-1.0.0/docs/about/platform-integration.md +378 -0
  16. auditkit-1.0.0/docs/annotators.md +305 -0
  17. auditkit-1.0.0/docs/api.md +39 -0
  18. auditkit-1.0.0/docs/architecture/data-model.md +430 -0
  19. auditkit-1.0.0/docs/architecture/system-design.md +345 -0
  20. auditkit-1.0.0/docs/assets/auditkit-logo-dark.png +0 -0
  21. auditkit-1.0.0/docs/assets/auditkit-logo-light.png +0 -0
  22. auditkit-1.0.0/docs/assets/extra.css +336 -0
  23. auditkit-1.0.0/docs/assets/extra.js +14 -0
  24. auditkit-1.0.0/docs/assets/favicon.png +0 -0
  25. auditkit-1.0.0/docs/assets/icon.png +0 -0
  26. auditkit-1.0.0/docs/assets/icon.svg +23 -0
  27. auditkit-1.0.0/docs/assets/logo.svg +27 -0
  28. auditkit-1.0.0/docs/best_practices/scorers.md +161 -0
  29. auditkit-1.0.0/docs/cli.md +138 -0
  30. auditkit-1.0.0/docs/community/changelog.md +373 -0
  31. auditkit-1.0.0/docs/community/contributing.md +62 -0
  32. auditkit-1.0.0/docs/community/faq.md +78 -0
  33. auditkit-1.0.0/docs/community/roadmap.md +46 -0
  34. auditkit-1.0.0/docs/configuration.md +55 -0
  35. auditkit-1.0.0/docs/cookbook/llm_judge.md +137 -0
  36. auditkit-1.0.0/docs/cookbook/rag_evaluation.md +177 -0
  37. auditkit-1.0.0/docs/development.md +55 -0
  38. auditkit-1.0.0/docs/encoder_judge.md +434 -0
  39. auditkit-1.0.0/docs/encoder_judge_prebuilts.md +161 -0
  40. auditkit-1.0.0/docs/examples/custom_scorer.md +121 -0
  41. auditkit-1.0.0/docs/examples/experiments.md +28 -0
  42. auditkit-1.0.0/docs/examples/many_datasets.md +165 -0
  43. auditkit-1.0.0/docs/examples/model_comparison.md +185 -0
  44. auditkit-1.0.0/docs/examples/quickstart.md +17 -0
  45. auditkit-1.0.0/docs/experiments.md +70 -0
  46. auditkit-1.0.0/docs/getting_started.md +68 -0
  47. auditkit-1.0.0/docs/guard_models.md +495 -0
  48. auditkit-1.0.0/docs/index.md +119 -0
  49. auditkit-1.0.0/docs/integrations.md +145 -0
  50. auditkit-1.0.0/docs/known_issues.md +111 -0
  51. auditkit-1.0.0/docs/llm_judge_rendering.md +185 -0
  52. auditkit-1.0.0/docs/metrics.md +128 -0
  53. auditkit-1.0.0/docs/model_backends.md +67 -0
  54. auditkit-1.0.0/docs/reports.md +39 -0
  55. auditkit-1.0.0/docs/requirements.txt +7 -0
  56. auditkit-1.0.0/docs/scenarios.md +48 -0
  57. auditkit-1.0.0/docs/scorers_reference.md +171 -0
  58. auditkit-1.0.0/examples/01_full_evaluation_pipeline.ipynb +639 -0
  59. auditkit-1.0.0/examples/02_generation_across_hf_families.ipynb +379 -0
  60. auditkit-1.0.0/examples/03_custom_annotators.ipynb +421 -0
  61. auditkit-1.0.0/examples/04_metrics_deep_dive.ipynb +510 -0
  62. auditkit-1.0.0/examples/05_data_types.ipynb +387 -0
  63. auditkit-1.0.0/examples/06_model_comparison.ipynb +362 -0
  64. auditkit-1.0.0/examples/07_annotators_across_models.ipynb +496 -0
  65. auditkit-1.0.0/examples/08_compare_result_deep_dive.ipynb +330 -0
  66. auditkit-1.0.0/examples/09_guard_judge_implementation_check.ipynb +526 -0
  67. auditkit-1.0.0/examples/10_guard_judge_legit_models.ipynb +445 -0
  68. auditkit-1.0.0/examples/11_encoder_judge_prebuilts.ipynb +441 -0
  69. auditkit-1.0.0/examples/12_performance_metrics_demo.ipynb +16470 -0
  70. auditkit-1.0.0/examples/README.md +80 -0
  71. auditkit-1.0.0/examples/applications/01_application_pruned_llama_boolq.ipynb +17660 -0
  72. auditkit-1.0.0/examples/applications/02_application_healthcare_pubmedqa.ipynb +285 -0
  73. auditkit-1.0.0/examples/applications/03_application_finance_10k_qa.ipynb +16180 -0
  74. auditkit-1.0.0/examples/applications/04_application_ecommerce_review_triage.ipynb +260 -0
  75. auditkit-1.0.0/examples/applications/05_application_education_arc_tutor.ipynb +281 -0
  76. auditkit-1.0.0/examples/applications/06_application_enterprise_search_rag.ipynb +294 -0
  77. auditkit-1.0.0/examples/applications/07_application_bert_nli_judge.ipynb +343 -0
  78. auditkit-1.0.0/examples/applications/README.md +53 -0
  79. auditkit-1.0.0/examples/applications/SUMMARY.md +96 -0
  80. auditkit-1.0.0/examples/auditkit.yaml +54 -0
  81. auditkit-1.0.0/examples/model_comparison_notebook.py +189 -0
  82. auditkit-1.0.0/examples/stress_tests/README.md +106 -0
  83. auditkit-1.0.0/examples/stress_tests/test_stress_gated_model.py +124 -0
  84. auditkit-1.0.0/examples/stress_tests/test_stress_open_model_load.py +153 -0
  85. auditkit-1.0.0/mkdocs.yml +166 -0
  86. auditkit-1.0.0/pyproject.toml +66 -0
  87. auditkit-1.0.0/scripts/__init__.py +1 -0
  88. auditkit-1.0.0/scripts/release.py +358 -0
  89. auditkit-1.0.0/src/auditkit/README.md +99 -0
  90. auditkit-1.0.0/src/auditkit/__init__.py +177 -0
  91. auditkit-1.0.0/src/auditkit/__main__.py +3 -0
  92. auditkit-1.0.0/src/auditkit/_bootstrap.py +77 -0
  93. auditkit-1.0.0/src/auditkit/_identity_guard.py +99 -0
  94. auditkit-1.0.0/src/auditkit/adapter.py +264 -0
  95. auditkit-1.0.0/src/auditkit/annotator.py +339 -0
  96. auditkit-1.0.0/src/auditkit/api.py +502 -0
  97. auditkit-1.0.0/src/auditkit/assets/auditkit_logo.png +0 -0
  98. auditkit-1.0.0/src/auditkit/cache.py +47 -0
  99. auditkit-1.0.0/src/auditkit/cli.py +417 -0
  100. auditkit-1.0.0/src/auditkit/comparison.py +563 -0
  101. auditkit-1.0.0/src/auditkit/diff.py +265 -0
  102. auditkit-1.0.0/src/auditkit/errors.py +54 -0
  103. auditkit-1.0.0/src/auditkit/evaluator.py +20 -0
  104. auditkit-1.0.0/src/auditkit/experiment.py +145 -0
  105. auditkit-1.0.0/src/auditkit/hf_publish.py +262 -0
  106. auditkit-1.0.0/src/auditkit/lmeval_engine.py +550 -0
  107. auditkit-1.0.0/src/auditkit/loaders.py +121 -0
  108. auditkit-1.0.0/src/auditkit/logs.py +18 -0
  109. auditkit-1.0.0/src/auditkit/metric.py +199 -0
  110. auditkit-1.0.0/src/auditkit/metrics/README.md +15 -0
  111. auditkit-1.0.0/src/auditkit/metrics/__init__.py +0 -0
  112. auditkit-1.0.0/src/auditkit/metrics/code.py +222 -0
  113. auditkit-1.0.0/src/auditkit/metrics/embedding.py +131 -0
  114. auditkit-1.0.0/src/auditkit/metrics/encoder_judge.py +423 -0
  115. auditkit-1.0.0/src/auditkit/metrics/generation.py +331 -0
  116. auditkit-1.0.0/src/auditkit/metrics/guard.py +412 -0
  117. auditkit-1.0.0/src/auditkit/metrics/hallucination.py +45 -0
  118. auditkit-1.0.0/src/auditkit/metrics/judge.py +547 -0
  119. auditkit-1.0.0/src/auditkit/metrics/pairwise.py +153 -0
  120. auditkit-1.0.0/src/auditkit/metrics/perf.py +53 -0
  121. auditkit-1.0.0/src/auditkit/metrics/rag.py +149 -0
  122. auditkit-1.0.0/src/auditkit/metrics/security.py +64 -0
  123. auditkit-1.0.0/src/auditkit/metrics/toxicity.py +238 -0
  124. auditkit-1.0.0/src/auditkit/model/README.md +16 -0
  125. auditkit-1.0.0/src/auditkit/model/__init__.py +485 -0
  126. auditkit-1.0.0/src/auditkit/model/anthropic.py +94 -0
  127. auditkit-1.0.0/src/auditkit/model/api_gen.py +133 -0
  128. auditkit-1.0.0/src/auditkit/model/groq_gen.py +121 -0
  129. auditkit-1.0.0/src/auditkit/model/hf_gen.py +385 -0
  130. auditkit-1.0.0/src/auditkit/model/lexsi.py +155 -0
  131. auditkit-1.0.0/src/auditkit/model/litellm_gen.py +65 -0
  132. auditkit-1.0.0/src/auditkit/model/openai.py +90 -0
  133. auditkit-1.0.0/src/auditkit/model/openrouter_gen.py +152 -0
  134. auditkit-1.0.0/src/auditkit/model/vllm_gen.py +316 -0
  135. auditkit-1.0.0/src/auditkit/model_compare.py +655 -0
  136. auditkit-1.0.0/src/auditkit/redteam/README.md +9 -0
  137. auditkit-1.0.0/src/auditkit/redteam/__init__.py +26 -0
  138. auditkit-1.0.0/src/auditkit/redteam/detector.py +37 -0
  139. auditkit-1.0.0/src/auditkit/redteam/detectors/README.md +5 -0
  140. auditkit-1.0.0/src/auditkit/redteam/detectors/builtin.py +126 -0
  141. auditkit-1.0.0/src/auditkit/redteam/probe.py +39 -0
  142. auditkit-1.0.0/src/auditkit/redteam/probes/README.md +5 -0
  143. auditkit-1.0.0/src/auditkit/redteam/probes/builtin.py +85 -0
  144. auditkit-1.0.0/src/auditkit/redteam/runner.py +206 -0
  145. auditkit-1.0.0/src/auditkit/registry.py +65 -0
  146. auditkit-1.0.0/src/auditkit/report.py +278 -0
  147. auditkit-1.0.0/src/auditkit/report_format.py +52 -0
  148. auditkit-1.0.0/src/auditkit/router.py +54 -0
  149. auditkit-1.0.0/src/auditkit/runner.py +575 -0
  150. auditkit-1.0.0/src/auditkit/runspec.py +159 -0
  151. auditkit-1.0.0/src/auditkit/sample.py +40 -0
  152. auditkit-1.0.0/src/auditkit/scenario.py +88 -0
  153. auditkit-1.0.0/src/auditkit/scenarios/README.md +10 -0
  154. auditkit-1.0.0/src/auditkit/scenarios/__init__.py +4 -0
  155. auditkit-1.0.0/src/auditkit/scenarios/arc.py +33 -0
  156. auditkit-1.0.0/src/auditkit/scenarios/gsm8k.py +32 -0
  157. auditkit-1.0.0/src/auditkit/scenarios/hellaswag.py +33 -0
  158. auditkit-1.0.0/src/auditkit/scenarios/humaneval.py +32 -0
  159. auditkit-1.0.0/src/auditkit/scenarios/mmlu.py +34 -0
  160. auditkit-1.0.0/src/auditkit/scenarios/truthfulqa.py +33 -0
  161. auditkit-1.0.0/src/auditkit/score.py +165 -0
  162. auditkit-1.0.0/src/auditkit/scorers.py +117 -0
  163. auditkit-1.0.0/src/auditkit/scoring.py +79 -0
  164. auditkit-1.0.0/src/auditkit/types.py +69 -0
  165. auditkit-1.0.0/tests/README.md +16 -0
  166. auditkit-1.0.0/tests/__init__.py +0 -0
  167. auditkit-1.0.0/tests/test_adapter.py +35 -0
  168. auditkit-1.0.0/tests/test_adapter_params.py +69 -0
  169. auditkit-1.0.0/tests/test_annotator.py +732 -0
  170. auditkit-1.0.0/tests/test_api.py +355 -0
  171. auditkit-1.0.0/tests/test_api_backend.py +108 -0
  172. auditkit-1.0.0/tests/test_benchmark.py +339 -0
  173. auditkit-1.0.0/tests/test_chat_messages.py +289 -0
  174. auditkit-1.0.0/tests/test_cli.py +92 -0
  175. auditkit-1.0.0/tests/test_code_metrics.py +365 -0
  176. auditkit-1.0.0/tests/test_compare.py +624 -0
  177. auditkit-1.0.0/tests/test_comparison.py +558 -0
  178. auditkit-1.0.0/tests/test_core_engine.py +88 -0
  179. auditkit-1.0.0/tests/test_custom_judge_pipeline.py +156 -0
  180. auditkit-1.0.0/tests/test_diff.py +257 -0
  181. auditkit-1.0.0/tests/test_embedding_metrics.py +110 -0
  182. auditkit-1.0.0/tests/test_encoder_judge.py +643 -0
  183. auditkit-1.0.0/tests/test_errors.py +27 -0
  184. auditkit-1.0.0/tests/test_evaluate_many.py +109 -0
  185. auditkit-1.0.0/tests/test_execute_concurrency.py +68 -0
  186. auditkit-1.0.0/tests/test_experiment.py +106 -0
  187. auditkit-1.0.0/tests/test_fingerprint_stability.py +86 -0
  188. auditkit-1.0.0/tests/test_generation_kwargs.py +884 -0
  189. auditkit-1.0.0/tests/test_generation_metrics.py +116 -0
  190. auditkit-1.0.0/tests/test_guard.py +433 -0
  191. auditkit-1.0.0/tests/test_hallucination_metrics.py +30 -0
  192. auditkit-1.0.0/tests/test_hf_gen_logits_sanitizer.py +137 -0
  193. auditkit-1.0.0/tests/test_hf_wire_format.py +55 -0
  194. auditkit-1.0.0/tests/test_integration.py +237 -0
  195. auditkit-1.0.0/tests/test_judge.py +100 -0
  196. auditkit-1.0.0/tests/test_judge_flow.py +109 -0
  197. auditkit-1.0.0/tests/test_llm_judge.py +282 -0
  198. auditkit-1.0.0/tests/test_lmeval_engine.py +506 -0
  199. auditkit-1.0.0/tests/test_lmeval_real_pipeline.py +147 -0
  200. auditkit-1.0.0/tests/test_loaders.py +79 -0
  201. auditkit-1.0.0/tests/test_metric.py +73 -0
  202. auditkit-1.0.0/tests/test_metrics_via_pipeline.py +283 -0
  203. auditkit-1.0.0/tests/test_model.py +160 -0
  204. auditkit-1.0.0/tests/test_model_backends.py +107 -0
  205. auditkit-1.0.0/tests/test_pairwise_metrics.py +120 -0
  206. auditkit-1.0.0/tests/test_pipeline_live_hf.py +319 -0
  207. auditkit-1.0.0/tests/test_practical.py +135 -0
  208. auditkit-1.0.0/tests/test_rag_metrics.py +149 -0
  209. auditkit-1.0.0/tests/test_redteam.py +103 -0
  210. auditkit-1.0.0/tests/test_registry.py +71 -0
  211. auditkit-1.0.0/tests/test_release.py +163 -0
  212. auditkit-1.0.0/tests/test_router.py +72 -0
  213. auditkit-1.0.0/tests/test_runner.py +424 -0
  214. auditkit-1.0.0/tests/test_sample.py +47 -0
  215. auditkit-1.0.0/tests/test_scenarios.py +35 -0
  216. auditkit-1.0.0/tests/test_score.py +107 -0
  217. auditkit-1.0.0/tests/test_security_perf.py +139 -0
  218. auditkit-1.0.0/tests/test_token_usage_and_cost.py +224 -0
  219. auditkit-1.0.0/tests/test_toxicity_metrics.py +130 -0
  220. auditkit-1.0.0/tests/test_types.py +19 -0
@@ -0,0 +1,376 @@
1
+ name: Automated patch release
2
+
3
+ on:
4
+ pull_request_target:
5
+ branches: [main]
6
+ types: [closed]
7
+ workflow_dispatch:
8
+
9
+ concurrency:
10
+ group: auditkit-patch-release
11
+ cancel-in-progress: false
12
+
13
+ permissions:
14
+ contents: read
15
+ pull-requests: read
16
+
17
+ env:
18
+ PYPI_PROJECT_NAME: auditkit
19
+ PACKAGE_DISPLAY_NAME: auditkit
20
+
21
+ jobs:
22
+ plan:
23
+ name: Inspect release state
24
+ if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true
25
+ runs-on: ubuntu-latest
26
+ outputs:
27
+ action: ${{ steps.plan.outputs.action }}
28
+ version: ${{ steps.plan.outputs.version }}
29
+ state: ${{ steps.plan.outputs.state }}
30
+ reason: ${{ steps.plan.outputs.reason }}
31
+ source-ref: ${{ steps.plan.outputs.source-ref }}
32
+ tag-exists: ${{ steps.plan.outputs.tag-exists }}
33
+ release-exists: ${{ steps.plan.outputs.release-exists }}
34
+ pypi-exists: ${{ steps.plan.outputs.pypi-exists }}
35
+ steps:
36
+ - name: Check out the trusted merged source
37
+ uses: actions/checkout@v6
38
+ with:
39
+ ref: ${{ github.event.pull_request.merge_commit_sha || github.ref }}
40
+ fetch-depth: 0
41
+ persist-credentials: false
42
+
43
+ - uses: actions/setup-python@v6
44
+ with:
45
+ python-version: "3.12"
46
+
47
+ - name: Classify trigger and external release state
48
+ id: plan
49
+ env:
50
+ GH_TOKEN: ${{ github.token }}
51
+ EVENT_NAME: ${{ github.event_name }}
52
+ shell: bash
53
+ run: |
54
+ set -euo pipefail
55
+ current_version=$(python scripts/release.py current-version)
56
+ source_sha=$(git rev-parse HEAD)
57
+ trigger=dispatch
58
+ requested_version=$current_version
59
+
60
+ if [[ "$EVENT_NAME" == "pull_request_target" ]]; then
61
+ trigger=normal
62
+ fi
63
+
64
+ latest_response=$(mktemp)
65
+ latest_status=$(curl --silent --show-error --location \
66
+ --header "Authorization: Bearer $GH_TOKEN" \
67
+ --header "Accept: application/vnd.github+json" \
68
+ --output "$latest_response" --write-out '%{http_code}' \
69
+ "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest")
70
+ if [[ "$latest_status" == "200" ]]; then
71
+ latest_version=$(python -c \
72
+ 'import json,sys; print(json.load(open(sys.argv[1]))["tag_name"])' \
73
+ "$latest_response")
74
+ requested_version=$(python -c \
75
+ 'import sys; from scripts.release import next_patch; print(next_patch(sys.argv[1]))' \
76
+ "$latest_version")
77
+
78
+ if git show-ref --verify --quiet "refs/tags/$latest_version"; then
79
+ latest_commit=$(git rev-list -n 1 "$latest_version")
80
+ latest_parent=$(git rev-parse "$latest_commit^" 2>/dev/null || true)
81
+ if [[ "$latest_commit" == "$source_sha" || "$latest_parent" == "$source_sha" ]]; then
82
+ requested_version=$latest_version
83
+ fi
84
+ fi
85
+ elif [[ "$latest_status" != "404" ]]; then
86
+ echo "::error::Latest GitHub release lookup failed with HTTP $latest_status."
87
+ exit 1
88
+ fi
89
+
90
+ tag_exists=false
91
+ tag_annotated=true
92
+ tag_matches_source=true
93
+ source_ref=$source_sha
94
+ if git show-ref --verify --quiet "refs/tags/$requested_version"; then
95
+ tag_exists=true
96
+ source_ref="refs/tags/$requested_version"
97
+ if [[ "$(git cat-file -t "$requested_version")" != "tag" ]]; then
98
+ tag_annotated=false
99
+ fi
100
+ tag_commit=$(git rev-list -n 1 "$requested_version")
101
+ tag_parent=$(git rev-parse "$tag_commit^" 2>/dev/null || true)
102
+ if [[ "$tag_commit" != "$source_sha" && "$tag_parent" != "$source_sha" ]]; then
103
+ tag_matches_source=false
104
+ fi
105
+
106
+ version_tree=$(mktemp -d)
107
+ mkdir -p "$version_tree/src/auditkit" "$version_tree/scripts"
108
+ cp scripts/release.py "$version_tree/scripts/release.py"
109
+ for version_file in pyproject.toml src/auditkit/__init__.py CITATION.cff; do
110
+ git show "$requested_version:$version_file" > "$version_tree/$version_file"
111
+ done
112
+ if ! (cd "$version_tree" && python scripts/release.py validate-version "$requested_version"); then
113
+ tag_matches_source=false
114
+ fi
115
+ fi
116
+
117
+ release_response=$(mktemp)
118
+ release_status=$(curl --silent --show-error --location \
119
+ --header "Authorization: Bearer $GH_TOKEN" \
120
+ --header "Accept: application/vnd.github+json" \
121
+ --output "$release_response" --write-out '%{http_code}' \
122
+ "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/tags/$requested_version")
123
+ release_exists=false
124
+ release_matches_tag=true
125
+ if [[ "$release_status" == "200" ]]; then
126
+ release_exists=true
127
+ if ! python - "$release_response" "$requested_version" <<'PY'
128
+ import json
129
+ import sys
130
+
131
+ release = json.load(open(sys.argv[1], encoding="utf-8"))
132
+ expected = sys.argv[2]
133
+ valid = (
134
+ release.get("tag_name") == expected
135
+ and release.get("name") == expected
136
+ and isinstance(release.get("draft"), bool)
137
+ and release.get("prerelease") is False
138
+ )
139
+ raise SystemExit(0 if valid else 1)
140
+ PY
141
+ then
142
+ release_matches_tag=false
143
+ fi
144
+ elif [[ "$release_status" != "404" ]]; then
145
+ echo "::error::GitHub release lookup failed with HTTP $release_status."
146
+ exit 1
147
+ fi
148
+
149
+ pypi_response=$(mktemp)
150
+ pypi_status=$(curl --silent --show-error --location \
151
+ --output "$pypi_response" --write-out '%{http_code}' \
152
+ "https://pypi.org/pypi/$PYPI_PROJECT_NAME/$requested_version/json")
153
+ pypi_exists=false
154
+ if [[ "$pypi_status" == "200" ]]; then
155
+ pypi_exists=true
156
+ python - "$pypi_response" "$requested_version" <<'PY'
157
+ import json
158
+ import sys
159
+
160
+ payload = json.load(open(sys.argv[1], encoding="utf-8"))
161
+ if payload.get("info", {}).get("version") != sys.argv[2]:
162
+ raise SystemExit("PyPI returned metadata for an unexpected version")
163
+ PY
164
+ elif [[ "$pypi_status" != "404" ]]; then
165
+ echo "::error::PyPI lookup failed with HTTP $pypi_status."
166
+ exit 1
167
+ fi
168
+
169
+ decision=$(python scripts/release.py plan \
170
+ --trigger "$trigger" --version "$requested_version" \
171
+ --tag "$tag_exists" --release "$release_exists" --pypi "$pypi_exists" \
172
+ --tag-annotated "$tag_annotated" \
173
+ --tag-matches-source "$tag_matches_source" \
174
+ --release-matches-tag "$release_matches_tag")
175
+
176
+ action=$(python -c 'import json,sys; print(json.loads(sys.argv[1])["action"])' "$decision")
177
+ version=$(python -c 'import json,sys; print(json.loads(sys.argv[1])["version"])' "$decision")
178
+ state=$(python -c 'import json,sys; print(json.loads(sys.argv[1])["state"])' "$decision")
179
+ reason=$(python -c 'import json,sys; print(json.loads(sys.argv[1])["reason"])' "$decision")
180
+ {
181
+ echo "action=$action"
182
+ echo "version=$version"
183
+ echo "state=$state"
184
+ echo "reason=$reason"
185
+ echo "source-ref=$source_ref"
186
+ echo "tag-exists=$tag_exists"
187
+ echo "release-exists=$release_exists"
188
+ echo "pypi-exists=$pypi_exists"
189
+ } >> "$GITHUB_OUTPUT"
190
+ echo "Release decision: action=$action version=$version state=$state reason=$reason"
191
+
192
+ release:
193
+ name: Build, release, and publish
194
+ needs: plan
195
+ if: needs.plan.outputs.action == 'release'
196
+ runs-on: ubuntu-latest
197
+ permissions:
198
+ contents: write
199
+ env:
200
+ RELEASE_TAG: ${{ needs.plan.outputs.version }}
201
+ steps:
202
+ - name: Check out exact release source
203
+ uses: actions/checkout@v6
204
+ with:
205
+ ref: ${{ needs.plan.outputs.source-ref }}
206
+ fetch-depth: 0
207
+
208
+ - uses: actions/setup-python@v6
209
+ with:
210
+ python-version: "3.12"
211
+
212
+ - name: Prepare exact release version
213
+ shell: bash
214
+ run: |
215
+ set -euo pipefail
216
+ current_version=$(python scripts/release.py current-version)
217
+ if [[ "$current_version" != "$RELEASE_TAG" ]]; then
218
+ python scripts/release.py set-version "$RELEASE_TAG"
219
+ expected_files=$'CITATION.cff\npyproject.toml\nsrc/auditkit/__init__.py'
220
+ actual_files=$(git diff --name-only | sort)
221
+ if [[ "$actual_files" != "$expected_files" ]]; then
222
+ echo "::error::Version helper changed files outside the authoritative version set."
223
+ exit 1
224
+ fi
225
+ git config user.name github-actions[bot]
226
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
227
+ git add CITATION.cff pyproject.toml src/auditkit/__init__.py
228
+ git commit -m "Release $RELEASE_TAG"
229
+ fi
230
+ python scripts/release.py validate-version "$RELEASE_TAG"
231
+
232
+ # Tests are intentionally skipped in the release workflow to avoid delaying
233
+ # GitHub releases and PyPI publication.
234
+ # - name: Install project test dependencies
235
+ # continue-on-error: true
236
+ # run: python -m pip install -e ".[dev]"
237
+
238
+ # - name: Run project test suite (advisory)
239
+ # continue-on-error: true
240
+ # run: python -m pytest
241
+
242
+ - name: Install mandatory packaging tools
243
+ run: python -m pip install --upgrade build twine
244
+
245
+ - name: Build and validate distributions
246
+ run: |
247
+ python -m build
248
+ python -m twine check dist/*
249
+ python scripts/release.py validate-dist "$RELEASE_TAG" --project-name "$PYPI_PROJECT_NAME" dist/*
250
+
251
+ - name: Create or verify annotated tag
252
+ env:
253
+ GH_TOKEN: ${{ github.token }}
254
+ shell: bash
255
+ run: |
256
+ set -euo pipefail
257
+ expected_sha=$(git rev-parse HEAD)
258
+ git fetch --force origin "refs/tags/$RELEASE_TAG:refs/tags/$RELEASE_TAG" 2>/dev/null || true
259
+ if git show-ref --verify --quiet "refs/tags/$RELEASE_TAG"; then
260
+ if [[ "$(git cat-file -t "$RELEASE_TAG")" != "tag" ]]; then
261
+ echo "::error::Existing $RELEASE_TAG is not an annotated tag."
262
+ exit 1
263
+ fi
264
+ if [[ "$(git rev-list -n 1 "$RELEASE_TAG")" != "$expected_sha" ]]; then
265
+ echo "::error::Existing $RELEASE_TAG points at a different commit; it will not be moved."
266
+ exit 1
267
+ fi
268
+ else
269
+ git config user.name github-actions[bot]
270
+ git config user.email 41898282+github-actions[bot]@users.noreply.github.com
271
+ git tag --annotate "$RELEASE_TAG" --message "auditkit $RELEASE_TAG"
272
+ git push origin "refs/tags/$RELEASE_TAG"
273
+ fi
274
+
275
+ - name: Create or verify GitHub release
276
+ env:
277
+ GH_TOKEN: ${{ github.token }}
278
+ shell: bash
279
+ run: |
280
+ set -euo pipefail
281
+ if gh release view "$RELEASE_TAG" \
282
+ --json databaseId,tagName,name,isDraft,isPrerelease > release.json 2>/dev/null; then
283
+ release_state=$(python - "$RELEASE_TAG" <<'PY'
284
+ import json
285
+ import sys
286
+
287
+ release = json.load(open("release.json", encoding="utf-8"))
288
+ expected = sys.argv[1]
289
+ valid = (
290
+ release.get("tagName") == expected
291
+ and release.get("name") == expected
292
+ and isinstance(release.get("isDraft"), bool)
293
+ and release.get("isPrerelease") is False
294
+ and isinstance(release.get("databaseId"), int)
295
+ )
296
+ if not valid:
297
+ raise SystemExit(f"Existing GitHub release conflicts with {expected}: {release}")
298
+ print("draft" if release["isDraft"] else "published")
299
+ PY
300
+ )
301
+ if [[ "$release_state" == "draft" ]]; then
302
+ release_id=$(python -c 'import json; print(json.load(open("release.json"))["databaseId"])')
303
+ gh api --method PATCH "repos/$GITHUB_REPOSITORY/releases/$release_id" \
304
+ --field draft=false --silent
305
+ echo "Published existing draft GitHub release $RELEASE_TAG."
306
+ fi
307
+ else
308
+ gh release create "$RELEASE_TAG" --verify-tag --generate-notes --title "$RELEASE_TAG"
309
+ fi
310
+
311
+ - name: Publish the exact distributions to PyPI
312
+ if: needs.plan.outputs.pypi-exists == 'false'
313
+ env:
314
+ TWINE_USERNAME: __token__
315
+ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
316
+ shell: bash
317
+ run: |
318
+ set -euo pipefail
319
+ : "${TWINE_PASSWORD:?PYPI_API_TOKEN is required to publish the release}"
320
+ python -m twine upload --non-interactive --verbose dist/*
321
+
322
+ # The version-bump commit created above (if any) only exists on this
323
+ # detached checkout so far; fast-forward main with it so the tracked
324
+ # version files don't silently drift behind the release that was just
325
+ # tagged and published. This is push-only and never forced: if main
326
+ # has moved on (a race with a new merge) or branch protection blocks
327
+ # a direct push, git rejects the push and we just warn instead of
328
+ # failing an otherwise-successful release.
329
+ - name: Sync release version bump back to main
330
+ if: needs.plan.outputs.tag-exists == 'false'
331
+ continue-on-error: true
332
+ env:
333
+ GH_TOKEN: ${{ github.token }}
334
+ shell: bash
335
+ run: |
336
+ set -euo pipefail
337
+ if git push origin HEAD:main; then
338
+ echo "Synced the $RELEASE_TAG version bump back to main."
339
+ else
340
+ echo "::warning::Could not fast-forward main with the $RELEASE_TAG version bump (branch protection or a race with a new merge). main's version files may still show the previous version; sync them manually, e.g. via 'python scripts/release.py set-version $RELEASE_TAG'."
341
+ fi
342
+
343
+ - name: Send release notes to Slack
344
+ uses: slackapi/slack-github-action@v1.24.0
345
+ continue-on-error: true
346
+ with:
347
+ channel-id: "lexsi-labs-auditkit-release" #${{ vars.SLACK_CHANNEL }}
348
+ payload: |
349
+ {
350
+ "text": "Auditkit release",
351
+ "blocks": [
352
+ {
353
+ "type": "section",
354
+ "text": {
355
+ "type": "mrkdwn",
356
+ "text": "*Version:* ${{ env.RELEASE_TAG }}"
357
+ }
358
+ },
359
+ {
360
+ "type": "section",
361
+ "text": {
362
+ "type": "mrkdwn",
363
+ "text": "*Release:* https://github.com/${{ github.repository }}/releases/tag/${{ env.RELEASE_TAG }}"
364
+ }
365
+ },
366
+ {
367
+ "type": "section",
368
+ "text": {
369
+ "type": "mrkdwn",
370
+ "text": "*PyPI:* https://pypi.org/project/auditkit/${{ env.RELEASE_TAG }}/"
371
+ }
372
+ }
373
+ ]
374
+ }
375
+ env:
376
+ SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
@@ -0,0 +1,17 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ venv/
6
+ *.egg-info/
7
+ build/
8
+ dist/
9
+ .pytest_cache/
10
+ .mypy_cache/
11
+ .ruff_cache/
12
+ .coverage
13
+ # OS / editor
14
+ .DS_Store
15
+ .idea/
16
+ .vscode/
17
+ site/
@@ -0,0 +1,94 @@
1
+ # Agent instructions — AuditKit (release v1.0.0)
2
+
3
+ AuditKit is a standalone Python library that evaluates any model on any dataset
4
+ across any technique. The core runs on the standard library with **zero required
5
+ third-party dependencies**; model backends and heavy metrics are optional extras.
6
+
7
+ ## Architecture — the 5-stage spine
8
+
9
+ `Dataset → Adapter → Model → Metrics → RunResult`, orchestrated by `ak.evaluate()`.
10
+
11
+ - **Dataset** — prompts and expected outputs (a YAML file, a Python list, or a loader).
12
+ - **Adapter** — the elicitation technique: benchmark, LLM-as-judge (`GEval`), code
13
+ checks, RAG, hallucination, embedding similarity, toxicity/bias, pairwise/preference,
14
+ red-teaming, security, performance.
15
+ - **Model** — 9 backends resolved by `AutoModel.resolve()`: `openai:`, `anthropic:`,
16
+ `hf:`, `lexsi:`, `vllm:`, `litellm:` (also reaches Ollama), `api:`, `groq:`,
17
+ `openrouter:`. Any `list[str] → list[str]` callable also works; `echo` is the
18
+ dependency-free stub for tests.
19
+ - **Metrics** — every metric subclasses `auditkit.metric.Metric` (10 families).
20
+ - **RunResult** — aggregate scores, per-sample rows, and `perf` (latency/throughput).
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ pip install auditkit # core, zero deps
26
+ pip install "auditkit[openai]" # one backend
27
+ pip install "auditkit[all]" # all backends + heavy metrics
28
+ ```
29
+
30
+ ## Quickstart
31
+
32
+ ```python
33
+ import auditkit as ak
34
+
35
+ result = ak.evaluate(
36
+ model="echo", # or "openai:gpt-4o-mini", "hf:Qwen/Qwen2.5-0.5B", ...
37
+ prompts=["2+2=", "capital of France?"],
38
+ metrics=[ak.Contains("4"), ak.Contains("Paris")],
39
+ )
40
+ print(result.summary())
41
+ ```
42
+
43
+ ## CLI
44
+
45
+ ```bash
46
+ auditkit eval config.yaml # run a YAML-defined evaluation
47
+ auditkit init # scaffold a config
48
+ auditkit list # list available metrics/backends
49
+ auditkit compare ... # compare models
50
+ auditkit redteam ... # red-team probes
51
+ ```
52
+
53
+ ## Test
54
+
55
+ ```bash
56
+ python -m pytest tests/ -q --tb=short # pyproject sets pythonpath=src; use python3 on Unix
57
+ ```
58
+
59
+ ~53 test modules under `tests/`. The CLI subprocess tests need an editable install
60
+ (`pip install -e .`). Some `test_extra_not_installed` checks fail on machines that
61
+ have optional extras (e.g. `transformers`) installed globally — that is expected.
62
+
63
+ ## Conventions
64
+
65
+ - `from __future__ import annotations` at the top of every module.
66
+ - **Zero required third-party deps.** Never import an optional extra at module top
67
+ level — import it lazily inside the function that needs it, and raise a clear error
68
+ if the extra is missing.
69
+ - Metrics inherit `auditkit.metric.Metric`; models inherit `auditkit.model.Model`.
70
+ Register new ones through `registry.py` / `router.py`.
71
+ - One test file per module or feature area, in `tests/`.
72
+ - **Version lives in two places, keep them in sync:** `src/auditkit/__init__.py`
73
+ (`__version__`) and `pyproject.toml` (`version`).
74
+
75
+ ## Module map (`src/auditkit/`)
76
+
77
+ | Module | Role |
78
+ |--------|------|
79
+ | `api.py` | Public `ak.evaluate()` surface |
80
+ | `runner.py`, `runspec.py` | Execution engine and run configuration |
81
+ | `adapter.py`, `scenario.py` | Elicitation techniques and scenarios |
82
+ | `model/`, `router.py`, `registry.py` | Model backends and resolution |
83
+ | `metric.py`, `metrics/`, `scorers.py`, `scoring.py` | Metrics and scoring |
84
+ | `comparison.py`, `model_compare.py`, `diff.py` | Model comparison |
85
+ | `redteam/` | Red-team probes |
86
+ | `report.py`, `report_format.py` | Result rendering |
87
+ | `cli.py`, `__main__.py` | Command-line interface |
88
+
89
+ ## License
90
+
91
+ Released under the **Lexsi Labs Source Available License (LSAL) v1.2** — free for
92
+ academic research and teaching (MIT-like); organizations must acknowledge their use
93
+ or obtain permission (Section 1A); commercial use requires a separate license. See
94
+ [LICENSE.md](LICENSE.md).
@@ -0,0 +1,36 @@
1
+ cff-version: 1.2.0
2
+ title: AuditKit
3
+ abstract: |
4
+ AuditKit is a Python library for evaluating and auditing AI models: a unified
5
+ evaluation spine across techniques and modalities. It provides 10 metric
6
+ families, 9 model backends, LLM-as-judge and encoder-judge scorers, a CLI with
7
+ YAML-configured runs, and an MkDocs documentation site.
8
+ type: software
9
+ message: "If you use this software, please cite it."
10
+
11
+ version: 1.0.0
12
+
13
+ authors:
14
+ - family-names: "Avaiya"
15
+ given-names: "Utsav"
16
+ - family-names: "Arora"
17
+ given-names: "Shreeyans"
18
+ - family-names: "Kadiyala"
19
+ given-names: "Ram Mohan Rao"
20
+ - family-names: "Lyngkhoi"
21
+ given-names: "Zera"
22
+ - family-names: "Sankarapu"
23
+ given-names: "Vinay Kumar"
24
+ - family-names: "Seth"
25
+ given-names: "Pratinav"
26
+ email: "pratinav.seth@lexsi.ai"
27
+
28
+ contact:
29
+ - family-names: "Seth"
30
+ given-names: "Pratinav"
31
+ email: "pratinav.seth@lexsi.ai"
32
+
33
+ repository-code: "https://github.com/Lexsi-Labs/AuditKIT"
34
+ url: "https://github.com/Lexsi-Labs/AuditKIT"
35
+ license: LSAL-1.2
36
+ license-url: "https://github.com/Lexsi-Labs/AuditKIT/blob/main/LICENSE.md"
@@ -0,0 +1,92 @@
1
+ # Lexsi Labs Source Available License (LSAL), Version 1.2 (AuditKit)
2
+
3
+ ## Preamble
4
+
5
+ This Source Available License governs use of the software known as **AuditKit**, together with its documentation, CLI, and example pipelines (collectively, the "Licensed Work"), developed and owned by **Lexsi Labs (Lithasa Technologies Pvt. Ltd.)** ("Licensor").
6
+
7
+ This is **not** an open-source license as defined by the [Open Source Initiative (OSI)](https://opensource.org/). It grants **academic research and teaching** MIT-like permissions: free use, modification, and redistribution with the notice intact. Organizations must acknowledge their use or obtain permission (Section 1A). It also bars commercial exploitation.
8
+
9
+ ---
10
+
11
+ ## 1. Grant of Rights
12
+
13
+ Subject to the terms of this License, permission is hereby granted, free of charge, to any person obtaining a copy of the Licensed Work, to use, copy, modify, merge, publish, and redistribute the Licensed Work and derivative works thereof, **for Noncommercial Purposes only**, provided that the above copyright notice and this License are included in full in all copies or substantial portions of the Licensed Work.
14
+
15
+ For academic research and teaching, this grant is MIT-like: you may use, modify, and redistribute the Licensed Work, provided the copyright notice and this License travel with every copy.
16
+
17
+ **Noncommercial Purposes** means:
18
+
19
+ * personal use for research, experimentation, private study, or hobby projects;
20
+ * academic and scholarly research, teaching, and publication (including use in papers, theses, benchmarks, and reproducibility artifacts).
21
+
22
+ Research and teaching by academics and their groups, including work done at a university or public research body, falls under this Section. Section 1A governs use by an organization as such, including a charitable organization, educational institution, public research organization, or government body acting for its own operations.
23
+
24
+ ## 1A. Use by Organizations
25
+
26
+ Before any organization, including a charitable organization, educational institution, public research organization, or government body, uses the Licensed Work for **internal evaluation, red-teaming, benchmarking, auditing, or any use in connection with developing, evaluating, or safeguarding its own models, products, or services**, whether or not it charges a fee or provides the Licensed Work to third parties, it must either:
27
+
28
+ * obtain Licensor's **prior written permission**; or
29
+ * provide Licensor a written **acknowledgement of use**, identifying the organization, the intended use, and an undertaking to attribute the Licensed Work, which Licensor may accept in place of negotiated permission.
30
+
31
+ Both go to **support@lexsi.ai**.
32
+
33
+ Licensor grants permission at its discretion. The written permission sets out the terms, which may include sharing with Licensor the evaluation results the Licensed Work produces, in AuditKit's standard report format, excluding model weights, training data, prompt text, and model generations. Licensor uses shared results for research and for improving the Licensed Work, and handles them under the terms stated in the written permission.
34
+
35
+ Permission under this Section does not authorize any use described in Section 2.
36
+
37
+ ## 2. Commercial Restriction
38
+
39
+ Without a separate **commercial license** from Lexsi Labs, you may **not** Sell the Licensed Work. "**Sell**" means practicing any right granted to you under this License to provide to third parties, for a fee or other consideration, a product or service whose value derives, entirely or substantially, from the functionality of the Licensed Work, including:
40
+
41
+ * offering the Licensed Work, or a derivative of it, as a commercial product, paid service, SaaS, hosted, or API offering;
42
+ * embedding the Licensed Work in proprietary or revenue-generating software;
43
+ * paid consulting or support whose substance is the Licensed Work.
44
+
45
+ If you redistribute a modified version, you must mark it as modified and must not present it as the original. You may also not **re-license, rebrand, or redistribute** the Licensed Work under different terms, nor use **Lexsi Labs**, **AuditKit**, or related trademarks, logos, or branding except to identify unmodified, licensed copies.
46
+
47
+ ## 3. Patents
48
+
49
+ NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. Any patent rights of Licensor relating to the Licensed Work are reserved and may be licensed only under a separate written agreement with Licensor.
50
+
51
+ ## 3A. Third-Party Components
52
+
53
+ The Licensed Work evaluates and audits third-party base models and draws on third-party benchmarks and datasets. Each carries its own license, and this License grants no rights under any of them. You must comply with those terms in addition to this License, including any restrictions a base-model or dataset license places on your use of it.
54
+
55
+ ## 4. Ownership
56
+
57
+ All rights, title, and interest in and to the Licensed Work remain with **Lithasa Technologies Pvt. Ltd.** Except as expressly stated in Sections 1 and 1A, nothing in this License transfers ownership or any other rights to the Licensee.
58
+
59
+ ## 5. Contributions
60
+
61
+ If you submit modifications, pull requests, or patches ("Contributions") to Lexsi Labs, you grant Lexsi Labs a perpetual, worldwide, royalty-free right to use, modify, distribute, and license your Contributions under any terms, including commercial ones, and you represent that you have the right to make such Contributions.
62
+
63
+ ## 6. Warranty Disclaimer and Responsibility for Use
64
+
65
+ THE LICENSED WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE LICENSOR OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE LICENSED WORK OR THE USE OR OTHER DEALINGS IN THE LICENSED WORK.
66
+
67
+ **You alone are responsible for your use of the Licensed Work.** This includes every evaluation, audit, output, or system you produce with it, and your compliance with applicable law. This responsibility applies to academic, personal, organizational, and commercial use alike. Licensor has no duty to monitor your use and bears no liability for misuse of the Licensed Work by you or by any third party who obtained it through you.
68
+
69
+ The Licensed Work is a research and auditing tool. Any measurements or findings it reports hold only under the conditions you configure. They do not certify that any model is safe to deploy; that decision rests with you.
70
+
71
+ If you use the Licensed Work under Section 1A or under a commercial license, you will, to the extent permitted by applicable law, indemnify and hold harmless Licensor and its contributors against any claim, loss, or expense, including legal fees, arising from your use or misuse of the Licensed Work or from any breach of this License by you. This indemnity does not apply to personal or academic use under Section 1; the two preceding paragraphs govern that use.
72
+
73
+ ## 7. Termination
74
+
75
+ This License terminates without notice if you breach any of its terms. On termination, you must stop using the Licensed Work and destroy every copy in your possession. Licenses of parties who received the Licensed Work from you remain in force provided they remain in compliance.
76
+
77
+ Sections 3, 3A, 4, 5, 6, and 8 survive termination.
78
+
79
+ ## 8. Governing Law and General Terms
80
+
81
+ This License shall be governed by and construed in accordance with the **laws of India**, without regard to its conflict of law principles. If a court holds any provision of this License unenforceable, the remaining provisions stay in effect. Licensor may publish revised versions of this License; a copy of the Licensed Work remains under the version it was received under unless you accept a later version.
82
+
83
+ ## 9. Contact
84
+
85
+ For acknowledgements and permission requests under Section 1A, and for commercial use, partnership, or redistribution rights under Section 2, contact:
86
+ **support@lexsi.ai** · **https://lexsi.ai**
87
+
88
+ ## 10. Notice
89
+
90
+ **AuditKit** © 2026 **Lithasa Technologies Pvt. Ltd.**
91
+ Licensed under the **Lexsi Labs Source Available License (LSAL) v1.2**.
92
+ **Academic research and teaching are free on MIT-like terms. Use by any organization requires written acknowledgement or permission (Section 1A). Commercial use requires a commercial license (Section 2).**