Repository navigation
v2.1.4 - feat: embed model swap + semantic search + UMAP canvas #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| ## What's new | ||
|
|
||
| ### Features | ||
|
|
||
| - **Embedding model swap — Nomic → bge-small-en-v1.5**: Replaced `nomic-ai/nomic-embed-text-v1.5` (137 MB, 768-dim, 8K context) with `Xenova/bge-small-en-v1.5` (33 MB, 384-dim, 512 context). Same MTEB quality score (~62) with 4× smaller download, 5× less peak memory, and 3–26× faster inference depending on text size. Since Cairn chunks notes at ≤4KB anyway, the 512-token context limit is not a constraint. | ||
|
|
||
| - **Automatic orphan model cleanup**: When the Embeddings settings panel opens, orphaned model directories (models no longer in `SUPPORTED_EMBEDDING_MODELS`) are automatically pruned from disk. Users upgrading from v2.1.3 will have the old 137 MB Nomic model silently removed with a console log — no manual cleanup needed. | ||
|
|
||
| - **Migrated to @huggingface/transformers v4**: Replaced the deprecated `@xenova/transformers` (v2) with the official `@huggingface/transformers` v4.2.0. Brings 120+ architecture support, improved quantization options (q4, q4f16, int8, uint8, bnb4), and ongoing maintenance from the Hugging Face team. The sharp stub continues to work — the stub exports a truthy no-op function so transformers.js's image module passes its `else if (sharp)` check without pulling in the native binary. | ||
|
|
||
| ### Changes | ||
|
|
||
| - **Dropped Intel macOS (darwin-x64) build target**: `onnxruntime-node` 1.24.3 (required by `@huggingface/transformers` v4) no longer ships a `darwin-x64` prebuilt binary. The macOS build target in `electron-builder.yml` is now `arm64` only. Apple Silicon Macs (M1+, shipped since 2020) are fully supported; Intel Mac users should stay on v2.1.3. | ||
|
|
||
| - **Embedding dimension changed from 768 to 384**: Existing note embeddings stored with the old Nomic model are automatically detected as stale (model ID mismatch in `reindexNotes`) and will be re-embedded with bge-small on the next reindex. No manual intervention or DB migration required — the `vector` column is `TEXT` (JSON-serialized) and handles any dimension. | ||
|
|
||
| - **Reindex prompt on startup**: When the app starts with embeddings enabled and detects that existing note embeddings were created with a different model (e.g. Nomic → bge-small), a modal prompts the user to reindex their notes. Shows progress (note count, percentage) and includes a "Later" dismiss button. The modal stays hidden if embeddings are disabled or all embeddings match the current model. | ||
|
|
||
| - **bge-small query prefix**: bge-small-en-v1.5 uses a different query instruction than Nomic. Search queries are prefixed with `Represent this sentence for searching relevant passages:` instead of Nomic's `search_query: ` prefix. Document embedding uses no prefix (Nomic used `search_document: `). | ||
|
|
||
| - **Embeddings onboarding step**: New onboarding step (between MCP and Views) lets new users enable local semantic embeddings and download the model (~33 MB) before their first note is indexed. Real-time download progress bar driven by the existing `embeddings:download-progress` IPC stream. Returning users see their saved preference. Settings can be changed later in Settings → Embeddings. | ||
|
|
||
| - **Semantic search in global ⌘K panel**: The search panel now has a Sparkles toggle (between the clear button and ESC kbd). When enabled and embeddings are ready, queries debounce (250 ms) through `embeddings.search` and results are merged with keyword `searchAll` hits (deduped by note id; semantic-only hits show the matching section title). Each semantic hit shows a cosine score badge (e.g. "Sparkles 87%"). Falls back silently to keyword-only if the worker is down. Preference persisted in `localStorage` under `search.semanticMode`. | ||
|
|
||
| - **`search_notes_semantic` MCP tool**: New read-only MCP tool exposed to Claude Desktop, Cursor, OpenCode, and the in-app Cairn agent. Schema: `{ workspaceId, query, k? }` (default k=5). Embeds the query via the local bge-small model and returns matching notes with similarity scores and matching section titles — better than `search_notes` when concepts are described in different words (e.g. query "auth flow" finds a note titled "Login pipeline"). Refuses gracefully if embeddings are disabled. Added to both the default and plan-mode tool allowlists. | ||
|
|
||
| - **Semantic Map canvas (Insights)**: New "Semantic Map" layout in the Insights view. Plots every embedded note as a dot positioned by its 2D UMAP projection (`dim_x` / `dim_y`), coloured by project. Pan via drag, zoom via wheel or +/− controls, reset via ⟲. Tooltips show note title, project, and model. Both empty-state (no projections yet) and stale-state (some rows have `proj_stale=1`) show a "Compute/Recompute projections" button that runs UMAP inline via the existing `embeddings.recomputeProjections` IPC, with live progress bar driven by the `embeddings:download-progress` broadcast. New IPC channel `embeddings:projections` exposes the projection table to the renderer. | ||
|
|
||
| - **`recomputeProjections` exposed in the UI**: Previously UMAP projection recomputation was only reachable via a manual button in Settings → Embeddings with no display consumer. Now surfaced inline on the Semantic Map canvas (both empty state and toolbar), giving users a compelling visualization that justifies the compute. | ||
|
|
||
| ### Fixes | ||
|
|
||
| - **Sharp stub must be truthy**: The sharp stub previously exported `null` (falsy), which caused transformers.js's `image.js` module to throw `Unable to load image processing library` — crashing the embeddings worker at startup on Node 25 (which doesn't define `self`, so the browser branch is also skipped). Fixed by exporting a function (truthy, matching sharp's callable API shape) that throws if ever called. Cairn never invokes it — only text tokenization is used. | ||
|
|
||
| - **`get_semantic_neighbors` now reachable via chat**: The in-app chat executor was missing a routing case for `get_semantic_neighbors`, so calls to this MCP tool from the AI chat would fall through to "Unknown tool". Added to the `executeMcpTool` dispatch group alongside `get_knowledge_graph` and `get_neighbors`. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import type { EmbedTask } from "./types"; | ||
|
|
||
| export function withTaskPrefix(task: EmbedTask, text: string): string { | ||
| switch (task) { | ||
| case "search_query": | ||
| return `Represent this sentence for searching relevant passages: ${text}`; | ||
| case "search_document": | ||
| case "clustering": | ||
| default: | ||
| return text; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.