DEV Community

shakti tiwari
shakti tiwari

Posted on • Originally published at optiontradingwithai.in

How to Tune Your Local AI Model for a Customized Experience (No API Key)

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:

  1. Privacy. Your prompts never leave the machine. For trading notes, medical drafts, or client data, that matters.
  2. 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.
  3. 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Build and run it:

ollama create my-assistant -f Modelfile
ollama run my-assistant
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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}"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. Install Ollama in Termux: pkg install ollama, then ollama serve.
  2. Pull a 4B GGUF-based model (e.g. ollama pull qwen3.5:4b or import a GGUF via Modelfile FROM ./model.gguf).
  3. 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|>"
Enter fullscreen mode Exit fullscreen mode

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_penalty to 1.15–1.2 or lower temperature.
  • Replies feel dumb after quant → you used Q2_K/IQ2. Re-quant with imatrix at Q4_K_M.
  • Context gets cut mid-doc → your num_ctx is too small; bump to 8192 or 16384 (needs more RAM).
  • Ollama "could not connect to server"ollama serve isn'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 SYSTEM prompt 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

  1. Start with the Modelfile — 90% of "customize experience" is SYSTEM + temperature, zero retraining.
  2. Use imatrix quants at Q4_K_M for 4B models; don't fall for Q2_K size savings.
  3. RAG before QLoRA unless you have 200+ clean training rows.
  4. Abliterate only if refusals actually block your work — and accept the quality trade-off.
  5. 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)