Graph Prompting
What Does "Graph Prompting" Mean? A graph is a structure made of nodes (things) and edges (relationships between things). Course prerequisites, organization charts, social networks, website links, and database relationships are all graphs.
Python Basics ──→ Django Fundamentals ──→ Django REST APIs ──→ Deploying Django ↑ ↑ SQL Basics ─────┘ Git Essentials ─┘ The term graph prompting is used for two different ideas, and it is important to distinguish them:
Meaning Field Description
- Prompting for graph neural networks Machine learning research Methods such as GraphPrompt (Liu et al., 2023) adapt the idea of prompts to graph neural networks, a different type of model that works directly on graph data. This is not about writing text prompts for chat models.
- Prompting language models with graph-structured information Prompt engineering Representing relationships as text in a prompt, so a language model can reason about connections, dependencies, and paths. This lesson focuses on the second meaning, which is what developers use when building applications with language models. It also introduces Graph of Thoughts, a related reasoning framework.
Why Graphs Need Special Attention in Prompts Language models read text as a sequence (Lesson 2). Graph structure, which relationships connect to which, must be flattened into that sequence. How you flatten it affects how well the model can reason about it.
Typical Graph Questions Question Type Example Direct relationship What does Django REST APIs require? Indirect relationship (multi-hop) What must a student complete, directly or indirectly, before Deploying Django? Ordering In what order should a student take the courses to reach Deploying Django? Path Is there a chain of prerequisites from Python Basics to Deploying Django? Impact If Django Fundamentals is cancelled, which courses are affected? Direct relationships are usually easy for a model. Multi-hop questions, which require following several edges, are much harder, because the model must keep track of several steps implicitly (Lesson 39).
Encoding a Graph as Text The same graph can be written in different textual forms. Research on encoding graphs for language models, such as "Talk like a Graph: Encoding Graphs for Large Language Models" (Fatemi et al., 2023), found that the choice of encoding can noticeably affect performance on graph reasoning tasks. In practice, choose an encoding that makes the relationships needed for your questions explicit.
Encoding 1: Edge List Each line is one relationship.
Python Basics -> Django Fundamentals Django Fundamentals -> Django REST APIs SQL Basics -> Django REST APIs Django REST APIs -> Deploying Django Git Essentials -> Deploying Django Strengths: compact, one fact per line. Weakness: you must explain what -> means, and finding everything connected to one node requires scanning all lines.
Encoding 2: Adjacency List Each node lists its connections.
Python Basics: requires nothing Git Essentials: requires nothing Django Fundamentals: requires Python Basics SQL Basics: requires nothing Django REST APIs: requires Django Fundamentals, SQL Basics Deploying Django: requires Django REST APIs, Git Essentials Strengths: all direct requirements of a course are in one place; the relationship is stated in words. Weakness: indirect requirements still require following several lines.
Encoding 3: Natural Language Django Fundamentals requires Python Basics. Django REST APIs requires both Django Fundamentals and SQL Basics. Deploying Django requires Django REST APIs and Git Essentials. Strengths: readable. Weakness: harder to scan for large graphs; relationships can be misread in long paragraphs.
Generating Encodings in Code Graphs usually come from a database or configuration. Generate the text from data so that it is always complete and consistent.
PREREQUISITES = { "Python Basics": [], "Git Essentials": [], "Django Fundamentals": ["Python Basics"], "SQL Basics": [], "Django REST APIs": ["Django Fundamentals", "SQL Basics"], "Deploying Django": ["Django REST APIs", "Git Essentials"], }
def as_edge_list(graph: dict[str, list[str]]) -> str: return "\n".join(f"{p} -> {course}" for course, prereqs in graph.items() for p in prereqs)
def as_adjacency(graph: dict[str, list[str]]) -> str: return "\n".join( f"{course}: requires {', '.join(prereqs) if prereqs else 'nothing'}" for course, prereqs in graph.items() )
print(as_edge_list(PREREQUISITES)) print() print(as_adjacency(PREREQUISITES)) Output:
Python Basics -> Django Fundamentals Django Fundamentals -> Django REST APIs SQL Basics -> Django REST APIs Django REST APIs -> Deploying Django Git Essentials -> Deploying Django
Python Basics: requires nothing Git Essentials: requires nothing Django Fundamentals: requires Python Basics SQL Basics: requires nothing Django REST APIs: requires Django Fundamentals, SQL Basics Deploying Django: requires Django REST APIs, Git Essentials Code Explanation PREREQUISITES maps each course to the courses it requires directly. as_edge_list() creates one prerequisite -> course line for every relationship, using a nested loop inside the generator expression. as_adjacency() creates one line per course and writes "nothing" for courses without prerequisites, so the absence of requirements is explicit rather than missing. Prompting the Model to Reason Over the Graph A Graph Question Prompt The course prerequisites are listed in . "X: requires A, B" means a student must complete A and B before X.
Python Basics: requires nothing Git Essentials: requires nothing Django Fundamentals: requires Python Basics SQL Basics: requires nothing Django REST APIs: requires Django Fundamentals, SQL Basics Deploying Django: requires Django REST APIs, Git Essentials
Question: Which courses must a student complete, directly or indirectly, before Deploying Django?
Work step by step: start from Deploying Django, list its direct requirements, then the requirements of each of those, and continue until no new courses appear. Then give the final list. Why Each Part Matters Defining the notation prevents misreading the direction of relationships, a very common error with graphs. Asking for step-by-step traversal turns a multi-hop question into a sequence of single hops (Lesson 39, Lesson 49). A stopping rule ("until no new courses appear") tells the model when the traversal is complete. Expected result: Django REST APIs, Git Essentials, Django Fundamentals, SQL Basics, Python Basics.
Verify Graph Answers With Code Graph questions with exact answers, such as reachability and ordering, can be computed perfectly in code. As with arithmetic (Lesson 58), use the model for understanding and explanation, and code for exact graph operations.
from collections import deque from graphlib import TopologicalSorter
def all_prerequisites(graph: dict[str, list[str]], course: str) -> set[str]: """Every course required directly or indirectly before course.""" seen, queue = set(), deque(graph[course]) while queue: item = queue.popleft() if item not in seen: seen.add(item) queue.extend(graph[item]) return seen
def is_valid_order(graph: dict[str, list[str]], order: list[str], target: str) -> bool: """Check that order contains exactly the needed courses and respects every prerequisite.""" needed = all_prerequisites(graph, target) | {target} if set(order) != needed: return False position = {course: i for i, course in enumerate(order)} return all(position[p] < position[c] for c in order for p in graph[c])
print(sorted(all_prerequisites(PREREQUISITES, "Deploying Django")))
model_order = ["Python Basics", "SQL Basics", "Django REST APIs", "Django Fundamentals", "Git Essentials", "Deploying Django"] print(is_valid_order(PREREQUISITES, model_order, "Deploying Django"))
needed = all_prerequisites(PREREQUISITES, "Deploying Django") | {"Deploying Django"} sub_graph = {c: [p for p in PREREQUISITES[c] if p in needed] for c in needed} correct_order = list(TopologicalSorter(sub_graph).static_order()) print(is_valid_order(PREREQUISITES, correct_order, "Deploying Django")) Output:
['Django Fundamentals', 'Django REST APIs', 'Git Essentials', 'Python Basics', 'SQL Basics'] False True Code Explanation all_prerequisites() A breadth-first search (BFS). It starts with the course's direct requirements, then repeatedly adds the requirements of each newly found course, using seen to avoid processing a course twice. This is exactly the traversal the prompt asked the model to perform, but done exactly.
is_valid_order()
Checks that the proposed order contains exactly the needed courses: no missing course and no extra course. Records each course's position, then checks that every prerequisite appears before the course that requires it. The model order The example order places Django REST APIs before Django Fundamentals, which violates a prerequisite, so the check returns False. This is the kind of mistake a model can make on ordering questions, especially with larger graphs.
TopologicalSorter Computes a correct order for the needed courses (Lesson 63). Several valid orders often exist; static_order() returns one of them, and is_valid_order() confirms it.
The Practical Pattern Model: interpret the user's question ("What do I need before deployment?") Code: compute the exact answer from the graph Model: explain the result in friendly language, using the computed list This combination gives natural interaction with exact results.
Graphs From Text: Letting the Model Build the Graph Sometimes the graph is not in a database but hidden in text, such as relationships described in documentation or meeting notes. A model can extract the graph as structured data, which code then analyzes.
Read the course descriptions in . For every statement that one course requires another, output one JSON object {"course": ..., "requires": ...}. Return only a JSON array. Use course names exactly as written. The extracted edges can be validated (Lesson 73): every course name should appear in the source, and the resulting graph should have no cycles, meaning no chain of requirements that leads back to its own starting course. TopologicalSorter raises a CycleError when a cycle exists (Lesson 63).
Graph of Thoughts A related idea uses graphs to structure the reasoning itself. Graph of Thoughts (GoT), introduced by Besta et al. (2023) in "Graph of Thoughts: Solving Elaborate Problems with Large Language Models", extends Tree of Thoughts (Lesson 47):
Framework Structure of Reasoning Can Combine Separate Lines of Reasoning? Chain-of-Thought A single line No Tree of Thoughts Branches that split No Graph of Thoughts A graph: thoughts can split and merge Yes In Graph of Thoughts, partial results can be combined. For example, a long list can be split into parts, each part sorted separately, and the sorted parts merged into one result. Several thoughts can also be refined in a loop. The map-reduce pattern from Lesson 15, where section summaries are combined into one summary, is a simple example of this kind of split-and-merge structure.
When to Use Graph Prompting Good Fit Why Questions about dependencies, prerequisites, or hierarchies Relationships are central Explaining relationships to users in natural language The model turns graph results into readable explanations Extracting relationships from unstructured text The model finds edges; code analyzes them Small graphs in a single prompt The whole structure fits comfortably in context Poor Fit Why Large graphs with thousands of nodes Too large for a prompt; use a graph database or code, and pass only relevant parts Exact path, ordering, or reachability results that must be correct Compute them in code Common Mistakes Mistake 1: Undefined Edge Direction What it is: Writing A -> B without saying whether it means "A requires B" or "A is required by B".
Why it happens: The meaning is obvious to the author.
What it causes: The model reverses relationships and gives inverted answers.
How to fix it: Define the notation explicitly, or use words such as "requires".
Mistake 2: Trusting Multi-Hop Answers What it is: Accepting a model's list of indirect prerequisites or a proposed order without checking.
Why it happens: The answer looks reasonable.
What it causes: Missing nodes or invalid orders.
How to fix it: Compute reachability and ordering in code, and use the model to explain.
Mistake 3: Writing the Graph by Hand in the Prompt What it is: Typing relationships into the prompt manually.
Why it happens: The graph is small at first.
What it causes: Missing or outdated edges as the data changes.
How to fix it: Generate the encoding from the source data each time.
Mistake 4: Sending the Entire Graph What it is: Including every node and edge for every question.
Why it happens: It guarantees completeness.
What it causes: Long prompts, higher cost, and more distraction for large graphs.
How to fix it: Use code to select the relevant subgraph, such as the target and its prerequisites, before prompting.
Best Practices Choose an encoding that makes the needed relationships explicit. Adjacency lists work well for "what does X require" questions.
Define what each relationship means. Direction errors are the most common graph mistake.
Ask for step-by-step traversal on multi-hop questions. One hop at a time.
Compute exact graph answers in code. Reachability, paths, and orderings.
Let the model extract and explain. Code handles the structure; the model handles the language.
Send only the relevant subgraph. Keep prompts focused as graphs grow.
Try It Yourself Exercise 1: Compare Encodings Create a prerequisite graph of 10 courses. Ask a model the same five multi-hop questions three times, once with each encoding (edge list, adjacency list, natural language). Check every answer with all_prerequisites() and compare the accuracy of the encodings.
Exercise 2: Model Explains, Code Computes Build a function that takes a target course, computes its prerequisites and a valid order in code, and then asks a model to write a friendly 80-word study plan using only the computed order. Verify that the model's plan keeps the order unchanged.
Exercise 3: Extract a Graph From Text Write five short course descriptions that mention prerequisites in different ways ("you should already know...", "builds on...", "requires..."). Ask a model to extract the edges as JSON, build the graph, and check it with TopologicalSorter for cycles. Compare the extracted edges with the ones you intended.