========================================================================
MOBILE TEAM HANDOFF
⚠ STEP 0 — Check the mobile team's installed react-native-executorch version
in Where_Zat/package.json. The PTE itself loads on any v0.6.0+ (which all
bundle ExecuTorch Runtime v1.0.0+). The JS integration code is what
varies. Pick ONE of the three options below.
Verified from npm registry: latest = 0.8.4, legacy = 0.7.3.
─────────────────────────────────────────────────────────────────────────
OPTION A — react-native-executorch v0.8.x (current latest)
─────────────────────────────────────────────────────────────────────────
⚠ v0.8.0 introduced TWO breaking changes vs v0.7.x:
initExecutorch() MUST be called once at app startup
contextWindowLength was renamed/replaced by contextStrategy
// ── App.tsx (or wherever your provider tree is rooted) ────────────────
import { initExecutorch } from 'react-native-executorch';
// Pick ONE adapter based on whether the app uses Expo:
import { ExpoResourceFetcher } from 'react-native-executorch-expo-resource-fetcher';
// --- OR ---
// import { BareResourceFetcher } from 'react-native-executorch-bare-resource-fetcher';
initExecutorch({ resourceFetcher: ExpoResourceFetcher }); // call ONCE at app entry
// ── In your component ─────────────────────────────────────────────────
import {
useLLM,
getStructuredOutputPrompt,
fixAndValidateStructuredOutput,
MessageCountContextStrategy,
} from 'react-native-executorch';
const wherezatSchema = {
type: 'object',
properties: {
intent: { type: 'string', enum: [
'store_item','find_item','update_item','delete_item','list_items',
'greeting','thanks','goodbye','help','unknown'
]},
item: { type: ['string', 'null'] },
location: { type: ['string', 'null'] },
message: { type: 'string' },
confirm_item: { type: 'boolean' },
accessibility: { type: ['string', 'null'], enum: ['private', 'public', null] },
},
required: ['intent', 'message'],
};
// Configure once. Append the schema instructions to the system prompt so
// the model is constrained to emit valid JSON.
useEffect(() => {
if (!llm.isReady) return;
llm.configure({
chatConfig: {
systemPrompt: SYSTEM_PROMPT + getStructuredOutputPrompt(wherezatSchema),
contextStrategy: new MessageCountContextStrategy(6), // keep last 6 msgs
},
});
}, [llm.isReady]);
─────────────────────────────────────────────────────────────────────────
OPTION B — react-native-executorch v0.6.x – v0.7.x (no initExecutorch)
─────────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────
OPTION C — react-native-executorch v0.4.x – v0.5.x (older flat API)
─────────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────
INFERENCE — generate() takes a Message[] array DIRECTLY (not wrapped)
─────────────────────────────────────────────────────────────────────────
// ✅ Correct — what the v0.8.x docs show
const response = await llm.generate([
{ role: 'system', content: SYSTEM_PROMPT }, // see below — verbatim
{ role: 'user', content: userInput },
]);
// ⚠ Do NOT call generate({ messages: [...] }) — that signature does NOT exist
─────────────────────────────────────────────────────────────────────────
PARSING THE RESPONSE — use the structured-output helper, not bare JSON.parse
─────────────────────────────────────────────────────────────────────────
// On v0.8+ — robust against minor formatting glitches:
const parsed = fixAndValidateStructuredOutput(response, wherezatSchema);
// → { intent, item, location, message, confirm_item, accessibility }
// On older versions (no helper available):
const parsed = JSON.parse(response); // wrap in try/catch
========================================================================
SYSTEM_PROMPT (paste verbatim into the mobile app)
Classify the message for an item locator app. Output ONLY a JSON object.
{"intent":"INTENT","item":"ITEM","location":"LOC","message":"MSG","confirm_item":BOOL,"accessibility":ACC}
Intents:
- store_item: store, save, put, keep, add, "i have/got" + item name. "store" ALWAYS means store_item.
- find_item: where, find, lost, search, "do i have", "have i got", "did i save" + item name
- update_item: move, moved, relocate + item name + new place
- delete_item: delete, remove, get rid + item name
- list_items: show all, list, what items, whats in, "do i have anything". item is ALWAYS null.
- greeting: hi, hello, hey, good morning, yo, sup
- thanks: thanks, thank you, thx, ty, cheers
- goodbye: bye, goodbye, see ya, later, peace
- help: help, how do I, what can you do
- unknown: anything else (e.g. "i have a headache/fever" — non-physical). Include a friendly redirect.
Rules:
- item = physical object name. location = place name. null if not in current message.
- "i have/got X" with no location = store_item, ask "Where do you want to store X?".
- "i have/got X in Y" = store_item with location, ask "Private or public?".
- "do i have X" / "have i got X" (X is a specific item) = find_item.
- "do i have anything" (no specific item) = list_items.
- "i have a headache/fever/cold/cough" etc. = unknown (not a physical object).
- Store flow: 1) get item 2) get location 3) ask private or public. All 3 needed.
- Update flow: 1) get item 2) get new location 3) ask private or public. All 3 needed.
- accessibility: "private" or "public". null until user answers.
- If user says "private/just me/only me" = private. "public/shared/everyone" = public.
- For multiple items use comma string: "apple, cake" (never array).
- If user stores 2 items and gives location for 1, ask where for the other.
- Always include message field in every response.
- "store X in Y" is ALWAYS store_item regardless of conversation history.
confirm_item rules for move/delete with "it/this/that":
- If ONLY 1 item was just mentioned in immediate previous message: confirm_item=false, use that item.
- If 2+ items in recent context: confirm_item=true, item=null, ask which.
- If there was any gap before "move it": confirm_item=true, item=null.
- If specific item name given: confirm_item=false always.
========================================================================
Length: 2286 chars (must match training prompt exactly)
========================================================================
NOTES FOR MOBILE TEAM
- PTE was exported with executorch==1.1.0
- max_seq_len = 1024 (KV cache size baked in — DO NOT exceed at inference)
- Quantization: 8da4w (linear) + 8w (embeddings)
- Tokenizer is JSON format (NOT .bin). useLLM reads it natively.
- Repo is PRIVATE — app needs an HF read token, OR mirror to a public bucket
- The 2,286-char SYSTEM_PROMPT is REQUIRED. Without it the model
produces freeform English instead of JSON.
- On v0.8+: initExecutorch() with the right resource-fetcher adapter
is mandatory. App will crash on first useLLM call without it.
- On v0.8+: prefer fixAndValidateStructuredOutput() over JSON.parse()
— it handles minor formatting glitches (trailing commas, etc.)