License notice This project is source-available under the PolyForm Noncommercial License 1.0.0 — free for personal, research, teaching, and internal-evaluation use.
Any commercial use, redistribution as part of a commercial product, or paid hosted deployment requires a separate commercial license. See COMMERCIAL.md or contact https://github.com/AnubhabBanerjee.
Unauthorized commercial use or redistribution is a violation of the license terms.
Qwen is not covered by the license above. The checkpoint this tutorial loads, Qwen2.5-Coder-1.5B-Instruct, is released by the Qwen team under the Apache License 2.0. That Apache 2.0 license is the license that applies to the Qwen model weights. See the Qwen license file.
A small classification head on an open Qwen model. It does not write a paragraph.
It reads a Python function once and returns match or mismatch, plus a confidence.
This is the companion repo for a beginner tutorial. The new head is a few thousand numbers. The Qwen backbone stays frozen. Training the head takes a few minutes on one GPU.
add can multiply, and the file is still valid Python. An editor can see an
unused note. It has no check for a name that does not mean what the body does.
check_names.py only reads functions written at the top of the file. A method
on a class, or a function nested inside another function, is left alone.
A chatbot guesses the next word until a sentence exists, and then you have to find the decision inside it. This model keeps Qwen's understanding and throws away the word-guessing head. One pass. One label.
Requires Python 3.10+.
pip install -r requirements.txt
python train.py # freeze Qwen, train the new head
python check_names.py sample_module.py
python quantize.py # optional: pack the backbone to int8 on CPURun train.py before check_names.py. The checker reads artifacts/jev_head.pt.
That file does not exist until training finishes.
The first run downloads Qwen/Qwen2.5-Coder-1.5B-Instruct into the normal
Hugging Face cache on your machine. If your weights already live in a folder of
your own, set CACHE_DIR at the top of model.py to that folder. Leave it as
None to use the default cache.
check_names.py exits with status 1 when at least one top-level name does not
agree with its body. Status 0 means every top-level function was a match.
sample_module.py is expected to exit 1. Ten of its twenty-seven functions are
flagged.
| File | What it does |
|---|---|
model.py |
Loads the Qwen backbone and attaches the two-score head |
train.py |
Trains only that head on data/names.csv |
check_names.py |
Scores the top-level functions in a Python file |
quantize.py |
Packs the backbone's linear layers to int8 and prints the size |
sample_module.py |
The demo file, with honest names and dishonest ones |
data/names.csv |
Labeled functions. The same name appears with both a right body and a wrong one |
train.py prints how many numbers were allowed to move. Expect a few thousand
trainable parameters, against the billion-plus in Qwen that stayed frozen.
check_names.py sample_module.py flags 10 of 27 functions. add, is_even,
and maximum are mismatches. rectangle_area is a match, even though it
contains an unused note an editor will complain about.
quantize.py prints the backbone size before and after packing. On a CPU
float32 copy, one run went from 6.17 GB to 0.93 GB, and add still came back
mismatch. Name checking in this repo still uses the ordinary backbone, so
the table above stays easy to reproduce.
