AbijahKaj/qwen3-4b-skidl
qwen3-4b-skidl
A fine-tune of Qwen/Qwen3-4B for generating executable SKiDL Python netlists from natural-language circuit descriptions. Given a description like "ESP32 board with BME280 on I2C and USB-C", the model outputs valid Python using Part(), Net(), and generate_netlist() — producing a .net file KiCad can open directly.
Blog post: Teaching a Small LLM to Design Electronic Circuits: Fine-Tuning Qwen3-4B on 100K KiCad Netlists
This repo has two branches:
Quick start
Merged (main branch — recommended)
from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained(
"AbijahKaj/qwen3-4b-skidl",
dtype="auto",
device_map="auto",
)
tokenizer = AutoTokenizer.from_pretrained("AbijahKaj/qwen3-4b-skidl")LoRA adapter (lora branch)
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
base = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3-4B", dtype="auto", device_map="auto")
tokenizer = AutoTokenizer.from_pretrained("AbijahKaj/qwen3-4b-skidl", revision="lora")
model = PeftModel.from_pretrained(base, "AbijahKaj/qwen3-4b-skidl", revision="lora")Generating a circuit
SYSTEM = (
"You are an expert electronics engineer and KiCad schematic designer. "
"When given a description of an electronic circuit, generate executable "
"SKiDL Python code that defines the circuit using the SKiDL library."
)
messages = [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": "Design a CAN bus interface using MCP2515 controller and TJA1050 transceiver on SPI, with 120 ohm termination resistor."},
]
text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
inputs = tokenizer(text, return_tensors="pt").to(model.device)
out = model.generate(**inputs, max_new_tokens=1024, do_sample=False)
print(tokenizer.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True))Training
Loss curve
SKiDL validation (final checkpoint)
Functional scoring across 5 held-out circuits: Python syntax + SKiDL import + net count + part count + connectivity + GND checks.
Why SKiDL?
KiCad's native s-expression netlist is deeply nested and pathological for LLMs. PCBSchemaGen (arXiv:2602.00510) shows SKiDL Python achieves 87% Pass@1 with GPT-4o on circuit generation — because Python-based HDLs align with LLM pretraining data and are 3× more compact than s-expressions.
Dataset
AbijahKaj/kicad-netlist-sft-dataset — 100,179 ChatML examples:
