跳到正文
DEV Community· Rahul Tapase·· 3 小時前AI 評分45

PrepMate:用 Gemma 4 準備模擬面試

PrepMate: Practice Interviews While Gemma 4 Does the Prep Work

AI 導讀

PrepMate 透過本機運行的 Gemma 4 進行模擬面試,按用戶履歷、目標職位及職位描述生成問題,並以語音提問和記錄回答。每題均會獲得評分及文字回饋,資料儲存在用戶電腦的 SQLite 檔案中;履歷 PDF 留在瀏覽器內。

正文

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

What I Built

PrepMate is a mock interviewer that runs on your own laptop. You drop in your resume PDF, paste the job description, pick Technical, HR or Managerial, and then you just talk. Gemma 4 reads your background, asks you tailored questions out loud, listens to your spoken answers, and when you end the session it hands you a scorecard: a communication score and a technical (or behavioral) score for every answer, a written comment on each one, an overall score, and a short list of things to work on.

Interview prep is the task everyone puts off. Doing it properly means hunting for question lists that match your role, rehearsing answers alone in your head with no idea whether they're any good, or convincing a friend to play interviewer for an hour and then give you honest feedback. PrepMate does all three jobs. The only effort left for you is showing up and speaking.

The lazy parts it handles for you:

  • No question hunting. Questions are generated from your resume, target role, company and job description, so a frontend intern and a backend engineer get different interviews.
  • No typing. Questions are read aloud and your answers are captured by voice.
  • No self-grading. Every answer is scored and commented on.
  • No tuning. After five completed sessions of the same type, the questions get harder on their own.
  • No bookkeeping. Every session lands on a dashboard with search, filters and the full feedback, so you can see whether you're improving without keeping notes.

I'm a student heading into interview season, so I'm the first lazy person this was built for.

Demo

PrepMate home page with the Start Practicing button and a preview of an AI interview session
The home page. One button and you're in.

Configure Session form with fields for name, job role, company, experience, interview type, job description, and resume content with an Upload PDF button
Setting up a session: fill in the role, paste the job description, and upload your resume as a PDF. That's all the typing you'll do.

Code


📖 About

PrepMate runs a full mock interview on your own machine. It reads your resume and the job description, asks tailored questions out loud, records your spoken answers, and then scores each answer with written feedback. The AI model (Gemma 4) runs locally through Ollama, and all data is stored in a local SQLite file.

✨ Features

  • 🤖 AI interviewer - Questions generated by Gemma 4 from your resume, target role, company and job description
  • 📄 PDF resume upload - Text is extracted in the browser and can be edited before the interview; pasting text also works
  • 🎙️ Voice answers - Questions are read aloud and answers are captured with speech-to-text
  • 📚 Interview types - Technical, HR and Managerial
  • ⚡ Scored feedback - Per-question communication…

How I Built It

Architecture

Browser (React + TypeScript + Vite)
   │  /api/*
   ▼
Express on 127.0.0.1:3001
   ├── auth  → SQLite users + sessions
   ├── data  → SQLite profiles, interviews, ratings
   └── ai    → Ollama at 127.0.0.1:11434 (gemma4:e2b)

The server only listens on 127.0.0.1, and the resume PDF never leaves the browser: pdf.js extracts the text client-side, and only that text goes into the prompt.

Talking to Gemma

The whole AI layer is one call to Ollama's chat API:

const res = await fetch(`${url}/api/chat`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  signal: controller.signal,
  body: JSON.stringify({
    model,                       // gemma4:e2b by default
    messages: [{ role: 'user', content: prompt }],
    stream: false,
    think: false,                // skip the reasoning trace, it only adds latency here
    ...(format ? { format } : {}), // JSON schema for feedback
    options: { num_ctx: numCtx },  // 16384
  }),
});

Three settings did most of the work:

  • think: false. A list of interview questions doesn't need a reasoning trace, and skipping it cuts the wait noticeably on a laptop.
  • num_ctx: 16384. A resume (up to 10k characters) plus a job description (up to 8k) plus the instructions doesn't fit in Ollama's default context window, and the prompt would get truncated. Raising it keeps the whole resume in view.
  • Schema-constrained feedback. The dashboard reads exact fields, so the feedback has to be valid JSON every time. App sends a JSON schema as Ollama's format, and Gemma's output is constrained to that shape. HR and Behavioral interviews get a behavioral score; Technical and Managerial get a technical score:
const perQuestion = softSkillsInterview
  ? { question: str, answer: str, communicationScore: scoreInt, fluencyComment: str, behavioralComment: str }
  : { question: str, answer: str, communicationScore: scoreInt, technicalScore: scoreInt, fluencyComment: str, techComment: str };

Small model, clear rules

gemma4:e2b is small enough to run on an ordinary laptop, so the prompts are explicit about format: one question per line, no headings, no labels, nothing else. A tolerant parser then keeps lines that end in a question mark, so a stray intro sentence from the model doesn't end up as "question 1".

Being honest about the hardware

Before an interview starts, a system check calls /api/health, which asks Ollama whether it's running and whether the model is installed. If either is missing, the Start button stays locked and the page shows the exact command to fix it (ollama serve or ollama pull gemma4:e2b).

Local generation is slower than a cloud API. On gemma4:e2b, questions take roughly 20 to 60 seconds and feedback 10 to 30 seconds, depending on the machine. The app says so up front instead of pretending otherwise. For a week themed on sloths, a short wait in exchange for keeping everything on your own disk felt like a fair trade.

Why Does Open Innovation Matter?

A mock interview is personal data. Your resume carries your phone number, email, college and grades, and your answers include things like "tell me about a time you failed." The resume text, questions, answers and scores live in one SQLite file on your disk, and the API isn't reachable from outside your machine.

Where the open approach worked better than the closed one:

  • It costs nothing per interview. Practice only works if you do it a lot. With a local model there's no quota or bill to ration, so a tenth mock interview costs the same as the first: nothing.
  • No API key. Setup is one ollama pull, and nothing expires.
  • Swap the model with one line. OLLAMA_MODEL=gemma4:e4b gives better questions and feedback if your machine has the memory for it. Nothing else changes.
  • Control over the output. Constraining Gemma to a JSON schema through Ollama made feedback dependable enough to build a dashboard on.

One honest caveat: speech-to-text still uses the browser's Web Speech API, and Chrome sends that audio to Google's speech service. So PrepMate isn't fully offline yet. The AI, the data and your resume are local, but live transcription needs a connection. Moving transcription to a local Whisper model is the next step to close that gap.

Prize Categories

  • Best Use of Gemma: Gemma 4 (gemma4:e2b) runs locally through Ollama and generates every interview question, the follow-up rounds, and all scored feedback, with schema-constrained JSON output for the scorecards. <!-- Only keep the line below if you embed or link a DevRelay agent session above --> <!-- - Best Use of Entire: the agent session behind this build is embedded above. -->

Thanks for reading. If you try it, I'd like to hear how it scored you.

來源:DEV Community · dev.to