ablate-llm 0.3.0__tar.gz → 0.3.1__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.
- {ablate_llm-0.3.0/src/ablate_llm.egg-info → ablate_llm-0.3.1}/PKG-INFO +40 -6
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/README.md +39 -5
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/pyproject.toml +1 -1
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/__init__.py +1 -1
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/hub.py +65 -3
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/pipeline.py +1 -1
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/ui/server.py +5 -2
- {ablate_llm-0.3.0 → ablate_llm-0.3.1/src/ablate_llm.egg-info}/PKG-INFO +40 -6
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/LICENSE +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/setup.cfg +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/_data/__init__.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/_data/harmful.txt +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/_data/harmless.txt +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/cli.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/config.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/data.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/evaluate.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/extract.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/harness.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/hooks.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/judges.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/model.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/optimize.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/subspace.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/ui/__init__.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/ui/static/architecture.svg +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/ui/static/index.html +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/ui/static/logo-dark.png +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/ui/static/logo-light.png +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/utils.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate/weights.py +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate_llm.egg-info/SOURCES.txt +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate_llm.egg-info/dependency_links.txt +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate_llm.egg-info/entry_points.txt +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate_llm.egg-info/requires.txt +0 -0
- {ablate_llm-0.3.0 → ablate_llm-0.3.1}/src/ablate_llm.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ablate-llm
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Directional ablation (abliteration) toolkit for open-source language models: extract, ablate, and optimize the removal of refusal / behavioral directions in the residual stream.
|
|
5
5
|
Author: AI Anytime
|
|
6
6
|
License: Proprietary
|
|
@@ -50,7 +50,7 @@ Dynamic: license-file
|
|
|
50
50
|
|
|
51
51
|
<h1 align="center">Ablate</h1>
|
|
52
52
|
|
|
53
|
-
<p align="center"><b>Directional ablation (abliteration) toolkit for automatic censorship removal of open-source language models.</b></p>
|
|
53
|
+
<p align="center"><b>Directional ablation (abliteration) toolkit for automatic censorship removal of open-source language models (SLMs/LLMs).</b></p>
|
|
54
54
|
|
|
55
55
|
<p align="center">
|
|
56
56
|
<a href="https://pypi.org/project/ablate-llm/"><img alt="PyPI" src="https://img.shields.io/pypi/v/ablate-llm.svg?color=7c5cff"></a>
|
|
@@ -59,19 +59,26 @@ Dynamic: license-file
|
|
|
59
59
|
</p>
|
|
60
60
|
|
|
61
61
|
<p align="center">
|
|
62
|
+
<a href="https://aianytime.github.io/ablate/">🌐 Website</a> •
|
|
62
63
|
<a href="https://pypi.org/project/ablate-llm/">📦 PyPI</a> •
|
|
63
64
|
<a href="https://huggingface.co/ai-anytime/qwen-1.5b-abliterated">🤗 Model</a> •
|
|
64
65
|
<a href="https://youtu.be/1-1bM3Ynql4">▶️ Video walkthrough</a> •
|
|
66
|
+
<a href="https://dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y">🎤 Dubai AI Tinkerers talk</a> •
|
|
65
67
|
<a href="#citation">📚 Cite</a>
|
|
66
68
|
</p>
|
|
67
69
|
|
|
68
70
|
<p align="center"><i>Created with 💜 by <b>AI Anytime</b></i></p>
|
|
69
71
|
|
|
70
72
|
<p align="center">
|
|
71
|
-
<a href="https://youtu.be/
|
|
72
|
-
<img
|
|
73
|
+
<a href="https://youtu.be/_pLKCRgzu6A">
|
|
74
|
+
<img
|
|
75
|
+
src="https://img.youtube.com/vi/_pLKCRgzu6A/maxresdefault.jpg"
|
|
76
|
+
alt="Ablate — Full YouTube Walkthrough"
|
|
77
|
+
width="800"
|
|
78
|
+
/>
|
|
73
79
|
</a>
|
|
74
|
-
<br
|
|
80
|
+
<br />
|
|
81
|
+
<i>▶️ Watch the full walkthrough on YouTube</i>
|
|
75
82
|
</p>
|
|
76
83
|
|
|
77
84
|
---
|
|
@@ -93,6 +100,23 @@ iterate on locally on a laptop, or on a free Colab T4.
|
|
|
93
100
|
> direction, not requests to fulfill. Use it on models and in contexts you're
|
|
94
101
|
> authorized to.
|
|
95
102
|
|
|
103
|
+
> **🎤 Presented at Dubai AI Tinkerers (October 2026).** Ablate was demoed live,
|
|
104
|
+
> no slides, using the browser UI shown below:
|
|
105
|
+
> [dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y](https://dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y)
|
|
106
|
+
|
|
107
|
+
## Architecture
|
|
108
|
+
|
|
109
|
+
<p align="center">
|
|
110
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-architecture.png"><img alt="Ablate architecture: three interfaces, one pipeline, and the three places it touches the model" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-architecture.png" width="900"></a>
|
|
111
|
+
</p>
|
|
112
|
+
|
|
113
|
+
Three ways in (browser UI, CLI, Python API), one `Ablator` pipeline, no training.
|
|
114
|
+
The coloured arrows are the only three places `ablate` touches the model: it
|
|
115
|
+
**reads** the residual stream on two piles of prompts, **subtracts** the refusal
|
|
116
|
+
direction at every layer's output while the model runs (a hook), or **rewrites**
|
|
117
|
+
the weights for good (bake). A one-page printable version is in
|
|
118
|
+
[`media/ablate-architecture.pdf`](media/ablate-architecture.pdf).
|
|
119
|
+
|
|
96
120
|
## 🤗 Released model
|
|
97
121
|
|
|
98
122
|
A worked example of the full pipeline is published at
|
|
@@ -285,6 +309,16 @@ ablate ui --model Qwen/Qwen2.5-0.5B-Instruct # preload a model
|
|
|
285
309
|
ablate ui --share # let others on the same Wi-Fi explore
|
|
286
310
|
```
|
|
287
311
|
|
|
312
|
+
<p align="center">
|
|
313
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-playground.png"><img alt="Playground: the original model refuses a gardening question, the edited model answers it" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-playground.png" width="900"></a>
|
|
314
|
+
<br><i>Playground: same prompt, same weights. The original refuses, the edited model answers.</i>
|
|
315
|
+
</p>
|
|
316
|
+
|
|
317
|
+
<p align="center">
|
|
318
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-find-direction.png"><img alt="Find direction: per-layer separation chart and every prompt plotted along the refusal direction" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-find-direction.png" width="900"></a>
|
|
319
|
+
<br><i>Find direction: which layer holds the refusal signal, and every prompt plotted along it.</i>
|
|
320
|
+
</p>
|
|
321
|
+
|
|
288
322
|
A local, dependency-free web app that walks through the whole pipeline:
|
|
289
323
|
|
|
290
324
|
1. **Model** — search the HuggingFace Hub and load any chat model.
|
|
@@ -423,4 +457,4 @@ mechanistic-interpretability work of Arditi et al. and the open-source
|
|
|
423
457
|
|
|
424
458
|
## License
|
|
425
459
|
|
|
426
|
-
Proprietary — all rights reserved. This code is published for viewing and evaluation only; no use, copying, modification, redistribution, commercial use, or use as AI/ML training data without written permission. See [LICENSE](LICENSE). Commercial licensing:
|
|
460
|
+
Proprietary — all rights reserved. This code is published for viewing and evaluation only; no use, copying, modification, redistribution, commercial use, or use as AI/ML training data without written permission. See [LICENSE](LICENSE). Commercial licensing: sonu@aianytime.net.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
<h1 align="center">Ablate</h1>
|
|
10
10
|
|
|
11
|
-
<p align="center"><b>Directional ablation (abliteration) toolkit for automatic censorship removal of open-source language models.</b></p>
|
|
11
|
+
<p align="center"><b>Directional ablation (abliteration) toolkit for automatic censorship removal of open-source language models (SLMs/LLMs).</b></p>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
14
|
<a href="https://pypi.org/project/ablate-llm/"><img alt="PyPI" src="https://img.shields.io/pypi/v/ablate-llm.svg?color=7c5cff"></a>
|
|
@@ -17,19 +17,26 @@
|
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
<p align="center">
|
|
20
|
+
<a href="https://aianytime.github.io/ablate/">🌐 Website</a> •
|
|
20
21
|
<a href="https://pypi.org/project/ablate-llm/">📦 PyPI</a> •
|
|
21
22
|
<a href="https://huggingface.co/ai-anytime/qwen-1.5b-abliterated">🤗 Model</a> •
|
|
22
23
|
<a href="https://youtu.be/1-1bM3Ynql4">▶️ Video walkthrough</a> •
|
|
24
|
+
<a href="https://dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y">🎤 Dubai AI Tinkerers talk</a> •
|
|
23
25
|
<a href="#citation">📚 Cite</a>
|
|
24
26
|
</p>
|
|
25
27
|
|
|
26
28
|
<p align="center"><i>Created with 💜 by <b>AI Anytime</b></i></p>
|
|
27
29
|
|
|
28
30
|
<p align="center">
|
|
29
|
-
<a href="https://youtu.be/
|
|
30
|
-
<img
|
|
31
|
+
<a href="https://youtu.be/_pLKCRgzu6A">
|
|
32
|
+
<img
|
|
33
|
+
src="https://img.youtube.com/vi/_pLKCRgzu6A/maxresdefault.jpg"
|
|
34
|
+
alt="Ablate — Full YouTube Walkthrough"
|
|
35
|
+
width="800"
|
|
36
|
+
/>
|
|
31
37
|
</a>
|
|
32
|
-
<br
|
|
38
|
+
<br />
|
|
39
|
+
<i>▶️ Watch the full walkthrough on YouTube</i>
|
|
33
40
|
</p>
|
|
34
41
|
|
|
35
42
|
---
|
|
@@ -51,6 +58,23 @@ iterate on locally on a laptop, or on a free Colab T4.
|
|
|
51
58
|
> direction, not requests to fulfill. Use it on models and in contexts you're
|
|
52
59
|
> authorized to.
|
|
53
60
|
|
|
61
|
+
> **🎤 Presented at Dubai AI Tinkerers (October 2026).** Ablate was demoed live,
|
|
62
|
+
> no slides, using the browser UI shown below:
|
|
63
|
+
> [dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y](https://dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y)
|
|
64
|
+
|
|
65
|
+
## Architecture
|
|
66
|
+
|
|
67
|
+
<p align="center">
|
|
68
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-architecture.png"><img alt="Ablate architecture: three interfaces, one pipeline, and the three places it touches the model" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-architecture.png" width="900"></a>
|
|
69
|
+
</p>
|
|
70
|
+
|
|
71
|
+
Three ways in (browser UI, CLI, Python API), one `Ablator` pipeline, no training.
|
|
72
|
+
The coloured arrows are the only three places `ablate` touches the model: it
|
|
73
|
+
**reads** the residual stream on two piles of prompts, **subtracts** the refusal
|
|
74
|
+
direction at every layer's output while the model runs (a hook), or **rewrites**
|
|
75
|
+
the weights for good (bake). A one-page printable version is in
|
|
76
|
+
[`media/ablate-architecture.pdf`](media/ablate-architecture.pdf).
|
|
77
|
+
|
|
54
78
|
## 🤗 Released model
|
|
55
79
|
|
|
56
80
|
A worked example of the full pipeline is published at
|
|
@@ -243,6 +267,16 @@ ablate ui --model Qwen/Qwen2.5-0.5B-Instruct # preload a model
|
|
|
243
267
|
ablate ui --share # let others on the same Wi-Fi explore
|
|
244
268
|
```
|
|
245
269
|
|
|
270
|
+
<p align="center">
|
|
271
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-playground.png"><img alt="Playground: the original model refuses a gardening question, the edited model answers it" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-playground.png" width="900"></a>
|
|
272
|
+
<br><i>Playground: same prompt, same weights. The original refuses, the edited model answers.</i>
|
|
273
|
+
</p>
|
|
274
|
+
|
|
275
|
+
<p align="center">
|
|
276
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-find-direction.png"><img alt="Find direction: per-layer separation chart and every prompt plotted along the refusal direction" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-find-direction.png" width="900"></a>
|
|
277
|
+
<br><i>Find direction: which layer holds the refusal signal, and every prompt plotted along it.</i>
|
|
278
|
+
</p>
|
|
279
|
+
|
|
246
280
|
A local, dependency-free web app that walks through the whole pipeline:
|
|
247
281
|
|
|
248
282
|
1. **Model** — search the HuggingFace Hub and load any chat model.
|
|
@@ -381,4 +415,4 @@ mechanistic-interpretability work of Arditi et al. and the open-source
|
|
|
381
415
|
|
|
382
416
|
## License
|
|
383
417
|
|
|
384
|
-
Proprietary — all rights reserved. This code is published for viewing and evaluation only; no use, copying, modification, redistribution, commercial use, or use as AI/ML training data without written permission. See [LICENSE](LICENSE). Commercial licensing:
|
|
418
|
+
Proprietary — all rights reserved. This code is published for viewing and evaluation only; no use, copying, modification, redistribution, commercial use, or use as AI/ML training data without written permission. See [LICENSE](LICENSE). Commercial licensing: sonu@aianytime.net.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ablate-llm"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.1"
|
|
8
8
|
description = "Directional ablation (abliteration) toolkit for open-source language models: extract, ablate, and optimize the removal of refusal / behavioral directions in the residual stream."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -19,10 +19,14 @@ def build_model_card(
|
|
|
19
19
|
method: str,
|
|
20
20
|
config: dict,
|
|
21
21
|
metrics: Optional[dict] = None,
|
|
22
|
-
license: str = "apache-2.0",
|
|
22
|
+
license: Optional[str] = "apache-2.0",
|
|
23
23
|
extra_notes: str = "",
|
|
24
|
+
license_name: Optional[str] = None,
|
|
25
|
+
license_link: Optional[str] = None,
|
|
24
26
|
) -> str:
|
|
25
27
|
"""Return the full README.md (model card) string, YAML frontmatter included."""
|
|
28
|
+
license = license or "other"
|
|
29
|
+
built_with_llama = _is_llama(base_model, license)
|
|
26
30
|
tags = [
|
|
27
31
|
"abliteration",
|
|
28
32
|
"directional-ablation",
|
|
@@ -31,10 +35,14 @@ def build_model_card(
|
|
|
31
35
|
"safety-research",
|
|
32
36
|
"ablate",
|
|
33
37
|
]
|
|
38
|
+
if built_with_llama:
|
|
39
|
+
tags.append("llama")
|
|
34
40
|
fm = [
|
|
35
41
|
"---",
|
|
36
42
|
f"base_model: {base_model}",
|
|
37
43
|
f"license: {license}",
|
|
44
|
+
*([f"license_name: {license_name}"] if license_name else []),
|
|
45
|
+
*([f"license_link: {license_link}"] if license_link else []),
|
|
38
46
|
"library_name: transformers",
|
|
39
47
|
"pipeline_tag: text-generation",
|
|
40
48
|
"tags:",
|
|
@@ -55,8 +63,16 @@ def build_model_card(
|
|
|
55
63
|
"judged attack-success rate on a harmful benchmark.\n\n"
|
|
56
64
|
)
|
|
57
65
|
|
|
66
|
+
llama_md = (
|
|
67
|
+
"**Built with Llama.** This model is a derivative of a Meta Llama model and is "
|
|
68
|
+
"distributed under the base model's Llama Community License. A copy of the "
|
|
69
|
+
"license and acceptable use policy from the base model is included in this repo.\n\n"
|
|
70
|
+
if built_with_llama else ""
|
|
71
|
+
)
|
|
72
|
+
|
|
58
73
|
body = f"""# {repo_id.split('/')[-1]}
|
|
59
74
|
|
|
75
|
+
{llama_md}
|
|
60
76
|
This is a **directionally-ablated ("abliterated")** version of
|
|
61
77
|
[`{base_model}`](https://huggingface.co/{base_model}), produced with
|
|
62
78
|
[**ablate**](https://github.com/AIAnytime/ablate) — an activation-engineering toolkit for
|
|
@@ -115,6 +131,46 @@ If you use this model or `ablate`, please cite Arditi et al. (2024),
|
|
|
115
131
|
return "\n".join(fm) + body
|
|
116
132
|
|
|
117
133
|
|
|
134
|
+
def _is_llama(base_model: str, license: Optional[str]) -> bool:
|
|
135
|
+
return base_model.lower().startswith("meta-llama/") or str(license or "").lower().startswith("llama")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def base_model_license(base_model: str, token: Optional[str] = None) -> dict:
|
|
139
|
+
"""Read ``license`` / ``license_name`` / ``license_link`` from the base model's card.
|
|
140
|
+
|
|
141
|
+
A derivative must carry its base model's license, so the card copies it instead
|
|
142
|
+
of assuming one. Returns ``{}`` when the base card cannot be read.
|
|
143
|
+
"""
|
|
144
|
+
try:
|
|
145
|
+
from huggingface_hub import HfApi
|
|
146
|
+
cd = HfApi(token=token).model_info(base_model).card_data
|
|
147
|
+
except Exception:
|
|
148
|
+
return {}
|
|
149
|
+
if cd is None:
|
|
150
|
+
return {}
|
|
151
|
+
out = {k: cd.get(k) for k in ("license", "license_name", "license_link") if cd.get(k)}
|
|
152
|
+
if isinstance(out.get("license"), list):
|
|
153
|
+
out["license"] = out["license"][0]
|
|
154
|
+
return out
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _copy_license_files(api, base_model: str, dest: str) -> list:
|
|
158
|
+
"""Copy LICENSE / NOTICE / USE_POLICY files from the base repo into ``dest``."""
|
|
159
|
+
copied = []
|
|
160
|
+
try:
|
|
161
|
+
from huggingface_hub import hf_hub_download
|
|
162
|
+
names = [f for f in api.list_repo_files(base_model)
|
|
163
|
+
if "/" not in f and f.upper().startswith(("LICENSE", "NOTICE", "USE_POLICY"))]
|
|
164
|
+
for f in names:
|
|
165
|
+
src = hf_hub_download(base_model, f, token=api.token)
|
|
166
|
+
with open(src, "rb") as a, open(os.path.join(dest, f), "wb") as b:
|
|
167
|
+
b.write(a.read())
|
|
168
|
+
copied.append(f)
|
|
169
|
+
except Exception:
|
|
170
|
+
pass
|
|
171
|
+
return copied
|
|
172
|
+
|
|
173
|
+
|
|
118
174
|
def push_to_hub(
|
|
119
175
|
model,
|
|
120
176
|
tokenizer,
|
|
@@ -125,12 +181,13 @@ def push_to_hub(
|
|
|
125
181
|
config: Optional[dict] = None,
|
|
126
182
|
metrics: Optional[dict] = None,
|
|
127
183
|
private: bool = True,
|
|
128
|
-
license: str =
|
|
184
|
+
license: Optional[str] = None,
|
|
129
185
|
extra_notes: str = "",
|
|
130
186
|
commit_message: str = "Upload abliterated model via ablate",
|
|
131
187
|
) -> str:
|
|
132
188
|
"""Save, card, and upload a model to ``repo_id``. Returns the repo URL.
|
|
133
189
|
|
|
190
|
+
``license`` defaults to the base model's own license, read from its Hub card.
|
|
134
191
|
``token`` falls back to the ``HF_TOKEN`` / ``HUGGINGFACE_TOKEN`` env vars or a
|
|
135
192
|
cached ``huggingface-cli login``.
|
|
136
193
|
"""
|
|
@@ -143,14 +200,19 @@ def push_to_hub(
|
|
|
143
200
|
api = HfApi(token=token)
|
|
144
201
|
api.create_repo(repo_id=repo_id, private=private, exist_ok=True, repo_type="model")
|
|
145
202
|
|
|
203
|
+
lic = {"license": license} if license else base_model_license(base_model, token)
|
|
146
204
|
card = build_model_card(
|
|
147
205
|
repo_id=repo_id, base_model=base_model, method=method,
|
|
148
|
-
config=config or {}, metrics=metrics, license=license,
|
|
206
|
+
config=config or {}, metrics=metrics, license=lic.get("license"),
|
|
207
|
+
license_name=lic.get("license_name"), license_link=lic.get("license_link"),
|
|
208
|
+
extra_notes=extra_notes,
|
|
149
209
|
)
|
|
150
210
|
|
|
151
211
|
with tempfile.TemporaryDirectory() as d:
|
|
152
212
|
model.save_pretrained(d)
|
|
153
213
|
tokenizer.save_pretrained(d)
|
|
214
|
+
if base_model != "unknown":
|
|
215
|
+
_copy_license_files(api, base_model, d)
|
|
154
216
|
with open(os.path.join(d, "README.md"), "w", encoding="utf-8") as f:
|
|
155
217
|
f.write(card)
|
|
156
218
|
with open(os.path.join(d, "ablate_meta.json"), "w") as f:
|
|
@@ -234,7 +234,7 @@ class Ablator:
|
|
|
234
234
|
token: Optional[str] = None,
|
|
235
235
|
private: bool = True,
|
|
236
236
|
metrics: Optional[dict] = None,
|
|
237
|
-
license: str =
|
|
237
|
+
license: Optional[str] = None,
|
|
238
238
|
bake_if_needed: bool = True,
|
|
239
239
|
) -> str:
|
|
240
240
|
"""Bake (if needed) and upload the abliterated model + a generated model
|
|
@@ -35,7 +35,7 @@ from ..config import AblationConfig, SubspaceConfig
|
|
|
35
35
|
from ..evaluate import _coherence, is_refusal, mean_kl_divergence
|
|
36
36
|
from ..extract import collect_activations
|
|
37
37
|
from ..hooks import AblationHooks
|
|
38
|
-
from ..hub import build_model_card
|
|
38
|
+
from ..hub import base_model_license, build_model_card
|
|
39
39
|
from ..model import LM
|
|
40
40
|
from ..optimize import optimize, optimize_subspace
|
|
41
41
|
from ..pipeline import Ablator
|
|
@@ -599,7 +599,10 @@ def _card_metrics() -> Optional[dict]:
|
|
|
599
599
|
def card_preview(body: dict) -> dict:
|
|
600
600
|
basis, conf = _resolve(body.get("config") or {})
|
|
601
601
|
repo = (body.get("repo_id") or "you/model-abliterated").strip()
|
|
602
|
-
|
|
602
|
+
lic = base_model_license(S.lm.name, S.token)
|
|
603
|
+
return {"card": build_model_card(repo, S.lm.name, _method_of(conf), conf.to_dict(), _card_metrics(),
|
|
604
|
+
license=lic.get("license"), license_name=lic.get("license_name"),
|
|
605
|
+
license_link=lic.get("license_link"))}
|
|
603
606
|
|
|
604
607
|
|
|
605
608
|
def _bake_then(body: dict, emit: Emit, ship: Callable[[], str]) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ablate-llm
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Directional ablation (abliteration) toolkit for open-source language models: extract, ablate, and optimize the removal of refusal / behavioral directions in the residual stream.
|
|
5
5
|
Author: AI Anytime
|
|
6
6
|
License: Proprietary
|
|
@@ -50,7 +50,7 @@ Dynamic: license-file
|
|
|
50
50
|
|
|
51
51
|
<h1 align="center">Ablate</h1>
|
|
52
52
|
|
|
53
|
-
<p align="center"><b>Directional ablation (abliteration) toolkit for automatic censorship removal of open-source language models.</b></p>
|
|
53
|
+
<p align="center"><b>Directional ablation (abliteration) toolkit for automatic censorship removal of open-source language models (SLMs/LLMs).</b></p>
|
|
54
54
|
|
|
55
55
|
<p align="center">
|
|
56
56
|
<a href="https://pypi.org/project/ablate-llm/"><img alt="PyPI" src="https://img.shields.io/pypi/v/ablate-llm.svg?color=7c5cff"></a>
|
|
@@ -59,19 +59,26 @@ Dynamic: license-file
|
|
|
59
59
|
</p>
|
|
60
60
|
|
|
61
61
|
<p align="center">
|
|
62
|
+
<a href="https://aianytime.github.io/ablate/">🌐 Website</a> •
|
|
62
63
|
<a href="https://pypi.org/project/ablate-llm/">📦 PyPI</a> •
|
|
63
64
|
<a href="https://huggingface.co/ai-anytime/qwen-1.5b-abliterated">🤗 Model</a> •
|
|
64
65
|
<a href="https://youtu.be/1-1bM3Ynql4">▶️ Video walkthrough</a> •
|
|
66
|
+
<a href="https://dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y">🎤 Dubai AI Tinkerers talk</a> •
|
|
65
67
|
<a href="#citation">📚 Cite</a>
|
|
66
68
|
</p>
|
|
67
69
|
|
|
68
70
|
<p align="center"><i>Created with 💜 by <b>AI Anytime</b></i></p>
|
|
69
71
|
|
|
70
72
|
<p align="center">
|
|
71
|
-
<a href="https://youtu.be/
|
|
72
|
-
<img
|
|
73
|
+
<a href="https://youtu.be/_pLKCRgzu6A">
|
|
74
|
+
<img
|
|
75
|
+
src="https://img.youtube.com/vi/_pLKCRgzu6A/maxresdefault.jpg"
|
|
76
|
+
alt="Ablate — Full YouTube Walkthrough"
|
|
77
|
+
width="800"
|
|
78
|
+
/>
|
|
73
79
|
</a>
|
|
74
|
-
<br
|
|
80
|
+
<br />
|
|
81
|
+
<i>▶️ Watch the full walkthrough on YouTube</i>
|
|
75
82
|
</p>
|
|
76
83
|
|
|
77
84
|
---
|
|
@@ -93,6 +100,23 @@ iterate on locally on a laptop, or on a free Colab T4.
|
|
|
93
100
|
> direction, not requests to fulfill. Use it on models and in contexts you're
|
|
94
101
|
> authorized to.
|
|
95
102
|
|
|
103
|
+
> **🎤 Presented at Dubai AI Tinkerers (October 2026).** Ablate was demoed live,
|
|
104
|
+
> no slides, using the browser UI shown below:
|
|
105
|
+
> [dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y](https://dubai.aitinkerers.org/talks/rsvp_rDbfcoxeQ5Y)
|
|
106
|
+
|
|
107
|
+
## Architecture
|
|
108
|
+
|
|
109
|
+
<p align="center">
|
|
110
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-architecture.png"><img alt="Ablate architecture: three interfaces, one pipeline, and the three places it touches the model" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-architecture.png" width="900"></a>
|
|
111
|
+
</p>
|
|
112
|
+
|
|
113
|
+
Three ways in (browser UI, CLI, Python API), one `Ablator` pipeline, no training.
|
|
114
|
+
The coloured arrows are the only three places `ablate` touches the model: it
|
|
115
|
+
**reads** the residual stream on two piles of prompts, **subtracts** the refusal
|
|
116
|
+
direction at every layer's output while the model runs (a hook), or **rewrites**
|
|
117
|
+
the weights for good (bake). A one-page printable version is in
|
|
118
|
+
[`media/ablate-architecture.pdf`](media/ablate-architecture.pdf).
|
|
119
|
+
|
|
96
120
|
## 🤗 Released model
|
|
97
121
|
|
|
98
122
|
A worked example of the full pipeline is published at
|
|
@@ -285,6 +309,16 @@ ablate ui --model Qwen/Qwen2.5-0.5B-Instruct # preload a model
|
|
|
285
309
|
ablate ui --share # let others on the same Wi-Fi explore
|
|
286
310
|
```
|
|
287
311
|
|
|
312
|
+
<p align="center">
|
|
313
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-playground.png"><img alt="Playground: the original model refuses a gardening question, the edited model answers it" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-playground.png" width="900"></a>
|
|
314
|
+
<br><i>Playground: same prompt, same weights. The original refuses, the edited model answers.</i>
|
|
315
|
+
</p>
|
|
316
|
+
|
|
317
|
+
<p align="center">
|
|
318
|
+
<a href="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-find-direction.png"><img alt="Find direction: per-layer separation chart and every prompt plotted along the refusal direction" src="https://raw.githubusercontent.com/AIAnytime/ablate/main/media/ui-find-direction.png" width="900"></a>
|
|
319
|
+
<br><i>Find direction: which layer holds the refusal signal, and every prompt plotted along it.</i>
|
|
320
|
+
</p>
|
|
321
|
+
|
|
288
322
|
A local, dependency-free web app that walks through the whole pipeline:
|
|
289
323
|
|
|
290
324
|
1. **Model** — search the HuggingFace Hub and load any chat model.
|
|
@@ -423,4 +457,4 @@ mechanistic-interpretability work of Arditi et al. and the open-source
|
|
|
423
457
|
|
|
424
458
|
## License
|
|
425
459
|
|
|
426
|
-
Proprietary — all rights reserved. This code is published for viewing and evaluation only; no use, copying, modification, redistribution, commercial use, or use as AI/ML training data without written permission. See [LICENSE](LICENSE). Commercial licensing:
|
|
460
|
+
Proprietary — all rights reserved. This code is published for viewing and evaluation only; no use, copying, modification, redistribution, commercial use, or use as AI/ML training data without written permission. See [LICENSE](LICENSE). Commercial licensing: sonu@aianytime.net.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|