update colors
This commit is contained in:
17
_colors.json
17
_colors.json
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"Malabar": "#000000",
|
||||
"Venus": "#808080",
|
||||
"Mars": "#FF0000",
|
||||
"Venus": "#FFD700",
|
||||
"Sun": "#FFA500",
|
||||
"Earth": "#228B22",
|
||||
"Atoms": "#008B8B",
|
||||
"Narrator": "#708090",
|
||||
"Volcanoes": "#8B0000",
|
||||
"Asteroids": "#696969",
|
||||
"Jupiter": "#D2691E",
|
||||
"Moon": "#A9A9A9",
|
||||
"Mars": "#FF4500",
|
||||
"Narrator": "#808080",
|
||||
"Asteroids": "#808080",
|
||||
"Comet": "#808080",
|
||||
"Volcanoes": "#8B0000",
|
||||
"Song": "#4682B4",
|
||||
"Earth": "#228B22",
|
||||
"Atoms": "#808080"
|
||||
"Comet": "#DAA520"
|
||||
}
|
||||
@@ -37,7 +37,11 @@ OUTPUT_FILE = Path("_colors.json")
|
||||
|
||||
# Fixed color assignments
|
||||
FIXED_COLORS = {
|
||||
"Malabar": "#000000" # Black
|
||||
"Malabar": "#000000", # Black
|
||||
"Mars": "#FF0000", # Red
|
||||
"Venus": "#FFD700", # Gold
|
||||
"Sun": "#FFA500", # Bright gold/orange
|
||||
"Earth": "#228B22" # Forest green
|
||||
}
|
||||
|
||||
# Default configurations for different providers
|
||||
@@ -97,43 +101,75 @@ def collect_speakers(input_dir: Path) -> Set[str]:
|
||||
return speakers
|
||||
|
||||
|
||||
def assign_colors(speakers: Set[str], client: OpenAI, model: str) -> Dict[str, str]:
|
||||
"""Assign colors to speakers using LLM."""
|
||||
# Start with fixed colors
|
||||
color_mapping = FIXED_COLORS.copy()
|
||||
def get_unique_fallback_color(index: int) -> str:
|
||||
"""Generate a unique fallback color from a palette."""
|
||||
# Distinct color palette for fallback (dark enough for white background)
|
||||
palette = [
|
||||
"#8B4513", # Saddle Brown
|
||||
"#556B2F", # Dark Olive Green
|
||||
"#483D8B", # Dark Slate Blue
|
||||
"#2F4F4F", # Dark Slate Gray
|
||||
"#8B008B", # Dark Magenta
|
||||
"#4B0082", # Indigo
|
||||
"#191970", # Midnight Blue
|
||||
"#006400", # Dark Green
|
||||
"#8B0000", # Dark Red
|
||||
"#B8860B", # Dark Goldenrod
|
||||
"#5F9EA0", # Cadet Blue
|
||||
"#708090", # Slate Gray
|
||||
"#CD853F", # Peru
|
||||
"#BC8F8F", # Rosy Brown
|
||||
"#4682B4", # Steel Blue
|
||||
"#6B8E23", # Olive Drab
|
||||
"#9370DB", # Medium Purple
|
||||
"#8FBC8F", # Dark Sea Green
|
||||
"#CD5C5C", # Indian Red
|
||||
"#4169E1", # Royal Blue
|
||||
]
|
||||
return palette[index % len(palette)]
|
||||
|
||||
# Filter out speakers that already have fixed colors
|
||||
remaining_speakers = [s for s in speakers if s not in color_mapping]
|
||||
|
||||
if not remaining_speakers:
|
||||
return color_mapping
|
||||
def call_llm_for_colors(speakers: List[str], client: OpenAI, model: str,
|
||||
existing_mapping: Dict[str, str], attempt: int = 1) -> Dict[str, str]:
|
||||
"""Call LLM to assign colors to speakers. Returns parsed color mapping."""
|
||||
speakers_list = ", ".join(speakers)
|
||||
|
||||
# Build prompt
|
||||
speakers_list = ", ".join(remaining_speakers)
|
||||
existing_info = ""
|
||||
if existing_mapping:
|
||||
existing_colors = [f" - {k} → {v}" for k, v in existing_mapping.items()]
|
||||
existing_info = f"\nAlready assigned:\n" + "\n".join(existing_colors)
|
||||
|
||||
prompt = f"""Assign CSS hex color codes to each speaker from "Little Malabar" based on their characteristics.
|
||||
|
||||
Speakers to assign colors:
|
||||
{speakers_list}
|
||||
{speakers_list}{existing_info}
|
||||
|
||||
Color assignment guidelines (use hex codes like #FF0000):
|
||||
- Mars → #CD5C5C (red planet) or #FF4500
|
||||
- Earth → #228B22 (forest green) or #4169E1 (royal blue)
|
||||
- Moon → #A9A9A9 (dark gray) - avoid light colors
|
||||
- Sun → #FFA500 (orange) - avoid light colors
|
||||
- Jupiter → #D2691E (chocolate/orange)
|
||||
- Galaxy → #9370DB (medium purple) or #FF69B4 (hot pink)
|
||||
- Star → #DAA520 (goldenrod) or #B8860B (dark goldenrod) - avoid white/light colors
|
||||
- Volcano → #8B0000 (dark red) or #FF4500 (orange red)
|
||||
- Kangaroo/Giraffe → #D2691E (chocolate) or #8B4513 (saddle brown)
|
||||
- Song → #4682B4 (steel blue) or #9370DB (medium purple) - avoid light colors
|
||||
- Asteroids → #696969 (dim gray) or #A9A9A9 (dark gray)
|
||||
- Atoms → #20B2AA (light sea green) or #008B8B (dark cyan)
|
||||
- Comet → #FFD700 (gold) or #DAA520 (goldenrod)
|
||||
- Narrator → #708090 (slate gray) or #778899 (light slate gray)
|
||||
|
||||
IMPORTANT: Do NOT use light colors like #FFFFFF (white), #FFFACD, #87CEEB, #C0C0C0. All colors must be dark enough to read on white backgrounds.
|
||||
IMPORTANT:
|
||||
- Do NOT use light colors like #FFFFFF (white), #FFFACD, #87CEEB, #C0C0C0
|
||||
- All colors must be dark enough to read on white backgrounds
|
||||
- Each speaker should have a UNIQUE color (no duplicates!)
|
||||
|
||||
Fixed assignment:
|
||||
- Malabar → #000000 (black, already set)
|
||||
Fixed assignments (DO NOT change these):
|
||||
- Malabar → #000000 (black)
|
||||
- Mars → #FF0000 (red)
|
||||
- Venus → #FFD700 (gold)
|
||||
- Sun → #FFA500 (bright gold)
|
||||
- Earth → #228B22 (green)
|
||||
|
||||
Reply with ONLY a JSON object mapping speaker names to hex color codes:
|
||||
Reply with ONLY a JSON object mapping the remaining speaker names to hex color codes:
|
||||
{{"SpeakerName": "#RRGGBB", ...}}
|
||||
|
||||
JSON:"""
|
||||
@@ -146,7 +182,8 @@ JSON:"""
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
temperature=0.3,
|
||||
max_tokens=500
|
||||
max_tokens=500,
|
||||
extra_body={"thinking": {"type": "disabled"}} # Disable thinking
|
||||
)
|
||||
|
||||
message = response.choices[0].message
|
||||
@@ -161,47 +198,59 @@ JSON:"""
|
||||
if json_match:
|
||||
try:
|
||||
parsed = json.loads(json_match.group())
|
||||
for speaker, color in parsed.items():
|
||||
if speaker in remaining_speakers:
|
||||
color_mapping[speaker] = color
|
||||
return {k: v for k, v in parsed.items() if k in speakers}
|
||||
except json.JSONDecodeError:
|
||||
print(f" Warning: Could not parse JSON response")
|
||||
print(f" Warning: Could not parse JSON response on attempt {attempt}")
|
||||
|
||||
# Assign default hex colors for any remaining speakers
|
||||
for speaker in remaining_speakers:
|
||||
if speaker not in color_mapping:
|
||||
# Simple fallback based on name (using hex codes)
|
||||
name_lower = speaker.lower()
|
||||
if 'mars' in name_lower:
|
||||
color_mapping[speaker] = "#FF4500" # Orange red
|
||||
elif 'earth' in name_lower:
|
||||
color_mapping[speaker] = "#228B22" # Forest green
|
||||
elif 'moon' in name_lower:
|
||||
color_mapping[speaker] = "#A9A9A9" # Dark gray
|
||||
elif 'sun' in name_lower:
|
||||
color_mapping[speaker] = "#FFA500" # Orange
|
||||
elif 'jupiter' in name_lower:
|
||||
color_mapping[speaker] = "#D2691E" # Chocolate/orange
|
||||
elif 'star' in name_lower:
|
||||
color_mapping[speaker] = "#DAA520" # Goldenrod
|
||||
elif 'galaxy' in name_lower:
|
||||
color_mapping[speaker] = "#9370DB" # Medium purple
|
||||
elif 'volcano' in name_lower:
|
||||
color_mapping[speaker] = "#8B0000" # Dark red
|
||||
elif 'song' in name_lower:
|
||||
color_mapping[speaker] = "#4682B4" # Steel blue
|
||||
else:
|
||||
color_mapping[speaker] = "#808080" # Gray
|
||||
|
||||
return color_mapping
|
||||
return {}
|
||||
|
||||
except Exception as e:
|
||||
print(f" Error assigning colors: {e}")
|
||||
# Return defaults for all remaining speakers
|
||||
for speaker in remaining_speakers:
|
||||
color_mapping[speaker] = "gray"
|
||||
print(f" Error calling LLM on attempt {attempt}: {e}")
|
||||
return {}
|
||||
|
||||
|
||||
def assign_colors(speakers: Set[str], client: OpenAI, model: str) -> Dict[str, str]:
|
||||
"""Assign colors to speakers using LLM with retry logic."""
|
||||
# Start with fixed colors
|
||||
color_mapping = FIXED_COLORS.copy()
|
||||
|
||||
# Filter out speakers that already have fixed colors
|
||||
remaining_speakers = [s for s in speakers if s not in color_mapping]
|
||||
|
||||
if not remaining_speakers:
|
||||
return color_mapping
|
||||
|
||||
max_retries = 3
|
||||
|
||||
for attempt in range(1, max_retries + 1):
|
||||
# Get speakers that still need colors
|
||||
still_need_colors = [s for s in remaining_speakers if s not in color_mapping]
|
||||
|
||||
if not still_need_colors:
|
||||
break # All speakers have colors
|
||||
|
||||
if attempt > 1:
|
||||
print(f" Retry {attempt-1}: {len(still_need_colors)} speakers still need colors...")
|
||||
|
||||
# Call LLM to get colors
|
||||
llm_result = call_llm_for_colors(still_need_colors, client, model, color_mapping, attempt)
|
||||
|
||||
# Merge results
|
||||
for speaker, color in llm_result.items():
|
||||
if speaker in still_need_colors:
|
||||
color_mapping[speaker] = color
|
||||
|
||||
# Check for any remaining speakers without colors
|
||||
still_need_colors = [s for s in remaining_speakers if s not in color_mapping]
|
||||
|
||||
if still_need_colors:
|
||||
print(f" Using fallback colors for {len(still_need_colors)} speakers...")
|
||||
# Assign unique fallback colors from palette
|
||||
for idx, speaker in enumerate(still_need_colors):
|
||||
color_mapping[speaker] = get_unique_fallback_color(idx)
|
||||
|
||||
return color_mapping
|
||||
|
||||
|
||||
def main():
|
||||
# Get LLM config
|
||||
|
||||
Reference in New Issue
Block a user