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
| """ | |
| Inference script for Expert Classification models. | |
| Loads a binary classifier (AutoModelForSequenceClassification + LoRA) that was | |
| trained with train_expert_classifier.py, and predicts whether a Solidity | |
| contract contains a specific vulnerability type. | |
| Output: a single label (safe / vulnerable) with confidence score. | |
| Usage: | |
| # From a local checkpoint folder (after training): | |
| python inference_classifier.py --checkpoint ./cls-expert-reentrancy/best_model --file contract.sol | |
| # From a Hub model (if pushed): | |
| python inference_classifier.py --checkpoint jhsu12/solidity-vuln-cls-reentrancy-v1 --file contract.sol | |
| # Inline code: | |
| python inference_classifier.py --checkpoint ./cls-expert-reentrancy/best_model \ | |
| --code "pragma solidity ^0.8.0; contract Vault { ... }" | |
| # Interactive mode: | |
| python inference_classifier.py --checkpoint ./cls-expert-reentrancy/best_model | |
| # Run all 5 experts at once (pass multiple checkpoints): | |
| python inference_classifier.py --file contract.sol \ | |
| --checkpoint ./cls-expert-reentrancy/best_model \ | |
| --checkpoint ./cls-expert-access-control/best_model \ | |
| --checkpoint ./cls-expert-integer-overflow-underflow/best_model \ | |
| --checkpoint ./cls-expert-timestamp-dependence/best_model \ | |
| --checkpoint ./cls-expert-unchecked-low-level-calls/best_model | |
| """ | |
| import argparse | |
| import os | |
| import sys | |
| import json | |
| import torch | |
| import torch.nn.functional as F | |
| from transformers import AutoTokenizer, AutoModelForSequenceClassification, BitsAndBytesConfig | |
| from peft import PeftModel, PeftConfig | |
| # ββ Configuration βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| BASE_MODEL = "Qwen/Qwen2.5-Coder-3B-Instruct" | |
| LABEL_MAP = {0: "safe", 1: "vulnerable"} | |
| def parse_args(): | |
| parser = argparse.ArgumentParser( | |
| description="Run expert classifier inference on Solidity code." | |
| ) | |
| parser.add_argument( | |
| "--checkpoint", type=str, action="append", required=True, | |
| help="Path to classifier checkpoint (local folder or Hub ID). " | |
| "Can specify multiple times to run several experts." | |
| ) | |
| parser.add_argument( | |
| "--file", type=str, default=None, | |
| help="Path to a .sol file to analyze" | |
| ) | |
| parser.add_argument( | |
| "--code", type=str, default=None, | |
| help="Inline Solidity code string to analyze" | |
| ) | |
| parser.add_argument( | |
| "--max_seq_len", type=int, default=1536, | |
| help="Max sequence length for tokenization (default: 1536)" | |
| ) | |
| parser.add_argument( | |
| "--load_in_4bit", action="store_true", default=True, | |
| help="Use 4-bit quantization (default: True)" | |
| ) | |
| parser.add_argument( | |
| "--load_in_8bit", action="store_true", default=False, | |
| help="Use 8-bit quantization instead of 4-bit" | |
| ) | |
| parser.add_argument( | |
| "--threshold", type=float, default=0.5, | |
| help="Confidence threshold for 'vulnerable' prediction (default: 0.5)" | |
| ) | |
| parser.add_argument( | |
| "--json", action="store_true", default=False, | |
| help="Output results as JSON" | |
| ) | |
| return parser.parse_args() | |
| def detect_base_model(checkpoint_path): | |
| """Try to read the base model from the adapter config, fallback to default.""" | |
| # Check for adapter_config.json in local 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) | |
| base = cfg.get("base_model_name_or_path", BASE_MODEL) | |
| print(f" Base model (from adapter_config): {base}") | |
| return base | |
| # Try loading PeftConfig from Hub | |
| try: | |
| peft_config = PeftConfig.from_pretrained(checkpoint_path) | |
| base = peft_config.base_model_name_or_path | |
| print(f" Base model (from PeftConfig): {base}") | |
| return base | |
| except Exception: | |
| pass | |
| print(f" Base model (default): {BASE_MODEL}") | |
| return BASE_MODEL | |
| def load_classifier(checkpoint_path, load_in_4bit=True, load_in_8bit=False): | |
| """Load base model (SeqCls) + LoRA adapter for classification.""" | |
| print(f"\nπ Loading classifier from: {checkpoint_path}") | |
| base_model_id = detect_base_model(checkpoint_path) | |
| # Device / dtype | |
| if torch.cuda.is_available(): | |
| gpu_name = torch.cuda.get_device_name(0) | |
| gpu_mem = torch.cuda.get_device_properties(0).total_memory / 1e9 | |
| has_bf16 = torch.cuda.is_bf16_supported() | |
| print(f" π₯οΈ GPU: {gpu_name} ({gpu_mem:.1f} GB)") | |
| else: | |
| has_bf16 = False | |
| print(" β οΈ No GPU β running on CPU (slow)") | |
| compute_dtype = torch.bfloat16 if has_bf16 else torch.float16 | |
| # Quantization | |
| if load_in_8bit: | |
| bnb_config = BitsAndBytesConfig(load_in_8bit=True) | |
| elif load_in_4bit: | |
| bnb_config = BitsAndBytesConfig( | |
| load_in_4bit=True, | |
| bnb_4bit_quant_type="nf4", | |
| bnb_4bit_compute_dtype=compute_dtype, | |
| bnb_4bit_use_double_quant=True, | |
| ) | |
| else: | |
| bnb_config = None | |
| # Attention implementation | |
| attn_impl = "sdpa" | |
| try: | |
| import flash_attn | |
| attn_impl = "flash_attention_2" | |
| except ImportError: | |
| pass | |
| # Load base as SequenceClassification model | |
| model_kwargs = dict( | |
| num_labels=2, | |
| id2label={0: "safe", 1: "vulnerable"}, | |
| label2id={"safe": 0, "vulnerable": 1}, | |
| device_map="auto", | |
| torch_dtype=compute_dtype, | |
| trust_remote_code=True, | |
| attn_implementation=attn_impl, | |
| ignore_mismatched_sizes=True, | |
| ) | |
| if bnb_config is not None: | |
| model_kwargs["quantization_config"] = bnb_config | |
| model = AutoModelForSequenceClassification.from_pretrained( | |
| base_model_id, **model_kwargs | |
| ) | |
| # Load LoRA adapter (includes the trained score head via modules_to_save) | |
| model = PeftModel.from_pretrained(model, checkpoint_path) | |
| model.eval() | |
| # Tokenizer β try from checkpoint first, fall back to base | |
| 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 | |
| # Infer expert name from checkpoint path | |
| expert_name = os.path.basename(checkpoint_path.rstrip("/")) | |
| for prefix in ["cls-expert-", "solidity-vuln-cls-", "best_model"]: | |
| expert_name = expert_name.replace(prefix, "") | |
| if not expert_name or expert_name == "best_model": | |
| expert_name = os.path.basename(os.path.dirname(checkpoint_path.rstrip("/"))) | |
| for prefix in ["cls-expert-", "solidity-vuln-cls-"]: | |
| expert_name = expert_name.replace(prefix, "") | |
| print(f" β Classifier loaded (expert: {expert_name})") | |
| return model, tokenizer, expert_name | |
| def classify(model, tokenizer, solidity_code, max_seq_len=1536, threshold=0.5): | |
| """Run a single classification inference. Returns dict with prediction.""" | |
| inputs = tokenizer( | |
| solidity_code, | |
| return_tensors="pt", | |
| truncation=True, | |
| max_length=max_seq_len, | |
| padding=True, | |
| ) | |
| inputs = {k: v.to(model.device) for k, v in inputs.items()} | |
| with torch.no_grad(): | |
| outputs = model(**inputs) | |
| logits = outputs.logits[0] # shape: (2,) | |
| probs = F.softmax(logits, dim=-1) | |
| safe_prob = probs[0].item() | |
| vuln_prob = probs[1].item() | |
| predicted_label = "vulnerable" if vuln_prob >= threshold else "safe" | |
| return { | |
| "prediction": predicted_label, | |
| "confidence": max(safe_prob, vuln_prob), | |
| "prob_safe": round(safe_prob, 4), | |
| "prob_vulnerable": round(vuln_prob, 4), | |
| "logit_safe": round(logits[0].item(), 4), | |
| "logit_vulnerable": round(logits[1].item(), 4), | |
| } | |
| def main(): | |
| args = parse_args() | |
| # ββ Get the Solidity code βββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if args.file: | |
| print(f"π Reading Solidity file: {args.file}") | |
| with open(args.file, "r") as f: | |
| solidity_code = f.read() | |
| elif args.code: | |
| solidity_code = args.code | |
| else: | |
| print("π Paste your Solidity code below, then press Ctrl-D (Linux/Mac) " | |
| "or Ctrl-Z+Enter (Windows) to submit:\n") | |
| solidity_code = sys.stdin.read() | |
| if not solidity_code.strip(): | |
| print("β No code provided. Use --file, --code, or pipe to stdin.") | |
| sys.exit(1) | |
| print(f"π Input code length: {len(solidity_code)} characters") | |
| # ββ Run each expert βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| all_results = [] | |
| for ckpt in args.checkpoint: | |
| model, tokenizer, expert_name = load_classifier( | |
| ckpt, | |
| load_in_4bit=args.load_in_4bit and not args.load_in_8bit, | |
| load_in_8bit=args.load_in_8bit, | |
| ) | |
| result = classify( | |
| model, tokenizer, solidity_code, | |
| max_seq_len=args.max_seq_len, | |
| threshold=args.threshold, | |
| ) | |
| result["expert"] = expert_name | |
| result["checkpoint"] = ckpt | |
| all_results.append(result) | |
| # Free memory before loading next expert | |
| del model | |
| if torch.cuda.is_available(): | |
| torch.cuda.empty_cache() | |
| # ββ Output ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| if args.json: | |
| print(json.dumps(all_results, indent=2)) | |
| else: | |
| print("\n" + "=" * 60) | |
| print(" EXPERT CLASSIFICATION RESULTS") | |
| print("=" * 60) | |
| for r in all_results: | |
| icon = "π΄" if r["prediction"] == "vulnerable" else "π’" | |
| print(f"\n {icon} Expert: {r['expert']}") | |
| print(f" Prediction: {r['prediction'].upper()}") | |
| print(f" Confidence: {r['confidence']:.1%}") | |
| print(f" P(safe): {r['prob_safe']:.4f}") | |
| print(f" P(vuln): {r['prob_vulnerable']:.4f}") | |
| print(f" Logits: safe={r['logit_safe']:.4f} vuln={r['logit_vulnerable']:.4f}") | |
| # Summary if multiple experts | |
| if len(all_results) > 1: | |
| flagged = [r for r in all_results if r["prediction"] == "vulnerable"] | |
| print(f"\n{'β' * 60}") | |
| if flagged: | |
| print(f" β οΈ Flagged by {len(flagged)}/{len(all_results)} experts:") | |
| for r in flagged: | |
| print(f" β’ {r['expert']} ({r['prob_vulnerable']:.1%} confidence)") | |
| else: | |
| print(f" β Passed all {len(all_results)} expert checks") | |
| print("\n" + "=" * 60) | |
| if __name__ == "__main__": | |
| main() | |