Local & sovereign AI

Monster
Scanner

A Qwen 2B vL model, ON AN iPhone

A working example of using local AI on an iPhone. Qwen3-VL-2B on an iPhone 14 Pro, with no network connectivity.

AI Engineering meetup · Bill Mcintyre · October 22 2026

Seven Questions

What we set out to explore

01

On-device LLM

Can a local OSS LLM reasonably run on an iPhone?

02

What it takes

Which runtime, models, hosts, and quantizations fit in memory?

03

Capabilities

Can it analyze photos and answer in strict, tool-ready JSON?

04

Performance

Fast enough for photo analysis in realtime, under 1 GB?

05

Deterministic

Can the model narrate within a testable code harness?

06

Guardrails

Can every AI response stay safe, reasonable and in-bounds?

07

Fallback

Can we maintain flow when/if the model fails?

02

Monster Scanner · Halloween edition

A Monster Scanner

Scan a friend. Find their inner monster.

2B

parameters

A16

iPhone 14 Pro

0

network calls

Vampire · Alien · Kaiju · Werewolf · Zombie · Robot · Ghost · Certified Human

03

Monster Scanner · Halloween edition

AI (monster) Brain, Deterministic Wrapper

The model only narrates

The model

Describes the photo and adds playful lines.

The code

Measures, decides and checks every AI sentence.

04

Monster Scanner · Halloween edition

How It Works

Photo

In memory

Classic · always

Vision: face, tilt, eyes
Labels: hats, glasses
Pixels, clock, moon

AI observer

Qwen3-VL-2B, llama.cpp
Grammar-forced JSON
Strict kindness check

Verdict engine

Deterministic Swift
Seeded by the photo
47 clues: clothes, pose

Reveal

Code-written jokes
AI’s playful lines
Voice, sound, haptics

late or hot: skip

05

Monster Scanner · Halloween edition

1.55 GB

on disk

< 1 GB

peak memory

Meet Qwen3-VL-2B

PartBitsSize
Language model4-bit1,107 MB
Vision projector8-bit445 MB

Apache 2.0 open weights from the official Qwen org. Files: Qwen3VL-2B-Instruct-Q4_K_M and mmproj-Qwen3VL-2B-Instruct-Q8_0, both GGUF.

06

Monster Scanner · Halloween edition

Three Jobs

1

Observer

Every scan

Reads the photo, returns JSON

2

Chaos Mode

Opt-in

Scores monsters; code clamps

3

AI Notes

Experimental

Streams checked notes

07

Monster Scanner · Halloween edition

Why This Model

Official GGUFs from Qwen itself

llama.cpp runs its architecture

Fits beside the camera on 6 GB

Apache 2.0: free to ship

Tested in PocketPal first

Not (yet)

Qwen3.5-2B

No official GGUF yet

MLX

The fallback runtime

F16 projector

819 MB, kept in reserve

08

Monster Scanner · Halloween edition

llama.cpp on Metal

Official prebuilt xcframework · build b11799 · MIT · mtmd for images

No Simulator slice

Device builds only

A Swift actor

Main thread stays free

Lifecycle

Loads in 0.73 s

A Mac twin

126 tokens/s on a Mac

09

Monster Scanner · Halloween edition

JSON Every Time

Setup (Mac, LlamaProbe)Tokens/sOutput
No grammar130JSON in a code fence
Grammar, full ~152k vocabulary55Valid JSON
Grammar, whitespace squeezed55Invented “glasses, headphones”
Grammar after top-k 40126Valid; crashes above temp 0
Check-then-resample (shipped)~105Always valid

5 of 5 valid on the phone

10

Monster Scanner · Halloween edition

Four More Lessons

Keep loops in C

Swift loop: −25% speed

Decode greedily

Same photo, same reading

Examples get copied

Show style, not samples

Only what you see

No more invented hats

On a props photo: “a top hat” · “two red balloons” · “like a happy, slightly sleepy explorer”

11

Monster Scanner · Halloween edition

0

unkind sentences kept, out of 187 in 50 field notes

Three Safety Layers

1 · Prompt rules

Clothes, props, pose, setting

2 · Grammar limits

Letters only, 100 chars max

3 · Kindness check in model

Safety reinforced in code

Word lists: unkind, age, looks, stereotypes

12

Monster Scanner · Halloween edition

Fast When Cool

Seconds per photo · dot = middle of the measured range · final prompt unless noted

9.5 s model deadline

Mac M3 Max, final prompt

iPhone, short prompt

iPhone, ordinary photo

iPhone, detail-rich photo

Before the sampler fix

Hot iPhone (“serious”)

1.1–1.6 s

4.4–4.5 s

6.4–6.6 s

8.5 s

11 s

15–20 s

0 s

5 s

10 s

15 s

20 s

13

Source: LlamaProbe (Mac) · in-app benchmark (iPhone 14 Pro, Debug)

9.1 s

worst reveal

budget: 12 s

Heat Is the Monster

“Serious” heat = half speed

Then the app skips the model

Soak: “fair” at 6, “serious” at 8

Scans 9–10 used Classic. No crash.

Load 0.73 s

~20 tokens/s

978 MB peak

14

Monster Scanner · Halloween edition

Works Offline

One download

HTTPS, pinned, Wi-Fi only

Pinned by hash

SHA-256 every launch

Checked first

GitHub, HF and CVE lists

One binary

llama.cpp + Qwen, that’s it

Nothing stored

Photos stay in memory

Approval gate

New stuff needs a human yes

15

Monster Scanner · Halloween edition

Apple Does the Rest

FrameworkUsed for
Vision, Core ImageFace geometry, smiles, blinks, hats and setting
AVFoundation, Core HapticsCamera, narration voice, synthesised sounds, haptics
SwiftUIEvery screen and the certificate image
PhotosUIPhoto import with no library permission
CryptoKitSHA-256 checks and the per-photo seed
URLSessionThe model download: the only network code

16

Monster Scanner · Halloween edition

Built by an Agent

Claude Code (Opus 5.5)

Wrote it all, built, deployed

Helper agents

Sounds, effects, certificate

LlamaProbe

Same engine, on the Mac

devicectl + tests

Benchmarks, soak, 76 tests

Working agreement

Logs kept together

Small commits

Ask before adding

Flag spec problems

17

Monster Scanner · Halloween edition

Nine Lessons

Model only sees

Code decides

Use a grammar

No broken JSON

Loops in C

Swift cost 25%

Design for heat

Plan a fallback

Describe style

Don’t show it

Build a Mac twin

1-second tests

AI is optional

Failures vanish

Pin and verify

Hash every file

Seed everything

Test the mix

18

Monster Scanner · Halloween edition

The Whole Stack

ComponentVersionLicencePurpose
llama.cpp xcframeworkb11799MITInference on Metal + mtmd
Qwen3-VL-2B Q4_K_Mcommit 52d6c8fApache 2.0Language model, 1,107 MB
Qwen3-VL-2B mmproj Q8_0commit 52d6c8fApache 2.0Vision projector, 445 MB
Apple frameworksiOS 17+ SDKApple SDKCamera, Vision, speech, UI
MonsterCore packagein the repoOursVerdicts, prompts, jokes

Target: iPhone 14 Pro (A16, 6 GB) · iOS 17+ · built on a MacBook Pro, M3 Max

19

Monster Scanner · Halloween edition

QR code linking to github.com/BillDX/monster-scanner

Scan me

Thank
You

Questions?

The model narrates. The code decides.

Copyleft, GPL-3.0: use it, change it, share it, keep it open.

Bill Mcintyre · github.com/BillDX/monster-scanner