Fine-tune a local open-weight LLM to imitate someone's Instagram DM texting style — 100% offline, no cloud APIs.
- Parses your Instagram DM export into a structured conversation timeline.
- Profiles the target sender's writing style (emoji habits, slang, sentence length, punctuation patterns).
- Builds a fine-tuning dataset of
(context → reply)pairs in Llama 3 chat format. - Fine-tunes Llama 3.1 8B Instruct with QLoRA (via Unsloth) on your local GPU.
- Exports the merged model to GGUF (Q4_K_M) and registers it in Ollama.
- Serves an interactive chat UI with Streamlit.
Everything runs locally after the initial model download. Your data never leaves your machine.
| Requirement | Notes |
|---|---|
| Python 3.10+ | |
| NVIDIA GPU | 8 GB+ VRAM recommended (tested on 12 GB) |
| CUDA 12.0+ | CUDA 13 for Blackwell/RTX 50xx |
| Ollama | For serving the final model |
git clone https://github.com/YOUR_USERNAME/LLM-Imitate.git
cd LLM-Imitate
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Linux / macOS
pip install -r requirements.txt
# Install PyTorch with CUDA support (adjust cu130 to your CUDA version)
pip install torch --index-url https://download.pytorch.org/whl/cu130
pip install unslothIn the Instagram app: Settings → Account → Your activity → Download your information. Select JSON format, then unzip and copy the thread folder into:
data/raw/inbox/<thread-name>/
message_1.json
message_2.json
...
cp config.yaml.example config.yamlEdit config.yaml:
| Key | Description |
|---|---|
thread_path |
Path to the thread folder inside data/raw/inbox/ |
target_sender |
Exact sender name to imitate (as it appears in the JSON export) |
my_sender |
Your name in the thread |
max_train_samples |
Set to a small number (e.g. 200) for a quick smoke test; null for full training |
# Step 1 — Parse the raw export
python parse_export.py
# Step 2 — Build a style profile for the target sender
python build_persona_profile.py
# Step 3 — Build the fine-tuning dataset (review pii_review.jsonl first!)
python build_dataset.py
# Step 4 — Fine-tune (smoke test: set max_train_samples: 200 in config.yaml first)
python train.py
# Step 5 — Export to GGUF and register with Ollama
python convert_to_gguf.py
ollama create persona-imitate -f Modelfile
# Step 6 — Launch the chat UI
streamlit run app.py
# Step 7 (optional) — Evaluate style fidelity
python evaluate.py| Step | Script | Output |
|---|---|---|
| 1 | parse_export.py |
data/processed/conversation.jsonl |
| 2 | build_persona_profile.py |
data/processed/persona_profile.json |
| 3 | build_dataset.py |
train.jsonl, val.jsonl, pii_review.jsonl |
| 4 | train.py |
LoRA adapter → models/adapters/final/ |
| 5 | convert_to_gguf.py |
Quantized GGUF → models/gguf/ |
| 6 | Ollama + Modelfile |
Local inference model persona-imitate |
| 7 | app.py |
Streamlit chat UI at http://localhost:8501 |
| 8 | evaluate.py |
Style-fidelity report |
LLM-Imitate/
├── config.yaml.example # Copy to config.yaml and fill in your details
├── data/
│ ├── raw/ # Instagram export — gitignored
│ └── processed/ # Generated artifacts — gitignored
├── models/
│ ├── adapters/ # LoRA checkpoints — gitignored
│ └── gguf/ # Merged + quantized weights — gitignored
├── parse_export.py
├── build_persona_profile.py
├── build_dataset.py
├── train.py
├── convert_to_gguf.py
├── Modelfile
├── app.py
├── evaluate.py
└── utils.py
- Smoke test first: Set
max_train_samples: 200andepochs: 1inconfig.yamlto verify the pipeline end-to-end in ~5 minutes before committing to a full run. - Full run: Set
max_train_samples: nullandepochs: 3. Expect ~1–3 hours depending on your dataset size and GPU. - PII: Always review
data/processed/pii_review.jsonlbefore training — it flags messages containing phone numbers, emails, and similar patterns. - Overfitting: Keep epochs at 2–3 and watch the validation loss. With 30k+ source messages you should have plenty of data.
- GPU memory: If you see
Unsloth: Will smartly offload gradients, reducemax_seq_lengthto1024and setpacking: falseinconfig.yaml.
See config.yaml.example for all available options with inline comments.