Sikia interviewer v6b (LoRA adapter, card format 12n)
A LoRA adapter on stock Gemma 4 E2B that reads a respondent's reply during an offline survey interview and
returns one short JSON reply. It follows the Sikia offline interview design: the app leads the interview
(question order, skip logic, repeat rounds, follow-ups, everything that is spoken) and the model only
listens. Each call gets the standing instructions (instructions.txt) and one short card.
Versions. v6b is trained like v4 (same base model, card format, instructions and settings) on corrected and wider data. v4 remains the version in use until v6b passes the checks listed under "Status".
Status: research pilot, candidate to replace v4. Better than v4 on real speech in our tests; a drop on whole numbers on drafted forms is still being checked, and Sikia's relevance test has not been run yet. Don't use it for real data collection yet.
What it does
| Card | Returns |
|---|---|
| Question (any form question: single or multiple choice, whole number, decimal, date, text) | {"act", "value", "say"} — act is answer, clarify, skip_request, impatient, correction (an earlier answer) or off_topic; say is always empty |
CURRENT: yes/no (another round? skip this question?) |
{"act": "yes"/"no"/"clarify", "say": ""} |
TASK: list items (split a spoken list) |
{"items": [...]} in the respondent's words |
TASK: probe (follow-up check on a researcher's goal) |
{"new_items": [...], "goal_met": bool, "follow_up": ""} |
goal_met is true only when the goal states a target ("Target: at least 3 points.") and that many points
have been heard; otherwise it is false and the app decides when to stop.
Example
LANG: sw
CURRENT: q=top_constraints type=select_multiple "Changamoto kubwa ni zipi?"
OPTIONS: 1=Ukame 2=Wadudu 3=Magonjwa 4=Udongo duni 5=Soko 6=Mbegu duni 7=Hakuna
CONTEXT: -
RESPONDENT SAID: "Wadudu ni wengi, na pia soko halina bei nzuri."
{"act": "answer", "value": "2 5", "say": ""}
Cards must match the training format byte for byte. slmlib/cards.py in the project code writes every card
and applies the app's post-processing (option numbers back to codes, the respondent's own words for text,
the year of a date).
Try it
Accept the Gemma licence on Hugging Face first, and use transformers 5.17 or later (earlier 5.x versions compute Gemma 4 E2B differently with the cache on, and the adapter then has no effect).
import torch
from huggingface_hub import hf_hub_download
from peft import PeftModel
from transformers import AutoModelForImageTextToText, AutoProcessor
BASE, ADAPTER = "google/gemma-4-E2B-it", "smutuvi/sikia-listener-v6b-gemma4-e2b-lora"
proc = AutoProcessor.from_pretrained(BASE)
model = AutoModelForImageTextToText.from_pretrained(BASE, dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(model, ADAPTER).eval()
system = open(hf_hub_download(ADAPTER, "instructions.txt"), encoding="utf-8").read().strip()
card = """LANG: sw
CURRENT: q=household_size type=integer "Watu wangapi wanaishi kwenye kaya yako?"
RANGE: 1 to 30
CONTEXT: -
RESPONDENT SAID: "Tuko saba, mimi na mke wangu na watoto watano." """
msgs = [{"role": "system", "content": system}, {"role": "user", "content": card.strip()}]
prompt = proc.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True, enable_thinking=False)
enc = proc.tokenizer(prompt, return_tensors="pt", add_special_tokens=False).to(model.device)
out = model.generate(**enc, max_new_tokens=80, do_sample=False)
print(proc.tokenizer.decode(out[0, enc["input_ids"].shape[1]:], skip_special_tokens=True))
# {"act": "answer", "value": "7", "say": ""}
With the project code, a whole interview on any form, typed or spoken:
python demo/form_interview.py --adapter smutuvi/sikia-listener-v6b-gemma4-e2b-lora --form bean_tricot # terminal
python demo/form_interview.py --adapter smutuvi/sikia-listener-v6b-gemma4-e2b-lora --form clinic --lang en
python demo/form_app.py # browser; lists this adapter
Speech is transcribed separately (the base model with the adapter switched off, or the ndizi speech model): one skill per adapter.
Training data
8,220 cards; the data itself is not published (it contains what respondents said).
| Source | Cards | |
|---|---|---|
| Real bean-trial replies (Swahili), question and follow-up cards | 2,095 | labels hand-checked on the test set, corrected in training |
| Drafted interviews on 7 topics (Swahili, English) | 3,876 | free text follows the core-answer rule; open opinion questions included |
| Sikia practice interviews on 14 real forms (Swahili, English) | 2,111 | part 1 (all reply types, weak-spot sets) and part 2 (off-topic replies to open questions) |
| Real Sikia replies on other forms (Swahili) | 138 | dev interviews only, usable labels only |
Changes from v4's data:
- Follow-up replies are follow-up cards only. 203 replies to a follow-up question had been exported as first-question cards, with "nothing new" keyed as the form's "Hakuna".
- Bean labels follow the question's direction. A "like" card codes what the respondent likes, a "dislike" card what they dislike; "nothing I dislike, it grew well" is Hakuna.
- Free text keeps the core answer: one unbroken stretch of the reply, copied exactly, without fillers or lead-ins (agreed with Sikia, 5 October 2026).
- For open opinion questions, an on-subject request or complaint is an answer ("We need an ambulance").
- Off-topic replies to open questions (Sikia part 2): answers to another question of the same form, and everyday talk, with as many real and roundabout answers so the model does not ask again on long replies.
Nothing comes from Sikia's 4 held-out forms.
Evaluation
v4 and v6b on the same test cards (one training run of v6b, seed 42).
| v4 | v6b | |
|---|---|---|
| Real Sikia replies on other forms (118): right answers | 101 | 103 |
| Real Sikia: single choice (94) | 88 | 91 |
| Real Sikia: answers misread as refusal, correction or off-topic | 1 | 2 |
| Real bean speech: trait codes, F1 | 0.899 | 0.907 |
| Real bean speech: "nothing" recognised | 0.968 | 1.000 |
| Real bean speech: follow-up points, word overlap | 0.702 | 0.767 |
| Drafted forms never used in training: whole numbers (117) | 116 | 109 |
| Drafted forms never used in training: single choice (24) | 24 | 23 |
Real bean speech: 189 hand-checked question cards and 198 hand-reviewed follow-up checks. Real Sikia: Sikia's fair
answer-key benchmark from interviews marked do-not-train. Full scores by group and language: scores_v12.json.
Differences of 1 to 3 cards are within run-to-run noise.
Known weak spots: whole numbers on unseen drafted forms (above, being checked); free text on real Sikia speech (6 of 16 exact; the benchmark keys often summarise); off-topic replies that answer a different question (Sikia's relevance test pending).
Training procedure
LoRA (PEFT) on the language model's linear layers only; the vision and audio towers are untouched. Loss on
the JSON reply only. Rank 16, alpha 32, 3 epochs, effective batch 16 (2 × 8), bf16, one GPU, transformers 5.17,
seed 42. Settings in train_config.json.