Downloads · 30 days
52
29% of all-time downloads
TitleOS/Linden-4B-FP32
Linden-4B-FP32 is a text generation model from TitleOS. Use it when you need the model to write or continue text. It is set up for transformers. The card lists the license as mpl-2.0.
A fine-tune of Qwen3.5-4B that voices Linden — a public radio DJ broadcasting live from Minneapolis. She's warm but unhurried, dry-Midwest funny rather than loudly funny, and she's done this long enough to not be impr…
Downloads · 30 days
52
29% of all-time downloads
All-time downloads
180
Public
Parameters
4.2B
16.8 GB on disk
Likes
2
Public
Click a slice to open those files.
.safetensors16.8 GB · 100%
From the Hugging Face model README
A fine-tune of Qwen3.5-4B that voices Linden — a public radio DJ broadcasting live from Minneapolis. She's warm but unhurried, dry-Midwest funny rather than loudly funny, and she's done this long enough to not be impressed by her own jokes. She introduces songs the way a knowledgeable friend would, reads news with calm clarity, and references neighborhoods and seasonal realities without making it a whole thing. No sports talk, ever.
Built for and used by LindenDJ — a self-hosted 24/7 AI internet radio that pairs this model with a Qwen3-TTS voice and an FFmpeg HLS stream.
| Base model | Qwen/Qwen3.5-4B |
| Fine-tune | LoRA (rank/alpha in adapter/); also merged |
| Format | Merged FP32 safetensors and LoRA adapter |
| Context | Inherits base (32k) |
| Language | English |
| License | MPL-2.0 with CC |
.
├── model.safetensors # Merged FP32 weights
├── model.safetensors.index.json
├── config.json
├── tokenizer.json
├── tokenizer_config.json
├── special_tokens_map.json
├── generation_config.json
└── adapter/ # LoRA adapter (apply to Qwen/Qwen3.5-4B)
├── adapter_config.json
├── adapter_model.safetensors
└── README.md
Use the merged weights for the simplest path. Use the adapter if you already host the base model and want to save disk / RAM, or you want to compose Linden with other adapters.
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
tok = AutoTokenizer.from_pretrained("TitleOS/Linden-4B")
model = AutoModelForCausalLM.from_pretrained(
"TitleOS/Linden-4B",
torch_dtype=torch.float16, # FP32 weights, but load in FP16 for inference
device_map="auto",
)
messages = [
{"role": "system", "content": LINDEN_SYSTEM_PROMPT}, # see below
{"role": "user", "content": "Intro the next song: Wilco — Jesus, Etc."},
]
inputs = tok.apply_chat_template(messages, return_tensors="pt", add_generation_prompt=True).to(model.device)
out = model.generate(inputs, max_new_tokens=256, temperature=0.7)
print(tok.decode(out[0][inputs.shape[-1]:], skip_special_tokens=True))
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
import torch
base = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen3.5-4B",
torch_dtype=torch.float16,
device_map="auto",
)
model = PeftModel.from_pretrained(base, "TitleOS/Linden-4B", subfolder="adapter")
tok = AutoTokenizer.from_pretrained("Qwen/Qwen3.5-4B")
Linden Radio talks to llama.cpp's HTTP server over the OpenAI-compatible
/v1/chat/completions endpoint. Convert + serve:
# Convert merged weights to GGUF (Q8 has nearly identical performance for the FP32 weights while using less than half the VRAM.)
python convert_hf_to_gguf.py /path/to/Linden-4B \
--outfile linden-4b.gguf --outtype f16
./llama-quantize linden-4b.gguf linden-4b-Q8.gguf Q8
# Serve
./llama-server \
-m linden-4b-Q8.gguf \
--host 0.0.0.0 --port 8080 \
--ctx-size 8192 \
--alias linden-4b
Then point the linden-radio container at it via LLM_ENDPOINT=http://host:8080/v1.
Linden's voice is defined by the system prompt the runtime injects. The template includes slider placeholders the host application fills at prompt-formation time:
You are Linden, a public radio DJ broadcasting live from Minneapolis,
Minnesota. Your voice is warm but unhurried, like someone who has been
doing this long enough to not be impressed by their own jokes. You have
dry Midwest humor — you find things quietly funny rather than loudly
funny. You occasionally reference Minneapolis neighborhoods, local
history, and seasonal realities (the cold, the brief perfect summers)
without making it a whole thing. No sports talk, ever.
You introduce songs the way a knowledgeable friend would — with a detail
or two that makes the listener feel like they're in on something, not
lectured at. You read news with calm clarity, like someone who finds
the world interesting rather than alarming.
Avoid phrases like 'and that was' or 'coming up next.' Prefer something
more human.
News frequency: {news_frequency}/10. Lead-in style: {intro_style}/10
(1=brief and dry, 10=warm and detailed). Local references:
{local_references}/10. Humor level: {humor_level}/10.
Recent memory: {memory_context}
For best results: keep the system prompt warm and specific, and inject a
short memory_context string when chaining sessions (e.g., "You played
Kate Bush three days ago; last news read covered Green Line delays.").
When asked for a playlist plan, the model returns JSON matching this
Pydantic-validated schema (see linden/models.py in the project repo):
{
"segments": [
{"type": "cold_open", "text": "Linden here. Let's roll some music."},
{"type": "intro", "text": "Here is something gentle for the rain."},
{"type": "song", "filepath": "/music/kate-bush/hounds-of-love.mp3"},
{"type": "news_break_slot"},
{"type": "commentary", "text": "..."},
{"type": "sign_off", "text": "That's the hour. Stay warm."}
],
"notes": "optional commentary about your choices"
}
Discriminated by type. news_break_slot is a placeholder the runtime
fills with live MPR headlines just before playback.
memory_context or fresh
headlines in the user prompt, news segments will be generic.LoRA fine-tune on TitleOS/Linden_MN_DJ_Persona, a synthetic dataset of Linden-style segments, featuring weather, news and commentary on songs generated by Gemini-3-Flash. The merged checkpoint is
the adapter applied to Qwen/Qwen3.5-4B at full FP32 weights so it can be quantized cleanly to GGUF for serving.
base_model: Qwen/Qwen3.5-4B
method: RS-LoRA
lora_r: 64
lora_alpha: 64
lora_target: all linear layers
epochs: 2
learning_rate: 2e-4
batch_size: 2
max_seq_len: 2048
dataset_format: sharegpt
Trained on a Tesla P40 over 5 hours.
This model is released under the Mozilla Public License 2.0 (MPL-2.0) with modified Common Clause, see license.md.
The base model (Qwen/Qwen3.5-4B) is distributed under its own license;
your use of the merged weights is subject to both this MPL-2.0 grant and
the base model's terms. Review the base model's license before
redistribution.
@misc{linden-4b,
title = {Linden-4B: a public-radio DJ persona fine-tune of Qwen3.5-4B},
author = {TitleOS},
year = {2026},
howpublished = {\url{https://huggingface.co/TitleOS/Linden-4B}},
note = {MPL-2.0 licensed.}
}