DEV Community

Cover image for Building MatchMetric-AI: A Real-Time Resume Tailoring Engine with Django, WebSockets, and LLMs
Adeniyi Olanrewaju
Adeniyi Olanrewaju

Posted on

Building MatchMetric-AI: A Real-Time Resume Tailoring Engine with Django, WebSockets, and LLMs

Applying for jobs is hard. Every resume needs to match the job description perfectly. To solve this, I built MatchMetric-AI, a tool that uses Artificial Intelligence to analyze resumes and give instant feedback.

What does this project do?

  1. Reads PDFs: It extracts text from your resume using the PyPDF library.

  2. AI Analysis: it sends that text to Google Gemini AI to see how well you match a job.

  3. Live Updates: It uses WebSockets so you don't have to refresh the page to see results.

  4. History: It saves your past scans so you can see your progress.

The Tech Stack

  • Django: The main framework.

  • Channels & Redis: To make the "Live" WebSocket connection work.

  • Google Gemini API: The "brain" that reads the resume.

  • PyPDF: To turn PDF files into plain text.

Here is a deep dive into how I built it.

  1. The Core Vision MatchMetric-AI isn’t just a simple wrapper for an LLM. It’s a full-cycle service that:
  • Extracts raw text from uploaded PDF resumes.

  • Analyzes the resume against a specific Job Description.

  • Streams feedback back to the user instantly using WebSockets.

  • Persists the history so users can track their application improvements.

Technical Deep Dive

A. Modular Project Structure
I followed a "Service-Oriented" architecture to keep the project clean. Instead of bloating the Django views.py, I separated the logic into distinct modules:

  • ai/google_genai: Handles all communication with Gemini.

  • pdf_extract/pypdf_extractor: Contains the logic for parsing PDFs.

  • apis/resumehistory: Manages the WebSocket consumers and database history.

B. PDF Extraction with PyPDF
One of the first hurdles was converting complex PDF layouts into clean text that an AI can understand. I utilized PyPDF to iterate through document pages and clean the whitespace to ensure the AI prompt doesn't get cluttered with "junk" characters.

from pypdf import PdfReader


class PyPDFExtractor:
    def __init__(self, file_obj):
        self.reader = PdfReader(file_obj)

    def extract_text(self) -> str:
        text = ""
        for page in self.reader.pages:
            page_text = page.extract_text()
            if page_text:
                text += page_text + "\n"
        return text
Enter fullscreen mode Exit fullscreen mode

C. Real-time Communication with Django Channels
Unlike standard HTTP where the user has to wait for a long AI processing time, I implemented WebSockets. This allows the server to maintain an open connection with the client.

The ResumeConsumer handles the connection. Because Gemini’s processing is synchronous, I used sync_to_async to ensure the server remains responsive while the AI "thinks."

D. Solving the ASGI "Handshake" Challenge
The most difficult part of the project was configuring the asgi.py to handle both standard HTTP (for logins) and WebSockets (for AI analysis) simultaneously. I had to ensure that the AuthMiddlewareStack was correctly positioned to allow my WebSocket to "see" the logged-in

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(websocket_urlpatterns)
    ),
})
Enter fullscreen mode Exit fullscreen mode

How to Run the Project

Prerequisites
Redis (for the message broker)

Google Gemini API Key (you can get it here: https://aistudio.google.com/)

Installation

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode
  • Environment Variables: Configure your .env with GOOGLE_API_KEY and REDIS_URL and other variables in the env.example file.

  • Migrations:

python manage.py migrate
Enter fullscreen mode Exit fullscreen mode
  • Launch:
chmod +x runapp.sh
./runapp.sh
Enter fullscreen mode Exit fullscreen mode

Testing with Postman

Since this uses WebSockets, you can't test it like a normal website with a frontend library consuming the api.

  • Login to Django admin with a superuser credential, inspect the browser page and get the sessionid from cookies in the application tab.
  • Open Postman and start a WebSocket Request.
  • Go to the headers and set Cookie as the key and sessionid=
  • Connect to ws://127.0.0.1:8000/ws/resume-tailor/.
  • Send a JSON message with your resume text and the job description. You need to access the upload endpoint to extract the text from uploaded resume(.pdf).
  • Watch the AI response appear in real-time!

What I Learned

The biggest challenge was Authentication. I had to make sure the WebSocket knew which user was logged in. I learned how to use Django's sessionid cookies to securely connect the user to their history.

Top comments (0)