palate / build_pilot_data.py
KassimYassin's picture
Deploy Palate multi-city culinary engine with Gradio and FastAPI
fb8df06 verified
Raw History Blame Contribute Delete
4.66 kB
# Multi-City Global Pilot Data Ingestion & Enrichment Engine
# Pilots: Dubai (UAE) & Istanbul (Turkey) + Amsterdam (NL)
import os
import json
import math
import sys
import random
import pickle
from collections import Counter
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import TruncatedSVD
if sys.platform == 'win32' and hasattr(sys.stdout, 'reconfigure'):
sys.stdout.reconfigure(encoding='utf-8')
DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
random.seed(42)
def haversine_distance_m(lat1, lon1, lat2, lon2):
R = 6371000.0
phi1 = math.radians(lat1)
phi2 = math.radians(lat2)
delta_phi = math.radians(lat2 - lat1)
delta_lambda = math.radians(lon2 - lon1)
a = math.sin(delta_phi / 2.0) ** 2 + math.cos(phi1) * math.cos(phi2) * math.sin(delta_lambda / 2.0) ** 2
c = 2.0 * math.atan2(math.sqrt(a), math.sqrt(1.0 - a))
return R * c
def build_semantic_model_for_city(city_id, places):
city_dir = os.path.join(DATA_DIR, city_id)
os.makedirs(city_dir, exist_ok=True)
docs = []
for p in places:
name = p.get('name', '')
cat = p.get('primary_category', '')
alts = ' '.join(p.get('alternate_categories', []))
cuisine = p.get('cuisine', '')
badges = ' '.join(p.get('craft_badges', []))
details = ' '.join(p.get('craft_details', []))
must_try = p.get('must_try', '')
neighborhood = p.get('neighborhood', '')
address = p.get('address', '')
heritage = p.get('heritage', {})
heritage_text = (heritage.get('status', '') + ' ' + heritage.get('badge', '') + ' ' + heritage.get('era', '')) if heritage.get('is_monument') else ''
own = p.get('ownership', {})
own_text = own.get('label', '') + ' ' + own.get('badge', '')
celiac = p.get('celiac_safety', {})
celiac_text = ('celiac safe gluten free ' + str(celiac.get('badge', '')) + ' ' + str(celiac.get('certified_by', ''))) if celiac.get('is_safe') else ''
scratch = p.get('scratch_kitchen', {})
scratch_text = ('scratch kitchen in-house production ' + str(scratch.get('badge', ''))) if scratch.get('is_scratch') else ''
hosp = p.get('hospitality', {})
hosp_text = ('free tap water welcoming hospitality ' + str(hosp.get('badge', ''))) if hosp.get('free_tap_water') else ''
amenities = p.get('amenities', {})
amenity_text = []
if amenities.get('outdoor_seating'): amenity_text.append('outdoor seating open air patio terrace')
if amenities.get('canal_terrace'): amenity_text.append('waterfront canal marina terrace view')
if amenities.get('microbrewery'): amenity_text.append('craft microbrewery house brewed')
if amenities.get('in_house_roastery'): amenity_text.append('in house micro roastery specialty coffee beans single origin')
acc = p.get('accreditation') or {}
acc_text = (str(acc.get('award_tier', '')) + ' ' + str(acc.get('review_quote', ''))) if acc else ''
doc = name + '. Type: ' + cat + ' ' + alts + '. Cuisine: ' + cuisine + '. Craft: ' + badges + ' ' + scratch_text + '. Details: ' + details + '. Heritage: ' + heritage_text + '. Ownership: ' + own_text + '. Kitchen Safety: ' + celiac_text + '. Hospitality: ' + hosp_text + '. Amenities: ' + ' '.join(amenity_text) + '. Critical awards: ' + acc_text + '. Location: ' + neighborhood + ' ' + address + '. Must try signature: ' + must_try + '.'
docs.append(doc)
print('Building semantic vector space for ' + city_id + ' with ' + str(len(docs)) + ' places...')
vectorizer = TfidfVectorizer(
ngram_range=(1, 2),
sublinear_tf=True,
max_features=5000,
stop_words='english'
)
tfidf_matrix = vectorizer.fit_transform(docs)
n_components = min(128, tfidf_matrix.shape[1] - 1)
svd = TruncatedSVD(n_components=n_components, random_state=42)
dense_vectors = svd.fit_transform(tfidf_matrix)
norms = np.linalg.norm(dense_vectors, axis=1, keepdims=True)
norms[norms == 0] = 1.0
normalized_vectors = dense_vectors / norms
vectors_path = os.path.join(city_dir, 'vectors.npy')
model_path = os.path.join(city_dir, 'semantic_model.pkl')
np.save(vectors_path, normalized_vectors)
with open(model_path, 'wb') as f:
pickle.dump({'vectorizer': vectorizer, 'svd': svd}, f)
print('Saved ' + city_id + ' vectors to ' + vectors_path + ' and model to ' + model_path)