In one line: the local embedding and NER models download only with your consent. Once the required files are cached and local backends are selected, those inference paths work offline. Explicit hosted providers and other external integrations have separate network behavior.
The default binary ships the semantic layer compiled in (opt-out, ADR-008 §SYN-168), but the model weights are not bundled. This page is the single source of truth for what gets downloaded, from where, to where, how big, and what it means for privacy, licensing, and compatibility.
Which models
Two models, two jobs. Both run locally on CPU via a statically-linked ONNX Runtime: no GPU, no Python, no separate runtime install.
| Job | Default model | Dim / output | Cached size | Languages | Source repo (Hugging Face) | License¹ |
|---|---|---|---|---|---|---|
| Embeddings (vector search) | bge-m3 | 1024-dim | ~2.2 GB | multilingual (en, pt, es, fr, de, it, ja, ko, zh) | BGE-M3 (BAAI), fetched by fastembed from Hugging Face | MIT |
| NER (entity discovery) | gliner-multi | spans | ~350 MB | multilingual | onnx-community/gliner_multi-v2.1 (onnx/model_quantized.onnx) | Apache-2.0 |
Total default footprint: ~2.5 GB (one-time download, shared across every workspace on the machine). The binary itself only grows ~25 MB (the ONNX Runtime).
Quality vs speed: the embedding profile (SYN-237)
The default bge-m3 is fp32: maximum recall, ~2.2 GB. The same model quantised to int8 is a lighter, faster, lower-memory alternative at a small recall cost. The guided syn init asks which you want (Quality is the recommended default); you can also set it directly:
| Profile | embedding_model | Dim | Cached size | Notes |
|---|---|---|---|---|
| Quality (default) | bge-m3 | 1024 | ~2.2 GB | fp32, maximum recall |
| Speed | bge-m3-int8 | 1024 | ~560 MB | int8 (gpahal/bge-m3-onnx-int8), lighter & faster, small recall cost |
Both are multilingual and 1024-dim (the same vector space) so switching is just a re-embed (syn embed --all), never a schema change. With bge-m3-int8 + gliner-multi, the multilingual footprint drops to ~900 MB.
Lighter, English-only opt-downs
Set these in .synapse/config.toml ([enrichment]) if multilingual quality or disk is not worth ~2.5 GB to you:
| Job | Opt-down model | Dim | Cached size | Notes |
|---|---|---|---|---|
| Embeddings | bge-small-en-v1.5-q | 384 | ~65 MB | English-only, quantised, ~5× faster |
| NER | gliner-base-en | spans | ~260 MB | English-only, quantised (onnx-community/gliner_base) |
English opt-down total: ~325 MB. See CONFIGURATION.md for the exact [enrichment] keys.
¹ Licenses are the upstream model-card licenses at time of writing: verify them on the linked model card for your use case; you (not Synapse) are responsible for complying with each model’s terms. ONNX Runtime is MIT-licensed.
Where the models come from
Both models are fetched over HTTPS from the Hugging Face Hub (huggingface.co / its CDN):
- Embeddings: the
fastembedcrate resolvesBGE-M3to its Hugging Face repo and downloads the ONNX file + tokenizer. - NER: Synapse calls the Hugging Face hub client (
hf-hub) directly foronnx/model_quantized.onnx+tokenizer.jsonfrom the repo above.
The fetch is anonymous: no Hugging Face account or token is needed for these public repos. As with any HTTPS request, Hugging Face’s servers see your IP address and a user-agent for the duration of the download; no information about your workspace, notes, or queries is ever sent: Synapse only issues GETs for model files.
Both transports use rustls (not system OpenSSL), so musl/Alpine and minimal containers work without extra system libraries.
Where they’re cached
Downloads land in a per-OS cache directory and are reused across every workspace on the machine (sharing is intentional: you download BGE-M3 once, not once per brain):
| OS | Default model cache |
|---|---|
| macOS | ~/Library/Caches/synapse/models/ |
| Linux | ${XDG_CACHE_HOME:-~/.cache}/synapse/models/ |
| Windows | %LOCALAPPDATA%\synapse\models\ |
Inside it: …/models/fastembed/… (embeddings) and …/models/gliner/<repo>/… (NER). A small .synapse-ready-<model> sentinel marks a model as fully downloaded; that file is how a write or search knows the model is present without trying to fetch it (SYN-168).
Override the location (precedence: config → env):
# .synapse/config.toml (or any config layer)
[enrichment]
model_cache_dir = "/data/synapse-models"
SYNAPSE_MODEL_CACHE=/data/synapse-models syn embed --all
Point both at the same shared path (e.g. an NFS mount or a team image) to provision a fleet from one download.
When they download (consent, never ambush)
The models are pulled only on an explicit action: never silently on your first syn project add:
syn initonboarding: on an interactive terminal, a freshsyn initasks “Download the models now? [Y/n]”. Decline and it explains exactly what you keep and lose; you can change your mind later.syn embed --all: the explicit “turn it on now” command; downloads on first run, then embeds the whole workspace.
Until a model is present, Synapse degrades gracefully: writes still save (without embeddings), and syn search falls back to fast keyword (FTS5) + graph. Check the state any time; this command is read-only and never triggers a download:
syn embed --check # … models_ready: false → not downloaded yet
Offline & air-gapped use
With the required model files cached and a local backend selected, embedding and NER inference run on device without sending note/query text to a model provider. Changing models or explicitly refreshing an incomplete cache can require another consented download.
This scope covers the local model path. Explicit hosted providers, remote source adapters and an external MCP client or host have separate network behavior. An air-gapped deployment must select local providers and configure those other paths accordingly.
For machines that must never reach huggingface.co:
- Pre-seed the cache. Download the models on a connected machine, then copy the cache directory (see table above) to the target, or point
SYNAPSE_MODEL_CACHEat a pre-populated shared path. The.synapse-ready-*sentinels travel with it. - Run without models. Set
[enrichment] mode = "off"(orSYNAPSE_ENRICHMENT_MODE=offper command) to skip the pipeline entirely, and usesyn search --no-vectorfor keyword + graph search with zero model load.
Enrichment is one-way: reindex drops inferred links (SYN-271)
Enrichment edges (the inferred mentions / references graph links and the vector embeddings) are produced at write time, not by reindex. reindex rebuilds the deterministic projection of your Markdown (entities, tags, structural links from frontmatter); it does not re-run the linker or the models. Two consequences:
- A
reindex --full(a from-scratch rebuild) drops the inferredmentions/referencesedges until they are re-derived. - Entities created before you downloaded the models have fewer inferred links than those created after.
This is a disposability property, not an integrity problem: syn verify deliberately excludes enrichment edges from its canonical dump (they are model/heuristic-derived, not a pure function of reindex(markdown)), so a rebuilt index still verifies clean.
To restore the heuristic inferred links (slug / @mention / URL: deterministic, model-free, offline) after a --full rebuild:
syn reindex --relink # re-derive mentions / references edges; never re-runs NER, never creates entities
--relink is idempotent and queues no proposals: it only re-creates links to entities that already exist. The NER-derived mentions:<kind> edges come back on the next write of each entity (or a re-embed), since they need the model.
What touches the network (and what never does)
| Path | Local backend (default) | Hosted backend (opt-in) |
|---|---|---|
| Model download | Explicit HTTPS GET from Hugging Face when required assets are absent or change | No local embedding model required |
| Embedding a write or query | Cached local-model inference does not send entity/query text to a model provider | Sends the supplied entity/query text to the selected provider |
Local inference is the default (BR-13). Under that model path, Synapse does not send your note, entity or query text to an embedding provider. This is a boundary of local model execution, not a blanket promise about hosted backends, configured remote source adapters or the application consuming MCP results. Synapse has no built-in telemetry.
The hosted backends (network_backends feature: OpenAI / Voyage) are opt-in and require
an explicit [enrichment] provider. Enabling one sends text to that provider when the
configured embedding operation runs, including supported writes and semantic queries.
syn init warns when a network provider is active. See IDENTITY.md and
CONFIGURATION.md for configuration and egress details.
Compatibility
- CPU-only. The models run on the CPU via ONNX Runtime; no GPU or CUDA is required or used.
- Platforms. macOS (Apple Silicon only: the ONNX Runtime has no Intel-macOS build, so
x86_64-apple-darwinis unsupported; ROADMAP SYN-174), Linux (x86_64 + aarch64), Windows (x86_64). - Linux glibc ≥ 2.38. The prebuilt ONNX Runtime that ships with the semantic layer is linked against glibc ≥ 2.38 and GCC 13+ libstdc++. Practically: Ubuntu 24.04+, Debian 13 (Trixie)+, Fedora 39+ and equivalents. Older distros (Ubuntu 20.04/22.04, Debian 12) lack the symbols (
__isoc23_strtol,__cxa_call_terminate) and the binary will not run there: build a core binary (--no-default-features --features mcp) for those, or upgrade the base. (This is also why the release pipeline builds the Linux artifacts onubuntu-24.04runners: SYN-168.) - Disk. Budget ~2.5 GB for the multilingual defaults (~325 MB for the English opt-downs) in the cache directory, plus ~25 MB in the binary.
- First use and latency. Download time depends on the selected models, cache and connection. Inference time depends on hardware, text length and batch size. Measure the chosen configuration before setting a latency target.
Managing the cache
syn embed --check # cache state (read-only; models_ready flag)
syn embed --all # download (if needed) + embed everything; idempotent
syn embed --reset-cache # drop every vector + meta row (forces a clean re-embed)
Switching models. Change embedding_model / ner_model in .synapse/config.toml, then syn embed --all: it re-embeds only the rows whose stored model id no longer matches. To reclaim disk from a model you no longer use, delete its sub-directory under the model cache (see table) by hand; Synapse never deletes downloaded weights on its own.
See also
- INSTALL.md: feature flags, opting out, the footprint table.
- CONFIGURATION.md: the
[enrichment]block, cache-path override, env vars. - ADR-008: why BGE-M3 + GLiNER + sqlite-vec, and the opt-out amendment.
- IDENTITY.md: the opt-in hosted providers and their privacy trade-off.