# How vitali87/code-graph-rag Generates Cypher Queries from Natural Language

> Discover how vitali87/code-graph-rag transforms natural language into Cypher queries. Learn about its five-step pipeline combining LLMs and post-processing for accurate results.

- Repository: [Vitali Avagyan/code-graph-rag](https://github.com/vitali87/code-graph-rag)
- Tags: how-to-guide
- Published: 2026-08-16

---

**`code-graph-rag` translates plain English questions into executable Cypher queries through a five-step pipeline that combines few-shot prompting, LLM inference, and post-processing validation.**

The open-source `code-graph-rag` project provides a retrieval-augmented generation (RAG) system for codebases stored in graph databases. At its core lies a **natural language to Cypher** translation mechanism that lets developers query their code's knowledge graph using everyday English rather than graph query syntax.

## The 5-Step Query Generation Pipeline

### 1. Capture the Request via CLI or SDK

User input enters the system through either the command-line interface or programmatic SDK. In [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py), the CLI receives raw text such as *"Show me all functions that call UserService.create_user"* and forwards it to the translation layer.

```python

# Example usage pattern from the SDK documentation

from cgr import CypherGenerator

generator = CypherGenerator()
cypher = generator.generate(
    "Find all functions that call UserService.create_user"
)

```

### 2. Build a Few-Shot Prompt

The `CypherGenerator` class relies on `PromptBuilder` (defined in [`codebase_rag/prompts.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/prompts.py)) to assemble a structured chat prompt containing:

- **System instruction**: Explains the NL→Cypher translation task
- **Few-shot examples**: Concrete question/query pairs from `CYPHER_EXAMPLE_PAIRS` in [`codebase_rag/cypher_queries.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cypher_queries.py)
- **User question**: The actual natural language input

These examples anchor the LLM to the project's specific graph schema and query patterns.

### 3. Invoke the LLM

The prompt passes to the generic `LLM` abstraction exposed in [`cgr/__init__.py`](https://github.com/vitali87/code-graph-rag/blob/main/cgr/__init__.py). The default implementation calls `self.llm.chat_completion()` with the constructed messages, routing to whichever provider is configured (OpenAI, Anthropic, etc.).

```python

# Simplified structure from the implementation

class CypherGenerator:
    def __init__(self, llm=None):
        self.llm = llm or DefaultLLM()
        self.prompt_builder = PromptBuilder()

    def generate(self, natural_language: str) -> str:
        prompt = self.prompt_builder.build(
            user_question=natural_language,
            examples=CYPHER_EXAMPLE_PAIRS  # few-shot anchors

        )
        response = self.llm.chat_completion(messages=prompt)
        return self._post_process(response.content)

```

### 4. Post-Process and Validate

Raw LLM output undergoes sanitization in [`codebase_rag/cypher_queries.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cypher_queries.py):

- Markdown fences (```cypher ... ```) are stripped
- Output is validated against **whitelisted Cypher patterns** defined in constants like `CYPHER_FIND_BY_QUALIFIED_NAME`
- Optional formatting (line-break normalization) is applied

This validation layer prevents malformed or potentially unsafe queries from reaching the database.

### 5. Execute Against Memgraph

The validated Cypher query ships to [`codebase_rag/services/graph_service.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/graph_service.py), which interfaces with the **Memgraph** backend. Results return to the user as structured code intelligence.

## Core Implementation Files

| File | Responsibility |
|------|---------------|
| [`codebase_rag/cypher_queries.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cypher_queries.py) | Cypher templates, example pairs (`CYPHER_EXAMPLE_PAIRS`), and validation logic |
| [`codebase_rag/prompts.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/prompts.py) | Prompt assembly templates and instruction formatting |
| [`cgr/__init__.py`](https://github.com/vitali87/code-graph-rag/blob/main/cgr/__init__.py) | Public API exposing `CypherGenerator` and `LLM` abstraction |
| [`codebase_rag/cli.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cli.py) | CLI entry point for natural language input |
| [`codebase_rag/services/graph_service.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/graph_service.py) | Query execution against Memgraph |

## Why Few-Shot Examples Matter

The `CYPHER_EXAMPLE_PAIRS` constant is the project's secret sauce. By embedding concrete English→Cypher mappings directly into each prompt, `code-graph-rag` achieves **schema-constrained generation** without fine-tuning. The LLM sees patterns like:

```python

# Conceptual example from cypher_queries.py structure

CYPHER_EXAMPLE_PAIRS = [
    {
        "question": "Find all functions that call UserService.create_user",
        "cypher": "MATCH (c:Function)-[:CALLS]->(t:Function {name: 'create_user', class: 'UserService'}) RETURN c"
    },
    # ... additional domain-specific examples

]

```

This approach outperforms zero-shot prompting on specialized graph schemas while remaining portable across LLM providers.

## Summary

- **`CypherGenerator`** is the primary interface for natural language to Cypher translation
- The pipeline follows **capture → prompt → LLM → validate → execute** stages
- **Few-shot examples** from [`codebase_rag/cypher_queries.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cypher_queries.py) ground the LLM in the codebase's graph schema
- **Post-processing validation** ensures only safe, pattern-matched queries reach Memgraph
- The architecture abstracts LLM providers through [`cgr/__init__.py`](https://github.com/vitali87/code-graph-rag/blob/main/cgr/__init__.py) for flexibility

## Frequently Asked Questions

### What LLM providers does code-graph-rag support?

The project uses a generic `LLM` abstraction layer in [`cgr/__init__.py`](https://github.com/vitali87/code-graph-rag/blob/main/cgr/__init__.py) that can wrap any provider implementing the `chat_completion` interface. OpenAI and Anthropic Claude are commonly configured, though the exact supported list depends on your installation's dependencies.

### How does the system prevent invalid Cypher queries?

Generated queries pass through a **whitelist validator** defined in [`codebase_rag/cypher_queries.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cypher_queries.py). The system checks against allowed patterns (such as `CYPHER_FIND_BY_QUALIFIED_NAME`) and strips extraneous formatting before execution. Queries failing validation are rejected before reaching the Memgraph backend.

### Can I customize the few-shot examples for my codebase?

Yes. The `CYPHER_EXAMPLE_PAIRS` constant in [`codebase_rag/cypher_queries.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/cypher_queries.py) is the designated extension point. Adding question→query pairs specific to your graph's node labels, relationship types, and property conventions improves translation accuracy without modifying core logic.

### Where is the Cypher query actually executed?

Execution happens in [`codebase_rag/services/graph_service.py`](https://github.com/vitali87/code-graph-rag/blob/main/codebase_rag/services/graph_service.py), which manages connections to **Memgraph**. This service receives the validated Cypher string, runs it against the knowledge graph, and formats results for the CLI or calling application.