# How to Set Up Semantic Search with Vector Embeddings in code-review-graph

> Learn to set up semantic search with vector embeddings in code-review-graph. Embed your knowledge graph and query code insights effortlessly using dedicated tools or the Python API.

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

---

**To set up semantic search with vector embeddings in code-review-graph, configure an embedding provider (local or cloud), run `embed_graph_tool` to vectorize your code knowledge graph, and query using `semantic_search_nodes_tool` or the Python `semantic_search` API.**

The `code-review-graph` repository ships a production-ready semantic search pipeline that transforms your code knowledge graph into searchable vector embeddings. This system uses a pluggable provider architecture to support both offline local models and cloud-based APIs, storing dense vectors in SQLite with optimized cosine-similarity retrieval. Whether you need privacy-preserving local inference or high-performance cloud embeddings, the setup follows a consistent three-step workflow: provider configuration, index building, and semantic querying.

## Prerequisites and Installation

Install the package with the optional embeddings extra to include `sentence-transformers` and vector dependencies:

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

```

This installs the base library plus all requirements for local embedding generation. Cloud providers (OpenAI, Google Gemini, MiniMax) require only API key configuration and no additional packages.

## Step 1 — Configure an Embedding Provider

The system uses the abstract `EmbeddingProvider` base class defined in [`code_review_graph/embeddings.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/embeddings.py), with concrete implementations for local and cloud inference. Choose one provider based on your privacy and latency requirements.

### Local Provider (Offline, Fast)

The local provider uses `sentence-transformers` models and runs entirely on your hardware. No API keys or network calls are required.

**Optional Windows optimization:** To prevent threading deadlocks on Windows, pre-warm the model on the main thread before parallel operations:

```python
from code_review_graph.embeddings import prewarm_local_embeddings

prewarm_local_embeddings()  # Uses CRG_EMBEDDING_MODEL env var or default model

```

If `CRG_EMBEDDING_MODEL` is unset, the system defaults to a lightweight multilingual model suitable for code semantics.

### OpenAI-Compatible Provider (Cloud)

For higher-quality embeddings or GPU acceleration, configure an OpenAI-compatible endpoint by setting three environment variables:

```bash
export CRG_OPENAI_API_KEY=sk-your-key-here
export CRG_OPENAI_BASE_URL=https://api.openai.com/v1
export CRG_OPENAI_MODEL=text-embedding-3-small

```

This pattern supports OpenAI, Azure OpenAI, and LiteLLM proxy endpoints. The same configuration structure applies to **Google Gemini** (`GOOGLE_API_KEY`) and **MiniMax** (`MINIMAX_API_KEY`) providers.

**Security note:** On first use, the library warns that source code will be transmitted to external APIs. Set `CRG_ACCEPT_CLOUD_EMBEDDINGS=1` to acknowledge and suppress this warning.

## Step 2 — Build the Vector Index

Generate embeddings for every node in your knowledge graph using the CLI tool or Python API. The CLI approach is fastest for initial setup:

```bash

# Use default local provider

crg embed_graph_tool

# Or specify a cloud provider explicitly

crg embed_graph_tool --provider openai --model text-embedding-3-small

```

Under the hood, `embed_graph_tool` (defined in [`code_review_graph/main.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/main.py)) invokes `embed_graph` → `EmbeddingStore.embed_nodes`, which performs the following operations:

1. **Serializes nodes** using `_node_to_text` (lines 180–188 in [`embeddings.py`](https://github.com/tirth8205/code-review-graph/blob/main/embeddings.py)) to convert graph nodes into searchable text representations.
2. **Hashes** the serialized text to detect content changes and avoid redundant API calls.
3. **Batches embedding requests** via `provider.embed(texts)` for efficient throughput.
4. **Persists vectors** using `_encode_vector` to store binary-encoded embeddings alongside the content hash and provider identity in the SQLite `embeddings` table.

The provider name (`provider.name`) is stored with each vector, ensuring that switching models or providers automatically invalidates stale embeddings and triggers re-processing.

## Step 3 — Query the Semantic Index

Search your vectorized codebase using natural language queries:

```bash
crg semantic_search_nodes_tool "create user session" --limit 10

```

The `semantic_search_nodes_tool` (implemented in [`code_review_graph/tools/query.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/tools/query.py)) executes the following logic:

- Generates a query vector via `provider.embed_query`.
- Retrieves all stored vectors for the active provider using `SELECT qualified_name, vector FROM embeddings WHERE provider = ?`.
- Computes cosine similarity via `_cosine_similarity` and ranks results by semantic relevance.
- Returns the top-N matches with similarity scores.

If no embeddings exist for the configured provider or the vector store is unavailable, the system gracefully degrades to the built-in FTS5 keyword search (`graph.search_nodes`) without raising errors.

## Python API Implementation

For programmatic access or custom pipelines, use the `EmbeddingStore` and `semantic_search` functions directly:

```python
from pathlib import Path
from code_review_graph.embeddings import EmbeddingStore, get_provider, semantic_search
from code_review_graph.graph import GraphStore, embed_all_nodes

# 1. Load existing graph database

graph = GraphStore(Path("graph.db"))

# 2. Initialize embedding store with local provider

store = EmbeddingStore(
    db_path=Path("embeddings.db"),
    provider="local",           # Options: "local", "openai", "google", "minimax"

    model="all-MiniLM-L6-v2",   # Optional; overrides env var defaults

)

# 3. Generate embeddings for all nodes (idempotent with hash checking)

embed_all_nodes(graph, store)

# 4. Execute semantic query

results = semantic_search(
    query="authentication token validation",
    graph_store=graph,
    embedding_store=store,
    limit=5,
)

for hit in results:
    print(f"{hit['qualified_name']}: {hit['similarity_score']:.3f}")

```

The `EmbeddingStore` class handles vector encoding/decoding, schema management (`_EMBEDDINGS_SCHEMA`), and similarity computation, while `semantic_search` orchestrates the query embedding and result ranking.

## Summary

- **Install** with `pip install "code-review-graph[embeddings]"` to include local embedding dependencies.
- **Configure** your provider via environment variables for cloud APIs or use the zero-config local provider.
- **Index** your graph once using `crg embed_graph_tool` or `embed_all_nodes()`; the system hashes content to avoid redundant work when re-indexing.
- **Query** via CLI (`semantic_search_nodes_tool`) or Python API (`semantic_search`), with automatic fallback to FTS5 keyword search if vectors are unavailable.
- **Monitor** the [`embeddings.py`](https://github.com/tirth8205/code-review-graph/blob/main/embeddings.py) file for provider implementations and [`tools/query.py`](https://github.com/tirth8205/code-review-graph/blob/main/tools/query.py) for search orchestration logic.

## Frequently Asked Questions

### How do I switch from local embeddings to OpenAI without re-indexing everything?

You must re-index when switching providers. The `EmbeddingStore` schema includes the provider name in each row (see `_EMBEDDINGS_SCHEMA` in [`embeddings.py`](https://github.com/tirth8205/code-review-graph/blob/main/embeddings.py)), and `refresh_embeddings` checks this field to invalidate stale vectors. Run `crg embed_graph_tool --provider openai` to generate new embeddings for the new backend.

### What happens if I search before building the vector index?

The `semantic_search_nodes_tool` automatically falls back to FTS5 keyword search via `graph.search_nodes` if no embeddings exist for the configured provider. This ensures the CLI remains functional during initial setup, though results will use lexical rather than semantic matching until you run `embed_graph_tool`.

### Why am I seeing Windows deadlock errors with local embeddings?

Local embedding generation uses `sentence-transformers` multi-threading that can deadlock on Windows if the model isn't loaded on the main thread first. Call `prewarm_local_embeddings()` from [`code_review_graph/embeddings.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/embeddings.py) before any parallel operations to load the transformer model into memory safely.

### Can I use different embedding models for different parts of the codebase?

No, the current `EmbeddingStore` implementation assumes a single active provider per database file. The `provider` parameter in `EmbeddingStore.__init__` sets the backend for all operations, and the SQLite schema filters queries by provider name. To use multiple models simultaneously, maintain separate `embeddings.db` files for each model configuration.