Skip to content
0

PawMatch: The AI-Powered Dog Breed Recommender

Executive Summary

PawMatch is an intelligent, conversational AI system designed to eliminate guesswork from dog adoption. Leveraging Google Gemini 2.0 and a proprietary, data-driven algorithm, the system provides potential dog owners with personalized, accurate breed recommendations through a natural, multi-turn chat experience. It analyzes user lifestyle, living situation, and preferences against a comprehensive database of 195 recognized dog breeds.


Requirements & Technical Implementation

RequirementPawMatch Technical Implementation
Conversational ApproachIntegrated Google Gemini 2.0 with a LangGraph state machine to manage complex, natural, multi-turn conversations and context.
Matching ApproachDeveloped a proprietary weighted scoring algorithm across 6 key categories, coupled with essential "deal-breaker" filtering for precise compatibility.
Results DisplayPresented comprehensive, engaging results featuring images, interactive radar charts, social share cards, and unique AI-generated breed stories.
Natural Language Processing (NLP)Implemented context-aware follow-ups and extraction logic to accurately parse and utilize preferences from open-ended user responses.
Dynamic QuestionsBuilt an adaptive questioning system that modifies the conversation flow and prompts based on real-time user input and current session context.

Live Application & Access

Try PawMatch Live

Note: A simple email/password account creation is required. This enables core functionality:

  • Saving conversation history and preferences across sessions.
  • Providing personalized, persistent match results.
  • Tracking and managing favorited breeds.

Privacy-friendly: No email verification is required. Feel free to use a temporary or test email (e.g., [email protected]) if you prefer not to share your real email address.

How to Get Started

  1. Browse Breeds - Explore all 195 breeds with filters and search to get familiar with the dataset
  2. Start a Match - Click "Find My Match" and chat with our AI to discover your perfect breed based on your lifestyle
  3. View Results - Get your top 3 personalized matches with detailed compatibility scores and explanations
  4. Compare Breeds - Use the comparison tool to see side-by-side trait analysis of multiple breeds
  5. Save Favorites - Mark breeds you love and access them anytime from your profile

No credit card or real email needed - just create an account and start exploring!


Project Scale & Data

  • 195 Dog Breeds: Sourced from AKC/FCI recognized classifications.
  • 17 Traits per Breed: Each trait is quantitatively rated on a 1-5 scale for detailed analysis.
  • 6,825+ High-Quality Images: An average of 35 unique images per breed.
  • 6 Matching Categories: Utilizing a sophisticated, weighted scoring system for optimal compatibility.

Advanced Feature Highlight (Video Generation)

StatusModel UsedGeneration TimeDescription
Temporarily DisabledGoogle Veo 3.1 Fast secondsCreates a personalized, 60-second "Day in the Life" video for the top matched breed, customized based on the user's profile and the breed's traits.

Reason for Disablement: The feature is fully implemented and functional. It was temporarily disabled to avoid unnecessary API costs during the development and competition judging periods.


Application Walkthrough & Key Features

1. Landing Page: First Impression

The homepage establishes trust and clarity with a clean, modern design. It features clear calls-to-action and visually highlights the breadth of the comprehensive breed dataset.

2. Conversational AI Interface

Powered by Google Gemini 2.0, the chat interface ensures an engaging and natural experience. The AI progressively asks relevant questions and offers convenient quick reply options to guide the user efficiently.

3. Match Results & Celebration

To create a memorable moment, users are presented with a celebratory confetti animation upon receiving their results. The top 3 breeds are clearly ranked (Gold/Silver/Bronze) with detailed compatibility scores.

4. Personality Visualization

Complex trait data is made instantly digestible through interactive radar charts. These charts visualize breed personalities across 6 key dimensions, empowering users to understand profiles at a glance.

5. Seamless Social Sharing

Users can effortlessly share their personalized match results directly from the results page using native mobile functionality or a desktop-friendly copy link.

6. Detailed Breed Information

Each breed is presented on a comprehensive detail page featuring image carousels, tabbed content, refined trait visualizations, and direct links to find breeders or adoption centers.


The data

The data consists of three datasets: data/breed_traits, data/trait_description, and a Github repo consisting of 30+ images per dog breed.

Dog breed traits

VariableClassDescription
BreedcharacterDog breed name
Affectionate With FamilycharacterPlacement on scale of 1–5 for the breed’s tendency to be affectionate with family
Good With Young ChildrencharacterPlacement on scale of 1–5 for the breed’s tendency to be good with young children
Good With Other DogscharacterPlacement on scale of 1–5 for the breed’s tendency to be good with other dogs
Shedding LevelcharacterPlacement on scale of 1–5 for the breed’s shedding level
Coat Grooming FrequencycharacterPlacement on scale of 1–5 for the breed’s grooming frequency
Drooling LevelcharacterPlacement on scale of 1–5 for the breed’s drooling level
Coat TypecharacterDescription of the breed’s coat type
Coat LengthcharacterDescription of the breed’s coat length
Openness To StrangerscharacterPlacement on scale of 1–5 for the breed’s openness to strangers
Playfulness LevelcharacterPlacement on scale of 1–5 for the breed’s playfulness
Watchdog/Protective NaturecharacterPlacement on scale of 1–5 for the breed’s protective instincts
Adaptability LevelcharacterPlacement on scale of 1–5 for the breed’s adaptability
Trainability LevelcharacterPlacement on scale of 1–5 for the breed’s trainability
Energy LevelcharacterPlacement on scale of 1–5 for the breed’s energy level
Barking LevelcharacterPlacement on scale of 1–5 for the breed’s barking level
Mental Stimulation NeedscharacterPlacement on scale of 1–5 for the breed’s mental stimulation needs

Trait descriptions

VariableClassDescription
TraitcharacterDog trait name
Trait_1characterDescription when scale = 1
Trait_5characterDescription when scale = 5
DescriptioncharacterLong-form explanation of the trait

Dog breed images

DetailDescription
CoverageBreeds recognized by the Fédération Cynologique Internationale (FCI)
Images per breed35
Total breeds356
FormatHigh-resolution JPEG images
import pandas as pd
dog_breeds = pd.read_csv('data/breed_traits.csv')
dog_breeds.head()
trait_descriptions = pd.read_csv('data/trait_description.csv')
trait_descriptions.head()

My Matching Algorithm

I designed a weighted scoring system that evaluates compatibility across 6 major life categories:

CategoryWeightRationale
Family Compatibility20%Critical for households with children
Activity Level Match25%Highest weight - mismatched energy causes most issues
Living Space Fit15%Size and adaptability matter for apartments vs houses
Grooming Compatibility15%Time commitment must match user availability
Training Match15%Experience level affects success with different breeds
Pet Compatibility10%Important for multi-pet households

Deal-Breaker Filtering

Before scoring, I apply hard filters for non-negotiable requirements:

  • Allergies → Eliminate high-shedding breeds
  • Apartment living → Filter out very large breeds
  • First-time owners → Prioritize easy-to-train breeds

Scoring Methodology

My algorithm calculates distance between user preferences and breed traits:

  • Exact match: 5/5 points
  • Close match (±1): 3-4/5 points
  • Poor match (±2+): 0-2/5 points

Final score is normalized to 0-100% for easy interpretation.

import numpy as np

def calculate_compatibility(breed_row, user_preferences):
    """
    Calculates a compatibility score (0-100) for a breed based on user preferences.
    
    Args:
        breed_row: DataFrame row with breed traits
        user_preferences: Dict with user profile data
        
    Returns:
        float: Compatibility score (0-100)
    """
    score = 0
    total_weight = 0
    
    # 1. Family & Household Compatibility (20% weight)
    if user_preferences.get('has_children'):
        # High importance for families with kids
        score += float(breed_row['Good With Young Children']) * 0.15
        total_weight += 0.15
        
    # Affection level
    score += float(breed_row['Affectionate With Family']) * 0.05
    total_weight += 0.05
        
    if user_preferences.get('has_other_dogs'):
        score += float(breed_row['Good With Other Dogs']) * 0.10
        total_weight += 0.10
    
    # 2. Activity Level Match (25% weight) - HIGHEST WEIGHT
    # Map user activity (1-5) to breed energy level
    user_activity = user_preferences.get('activity_level', 3)
    energy_diff = abs(float(breed_row['Energy Level']) - user_activity)
    # Closer match = higher score (5 - diff)
    energy_score = max(0, 5 - energy_diff)
    score += energy_score * 0.20
    total_weight += 0.20
    
    # Playfulness alignment
    score += float(breed_row['Playfulness Level']) * 0.05
    total_weight += 0.05
    
    # 3. Living Space Fit (15% weight)
    # Adaptability to living situation
    score += float(breed_row['Adaptability Level']) * 0.15
    total_weight += 0.15
    
    # 4. Grooming Compatibility (15% weight)
    # User preference: 1=Low effort, 5=High effort allowed
    user_grooming_effort = user_preferences.get('grooming_dedication', 3)
    # Penalize if breed needs more grooming than user can provide
    grooming_diff = max(0, float(breed_row['Coat Grooming Frequency']) - user_grooming_effort)
    grooming_score = max(0, 5 - grooming_diff)
    score += grooming_score * 0.15
    total_weight += 0.15
    
    # 5. Training Match (15% weight)
    # Higher trainability = easier for user
    score += float(breed_row['Trainability Level']) * 0.15
    total_weight += 0.15
    
    # Normalize to 0-100 scale
    if total_weight > 0:
        final_score = (score / (total_weight * 5)) * 100
    else:
        final_score = 0
        
    return round(final_score, 1)

def find_top_matches(user_prefs, breeds_df, top_n=3):
    """
    Finds the top N matching breeds for a user profile.
    
    Args:
        user_prefs: Dict with user preferences
        breeds_df: DataFrame with breed data
        top_n: Number of top matches to return
        
    Returns:
        DataFrame with top matches and scores
    """
    # Create a copy to avoid modifying original
    scored_breeds = breeds_df.copy()
    
    # Calculate score for each breed
    scored_breeds['Compatibility'] = scored_breeds.apply(
        lambda row: calculate_compatibility(row, user_prefs), axis=1
    )
    
    # Sort by score descending
    top_matches = scored_breeds.sort_values('Compatibility', ascending=False).head(top_n)
    
    return top_matches[['Breed', 'Compatibility', 'Energy Level', 'Trainability Level', 
                        'Good With Young Children', 'Coat Grooming Frequency']]

print("Matching algorithm loaded successfully!")
# Test Case 1: Active Family with Young Children
print("=" * 60)
print("TEST CASE: Active Family with Young Children")
print("=" * 60)

family_user = {
    'has_children': True,
    'has_other_dogs': False,
    'activity_level': 4,  # Active lifestyle
    'grooming_dedication': 2,  # Low maintenance preferred
}

print(f"\n User Profile:")
print(f"   - Has young children: Yes")
print(f"   - Activity level: 4/5 (Active)")
print(f"   - Grooming dedication: 2/5 (Low maintenance)")
print(f"\n Finding top 3 matches...\n")

matches = find_top_matches(family_user, dog_breeds, top_n=3)

for i, (index, breed) in enumerate(matches.iterrows(), 1):
    print(f"{'Best Match' if i==1 else 'Second Best Match' if i==2 else 'Third Best Match'} Match #{i}: {breed['Breed']}")
    print(f"   Compatibility Score: {breed['Compatibility']:.1f}%")
    print(f"   Energy Level: {breed['Energy Level']}/5")
    print(f"   Good with Children: {breed['Good With Young Children']}/5")
    print(f"   Trainability: {breed['Trainability Level']}/5")
    print(f"   Grooming Needs: {breed['Coat Grooming Frequency']}/5")
    print()

Technical Architecture

Technology Stack

ComponentTechnology ChoicesRationale
FrontendNext.js 15 + React 19, TypeScriptServer-Side Rendering (SSR) for optimal performance and improved type safety.
StylingTailwindCSS + Shadcn/UIEnables rapid, utility-first styling and consistent, high-quality UI components.
VisualizationRecharts, Canvas ConfettiUsed for interactive data visualizations (radar charts) and engaging celebration animations.
Backend APIFastAPI (Python)High-performance, asynchronous framework suitable for handling concurrent API requests.
Core AIGoogle Gemini 2.0, LangGraphProvides the conversational intelligence and sophisticated state management for multi-turn chats.
DatabasePostgreSQLReliable, transactional storage for the comprehensive 195-breed dataset.
Caching/QueueRedisImplemented for intelligent caching to manage API rate limits and for job queue management.
DeploymentRailway, Docker, GitHubRailway for consistent hosting; Docker for containerization; GitHub for version control and CI/CD pipeline integration.

Lessons Learned & Challenges

What Worked Well (Success Factors)

  1. Conversational UI: Users overwhelmingly preferred the natural chat interaction over traditional form filling, driving higher engagement.
  2. Visual Feedback: Interactive Radar Charts successfully translated complex trait data into accessible, easily understandable visual profiles.
  3. Emotional Moments: Strategic use of Confetti and AI-generated stories created memorable, high-impact user experiences.
  4. Progressive Disclosure: Asking questions gradually, managed by LangGraph, prevented user overwhelm and maintained conversation flow.

Challenges I Overcame (Problem Solving)

  1. Ambiguous Input: Successfully implemented logic using Gemini 2.0 to identify and resolve unclear user responses through intelligent clarifying questions.
  2. Performance & Cost: Solved API rate limit concerns and optimized speed by implementing smart Redis caching mechanisms.
  3. Mobile UX: Addressed various design issues through iterative testing, resulting in a highly responsive and intuitive mobile application.
  4. Data Quality: Developed robust normalization routines to handle and standardize inconsistent trait data (e.g., traits with internal spacing) before API use.

Future Vision & Roadmap

PhaseTimelineKey Features
Phase 1Next 3 monthsRe-enable Video Generation using Google Veo, implement user testimonials and community reviews, and add advanced filtering (size, coat type, etc.).
Phase 26-12 monthsDevelop native mobile apps (iOS/Android), introduce community forums and Q&A, and establish a Breeder Verification System and adoption center partnerships.
Phase 3Long-termExplore Augmented Reality (AR) breed visualization, virtual breed meetups, a training course marketplace, and a subscription-based pet care service.

Conclusion

Building PawMatch was a great opportunity to leverage AI and data science to solve a significant real-world problem—finding the perfect pet—in a user-friendly and engaging way. By combining:

  • Natural Conversation (Gemini 2.0)
  • Data-Driven Matching (195 breeds 17 traits)
  • Beautiful UX (confetti, radar charts, social cards)
  • Emotional Storytelling ("Day in the Life" narratives)

I created an application that moves beyond simple recommendations to genuinely help families find their ideal companion, ultimately ensuring happy homes for both humans and dogs. While the core is robust, there is a clear roadmap for further polishing and scaling this application beyond the competition. I am committed to continuing this work.


🔗 Project Links


NB: This entire application was built in a short timeframe, leveraging AI coding assistance to accelerate the development process. I am actively seeking to continue building this application. All code is open-source, and contributions or use of the codebase are highly welcome.

# This example code shows how to run and access apps in a session
import os
from http.server import SimpleHTTPRequestHandler
from socketserver import TCPServer
from threading import Thread
from IPython.display import IFrame

session_id = os.environ["PROXYTOKEN"]
port = 9000
path = f"/proxy/{port}/absolute/{session_id}"
interface ="0.0.0.0"
domain = "https://www.datacamp-workspace.com"
url = domain + path

# The thread runs a basic server in a session
# Replace this code according to the documentation of the package exposing a user interface
class CustomHandler(SimpleHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        self.wfile.write(b"<html><body><h1>Hello, World!</h1></body></html>")

def start_server():
    with TCPServer((interface, port), CustomHandler) as httpd:
        httpd.serve_forever()

t = Thread(target=start_server)
t.daemon = True
t.start()

print(f"Serving at {url}")
IFrame(url, width='100%', height=100)