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
| Requirement | PawMatch Technical Implementation |
|---|---|
| Conversational Approach | Integrated Google Gemini 2.0 with a LangGraph state machine to manage complex, natural, multi-turn conversations and context. |
| Matching Approach | Developed a proprietary weighted scoring algorithm across 6 key categories, coupled with essential "deal-breaker" filtering for precise compatibility. |
| Results Display | Presented 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 Questions | Built an adaptive questioning system that modifies the conversation flow and prompts based on real-time user input and current session context. |
Live Application & Access
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
- Browse Breeds - Explore all 195 breeds with filters and search to get familiar with the dataset
- Start a Match - Click "Find My Match" and chat with our AI to discover your perfect breed based on your lifestyle
- View Results - Get your top 3 personalized matches with detailed compatibility scores and explanations
- Compare Breeds - Use the comparison tool to see side-by-side trait analysis of multiple breeds
- 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)
| Status | Model Used | Generation Time | Description |
|---|---|---|---|
| Temporarily Disabled | Google Veo 3.1 Fast | Creates 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
| Variable | Class | Description |
|---|---|---|
| Breed | character | Dog breed name |
| Affectionate With Family | character | Placement on scale of 1–5 for the breed’s tendency to be affectionate with family |
| Good With Young Children | character | Placement on scale of 1–5 for the breed’s tendency to be good with young children |
| Good With Other Dogs | character | Placement on scale of 1–5 for the breed’s tendency to be good with other dogs |
| Shedding Level | character | Placement on scale of 1–5 for the breed’s shedding level |
| Coat Grooming Frequency | character | Placement on scale of 1–5 for the breed’s grooming frequency |
| Drooling Level | character | Placement on scale of 1–5 for the breed’s drooling level |
| Coat Type | character | Description of the breed’s coat type |
| Coat Length | character | Description of the breed’s coat length |
| Openness To Strangers | character | Placement on scale of 1–5 for the breed’s openness to strangers |
| Playfulness Level | character | Placement on scale of 1–5 for the breed’s playfulness |
| Watchdog/Protective Nature | character | Placement on scale of 1–5 for the breed’s protective instincts |
| Adaptability Level | character | Placement on scale of 1–5 for the breed’s adaptability |
| Trainability Level | character | Placement on scale of 1–5 for the breed’s trainability |
| Energy Level | character | Placement on scale of 1–5 for the breed’s energy level |
| Barking Level | character | Placement on scale of 1–5 for the breed’s barking level |
| Mental Stimulation Needs | character | Placement on scale of 1–5 for the breed’s mental stimulation needs |
Trait descriptions
| Variable | Class | Description |
|---|---|---|
| Trait | character | Dog trait name |
| Trait_1 | character | Description when scale = 1 |
| Trait_5 | character | Description when scale = 5 |
| Description | character | Long-form explanation of the trait |
Dog breed images
| Detail | Description |
|---|---|
| Coverage | Breeds recognized by the Fédération Cynologique Internationale (FCI) |
| Images per breed | 35 |
| Total breeds | 356 |
| Format | High-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:
| Category | Weight | Rationale |
|---|---|---|
| Family Compatibility | 20% | Critical for households with children |
| Activity Level Match | 25% | Highest weight - mismatched energy causes most issues |
| Living Space Fit | 15% | Size and adaptability matter for apartments vs houses |
| Grooming Compatibility | 15% | Time commitment must match user availability |
| Training Match | 15% | Experience level affects success with different breeds |
| Pet Compatibility | 10% | 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
| Component | Technology Choices | Rationale |
|---|---|---|
| Frontend | Next.js 15 + React 19, TypeScript | Server-Side Rendering (SSR) for optimal performance and improved type safety. |
| Styling | TailwindCSS + Shadcn/UI | Enables rapid, utility-first styling and consistent, high-quality UI components. |
| Visualization | Recharts, Canvas Confetti | Used for interactive data visualizations (radar charts) and engaging celebration animations. |
| Backend API | FastAPI (Python) | High-performance, asynchronous framework suitable for handling concurrent API requests. |
| Core AI | Google Gemini 2.0, LangGraph | Provides the conversational intelligence and sophisticated state management for multi-turn chats. |
| Database | PostgreSQL | Reliable, transactional storage for the comprehensive 195-breed dataset. |
| Caching/Queue | Redis | Implemented for intelligent caching to manage API rate limits and for job queue management. |
| Deployment | Railway, Docker, GitHub | Railway for consistent hosting; Docker for containerization; GitHub for version control and CI/CD pipeline integration. |
Lessons Learned & Challenges
What Worked Well (Success Factors)
- Conversational UI: Users overwhelmingly preferred the natural chat interaction over traditional form filling, driving higher engagement.
- Visual Feedback: Interactive Radar Charts successfully translated complex trait data into accessible, easily understandable visual profiles.
- Emotional Moments: Strategic use of Confetti and AI-generated stories created memorable, high-impact user experiences.
- Progressive Disclosure: Asking questions gradually, managed by LangGraph, prevented user overwhelm and maintained conversation flow.
Challenges I Overcame (Problem Solving)
- Ambiguous Input: Successfully implemented logic using Gemini 2.0 to identify and resolve unclear user responses through intelligent clarifying questions.
- Performance & Cost: Solved API rate limit concerns and optimized speed by implementing smart Redis caching mechanisms.
- Mobile UX: Addressed various design issues through iterative testing, resulting in a highly responsive and intuitive mobile application.
- 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
| Phase | Timeline | Key Features |
|---|---|---|
| Phase 1 | Next 3 months | Re-enable Video Generation using Google Veo, implement user testimonials and community reviews, and add advanced filtering (size, coat type, etc.). |
| Phase 2 | 6-12 months | Develop native mobile apps (iOS/Android), introduce community forums and Q&A, and establish a Breeder Verification System and adoption center partnerships. |
| Phase 3 | Long-term | Explore 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
- Live App: https://paw-match-frontend-production.up.railway.app/
- API Documentation: https://paw-match-production.up.railway.app/docs
- Source Code Repositories:
- Contact: [email protected]
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)