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
PyBytecode v3 β full evaluation
The model card is deliberately short. This file is the long version: every number, the interval around it, the set it was measured on, and the command that reproduces it. Nothing here is softened relative to the card; the card is a subset.
Companion files: ORACLE-LIMITS.md for what the check can and cannot do,
DATA-CARD-training-corpus.md for training-data lineage.
1. What "certified" means
The oracle is sound but incomplete:
verified = PROVABLY correct. Recompiling the prediction yields a code object byte-identical to
the target's. Identical code object => identical behaviour. No false positives.
unverified = UNKNOWN, not wrong. A correct decompilation that compiles differently β a `while`
where the original had a `for`, a differently-ordered but equivalent boolean β
does not certify.
Three consequences:
- Reported accuracy is a lower bound on correctness. Everything counted here is proven; some of what is not counted is right too.
- Best-of-N buys real accuracy, not a better guess. Sample until something certifies, then stop. The verifier decides when to stop, so extra budget cannot mislead you.
- The check is exact. Comparison runs over the real code object, recursively, including
docstrings and
co_exceptiontableβ not over a textual disassembly. That is not decoration: an earlier representation omitted the exception table'send, which made atry:body and atry/else:body indistinguishable, and it once certified a wrong prediction.
Strict L1 oracle throughout this file. Every figure carries a 95% interval and names its set.
2. Headline results β csn-3.12-licensed, n=600 across 117 repositories
| certified | 95% CI | |
|---|---|---|
| PyBytecode v3, greedy | 506 / 600 = 84.33% | [80.48, 87.94] |
| PyBytecode v3, verified best-of-32 | 562 / 600 = 93.67% | [90.86, 96.08] |
Untuned Qwen2.5-Coder-1.5B-Instruct, greedy |
4 / 600 = 0.67% | [0.16, 1.35] |
Intervals are repo-clustered (bootstrap over repositories, 10,000 resamples), because rows from one repository share an author and a house style and are not independent. Design effects 1.65 / 1.79 / 0.84.
The benchmark ships with the model, licence-resolved per row at the exact commit, so these numbers are recomputable from files in this repository rather than taken on faith.
The untuned base scores ~0, which is what makes the benchmark trustworthy
The same base model, given the same prompt, the same decoding budget and the same oracle, certifies 4 of 600 here and 0 of 400 on our earlier benchmark. Under looser oracles it is clearer still: the base produces syntactically valid Python on 52% of rows and reaches AST-identity on 0%. It paraphrases the disassembly into plausible-looking code with invented helpers rather than inverting it.
A strong general code model cannot guess its way to a single point on this task. The benchmark is not solvable by pattern-matching, and everything v3 scores was learned from the fine-tune. The paired difference is not close to the noise floor: exact McNemar on 502 discordant pairs in our favour and 0 against gives p < 1e-12.
The benchmark rebuild reproduced the result
The published 600-row set was built from scratch: different rows (only 85 of 600 appear in the earlier 400-row set), 117 repositories instead of 24, and a 1% per-repo cap replacing a 15% concentration. It lands in the same place β certified@32 93.67% against 93.25%, greedy 84.33% against 83.75%. The difference of +0.42pp carries a 95% interval of [β4.38, +5.22], so it is well inside noise, and the two size profiles are near-identical (median 59 vs 62 rep lines; 93.3% vs 94.0% of rows under 200), which is the composition factor that would otherwise move the number. Standardised to the older set's size mix the new set reads 94.48%. A result that survives a rebuild of the set it was measured on is worth more than the same result quoted twice.
Which numbers came from where
| Set | Published? | Why |
|---|---|---|
csn-3.12-licensed (600) |
yes | every row licence-resolved at its commit |
pybytecode-mbpp-3.12 (383) |
yes | MBPP, CC-BY-4.0 |
| CSN-3.12 (400) | no | 45% of its rows are not redistributable |
| Held-out (279) | no | per-row attribution was not retained |
Our own results are measured on both the published set and the earlier pair. The figures in Comparison with other systems exist only on the earlier pair, because that is where those runs were done; they are labelled there because you cannot re-run them from what we shipped.
3. How much sampling budget to spend
The best-of-32 budget is 1 greedy decode + 31 sampled candidates at temperature 0.8, with verified early stop β sampling halts on the first candidate that certifies, so the mean cost is far below 32. Across the 94 greedy failures it took a mean of 15.16 samples and recovered 56:
| budget | certified | |
|---|---|---|
| @1 (greedy alone) | 506 / 600 | 84.33% |
| @2 | 525 / 600 | 87.50% |
| @4 | 546 / 600 | 91.00% |
| @8 | 555 / 600 | 92.50% |
| @16 | 558 / 600 | 93.00% |
| @32 | 562 / 600 | 93.67% |
Most of the recovery arrives in the first few samples: @4 already captures two thirds of what @32 gets. Because early stop depends only on the index of the first passing sample, this curve is exact rather than an estimate β the same cached generations give every point.
4. Accuracy by input size β the full curve
The size axis is rep lines: the number of lines in the disassembly handed to the model. One line measures it:
from harness.pybytecode_core.rep import disassemble_v2
rep_lines = disassemble_v2(code_object).count("\n")
On the published 600-row benchmark
Recomputable from the files in this repo with harness/size_curve.py:
| rep lines | rows | v3 greedy | 95% CI | v3 best-of-32 | 95% CI |
|---|---|---|---|---|---|
| 0β49 | 224 | 95.98% | [93.01, 98.51] | 98.21% | [96.31, 99.58] |
| 50β99 | 224 | 89.73% | [85.17, 93.93] | 98.21% | [96.26, 99.57] |
| 100β199 | 112 | 65.18% | [55.36, 74.14] | 85.71% | [77.57, 92.98] |
| 200β299 | 27 | 51.85% | β | 77.78% | β |
| 300β399 | 5 | 60.00% | β | 100.00% | β |
| 400β599 | 5 | 0.00% | β | 0.00% | β |
| 600+ | 3 | 0.00% | β | 0.00% | β |
Intervals are repo-clustered, and omitted below 30 rows / 10 repositories rather than printed at a width that would imply precision we do not have. The 300β399 bucket reading above the one below it is n=5 noise, not a recovery. Median input in this benchmark is 59 rep lines; p90 is 167, max 1,622.
On this set the top two buckets stay at 0% even with 32 samples β above ~400 rep lines, sampling did not rescue a single one of the 8 rows. 96.64% of greedy certifications and 95.37% of best-of-32 certifications come from units under 200 rep lines.
The four-row grouping on the model card is this same table pooled: under 100 rep lines is 416 / 448 = 92.86% greedy and 440 / 448 = 98.21% at 32; 200β399 is 17 / 32 = 53.12% and 26 / 32 = 81.25%; 400+ is 0 / 8 at both budgets.
Pooled over both earlier benchmarks (n=679)
Pooled so the thin upper buckets carry as many rows as we can give them. This is also the only table where PyLingual appears per bucket:
| rep lines | rows | v3 greedy | v3 best-of-32 | untuned base | PyLingual k=32 |
|---|---|---|---|---|---|
| 0β49 | 311 | 94.21% | 98.71% | 0.96% | 99.04% |
| 50β99 | 229 | 88.65% | 96.94% | 0.00% | 95.63% |
| 100β199 | 105 | 78.10% | 88.57% | 0.00% | 84.76% |
| 200β299 | 19 | 47.37% | 84.21% | 0.00% | 84.21% |
| 300β399 | 11 | 18.18% | 54.55% | 0.00% | 81.82% |
| 400β599 | 2 | 0.00% | 50.00% | 0.00% | 100.00% |
| 600+ | 2 | 0.00% | 0.00% | 0.00% | 50.00% |
- The greedy knee is at ~200 rep lines: 78.1% β 47.4% β 18.2% β 0% across four consecutive buckets.
- Best-of-32 postpones the knee to ~300; it does not remove it. Sampling 32 times buys roughly one bucket of headroom.
- Almost every point we score comes from small units. On the earlier CSN-3.12 set (n=400), 97.61% of greedy certifications and 95.98% of best-of-32 certifications are units under 200 rep lines; on the published 600-row set it is 96.64% of greedy certifications. The headline accuracy is a statement about small units.
- The top two buckets are n=2 each and carry nothing on their own. What carries the conclusion is the monotone decline through n=311/229/105/19/11 below them.
5. Comparison with other systems
PyLingual is another system that performs this task, by symbolic reconstruction rather than generation. We ran it on the same sets, under the same oracle, at a matched budget.
| CSN-3.12, n=400, 24 repos | certified | 95% CI (repo-clustered) |
|---|---|---|
| untuned base, greedy | 0 / 400 = 0.00% | β |
| v3 greedy | 335 / 400 = 83.75% | [77.84, 88.89] |
| v3 certified@32 | 373 / 400 = 93.25% | [88.82, 96.89] |
| PyLingual k=32 | 377 / 400 = 94.25% | [91.06, 96.80] |
| union | 393 / 400 = 98.25% | [96.81, 99.51] |
| Held-out, n=279 | certified | 95% CI (Wilson) |
|---|---|---|
| untuned base, greedy | 3 / 279 = 1.08% | [0.37, 3.11] |
| v3 greedy | 254 / 279 = 91.04% | [87.11, 93.86] |
| v3 certified@32 | 272 / 279 = 97.49% | [94.91, 98.78] |
| PyLingual k=32 | 267 / 279 = 95.70% | [92.63, 97.52] |
| union | 275 / 279 = 98.57% | [96.37, 99.44] |
Neither difference is statistically significant (exact paired McNemar, p = 0.6177 on CSN and p = 0.2266 on held-out). We claim no accuracy advantage, and none is claimed against us. On cost the comparison runs against us: ~1.5B parameters against their ~320M, and slower wall-clock.
Docstring recovery on the 115 held-out rows carrying a real docstring: 115 / 115 = 100% (PyLingual: 113/115 = 98.26%, under an oracle that does not score docstrings at all).
The held-out interval is Wilson, not clustered: every row of that set carries the same placeholder repository value, so its clustering cannot be assessed. The CSN design effects of 2.34β2.69 show why that matters β on a set where one repository supplied 15% of rows, a naive interval would have been far too narrow.
These figures were measured on our earlier benchmark pair, which is not published. PyLingual has not been run on the 600-row licensed benchmark released alongside this model.
The two approaches fail on different inputs
The more interesting measured result is not which number is larger, but that the two systems lose on different inputs, along an axis that turns out to be unit size:
| rep lines | rows | PyBytecode greedy | PyBytecode @32 | PyLingual k=32 |
|---|---|---|---|---|
| 100β199 | 105 | 78.10% | 88.57% | 84.76% |
| 200β299 | 19 | 47.37% | 84.21% | 84.21% |
| 300β399 | 11 | 18.18% | 54.55% | 81.82% |
| 400β599 | 2 | 0.00% | 50.00% | 100.0% |
A generative model degrades as its input grows; a symbolic reconstruction does not. Two things follow, both useful:
- Large units are not intrinsically unsolvable. A symbolic system handles them at 81.82% where we score 18.18%. What our curve measures is a capability limit of a 1.5B model, not a property of the task β which is a statement about where to spend the next round of scale.
- The union exceeds either system, 98.25% and 98.57% above. Because verification is sound, the union costs nothing to take: run either, keep the answer that certifies, fall through to the other. Neither system can certify a wrong answer, so combining them cannot mislead you.
6. Limits, in full
Large units β this is the measured limit. Certification falls from 94% under 50 representation lines to 18% at 300β399 and 0% above 400. The curve in Β§4 is the honest specification of what this model does. It was trained on functions; a whole module is a different regime in both size and shape, and we have not evaluated one.
Python 3.12 only. A scope statement, not the explanation for the size behaviour above: trained and measured on 3.12, and the oracle refuses cross-minor input by design. Every number in this file is in-version, so nothing here is contaminated by a version mismatch.
It did not decompile real malware. On the one wild PyInstaller-packed sample in scope, the entry-point module produced nothing certifiable β the prediction did not even compile. 3 of 9 units in that sample certified, and those three were PyInstaller's own bootstrap plus a bundled stdlib module. Extraction and representation work (1,510/1,510 code objects recovered); end-to-end decompilation of real malware logic is not demonstrated.
That entry point was both 3.13 and 491 representation lines, so size and version are confounded in it and it is evidence for neither on its own. It is reported because you should know the result, not because it diagnoses anything. The benign in-version curve in Β§4 is the instrument, and it already shows the model failing at that size on clean 3.12 input.
Annotated functions are handicapped: the training corpus was compiled with PEP-563 stringised annotations inherited, real
.pycfiles are not, and the benchmarks deliberately do not hand the model its training-time distribution back.
The oracle's limits, where you will meet them
Full detail in ORACLE-LIMITS.md.
0.33% false-reject floor on foreign
.pyc. On 600 wild install-time.pyc, 598 certify; 2 do not, because CPython 3.12.3 and 3.12.13 generate different code for the same source. No normalisation fixes that without abandoning the byte-identical guarantee. It fails to a false reject β you are told "unknown" about a correct answer, never "verified" about a wrong one.Optimization level must match the producer's. A
.pycbuilt with-Ois a different code object. The wrong level does not degrade gracefully, it collapses to ~24%. Try all three; it costs three compiles. But note that atoptimize>=1docstrings are absent from the.pyc, so docstring recovery becomes unprovable against such a file β a limit of the artifact, not of the oracle.The 100% pre-flight the harness prints proves nothing about soundness. It grades each reference against itself, i.e. compares
compile(x)withcompile(x), so any deterministic function of the source scores 100% β including a stub that ignores the bytecode entirely. It detects a broken harness and nothing more. The soundness evidence is the mutation test (0 true survivors in 1,239 mutants) and 18 targeted blind-spot probes (18/18).Formatting the AST does not capture can still change the bytecode, so byte-exact certification has a ceiling on some code. CPython 3.12 inlines comprehensions (PEP 709) and emits a cleanup entry in the exception table for the inlined scope. How the comprehension is line-wrapped changes that entry. Two source texts with an identical AST, identical
ast.unparseoutput and identical behaviour therefore compile to different code objects:def f(xs): return sum([1 for a in range(len(xs)) for b in range(a, len(xs)) if xs[b] == a]) def f(xs): return sum([1 for a in range(len(xs)) for b in range(a, len( # same AST, xs)) if xs[b] == a]) # different bytecodeMeasured on this interpreter: over 516 standard-library modules, rewriting each through
ast.unparse(ast.parse(src))β a formatting-only change β preserves the compiled fingerprint for 416, 80.62%. Roughly one wild module in five compiles differently after a rewrite that changes no code. (Byte-identical text round-trip is 0.6%, as expected, sinceunparsenormalises formatting by design. 80.62% is the figure that matters, because certification compares code objects, not text.)On the published benchmarks, an AST-identical re-wrap changes the fingerprint for 26 of 600 rows of
csn-3.12-licensed(4.33%) and 20 of 383 rows of the MBPP set (5.22%). 12.8% and 19.1% of their rows contain a comprehension at all.This is a property of byte-exact certification, not of this model, and it applies to every system scored this way β including PyLingual in Β§5. A decompiler that recovers correct source but wraps it differently is recorded as failing on those inputs. It fails safe: the verdict is "not proven", never "verified" for a wrong answer.
It costs the numbers in this file nothing measurable. Both benchmarks' reference text is
ast.unparseoutput and the model reproduces that canonical single-line form, so of the 94 greedy failures oncsn-3.12-licensed, 0 have an AST identical to the reference. The ceiling limits what certification can prove about differently-formatted source; it does not inflate or deflate the reported scores.Two consequences worth stating plainly. First, both published benchmarks are internally self-consistent: the reference source and the
.pycare compiled from the same normalised string β verified 600/600 and 383/383 β which is what makes the oracle sound. Second, that normalised string is not the upstream text. For the MBPP set, 1 of 383 rows (src/00117.py, MBPPtask_id757) compiles to different bytecode than the original MBPP solution, because that solution wraps a nested comprehension across lines. The row remains a valid decompilation task and its rewrite is declared in the dataset'sprovenance.transformandNOTICES.md; it is recorded here rather than quietly re-derived.Untested: cross-minor 3.13, Nuitka, non-CPython builds, obfuscated bytecode.
7. Reproduce every number
No model, no GPU, no network, no third-party decompiler β CPython 3.12 standard library only:
cd harness
python3 grade.py --bench ../benchmarks/csn-3.12-licensed/bench.jsonl --self-test-only --out /tmp/st.json
python3 analyze_scores.py --bench ../benchmarks/csn-3.12-licensed/bench.jsonl \
--greedy ../generations/gen_v3_csn600.jsonl \
--base ../generations/gen_base_csn600.jsonl \
--out /tmp/scores.json --rows-out /tmp/rows.jsonl
python3 size_curve.py --bench ../benchmarks/csn-3.12-licensed/bench.jsonl \
--greedy ../generations/gen_v3_csn600.jsonl \
--base ../generations/gen_base_csn600.jsonl \
--out /tmp/size_curve.json
Per-row verdicts for all 600 rows β repo, function, commit SHA, SPDX, tuned verdict, base verdict
β land in rows.jsonl. Every aggregate in Β§2 and Β§4 is recomputable from that file.
The figures in Β§5 are the exception: they were produced on the unpublished earlier benchmark pair and against a GPL-3.0 third-party decompiler we do not vendor, so they cannot be re-run from what ships here.
8. Training
| Base | Qwen/Qwen2.5-Coder-1.5B-Instruct (Apache-2.0) |
| Method | LoRA r=16, Ξ±=32, all attention + MLP projections, 1 epoch, lr 2e-4, merged into the base |
| Rows | 48,196 pairs of Python 3.12 disassembly β source |
| Corpus | codeparrot/github-code-clean, per-row filtered to 7 permissive licences; all GPL/LGPL/AGPL/MPL/EPL dropped before extraction |
| Decontamination | shard-disjoint, repo-disjoint, and identifier-blind fingerprint-disjoint |
The training corpus is not distributed. Per-row attribution was not retained during
extraction, so the corpus cannot be redistributed without dropping required MIT/BSD/Apache
notices. That is a property of the artifact, not of the licences β nothing in it is unlicensed or
reciprocally licensed. Full lineage, including what was dropped and why:
DATA-CARD-training-corpus.md.