Instructions to use jhsu12/solidity-vulnerability-detector with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use jhsu12/solidity-vulnerability-detector with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen2.5-Coder-7B-Instruct") model = PeftModel.from_pretrained(base_model, "jhsu12/solidity-vulnerability-detector") - Transformers
How to use jhsu12/solidity-vulnerability-detector with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="jhsu12/solidity-vulnerability-detector") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("jhsu12/solidity-vulnerability-detector", dtype="auto") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- vLLM
How to use jhsu12/solidity-vulnerability-detector with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "jhsu12/solidity-vulnerability-detector" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "jhsu12/solidity-vulnerability-detector", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/jhsu12/solidity-vulnerability-detector
- SGLang
How to use jhsu12/solidity-vulnerability-detector with SGLang:
Install from pip and serve model
# Install SGLang from pip: pip install sglang # Start the SGLang server: python3 -m sglang.launch_server \ --model-path "jhsu12/solidity-vulnerability-detector" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "jhsu12/solidity-vulnerability-detector", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker images
docker run --gpus all \ --shm-size 32g \ -p 30000:30000 \ -v ~/.cache/huggingface:/root/.cache/huggingface \ --env "HF_TOKEN=<secret>" \ --ipc=host \ lmsysorg/sglang:latest \ python3 -m sglang.launch_server \ --model-path "jhsu12/solidity-vulnerability-detector" \ --host 0.0.0.0 \ --port 30000 # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:30000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "jhsu12/solidity-vulnerability-detector", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Docker Model Runner
How to use jhsu12/solidity-vulnerability-detector with Docker Model Runner:
docker model run hf.co/jhsu12/solidity-vulnerability-detector
| """ | |
| Quick sanity check: evaluate a classifier expert on its OWN training/test data. | |
| This confirms whether the model actually learned anything, using the exact same | |
| data format and preprocessing as training. | |
| Usage: | |
| python evaluate_on_train_data.py \ | |
| --checkpoint ./cls-expert-reentrancy/checkpoint-150 \ | |
| --expert reentrancy | |
| # Use train split instead of test: | |
| python evaluate_on_train_data.py \ | |
| --checkpoint ./cls-expert-reentrancy/checkpoint-150 \ | |
| --expert reentrancy --split train | |
| # Limit samples: | |
| python evaluate_on_train_data.py \ | |
| --checkpoint ./cls-expert-reentrancy/checkpoint-150 \ | |
| --expert reentrancy --max_samples 50 | |
| # Show more preview samples: | |
| python evaluate_on_train_data.py \ | |
| --checkpoint ./cls-expert-reentrancy/checkpoint-150 \ | |
| --expert reentrancy --preview 10 | |
| """ | |
| import argparse | |
| import os | |
| import json | |
| import numpy as np | |
| import torch | |
| from datasets import load_dataset | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification, BitsAndBytesConfig | |
| from peft import PeftModel, PeftConfig | |
| from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, roc_auc_score, confusion_matrix | |
| # ββ Config ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| BASE_MODEL = "Qwen/Qwen2.5-Coder-3B-Instruct" | |
| EXPERT_DATASETS = { | |
| "reentrancy": "jhsu12/solidity-vuln-expert-reentrancy", | |
| "access-control": "jhsu12/solidity-vuln-expert-access-control", | |
| "integer-overflow-underflow": "jhsu12/solidity-vuln-expert-integer-overflow-underflow", | |
| "timestamp-dependence": "jhsu12/solidity-vuln-expert-timestamp-dependence", | |
| "unchecked-low-level-calls": "jhsu12/solidity-vuln-expert-unchecked-low-level-calls", | |
| } | |
| EXPERTS = { | |
| "reentrancy": "Reentrancy", | |
| "access-control": "Access Control", | |
| "integer-overflow-underflow": "Integer Overflow/Underflow", | |
| "timestamp-dependence": "Timestamp Dependence", | |
| "unchecked-low-level-calls": "Unchecked Low-Level Calls", | |
| } | |
| def parse_args(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument("--checkpoint", type=str, required=True) | |
| parser.add_argument("--expert", type=str, required=True, choices=list(EXPERTS.keys())) | |
| parser.add_argument("--split", type=str, default="test", choices=["train", "test"]) | |
| parser.add_argument("--max_samples", type=int, default=None) | |
| parser.add_argument("--max_seq_len", type=int, default=1536) | |
| parser.add_argument("--batch_size", type=int, default=16) | |
| parser.add_argument("--threshold", type=float, default=0.5) | |
| parser.add_argument("--preview", type=int, default=5, help="Number of samples to print in detail") | |
| return parser.parse_args() | |
| def detect_base_model(checkpoint_path): | |
| config_path = os.path.join(checkpoint_path, "adapter_config.json") | |
| if os.path.isfile(config_path): | |
| with open(config_path, "r") as f: | |
| cfg = json.load(f) | |
| return cfg.get("base_model_name_or_path", BASE_MODEL) | |
| try: | |
| peft_config = PeftConfig.from_pretrained(checkpoint_path) | |
| return peft_config.base_model_name_or_path | |
| except Exception: | |
| return BASE_MODEL | |
| def load_classifier(checkpoint_path): | |
| base_model_id = detect_base_model(checkpoint_path) | |
| print(f" Base model: {base_model_id}") | |
| has_bf16 = torch.cuda.is_bf16_supported() if torch.cuda.is_available() else False | |
| compute_dtype = torch.bfloat16 if has_bf16 else torch.float16 | |
| bnb_config = BitsAndBytesConfig( | |
| load_in_4bit=True, bnb_4bit_quant_type="nf4", | |
| bnb_4bit_compute_dtype=compute_dtype, bnb_4bit_use_double_quant=True, | |
| ) | |
| attn_impl = "sdpa" | |
| try: | |
| import flash_attn | |
| attn_impl = "flash_attention_2" | |
| except ImportError: | |
| pass | |
| model = AutoModelForSequenceClassification.from_pretrained( | |
| base_model_id, num_labels=2, | |
| id2label={0: "safe", 1: "vulnerable"}, | |
| label2id={"safe": 0, "vulnerable": 1}, | |
| quantization_config=bnb_config, device_map="auto", | |
| torch_dtype=compute_dtype, trust_remote_code=True, | |
| attn_implementation=attn_impl, ignore_mismatched_sizes=True, | |
| ) | |
| model = PeftModel.from_pretrained(model, checkpoint_path) | |
| model.eval() | |
| try: | |
| tokenizer = AutoTokenizer.from_pretrained(checkpoint_path, trust_remote_code=True) | |
| except Exception: | |
| tokenizer = AutoTokenizer.from_pretrained(base_model_id, trust_remote_code=True) | |
| if tokenizer.pad_token is None: | |
| tokenizer.pad_token = tokenizer.eos_token | |
| model.config.pad_token_id = tokenizer.pad_token_id | |
| return model, tokenizer | |
| def extract_user_code(messages): | |
| """Extract the Solidity code from the user message β same as training.""" | |
| for msg in messages: | |
| if msg["role"] == "user": | |
| return msg["content"] | |
| return "" | |
| def main(): | |
| args = parse_args() | |
| expert_name = EXPERTS[args.expert] | |
| dataset_id = EXPERT_DATASETS[args.expert] | |
| print("=" * 60) | |
| print(f" Sanity Check: {expert_name} on its own {args.split} split") | |
| print("=" * 60) | |
| print(f" Checkpoint: {args.checkpoint}") | |
| print(f" Dataset: {dataset_id}") | |
| print(f" Split: {args.split}") | |
| # ββ Load dataset ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| print(f"\nπ¦ Loading {dataset_id} [{args.split}]...") | |
| dataset = load_dataset(dataset_id, split=args.split) | |
| if args.max_samples: | |
| dataset = dataset.select(range(min(args.max_samples, len(dataset)))) | |
| # Extract codes and labels β SAME preprocessing as training | |
| codes = [extract_user_code(row["messages"]) for row in dataset] | |
| labels = [int(row["is_expert_type"]) for row in dataset] | |
| n_pos = sum(labels) | |
| n_neg = len(labels) - n_pos | |
| print(f" Samples: {len(codes)} (positive={n_pos}, negative={n_neg}, " | |
| f"ratio={n_pos/len(labels):.1%})") | |
| # Token length stats | |
| print(f"\nπ Code length stats:") | |
| char_lens = [len(c) for c in codes] | |
| print(f" Chars: min={min(char_lens)}, median={int(np.median(char_lens))}, " | |
| f"mean={int(np.mean(char_lens))}, max={max(char_lens)}") | |
| # ββ Load model ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| print(f"\nπ€ Loading model...") | |
| model, tokenizer = load_classifier(args.checkpoint) | |
| print(f" β Model loaded") | |
| # ββ Run inference βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| print(f"\nπ Running inference...") | |
| all_logits = [] | |
| for i in range(0, len(codes), args.batch_size): | |
| batch = codes[i:i + args.batch_size] | |
| inputs = tokenizer(batch, return_tensors="pt", truncation=True, | |
| max_length=args.max_seq_len, padding=True) | |
| inputs = {k: v.to(model.device) for k, v in inputs.items()} | |
| with torch.no_grad(): | |
| outputs = model(**inputs) | |
| all_logits.append(outputs.logits.cpu().float().numpy()) | |
| done = min(i + args.batch_size, len(codes)) | |
| if done % (args.batch_size * 10) == 0 or done == len(codes): | |
| print(f" [{done}/{len(codes)}]") | |
| logits = np.concatenate(all_logits, axis=0) | |
| probs = torch.softmax(torch.tensor(logits), dim=-1).numpy() | |
| probs_vuln = probs[:, 1].tolist() | |
| preds = [1 if p >= args.threshold else 0 for p in probs_vuln] | |
| # ββ Print first N samples βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| n_preview = min(args.preview, len(codes)) | |
| print(f"\n{'β' * 60}") | |
| print(f" FIRST {n_preview} SAMPLES") | |
| print(f"{'β' * 60}") | |
| for idx in range(n_preview): | |
| code_preview = codes[idx].replace('\n', ' ')[:100] | |
| gt = "VULNERABLE" if labels[idx] == 1 else "SAFE" | |
| pred = "VULNERABLE" if preds[idx] == 1 else "SAFE" | |
| match = "β " if labels[idx] == preds[idx] else "β" | |
| print(f"\n [{idx+1}/{n_preview}] {match}") | |
| print(f" Code: {code_preview}...") | |
| print(f" is_expert_type: {bool(labels[idx])}") | |
| print(f" Ground truth: {gt} (label={labels[idx]})") | |
| print(f" Prediction: {pred} (label={preds[idx]})") | |
| print(f" P(safe): {probs[idx][0]:.6f}") | |
| print(f" P(vulnerable): {probs_vuln[idx]:.6f}") | |
| print(f" Logits: safe={logits[idx][0]:.4f} vuln={logits[idx][1]:.4f}") | |
| # ββ Compute metrics βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| acc = accuracy_score(labels, preds) | |
| f1 = f1_score(labels, preds, average="binary", zero_division=0) | |
| prec = precision_score(labels, preds, average="binary", zero_division=0) | |
| rec = recall_score(labels, preds, average="binary", zero_division=0) | |
| try: | |
| auc = roc_auc_score(labels, probs_vuln) if len(set(labels)) > 1 else 0.0 | |
| except ValueError: | |
| auc = 0.0 | |
| cm = confusion_matrix(labels, preds, labels=[0, 1]) | |
| print(f"\n{'β' * 60}") | |
| print(f" RESULTS β {expert_name} on {args.split} split") | |
| print(f"{'β' * 60}") | |
| print(f" Accuracy: {acc:.4f}") | |
| print(f" F1: {f1:.4f}") | |
| print(f" Precision: {prec:.4f}") | |
| print(f" Recall: {rec:.4f}") | |
| print(f" AUC: {auc:.4f}") | |
| print(f"\n Confusion Matrix:") | |
| print(f" Pred SAFE Pred VULN") | |
| print(f" Actual SAFE {cm[0][0]:>8} {cm[0][1]:>8}") | |
| print(f" Actual VULN {cm[1][0]:>8} {cm[1][1]:>8}") | |
| # ββ Diagnosis βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| print(f"\n{'β' * 60}") | |
| print(f" DIAGNOSIS") | |
| print(f"{'β' * 60}") | |
| if acc > 0.9 and f1 > 0.8: | |
| print(f" β Model learned well on {args.split} data.") | |
| print(f" Low eval F1 is likely due to distribution shift (longer code).") | |
| elif acc > 0.7: | |
| print(f" β οΈ Model partially learned. F1={f1:.3f} suggests room for improvement.") | |
| print(f" Check: learning rate, epochs, class balance.") | |
| else: | |
| print(f" β Model did NOT learn. Acc={acc:.3f}, F1={f1:.3f}") | |
| print(f" Possible issues:") | |
| print(f" - Training didn't converge (check training loss)") | |
| print(f" - Score head not saved properly (check modules_to_save)") | |
| print(f" - Wrong checkpoint loaded") | |
| # Check if model is just predicting one class | |
| pred_dist = {0: preds.count(0), 1: preds.count(1)} | |
| if pred_dist[0] == 0 or pred_dist[1] == 0: | |
| majority = 0 if pred_dist[0] > pred_dist[1] else 1 | |
| print(f"\n β οΈ Model predicts ALL {'SAFE' if majority == 0 else 'VULNERABLE'}!") | |
| print(f" Pred distribution: safe={pred_dist[0]}, vuln={pred_dist[1]}") | |
| print(f" This means the model hasn't learned to discriminate.") | |
| else: | |
| print(f"\n Pred distribution: safe={pred_dist[0]}, vuln={pred_dist[1]}") | |
| print(f" True distribution: safe={n_neg}, vuln={n_pos}") | |
| # Check confidence calibration | |
| correct_probs = [probs_vuln[i] if labels[i] == 1 else 1 - probs_vuln[i] | |
| for i in range(len(labels))] | |
| print(f"\n Confidence on correct class:") | |
| print(f" Mean: {np.mean(correct_probs):.4f}") | |
| print(f" Min: {np.min(correct_probs):.4f}") | |
| print(f" P25: {np.percentile(correct_probs, 25):.4f}") | |
| print(f" P50: {np.percentile(correct_probs, 50):.4f}") | |
| print(f"\n{'=' * 60}") | |
| if __name__ == "__main__": | |
| main() | |