import re from typing import List, Optional from models import WardrobeItem, ChatResponse from query_processing import get_color_matches from model_manager import generate_chat_response from conversation import get_conversation_context, enhance_message_with_context, update_context from rag import retrieve_relevant_context, format_rag_context def clean_wardrobe_response(text: str) -> str: text = re.sub(r'\b(\w+)\s+\1\b', r'\1', text) text = re.sub(r'\b(navy|grey|gray|black|white|brown|blue|red|green|beige|tan|charcoal|rolex|fossil|hermes|zara|nike)\s+\1\b', r'\1', text, flags=re.IGNORECASE) if "protein" in text.lower(): text = re.sub(r'[Pp]rotein\s*', '', text) lines = text.split('\n') cleaned_lines = [] for line in lines: line = line.strip() if not line or len(line) < 3: continue if "protein" in line.lower(): continue cleaned_lines.append(line) result = '\n'.join(cleaned_lines).strip() if len(result) > 1000: sentences = result.split('. ') result = '. '.join(sentences[:8]) + '.' return result def format_wardrobe_for_prompt(wardrobe: List[WardrobeItem]) -> str: wardrobe_by_category = {} for item in wardrobe: category = item.category.lower() if category not in wardrobe_by_category: wardrobe_by_category[category] = [] wardrobe_by_category[category].append(item) wardrobe_details = [] for idx, item in enumerate(wardrobe, 1): parts = [] if item.brand: parts.append(item.brand) if item.color: parts.append(item.color) if item.name: parts.append(item.name) elif item.category: parts.append(item.category) item_name = " ".join(parts) if parts else item.category wardrobe_details.append(f'{idx}. {item_name} ({item.category}, {item.style})') categories_list = ", ".join(wardrobe_by_category.keys()) return f"""Available items ({len(wardrobe)} total): {chr(10).join(wardrobe_details)} Categories: {categories_list}""" async def handle_wardrobe_chat(message: str, wardrobe: List[WardrobeItem], session_id: str, images: Optional[List[str]] = None, wardrobe_description: Optional[str] = None) -> ChatResponse: conv_context = get_conversation_context(session_id) enhanced_message = enhance_message_with_context(message, conv_context["context"]) wardrobe_context = wardrobe_description if wardrobe_description else format_wardrobe_for_prompt(wardrobe) wardrobe_by_category = {} for item in wardrobe: category = item.category.lower() if category not in wardrobe_by_category: wardrobe_by_category[category] = [] wardrobe_by_category[category].append(item) rag_chunks = retrieve_relevant_context(enhanced_message, top_k=3) rag_context = format_rag_context(rag_chunks) occasion_keywords = ["defense", "project", "presentation", "meeting", "interview", "formal", "casual", "party", "wedding", "dinner", "date", "work", "office"] occasion = next((word for word in occasion_keywords if word in enhanced_message.lower()), None) context_info = f"Available wardrobe categories: {', '.join(wardrobe_by_category.keys())}. " if occasion: context_info += f"Occasion: {occasion}. " system_override = "You are a friendly and helpful fashion stylist. Suggest complete outfits conversationally and warmly. Include accessories when available. Be natural and friendly in your responses." prompt = f"""{wardrobe_context} User request: {enhanced_message} Suggest a complete outfit using ONLY the items listed above. Reference items by their exact names as shown (e.g., if item is "zara black pants", say "zara black pants", not "black zara pants"). Include accessories (watches, bags, jewelry, belts, glasses) if available. Be friendly and conversational. Suggest: one top/shirt, one bottom (pants/shorts), shoes, and accessories. Explain briefly why it works.""" if context_info.strip(): prompt += f"\n\nContext: {context_info.strip()}" response_text = generate_chat_response(prompt, max_length=512, temperature=0.8, rag_context=rag_context, system_override=system_override, images=images) response_text = clean_wardrobe_response(response_text) update_context(session_id, message, { "response": response_text, "wardrobe_count": len(wardrobe), "categories": list(wardrobe_by_category.keys()) }) return ChatResponse( response=response_text, session_id=session_id )