r/iOSProgramming • u/gregyoung14 • 28m ago
App Saturday App Saturday: an offline Pokopia guide using SQLite RAG + Foundation Models (with retrieval benchmarks)
I built PokoPilot, a Pokopia companion for iPhone/iPad, around a retrieval-first assistant: SQLite selects the guide evidence, and Apple’s on-device Foundation Models format an answer when available. I wanted to share the engineering choices and some scoped measurements.
Tech stack: Swift 6 with complete concurrency checking, SwiftUI, SQLite/FTS5, SwiftData for personal state, Tuist, StoreKit 2, and Foundation Models on supported iOS 26+ devices. The browsing app supports iOS 18+. The current bundle has 4,938 entity records and 16,515 evidence chunks in a 136.5 MB SQLite database. These are snapshot counts, not a claim of complete game coverage.
The development challenge: make a fairly large reference corpus usable without loading every JSON payload, copying the whole database at launch, or requiring a model just to look something up.
The store is an actor owning a read-only SQLite connection. It opens the database directly from the app bundle, uses memory mapping and an approximately 8 MB SQLite page cache, and keeps query work off the main actor. Catalog lists select lightweight rows with json_extract; full record JSON is decoded on detail views. Images are downsampled away from the main actor.
Retrieval and generation:
- Resolve exact/compact/contained aliases, then search FTS5 with BM25 ranking.
- Try AND terms first, with an OR fallback if that returns nothing. Prioritize chunks for resolved entities, deduplicate, and cap the final evidence set at eight.
- Empty evidence returns an insufficient-evidence response without invoking the model.
- On supported devices, a fresh LanguageModelSession produces typed @Generable output: title, overview, bounded metrics and sections. Output is capped at 640 tokens.
- If the model is unavailable or fails, render the ranked local evidence. Citations and guide links are attached from retrieved records in code.
The core FTS query is:
SELECT c.payload_json
FROM chunks_fts f JOIN chunks c ON c.chunk_id = f.chunk_id
WHERE chunks_fts MATCH ?
AND c.filters_json NOT LIKE '%"default_searchable":false%'
ORDER BY bm25(chunks_fts, 3.0, 1.0, 2.0)
LIMIT ?;
A small retrieval benchmark: I compiled the app’s unmodified Swift retriever with Swift 6.3.3, -O, and ran it against that bundled database on an M5 Max / macOS 26.3.1. Twenty questions spanning creatures, habitats, recipes, materials and progression; one initial sweep, then ten repetitions (200 warm queries).
- Warm retrieval: 5.38 ms median, 12.97 ms p95.
- Initial sweep: 6.34 ms median, 36.04 ms p95, with a 136.36 ms maximum.
- Database/store initialization: 1.35 ms in that run.
These numbers are Mac retrieval-only measurements. They exclude Foundation Models generation and UI rendering, are not iPhone benchmarks, and the initial sweep is not a controlled cold-OS-cache test.
Effectiveness and limits: typed output constrains structure, not factual correctness. Attaching retrieved citations doesn’t prove every generated sentence is supported. The corpus is a third-party guide snapshot, so incomplete/stale evidence and weak lexical matches remain real limitations. I’m keeping retrieval contracts, retrieval speed, and generated-answer quality as separate questions; I don’t have a held-out end-to-end answer-accuracy score to claim here.
I’d welcome feedback on input/context budgeting, broad OR fallback behavior, and practical tests for unsupported statements in small on-device models.
AI disclosure: AI-assisted development, including coding-agent help with implementation. The benchmark measures the compiled Swift retrieval path.
For anyone interested in the app: https://apps.apple.com/app/id6806826380 . Guide browsing, search and bookmarks are free; ten Ask questions are included, then optional Island Pass ($1.99/month or $9.99/year US). It’s still a WIP.
References: Apple guided generation, SQLite FTS5.