Building Knowledge Graph RAG solution from Model Driven Engeneering – Part 1

knowledge graph

Building Knowledge Graphs for RAG from Famix Models

Large Language Models (LLMs) are impressively good at understanding code — but they also hallucinate. When reasoning about an unfamiliar codebase, an LLM can fabricate methods, classes, or relationships that don’t exist. This is a real problem when we ask them to help us navigate, understand, or modify software.

The usual remedy is Retrieval-Augmented Generation (RAG) : instead of relying only on what the model “remembers”, we feed it relevant contextual documents at query time. But standard RAG has a blind spot when it comes to code: source code is text full of self-references that describe complex behavior. In this post we show how Model-Driven Engineering (MDE) – specifically the Moose platform and its Famix models — can help us.

The problem with text-based RAG for code

Classic RAG stores documents and hands them to the LLM without any explicit relationships between them. Each chunk of text lives in isolation. For prose, that is often fine. For code, it throws away exactly the information that matters most: the structure.

Knowledge-Graph-based RAG (KG-RAG) could be a fitting solution. Instead of a flat pile of documents, KG-RAG models the relationships between pieces of knowledge in a graph, so retrieval can follow connections and provide the LLM with much richer context.

There’s a catch, though. Most current KG-RAG implementations build that graph by running an LLM over text or chunks to infer entities and their relationships. When the documents are source code, this is wasteful and error-prone: the codebase already contains explicit, reliable links — method calls, inheritance, exception handling — and instead of using them, these systems try to guess them from text. The result is a graph that is often noisier and less trustworthy than it needs to be.

Our idea: let the code’s model build the graph

Source code is already a highly structured artifact. Why infer relationships from text when a program analysis platform can give them to us directly?

This is where Moose and Famix come in. Moose is a software analysis platform, and Famix is its language-independent meta-model for representing code. From a Famix model we get, for free and with high fidelity, the structural and behavioral relationships of a codebase: which method calls which; which class declares which attribute; which exceptions are thrown, declared, or caught.

Our proposal is to build the knowledge graph for RAG directly from the Famix model, rather than re-deriving it from text with an LLM. To the best of our knowledge, no prior work leverages MDE models to build knowledge graphs for RAG pipelines — even though the broader research trend in code retrieval is clearly moving away from pure text search and toward structure-aware retrieval. The lesson from related work is consistent: effective retrieval for code depends less on retrieving more context and more on building an adequate intermediate representation of the program. A Famix model is precisely such a representation.

Left: Example of a Knowledge Graph ; Right: Example of a Famix Model instance

Bringing Moose to GraphRAG

KG-RAG is not a single tool but a family of implementations, and not all of them let you supply your own graph. We use Microsoft’s GraphRAG, which ships with a handy Bring Your Own Graph feature. This lets us plug in a graph we constructed ourselves — from Famix — instead of relying on GraphRAG’s default LLM-driven text extraction.

From Famix model to graph

To make a Famix model digestible by GraphRAG, we transform it into the format the framework expects: a set of nodes (entities) and edges (relationships), stored in the Parquet columnar file format (an Apache Arrow format optimized for efficient querying of large datasets). GraphRAG also requires text_units associated with each entity for vector-based retrieval.

We use Moose’s querying capabilities to extract the entities and relationships, and we recover the text_units from the actual source code of each entity, using the source anchors that Famix conveniently provides.

Less is more: choosing what goes into the graph

Our first attempt was the obvious one: extract everything from the Famix model. This produces a huge graph with a large number of entities and relationships — and it turned out to be a bad idea. Not everything in the model is relevant to retrieval, and dumping it all in made the graph more complex and actually harder for the GraphRAG system to use effectively. That first “extract-it-all” approach simply did not yield good results.

So we took a more focused approach, keeping only what matters for retrieval:

CategoryItems
EntitiesClass, Method, Attribute, and Package
Relationshipsinvocations (method calls) and exception handling (thrown, declared, caught)

This curated selection keeps the graph meaningful and tractable. The transformation code is open source: MooseGraphRAG

How the GraphRAG pipeline uses the graph

Microsoft’s GraphRAG framework runs in three main steps, and our Famix graph slots neatly into the first one.

  1. Graph construction. This is the step we replace. Instead of having an LLM infer the graph from raw text, we supply the Famix-derived graph directly. From the entities and their relationships, GraphRAG builds communities of closely related entities. Conceptually, these communities are close to the software-engineering notions of cohesion and coupling: group together what is tightly related, keep apart what is not. An LLM then generates natural-language descriptions of these communities, which are later used for retrieval.
  2. Retrieval. Entities or communities act as retrieval units. Given a query, the system retrieves the most relevant units based on vector similarity between the query and the text associated with each unit.
  3. Generation. Finally, the retrieved units are used to generate the answer to the query.

The key point: by grounding step 1 in a real code model, every downstream step works with relationships that are actually true of the code, not merely inferred from text.

Future work: evaluating on issue-driven class localization

Having a cleaner way to build the graph is only half the story — we also need to show it helps. Our ongoing and future work is a rigorous evaluation of the Famix-based KG-RAG against a text-based one, on a concrete and practical coding task: issue-driven Java class localization.

The task is realistic: given a GitHub issue title and description, the system must retrieve the Java classes that actually need to be modified to fix the issue. Because existing feature-location benchmarks (such as ArgoUML-SPL) target feature location rather than issue-driven localization, we are building a dedicated benchmark. A custom miner automatically extracts issues from GitHub repositories, keeping only closed issues linked to at least one merged pull request, and derives the ground truth from the files actually changed in those linked pull requests. Each issue is thus paired with the set of Java classes that were modified to resolve it.

On top of this benchmark we are building a shared evaluation pipeline that standardizes query building, prediction, and scoring (precision, recall, and F1, macro-averaged across issues). Crucially, the same pipeline drives several evaluator variants so that differences come from retrieval behavior rather than metric definitions:

Evaluator VariantDescription
Base GraphRAGText-driven graph
Moose/Famix-informed GraphRAGGraph derived from Moose/Famix models
Random baselineRandom class selection
Direct LLM inference baselineLLM directly infers classes
GitHub Copilot agent baselineCopilot’s agent mode predicts classes from query

This setup will let us measure precisely the impact of grounding the knowledge graph in an MDE model, and share the lessons learned along the way.

Takeaway

Code is already structured — so when building a knowledge graph for RAG, we shouldn’t throw that structure away and reconstruct it from text. By deriving the graph directly from Moose/Famix models, we get relationships that are reliable by construction, a graph that stays focused and usable, and a promising foundation for structure-aware retrieval over code. The next step is proving it out on real issue-resolution tasks — stay tuned for part 2.


Transformation code: MooseGraphRAG · Benchmark & evaluator: benchmark-GraphRag

More ...

Scroll to Top