What Am I Looking At?
A local-first visual assistant for macOS β it sees the scene, names the objects, and answers your questions. On your Mac. Nothing uploaded.
Quick start Β· How it works Β· Stack Β· Docs Β· License
Most visual assistants ship camera frames to a cloud API. Senti does not.
It is built for Apple Silicon so the fast path β object detection and tracking β stays at interactive rates, while the slow path β a local vision-language model via Ollama β only runs when the scene actually changes or you ask a question.
| π― Live boxes & track IDs | π¬ Follow-up questions | π Object focus |
|---|---|---|
YOLO26 labels, confidence, stable #1 #2 IDs |
βWhatβs that connector?β βWhat objects do you see?β | Crop #2 phone before the VLM sees it |
| π On-device OCR | π Spoken answers | ποΈ Push-to-talk |
Ask read this or auto-read on READY |
macOS TTS (Qt or say) |
Local Whisper, Esc to cancel |
| Capability | Detail | |
|---|---|---|
| π₯ | Live perception | YOLO26 on Apple Silicon β PyTorch mps or yolo-mlx Metal β plus ByteTrack / BoT-SORT IDs |
| π§ | Scene intelligence | Visual + object + spatial change detection, stability gating, best-frame selection |
| π§ | Local understanding | Ollama VLM, auto-analysis when the scene settles, conversational memory |
| βοΈ | Object focus | Padded crop of the most likely target before a focused question |
| π€ | On-device OCR | EasyOCR on demand (read this) or automatically when the scene is ready |
| π£οΈ | Speech I/O | macOS TTS and local Whisper push-to-talk |
| π | Privacy by design | No cloud uploads, no disk recordings, bounded in-memory frame buffer |
Two loops keep the UI live. The camera never waits on the language model.
flowchart LR
Cam["π· Camera"] --> Fast
subgraph Fast["β‘ Fast loop β 15β30 FPS"]
YOLO["π― YOLO26 + tracking"]
Scene["π§ Scene change + stability"]
YOLO --> Scene
end
Fast --> Slow
subgraph Slow["π Slow loop β on change or question"]
Frame["πΌοΈ Best-frame selection"]
OCR["π€ Optional OCR"]
VLM["π§ Local VLM"]
Frame --> OCR --> VLM
end
Slow --> UI["π₯οΈ Desktop UI + TTS"]
Mic["ποΈ Push-to-talk"] --> UI
UI --> Ask["π¬ Ask / Focus / Analyze"]
Ask --> Slow
- β‘ Fast loop β frames go to YOLO26, then tracking and scene-change detection. Target: 15β30 FPS.
- π Slow loop β when the scene reaches
READY, Senti picks the sharpest, most stable frame from a rolling buffer and sends it to the local VLM (and OCR, if enabled). Follow-ups reuse scene memory when they can.
State machine: WATCHING β SCENE_CHANGED β WAITING_FOR_STABILITY β READY
Full package map and thread model: Architecture.
Every runtime dependency, with a badge that opens its official site. Click through β these are the projects Senti stands on.
| Project | Official site | Role in Senti | |
|---|---|---|---|
| Python | python.org | Runtime (3.11+) | |
| macOS | apple.com/macos | Camera, TTS say, permissions |
|
| PySide6 / Qt | doc.qt.io/qtforpython-6 Β· qt.io | Native window, AVFoundation capture, TTS | |
| NumPy | numpy.org | Frame arrays | |
| OpenCV | opencv.org | Overlays, sharpness, scene diff | |
| Ultralytics YOLO26 | ultralytics.com Β· YOLO26 docs | Detection + tracking | |
| PyTorch | pytorch.org | Default YOLO path: MPS on Apple Silicon | |
| π | MLX / yolo-mlx | MLX Β· yolo-mlx | Optional native Metal detector (YOLO_RUNTIME=mlx; pip install "yolo-mlx[tracking,convert]") |
| Ollama | ollama.com | Local vision-language model | |
| π€ | EasyOCR | jaided.ai/easyocr Β· GitHub | On-device text recognition |
| ποΈ | faster-whisper | SYSTRAN/faster-whisper | Push-to-talk transcription |
| ποΈ | sounddevice | python-sounddevice.readthedocs.io | Microphone capture |
| βοΈ | python-dotenv | GitHub | .env configuration |
| pytest | docs.pytest.org | Unit tests |
Pinned versions live in requirements.txt.
- π macOS on Apple Silicon (developed on M2 Pro)
- π Python 3.11 or newer
- π· Built-in or Continuity Camera
- π Camera permission (and microphone if voice input is on)
- π¦ Ollama with a vision model for scene descriptions
git clone https://github.com/TeslaNeuro/Senti.git
cd Senti
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .envPull a local vision model, then launch:
ollama pull gemma4
./scripts/run.shOr:
source .venv/bin/activate
python -m appOn first launch, macOS will ask for camera access. Grant it to Terminal (or your IDE) if you start Senti from the command line. Ultralytics downloads yolo26n.pt into models/ automatically (~6 MB) unless that file is already there.
Optional native Metal path: install yolo-mlx with pip install "yolo-mlx[tracking,convert]", then set YOLO_RUNTIME=mlx.
π‘ If the preview is black, another app (FaceTime, Zoom, Chrome, β¦) likely holds the camera. Quit it and relaunch.
| Action | What happens |
|---|---|
| π Watch the preview | Live boxes, labels, confidence, track IDs (#1, #2, β¦) |
β³ Wait for READY |
Automatic VLM description of the best buffered frame |
| π¬ Type in Ask | Follow-up against scene memory, or a new VLM call when needed |
| π― Focus dropdown | Analyze a specific tracked object (cropped when enabled) |
| π Analyze | Force a fresh VLM pass (bypasses cooldown) |
| π§Ή Clear | Reset scene memory and the response panel |
| π Speak / say that | Replay the current answer (when TTS is on) |
| ποΈ Mic / Stop | Push-to-talk; Esc cancels an in-progress recording |
| π read this | Run OCR on the current scene |
Status bar shows camera, YOLO device, VLM activity, FPS, and inference latency. Hover a pill for the full detail.
Step-by-step walkthrough: Usage.
Copy .env.example to .env. Important defaults:
| Variable | Default | Purpose |
|---|---|---|
CAMERA_WIDTH / CAMERA_HEIGHT |
1280 / 720 |
Capture size |
YOLO_MODEL |
yolo26n.pt |
Weights filename; stored in models/ (yolo26s.pt is more accurate) |
YOLO_RUNTIME |
auto |
auto (Ultralytics unless YOLO_DEVICE=mlx), ultralytics (PyTorch MPS), or mlx (yolo-mlx Metal) |
YOLO_DEVICE |
auto |
auto β PyTorch mps on Apple Silicon; mlx for yolo-mlx |
VLM_MODEL |
gemma4 |
Ollama vision model |
VLM_BASE_URL |
http://localhost:11434 |
Local Ollama API |
OCR_ENABLED |
false |
On-device text recognition |
TTS_ENABLED |
false |
Speak answers aloud |
VOICE_ENABLED |
false |
Whisper push-to-talk |
Optional features (OCR, TTS, voice) are off until you turn them on. Full reference: Configuration.
π Optional extras
OCR_ENABLED=true
TTS_ENABLED=true
TTS_RUNTIME=auto
VOICE_ENABLED=true
VOICE_MODEL=baseTTS_RUNTIME=auto uses Qt when it exposes your voice, otherwise the macOS say command (so names like Tessa still work). First OCR or Whisper use downloads models in the background.
source .venv/bin/activate
pytest tests/ -q| Guide | Contents | |
|---|---|---|
| ποΈ | Architecture | Layers, threads, scene states, package map |
| π±οΈ | Usage | Window tour, questions, focus, speech, voice |
| βοΈ | Configuration | Every .env setting and sensible ranges |
| π©Ί | Troubleshooting | Camera, Qt, Ollama, OCR, TTS, Whisper |
| π‘οΈ | Security | Privacy model and how to report issues |
| π | License | MIT License |
Senti is local-first:
- π« Camera frames are never written to disk
- π§ The frame buffer is bounded and in-memory only
- π» YOLO, OCR, Whisper, and the VLM run on-device (Ollama on localhost)
- π‘ No telemetry, no cloud uploads, no account
See SECURITY.md for the threat model and reporting.
Senti/
βββ app/ Application package
β βββ camera/ Qt / AVFoundation capture + in-memory buffer
β βββ detection/ YOLO26 worker
β βββ tracking/ ByteTrack / BoT-SORT monitor
β βββ perception/ Scene change, stability, best-frame selection
β βββ vision/ Local VLM, scheduler, object crops
β βββ scene/ Conversational scene memory
β βββ ocr/ EasyOCR worker
β βββ speech/ Qt TTS + macOS say
β βββ voice/ Push-to-talk + faster-whisper
β βββ ui/ Native desktop window
βββ docs/ Architecture, usage, configuration
β βββ assets/ README graphics (logo, banner, pipeline)
βββ models/ YOLO26 weights (gitignored *.pt / *.npz)
βββ scripts/run.sh Create venv, install, launch
βββ tests/ Unit tests
βββ resources/Info.plist Camera and microphone usage strings
Senti is released under the MIT License.
Copyright (c) 2026 Arshia Keshvari.


