What GenAI Projects to Build to Get Hired in 2025
Blog Post

What GenAI Projects to Build to Get Hired in 2025

Jake McCluskey
Back to blog

Recruiters skip over AI portfolios filled with basic chatbots and OpenAI API wrappers because those projects don't prove you can solve production problems. To stand out, you need projects that demonstrate cited retrieval, autonomous agent control flow, and CI/CD for AI systems. Four or five advanced ones work better than ten simple ones. This guide walks you through five specific portfolio projects that showcase these skills, using free-tier APIs and open-source tools you can start building today.

Why Basic GenAI Projects Don't Get You Hired Anymore

A to-do list app with ChatGPT integration proves you can read API documentation. That's it. Roughly 78% of AI portfolio projects submitted to entry-level positions are variations of the same ideas: a chatbot interface, a document summarizer, or a text generator with a custom prompt.

Recruiters and hiring managers look for evidence you understand the hard parts. How to make retrieval systems cite their sources accurately. How to build agents that know when to stop. How to test AI behavior in production. These skills separate candidates who've watched tutorials from candidates who can ship.

The job market shifted in late 2024. Companies hiring for AI roles now expect you to demonstrate competence with retrieval architectures, agent orchestration, and evaluation frameworks. A long list of simple projects signals less than a short list of technically challenging ones, honestly.

The Three Technical Challenges That Prove GenAI Competence

First challenge: cited retrieval. Anyone can stuff documents into a vector database and return similar chunks. Proving which specific page or section supports each claim in an AI response requires hybrid search, reranking, and citation tracking. This is what RAG systems look like in production.

Second challenge: agent stopping logic. Autonomous agents that run forever or quit too early are useless. You need to demonstrate human-in-the-loop approval gates, confidence thresholds, and graceful failure modes. This proves you understand how ReAct loops work and when to break them.

Third challenge: CI/CD for AI systems. Models drift, prompts break, and retrieval quality degrades silently. Building automated tests that catch these failures before users do shows you think about AI systems as software that needs maintenance, not magic that just works.

DocuMind: Building RAG with Hybrid Search and Page-Level Citations

This project demonstrates production-grade retrieval. You build a system that answers questions about technical documentation and cites the exact page number and section for each claim. Users can verify every statement your AI makes.

Start with a corpus of 500 to 1000 page PDF documents. Use PyMuPDF to extract text while preserving page numbers and section headers. Split documents into chunks of roughly 400 tokens with 50-token overlap, storing the page number and section title with each chunk.

Implementing Hybrid Search

Use Qdrant's free tier to store vector embeddings generated with the sentence-transformers/all-MiniLM-L6-v2 model. This model is fast and runs locally without API costs. For each query, perform both semantic search (vector similarity) and keyword search (BM25) then combine results.


from qdrant_client import QdrantClient
from sentence_transformers import SentenceTransformer
from rank_bm25 import BM25Okapi

def hybrid_search(query, top_k=10):
    # Vector search
    query_vector = model.encode(query)
    vector_results = client.search(
        collection_name="docs",
        query_vector=query_vector,
        limit=top_k
    )
    
    # BM25 keyword search
    bm25_scores = bm25.get_scores(query.split())
    bm25_results = sorted(enumerate(bm25_scores), 
                         key=lambda x: x[1], 
                         reverse=True)[:top_k]
    
    # Combine with reciprocal rank fusion
    combined = reciprocal_rank_fusion(vector_results, bm25_results)
    return combined[:5]

Adding Reranking and Citations

Take your top 10 hybrid results and rerank them using a cross-encoder model like ms-marco-MiniLM-L-6-v2. This typically improves relevance by 15 to 20% compared to vector search alone. Keep the top chunks and pass them to your LLM with explicit instructions to cite page numbers. Three to five usually works.

Use a structured prompt that requires the model to format citations: "For each claim, add [Page X, Section Y] immediately after the statement." Then parse these citations in your response rendering to create clickable links back to source documents. This proves your retrieval system is grounded and auditable.

TaskPilot: Autonomous Agent with Human Approval Gates

This project shows you can build agents that don't run wild. TaskPilot is an autonomous task executor that breaks down complex requests, proposes an execution plan, waits for human approval, then executes with checkpoints.

Use LangGraph to implement the state machine. The agent moves through states: planning, awaiting_approval, executing, and complete. At the awaiting_approval state, execution pauses until a human reviews the plan and approves or modifies it.

Building a Custom MCP Server

Implement a Model Context Protocol server that gives your agent access to real tools: file system operations, API calls, and database queries. MCP standardizes how agents interact with external systems, and building a custom server demonstrates you understand agentic loops and MCP integration.


from mcp import Server, Tool

server = Server("taskpilot-tools")

@server.tool()
async def read_file(path: str) -> str:
    """Read contents of a file"""
    with open(path, 'r') as f:
        return f.read()

@server.tool()
async def execute_query(query: str) -> dict:
    """Execute SQL query and return results"""
    # Add safety checks and query validation
    if not is_safe_query(query):
        raise ValueError("Query failed safety check")
    return db.execute(query).fetchall()

Implementing Confidence Thresholds

Add logic that makes the agent pause when confidence drops below 0.7 on a scale of 0 to 1. Use a secondary LLM call that evaluates whether the agent has enough information to proceed. If not, it asks the user a clarifying question instead of guessing. This prevents the "confidently wrong" behavior that makes AI agents unusable in production.

Track how often your agent requests human input versus proceeding autonomously. A well-calibrated agent on typical tasks should pause for approval roughly 20 to 30% of the time. Not never and not constantly.

VoiceCoach: Interruptible Real-Time Voice AI

Real-time voice AI is technically challenging because you need sub-4-second latency and natural interruption handling. VoiceCoach is a mock interview coach that asks questions, listens to answers, and provides feedback, all through voice with natural turn-taking.

Use Deepgram's free tier for streaming speech-to-text and ElevenLabs' free tier for text-to-speech. The hard part is building the interruption logic: when the user starts speaking, you need to stop the AI's audio output immediately and process the interruption.

Building the Audio Pipeline

Set up a WebSocket connection that handles bidirectional audio streaming. Use a voice activity detection (VAD) model like Silero VAD to detect when the user starts speaking. When VAD triggers during AI speech, send a stop signal to the audio player and flush the TTS buffer.


import torch
from deepgram import Deepgram
from elevenlabs import stream

class VoiceCoach:
    def __init__(self):
        self.vad_model, _ = torch.hub.load(
            repo_or_dir='snakers4/silero-vad',
            model='silero_vad'
        )
        self.is_speaking = False
        
    async def handle_audio_stream(self, audio_chunk):
        # Check for user speech
        speech_prob = self.vad_model(audio_chunk, 16000).item()
        
        if speech_prob > 0.5 and self.is_speaking:
            # User interrupted, stop AI speech
            await self.stop_playback()
            self.is_speaking = False
            
        # Process transcription
        transcript = await self.transcribe(audio_chunk)
        if transcript:
            response = await self.generate_response(transcript)
            await self.speak(response)

Achieving Sub-4-Second Latency

Measure end-to-end latency from when the user stops speaking to when AI audio starts playing. Break this into components: transcription finalization (typically 500 to 800ms), LLM response generation (1000 to 2000ms), and TTS synthesis (800 to 1200ms). To hit your 4-second target, use streaming for both LLM and TTS.

Stream the LLM response token by token and start TTS as soon as you have a complete sentence. This cuts perceived latency in half compared to waiting for the full response. Most users can't tell when latency drops below 3 seconds, which makes this threshold production-ready.

AutoQA: Browser Testing Agent That Files Bugs

This project demonstrates you can build AI systems that test themselves. AutoQA is an autonomous agent that navigates web applications, performs test scenarios, detects bugs, captures screenshots, and files detailed bug reports.

Use Playwright for browser automation and GPT-4 Vision or Claude 3.5 Sonnet for visual understanding. The agent receives a test scenario like "Sign up for a new account and add an item to cart" then executes it while checking for errors.

Implementing Visual Verification

After each action (click, type, navigate), capture a screenshot and send it to a vision model with the question: "Did this action succeed? Are there any error messages or unexpected states?" The model returns a structured response with success status and any issues detected.


from playwright.async_api import async_playwright
import anthropic

async def test_scenario(scenario: str):
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        
        steps = await plan_test_steps(scenario)
        
        for step in steps:
            await execute_step(page, step)
            screenshot = await page.screenshot()
            
            # Visual verification
            verification = await claude.messages.create(
                model="claude-3-5-sonnet-20241022",
                max_tokens=1024,
                messages=[{
                    "role": "user",
                    "content": [
                        {
                            "type": "image",
                            "source": {
                                "type": "base64",
                                "media_type": "image/png",
                                "data": screenshot
                            }
                        },
                        {
                            "type": "text",
                            "text": f"Did this step succeed: {step}?"
                        }
                    ]
                }]
            )
            
            if "error" in verification.content[0].text.lower():
                await file_bug_report(step, screenshot, verification)

Building the Bug Filing System

When the agent detects a bug, it generates a structured report with reproduction steps, expected behavior, actual behavior, screenshot evidence, and browser details. Integrate with GitHub Issues or Jira APIs to automatically file these reports. This proves you understand how to make AI systems that improve software quality, not just answer questions.

SpendLens: Full AI SaaS with Receipt Parsing and Grounded Chat

This capstone project ties everything together. SpendLens is an expense tracking SaaS that uses AI to parse receipt photos, validate expenses against company policies, and answer questions about spending with grounded, cited responses.

The receipt parsing component uses GPT-4 Vision to extract merchant, date, amount, and line items from photos. The validation component checks extracted data against a rules engine (no alcohol, meals under $50, valid business categories). The chat component uses RAG over historical expenses to answer questions like "How much did we spend on software last quarter?"

Implementing Multi-Stage Validation

Don't trust the vision model's first output. Implement validation in stages: initial extraction, confidence scoring, and human review flagging. If the model's confidence on any field drops below 0.85, flag that receipt for human review before posting to the accounting system. Simple.


async def process_receipt(image_data):
    # Stage 1: Extract data
    extraction = await extract_receipt_data(image_data)
    
    # Stage 2: Confidence scoring
    confidence = await score_extraction_confidence(
        extraction, 
        image_data
    )
    
    # Stage 3: Validation
    validation_result = validate_against_policy(extraction)
    
    if confidence['overall'] < 0.85 or not validation_result['valid']:
        return {
            'status': 'needs_review',
            'extraction': extraction,
            'issues': validation_result['issues'],
            'confidence': confidence
        }
    
    return {
        'status': 'approved',
        'extraction': extraction
    }

Adding Grounded Chat Over Expenses

Build a RAG system over the expense database that cites specific transactions in its answers. When a user asks about spending patterns, the system queries the database, retrieves relevant transactions, and generates a response that links to the source receipts. This demonstrates you can build AI knowledge bases that capture context and provide verifiable answers.

Store embeddings of expense descriptions and use hybrid search to find relevant transactions. Include the transaction ID, date, and amount in the context passed to the LLM, then format responses with inline citations like "Software expenses totaled $12,450 in Q4 [Transactions: #1234, #1256, #1289]."

How to Build These Projects Using Free-Tier APIs

You can build all five projects without spending money on API calls during development. Use Anthropic's free tier (currently $5 credit for new accounts), OpenAI's $5 new user credit, or run models locally with Ollama on your Mac.

For embeddings, use sentence-transformers models that run locally. For vector storage, Qdrant offers 1GB free and Pinecone offers 100k vectors free. For voice, Deepgram and ElevenLabs both have generous free tiers. The bottleneck isn't money. It's your time and technical execution.

Deploy your projects on free hosting: Vercel for frontends, Railway or Render for backends (both have free tiers), and Supabase for databases. Your total cost during development should be close to zero, and you can add paid tiers once you're job hunting and want to show projects running live.

Why 3-5 Advanced Projects Beat a Long List of Basic Ones

Recruiters spend an average of 6 to 8 seconds on initial resume screens. They don't read through ten projects. They scan for signals of technical depth. One project with hybrid search, reranking, and citations signals more competence

Ready to stop reading and start shipping?

Get a free AI-powered SEO audit of your site

We'll crawl your site, benchmark your local pack, and hand you a prioritized fix list in minutes. No call required.

Run my free audit
WANT THE SHORTCUT

Need help applying this to your business?

The post above is the framework. Spend 30 minutes with me and we'll map it to your specific stack, budget, and timeline. No pitch, just a real scoping conversation.