In customer support, fast and reliable answers matter. I wanted to create a controlled, efficient support chatbot — one that doesn't rely on generative AI but instead uses traditional machine learning, information retrieval, and a custom-designed user interface for an interactive, predictible experience.

In this project, I built a Flask web application that uses SVM classification, TF-IDF vectorisation, and Cosine Similarity to serve accurate responses from a custom knowledge base, and a fully custom frontend built in HTML, CSS, and JavaScript.

Problem to Solve

Modern LLM-based bots are powerful, but they come with risks:

  • Hallucinated responses.
  • Inconsistent tone.
  • Data privacy concerns.

Many small businesses actually need a cheaper, smaller, safer, and more deterministic chatbot.
This project addresses that gap.

Backend Tech Stack

  • Python 3
  • Flask (web server and API)
  • Scikit-learn (for machine learning models)
  • Pandas / Numpy (for data manipulation)
  • TF-IDF vectorisation (for text representation)
  • SVM (Support Vector Machine) (for classification)
  • Cosine Similarity (for fine-grained matching)

Workflow and the Maths Behind It

  1. Preprocessing the Knowledge Base The core of the chatbot is a CSV file containing common customer support questions and answers for a bank.

Before training:

Stemming: Normalise words like "running" to "run".
TF-IDF Vectorisation: Convert text into a matrix that captures the importance of terms.

Here’s a simple example of the preprocessing pipeline:

Image description

  1. Classifying User Queries Once the data is preprocessed, I trained a Support Vector Machine (SVM) classifier with a linear kernel:

Image description

When a user submits a query:

  • It’s preprocessed the same way (stemming + TF-IDF).

  • Then classified into a question category.

  1. Fine-Grained Matching within the Class After finding the class, I zoom into the subset of related questions and use Cosine Similarity to identify the closest match.

This ensures fast and accurate matching even if user phrasing varies.

Handling Escalations: Automated Support Ticket System

Even with the best machine learning models, some user queries might not be answered perfectly. To handle these cases professionally, I built an automated support ticket creation system inside the chatbot flow. When a user indicates that the chatbot's answer was not helpful, the bot automatically initiates a support ticket creation dialogue.

How the Support Ticket Flow Works

  • Ask for the user's email:
  • The bot prompts the user to input a valid email address. A simple email format check (@ and . present) is performed.
  • Confirm or Update the Question: The user can either confirm the original query or provide additional detailed information.
  • Generate and Log the Ticket: A unique ticket ID is created based on the timestamp.
  • The ticket is saved using a helper function (save_support_ticket()).
  • An email notification is sent to the user using send_email_notification() and sent to the support team.
  • Handle Errors Gracefully: If something fails, users are informed politely, and the system logs the error and support ticket locally for admins.

Sample code:

Image description

Each step is stateful — meaning the chatbot remembers where the user is in the conversation flow — and the system automatically progresses based on user input.

This support ticket system enables the user to contact the support team correctly if the bot fails to answer their query to their liking. By combining smart automation with human fallback options, I built a chatbot that doesn't just answer questions — it ensures no customer is ever left behind.

Frontend Tech Stack and deployment

  • HTML5 (structure)
  • CSS3 (styling, animations)
  • Vanilla JavaScript (dynamic behavior)
  • Google Fonts and Material Symbols (icons)
  • Responsive Design (for mobile and desktop
  • Heroku to deploy
  • JS widget for deployment

Chatbot UI Features

  1. Clean, Toggleable Interface
    The chatbot toggles open and closed with a floating button, creating a minimal footprint when not in use. I used CSS transitions for smooth animations between states.

  2. Modern, Card-Style Chat Window
    The main chat interface is styled like a mobile chat app. Messages are dynamically appended to the chatbox using JavaScript.

  3. Fully Responsive Design
    On mobile screens, the chatbot resizes to full-screen mode automatically for better usability.

  4. Asynchronous Communication with Backend
    When the user submits a message, JavaScript sends an HTTP request to the Flask server.
    The chatbot displays the server’s reply without reloading the page, creating a smooth, real-time experience.

Example of the JS widget:

Image description

Design Philosophy

  • Speed: Lightweight frontend and backend.
  • Simplicity: No frameworks; pure HTML/CSS/JS for maximum control.
  • Professionalism: Clean UX and error handling.
  • Expandability: Easy to add new questions, classes, or UI features.

What I Learned

  • Classic machine learning techniques can deliver incredible value in well-defined domains.
  • Frontend design plays a crucial role in user trust and experience.
  • Building debug tools and fallback strategies improves reliability.
  • Full-stack integration (Flask + Vanilla JS) made me appreciate how different layers must work together for a seamless product.

Final Thoughts

This project shows that you don't always need the biggest AI models to solve real problems.
With thoughtful backend logic and a polished, user-friendly frontend, you can build robust, safe, and beautiful ML experiences.