How to Set Up Local Vector Embeddings for code-review-graph Semantic Search

To enable offline semantic search in code-review-graph, install the [embeddings] extra, ensure the local provider is selected, and run code-review-graph build to generate Sentence-Transformer vectors stored in SQLite.

The code-review-graph repository by tirth8205 supports dense vector embeddings for semantic code search without requiring external API keys or network access. By using the LocalEmbeddingProvider implemented in code_review_graph/embeddings.py, you can generate embeddings entirely offline using open-source Sentence-Transformers models. This guide walks through the exact steps to configure, build, and verify local embeddings for your codebase graph.

Install the Optional Embeddings Dependency

The core package does not include the heavy PyTorch and Sentence-Transformers dependencies. You must install the optional embeddings extra to enable local vector generation:

pip install "code-review-graph[embeddings]"

# Or with uv:

uv pip install "code-review-graph[embeddings]"

This pulls in sentence_transformers and its backend, registering the LocalEmbeddingProvider class located at lines 13–80 of code_review_graph/embeddings.py. Without this extra, attempting to use local embeddings raises an ImportError.

Configure the Local Provider and Model

By default, the system uses cloud providers if API keys are present. To force local embeddings, ensure no cloud provider environment variables (like GOOGLE_API_KEY or MINIMAX_API_KEY) are set, or explicitly configure the provider via your environment:

export CRG_EMBEDDING_PROVIDER=local
export CRG_EMBEDDING_MODEL="all-MiniLM-L6-v2"  # Optional: override default model

The LocalEmbeddingProvider uses all-MiniLM-L6-v2 by default. The chosen model name is stored in the provider’s name property (formatted as local:<model>), which appears in tool outputs to ensure vector space consistency.

Select a Sentence-Transformers Model (Optional)

You can switch to a larger model for potentially better accuracy at the cost of speed:

export CRG_EMBEDDING_MODEL="all-MiniLM-L12-v2"

When you change models, you must re-embed the graph to avoid mixing vector spaces (see the Force Re-embedding section below).

Pre-warm the Model to Avoid Deadlocks

On Windows, lazy-loading the Sentence-Transformers model inside an async worker can cause deadlocks. The codebase provides a pre-warming utility that loads the model on the main thread before any async operations begin:

from code_review_graph.embeddings import prewarm_local_embeddings

prewarm_local_embeddings()  # Loads model into _MODEL_CACHE

The code-review-graph serve and code-review-graph build commands automatically invoke this for you. If you are embedding the library in a custom long-running process, call this function explicitly before starting async work. The model is cached process-wide (see the lock logic around lines 30–40 of embeddings.py) to prevent repeated expensive imports.

Build the Graph and Generate Embeddings

Once dependencies are installed and configured, generate embeddings by building the graph. This parses your source files and calls the provider to embed every identifier (function names, class names, docstrings, etc.), storing results in the SQLite table embeddings(qualified_name TEXT PRIMARY KEY, vector BLOB):

code-review-graph build

For incremental updates after initial setup:

code-review-graph update

These commands invoke GraphStore._create_embeddings_table (referenced from code_review_graph/graph.py) and populate it with vectors from the LocalEmbeddingProvider.

Force Re-embedding After Model Changes

If you switch embedding models or suspect vector corruption, purge and rebuild the embedding table explicitly:

code-review-graph embed \
    --provider local \
    --model "${CRG_EMBEDDING_MODEL:-all-MiniLM-L6-v2}"

This command is a thin wrapper around the embed_graph_tool MCP tool; it clears the old embeddings table and re-populates it with vectors from the selected provider.

With vectors stored, you can perform semantic search via the CLI or MCP tools. The semantic_search_nodes_tool (defined in code_review_graph/mcp_tools/semantic_search_nodes_tool.py) performs a hybrid search combining SQLite FTS5 and cosine similarity over the vector column:

CLI shortcut:

code-review-graph search "authentication token"

MCP client (e.g., Claude Code, Cursor):


# Tool invocation via MCP client

semantic_search_nodes_tool(query="database connection logic")

Both methods return the nearest nodes according to cosine similarity against the query embedding generated by the local provider.

Verify Your Local Embedding Setup

Confirm the setup is working correctly using these verification steps:

Check provider status:

code-review-graph status | grep embedding

# Expected: "embedding provider: local:all-MiniLM-L6-v2"

Inspect the database:

Query the SQLite store directly to verify vector storage. The vector column contains float32 blobs; length should equal dimension * 4:

sqlite3 .code-review-graph/graph.db \
  "SELECT qualified_name, LENGTH(vector) FROM embeddings LIMIT 5;"

# Expected length: 384 bytes for a 96-dim model (or 1536 bytes for 384-dim models like all-MiniLM-L6-v2)

Run unit tests:

pytest -q tests/test_embeddings.py

All tests should pass when the optional dependency is correctly installed.

Troubleshooting Common Issues

Symptom Cause Solution
ImportError: sentence-transformers not installed Missing optional dependency Run pip install "code-review-graph[embeddings]"
Dead-lock on Windows during first embed Lazy import inside async context Call prewarm_local_embeddings() before async code, or use code-review-graph build which handles this automatically
"Unknown embedding provider" error Environment variable points to cloud provider Unset cloud API keys or explicitly set CRG_EMBEDDING_PROVIDER=local
Mixed or incorrect search results after model switch Old vectors from previous model remain in DB Run code-review-graph embed --provider local --model <new> to purge and rebuild

Summary

  • Install the extra: Use pip install "code-review-graph[embeddings]" to get Sentence-Transformers and PyTorch support.
  • Select local mode: Ensure CRG_EMBEDDING_PROVIDER is not set to a cloud provider, or explicitly configure it; optionally set CRG_EMBEDDING_MODEL to choose a specific model.
  • Pre-warm on Windows: Call prewarm_local_embeddings() to prevent async deadlocks, or rely on the CLI commands which handle this automatically.
  • Build to embed: Run code-review-graph build to parse code and populate the SQLite embeddings table with vectors.
  • Search offline: Use code-review-graph search "<query>" or the semantic_search_nodes_tool MCP tool to perform hybrid semantic search without API calls.

Frequently Asked Questions

Do I need an internet connection to use local embeddings?

No. After the initial download of the Sentence-Transformers model (cached locally), the LocalEmbeddingProvider in code_review_graph/embeddings.py generates vectors completely offline. No API keys or network traffic are required for embedding generation or semantic search queries.

How do I switch to a different embedding model?

Set the CRG_EMBEDDING_MODEL environment variable to any Hugging Face Sentence-Transformers model name (e.g., all-MiniLM-L12-v2), then run code-review-graph embed --provider local --model <name> to rebuild the vector table. The provider stores the model identifier in the name property to prevent accidental mixing of different vector spaces.

Why is my Windows build freezing on first run?

The first lazy import of sentence_transformers inside an async worker can deadlock on Windows due to PyTorch import locks. The codebase mitigates this via prewarm_local_embeddings(), which loads the model into the process-wide _MODEL_CACHE on the main thread before any async workers start. Running code-review-graph build automatically handles this pre-warming for you.

Where are the embedding vectors actually stored?

Vectors are stored as BLOBs in the SQLite table embeddings, created by GraphStore._create_embeddings_table in code_review_graph/graph.py. Each row maps a qualified_name (the code identifier) to its dense vector. The semantic_search_nodes_tool queries this table using a hybrid of FTS5 full-text search and vector cosine similarity.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →