Image-Text-to-Text
PEFT
Safetensors
English
muse_glimmer
trained-eye
qlora
lora
axolotl
smart-glasses
egocentric-vision
conversational
4-bit precision
bitsandbytes
Instructions to use amaan784/trained-eye with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use amaan784/trained-eye with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("meta-models/Muse-Glimmer-30B") model = PeftModel.from_pretrained(base_model, "amaan784/trained-eye") - Notebooks
- Google Colab
- Kaggle
File size: 14,345 Bytes
529d93a ee660e3 529d93a ee660e3 529d93a ee660e3 529d93a ee660e3 c189654 ee660e3 529d93a c189654 da5da2e c189654 529d93a ee660e3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | ---
base_model: meta-models/Muse-Glimmer-30B
base_model_relation: adapter
library_name: peft
license: apache-2.0
language: [en]
pipeline_tag: image-text-to-text
tags: [trained-eye, qlora, lora, axolotl, smart-glasses, egocentric-vision]
---
# Trained Eye: watch skills for Muse Glimmer 30B (LoRA adapter)
**What this is.** A QLoRA adapter (PEFT) for `meta-models/Muse-Glimmer-30B` (revision `a4e59da52a7bc87ae7251dd5545c0dd437c44b68`), from
[Trained Eye](https://github.com/amaan784/trained-eye), which lets Meta glasses watch for something and say when it
happens. Given one first-person camera frame and a condition in the prompt, it answers
yes or no. It was trained on two skills at once (the training run is called
`product`): `burner_left_on` ("Tell me when a burner has been left on"), `fridge_left_open` ("Tell me when the fridge door is left open"). It is not a model on its own: it needs the base model's weights.
[Code](https://github.com/amaan784/trained-eye) | [Playground](https://aas2438--trained-eye-playground-web.us-east.modal.run) | [Training runs (W&B)](https://wandb.ai/amaan784-columbia-university/trained-eye) |
[How it works](https://aas2438--trained-eye-playground-web.us-east.modal.run/how-it-works)
## What is in this repository
| File | What it is |
|---|---|
| `adapter_model.safetensors` | The LoRA weights: rank 32 on every attention and MLP projection of the language model's layers; the vision tower is unchanged. 767 MB. |
| `adapter_config.json` | PEFT's settings for those weights: the base model, the rank, alpha and the target modules. |
| `config.json` | The model configuration the training run saved with the adapter. |
| `processor_config.json` | The image processor's settings, saved with the adapter. |
| `tokenizer.json` | The tokenizer, saved with the adapter. |
| `tokenizer_config.json` | The tokenizer's settings, saved with the adapter. |
| `chat_template.jinja` | The chat template the prompts were built with. |
| `manifests/<skill>.jsonl` | One line per generated training image (300 for burner_left_on, 300 for fridge_left_open): Muse Image's edit prompt, the answer it was made for (yes, or no for a near-miss), and the SHA-256 of the frame it edited and of the image. The images themselves are not here. |
| `LICENSE` | The base model's license text (Apache-2.0). |
| `release.json` | Every file here with its size and SHA-256. |
| `README.md` | This card. |
Not in this repository:
- The base model's weights: get `meta-models/Muse-Glimmer-30B` at revision `a4e59da52a7bc87ae7251dd5545c0dd437c44b68` from Hugging Face, under its own terms.
- The training images. The generated images are never published (they keep Muse Image's
provenance and stay with the author), and neither are the teaching frames they were
edited from. `manifests/` says how each generated image was made.
- The test clips and their labels, and the training code, which is on [GitHub](https://github.com/amaan784/trained-eye).
## How to use it
Send each frame the way the training examples were built:
- System message: `You watch first-person camera frames for one condition. Answer only yes or no.`
- User message: the frame, padded (not cropped) to 512 x 512 pixels with black
bars, then this text: `Condition: <what to watch for>. Not: <a near-miss>; <another>.
Is the condition true in this frame?`
The conditions it was trained with, word for word:
| Skill | Asked as | Condition | Not |
|---|---|---|---|
| burner_left_on | Tell me when a burner has been left on | a burner is visibly on with a blue gas flame or glowing red hot and no pot or pan on it | a burner is off, dark and unlit with no flame or glow; a burner is on but has a pot or pan sitting on it; an unlit neighbouring burner on the same cooktop; shiny foil burner liner or metal grate with no flame or red glow |
| fridge_left_open | Tell me when the fridge door is left open | the fridge door stands open with its brightly lit interior, food shelves, and door bins exposed | the fridge doors are fully closed, showing only the dark flat exterior with no interior light visible; the bottom freezer drawer is closed beneath the fridge compartment; a closed kitchen cabinet above the refrigerator; an open cabinet or pantry door that is not the refrigerator |
Glimmer writes a short reasoning before it answers, so read the last `yes` or `no` token it
generates, and take the chance of yes from that token's top logprobs (yes over yes plus
no). An alert should wait until that chance has stayed over a threshold, calibrated on
your own labelled clips, for the skill's hold (Trained Eye's watcher does this).
What ran on Nov 4: the adapter merged into the bf16 base with PEFT's
`merge_and_unload()` on one 80 GB H100, then served with vLLM's
`vllm/vllm-openai:muse-glimmer` image, each request with `logprobs` on, `top_logprobs`
10, up to 512 new tokens and `chat_template_kwargs` `{"reasoning_strength": "low"}`.
Loading the adapter with vLLM's `--enable-lora` did not start for this model on that
image. The merge, as the project's `te export` runs it:
```python
import torch
from peft import PeftModel
from transformers import AutoModelForImageTextToText, AutoProcessor
base, revision = "meta-models/Muse-Glimmer-30B", "a4e59da52a7bc87ae7251dd5545c0dd437c44b68"
model = AutoModelForImageTextToText.from_pretrained(
base, revision=revision, torch_dtype=torch.bfloat16, device_map="auto")
model = PeftModel.from_pretrained(model, "amaan784/trained-eye").merge_and_unload()
model.save_pretrained("trained-eye-merged")
AutoProcessor.from_pretrained(base, revision=revision).save_pretrained("trained-eye-merged")
```
## Results
In short: on other kitchens filmed first-person on phones, the fine-tuned model spotted the condition about as accurately as base Glimmer and less accurately than Muse Spark (frame F1 0.87, 0.88 and 0.94), answering in 1.64 s a frame against 2.53 s and 11.80 s, at $4.00 an hour against $16.53 for Spark.
By skill, the fine-tuned model was the least accurate of the three on burner_left_on (frame F1 0.64, against 0.79 for base Glimmer and 0.97 for Muse Spark) and the most accurate of the three on fridge_left_open (frame F1 0.95, against 0.91 and 0.92). burner_left_on has no calibration clip, so the fine-tuned model runs it at the default threshold, 0.50.
| Skill | Model | Frame precision | Frame recall | Frame F1 | Frame accuracy | Seconds per frame | Dollars per hour |
|---|---|---|---|---|---|---|---|
| burner_left_on | this adapter | 1.00 | 0.47 | 0.64 | 0.70 | 1.69 | $4.10 |
| burner_left_on | base Muse Glimmer 30B | 1.00 | 0.65 | 0.79 | 0.80 | 3.22 | $4.26 |
| burner_left_on | Muse Spark (API) | 0.98 | 0.96 | 0.97 | 0.97 | 11.93 | $16.53 |
| fridge_left_open | this adapter | 0.93 | 0.96 | 0.95 | 0.95 | 1.58 | $3.95 |
| fridge_left_open | base Muse Glimmer 30B | 0.86 | 0.97 | 0.91 | 0.91 | 2.34 | $3.95 |
| fridge_left_open | Muse Spark (API) | 0.87 | 0.98 | 0.92 | 0.91 | 11.67 | $16.53 |
Test footage: other kitchens filmed first-person on phones (handheld; four fridges and two stoves the model was not taught on; labels drafted by an AI assistant, see docs/evaluation.md). From `te eval`'s `results.json` (SHA-256 `6704865a78632b3e1d28aa5b50c1f56ca68537b9307949ead80969b32ecb1d8a`); evaluations scored: 6, pending: 0. n/a means there was nothing to compute it from. Each skill alerts only once its condition has stayed true for its hold: event_recall_in_window counts an alert within the skill's window after the hold ends, and time_to_alert_median_s is counted from the end of the hold. Holds and windows: burner_left_on, a 10 s hold and a 5 s window; fridge_left_open, a 20 s hold and a 10 s window. Thresholds were calibrated for frame F1 (this footage has too few events past the hold to judge alerts).
<details><summary>Every scored evaluation</summary>
| evaluation | experiment | skill | variant | hours | precision | recall | f1 | event_recall_in_window | false_alarms_per_hour | time_to_alert_median_s | latency_median_s | usd_per_hour |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| phone-exp4-finetuned-fridge_left_open | 4 | fridge_left_open | finetuned | 0.1322 | 0.9328 | 0.9633 | 0.9478 | 0.6667 | 7.563 | 0.0 | 1.5845 | 3.95 |
| phone-exp4-base-fridge_left_open | 4 | fridge_left_open | base | 0.1322 | 0.8614 | 0.9746 | 0.9145 | 0.6667 | 7.563 | 0.0 | 2.341 | 3.95 |
| phone-exp4-spark-fridge_left_open | 4 | fridge_left_open | spark | 0.1322 | 0.8723 | 0.9755 | 0.921 | 0.6667 | 7.563 | 0.0 | 11.6665 | 16.5276 |
| phone-exp4-finetuned-burner_left_on | 4 | burner_left_on | finetuned | 0.0594 | 1.0 | 0.4667 | 0.6364 | 0.0 | 0.0 | 13.0 | 1.689 | 4.1045 |
| phone-exp4-base-burner_left_on | 4 | burner_left_on | base | 0.0594 | 1.0 | 0.65 | 0.7879 | 0.5 | 0.0 | 0.0 | 3.2215 | 4.2589 |
| phone-exp4-spark-burner_left_on | 4 | burner_left_on | spark | 0.0594 | 0.9829 | 0.9583 | 0.9705 | 0.5 | 16.8224 | 9.5 | 11.9315 | 16.5276 |
</details>
The full tables, the EPIC-KITCHENS-100 results and how it was measured are on GitHub:
[results](https://github.com/amaan784/trained-eye/blob/main/eval/results.md), [EPIC-KITCHENS](https://github.com/amaan784/trained-eye/blob/main/eval/epic/results.md),
[method](https://github.com/amaan784/trained-eye/blob/main/docs/evaluation.md).
## Training
Meta's cookbook QLoRA recipe for Muse Glimmer (meta-oss-cookbook at commit b30ca2c,
muse-glimmer/post-training/sft/axolotl) with Axolotl 0.19.0, unchanged except the paths, the
W&B names and the gradient accumulation that keeps its global batch of 32 on one GPU.
The training data was made through the Meta Model API:
compiler `muse-wonder-1.0`, sam `sam-3.1`, image `muse-image-1.0`, labeler `muse-spark-1.3`.
| Setting | Value |
|---|---|
| `adapter` | `qlora` |
| `load_in_4bit` | `true` |
| `lora_r` | `32` |
| `lora_alpha` | `16` |
| `lora_dropout` | `0.05` |
| `lora_target_modules` | `model\.language_model\.layers\.\d+\.(self_attn\.(q\|k\|v\|o)_proj\|mlp\.(gate\|up\|down)_proj)` |
| `sequence_len` | `4096` |
| `micro_batch_size` | `1` |
| `num_epochs` | `1` |
| `optimizer` | `adamw_bnb_8bit` |
| `lr_scheduler` | `cosine` |
| `learning_rate` | `0.0002` |
| `warmup_ratio` | `0.1` |
| `weight_decay` | `0.0` |
| `bf16` | `true` |
| `attn_implementation` | `flash_attention_2` |
| `seed` | `42` |
## Training data
Bundle `mixed`: 603 training and 65 validation examples (train.jsonl SHA-256 `c056bbd61a66ece9bc9b4ec2af87f8b587a6cf952bf0d020fef29f4624473e49`). Real: keyframes of the user's own teaching clips, labelled by the user or else by Muse Spark. Generated: images Muse Image made by editing those same keyframes (the condition, near-misses, other light and angles), labelled by Muse Spark and kept only where Spark agreed with the label it was made for.
| Skill | Split | Real yes | Real no | Generated yes | Generated no |
|---|---|---|---|---|---|
| burner_left_on | train | 33 | 0 | 125 | 135 |
| burner_left_on | val | 7 | 0 | 12 | 15 |
| fridge_left_open | train | 45 | 0 | 134 | 131 |
| fridge_left_open | val | 1 | 0 | 16 | 14 |
The generated images are not included. `manifests/` lists every edit prompt with the SHA-256 of its keyframe and of its image. For burner_left_on, fridge_left_open, `te regenerate` needs the original keyframes, which are not published.
## Uses
Intended: yes/no watch skills on first-person frames from smart glasses or a phone, each
taught by its user from their own footage: the state of an object, a display, a sign or a
vehicle (has the fridge been left open? is the tap still running?), with an alert threshold
calibrated on the user's own validation clips and a hold before each alert. An alert is a
reminder: it never replaces a smoke alarm or turning a burner off.
Out of scope: people (identifying, recognising or tracking anyone), bodies, health,
medication and other sensitive traits, covert monitoring, sensitive places, sports analysis
or coaching, and anything where a missed or false alert could put someone at risk.
## Limitations
- Each skill comes from one user's scenes and camera; others are untested beyond the
evaluation above. Most training images are Muse Image edits with Muse Spark's labels, which can be wrong.
- It answers per frame: alerts need the watcher's smoothing, each skill's hold, a
calibrated threshold and a cooldown. The vision tower stayed frozen, so small, distant or glary targets stay hard.
- Scoring reads the server's top logprobs for the yes or no token, so the server must return them.
- In plain words: overall it is about as accurate as base Glimmer and faster; it is the best
of the three on the fridge and the weakest on the burner, so do not read it as an accuracy
gain from fine-tuning on every skill.
- It watches only what the glasses can see: look away and it cannot tell whether the
condition is still true.
- If Muse Spark's check fails outright (an error, not a no), the alert is still spoken and
logged as unconfirmed, on purpose, so a cloud outage never silences an alert; a no from
Spark holds it back.
- The test labels were drafted by an AI assistant, too few events lasted past the hold to
judge alerts well, and Experiments 2 and 3 did not run.
- Validation during training was split by example, not by source frame, so related images
can sit on both sides; the separate test footage is not affected.
## Privacy and provenance
- Faces are blurred in everything published with this model. Watch mode does not store
frames unless the user saves a clip, and never hides the glasses' capture LED.
- Muse Image outputs keep their watermark and provenance metadata, byte for byte, and are
never published.
## License
`apache-2.0` as the base model's (meta-models/Muse-Glimmer-30B at revision `a4e59da52a7bc87ae7251dd5545c0dd437c44b68`; its license text is in `LICENSE`). These weights are a modification of that model: QLoRA fine-tuning on the data above (for a merged build, that adapter merged into the base). Any use is also subject to Meta's [Muse Glimmer Usage Policy](https://huggingface.co/meta-models/Muse-Glimmer-30B/blob/main/USAGE_POLICY.md).
## Citation
```bibtex
@software{sheikh2026trainedeye,
author = {Sheikh, Amaan},
title = {Trained Eye: Teach Your Glasses to Notice Anything},
year = {2026},
month = nov,
url = {https://github.com/amaan784/trained-eye}
}
```
|