ABTdomain/dksplit-qwen-lora
DKSplit Qwen 3.5 9B LoRA r128: Domain Name Segmentation
LoRA adapter fine-tuned on Qwen 3.5 9B for domain name segmentation (splitting concatenated strings into words).
This is the research and evaluation companion to DKSplit, the production BiLSTM-CRF segmenter. The LLM is used as a teacher model for labeling and cross-validation, not as the production runtime.
Performance
5,000-sample benchmark (primary)
1,000-sample benchmark
Strict EM counts only exact matches against truth. Lenient EM also accepts the might_right alternative for genuinely ambiguous cases.
The BiLSTM-CRF outperforms this LLM on both benchmarks while being ~1000x cheaper to run (9 MB, CPU-only, ~800 samples/s single-thread).
Character mutation rate (100K real domains)
Mutation = output characters differ from input after removing spaces. Training reduces character hallucination by 22x.
Cross-prompt robustness (5,000-sample, Lenient EM)
After training, prompt choice has negligible impact on output (<1pp difference). Behavior is baked into the weights.
Usage
from transformers import AutoTokenizer, AutoModelForCausalLM
from peft import PeftModel
import torch
# Load base model + adapter
base_model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3.5-9B",
torch_dtype=torch.bfloat16,
device_map="auto",
trust_remote_code=True,
)
model = PeftModel.from_pretrained(base_model, "ABTdomain/dksplit-qwen-lora")
model.eval()
tokenizer = AutoTokenizer.from_pretrained("ABTdomain/dksplit-qwen-lora", trust_remote_code=True)
# Inference
system = "You are a domain name segmentation tool. Given a concatenated string that might be in any language, split it into separate words in the most accurate way. Do not add or remove any characters. Output ONLY the segmented result, nothing else."
messages = [
{"role": "system", "content": system},
{"role": "user", "content": "chatgptlogin"},
]
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True, enable_thinking=False)
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
with torch.no_grad():
output = model.generate(**inputs, max_new_tokens=64, do_sample=False)
result = tokenizer.decode(output[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True)
print(result.strip())
# chatgpt loginExamples
Training Details
Key Findings
- Parameter capacity matters: LoRA r64 (116M trainable) saturates at 82.1%; r128 (300M trainable) reaches 88.82%
- Training bakes behavior into weights: swapping the inference prompt after SFT does not change output
- Training eliminates character hallucination: mutation rate drops from 5.62% to 0.25%
- Full fine-tune is not worth it: 4xA100 yields only 8 samples/s for full FT (ETA 40 days); LoRA r128 is sufficient
- The BiLSTM-CRF is still better for production: 9 MB, CPU-only, faster, and higher accuracy
When to Use This Model
- Cross-validating BiLSTM-CRF labels during benchmark construction
- Research into LLM segmentation behavior on novel domains
- Offline batch evaluation where latency is not a constraint
- Generating alternative segmentations for ambiguous inputs
For production use, install the BiLSTM-CRF:
pip install dksplitAdapter Files
Links
- Read more about DKSplit: DKSplit on EuroHPC
- DKSplit (production model): huggingface.co/ABTdomain/dksplit
- DKSplit (Python): pypi.org/project/dksplit
- GitHub: github.com/ABTdomain/dksplit
- Benchmark: huggingface.co/datasets/ABTdomain/dksplit-benchmark
- Blog: DKSplit on EuroHPC
- Website: ABTdomain.com, DomainKits.com
Acknowledgements
Trained on the Leonardo Booster supercomputer at CINECA, Italy, with computing resources provided by the EuroHPC Joint Undertaking through the Playground Access program (EHPC-AIF-2026PG01-281). We thank EuroHPC JU for enabling SMEs to explore new possibilities with world-class HPC infrastructure.
License
CC BY 4.0. Attribution required: credit "DKSplit by ABTdomain" in your README, documentation, about page, or API response metadata.
