feat: harden local runtime and verification

This commit is contained in:
Joseph Magly
2026-08-23 11:16:10 -04:00
parent b0da692ea0
commit ad883cef0b
14 changed files with 602 additions and 58 deletions
@@ -0,0 +1,30 @@
# Documentation-code sync report
- Date: 2026-08-22
- Direction: code-to-docs
- Scope: coherence verification, local CUDA setup, OpenBao runtime credentials, developer launch
- Mode: incremental
## Reconciled drift
1. Documented the deterministic semantic-anchor coherence scorer and its corpus-contamination rejection.
2. Corrected CUDA operator commands to use `.venv/bin/python` after the CUDA wheel override; `uv run` can restore the CPU-locked wheel.
3. Added the canonical `setup.aiwg.io/v1` developer manifest and launch command.
4. Documented exact OpenBao scope and the separation between read and Hub-publishing tokens.
## Changed documentation
- `README.md`
- `docs/conditional-testing.md`
- `installer/setup.dev.manifest.yaml`
## Validation
- `aiwg setup-validate installer/setup.dev.manifest.yaml`
- `.venv/bin/pytest -q --no-cov tests/test_abliterate.py::TestCoherenceScoring`
- `.venv/bin/ruff check obliteratus/abliterate.py tests/test_abliterate.py installer/scripts`
## Human review
- A write-scoped Hugging Face token remains intentionally absent. Add `HF_PUSH_TOKEN` or `OBLITERATUS_HUB_TOKEN` only when Hub publishing is explicitly tested.
- The provider-orchestrated manifest requires an AIWG trust-root/attestation handoff before `setup-run`; validation alone does not authorize privileged OpenBao or TPM operations.
+14
View File
@@ -0,0 +1,14 @@
{
"schema": "aiwg.doc-sync.last-run.v1",
"timestamp": "2026-08-22T17:20:00Z",
"direction": "code-to-docs",
"mode": "incremental",
"scope": [
"obliteratus/abliterate.py",
"tests/test_abliterate.py",
"installer/",
"README.md",
"docs/conditional-testing.md"
],
"report": ".aiwg/reports/doc-sync-20260822T172000Z.md"
}
+26
View File
@@ -336,6 +336,32 @@ configuration; never point it at contributor-controlled code or emit diagnostics
stdout. Secrets are resolved at use time so mounted-file and broker rotations do not
require restarting the application.
### Agentic local setup
The canonical developer setup is [`installer/setup.dev.manifest.yaml`](installer/setup.dev.manifest.yaml),
a `setup.aiwg.io/v1` provider-orchestrated manifest. It installs the locked UI
environment, replaces the deliberately CPU-locked PyTorch wheel with the matching
CUDA build when NVIDIA hardware is present, proves a real CUDA tensor operation,
and guides an agent through least-privilege OpenBao configuration.
```bash
aiwg setup-validate installer/setup.dev.manifest.yaml
aiwg setup-run installer/setup.dev.manifest.yaml --type developer
```
The OpenBao step grants the local runtime read access only to the Hugging Face
download token and OpenRouter analysis key. It does not reinterpret a read token
as `HF_PUSH_TOKEN` or `OBLITERATUS_HUB_TOKEN`; Hub publishing requires a separate
write-scoped credential. After setup, launch with:
```bash
installer/scripts/launch-local.sh
```
The launch script uses `.venv/bin/python` directly. This matters on CUDA systems:
running `uv run` after the installer override can resynchronize the environment
back to the CPU wheel recorded for portable mandatory CI.
## Two intervention paradigms
OBLITERATUS supports both permanent and reversible liberation:
+152 -48
View File
@@ -740,13 +740,37 @@ def _should_quantize(model_id: str, is_preset: bool = False) -> str | None:
# ---------------------------------------------------------------------------
def _clear_gpu():
"""Free GPU/accelerator memory. Resilient to device errors."""
"""Unload model tensors while retaining the checkpoint for lazy reload."""
with _lock:
_state["model"] = None
_state["tokenizer"] = None
dev.free_gpu_memory()
def _checkpoint_is_available(checkpoint: str | None) -> bool:
"""Return whether *checkpoint* is a recoverable model directory."""
if not checkpoint:
return False
try:
return Path(checkpoint).is_dir()
except OSError:
return False
def _clear_stale_model_state() -> None:
"""Remove UI metadata when neither a loaded model nor checkpoint exists."""
with _lock:
_state.update({
"model": None,
"tokenizer": None,
"model_name": None,
"method": None,
"status": "idle",
"steering": None,
"output_dir": None,
})
def _install_steering_hooks(model, steering_meta: dict) -> int:
"""Re-install activation steering hooks on a (possibly reloaded) model.
@@ -815,51 +839,93 @@ def _install_steering_hooks(model, steering_meta: dict) -> int:
return hooks_installed
def _cleanup_disk():
"""Purge HF cache, stale offload dirs, and previous saves. Returns status string."""
def _cleanup_disk(
*,
cache_roots: list[Path] | None = None,
temp_root: Path = Path("/tmp"),
):
"""Purge stale caches while preserving the active model checkpoint.
Model tensors are unloaded from accelerator memory. Chat lazily reloads
them from the preserved checkpoint on the next message.
"""
import shutil
freed = 0
targets = [
(Path.home() / ".cache" / "huggingface" / "hub", "HF model cache"),
(Path("/tmp/hf_home"), "HF fallback cache"),
(Path("/tmp/obliterated"), "previous save"),
]
with _lock:
active_value = _state.get("output_dir")
active_checkpoint = None
if _checkpoint_is_available(active_value):
try:
active_checkpoint = Path(active_value).resolve()
except OSError:
active_checkpoint = None
if cache_roots is None:
cache_roots = [
Path.home() / ".cache" / "huggingface" / "hub",
temp_root / "hf_home",
]
targets = [(path, "model cache") for path in cache_roots]
targets.append((temp_root / "obliterated", "previous save"))
# Glob obliterated model checkpoints (numbered: /tmp/obliterated_1, etc.)
for p in Path("/tmp").glob("obliterated_*"):
for p in temp_root.glob("obliterated_*"):
if p.is_dir():
targets.append((p, "obliterated checkpoint"))
# Glob stale offload dirs
for p in Path("/tmp").glob("obliteratus_offload_*"):
for p in temp_root.glob("obliteratus_offload_*"):
targets.append((p, "stale offload dir"))
# Glob benchmark checkpoints
for p in Path("/tmp").glob("bench_*"):
for p in temp_root.glob("bench_*"):
if p.is_dir():
targets.append((p, "benchmark checkpoint"))
# Glob stale chart images, sweep plots, export ZIPs, and bench CSVs
for pattern in ["obliteratus_chart_*.png", "obliteratus_sweep_*.png",
"obliteratus_bench_*.png", "obliteratus_bench_*.csv",
"obliteratus_export_*.zip"]:
for p in Path("/tmp").glob(pattern):
for p in temp_root.glob(pattern):
targets.append((p, "stale temp file"))
seen: set[Path] = set()
for path, label in targets:
try:
resolved = path.resolve()
except OSError:
resolved = path
if resolved in seen:
continue
seen.add(resolved)
# Never make the active chat model unrecoverable. Also skip a parent
# cache directory if a custom setup places the checkpoint below it.
if active_checkpoint is not None and (
resolved == active_checkpoint or active_checkpoint.is_relative_to(resolved)
):
continue
if path.exists():
size = sum(f.stat().st_size for f in path.rglob("*") if f.is_file())
shutil.rmtree(path, ignore_errors=True)
if path.is_dir():
size = sum(
f.stat().st_size for f in path.rglob("*") if f.is_file()
)
shutil.rmtree(path, ignore_errors=True)
else:
size = path.stat().st_size
path.unlink(missing_ok=True)
freed += size
# Clear session model cache (checkpoints are gone)
_session_models.clear()
# Drop only entries whose checkpoints were actually purged.
for label, metadata in list(_session_models.items()):
if not _checkpoint_is_available(metadata.get("output_dir")):
_session_models.pop(label, None)
# Also clear GPU
_clear_gpu()
disk = shutil.disk_usage("/tmp")
disk = shutil.disk_usage(temp_root)
return (
f"Freed {freed / 1e9:.1f} GB. "
f"Disk: {disk.free / 1e9:.1f} GB free / {disk.total / 1e9:.1f} GB total. "
f"GPU cache cleared."
"GPU model unloaded; the active checkpoint was preserved and Chat "
"will reload it automatically."
)
@@ -2384,10 +2450,10 @@ def chat_respond(message: str, history: list[dict], system_prompt: str,
checkpoint = _state.get("output_dir")
# ZeroGPU recovery: if output_dir is lost (process restart), try to
# recover session data from checkpoint metadata files on disk.
if not checkpoint or not Path(checkpoint).exists():
if not _checkpoint_is_available(checkpoint):
_recover_sessions_from_disk()
checkpoint = _state.get("output_dir")
if checkpoint and Path(checkpoint).exists():
if _checkpoint_is_available(checkpoint):
try:
is_preset = (_state.get("model_name") or "") in MODELS
model = _load_model_to_device(
@@ -2411,6 +2477,7 @@ def chat_respond(message: str, history: list[dict], system_prompt: str,
yield "Model failed to reload from checkpoint. Try re-obliterating."
return
else:
_clear_stale_model_state()
yield "No model loaded yet. Go to the **Obliterate** tab first and liberate a model."
return
@@ -2524,7 +2591,17 @@ def get_chat_header():
status = _state["status"]
name = _state["model_name"]
method = _state["method"]
loaded = _state["model"] is not None and _state["tokenizer"] is not None
checkpoint = _state.get("output_dir")
if status == "ready":
if not loaded and _checkpoint_is_available(checkpoint):
return (
f"**{name}** (liberated via `{method}`) is unloaded from GPU; "
"it will load automatically when you send a message."
)
if not loaded:
_clear_stale_model_state()
return "No model loaded. Use the **Obliterate** tab to liberate a model first."
return f"Chatting with **{name}** (liberated via `{method}`)"
return "No model loaded. Use the **Obliterate** tab to liberate a model first."
@@ -3604,35 +3681,39 @@ THEME = gr.themes.Base(
font=gr.themes.GoogleFont("Fira Code"),
font_mono=gr.themes.GoogleFont("Fira Code"),
).set(
body_background_fill="#0a0a0f",
body_background_fill="#f3f7f4",
body_background_fill_dark="#0a0a0f",
body_text_color="#c0ccd0",
body_text_color="#17231b",
body_text_color_dark="#c0ccd0",
block_background_fill="#0d0d14",
background_fill_primary="#f3f7f4",
background_fill_primary_dark="#0a0a0f",
background_fill_secondary="#ffffff",
background_fill_secondary_dark="#0d0d14",
block_background_fill="#ffffff",
block_background_fill_dark="#0d0d14",
block_border_color="#1a1f2e",
block_border_color="#aabbb0",
block_border_color_dark="#1a1f2e",
block_label_text_color="#00cc33",
block_label_text_color="#087a2b",
block_label_text_color_dark="#00cc33",
block_title_text_color="#00ff41",
block_title_text_color="#006b25",
block_title_text_color_dark="#00ff41",
button_primary_background_fill="transparent",
button_primary_background_fill_dark="transparent",
button_primary_text_color="#00ff41",
button_primary_text_color="#087a2b",
button_primary_text_color_dark="#00ff41",
button_primary_border_color="#00ff41",
button_primary_border_color="#087a2b",
button_primary_border_color_dark="#00ff41",
button_secondary_background_fill="transparent",
button_secondary_background_fill_dark="transparent",
button_secondary_text_color="#4a5568",
button_secondary_text_color="#075f75",
button_secondary_text_color_dark="#4a5568",
button_secondary_border_color="#1a1f2e",
button_secondary_border_color="#087d98",
button_secondary_border_color_dark="#1a1f2e",
input_background_fill="#0a0a0f",
input_background_fill="#ffffff",
input_background_fill_dark="#0a0a0f",
input_border_color="#1a1f2e",
input_border_color="#91a69a",
input_border_color_dark="#1a1f2e",
input_placeholder_color="#4a5568",
input_placeholder_color="#607168",
input_placeholder_color_dark="#4a5568",
shadow_drop="none",
shadow_drop_lg="none",
@@ -3676,6 +3757,10 @@ body::after {
contain: strict;
}
/* The CRT treatment belongs to dark mode. Keep light mode genuinely light. */
html:not(.dark) body::before { opacity: 0.18; }
html:not(.dark) body::after { display: none; }
/* ---- TITLE GLOW + GLITCH ---- */
@keyframes glitch {
0%, 100% { text-shadow: 0 0 10px #00ff41, 0 0 30px rgba(0,255,65,0.3); }
@@ -3698,7 +3783,7 @@ body::after {
text-align: center;
font-size: 1.8rem;
letter-spacing: 0.4em;
color: #00ff41;
color: var(--block-title-text-color);
margin-bottom: 0;
font-weight: 700;
text-shadow: 0 0 10px #00ff41, 0 0 30px rgba(0,255,65,0.3);
@@ -3744,9 +3829,9 @@ button.tab-nav {
border: none !important;
background: transparent !important;
}
button.tab-nav:hover { color: #00ff41 !important; }
button.tab-nav:hover { color: var(--block-title-text-color) !important; }
button.tab-nav.selected {
color: #00ff41 !important;
color: var(--block-title-text-color) !important;
text-shadow: 0 0 8px rgba(0,255,65,0.5);
border-bottom: 2px solid #00ff41 !important;
background: rgba(0,255,65,0.06) !important;
@@ -3767,9 +3852,9 @@ div.block::before {
/* ---- PRIMARY BUTTON GLOW ---- */
.gr-button-primary, button.primary {
border: 1px solid #00ff41 !important;
border: 1px solid var(--button-primary-border-color) !important;
background: transparent !important;
color: #00ff41 !important;
color: var(--button-primary-text-color) !important;
text-transform: uppercase !important;
letter-spacing: 2px !important;
font-weight: 600 !important;
@@ -3784,9 +3869,9 @@ div.block::before {
/* ---- SECONDARY BUTTON ---- */
.gr-button-secondary, button.secondary {
border: 1px solid #00ccff !important;
border: 1px solid var(--button-secondary-border-color) !important;
background: rgba(0,204,255,0.08) !important;
color: #00ccff !important;
color: var(--button-secondary-text-color) !important;
text-transform: uppercase !important;
letter-spacing: 1px !important;
font-weight: 600 !important;
@@ -3826,11 +3911,28 @@ label span {
/* ---- CHATBOT STYLING ---- */
.chatbot .message {
border: 1px solid #1a1f2e !important;
background: #0d0d14 !important;
border: 1px solid var(--block-border-color) !important;
color: var(--body-text-color) !important;
}
.chatbot .message.user {
border-left: 3px solid #bc13fe !important;
background: var(--color-accent-soft) !important;
}
.chatbot .message.bot {
border-left: 3px solid #00a832 !important;
background: var(--background-fill-secondary) !important;
}
.chatbot .message .prose,
.chatbot .message .md,
.chatbot .message .message-content,
.chatbot .message p,
.chatbot .message li {
color: var(--body-text-color) !important;
}
.chatbot .bubble-wrap,
.chatbot .panel-wrap {
background: var(--body-background-fill) !important;
}
.chatbot .message.user { border-left: 3px solid #bc13fe !important; }
.chatbot .message.bot { border-left: 3px solid #00ff41 !important; }
/* ---- CHAT TAB: RESIZABLE CHATBOT ---- */
#chat .chatbot, #chat .chat-interface {
@@ -3881,12 +3983,12 @@ label span {
/* ---- MARKDOWN ACCENT ---- */
.prose h1, .prose h2, .prose h3,
.md h1, .md h2, .md h3 {
color: #00ff41 !important;
color: var(--block-title-text-color) !important;
text-transform: uppercase;
letter-spacing: 2px;
}
.prose strong, .md strong { color: #e0ffe6 !important; }
.prose em, .md em { color: #00cc33 !important; }
.prose strong, .md strong { color: var(--body-text-color) !important; }
.prose em, .md em { color: var(--block-label-text-color) !important; }
.prose code, .md code {
color: #bc13fe !important;
background: rgba(188,19,254,0.1) !important;
@@ -4200,7 +4302,9 @@ with gr.Blocks(title="OBLITERATUS", fill_height=True) as demo:
)
with gr.Row():
cleanup_btn = gr.Button("Purge Cache", variant="secondary", size="sm")
cleanup_btn = gr.Button(
"Unload GPU + Purge Stale Cache", variant="secondary", size="sm"
)
cleanup_status = gr.Markdown("")
gr.Markdown(
+24 -2
View File
@@ -76,10 +76,32 @@ CUDA_TORCH_VERSION="$(.venv/bin/python -c \
UV_TORCH_BACKEND=cu130 uv pip install --python .venv/bin/python \
--reinstall-package torch "torch==$CUDA_TORCH_VERSION"
uv pip check --python .venv/bin/python
uv run --extra dev --extra quantization python scripts/run_conditional_gate.py cuda-runtime
uv run --extra dev --extra quantization python scripts/run_conditional_gate.py bitsandbytes-runtime
.venv/bin/python scripts/run_conditional_gate.py cuda-runtime
.venv/bin/python scripts/run_conditional_gate.py bitsandbytes-runtime
```
Use the virtual environment interpreter directly after replacing Torch. A subsequent
`uv run` or `uv sync` without the CUDA override may restore the portable CPU wheel
from the lock. The agentic developer installer automates this ordering and performs
a real CUDA tensor probe; see `installer/setup.dev.manifest.yaml`.
## Quality-verifier coherence semantics
The built-in VERIFY stage does not treat length and vocabulary diversity as
coherence. Each fixed factual prompt has deterministic semantic anchors, and the
scorer rejects strong repetition and recognizable corpus contamination such as
scraped Q&A profile/answer fragments. This is intentionally local and deterministic:
release verification does not call another model or a network judge. Perplexity and
extended capability checks remain separate measurements.
On Linux workstations that also install cuDNN system-wide, the dynamic loader can
mix a host sublibrary with PyTorch's bundled cuDNN and raise
`CUDNN_STATUS_SUBLIBRARY_VERSION_MISMATCH`. The local launcher sets
`OBLITERATUS_DISABLE_CUDNN=1`, keeping causal convolutions and attention on
PyTorch's other CUDA kernels rather than moving the model to the CPU. Installer
verification runs actual causal `conv1d` and SDPA operations, not only a generic
CUDA allocation, so this failure is caught before a model pipeline begins.
Jetson CUDA support is tracked separately from this generic x64 CUDA lane. The
mandatory `Linux ARM64 preflight` uses GitHub's hosted `ubuntu-24.04-arm` runner
to prove locked CPU packaging, imports, CLI startup, and Jetson tooling contracts.
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
set +x
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
if [[ -z "${OBLITERATUS_SECRET_COMMAND:-}" ]] && \
[[ -x /home/roctinam/.local/bin/obliteratus-secret-broker ]]; then
export OBLITERATUS_SECRET_COMMAND=/home/roctinam/.local/bin/obliteratus-secret-broker
fi
# Avoid dynamic mixing between PyTorch's bundled cuDNN and a host cuDNN
# installation. Causal convolutions and attention use other CUDA kernels.
export OBLITERATUS_DISABLE_CUDNN="${OBLITERATUS_DISABLE_CUDNN:-1}"
exec .venv/bin/python app.py --host "${OBLITERATUS_HOST:-127.0.0.1}" \
--port "${OBLITERATUS_PORT:-7860}"
+38
View File
@@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -euo pipefail
set +x
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
uv sync --locked --extra spaces --extra dev --no-editable
enable_cuda="${ENABLE_CUDA:-auto}"
if [[ "$enable_cuda" != "false" ]] && command -v nvidia-smi >/dev/null 2>&1; then
torch_version="$(.venv/bin/python -c 'import torch; print(torch.__version__.split("+", 1)[0])')"
UV_TORCH_BACKEND=cu130 uv pip install \
--python .venv/bin/python \
--reinstall-package torch \
"torch==$torch_version"
fi
uv pip check --python .venv/bin/python
.venv/bin/python - <<'PY'
import shutil
import torch
if torch.cuda.is_available():
probe = torch.arange(16, device="cuda", dtype=torch.float32).square().sum()
assert probe.device.type == "cuda"
torch.backends.cudnn.enabled = False
torch.backends.cuda.enable_cudnn_sdp(False)
conv_input = torch.randn(1, 8, 32, device="cuda", dtype=torch.float16)
conv_weight = torch.randn(8, 8, 3, device="cuda", dtype=torch.float16)
convolution = torch.nn.functional.conv1d(conv_input, conv_weight)
q = torch.randn(1, 2, 32, 16, device="cuda", dtype=torch.float16)
attention = torch.nn.functional.scaled_dot_product_attention(q, q, q, is_causal=True)
torch.cuda.synchronize()
assert convolution.device.type == "cuda" and torch.isfinite(convolution).all()
assert attention.device.type == "cuda" and torch.isfinite(attention).all()
elif shutil.which("nvidia-smi"):
raise SystemExit("NVIDIA hardware detected but the installed PyTorch runtime cannot use CUDA")
PY
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -euo pipefail
set +x
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
.venv/bin/python - <<'PY'
import os
import shutil
import torch
from obliteratus.credential_sources import secret_available
assert torch.ones(1).add(1).item() == 2
if shutil.which("nvidia-smi"):
assert torch.cuda.is_available(), "NVIDIA GPU detected but CUDA is unavailable"
assert torch.ones(1, device="cuda").device.type == "cuda"
torch.backends.cudnn.enabled = False
torch.backends.cuda.enable_cudnn_sdp(False)
conv_input = torch.randn(1, 8, 32, device="cuda", dtype=torch.float16)
conv_weight = torch.randn(8, 8, 3, device="cuda", dtype=torch.float16)
convolution = torch.nn.functional.conv1d(conv_input, conv_weight)
q = torch.randn(1, 2, 32, 16, device="cuda", dtype=torch.float16)
attention = torch.nn.functional.scaled_dot_product_attention(q, q, q, is_causal=True)
torch.cuda.synchronize()
assert convolution.device.type == "cuda" and torch.isfinite(convolution).all()
assert attention.device.type == "cuda" and torch.isfinite(attention).all()
broker = os.environ.get("OBLITERATUS_SECRET_COMMAND")
if broker:
assert os.path.isabs(broker)
assert secret_available("HF_TOKEN")
assert secret_available("OPENROUTER_API_KEY")
PY
.venv/bin/pytest -q --no-cov tests/test_device_boundaries.py tests/test_secrets.py \
tests/test_abliterate.py::TestCoherenceScoring
+81
View File
@@ -0,0 +1,81 @@
apiVersion: setup.aiwg.io/v1
kind: SetupManifest
metadata:
name: obliteratus-dev
version: 1.0.0
description: Provider-orchestrated Linux setup with optional NVIDIA CUDA and scoped OpenBao runtime credentials.
install_type: developer
execution_mode: provider-orchestrated
spec:
platforms:
- os: linux
arch: [x86_64, arm64]
shell: bash
params:
- name: ENABLE_CUDA
type: choice
choices: [auto, "true", "false"]
default: auto
description: Install the matching CUDA PyTorch wheel when NVIDIA hardware is available.
- name: ENABLE_OPENBAO
type: choice
choices: [auto, "true", "false"]
default: auto
description: Configure the scoped OBLITERATUS AppRole through the sibling itops repository.
- name: OPENBAO_ITOPS_ROOT
type: path
default: "${HOME}/dev/itops"
description: Trusted itops checkout containing OpenBao policy and token helpers.
prerequisites:
- name: python
detect: "python3 --version | awk '{print $2}'"
version_min: "3.10"
install_hint: Install Python 3.10 or newer.
- name: uv
detect: "uv --version | awk '{print $2}'"
install_hint: Install uv from https://docs.astral.sh/uv/.
- name: git
detect: "git --version | awk '{print $3}'"
version_min: "2.30"
install_hint: Install Git from https://git-scm.com/.
- name: disk-space
detect: "df --output=avail -BG . | tail -1 | tr -d ' G'"
version_min: "12"
install_hint: At least 12 GB free space is required for dependencies and a test model.
- name: ram
detect: "awk '/MemTotal/ {printf \"%.0f\", $2/1024/1024}' /proc/meminfo"
version_min: "8"
install_hint: At least 8 GB RAM is required; 16 GB or more is recommended.
steps:
- id: install-runtime
type: script
script: scripts/setup.sh
verify: ".venv/bin/python -c 'import gradio, torch, transformers'"
- id: configure-openbao
type: agentic
depends_on: [install-runtime]
instruction: |
When ENABLE_OPENBAO is true, or auto and OPENBAO_ITOPS_ROOT is usable,
follow that repository's AGENTS.md and security SOP. Reuse or provision a
least-privilege obliteratus-local AppRole restricted to reads of
kv_internal/data/{huggingface/read-token,openrouter/automation-agent-key}
and their exact metadata leaves. Seal the AppRole bootstrap to the host
TPM when available. Install a mode-0700 OBLITERATUS_SECRET_COMMAND broker
that maps only HF_TOKEN and OPENROUTER_API_KEY. Verify intended reads and
an adjacent 403 denial. Never print secret values. Do not map the read-only
HF token to HF_PUSH_TOKEN or OBLITERATUS_HUB_TOKEN.
- id: verify-runtime
type: script
script: scripts/verify.sh
depends_on: [install-runtime, configure-openbao]
briefing:
success: OBLITERATUS developer runtime is ready.
next_steps:
- Run installer/scripts/launch-local.sh and open http://127.0.0.1:7860.
- Use a separate write-scoped HF_PUSH_TOKEN or OBLITERATUS_HUB_TOKEN only when testing Hub publishing.
recovery:
- id: reinstall-runtime
steps:
- id: reinstall
type: script
script: scripts/setup.sh
+54 -7
View File
@@ -23,6 +23,7 @@ from __future__ import annotations
import logging
import math
import os
import re
import shutil
import time
import warnings
@@ -111,6 +112,57 @@ logger = logging.getLogger(__name__)
_MAX_NORM_RATIO = 1.10
_COHERENCE_ANCHORS: dict[str, tuple[tuple[str, ...], ...]] = {
"The capital of France is": (("paris",),),
"In machine learning, a neural network": (
("model", "system"),
("layer", "node", "neuron", "weight"),
),
"The meaning of life is": (
("meaning", "purpose", "question"),
("life", "existence", "philosoph"),
),
"Water boils at a temperature of": (("100", "212", "celsius", "fahrenheit"),),
"The Pythagorean theorem states that": (
("hypotenuse",),
("square", "squared"),
),
"Photosynthesis is the process by which": (
("plant", "organism"),
("light", "sun"),
),
"The largest ocean on Earth is": (("pacific",),),
"A binary search algorithm works by": (
("half", "middle", "divide"),
("sorted", "search", "interval", "array"),
),
"The speed of light in a vacuum is": (("299,792", "299792", "3.00", "3 x 10", "300,000"),),
"Shakespeare wrote many famous plays including": (("hamlet", "macbeth", "othello", "romeo"),),
}
_CORPUS_CONTAMINATION_RE = re.compile(
r"(?im)(?:\bbrainly\b|^\s*(?:profile|answer|answered)\s*$|^\s*\d{2}\.\d{2}\.\d{4}\s*$)"
)
def _is_coherent_completion(prompt: str, completion: str) -> bool:
"""Return whether a completion is relevant, varied, and contamination-free."""
text = completion.strip()
words = re.findall(r"[\w'-]+", text.lower())
if len(text) <= 5 or len(words) < 3:
return False
if len(set(words)) / len(words) <= 0.2:
return False
if _CORPUS_CONTAMINATION_RE.search(text):
return False
anchors = _COHERENCE_ANCHORS.get(prompt)
if anchors is None:
return False
lowered = text.lower()
return all(any(term in lowered for term in alternatives) for alternatives in anchors)
# ── Abliteration method presets ───────────────────────────────────────────
METHODS = {
@@ -6536,13 +6588,8 @@ class AbliterationPipeline:
self._free_gpu_memory()
self.log(f' "{prompt}" -> {completion}')
# Simple coherence check: completion should have > 5 chars and no repetition
if len(completion) > 5:
words = completion.split()
if len(words) > 2:
unique_ratio = len(set(words)) / len(words)
if unique_ratio > 0.2:
coherent_count += 1
if _is_coherent_completion(prompt, completion):
coherent_count += 1
except (RuntimeError, Exception) as e:
if dev.is_oom_error(e):
self._free_gpu_memory()
+13 -1
View File
@@ -323,6 +323,18 @@ def supports_device_map_auto(device: str | None = None) -> bool:
# ---------------------------------------------------------------------------
def configure_cuda_alloc() -> None:
"""Set expandable_segments for CUDA if available."""
"""Configure CUDA allocation and optional attention backend safeguards."""
if is_cuda() and "PYTORCH_CUDA_ALLOC_CONF" not in os.environ:
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"
if (
is_cuda()
and os.environ.get("OBLITERATUS_DISABLE_CUDNN", "0") == "1"
):
# Some Linux hosts expose a system cuDNN beside the version bundled by
# PyTorch. cuDNN dynamically loads sublibraries by soname, which can mix
# those installations and fail at descriptor finalization. Transformer
# causal convolutions and attention remain on PyTorch's other CUDA
# kernels rather than falling back to the CPU.
torch.backends.cudnn.enabled = False
if hasattr(torch.backends.cuda, "enable_cudnn_sdp"):
torch.backends.cuda.enable_cudnn_sdp(False)
+32
View File
@@ -18,6 +18,7 @@ from obliteratus.abliterate import (
AbliterationPipeline,
PipelineStage,
StageResult,
_is_coherent_completion,
)
from obliteratus.models.loader import ModelHandle
@@ -104,6 +105,37 @@ class TestPrompts:
assert len(HARMLESS_PROMPTS[:n]) == n
class TestCoherenceScoring:
@pytest.mark.parametrize(
("prompt", "completion"),
[
("The capital of France is", "Paris, the country's largest city."),
("Water boils at a temperature of", "100 degrees Celsius at sea level."),
("A binary search algorithm works by", "dividing a sorted array in half around its middle element."),
],
)
def test_accepts_relevant_completion(self, prompt, completion):
assert _is_coherent_completion(prompt, completion) is True
def test_rejects_fluent_but_irrelevant_completion(self):
assert _is_coherent_completion(
"The capital of France is",
"A computational model composed of many connected layers and nodes.",
) is False
def test_rejects_corpus_contamination_seen_in_verifier(self):
assert _is_coherent_completion(
"Water boils at a temperature of",
"100°C. What is the temperature in Fahrenheit? - Brainly.in\nprofile\nanswer\nanswered",
) is False
def test_rejects_repetition(self):
assert _is_coherent_completion(
"The largest ocean on Earth is",
"Pacific Pacific Pacific Pacific Pacific Pacific Pacific Pacific.",
) is False
class TestStages:
def test_six_stages(self):
assert len(STAGES) == 6
+71
View File
@@ -0,0 +1,71 @@
"""Regression test for unload, cleanup, and lazy chat model lifecycle."""
from __future__ import annotations
import subprocess
import sys
def test_active_checkpoint_survives_cleanup_and_remains_chat_recoverable(tmp_path):
"""Exercise app state in isolation from Gradio's import-time worker sockets."""
script = r'''
import pathlib
import sys
import app
theme = app.THEME.to_dict()["theme"]
assert theme["body_background_fill"] != theme["body_background_fill_dark"]
assert theme["body_text_color"] != theme["body_text_color_dark"]
assert theme["background_fill_secondary"] == "#ffffff"
assert theme["background_fill_secondary_dark"] == "#0d0d14"
assert ".chatbot .message.bot" in app.CSS
assert "color: var(--body-text-color) !important" in app.CSS
root = pathlib.Path(sys.argv[1])
active = root / "obliterated_1"
stale = root / "obliterated_2"
cache = root / "model-cache"
for directory in (active, stale, cache):
directory.mkdir()
(directory / "weights.bin").write_bytes(b"model")
app.dev.free_gpu_memory = lambda: None
app._state.update({
"model": object(), "tokenizer": object(), "model_name": "org/model",
"method": "advanced", "status": "ready", "output_dir": str(active),
})
app._session_models.clear()
app._session_models.update({
"active": {"output_dir": str(active)},
"stale": {"output_dir": str(stale)},
})
message = app._cleanup_disk(cache_roots=[cache], temp_root=root)
assert active.is_dir()
assert not stale.exists()
assert not cache.exists()
assert list(app._session_models) == ["active"]
assert app._state["model"] is None and app._state["tokenizer"] is None
assert app._state["status"] == "ready"
assert "will reload it automatically" in message
header = app.get_chat_header()
assert "unloaded from GPU" in header and "load automatically" in header
active.rename(root / "removed")
header = app.get_chat_header()
assert header.startswith("No model loaded")
assert app._state["status"] == "idle"
assert app._state["model_name"] is None
assert app._state["output_dir"] is None
'''
result = subprocess.run(
[sys.executable, "-c", script, str(tmp_path)],
capture_output=True,
text=True,
timeout=60,
check=False,
)
assert result.returncode == 0, result.stdout + result.stderr
+13
View File
@@ -235,3 +235,16 @@ def test_configure_cuda_allocator(monkeypatch):
monkeypatch.setenv("PYTORCH_CUDA_ALLOC_CONF", "existing")
device.configure_cuda_alloc()
assert device.os.environ["PYTORCH_CUDA_ALLOC_CONF"] == "existing"
def test_configure_cuda_can_disable_cudnn(monkeypatch):
disable = Mock()
monkeypatch.setattr(device, "is_cuda", lambda: True)
monkeypatch.setattr(device.torch.backends.cuda, "enable_cudnn_sdp", disable)
monkeypatch.setenv("OBLITERATUS_DISABLE_CUDNN", "1")
monkeypatch.setattr(device.torch.backends.cudnn, "enabled", True)
device.configure_cuda_alloc()
disable.assert_called_once_with(False)
assert device.torch.backends.cudnn.enabled is False