Views
No views yet
1from peft import PeftModel
2from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
3import torch
4
5MODEL_ID = "Qwen/Qwen3-4B"
6ADAPTER_ID = "AbijahKaj/qwen3-4b-kicad-netlist"
7
8bnb_config = BitsAndBytesConfig(
9 load_in_4bit=True, bnb_4bit_quant_type="nf4", bnb_4bit_compute_dtype=torch.bfloat16,
10)
11
12base_model = AutoModelForCausalLM.from_pretrained(MODEL_ID, quantization_config=bnb_config, device_map="auto")
13model = PeftModel.from_pretrained(base_model, ADAPTER_ID)
14tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
15
16messages = [
17 {"role": "system", "content": "You are an expert electronics engineer and KiCad schematic designer. When given a description of an electronic circuit or system, you generate a complete, valid KiCad netlist in s-expression format."},
18 {"role": "user", "content": "Design an RP2040-based flight controller with ICM-42688-P IMU on SPI, BMP388 barometer on I2C, 4 PWM motor outputs, USB-C, QSPI flash, and SWD debug header."}
19]
20
21text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True, enable_thinking=False)
22inputs = tokenizer(text, return_tensors="pt").to(model.device)
23
24with torch.no_grad():
25 outputs = model.generate(**inputs, max_new_tokens=8192, temperature=0.3, top_p=0.9, do_sample=True)
26
27netlist = tokenizer.decode(outputs[0][inputs['input_ids'].shape[-1]:], skip_special_tokens=True)
28print(netlist)| Circuit Type | Key Components |
|---|---|
| Flight Controller | RP2040, ICM-42688-P IMU, BMP388 baro, PWM outputs |
| IoT Sensor Node | STM32F411, BME280, SX1276 LoRa, OLED |
| WiFi/CAN Gateway | ESP32-S3, MCP2515, TJA1050, SD card, ADS1115 |
| Arduino Clone | ATmega328P, CH340G USB-UART, 16MHz crystal |
| Battery Sensor | ATtiny85, nRF24L01+, BME280, MCP73831 charger |
| USB Power Meter | ATmega328P, INA219, OLED display |
| Motor Driver | RP2040, DRV8833, reverse polarity protection |
| GPS Tracker | ESP32-S3, u-blox MAX-M8, SD card, LiPo charger |
| Thermocouple Reader | ATmega328P, MAX31855, OLED |
| Data Logger | RP2040, ADS1115 ADC, SD card, OLED |
| CM4 Carrier Board | Dual Hirose DF40HC, USB 2.0, HDMI, SD, GPIO |
| CM5 Carrier Board | Dual Hirose DF40HC, PCIe NVMe, USB 3.0, Ethernet, Fan |
| CAN Bus Node | STM32F103, MCP2515, TJA1050, 120Ω termination |
| Simple circuits | LED drivers, voltage dividers, current sensors, buck converters |
(nets sections — converted from real .kicad_sch schematics from ~6,000 GitHub repos plus synthetic circuitssearch_component and get_datasheet_info tool callserc_validator.py (v2) validates generated netlists:| Check | What It Validates |
|---|---|
| Syntax | Balanced parentheses, valid s-expression structure |
| Structure | Has (export), (design), (components), (nets) sections |
| Components | Unique refs, values, footprints, libsource |
| Nets | Multi-node connectivity, no floating pins, pin-type compatibility |
| Net Quality | Multi-node ratio, average nodes/net, named net ratio |
| Power | GND net present, power supply net present |
| Decoupling | ICs on power nets have bypass capacitors |
| Connectivity | All components connected to at least one net |
1python erc_validator.py your_netlist.kicad_net
2python erc_validator.py your_dataset.jsonl| Parameter | Value |
|---|---|
| Method | QLoRA (4-bit NF4, double quant) + SFT |
| LoRA rank | r=64, α=32, all-linear targets |
| Effective batch | 8 (BS=1 × grad_accum=8) |
| Max seq length | 8,192 tokens |
| Learning rate | 2e-4 (cosine decay) |
| Epochs | 2 |
| Train loss | 0.1442 (avg), 0.112 (final) |
| Eval loss | 0.1251 |
| Token accuracy | 96.78% |
| ERC checks | Every 500 steps on 3 validation prompts |
| Best ERC | 0.613 (step 4000) |
| Final ERC | 0.433 |
| Parameter | Value |
|---|---|
| Method | QLoRA (4-bit NF4, double quant) + SFT |
| LoRA rank | r=64, α=32, all-linear targets |
| Effective batch | 8 (BS=1 × grad_accum=8) |
| Max seq length | 8,192 tokens |
| Epochs | 1 |
| Train loss | 0.125 |
| Eval loss | 0.141 |
| Token accuracy | 96.3% |
| File | Description |
|---|---|
adapter_model.safetensors | LoRA adapter weights (504 MB) |
adapter_config.json | PEFT adapter configuration |
train.py | Training script with inline ERC v2 |
erc_validator.py | ERC v2 — stricter net quality checks |
evaluate_model.py | Evaluation suite: 7 prompts, ERC scoring, A/B comparison |
chat_template.jinja | Qwen3 chat template |
erc_validator.py to check generated netlistsenable_thinking=False for direct netlist output