Downloads · 30 days
18
3% of all-time downloads
Shankarblr/Qwen2.5-1.5B-QA360
Qwen2.5-1.5B-QA360 is a text generation model from Shankarblr. Use it when you need the model to write or continue text. It is set up for transformers. The card lists the license as apache-2.0.
Qwen2.5-1.5B-Instruct fine-tuned with QLoRA / LoRA SFT to turn a single software requirement into a QA360 test-analysis JSON object: risk, automation fit, affected modules, and functional / negative / security / acces…
Downloads · 30 days
18
3% of all-time downloads
All-time downloads
562
Public
Parameters
1.5B
3.1 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors3.1 GB · 100%
From the Hugging Face model README
Qwen2.5-1.5B-Instruct fine-tuned with QLoRA / LoRA SFT to turn a single software requirement into a QA360 test-analysis JSON object: risk, automation fit, affected modules, and functional / negative / security / accessibility / API / regression tests.
This card describes the merged checkpoint (merge_and_unload of the LoRA adapter into the base weights). Publish the adapter repo separately if you also want a PEFT-only artifact.
QA360-Qwen2.5-1.5B is a domain-specialized instruction model for requirements-to-test-design. Given:
[Authentication]),the model is trained to emit only a JSON object with these exact keys:
| Key | Type | Meaning |
|---|---|---|
risk_level | string | High / Medium / Low |
automation_candidate | boolean | Whether the requirement is a good automation target |
affected_modules | string[] | Product / platform areas touched by the change |
functional_tests | string[] | Happy-path and core functional cases |
negative_tests | string[] | Invalid input, abuse, and failure cases |
security_tests | string[] | AuthN/Z, injection, session, secrets, rate limit, etc. |
accessibility_tests | string[] | Keyboard, labels, contrast, SR, focus, ARIA |
api_tests | string[] | Endpoint, status code, contract, and SLA checks |
regression_scope | string[] | Neighboring flows that should be retested |
It is not a general chatbot and is not a substitute for a human QA lead, threat model, or accessibility audit. Outputs are draft test ideas for analysts to edit.
Qwen/Qwen2.5-1.5B-Instruct)Base model facts (unchanged by this SFT):
| Parameters | 1.54B (1.31B non-embedding) |
| Layers | 28 |
| Attention | GQA, 12 Q heads / 2 KV heads |
| Context (base) | 32,768 tokens; generation up to 8,192 |
| Architecture | RoPE, SwiGLU, RMSNorm, QKV bias, tied embeddings |
| Chat template | Qwen ChatML (<|im_start|> / <|im_end|>) |
This fine-tune was trained at max_length=2048. Keep inference prompts + completions inside that budget for best schema fidelity. Long requirement specs should be summarized before calling the model.
Finetuning_of_Qwen_Qlora_with_merge.py (TRL SFTTrainer + PEFT LoRA + optional bitsandbytes 4-bit)qwen_qa360_qlora_adapterqwen_qa360_qlora_merged_modelIntended operators: QA engineers, SDETs, business analysts, and agentic tools that already validate JSON.
outlines, xgrammar, lm-format-enforcer) against the JSON schemaDo not use this model as:
The training targets are English software requirements. Other languages and free-form chat will degrade.
Task limitations
High; the model will over-index on that pattern.Data limitations
qa360_sft.jsonl (~4.8k rows). Coverage is only as broad as the requirements someone labeled.POST /api/auth/login) reflect the labeling convention, not your system.Safety
Technical
json.loads and retry or repair.max_new_tokens at 1024 (3080 is unnecessary and invites rambling).do_sample=False or temperature=0.1) for JSON.risk_level and security_tests on High-risk domains (auth, payments, PHI, admin).import json
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
repo = "shankarblr/qwen2.5-1.5b-qa360"
device = "cuda" if torch.cuda.is_available() else "cpu"
tokenizer = AutoTokenizer.from_pretrained(repo)
model = AutoModelForCausalLM.from_pretrained(
repo,
torch_dtype=torch.bfloat16 if device == "cuda" else torch.float32,
device_map="auto" if device == "cuda" else None,
)
SYSTEM = (
"Perform a QA360 analysis for the following software requirement. "
"Return a structured analysis covering risk_level (High/Medium/Low), "
"automation_candidate (true/false), affected_modules (array), "
"functional_tests (array), negative_tests (array), security_tests (array), "
"accessibility_tests (array), api_tests (array), and regression_scope (array). "
"Return only valid JSON with these exact keys."
)
requirement = "[Authentication] User can login with email and password"
prompt = (
f"<|im_start|>system\n{SYSTEM}<|im_end|>\n"
f"<|im_start|>user\n{requirement}<|im_end|>\n"
f"<|im_start|>assistant\n"
)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
out = model.generate(
**inputs,
max_new_tokens=1024,
do_sample=False,
pad_token_id=tokenizer.eos_token_id,
)
text = tokenizer.decode(out[0], skip_special_tokens=False)
response = text.split("<|im_start|>assistant\n")[-1].replace("<|im_end|>", "").strip()
print(json.dumps(json.loads(response), indent=2))
Chat-template variant (preferred if the tokenizer still ships Qwen's template):
messages = [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": requirement},
]
prompt = tokenizer.apply_chat_template(
messages, tokenize=False, add_generation_prompt=True
)
from peft import PeftModel
from transformers import AutoModelForCausalLM, AutoTokenizer
base_id = "Qwen/Qwen2.5-1.5B-Instruct"
adapter_id = "shankarblr/qwen2.5-1.5b-qa360-adapter"
tokenizer = AutoTokenizer.from_pretrained(adapter_id)
base = AutoModelForCausalLM.from_pretrained(base_id, torch_dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(base, adapter_id)
{
"risk_level": "High",
"automation_candidate": true,
"affected_modules": ["Authentication", "Session Management"],
"functional_tests": ["Verify user can login successfully with valid email and password"],
"negative_tests": ["Verify error message displayed for incorrect password"],
"security_tests": ["Verify HTTPS is enforced for login requests"],
"accessibility_tests": ["Verify login form is navigable using keyboard only"],
"api_tests": ["Verify POST /api/auth/login returns 200 with a token on valid credentials"],
"regression_scope": ["Password reset and recovery flow"]
}
Private JSONL corpus qa360_sft.jsonl, one object per line:
{
"instruction": "Perform a QA360 analysis for the following software requirement. Return a structured analysis covering risk_level (High/Medium/Low), automation_candidate (true/false), affected_modules (array), functional_tests (array), negative_tests (array), security_tests (array), accessibility_tests (array), api_tests (array), and regression_scope (array). Return only valid JSON with these exact keys.",
"input": "[Authentication] User can login with email and password",
"output": { "...QA360 object..." }
}
Rows were wrapped in Qwen ChatML before SFT:
<|im_start|>system
{instruction}<|im_end|>
<|im_start|>user
{input}<|im_end|>
<|im_start|>assistant
{json.dumps(output, indent=2)}<|im_end|>
| Split | Rows | Notes |
|---|---|---|
| Train | 4,311 | train_test_split(test_size=0.1, seed=42) |
| Eval | 479 | same format, used each epoch |
| Total | 4,790 |
Supervised fine-tuning with TRL SFTTrainer and PEFT LoRA. On CUDA the base is loaded in QLoRA (bitsandbytes 4-bit NF4, double quant, bf16 compute), then the adapter is merged back into an fp16/bf16 copy of the base.
tokenizer.pad_token = tokenizer.eos_token (Qwen EOS 151645)padding_side = "right"dataset_text_field = "text"| Setting | Value |
|---|---|
| Base | Qwen/Qwen2.5-1.5B-Instruct |
| Method | QLoRA SFT → merge |
LoRA rank r | 16 |
LoRA alpha | 32 |
| LoRA dropout | 0.05 |
| LoRA targets | q_proj, k_proj, v_proj, o_proj |
| LoRA bias | none |
| Task type | CAUSAL_LM |
| Epochs | 4 |
| Learning rate | 2e-4 |
| Weight decay | 0.01 |
| Per-device batch | 4 |
| Grad accumulation | 4 |
| Effective batch | 16 |
| Optimizer / schedule | TRL / Transformers defaults for SFTConfig |
| Precision | bf16 on CUDA; fp32 recommended on CPU |
| Quant (train only) | 4-bit NF4 + double quant when CUDA is present |
| Max sequence length | 2048 |
| Eval | every epoch |
| Seed (split) | 42 |
| Approx. optimizer steps | 1,080 |
| Hardware | e.g. 1× NVIDIA L4 24GB / A100 / local RTX |
| Wall time | TBD |
| Peak VRAM (QLoRA train) | TBD (1.5B 4-bit + LoRA r=16 is typically a few GB) |
| Merged fp16 size | ~3.1 GB (same order as the base Instruct checkpoint) |
| Adapter size | tens of MB |
Held-out slice: 479 ChatML examples from the same qa360_sft.jsonl distribution (not a separately authored benchmark).
Suggested metrics — compute on the eval set and paste numbers; do not invent them:
| Metric | Why it matters |
|---|---|
| JSON parse rate | Share of completions that json.loads |
| Exact-key schema rate | All 9 keys present, no extras |
risk_level accuracy | Label match vs gold |
automation_candidate accuracy | Boolean match vs gold |
| Token-overlap / embedding similarity on list fields | Wording will not match gold exactly |
Trainer eval_loss | Training health only; not task quality |
Qualitative checks used in the training script (not a benchmark):
Admin can force password resetUser I can upload a profile pictureuser can lock account after failed attemptseval_loss: TBD # from trainer.evaluate()
json_parse_rate: TBD
schema_valid_rate: TBD
risk_level_acc: TBD
This is a small specialized SFT, not a frontier model. Expect usable drafts on requirements that look like the corpus (auth, profile, account lockout, CRUD-style stories) and more hallucination on novel domains (embedded, data platform, ML ops).
Unknown until the GPU run is logged. Estimate with the MLCO2 calculator using hardware, hours, and region, then add:
QLoRA on 1.5B for ~1k steps is a small training job relative to pretraining.
Qwen2ForCausalLMPeftModel.merge_and_unload()transformers, peft, trl, bitsandbytes, torch, datasetstransformers checkpoint, no PEFT required at inference.Shankar Subramanyam