---
version: 0.27.1
title: Voyage multimodal embeddings + image ingestion
date: 2026-05-05
feature_pitch: |
  gbrain remembers what you SAW, not just what you typed. Drop a screenshot,
  whiteboard photo, or iPhone HEIC into your brain repo, run sync, and the
  image lands as a first-class page with a 1024-dim Voyage multimodal
  embedding. Optionally turn on OCR and gpt-4o-mini extracts the visible
  text — whiteboard captures become keyword-searchable in one move.
---

# v0.27.1 migration

`gbrain upgrade` runs `gbrain apply-migrations --yes` automatically, which
applies migration v36. Most users need no manual action.

## What changes

- **Schema**: `content_chunks.modality TEXT NOT NULL DEFAULT 'text'` and
  `content_chunks.embedding_image vector(1024)` with a partial HNSW index.
  Existing text + code chunks continue to work unchanged (modality defaults
  to `'text'`, embedding_image is NULL on those rows).
- **Schema (PGLite)**: the `files` table that v0.18 deliberately omitted
  is added on PGLite. Postgres has had it since v0.18; this is parity.
- **Schema (both)**: `pages.page_kind` CHECK constraint widened to admit
  `'image'`. The migration drops + recreates the auto-named constraint
  idempotently.
- **Off by default**: nothing changes at runtime until you flip
  `embedding_multimodal: true` (DB plane via `gbrain config set` or env via
  `GBRAIN_EMBEDDING_MULTIMODAL=true`).

## Verification

```bash
gbrain apply-migrations --yes
gbrain doctor                # schema_version should be 36+
```

If `gbrain doctor` reports a `schema_version` warning, run apply-migrations
manually and check `~/.gbrain/upgrade-errors.jsonl` for details.

## Enabling multimodal ingestion

The feature is opt-in. To turn it on:

```bash
# Required: switch to Voyage 1024-dim embeddings (or keep your existing
# 1024-dim Voyage brain).
gbrain config set embedding_model voyage:voyage-3-large
gbrain config set embedding_dimensions 1024

# Required: flip the multimodal gate.
gbrain config set embedding_multimodal true

# Optional: enable OCR via gpt-4o-mini (~$0.0003 per image).
gbrain config set embedding_image_ocr true
```

Drop image files (PNG, JPG, JPEG, GIF, WEBP, HEIC, AVIF) into your brain
repo and run `gbrain sync`. The image lands as a `type: image` page with:

- 1024-dim Voyage multimodal embedding in `content_chunks.embedding_image`
- File metadata in the `files` table (storage_path, mime_type, content_hash)
- EXIF metadata in frontmatter (`captured_at`, `gps`, `camera`, `dims`)
- Optional OCR text in `compiled_truth` (when the OCR flag is on)
- Auto-linked `image_of` graph edge to a sibling text page if one exists

## pgvector requirement

Migration v36 requires pgvector >= 0.5.0 on Postgres (HNSW partial indexes).
PGLite ships a recent pgvector inside its WASM bundle, so this gate only
applies to managed-Postgres brains (Supabase, RDS, etc.).

If your provider runs pgvector < 0.5, the migration handler refuses BEFORE
running any DDL with this fix hint:

```sql
ALTER EXTENSION vector UPDATE;
```

Then re-run `gbrain apply-migrations --yes`. If your provider doesn't ship
pgvector >= 0.5 at all, request an upgrade or migrate to PGLite for v0.27.1
multimodal support.

## Cost expectations

- **Voyage multimodal**: free tier covers 200K calls/month. 1 call = 1 image
  (or up to 32 images batched). Beyond the free tier: see Voyage's pricing.
- **OCR via gpt-4o-mini**: ~$0.0003 per image. Off by default; only runs
  when `embedding_image_ocr=true`.
- **Storage**: image bytes never enter the DB. They live on disk in your
  brain repo (the same place markdown lives). Only metadata + embeddings
  go to the database.

## What's NOT included (for v0.27.2+)

- `gbrain query --image <path>` flag for image-similarity search.
- Cross-modal text→image fusion (text query → image hits via RRF).
- PDF page rasterization.
- Video keyframe extraction (waits on Voyage 3.5 multimodal video model).
- OpenAI / Cohere multimodal embed support.
