An interactive joke-telling bot built with LangGraph that demonstrates loops, conditional routing, and state management.
Perfect for Learning LangGraph | Runs on Google Colab | No API Keys Required | 100% Free
This notebook teaches you LangGraph fundamentals through a fun, interactive bot that:
- β Shows you programming jokes
- β Lets you change joke categories (neutral, chuck norris, all)
- β Keeps track of jokes told
- β Loops until you quit
- β Demonstrates conditional routing and state management
The Flow:
Menu β Fetch Joke β Show Menu β Change Category β Show Menu β Quit β
β__________________________| β__________________|
(loop) (loop)
Press Runtime > Run all and interact with the bot!
[n] Next [c] Category [q] Quit
> n
No API keys needed! Uses the free pyjokes library.
# Automatically installed in Cell 1:
!pip install langgraph pydantic pyjokesWhy these?
- langgraph β Graph-based workflow framework
- pydantic β Data validation and state management
- pyjokes β Programming jokes library (no API!)
βββββββββββββββ
ββββββ€ show_menu βββββ
β βββββββββββββββ β
β β
βΌ β
ββββββββ ββββββββββ
βfetch β βupdate β
βjoke ββββββββββββββββ€categoryβ
ββββββββ ββββββββββ
β β
ββββββββββββββββββββββββ
βΌ
ββββββββββββ
β exit_bot ββββΊ END
ββββββββββββ
class JokeState(BaseModel):
jokes: List[Joke] = [] # All jokes told (accumulated)
jokes_choice: str = "n" # User's menu choice (n/c/q)
category: str = "neutral" # Current joke category
language: str = "en" # Language for jokes
quit: bool = False # Exit flagKey Concept: The jokes list uses a reducer that appends new jokes instead of replacing them!
πͺ show_menu
- Shows options: [n] Next, [c] Category, [q] Quit
- Gets user input
- Routes to appropriate node
π© fetch_joke
- Gets a joke from
pyjokeslibrary - Displays it with formatting
- Loops back to menu
π¦ update_category
- Shows category options (neutral, chuck, all)
- Updates the category
- Loops back to menu
β exit_bot
- Shows goodbye message
- Shows total jokes told
- Ends the graph
def route_choice(state: JokeState) -> str:
if state.jokes_choice == "n":
return "fetch_joke" # Tell another joke
elif state.jokes_choice == "c":
return "update_category" # Change category
elif state.jokes_choice == "q":
return "exit_bot" # Quitπππππππππππππ
WELCOME TO JOKE BOT!
πππππππππππππ
[n] Next [c] Category [q] Quit
> n
==================================================
π Joke #1 (Category: neutral)
==================================================
Why do programmers prefer dark mode?
Because light attracts bugs.
==================================================
[n] Next [c] Category [q] Quit
> c
Select category [0=neutral, 1=chuck, 2=all]: 1
[n] Next [c] Category [q] Quit
> n
==================================================
π Joke #2 (Category: chuck)
==================================================
Chuck Norris can write infinite recursion functions
and have them return.
==================================================
[n] Next [c] Category [q] Quit
> q
==================================================
π Thanks for using Joke Bot!
π You enjoyed 2 jokes today!
==================================================
# In update_category function:
categories = ["neutral", "chuck", "all", "programming", "dad"]# In JokeState:
language: str = "de" # German jokes!class JokeState(BaseModel):
# ... existing fields ...
favorite_jokes: List[Joke] = []
ratings: List[int] = []def rate_joke(state: JokeState) -> dict:
rating = int(input("Rate this joke (1-5): "))
return {"ratings": [rating]}# State flows through all nodes
jokes: Annotated[List[Joke], add] = [] # Accumulates
category: str = "neutral" # Overwritesworkflow.add_conditional_edges(
"show_menu", # From this node
route_choice, # Use this function to decide
{ # Map to these nodes
"fetch_joke": "fetch_joke",
"update_category": "update_category",
"exit_bot": "exit_bot"
}
)# These edges create loops
workflow.add_edge("fetch_joke", "show_menu") # Loop back
workflow.add_edge("update_category", "show_menu") # Loop backworkflow.add_edge("exit_bot", END) # Special END nodeEvery LangGraph system follows this pattern:
- Define the State β What to remember
- Write Node Functions β What each step does
- Create Graph Builder β Initialize the graph
- Add Nodes and Edges β Connect everything
- Compile and Run β Execute the workflow
This project demonstrates all 5 steps clearly!
Start Here (This Project) β Learn basics:
- State management
- Nodes and edges
- Conditional routing
- Loops
Next Project β LangGraph Research Assistant
- Web search integration
- Iteration limits
- LLM integration
- Complex workflows
Error: "Invalid choice"
- Make sure you type exactly
n,c, orq - No spaces or capital letters
Jokes not showing up
- The
pyjokeslibrary has limited jokes - Try changing categories
Graph runs forever
- Check the
recursion_limitin the config - Default is 100 iterations (plenty for this bot)
| Traditional Chain | This Graph |
|---|---|
| A β B β C β Done | Menu β Action β Menu (loops) |
| No user interaction | Interactive at each step |
| Fixed path | Dynamic routing based on input |
| No memory of previous steps | Tracks all jokes told |
Try these modifications:
- Easy: Add a "Random" category option
- Medium: Add a "Favorites" feature to save best jokes
- Hard: Add joke ratings and show statistics at the end
- Expert: Connect to an LLM to generate custom jokes
This pattern is useful for:
- Customer Support Bots - Route to different departments
- Interactive Tutorials - Let users choose their path
- Game Engines - Menu systems and state machines
- CLI Tools - Interactive command-line apps
- Survey Bots - Dynamic questionnaires
Ideas for improvements:
- Add more joke categories
- Create a web UI version
- Add joke ratings
- Export favorite jokes
- Multi-language support
Fork and share your version!
MIT License - Use freely in your projects!
Built with β€οΈ for beginners learning graph-based workflows