import gradio as gr import pandas as pd import numpy as np import torch from transformers import CLIPProcessor, CLIPModel from datasets import load_dataset from diffusers import StableDiffusionPipeline from sklearn.metrics.pairwise import cosine_similarity import warnings warnings.filterwarnings('ignore') custom_css = """ body { background-image: url('https://huggingface.co/spaces/matanzig/Interior-Design-GenAI/resolve/main/viss.jpeg'); background-size: 130% 130%; background-position: 0% 0%; background-attachment: fixed; animation: panBackground 40s ease-in-out infinite alternate; } @keyframes panBackground { 0% { background-position: 0% 0%; } 100% { background-position: 100% 100%; } } .gradio-container { background: rgba(20, 20, 20, 0.75) !important; border-radius: 20px; box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.5); backdrop-filter: blur(5px); border: 1px solid rgba(255, 255, 255, 0.1); } .visionary-title { font-size: 3.5rem; font-weight: 900; text-align: center; letter-spacing: 4px; margin-bottom: 5px; margin-top: 15px; background: linear-gradient(270deg, #b8860b, #ffd700, #fff8dc, #b8860b); background-size: 200% 200%; -webkit-background-clip: text; -webkit-text-fill-color: transparent; animation: goldShine 4s ease infinite; transition: transform 0.3s ease, text-shadow 0.3s ease; cursor: pointer; } .visionary-title:hover { transform: scale(1.03); text-shadow: 0px 0px 20px rgba(255, 215, 0, 0.4); } @keyframes goldShine { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } .visionary-subtitle { text-align: center; color: rgba(255, 255, 255, 0.7); font-size: 1.2rem; letter-spacing: 2px; margin-bottom: 30px; } .custom-card { background: rgba(15, 15, 15, 0.6) !important; border-radius: 20px !important; border: 1px solid rgba(255, 215, 0, 0.15) !important; transition: all 0.3s ease-in-out !important; overflow: hidden !important; box-shadow: 0 4px 15px rgba(0,0,0,0.4) !important; } .custom-card:hover { transform: translateY(-5px) scale(1.01) !important; border: 1px solid rgba(255, 215, 0, 0.6) !important; box-shadow: 0 10px 30px rgba(255, 215, 0, 0.15) !important; } .custom-card img { transition: transform 0.4s ease !important; } .custom-card:hover img { transform: scale(1.05) !important; } .custom-score { background: rgba(10, 10, 10, 0.8) !important; border-radius: 12px !important; border: 1px solid rgba(255, 215, 0, 0.1) !important; transition: all 0.3s ease !important; } .custom-score:hover { border: 1px solid rgba(255, 215, 0, 0.4) !important; box-shadow: 0 0 15px rgba(255, 215, 0, 0.1) !important; } .custom-score:hover textarea { color: #ffd700 !important; } button.primary { background: linear-gradient(90deg, #151515, #252525) !important; border: 1px solid rgba(255, 215, 0, 0.4) !important; color: #ffd700 !important; text-transform: uppercase; letter-spacing: 1px; font-weight: bold !important; transition: all 0.3s ease !important; } button.primary:hover { background: linear-gradient(90deg, #252525, #353535) !important; border: 1px solid rgba(255, 215, 0, 0.8) !important; box-shadow: 0 0 15px rgba(255, 215, 0, 0.2) !important; transform: translateY(-2px) !important; } """ # --- 1. Load Dataset & Embeddings --- print("Loading Dataset and Embeddings...") full_ds = load_dataset("tonijhanel/my_interior_design_dataset", split="train") sample_dataset = full_ds.shuffle(seed=42).select(range(5000)) df_saved = pd.read_parquet("interior_embeddings.parquet") dataset_matrix = np.array(df_saved['embedding'].tolist()) # --- 2. Load Deep Learning Models --- device = "cuda" if torch.cuda.is_available() else "cpu" print("Loading CLIP Model...") clip_id = "openai/clip-vit-base-patch32" processor = CLIPProcessor.from_pretrained(clip_id) clip_model = CLIPModel.from_pretrained(clip_id).to(device) print("Loading Stable Diffusion Model...") pipe = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4", torch_dtype=torch.float32) pipe = pipe.to(device) pipe.enable_attention_slicing() # --- 3. Core Engine Logic --- def get_recommendations_from_vector(user_vector): similarities = cosine_similarity(user_vector, dataset_matrix)[0] top_indices = np.argsort(similarities)[-3:][::-1] top_scores = similarities[top_indices] recs = [sample_dataset[int(i)]['image'] for i in top_indices] scores = [f"Match: {score*100:.1f}%" for score in top_scores] return recs[0], scores[0], recs[1], scores[1], recs[2], scores[2] def search_by_image(user_image): if user_image is None: return None, "", None, "", None, "" inputs = processor(images=user_image, return_tensors="pt").to(device) with torch.no_grad(): features = clip_model.get_image_features(**inputs) if not isinstance(features, torch.Tensor): features = features.pooler_output if hasattr(features, 'pooler_output') else features[0] user_vector = features.cpu().numpy().flatten().reshape(1, -1) return get_recommendations_from_vector(user_vector) def search_by_text_only(prompt): if not prompt: return None, "", None, "", None, "" inputs = processor(text=[prompt], return_tensors="pt", padding=True).to(device) with torch.no_grad(): features = clip_model.get_text_features(**inputs) if not isinstance(features, torch.Tensor): features = features.pooler_output if hasattr(features, 'pooler_output') else features[0] user_vector = features.cpu().numpy().flatten().reshape(1, -1) return get_recommendations_from_vector(user_vector) def generate_and_recommend(prompt): if not prompt: return None, None, "", None, "", None, "" generated_image = pipe(prompt, num_inference_steps=15).images[0] inputs = processor(images=generated_image, return_tensors="pt").to(device) with torch.no_grad(): features = clip_model.get_image_features(**inputs) if not isinstance(features, torch.Tensor): features = features.pooler_output if hasattr(features, 'pooler_output') else features[0] user_vector = features.cpu().numpy().flatten().reshape(1, -1) rec1, score1, rec2, score2, rec3, score3 = get_recommendations_from_vector(user_vector) return generated_image, rec1, score1, rec2, score2, rec3, score3 # --- 4. Gradio User Interface (Premium UI) --- custom_theme = gr.themes.Monochrome( primary_hue="neutral", secondary_hue="neutral", font=[gr.themes.GoogleFont("Montserrat"), "ui-sans-serif", "system-ui", "sans-serif"] ) with gr.Blocks(title="Visionary | AI Interior Design", css=custom_css, theme=custom_theme) as demo: gr.HTML("""