Insights
The questions similarity search can't answer
There is a kind of question the assistant on this site cannot answer, and it took me a while to see why. Ask it what a build costs and it does fine: retrieval finds the pricing chunk, the model reads it back. Ask which client sites still run the engine build from before a particular fix, and it comes up empty, even though every fact needed for the answer sits somewhere in my notes. The fix is recorded in one place. Each client fork records the exact commit it was cut from in another. Which client runs which fork is in a third.
Better embeddings would not fix this, because the failure is structural. An embedding turns a passage into a point in a space where nearby means similar. That is the entire trick, and it is a good one: it is how the chat here finds the right chunk out of nearly two hundred without keyword luck. But that space only has distances. "The fix landed in June" and "this site was forked in May" are two points that sit nowhere near each other, and nothing in the geometry lets you lay them end to end. Answering the question means walking a chain: fix, to engine version, to fork, to client. Similarity finds things. It does not follow them.
The structure built for following
That structure is a graph, and the whole vocabulary fits in a breath. Nodes are things: a person, a service, a client site, a commit. Edges are how they relate: this site was forked from that engine version, this fix was ported to that site. Properties hang details on either one: the fork carries its parent hash, the edge carries a date. A fact is just a subject, a relation, and an object, and a knowledge graph is a pile of facts that share their nouns. The sharing is the power. Nobody has to write down the answer to the chain question anywhere, because the graph can assemble it by stepping from edge to edge.
Graphs are old technology; fraud detection and social networks have run on them for decades. The reason a one-person studio can suddenly care is that the expensive part collapsed. Populating a graph used to mean structured data or hired annotators tagging entities by hand. Now a language model reads plain notes, tickets, and commit messages and extracts the facts for pennies. The structure was always good. Filling it just stopped being a project.
What retrieval looks like with one
Ordinary RAG embeds the question, pulls the most similar chunks, and hands them to the model. Graph retrieval changes the middle step. Match the entities in the question to nodes. Walk outward from them, a hop or two. Turn the small subgraph you collected back into sentences, and let the model answer from those, citing the path it used. The retrieval step stops asking what text resembles the question and starts asking what the question's subjects are attached to. On chain questions, that is the difference between a confident half-answer and a list of names you can verify.
What I actually run today
The assistant here runs hybrid retrieval: full-text match blended with cosine similarity over embedded chunks, on a knowledge base I curate by hand. I am not tearing that out. Most visitor questions are similarity questions (what does this cost, what is Frida, who built this), and for those, embeddings plus curation is the right amount of machinery. Bolting a graph onto questions similarity already answers is complexity with no payoff.
But two things in this shop are already graphs wearing plain clothes. My working memory is a folder of notes that reference each other by name, which is an edge list nobody traverses. And the client playbook records, for every fork of the CMS engine, exactly which commit it was cut from, which is the spine of the chain question that opened this post. So the plan is not a new database. It is a table of facts living next to the chunks: subject, relation, object, where it came from, when it was true. An extraction pass fills it from notes that already exist, using the same model cascade the chat already runs. Retrieval keeps vectors as the way in and adds a hop outward before the model answers. Similarity to get in the door, edges to get around the room.
The part that will actually be work
Not the extraction. The cleanup. My notes call the same client by a first name, a project name, and a domain, and a naive extractor will mint three nodes for one person, at which point the graph quietly fragments and chain queries return nothing while looking healthy. Entity resolution, the unglamorous business of deciding that two names are one thing, is most of the real effort in every graph project I have read about, and I believe it. The second trap is staleness: a graph states facts with a straight face long after they stop being true, so every edge gets a date and old ones lose their vote. Fix both and the payoff is an assistant that can answer with a chain of custody instead of a vibe.
The test I keep taped above the whole decision: if the answer to your question is a passage that exists somewhere, embeddings will find it. If the answer has to be assembled by walking from fact to fact, no amount of similarity will assemble it. Most systems that work end up holding both tools and knowing which question is which.
Common questions
What is a knowledge graph?
A collection of facts stored as subject, relation, object, where facts that share an entity connect automatically. Ask a question and the graph can assemble an answer by walking those connections, even when no single document contains it.
What is GraphRAG?
Retrieval that matches the entities in a question to nodes in a graph, walks their connections a hop or two, and hands the assembled facts to the model. It answers multi-step questions that similarity retrieval structurally cannot.
Do I need a graph for my RAG system?
Only if your questions chain facts together or ask what is connected to what. If they are all variations of "find me things like X", embedding retrieval already covers you and a graph adds complexity without payoff.
What is the hardest part of building one?
Entity resolution: merging the three names your documents use for one thing. Skip it and the graph fragments into islands that return nothing. Second is freshness, since a graph will state stale facts confidently unless edges carry dates.
Related