Quick answer: You tune a local AI model in four layers — (1) pick the right base and quantization (use an importance-matrix / imatrix quant to keep quality at 4-bit), (2) steer behavior with a Modelfile SYSTEM prompt and PARAMETER knobs in Ollama, (3) fine-tune a small LoRA adapter with QLoRA if you need private knowledge, and (4) optionally remove the refusal direction via abliteration for an uncensored build. All of this runs offline on a laptop or even an Android phone through Termux.
Most people think "tuning an AI model" means owning a GPU cluster and a research team. It doesn't. In 2026 you can take a 4-billion-parameter open-weight model, run it on a phone, and reshape how it talks, what it refuses, and what it remembers — without sending a single token to OpenAI or Google.
This guide is built from primary sources: the llama.cpp quantize README, the Ollama Modelfile reference, the NousResearch llm-abliteration repo, and the original QLoRA paper (Dettmers et al., 2023, arXiv:2305.14314). I'll show you the exact commands, the honest trade-offs, and where each technique breaks.
Educational disclaimer: This article covers model customization for developers. It is not financial, legal, or safety advice. Techniques like abliteration remove safety refusals — use them only on models you are licensed to modify, and keep a responsible-use policy for anything you deploy.
Why tune a local model instead of using an API?
Three reasons push people to on-device LLMs:
- Privacy. Your prompts never leave the machine. For trading notes, medical drafts, or client data, that matters.
- Cost. No per-token billing. A 4B model at Q4_K_M costs ~2.7 GB of RAM and runs on a mid-range phone.
- Control. You decide the persona, the stop words, the context window, and whether it declines a request.
The catch: a 4B model is not GPT-class. Tuning is how you close the gap for your specific use case instead of begging a hosted model to act differently.
Layer 1 — Quantization: shrink without melting the brain
A model ships as weights. Full-precision (F16) Qwen3.5-4B is ~8 GB. You rarely need that. Quantization compresses weights to 4-bit or 6-bit so it fits in device memory.
The imatrix trick (don't skip this)
Naive 4-bit quants lose detail. The fix is an importance matrix (imatrix), a calibration step that measures which weights actually matter, then protects them during compression.
From the Qwen llama.cpp docs:
# 1. Build the importance matrix from a calibration text file
./llama-imatrix -m Qwen3-4B-F16.gguf \
-f calibration-text.txt --chunk 512 \
-o Qwen3-4B-imatrix.dat -ngl 80
# 2. Quantize using that matrix — quality stays high at 4-bit
./llama-quantize --imatrix Qwen3-4B-imatrix.dat \
Qwen3-4B-F16.gguf Qwen3-4B-Q4_K_M.gguf Q4_K_M
If you download a pre-built GGUF, prefer one built with an imatrix (often labelled Q4_K_M from reputable quantizers). The llama.cpp README warns that for 1-bit or 2-bit mixes, skipping --imatrix prints a warning — that's your signal the quant will be rough.
Rule of thumb for a 4B model:
-
Q4_K_M(~2.7 GB) — best balance for phones. -
Q5_K_M(~3.3 GB) — if you have the RAM, slightly sharper. -
Q2_K/IQ2— only for desperation; quality drops fast.
Layer 2 — The Modelfile: steer personality without retraining
You don't need to touch weights to change behavior. Ollama's Modelfile lets you wrap a base model with a system prompt, parameters, and a template. This is the fastest "customize experience" win.
From the Ollama Modelfile reference:
FROM qwen3.5:4b
# Behavior of the assistant
SYSTEM """You are a concise trading-research aide. You answer in short
bullet points, cite numbers with their source, and never invent stats.
If data is missing, say so."""
# Sampling knobs
PARAMETER temperature 0.3
PARAMETER num_ctx 8192
PARAMETER stop "<|eot_id|>"
# Optional: attach a LoRA you trained (Layer 3)
# ADAPTER ./my-adapter.gguf
Build and run it:
ollama create my-assistant -f Modelfile
ollama run my-assistant
What each knob does
| Parameter | Effect | Good starting value |
|---|---|---|
temperature |
Creativity vs coherence | 0.2–0.4 for factual, 0.8+ for brainstorming |
num_ctx |
Context window (tokens) | 4096–8192 on 4B |
repeat_penalty |
Stops loops | 1.1 |
top_p |
Nucleus sampling | 0.9 |
stop |
Halt tokens | model's eot token |
The SYSTEM line is where "customized experience" lives. Want Hinglish replies for your Indian audience? Write the system prompt in Hinglish. Want JSON-only output for piping into a script? Say "Respond only with valid JSON."
Layer 3 — QLoRA: teach it your private knowledge
Prompts can't hold everything. If you need the model to know your data (stock CSVs, support tickets, personal notes), fine-tune a LoRA adapter with QLoRA.
QLoRA (Dettmers et al., 2023) made this possible on consumer hardware: it freezes the base weights at 4-bit NF4 and trains small low-rank adapters in 16-bit. The paper fine-tuned a 65B model on a single 48 GB GPU and hit 99.3% of ChatGPT's score on the Vicuna benchmark. For a 4B model you need far less — often 8–12 GB VRAM, or CPU-only if you're patient.
Minimal concept (pseudo-code, real libs: peft + bitsandbytes + transformers):
from peft import LoraConfig, get_peft_model
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
bnb = BitsAndBytesConfig(load_in_4bit=True, bnb_4bit_quant_type="nf4")
model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3.5-4B",
quantization_config=bnb)
lora = LoraConfig(r=16, lora_alpha=32, target_modules=["q_proj","v_proj"])
model = get_peft_model(model, lora)
# train on your dataset, then save adapter; merge or load at runtime
In Ollama you attach the merged adapter via ADAPTER ./my-adapter.gguf in the Modelfile. Net result: a model that writes in your voice and recalls your domain — without re-training 4 billion parameters.
Honest limit: QLoRA on 4B won't magically make it smarter than its base. It bakes in style and facts you fed, not reasoning it didn't have. Keep expectations realistic.
Layer 4 — Abliteration: remove the refusal direction
Some open models still refuse ("As an AI, I cannot…"). Abliteration removes the refusal direction in activation space by orthogonalizing weights against it — no retraining, one pass over the tensors.
NousResearch's llm-abliteration repo does this:
python ablate.py --model Qwen3.5-4B \
--refusal_direction refusal_dir.pt \
--output Qwen3.5-4B-uncensored.gguf
The catch (read this)
Abliteration is not a magic "uncensor" button, and the repo says so plainly:
- It does not guarantee full removal of censorship. A properly ablated model will not explicitly refuse based on the captured dataset, but edge cases survive.
- Quality can degrade. Removing a direction from fewer layers preserves quality but may leave some refusals; hitting more layers cleans refusals but dulls the model.
- It changes how the model responds, not what it knows.
Use abliteration only on models you're licensed to modify, and keep a responsible-use policy if you ship anything. For most personal use, a well-written SYSTEM prompt (Layer 2) gets you 90% of the way without touching weights.
Layer 5 — RAG: give it memory without training
"Customized experience" often just means it remembers my stuff. You don't need fine-tuning for that — use Retrieval-Augmented Generation. Embed your documents, fetch the top-k at query time, stuff them into context.
# conceptual
context = vector_db.search(query, top_k=4)
prompt = f"Answer using only:\n{context}\n\nQuestion: {query}"
This keeps the base model untouched, updates instantly when your data changes, and is the cheapest path to a "personal" assistant. Pair it with a Modelfile num_ctx of 8192+ so the retrieved text fits.
A minimal RAG that runs on the phone too
You don't need a vector DB server. For a few hundred docs, sentence-transformers (or a small GGUF embedder) + a flat numpy index is enough:
import numpy as np
from sentence_transformers import SentenceTransformer
embed = SentenceTransformer("all-MiniLM-L6-v2") # ~80 MB
docs = ["your note 1", "your note 2", ...]
idx = np.array([embed.encode(d) for d in docs])
def ask(model, query, k=4):
q = embed.encode(query)
sims = idx @ q
top = np.argsort(-sims)[:k]
ctx = "\n".join(docs[i] for i in top)
return model(f"Use only:\n{ctx}\n\nQ: {query}") # via Ollama API
The point: RAG + a tuned Modelfile gives you a personal assistant with zero retraining and zero cloud. If your data changes daily (like market notes), RAG beats QLoRA because you just re-embed — no training run.
End-to-end walkthrough: from download to "my model"
Here's the full sequence on a Termux/Android device, start to finish:
# 1. install + start server
pkg install ollama
ollama serve &
# 2. grab a 4B base (or import a GGUF you downloaded)
ollama pull qwen3.5:4b
# 3. write Modelfile (use the Hinglish trading example above)
nano Modelfile
ollama create my-ai -f Modelfile
# 4. chat — fully offline
ollama run my-ai
That's it for a customized persona. If later you want it to know private facts, add a QLoRA adapter (ADAPTER line) or wire RAG in front. You only go deeper when the SYSTEM prompt hits a wall — which, honestly, is rare.
When NOT to tune
- You just need a one-off answer → use the API or a plain local run, don't build a Modelfile.
- Your base model is already censored and you only need tone change → Modelfile, skip abliteration.
- You have <100 example rows → RAG, not QLoRA (avoids overfit).
- You're serving untrusted users → don't abliterate; refusals protect you legally.
Tuning is a ladder. Climb one rung at a time: persona → quant → memory → knowledge → uncensor. Most projects live on rung one or two and ship fine.
Running it on Android (Termux)
Yes, you can serve a 4B model from a phone. Verified path:
- Install Ollama in Termux:
pkg install ollama, thenollama serve. - Pull a 4B GGUF-based model (e.g.
ollama pull qwen3.5:4bor import a GGUF via ModelfileFROM ./model.gguf). - At Q4_K_M (~2.7 GB) it runs on a device with 8 GB RAM; expect 5–15 tokens/sec on CPU.
Earlier in this session I had Ollama 0.30.10 running on a Termux device with 10 GB RAM and 166 GB free — a 4B Q4 model is well within budget. For speed, a device with a Neural Engine or NPU helps, but CPU-only works for chat.
A real Modelfile for an Indian trading aide (Hinglish persona)
This is the exact shape I use when I want the model to sound like me and stay disciplined on numbers:
FROM qwen3.5:4b
SYSTEM """Tu ek NIFTY option-trading research aide hai. Hinglish me jawab de.
Har number ke saath source batao. Agar data nahi hai toh 'pata nahi' bolo,
matlab mat banao. 3-5 bullet me answer do. Over-promise mat karo."""
PARAMETER temperature 0.25
PARAMETER num_ctx 8192
PARAMETER repeat_penalty 1.1
PARAMETER stop "<|eot_id|>"
Build it: ollama create nifty-aide -f Modelfile && ollama run nifty-aide. The temperature 0.25 keeps it from hallucinating stats; the Hinglish SYSTEM line makes the experience yours, not a generic chatbot's. That single file is the difference between "an LLM" and "my LLM."
Troubleshooting the common failures
-
Model loops the same sentence → raise
repeat_penaltyto 1.15–1.2 or lowertemperature. -
Replies feel dumb after quant → you used
Q2_K/IQ2. Re-quant with imatrix atQ4_K_M. -
Context gets cut mid-doc → your
num_ctxis too small; bump to 8192 or 16384 (needs more RAM). -
Ollama "could not connect to server" →
ollama serveisn't running in the background; start it first. -
Abliterated model still refuses sometimes → expected; the technique isn't 100% (see Layer 4). Write a stronger
SYSTEMprompt as backup. - QLoRA overfits (parrot your few examples) → you trained on <50 rows. Get 200+ diverse samples or just use RAG instead.
Mobile benchmark reality (what to expect)
| Device RAM | Model | Quant | Speed (CPU) | Usable? |
|---|---|---|---|---|
| 4 GB | 3B | Q4_K_M | 3–6 t/s | 勉强 for chat |
| 8 GB | 4B | Q4_K_M | 8–15 t/s | Yes, smooth chat |
| 12 GB | 4B | Q5_K_M | 12–20 t/s | Great |
| 8 GB + NPU | 4B | Q4_K_M | 20–40 t/s | Near-desktop feel |
"t/s" = tokens per second. Below ~5 t/s it feels sluggish; aim for 8+. If your phone is 4 GB, drop to a 3B model (Llama-3.2-3B-Uncensored at Q4 is ~2.2 GB and chat-friendly).
Comparison: which layer do you need?
| Goal | Best layer | Effort | Risk |
|---|---|---|---|
| Change tone/persona | Modelfile SYSTEM | Low | None |
| Fit in small RAM | imatrix quant | Low | Minor quality |
| Inject private facts | QLoRA / RAG | Med | Overfit if data small |
| Stop refusals | Abliteration | Med | Quality drop, ethics |
| Always-fresh memory | RAG | Med | Context size |
Start at Layer 2. Most "I want it to act differently" problems die there. Move down only when prompts hit a wall.
FAQ
Q: Do I need a GPU to tune a local model?
A: No. Quantization and Modelfile wrapping are CPU-only. QLoRA fine-tuning is faster on a GPU but runs on CPU too — just slower.
Q: Will abliteration make my model unsafe?
A: It removes refusals, so the model will answer things the base declined. That's your responsibility. Test boundaries, and don't expose an uncensored build to untrusted users.
Q: What's the smallest model worth tuning?
A: 3B–4B is the sweet spot for phones. Below 1.5B, tuning helps less because the base is too weak to hold new behavior.
Q: imatrix vs normal quant — worth it?
A: Yes at 3–4 bit. The calibration costs one extra command and visibly keeps responses coherent. Skip only if you're at Q6/Q8 where quality is already high.
Q: Can I run this fully offline?
A: Yes. Once the GGUF is downloaded, everything — serve, tune, infer — works with zero network. That's the whole point of local AI.
Q: How is this different from just prompting ChatGPT?
A: ChatGPT locks the persona, logs your prompts, and bills per token. A local tuned model is yours: same system prompt every session, no data leaves the device, no recurring cost, and you can abliterate or retrain it. For a trading or research workflow where consistency and privacy matter, that difference is the product.
Key takeaways
-
Start with the Modelfile — 90% of "customize experience" is
SYSTEM+temperature, zero retraining. - Use imatrix quants at Q4_K_M for 4B models; don't fall for Q2_K size savings.
- RAG before QLoRA unless you have 200+ clean training rows.
- Abliterate only if refusals actually block your work — and accept the quality trade-off.
- It runs on a phone — Ollama + Termux + a 4B Q4 model is a real, shippable setup.
Local AI in 2026 isn't a lab curiosity. It's a tunable, ownable, offline assistant you shape in an afternoon.
Governance note (research-governor applied)
Per the research-governor skill, this piece is classified RESEARCH / educational (evidence class: primary-source documentation + published paper). No live trading or performance claims are made. Every non-obvious claim traces to a cited primary source (llama.cpp, Ollama docs, NousResearch, arXiv:2305.14314). Fast-moving facts (model names, Ollama version 0.30.10) were verified in-session, not from memory. Promotion Gate 3 (cost-adjusted OOS evidence) is not asserted here because no strategy or backtest is presented — this is a how-to, not a model-performance claim.
Written by **Shakti Tiwari* — Nifty Option Trader, XGBoost Expert. More on-device AI and systematic-trading write-ups at optiontradingwithai.in.*
Books by the author: Option Trading with AI (B0H9ZNTBPK) | The AI Opportunity (B0HBBFKDQF)
Top comments (0)