Text Classification
Transformers
Safetensors
English
lfm2_vl
feature-extraction
decision-model
typed-decisions
system-one
shell
guardrail
command-risk
lfm2
liquid
lora
custom_code
Eval Results (legacy)
Instructions to use yannelli/d1-3b-cli-command-risk with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use yannelli/d1-3b-cli-command-risk with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="yannelli/d1-3b-cli-command-risk", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoProcessor, AutoModel processor = AutoProcessor.from_pretrained("yannelli/d1-3b-cli-command-risk", trust_remote_code=True) model = AutoModel.from_pretrained("yannelli/d1-3b-cli-command-risk", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download training/build_cli_decisions.py from yannelli/d1-3b-cli-command-risk: direct link, hf CLI and curl.
- Browser
- Download file 5.87 kB
-
https://huggingface.co/yannelli/d1-3b-cli-command-risk/resolve/main/training/build_cli_decisions.py
- Command line
-
hf download hf://yannelli/d1-3b-cli-command-risk/training/build_cli_decisions.py
-
curl -L -o build_cli_decisions.py https://huggingface.co/yannelli/d1-3b-cli-command-risk/resolve/main/training/build_cli_decisions.py
5.87 kB
| #!/usr/bin/env python3 | |
| """Pose CLI Command Risk as typed decisions for the d1 scripts in this folder. | |
| Writes cli-data/decisions/{train,validation,test}.parquet with the columns `common.load_split` reads: id, | |
| task_slug (the template family), state ({shell, command}), questions (17, identical per row) and gold. | |
| Train and validation keep one shell per distinct command and at most --train-cap / --val-cap commands per | |
| family, because rows within a family are near copies. Test keeps every row, so scores compare with the | |
| TF-IDF baseline in cli-command-risk/baseline.py. | |
| uv run --no-project --with pyarrow python build_cli_decisions.py | |
| """ | |
| import argparse | |
| import collections | |
| import hashlib | |
| import json | |
| import re | |
| from pathlib import Path | |
| import pyarrow as pa | |
| import pyarrow.parquet as pq | |
| HERE = Path(__file__).resolve().parent | |
| SOURCE = HERE.parent / "cli-command-risk" | |
| OUT = HERE / "cli-data" / "decisions" | |
| LEVELS = ["safe", "low", "moderate", "high", "critical"] | |
| SHELL_SUFFIX = re.compile(r"-(?:bash|zsh|sh|fish|dash)-[0-9a-f]+$") | |
| def questions(taxonomy, cats): | |
| defs = {c["name"]: c["definition"] for c in taxonomy["risk_categories"]} | |
| level_defs = {lv["name"]: lv["definition"] for lv in taxonomy["risk_levels"]} | |
| out = { | |
| "risk_level": {"type": "score", "instructions": "How much harm can running this shell command as written cause?", | |
| "criteria": [f"{lv.capitalize()}. {level_defs[lv]}" for lv in LEVELS]}, | |
| "risky": {"type": "noul", "instructions": "Is this shell command risky to run as written?", | |
| "criteria": {"true": "Running it can destroy data, change permissions or privileges, expose secrets, " | |
| "or disrupt the system.", | |
| "false": "It is read-only or routine, with no plausible path to harm."}}, | |
| } | |
| for c in cats: | |
| name = c.replace("_", " ") | |
| out[c] = {"type": "noul", "instructions": f"Does this command carry {name} risk?", | |
| "criteria": {"true": defs[c], "false": f"Nothing in the command matches {name}."}} | |
| out["reversible"] = {"type": "noul", "instructions": "Can an average user undo the effect of this command without backups?", | |
| "criteria": {"true": "The effect can be undone without backups, or there is no effect to undo.", | |
| "false": "Undoing the effect needs backups or is not possible."}} | |
| out["requires_root"] = {"type": "noul", "instructions": "Does the harm from this command need root or sudo?", | |
| "criteria": {"true": "The command needs root or sudo to do its harm.", | |
| "false": "An ordinary user can run it with the same effect."}} | |
| return out | |
| def family(row): | |
| if row["derived_from"]: | |
| return row["derived_from"] | |
| if row["source"] == "open_source": | |
| return "os:" + row["command"] | |
| return SHELL_SUFFIX.sub("", row["id"]) | |
| def rank(text): | |
| return hashlib.sha256(text.encode()).hexdigest() | |
| def thin(rows, cap): | |
| """One shell per distinct command, then the first `cap` commands per family in hash order.""" | |
| by_family = collections.defaultdict(dict) | |
| for r in rows: | |
| best = by_family[family(r)].get(r["command"]) | |
| if best is None or rank(r["id"]) < rank(best["id"]): | |
| by_family[family(r)][r["command"]] = r | |
| kept = [] | |
| for fam in sorted(by_family): | |
| kept += sorted(by_family[fam].values(), key=lambda r: rank(r["command"]))[:cap] | |
| return kept | |
| def gold(row, cats): | |
| noul = lambda value: {"label": "true" if value else "false"} # noqa: E731 | |
| out = {"risk_level": {"label": str(LEVELS.index(row["risk_level"]))}, | |
| "risky": noul(row["risk_level"] != "safe")} | |
| out.update({c: noul(c in row["risk_categories"]) for c in cats}) | |
| out["reversible"] = noul(row["reversible"]) | |
| out["requires_root"] = noul(row["requires_root"]) | |
| return out | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--train-cap", type=int, default=40) | |
| ap.add_argument("--val-cap", type=int, default=8) | |
| ap.add_argument("--full-train", action="store_true", help="keep every train row, all shells, no family cap") | |
| ap.add_argument("--out", type=Path, default=OUT.parent) | |
| args = ap.parse_args() | |
| out = args.out / "decisions" | |
| taxonomy = json.loads((SOURCE / "taxonomy.json").read_text()) | |
| data = {s: pq.read_table(SOURCE / "data" / f"{s}.parquet").to_pylist() for s in ("train", "validation", "test")} | |
| present = {c for r in data["train"] for c in r["risk_categories"]} | |
| cats = [c["name"] for c in taxonomy["risk_categories"] if c["name"] != "safe_baseline" and c["name"] in present] | |
| qs = json.dumps(questions(taxonomy, cats)) | |
| picked = {"train": data["train"] if args.full_train else thin(data["train"], args.train_cap), | |
| "validation": thin(data["validation"], args.val_cap), "test": data["test"]} | |
| out.mkdir(parents=True, exist_ok=True) | |
| summary = {} | |
| for split, rows in picked.items(): | |
| table = pa.table({ | |
| "id": [r["id"] for r in rows], | |
| "task_slug": [family(r) for r in rows], | |
| "state": [json.dumps({"shell": r["shell"], "command": r["command"]}) for r in rows], | |
| "questions": [qs] * len(rows), | |
| "gold": [json.dumps(gold(r, cats)) for r in rows], | |
| }) | |
| pq.write_table(table, out / f"{split}.parquet") | |
| summary[split] = {"cases": len(rows), "families": len({family(r) for r in rows}), | |
| "levels": dict(collections.Counter(r["risk_level"] for r in rows))} | |
| summary["questions"] = len(json.loads(qs)) | |
| (out.parent / "summary.json").write_text(json.dumps(summary, indent=1) + "\n") | |
| print(json.dumps(summary, indent=1)) | |
| if __name__ == "__main__": | |
| main() | |