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

> Learn how to set up local vector embeddings for code-review-graph semantic search. Install the embeddings extra, select the local provider, and build vectors offline with Sentence-Transformers and SQLite.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-08-07

---

**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`](https://github.com/tirth8205/code-review-graph/blob/main/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:

```bash
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`](https://github.com/tirth8205/code-review-graph/blob/main/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:

```bash
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:

```bash
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:

```python
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`](https://github.com/tirth8205/code-review-graph/blob/main/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)`:

```bash
code-review-graph build

```

For incremental updates after initial setup:

```bash
code-review-graph update

```

These commands invoke `GraphStore._create_embeddings_table` (referenced from [`code_review_graph/graph.py`](https://github.com/tirth8205/code-review-graph/blob/main/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:

```bash
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.

## Query with Semantic Search

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`](https://github.com/tirth8205/code-review-graph/blob/main/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:**

```bash
code-review-graph search "authentication token"

```

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

```python

# 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:**

```bash
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`:

```bash
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:**

```bash
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`](https://github.com/tirth8205/code-review-graph/blob/main/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`](https://github.com/tirth8205/code-review-graph/blob/main/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.