Python Series track

Project 15 · Practice Projects

Project 15 — Markov Chain Chatbot

Build a text generator chatbot using Markov chains. Train it on any text corpus and generate statistically plausible responses.

Practice Projects1 min readFree lesson

Difficulty: Lv ★★★★ | Prerequisites: Advanced Week 7 (requests)

Goal

Console-based chatbot (rule-based or LLM API)

Requirements

  • User input ↔ response loop
  • Exit command (/quit, /exit)
  • Save chat history in JSON
  • Command mode: /clear, /save, /load, /history

Options

  • A. Rule-based: Keyword matching
  • B. API-based: LLM API with requests + .env (python-dotenv)

Challenge Task

  • Token usage
  • Asynchronous multi-model

Assignment

Show the reference solution

Try the assignment yourself first — comparing your attempt with a working solution is where most of the learning happens.

solution.pyPython
"""Rule-based console chatbot — works without an API key"""
import json
import re
from pathlib import Path
from datetime import datetime

HISTORY = Path("chat_history.json")

RULES = [
    (r"Hello|hello|hi", "Hello!"),
    (r"Name|Who", "I am a learning chatbot."),
    (r"Weather", "Sorry, I cannot provide real-time weather."),
    (r"Python|python", "Python is an interpreted language released in 1991."),
    (r"Thanks|thank you|thanks", "You're welcome!"),
    (r"(\d+)\s*\+\s*(\d+)", lambda m: f"= {int(m.group(1)) + int(m.group(2))}"),
]

def respond(text):
    for pattern, reply in RULES:
        m = re.search(pattern, text)
        if m:
            return reply(m) if callable(reply) else reply
    return "I don't know. Please say it again."

def save(history):
    HISTORY.write_text(json.dumps(history, ensure_ascii=False, indent=2), encoding="utf-8")

def load():
    return json.loads(HISTORY.read_text(encoding="utf-8")) if HISTORY.exists() else []

def main():
    history = []
    print("Chatbot start (/quit to exit, /help for commands)")
    while True:
        user = input("\nyou: ").strip()
        if not user: continue
        if user.startswith("/"):
            cmd = user[1:]
            if cmd in ("quit", "exit"): break
            elif cmd == "help":
                print("/clear /save /load /history /quit")
            elif cmd == "clear": history = []; print("Reset history")
            elif cmd == "save": save(history); print("Saved")
            elif cmd == "load": history = load(); print(f"Loaded ({len(history)} items)")
            elif cmd == "history":
                for h in history[-5:]:
                    print(f"  [{h['time']}] {h['who']}: {h['text']}")
            continue
        bot_reply = respond(user)
        ts = datetime.now().strftime("%H:%M:%S")
        history.append({"time": ts, "who": "user", "text": user})
        history.append({"time": ts, "who": "bot", "text": bot_reply})
        print(f"bot: {bot_reply}")

if __name__ == "__main__":
    main()

Learn this lesson with a mentor

Work through the Python Series track on your own, or join a guided cohort at our Pitampura campus and online.

Call NowEnroll Now