Spaces:
				
			
			
	
			
			
					
		Running
		
	
	
	
			
			
	
	
	
	
		
		
					
		Running
		
	Upload folder using huggingface_hub
Browse files- .gitattributes +1 -0
- README.md +4 -6
- app.py +455 -0
- requirements.txt +2 -0
    	
        .gitattributes
    CHANGED
    
    | @@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text | |
| 33 | 
             
            *.zip filter=lfs diff=lfs merge=lfs -text
         | 
| 34 | 
             
            *.zst filter=lfs diff=lfs merge=lfs -text
         | 
| 35 | 
             
            *tfevents* filter=lfs diff=lfs merge=lfs -text
         | 
|  | 
|  | |
| 33 | 
             
            *.zip filter=lfs diff=lfs merge=lfs -text
         | 
| 34 | 
             
            *.zst filter=lfs diff=lfs merge=lfs -text
         | 
| 35 | 
             
            *tfevents* filter=lfs diff=lfs merge=lfs -text
         | 
| 36 | 
            +
            transformers-4.57.0.dev0-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
         | 
    	
        README.md
    CHANGED
    
    | @@ -1,14 +1,12 @@ | |
| 1 | 
             
            ---
         | 
| 2 | 
            -
            title: Mood Palette
         | 
| 3 | 
            -
            emoji:  | 
| 4 | 
            -
            colorFrom:  | 
| 5 | 
            -
            colorTo:  | 
| 6 | 
             
            sdk: gradio
         | 
| 7 | 
             
            sdk_version: 5.44.1
         | 
| 8 | 
             
            app_file: app.py
         | 
| 9 | 
             
            pinned: false
         | 
| 10 | 
            -
            license: gemma
         | 
| 11 | 
             
            short_description: Mood Palette Generator
         | 
| 12 | 
             
            ---
         | 
| 13 |  | 
| 14 | 
            -
            Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
         | 
|  | |
| 1 | 
             
            ---
         | 
| 2 | 
            +
            title: Mood Palette Generator
         | 
| 3 | 
            +
            emoji: 🎨
         | 
| 4 | 
            +
            colorFrom: purple
         | 
| 5 | 
            +
            colorTo: indigo
         | 
| 6 | 
             
            sdk: gradio
         | 
| 7 | 
             
            sdk_version: 5.44.1
         | 
| 8 | 
             
            app_file: app.py
         | 
| 9 | 
             
            pinned: false
         | 
|  | |
| 10 | 
             
            short_description: Mood Palette Generator
         | 
| 11 | 
             
            ---
         | 
| 12 |  | 
|  | 
    	
        app.py
    ADDED
    
    | @@ -0,0 +1,455 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import gradio as gr
         | 
| 2 | 
            +
            import numpy as np
         | 
| 3 | 
            +
            import os
         | 
| 4 | 
            +
            from huggingface_hub import login
         | 
| 5 | 
            +
            from sentence_transformers import SentenceTransformer, util
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            # --- 1. CONFIGURATION ---
         | 
| 8 | 
            +
            # Centralized place for all settings and constants.
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            class Config:
         | 
| 11 | 
            +
                """Configuration settings for the application."""
         | 
| 12 | 
            +
                EMBEDDING_MODEL_ID = "google/embeddinggemma-300M"
         | 
| 13 | 
            +
                PROMPT_NAME = "STS"
         | 
| 14 | 
            +
                TOP_K = 5
         | 
| 15 | 
            +
                HF_TOKEN = os.getenv('HF_TOKEN')
         | 
| 16 | 
            +
             | 
| 17 | 
            +
             | 
| 18 | 
            +
            # --- 2. COLOR DATA ---
         | 
| 19 | 
            +
            # The color palette data is kept separate for clarity and easy modification.
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            COLOR_DATA = [
         | 
| 22 | 
            +
              {
         | 
| 23 | 
            +
                "name": "Crimson",
         | 
| 24 | 
            +
                "hex": "#DC143C",
         | 
| 25 | 
            +
                "description": "A deep, rich red color, leaning slightly towards purple."
         | 
| 26 | 
            +
              },
         | 
| 27 | 
            +
              {
         | 
| 28 | 
            +
                "name": "Scarlet",
         | 
| 29 | 
            +
                "hex": "#FF2400",
         | 
| 30 | 
            +
                "description": "A brilliant, vivid red with a hint of orange."
         | 
| 31 | 
            +
              },
         | 
| 32 | 
            +
              {
         | 
| 33 | 
            +
                "name": "Coral",
         | 
| 34 | 
            +
                "hex": "#FF7F50",
         | 
| 35 | 
            +
                "description": "A vibrant pinkish-orange reminiscent of marine invertebrates."
         | 
| 36 | 
            +
              },
         | 
| 37 | 
            +
              {
         | 
| 38 | 
            +
                "name": "Tangerine",
         | 
| 39 | 
            +
                "hex": "#F28500",
         | 
| 40 | 
            +
                "description": "A saturated, zesty orange, like the ripe citrus fruit."
         | 
| 41 | 
            +
              },
         | 
| 42 | 
            +
              {
         | 
| 43 | 
            +
                "name": "Gold",
         | 
| 44 | 
            +
                "hex": "#FFD700",
         | 
| 45 | 
            +
                "description": "A bright, metallic yellow associated with wealth and luxury."
         | 
| 46 | 
            +
              },
         | 
| 47 | 
            +
              {
         | 
| 48 | 
            +
                "name": "Lemon Chiffon",
         | 
| 49 | 
            +
                "hex": "#FFFACD",
         | 
| 50 | 
            +
                "description": "A pale, light yellow, as soft and airy as the dessert."
         | 
| 51 | 
            +
              },
         | 
| 52 | 
            +
              {
         | 
| 53 | 
            +
                "name": "Lime Green",
         | 
| 54 | 
            +
                "hex": "#32CD32",
         | 
| 55 | 
            +
                "description": "A bright green color, evoking freshness and zesty energy."
         | 
| 56 | 
            +
              },
         | 
| 57 | 
            +
              {
         | 
| 58 | 
            +
                "name": "Forest Green",
         | 
| 59 | 
            +
                "hex": "#228B22",
         | 
| 60 | 
            +
                "description": "A dark, shaded green, like the canopy of a dense forest."
         | 
| 61 | 
            +
              },
         | 
| 62 | 
            +
              {
         | 
| 63 | 
            +
                "name": "Teal",
         | 
| 64 | 
            +
                "hex": "#008080",
         | 
| 65 | 
            +
                "description": "A medium blue-green color, often seen as sophisticated and calming."
         | 
| 66 | 
            +
              },
         | 
| 67 | 
            +
              {
         | 
| 68 | 
            +
                "name": "Cyan",
         | 
| 69 | 
            +
                "hex": "#00FFFF",
         | 
| 70 | 
            +
                "description": "A vibrant greenish-blue, one of the primary subtractive colors."
         | 
| 71 | 
            +
              },
         | 
| 72 | 
            +
              {
         | 
| 73 | 
            +
                "name": "Sky Blue",
         | 
| 74 | 
            +
                "hex": "#87CEEB",
         | 
| 75 | 
            +
                "description": "A light, pale blue, like the color of a clear daytime sky."
         | 
| 76 | 
            +
              },
         | 
| 77 | 
            +
              {
         | 
| 78 | 
            +
                "name": "Royal Blue",
         | 
| 79 | 
            +
                "hex": "#4169E1",
         | 
| 80 | 
            +
                "description": "A deep, vivid blue that is both rich and bright."
         | 
| 81 | 
            +
              },
         | 
| 82 | 
            +
              {
         | 
| 83 | 
            +
                "name": "Indigo",
         | 
| 84 | 
            +
                "hex": "#4B0082",
         | 
| 85 | 
            +
                "description": "A deep, rich color between blue and violet in the spectrum."
         | 
| 86 | 
            +
              },
         | 
| 87 | 
            +
              {
         | 
| 88 | 
            +
                "name": "Lavender",
         | 
| 89 | 
            +
                "hex": "#E6E6FA",
         | 
| 90 | 
            +
                "description": "A light, pale purple with a bluish hue, named after the flower."
         | 
| 91 | 
            +
              },
         | 
| 92 | 
            +
              {
         | 
| 93 | 
            +
                "name": "Plum",
         | 
| 94 | 
            +
                "hex": "#DDA0DD",
         | 
| 95 | 
            +
                "description": "A reddish-purple color, like the ripe fruit it's named after."
         | 
| 96 | 
            +
              },
         | 
| 97 | 
            +
              {
         | 
| 98 | 
            +
                "name": "Magenta",
         | 
| 99 | 
            +
                "hex": "#FF00FF",
         | 
| 100 | 
            +
                "description": "A purplish-red color that lies between red and violet."
         | 
| 101 | 
            +
              },
         | 
| 102 | 
            +
              {
         | 
| 103 | 
            +
                "name": "Hot Pink",
         | 
| 104 | 
            +
                "hex": "#FF69B4",
         | 
| 105 | 
            +
                "description": "A bright, vivid pink that is both bold and energetic."
         | 
| 106 | 
            +
              },
         | 
| 107 | 
            +
              {
         | 
| 108 | 
            +
                "name": "Ivory",
         | 
| 109 | 
            +
                "hex": "#FFFFF0",
         | 
| 110 | 
            +
                "description": "An off-white color that resembles the material from tusks and teeth."
         | 
| 111 | 
            +
              },
         | 
| 112 | 
            +
              {
         | 
| 113 | 
            +
                "name": "Beige",
         | 
| 114 | 
            +
                "hex": "#F5F5DC",
         | 
| 115 | 
            +
                "description": "A pale sandy fawn color, often used as a warm, neutral tone."
         | 
| 116 | 
            +
              },
         | 
| 117 | 
            +
              {
         | 
| 118 | 
            +
                "name": "Taupe",
         | 
| 119 | 
            +
                "hex": "#483C32",
         | 
| 120 | 
            +
                "description": "A dark grayish-brown or brownish-gray color."
         | 
| 121 | 
            +
              },
         | 
| 122 | 
            +
              {
         | 
| 123 | 
            +
                "name": "Slate Gray",
         | 
| 124 | 
            +
                "hex": "#708090",
         | 
| 125 | 
            +
                "description": "A medium gray with a slight blue tinge, like the metamorphic rock."
         | 
| 126 | 
            +
              },
         | 
| 127 | 
            +
              {
         | 
| 128 | 
            +
                "name": "Charcoal",
         | 
| 129 | 
            +
                "hex": "#36454F",
         | 
| 130 | 
            +
                "description": "A dark, almost black gray, like burnt wood."
         | 
| 131 | 
            +
              },
         | 
| 132 | 
            +
              {
         | 
| 133 | 
            +
                "name": "Onyx",
         | 
| 134 | 
            +
                "hex": "#353839",
         | 
| 135 | 
            +
                "description": "A deep, rich black, often with a subtle hint of dark blue."
         | 
| 136 | 
            +
              },
         | 
| 137 | 
            +
              {
         | 
| 138 | 
            +
                "name": "Emerald",
         | 
| 139 | 
            +
                "hex": "#50C878",
         | 
| 140 | 
            +
                "description": "A brilliant green, named after the precious gemstone."
         | 
| 141 | 
            +
              },
         | 
| 142 | 
            +
              {
         | 
| 143 | 
            +
                "name": "Sapphire",
         | 
| 144 | 
            +
                "hex": "#0F52BA",
         | 
| 145 | 
            +
                "description": "A deep, lustrous blue, reminiscent of the valuable gemstone."
         | 
| 146 | 
            +
              },
         | 
| 147 | 
            +
              {
         | 
| 148 | 
            +
                "name": "Ruby",
         | 
| 149 | 
            +
                "hex": "#E0115F",
         | 
| 150 | 
            +
                "description": "A deep red color, inspired by the gemstone of the same name."
         | 
| 151 | 
            +
              },
         | 
| 152 | 
            +
              {
         | 
| 153 | 
            +
                "name": "Amethyst",
         | 
| 154 | 
            +
                "hex": "#9966CC",
         | 
| 155 | 
            +
                "description": "A moderate, violet-purple color, like the quartz gemstone."
         | 
| 156 | 
            +
              },
         | 
| 157 | 
            +
              {
         | 
| 158 | 
            +
                "name": "Peridot",
         | 
| 159 | 
            +
                "hex": "#E6E200",
         | 
| 160 | 
            +
                "description": "A light olive-green or yellowish-green, named for the gem."
         | 
| 161 | 
            +
              },
         | 
| 162 | 
            +
              {
         | 
| 163 | 
            +
                "name": "Turquoise",
         | 
| 164 | 
            +
                "hex": "#40E0D0",
         | 
| 165 | 
            +
                "description": "A greenish-blue color, often associated with tropical waters."
         | 
| 166 | 
            +
              },
         | 
| 167 | 
            +
              {
         | 
| 168 | 
            +
                "name": "Silver",
         | 
| 169 | 
            +
                "hex": "#C0C0C0",
         | 
| 170 | 
            +
                "description": "A metallic gray color that resembles polished silver."
         | 
| 171 | 
            +
              },
         | 
| 172 | 
            +
              {
         | 
| 173 | 
            +
                "name": "Bronze",
         | 
| 174 | 
            +
                "hex": "#CD7F32",
         | 
| 175 | 
            +
                "description": "A metallic brown color that resembles the alloy of copper and tin."
         | 
| 176 | 
            +
              },
         | 
| 177 | 
            +
              {
         | 
| 178 | 
            +
                "name": "Obsidian",
         | 
| 179 | 
            +
                "hex": "#000000",
         | 
| 180 | 
            +
                "description": "A pure, deep black, like the volcanic glass formed from cooled lava."
         | 
| 181 | 
            +
              }
         | 
| 182 | 
            +
            ]
         | 
| 183 | 
            +
             | 
| 184 | 
            +
             | 
| 185 | 
            +
            # --- 3. CORE LOGIC ---
         | 
| 186 | 
            +
            # Encapsulated in a class to manage state (model, embeddings) cleanly.
         | 
| 187 | 
            +
             | 
| 188 | 
            +
            class MoodPaletteGenerator:
         | 
| 189 | 
            +
                """Handles model loading, embedding generation, and palette creation."""
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                def __init__(self, config: Config, color_data: list[dict[str, any]]):
         | 
| 192 | 
            +
                    """Initializes the generator, logs in, and loads necessary assets."""
         | 
| 193 | 
            +
                    self.config = config
         | 
| 194 | 
            +
                    self.color_data = color_data
         | 
| 195 | 
            +
                    self._login_to_hf()
         | 
| 196 | 
            +
                    self.embedding_model = self._load_model()
         | 
| 197 | 
            +
                    self.color_embeddings = self._precompute_color_embeddings()
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                def _login_to_hf(self):
         | 
| 200 | 
            +
                    """Logs into Hugging Face Hub if a token is provided."""
         | 
| 201 | 
            +
                    if self.config.HF_TOKEN:
         | 
| 202 | 
            +
                        print("Logging into Hugging Face Hub...")
         | 
| 203 | 
            +
                        login(token=self.config.HF_TOKEN)
         | 
| 204 | 
            +
                    else:
         | 
| 205 | 
            +
                        print("HF_TOKEN not found. Proceeding without login.")
         | 
| 206 | 
            +
                        print("Note: This may fail if the model is gated.")
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                def _load_model(self) -> SentenceTransformer:
         | 
| 209 | 
            +
                    """Loads the Sentence Transformer model."""
         | 
| 210 | 
            +
                    print(f"Initializing embedding model: {self.config.EMBEDDING_MODEL_ID}...")
         | 
| 211 | 
            +
                    try:
         | 
| 212 | 
            +
                        return SentenceTransformer(self.config.EMBEDDING_MODEL_ID)
         | 
| 213 | 
            +
                    except Exception as e:
         | 
| 214 | 
            +
                        print(f"Error loading model: {e}")
         | 
| 215 | 
            +
                        raise
         | 
| 216 | 
            +
             | 
| 217 | 
            +
                def _precompute_color_embeddings(self) -> np.ndarray:
         | 
| 218 | 
            +
                    """Generates and stores embeddings for the color descriptions."""
         | 
| 219 | 
            +
                    print("Pre-computing embeddings for color palette...")
         | 
| 220 | 
            +
                    color_texts = [
         | 
| 221 | 
            +
                        f"{color['name']}, {color['description']}"
         | 
| 222 | 
            +
                        for color in self.color_data
         | 
| 223 | 
            +
                    ]
         | 
| 224 | 
            +
                    embeddings = self.embedding_model.encode(
         | 
| 225 | 
            +
                        color_texts,
         | 
| 226 | 
            +
                        prompt_name=self.config.PROMPT_NAME
         | 
| 227 | 
            +
                    )
         | 
| 228 | 
            +
                    print("Embeddings computed successfully.")
         | 
| 229 | 
            +
                    return embeddings
         | 
| 230 | 
            +
             | 
| 231 | 
            +
                def _get_text_color_for_bg(self, hex_color: str) -> str:
         | 
| 232 | 
            +
                    """
         | 
| 233 | 
            +
                    Calculates the luminance of a hex color and returns black ('#000000')
         | 
| 234 | 
            +
                    or white ('#FFFFFF') for the best text contrast.
         | 
| 235 | 
            +
                    """
         | 
| 236 | 
            +
                    hex_color = hex_color.lstrip('#')
         | 
| 237 | 
            +
                    try:
         | 
| 238 | 
            +
                        r, g, b = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
         | 
| 239 | 
            +
                        luminance = (0.299 * r + 0.587 * g + 0.114 * b)
         | 
| 240 | 
            +
                        return '#000000' if luminance > 150 else '#FFFFFF'
         | 
| 241 | 
            +
                    except (ValueError, IndexError):
         | 
| 242 | 
            +
                        return '#000000' # Default to black on invalid hex
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                def _format_palette_as_html(self, top_hits: list[dict[str, any]]) -> str:
         | 
| 245 | 
            +
                    """Formats the top color hits into a displayable HTML string."""
         | 
| 246 | 
            +
                    if not top_hits:
         | 
| 247 | 
            +
                        return "<p>Could not generate a palette. Please try another mood.</p>"
         | 
| 248 | 
            +
             | 
| 249 | 
            +
                    cards_html = ""
         | 
| 250 | 
            +
                    for hit in top_hits:
         | 
| 251 | 
            +
                        color_info = self.color_data[hit['corpus_id']]
         | 
| 252 | 
            +
                        hex_code = color_info['hex']
         | 
| 253 | 
            +
                        name = color_info['name']
         | 
| 254 | 
            +
                        score = hit['score']
         | 
| 255 | 
            +
                        text_color = self._get_text_color_for_bg(hex_code)
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                        cards_html += f"""
         | 
| 258 | 
            +
                        <div class="color-card" style="background-color: {hex_code}; color: {text_color};">
         | 
| 259 | 
            +
                            {name} | {hex_code} | Score: {score:.2f}
         | 
| 260 | 
            +
                        </div>
         | 
| 261 | 
            +
                        """
         | 
| 262 | 
            +
                    return f"<div class='palette-container'>{cards_html}</div>"
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                def _create_dynamic_theme_css(self, top_hits: list[dict[str, any]]) -> str:
         | 
| 265 | 
            +
                    """Generates a <style> block to override Gradio theme variables."""
         | 
| 266 | 
            +
                    theme_colors = []
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                    if top_hits:
         | 
| 269 | 
            +
                        theme_colors = [
         | 
| 270 | 
            +
                            {
         | 
| 271 | 
            +
                                "bg": self.color_data[hit['corpus_id']]['hex'],
         | 
| 272 | 
            +
                                "txt": self._get_text_color_for_bg(self.color_data[hit['corpus_id']]['hex'])
         | 
| 273 | 
            +
                            }
         | 
| 274 | 
            +
                            for hit in top_hits
         | 
| 275 | 
            +
                        ]
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                    css_map = {
         | 
| 278 | 
            +
                        "button-primary-background-fill": (0, 'bg'),
         | 
| 279 | 
            +
                        "button-primary-text-color": (0, 'txt'),
         | 
| 280 | 
            +
                        "button-secondary-background-fill": (1, 'bg'),
         | 
| 281 | 
            +
                        "button-secondary-text-color": (1, 'txt'),
         | 
| 282 | 
            +
                        "block-background-fill": (2, 'bg'),
         | 
| 283 | 
            +
                        "block-info-text-color": (2, 'txt'),
         | 
| 284 | 
            +
                        "block-title-background-fill": (3, 'bg'),
         | 
| 285 | 
            +
                        "button-primary-background-fill-hover": (3, 'bg'),
         | 
| 286 | 
            +
                        "block-title-text-color": (3, 'txt'),
         | 
| 287 | 
            +
                        "button-primary-text-color-hover": (3, 'txt'),
         | 
| 288 | 
            +
                        "button-secondary-background-fill-hover": (4, 'bg'),
         | 
| 289 | 
            +
                        "button-secondary-text-color-hover": (4, 'txt'),
         | 
| 290 | 
            +
                    }
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                    css_rules = []
         | 
| 293 | 
            +
                    num_available_colors = len(theme_colors)
         | 
| 294 | 
            +
             | 
| 295 | 
            +
                    for var_suffix, (index, key) in css_map.items():
         | 
| 296 | 
            +
                        if index < num_available_colors:
         | 
| 297 | 
            +
                            color_value = theme_colors[index][key]
         | 
| 298 | 
            +
                            css_rules.append(f"--{var_suffix}: {color_value};")
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                    css_rules_str = "\n".join(css_rules)
         | 
| 301 | 
            +
             | 
| 302 | 
            +
                    # Create CSS variables to inject
         | 
| 303 | 
            +
                    css = f"""
         | 
| 304 | 
            +
                    <style>
         | 
| 305 | 
            +
                        :root {{
         | 
| 306 | 
            +
            {css_rules_str}
         | 
| 307 | 
            +
                        }}
         | 
| 308 | 
            +
             | 
| 309 | 
            +
                        :root .dark {{
         | 
| 310 | 
            +
            {css_rules_str}
         | 
| 311 | 
            +
                        }}
         | 
| 312 | 
            +
             | 
| 313 | 
            +
                        .gallery-item .gallery {{
         | 
| 314 | 
            +
                            background: {theme_colors[4]['bg']};
         | 
| 315 | 
            +
                            color: {theme_colors[4]['txt']};
         | 
| 316 | 
            +
                        }}
         | 
| 317 | 
            +
                    </style>
         | 
| 318 | 
            +
                    """
         | 
| 319 | 
            +
             | 
| 320 | 
            +
                    return css
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                def generate_palette_and_theme(self, mood_text: str) -> tuple[str, str]:
         | 
| 323 | 
            +
                    """
         | 
| 324 | 
            +
                    Generates a color palette HTML and a dynamic theme CSS string.
         | 
| 325 | 
            +
                    """
         | 
| 326 | 
            +
                    if not mood_text or not mood_text.strip():
         | 
| 327 | 
            +
                        return "<p>Please enter a mood or a description.</p>", ""
         | 
| 328 | 
            +
             | 
| 329 | 
            +
                    mood_embedding = self.embedding_model.encode(
         | 
| 330 | 
            +
                        mood_text,
         | 
| 331 | 
            +
                        prompt_name=self.config.PROMPT_NAME
         | 
| 332 | 
            +
                    )
         | 
| 333 | 
            +
                    top_hits = util.semantic_search(
         | 
| 334 | 
            +
                        mood_embedding, self.color_embeddings, top_k=self.config.TOP_K
         | 
| 335 | 
            +
                    )[0]
         | 
| 336 | 
            +
             | 
| 337 | 
            +
                    palette_html = self._format_palette_as_html(top_hits)
         | 
| 338 | 
            +
                    theme_css = self._create_dynamic_theme_css(top_hits)
         | 
| 339 | 
            +
             | 
| 340 | 
            +
                    return palette_html, theme_css
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                def clear_theme(self) -> tuple[str, str]:
         | 
| 343 | 
            +
                    return "", ""
         | 
| 344 | 
            +
             | 
| 345 | 
            +
             | 
| 346 | 
            +
            # --- 4. GRADIO UI ---
         | 
| 347 | 
            +
            # Defines and launches the web interface.
         | 
| 348 | 
            +
             | 
| 349 | 
            +
            def create_ui(generator: MoodPaletteGenerator):
         | 
| 350 | 
            +
                """Creates the Gradio web interface."""
         | 
| 351 | 
            +
                with gr.Blocks(theme=gr.themes.Soft()) as demo:
         | 
| 352 | 
            +
                    # This invisible component will hold our dynamic CSS
         | 
| 353 | 
            +
                    dynamic_css_output = gr.HTML()
         | 
| 354 | 
            +
             | 
| 355 | 
            +
                    gr.Markdown("""
         | 
| 356 | 
            +
                        # 🎨 Mood Palette Generator
         | 
| 357 | 
            +
                        Describe a mood, a scene, or a feeling, and get a matching color palette.<br>
         | 
| 358 | 
            +
                        **The UI theme will update to match your mood!**
         | 
| 359 | 
            +
                    """)
         | 
| 360 | 
            +
             | 
| 361 | 
            +
                    with gr.Row():
         | 
| 362 | 
            +
                        with gr.Column(scale=4):
         | 
| 363 | 
            +
                            mood_input = gr.Textbox(
         | 
| 364 | 
            +
                                value="Strawberry ice cream",
         | 
| 365 | 
            +
                                label="Enter Your Mood or Scene",
         | 
| 366 | 
            +
                                info="Be as descriptive as you like!"
         | 
| 367 | 
            +
                            )
         | 
| 368 | 
            +
                        with gr.Column(scale=1, min_width=150):
         | 
| 369 | 
            +
                            submit_button = gr.Button("Generate Palette", variant="primary")
         | 
| 370 | 
            +
                            clear_button = gr.Button("Clear", variant="secondary")
         | 
| 371 | 
            +
             | 
| 372 | 
            +
                    palette_output = gr.HTML(label="Your Generated Palette")
         | 
| 373 | 
            +
             | 
| 374 | 
            +
                    # Define CSS for palette cards here once, instead of in every update
         | 
| 375 | 
            +
                    gr.HTML("""
         | 
| 376 | 
            +
                        <style>
         | 
| 377 | 
            +
                            .palette-container {
         | 
| 378 | 
            +
                                display: flex; flex-direction: column; gap: 10px;
         | 
| 379 | 
            +
                                align-items: center; width: 100%;
         | 
| 380 | 
            +
                            q}
         | 
| 381 | 
            +
                            .color-card {
         | 
| 382 | 
            +
                                border-radius: 10px; text-align: center; padding: 15px 10px;
         | 
| 383 | 
            +
                                width: 90%; max-width: 400px;
         | 
| 384 | 
            +
                                box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
         | 
| 385 | 
            +
                                font-family: sans-serif; font-size: 16px; font-weight: bold;
         | 
| 386 | 
            +
                                transition: transform 0.2s;
         | 
| 387 | 
            +
                            }
         | 
| 388 | 
            +
                            .color-card:hover { transform: scale(1.05); }
         | 
| 389 | 
            +
                        </style>
         | 
| 390 | 
            +
                    """)
         | 
| 391 | 
            +
             | 
| 392 | 
            +
                    # Define the function to be called by events
         | 
| 393 | 
            +
                    event_handler = generator.generate_palette_and_theme
         | 
| 394 | 
            +
                    outputs_list = [palette_output, dynamic_css_output]
         | 
| 395 | 
            +
             | 
| 396 | 
            +
                    gr.Examples(
         | 
| 397 | 
            +
                        [
         | 
| 398 | 
            +
                            "A futuristic city at night, slick with rain",
         | 
| 399 | 
            +
                            "The feeling of a cozy cabin during a blizzard",
         | 
| 400 | 
            +
                            "Joyful chaos at a summer music festival",
         | 
| 401 | 
            +
                            "Beach sunset with the palm tree",
         | 
| 402 | 
            +
                            "A calm and lonely winter morning",
         | 
| 403 | 
            +
                            "Vintage romance in a dusty library",
         | 
| 404 | 
            +
                            "Cyberpunk alleyway with neon signs",
         | 
| 405 | 
            +
                        ],
         | 
| 406 | 
            +
                        inputs=mood_input,
         | 
| 407 | 
            +
                        outputs=outputs_list,
         | 
| 408 | 
            +
                        fn=event_handler,
         | 
| 409 | 
            +
                        run_on_click=True,
         | 
| 410 | 
            +
                    )
         | 
| 411 | 
            +
             | 
| 412 | 
            +
                    submit_button.click(
         | 
| 413 | 
            +
                        fn=event_handler,
         | 
| 414 | 
            +
                        inputs=mood_input,
         | 
| 415 | 
            +
                        outputs=outputs_list,
         | 
| 416 | 
            +
                    )
         | 
| 417 | 
            +
                    clear_button.click(
         | 
| 418 | 
            +
                        fn=generator.clear_theme,
         | 
| 419 | 
            +
                        outputs=outputs_list,
         | 
| 420 | 
            +
                    )
         | 
| 421 | 
            +
                    # Also allow submitting by pressing Enter in the textbox
         | 
| 422 | 
            +
                    mood_input.submit(
         | 
| 423 | 
            +
                        fn=event_handler,
         | 
| 424 | 
            +
                        inputs=mood_input,
         | 
| 425 | 
            +
                        outputs=outputs_list,
         | 
| 426 | 
            +
                    )
         | 
| 427 | 
            +
             | 
| 428 | 
            +
                    gr.Markdown("""
         | 
| 429 | 
            +
                        ----
         | 
| 430 | 
            +
             | 
| 431 | 
            +
                        ## What is this?
         | 
| 432 | 
            +
             | 
| 433 | 
            +
                        This interactive application, the **Mood Palette Generator**, transforms your words into a vibrant color palette. Simply describe a mood, a scene, or a feeling and the app will generate a set of matching colors. As a unique touch, the entire user interface dynamically updates its theme to reflect the generated palette, immersing you in your chosen mood.
         | 
| 434 | 
            +
             | 
| 435 | 
            +
                         ## How It Works?
         | 
| 436 | 
            +
             | 
| 437 | 
            +
                         At its core, this tool is powered by [**EmbeddingGemma**](http://huggingface.co/google/embeddinggemma-300M), a state-of-the-art text embedding model. The process works in a few simple steps:
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                         1.  **Text to Vector**: When you enter a description, EmbeddingGemma converts your text into a numerical representation called an **embedding**. This embedding captures the semantic essence, or the "vibe" of your words.
         | 
| 440 | 
            +
                         2.  **Semantic Color Search**: The application has a pre-defined library of colors, where each color is associated with its own descriptive text and a pre-computed embedding.
         | 
| 441 | 
            +
                         3.  **Finding the Match**: Your input embedding is compared against the entire library of color embeddings to find the closest matches based on a similarity score.
         | 
| 442 | 
            +
                         4.  **Palette Creation**: The colors with the highest similarity scores are selected and presented to you as a complete palette.
         | 
| 443 | 
            +
             | 
| 444 | 
            +
                         The Mood Palette Generator is a perfect example of how embeddings can be used for creative applications beyond simple text search.
         | 
| 445 | 
            +
                    """)
         | 
| 446 | 
            +
             | 
| 447 | 
            +
                return demo
         | 
| 448 | 
            +
             | 
| 449 | 
            +
            if __name__ == "__main__":
         | 
| 450 | 
            +
                # Initialize application components
         | 
| 451 | 
            +
                generator = MoodPaletteGenerator(config=Config(), color_data=COLOR_DATA)
         | 
| 452 | 
            +
                
         | 
| 453 | 
            +
                demo = create_ui(generator)
         | 
| 454 | 
            +
                demo.launch()
         | 
| 455 | 
            +
             | 
    	
        requirements.txt
    ADDED
    
    | @@ -0,0 +1,2 @@ | |
|  | |
|  | 
|  | |
| 1 | 
            +
            sentence-transformers
         | 
| 2 | 
            +
            git+https://github.com/huggingface/[email protected]
         | 

