6.3 KiB
AI Recommendation Type Fix
Problem Statement
The AI recommendation system was hardcoding recommended_type: 'daily_tour' for all recommendations, regardless of the actual service being matched. This caused inconsistencies where:
- A
private_guideservice would be recommended but labeled asdaily_tour - The UI couldn't properly distinguish between different service types
- The system couldn't recommend
driver_caroractivity_bundleservices
Solution Overview
The fix implements dynamic type derivation from the matched service slug, ensuring that:
recommended_typeis always derived from the actual service slug- All three service types (
private_guide,driver_car,daily_tour) are valid outputs - The UI renders recommendations strictly based on AI output without assumptions
Changes Made
1. Edge Function: analyze-trip/index.ts
Rule-Based Matching (Lines 475-530)
// CRITICAL: Derive recommended_type from matched service slug
let recommendedType: 'daily_tour' | 'private_guide' | 'driver_car' | 'activity_bundle' = 'daily_tour';
if (matchedDailyTour.slug === 'private_guide') {
recommendedType = 'private_guide';
} else if (matchedDailyTour.slug === 'driver_car') {
recommendedType = 'driver_car';
} else if (matchedDailyTour.slug === 'activity_bundle') {
recommendedType = 'activity_bundle';
} else {
// All other slugs (red_tour, green_tour, blue_tour, balloon_day, etc.) are daily tours
recommendedType = 'daily_tour';
}
Logic:
- If slug is
private_guide→ type isprivate_guide - If slug is
driver_car→ type isdriver_car - If slug is
activity_bundle→ type isactivity_bundle - If slug is any tour (red_tour, green_tour, etc.) → type is
daily_tour
AI Response Validation (Lines 756-778)
// CRITICAL: Validate and derive recommended_type from daily_tour_slug
if (analysis.daily_tour_slug) {
if (analysis.daily_tour_slug === 'private_guide') {
analysis.recommended_type = 'private_guide';
} else if (analysis.daily_tour_slug === 'driver_car') {
analysis.recommended_type = 'driver_car';
} else if (analysis.daily_tour_slug === 'activity_bundle') {
analysis.recommended_type = 'activity_bundle';
} else if (['red_tour', 'green_tour', 'blue_tour', 'balloon_day', 'mixed_custom'].includes(analysis.daily_tour_slug)) {
analysis.recommended_type = 'daily_tour';
}
}
Purpose: Ensures AI responses are validated and corrected if the AI returns inconsistent type/slug combinations.
Updated AI Prompt (Lines 673-698)
Added clear instructions to the AI:
ÖNEMLİ KURAL:
- recommended_type ve daily_tour_slug UYUMLU OLMALI!
- Eğer daily_tour_slug = "private_guide" ise, recommended_type = "private_guide"
- Eğer daily_tour_slug = "driver_car" ise, recommended_type = "driver_car"
- Eğer daily_tour_slug = "red_tour/green_tour/blue_tour/balloon_day/mixed_custom" ise, recommended_type = "daily_tour"
2. Database: Added Missing Service Types
Migration: add_driver_car_and_activity_bundle_services_fixed
Added two new service types to daily_tours table:
INSERT INTO daily_tours (slug, title, description, ...) VALUES
('driver_car', 'Şoförlü Araç Hizmeti', '...'),
('activity_bundle', 'Aktivite Paketi', '...');
Current Service Types:
red_tour→ daily_tourgreen_tour→ daily_tourblue_tour→ daily_tourballoon_day→ daily_tourprivate_guide→ private_guidedriver_car→ driver_caractivity_bundle→ activity_bundle
3. UI Components
TourModal.tsx
Added type labels for better UX:
const typeLabels: Record<string, string> = {
daily_tour: 'Günlük Tur',
private_guide: 'Özel Rehber',
driver_car: 'Şoförlü Araç',
activity_bundle: 'Aktivite Paketi',
};
Updated dialog description to show Turkish labels:
{typeLabels[analysis.recommended_type] || analysis.recommended_type}
AITourRecommendation.tsx
Already had proper type labels and renders based on analysis.recommended_type without assumptions.
Type Mapping Rules
| Service Slug | Recommended Type | Description |
|---|---|---|
red_tour |
daily_tour |
Full-day Red Tour |
green_tour |
daily_tour |
Full-day Green Tour |
blue_tour |
daily_tour |
Full-day Blue Tour |
balloon_day |
daily_tour |
Balloon + Light Tour |
mixed_custom |
daily_tour |
Custom Mixed Tour |
private_guide |
private_guide |
Private Guide Service |
driver_car |
driver_car |
Driver with Car Service |
activity_bundle |
activity_bundle |
Activity Package |
Validation Flow
1. AI/Rule-Based Matching
↓
2. Match Service Slug (e.g., "private_guide")
↓
3. Derive Type from Slug
↓
4. Return Response with:
- recommended_type: "private_guide"
- daily_tour_slug: "private_guide"
↓
5. UI Renders Based on Type
- Shows "Özel Rehber" label
- Filters providers with private_guide service
Testing Checklist
- Rule-based matching derives correct type
- AI response validation corrects inconsistencies
- All service types (daily_tour, private_guide, driver_car, activity_bundle) can be recommended
- UI displays correct Turkish labels
- search-tours edge function filters by daily_tour_slug
- Database has all service types
- Lint passes without errors
Debug Information
The system now includes detailed debug info in responses:
{
"debug_info": {
"recommendation_reasoning": "Matched service 'private_guide' (type: private_guide) with 75% confidence. ..."
}
}
This helps track:
- Which service was matched
- What type was derived
- Why the recommendation was made
Benefits
- Consistency: Type always matches the actual service being recommended
- Flexibility: All service types can be recommended based on trip characteristics
- Transparency: Debug info shows exactly how the type was derived
- Maintainability: Single source of truth for type derivation logic
- User Experience: Proper Turkish labels for all service types
Future Enhancements
- Add more service types as needed (e.g.,
photography_tour,culinary_tour) - Implement confidence-based type selection (e.g., if confidence < 0.7, suggest driver_car instead of full tour)
- Add A/B testing to compare recommendation accuracy