Back openDesk Edu for a sovereign, open-source education β every vote counts.
Vote nowLarge Language Models excel at reasoning but lack grounding. Knowledge Graphs provide grounding but speak a different language. Integrating these paradigms has been challenging β until now.
GRALAN (Graph Language) enables KGs to speak directly in the LLM's semantic space through relational tokens that preserve graph structure. A trainable language mediator generates structured tokens for any frozen LLM, creating a foundation for knowledge-intensive applications.
The result: significant improvement on complex multi-hop reasoning tasks without fine-tuning the base model.
Knowledge Graphs and LLMs have complementary strengths:
| LLMs | Knowledge Graphs |
|---|---|
| Fluent generation | Structured facts |
| Reasoning ability | Precise relationships |
| Broad knowledge | Grounded evidence |
| But: Hallucinate | But: Rigid querying |
The challenge: how to combine them without losing either's strengths?
Existing approaches fall into three categories:
Encode KG entities as vectors, feed to LLM.
Problem: Loses structural information. Relationships become distances in vector space.
Describe KG subgraphs in natural language prompts.
Problem: Token-heavy. Structure is flattened to text. Context window limits apply.
Fine-tune LLM on KG-augmented data.
Problem: Expensive. Loses base model capabilities. Not portable across models.
GRALAN takes a different approach: language mediation.
GRALAN introduces a new token type: relational tokens that encode graph structure directly in the token space.
Standard tokens: [Paris] [is] [capital] [of] [France]
Relational tokens: [Paris] [<entity>] [capital_of] [France] [<entity>]
The relational tokens <entity> and capital_of are learned embeddings that preserve:
The mediator is a lightweight transformer that sits between the KG and the frozen LLM:
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β Knowledge β β Language β β Frozen LLM β
β Graph βββββββΊβ Mediator βββββββΊβ (e.g., Llama) β
β (Neo4j, etc.) β β (trainable) β β (frozen) β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
The mediator:
Given a query and a KG, GRALAN:
def subgraph_to_tokens(query, kg, mediator):
# Step 1: Retrieve relevant subgraph
subgraph = kg.retrieve(query) # Neo4j Cypher query
# Step 2: Linearise with relational tokens
tokens = []
for node in subgraph.nodes:
tokens.append(f"<entity:{node.type}>")
tokens.append(node.text)
for edge in subgraph.edges:
tokens.append(f"<relation:{edge.type}>")
# Step 3: Convert to embeddings via mediator
embeddings = mediator.encode(tokens)
return embeddings
The key: structure is preserved in the token sequence, not lost to flattening.
GRALAN reframes QA as entity classification over question-focused subgraphs:
Query: "Who founded Microsoft?"
Step 1: Retrieve subgraph
Microsoft ββ[founded_by]βββΊ [Entity: ?]
Step 2: Convert to relational tokens
[<entity:Organization>] Microsoft [<relation:founded_by>] [<entity:Person>]
Step 3: Feed to LLM with special classification head
LLM predicts: [<entity:Person> = "Paul Allen"]
Step 4: Extract answer
Answer: "Paul Allen"
This is more efficient than open-ended generation. The LLM classifies from the subgraph entities rather than generating from scratch.
GRALAN was evaluated on knowledge-intensive QA benchmarks:
| Benchmark | Task | Baseline (RAG) | GRALAN | Improvement |
|---|---|---|---|---|
| WebQSP | Multi-hop QA | 0.58 EM | 0.71 EM | +22.4% |
| ComplexWebQuestions | Multi-hop QA | 0.52 EM | 0.64 EM | +23.1% |
| MetaQA | 1-3 hop QA | 0.89 EM | 0.94 EM | +5.6% |
| HotpotQA | Multi-hop QA | 0.41 EM | 0.53 EM | +29.3% |
Key findings:
The language mediator is trained with contrastive learning:
# Training objective
for query, positive_subgraph, negative_subgraph in dataloader:
# Encode subgraphs
query_embed = mediator.encode(query)
pos_embed = mediator(subgraph_to_tokens(query, positive_subgraph))
neg_embed = mediator(subgraph_to_tokens(query, negative_subgraph))
# Contrastive loss: pull positive closer, push negative away
loss = contrastive_loss(query_embed, pos_embed, neg_embed)
loss.backward()
Training requirements:
GRALAN works with any graph database:
# Neo4j integration
class Neo4jGRALAN:
def __init__(self, uri, user, password, mediator, llm):
self.driver = GraphDatabase.driver(uri, auth=(user, password))
self.mediator = mediator
self.llm = llm # LLM for final classification
def retrieve_subgraph(self, query):
with self.driver.session() as session:
result = session.run("""
MATCH path = (start)-[*1..3]-(related)
WHERE start.name CONTAINS $query
RETURN start, relationships(path) as rels, related
LIMIT 100
""", query=query)
return self._build_subgraph(result)
def answer(self, query):
subgraph = self.retrieve_subgraph(query)
tokens = subgraph_to_tokens(query, subgraph, self.mediator)
embeddings = self.mediator.encode(tokens)
return self.llm.classify(query, embeddings)
def _build_subgraph(self, result):
"""Convert Neo4j result records into a subgraph structure."""
nodes = {}
edges = []
for record in result:
start = record["start"]
related = record["related"]
nodes[start.element_id] = start
nodes[related.element_id] = related
for rel in record["rels"]:
edges.append((start.element_id, rel.type, related.element_id))
return {"nodes": nodes, "edges": edges}
GRALAN adds minimal overhead:
For production: negligible incremental cost over standard RAG.
Here's the minimal architecture:
class GRALAN:
def __init__(self, kg_client, mediator, llm):
self.kg = kg_client
self.mediator = mediator
self.llm = llm
def train_mediator(self, training_data):
# Contrastive learning on query-subgraph pairs
for query, pos_sg, neg_sg in training_data:
pos_emb = self.mediator.encode(subgraph_to_tokens(query, pos_sg))
neg_emb = self.mediator.encode(subgraph_to_tokens(query, neg_sg))
loss = contrastive_loss(query_emb, pos_emb, neg_emb)
loss.backward()
def answer(self, query):
# Step 1: Retrieve subgraph
subgraph = self.kg.retrieve(query)
# Step 2: Convert to relational tokens
tokens = subgraph_to_tokens(query, subgraph, self.mediator)
# Step 3: Encode via mediator
embeddings = self.mediator.encode(tokens)
# Step 4: Classify with frozen LLM
answer = self.llm.classify(query, embeddings)
return answer
GRALAN reveals three trends:
Flattening graphs to text loses information. Structure-preserving tokenisation is the future of KG-LLM integration.
Trainable mediators that work with frozen LLMs are more efficient and portable than fine-tuning.
QA as entity classification beats open-ended generation for knowledge-intensive tasks. Task reformulation unlocks efficiency.
GRALAN solves the KG-LLM integration problem by:
For knowledge-intensive applications, the implication is clear: structure matters. Graph-native integration beats text flattening.