Text Generation
Transformers
Safetensors
GGUF
English
qwen2
decompilation
reverse-engineering
python
bytecode
code
verified-generation
conversational
text-generation-inference
Instructions to use BlazingCustoms/pybytecode-v3-1.5b with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use BlazingCustoms/pybytecode-v3-1.5b with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-generation", model="BlazingCustoms/pybytecode-v3-1.5b") messages = [ {"role": "user", "content": "Who are you?"}, ] pipe(messages)# Load model directly from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained("BlazingCustoms/pybytecode-v3-1.5b") model = AutoModelForCausalLM.from_pretrained("BlazingCustoms/pybytecode-v3-1.5b", device_map="auto") messages = [ {"role": "user", "content": "Who are you?"}, ] inputs = tokenizer.apply_chat_template( messages, add_generation_prompt=True, tokenize=True, return_dict=True, return_tensors="pt", ).to(model.device) outputs = model.generate(**inputs, max_new_tokens=40) print(tokenizer.decode(outputs[0][inputs["input_ids"].shape[-1]:])) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use BlazingCustoms/pybytecode-v3-1.5b with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf BlazingCustoms/pybytecode-v3-1.5b:F16 # Run inference directly in the terminal: llama cli -hf BlazingCustoms/pybytecode-v3-1.5b:F16
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf BlazingCustoms/pybytecode-v3-1.5b:F16 # Run inference directly in the terminal: llama cli -hf BlazingCustoms/pybytecode-v3-1.5b:F16
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf BlazingCustoms/pybytecode-v3-1.5b:F16 # Run inference directly in the terminal: ./llama-cli -hf BlazingCustoms/pybytecode-v3-1.5b:F16
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf BlazingCustoms/pybytecode-v3-1.5b:F16 # Run inference directly in the terminal: ./build/bin/llama-cli -hf BlazingCustoms/pybytecode-v3-1.5b:F16
Use Docker
docker model run hf.co/BlazingCustoms/pybytecode-v3-1.5b:F16
- LM Studio
- Jan
- vLLM
How to use BlazingCustoms/pybytecode-v3-1.5b with vLLM:
Install from pip and serve model
# Install vLLM from pip: pip install vllm # Start the vLLM server: vllm serve "BlazingCustoms/pybytecode-v3-1.5b" # Call the server using curl (OpenAI-compatible API): curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "BlazingCustoms/pybytecode-v3-1.5b", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }'Use Docker
docker model run hf.co/BlazingCustoms/pybytecode-v3-1.5b:F16
- SGLang
How to use BlazingCustoms/pybytecode-v3-1.5b 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 "BlazingCustoms/pybytecode-v3-1.5b" \ --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": "BlazingCustoms/pybytecode-v3-1.5b", "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 "BlazingCustoms/pybytecode-v3-1.5b" \ --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": "BlazingCustoms/pybytecode-v3-1.5b", "messages": [ { "role": "user", "content": "What is the capital of France?" } ] }' - Ollama
How to use BlazingCustoms/pybytecode-v3-1.5b with Ollama:
ollama run hf.co/BlazingCustoms/pybytecode-v3-1.5b:F16
- Unsloth Studio
How to use BlazingCustoms/pybytecode-v3-1.5b with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for BlazingCustoms/pybytecode-v3-1.5b to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for BlazingCustoms/pybytecode-v3-1.5b to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for BlazingCustoms/pybytecode-v3-1.5b to start chatting
- Pi
How to use BlazingCustoms/pybytecode-v3-1.5b with Pi:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf BlazingCustoms/pybytecode-v3-1.5b:F16
Configure the model in Pi
# Install Pi: npm install -g @mariozechner/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "llama-cpp": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "BlazingCustoms/pybytecode-v3-1.5b:F16" } ] } } }Run Pi
# Start Pi in your project directory: pi
- OpenClaw new
How to use BlazingCustoms/pybytecode-v3-1.5b with OpenClaw:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf BlazingCustoms/pybytecode-v3-1.5b:F16
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "BlazingCustoms/pybytecode-v3-1.5b:F16" \ --custom-provider-id llama-cpp \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
- Docker Model Runner
How to use BlazingCustoms/pybytecode-v3-1.5b with Docker Model Runner:
docker model run hf.co/BlazingCustoms/pybytecode-v3-1.5b:F16
- Lemonade
How to use BlazingCustoms/pybytecode-v3-1.5b with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull BlazingCustoms/pybytecode-v3-1.5b:F16
Run and chat with the model
lemonade run user.pybytecode-v3-1.5b-F16
List all available models
lemonade list
- Hermes Agent
How to use BlazingCustoms/pybytecode-v3-1.5b with Hermes Agent:
Start the llama.cpp server
# Install llama.cpp: brew install llama.cpp # Start a local OpenAI-compatible server: llama serve -hf BlazingCustoms/pybytecode-v3-1.5b:F16
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default BlazingCustoms/pybytecode-v3-1.5b:F16
Run Hermes
hermes
- Atomic Chat
| license: apache-2.0 | |
| base_model: Qwen/Qwen2.5-Coder-1.5B-Instruct | |
| library_name: transformers | |
| pipeline_tag: text-generation | |
| language: | |
| - en | |
| tags: | |
| - decompilation | |
| - reverse-engineering | |
| - python | |
| - bytecode | |
| - code | |
| - verified-generation | |
| - qwen2 | |
| # PyBytecode v3 β 1.5B | |
| Turns Python 3.12 bytecode back into Python source. Hand it a disassembled code object, get source | |
| code back. | |
| The unusual part: **you can check every answer.** Recompile what the model wrote and compare it | |
| against the bytecode you started with β if they match, that file is exactly right, and you know it | |
| without trusting an accuracy number. | |
| Weights are Apache-2.0. A GGUF build ships alongside for llama.cpp / LM Studio / Ollama. | |
| ## Quickstart | |
| ```python | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| tok = AutoTokenizer.from_pretrained("BlazingCustoms/pybytecode-v3-1.5b") | |
| model = AutoModelForCausalLM.from_pretrained( | |
| "BlazingCustoms/pybytecode-v3-1.5b", torch_dtype="bfloat16", device_map="auto") | |
| INSTRUCTION = ("Decompile this Python 3.12 bytecode disassembly back into the original Python " | |
| "source code. Output only the source code.") | |
| # `disasm` comes from harness/pybytecode_core/rep.py: disassemble_v2(code_object) | |
| msgs = [{"role": "user", "content": f"{INSTRUCTION}\n\n{disasm}"}] | |
| batch = tok.apply_chat_template(msgs, add_generation_prompt=True, | |
| return_tensors="pt", return_dict=True).to(model.device) | |
| prediction = tok.decode(model.generate(**batch, max_new_tokens=2048, | |
| do_sample=False)[0][batch["input_ids"].shape[1]:], | |
| skip_special_tokens=True) | |
| ``` | |
| Greedy decoding (temperature 0) for a single shot; temperature ~0.8 when you sample several | |
| candidates. | |
| ## Checking the answer | |
| Compile the model's output and compare the resulting code object to the one you were decompiling. | |
| Same code object means same behaviour, so a match tells you *this* answer is correct: | |
| ```python | |
| from harness.pybytecode_core.verify import code_fingerprint | |
| def certified(prediction: str, reference_code_object) -> bool: | |
| got = compile(prediction, "<pred>", "exec", dont_inherit=True, optimize=0) | |
| return code_fingerprint(got) == code_fingerprint(reference_code_object) | |
| ``` | |
| Two things follow. A failed check means "not confirmed", not "wrong" β a correct rewrite that | |
| compiles differently (a `while` where the original had a `for`) won't match, so the accuracy | |
| figures below are a floor, not an estimate. And because the check is cheap and reliable, sampling | |
| several answers and keeping the first one that passes is a real gain rather than a nicer guess. | |
| ## Results | |
| On the benchmark published with this model: | |
| | | certified | | |
| |---|---| | |
| | **PyBytecode v3, one attempt** | **506 / 600 = 84.33%** | | |
| | **PyBytecode v3, up to 32 tries** | **562 / 600 = 93.67%** | | |
| | `Qwen2.5-Coder-1.5B-Instruct` before fine-tuning, one attempt | 4 / 600 = 0.67% | | |
| The benchmark is `csn-3.12-licensed`: 600 real functions from 117 GitHub repositories, compiled to | |
| 3.12 bytecode, shipped with the model. The base model before fine-tuning gets essentially none of | |
| them, so this is not something a general code model can guess its way through. | |
| Full numbers, confidence intervals, method, per-budget curve and the comparison with other | |
| systems: [`EVAL.md`](EVAL.md). | |
| [PyLingual](https://github.com/syssec-utd/pylingual) is another system that does this task, by | |
| symbolic reconstruction rather than generation. On our earlier benchmarks it scores about the same | |
| as we do, and the two miss on different inputs β so running both and keeping whichever answer | |
| passes the check gets you more than either alone. Numbers in [`EVAL.md`](EVAL.md). | |
| ## When it works well, and when it doesn't | |
| **It is good on individual functions and gets much worse on long ones.** Size is measured in | |
| *disassembly lines* β how long the input you hand the model is. One line tells you: | |
| ```python | |
| from harness.pybytecode_core.rep import disassemble_v2 | |
| rep_lines = disassemble_v2(code_object).count("\n") | |
| ``` | |
| | disassembly lines | rows | one attempt | up to 32 tries | | |
| |---|---|---|---| | |
| | under 100 | 448 | 92.86% | 98.21% | | |
| | 100β199 | 112 | 65.18% | 85.71% | | |
| | 200β399 | 32 | 53.12% | 81.25% | | |
| | 400+ | 8 | 0.00% | 0.00% | | |
| Below ~100 lines it is on home ground. Accuracy starts dropping around 200, and above ~400 lines | |
| nothing certified at all, even with 32 tries. Sampling more buys roughly one bucket of headroom; | |
| it does not remove the limit. For big units, a symbolic decompiler is the better tool. The full | |
| seven-bucket curve is in [`EVAL.md`](EVAL.md). | |
| ## Limits | |
| - **Long inputs.** The table above is the honest specification: trained on functions, not modules, | |
| and it fails above ~400 disassembly lines. | |
| - **Python 3.12 only.** Trained and measured on 3.12; the checker refuses other minor versions by | |
| design. | |
| - **If the `.pyc` was built with `-O`, compile at the same level or the check will not match.** | |
| Wrong level collapses to ~24%, so try all three β it costs three compiles. At `-O` and above, | |
| docstrings aren't in the `.pyc` at all, so docstring recovery can't be confirmed against one. | |
| - **A `.pyc` built by someone else can fail the check even when the answer is right** β about | |
| 0.33% of the time, because CPython patch releases compile the same source differently. It always | |
| fails in the safe direction: "unknown" about a correct answer, never "confirmed" about a wrong | |
| one. | |
| - **It has not been shown to work on real malware.** On the one packed sample we tried, the | |
| entry-point module produced nothing certifiable. Extraction worked; decompiling the actual | |
| malware logic did not. | |
| - Untested: Python 3.13, Nuitka, non-CPython builds, obfuscated bytecode. | |
| Details on all of these in [`EVAL.md`](EVAL.md) and [`ORACLE-LIMITS.md`](ORACLE-LIMITS.md). | |
| ## Model details | |
| Fine-tuned from [`Qwen/Qwen2.5-Coder-1.5B-Instruct`](https://huggingface.co/Qwen/Qwen2.5-Coder-1.5B-Instruct) | |
| (Apache-2.0) with LoRA on 48,196 pairs of Python 3.12 disassembly β source, adapter merged. The | |
| corpus was filtered to permissive licences before training and is not redistributed β per-row | |
| attribution was not retained, so shipping it would strip required notices. Lineage: | |
| [`DATA-CARD-training-corpus.md`](DATA-CARD-training-corpus.md). Training settings: [`EVAL.md`](EVAL.md). | |
| ## Licence | |
| **Apache-2.0.** See [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE). | |
| Derived from `Qwen/Qwen2.5-Coder-1.5B-Instruct`, which is Apache-2.0. Under Apache-2.0 Β§4 we ship | |
| the licence, retain attribution, and state our changes (LoRA fine-tune, adapter merged; no | |
| architecture, vocabulary or tokenizer change). The same obligations pass to you if you | |
| redistribute these weights or build derivatives. | |
| Decompilation has obvious dual use. Apache-2.0 imposes no field-of-use restriction and we have not | |
| added one. Complying with the law where you operate is your responsibility. | |
| ## Citation | |
| ```bibtex | |
| @software{pybytecode2026, | |
| title = {PyBytecode: verified neural decompilation for Python 3.12 bytecode}, | |
| author = {Blazing Customs}, | |
| year = {2026}, | |
| note = {Fine-tuned from Qwen2.5-Coder-1.5B-Instruct}, | |
| url = {https://huggingface.co/BlazingCustoms/pybytecode-v3-1.5b} | |
| } | |
| ``` | |