The image shows a basket full of freshly baked croissants. They are golden brown and flaky, and some of them have a slightly burnt edge. They are piled high in the basket, and some of them are overlapping. The background is blurred, but it appears to be a kitchen counter or table. { "title": "Croissants", "ingredients": [ { "name": "All-purpose flour", "quantity": "500g" }, { "name": "Salt", "quantity": "10g" }, { "name": "Sugar", "quantity": "20g" }, { "name": "Instant yeast", "quantity": "7g" }, { "name": "Unsalted butter", "quantity": "250g" }, { "name": "Milk", "quantity": "250ml" }, { "name": "Egg yolk", "quantity": "1" } ], "instructions": [ "In a large bowl, combine the flour, salt, sugar, and yeast.", "Add the milk and mix until a dough forms.", "Knead the dough for 10 minutes, until it is smooth and elastic.", "Place the dough in a greased bowl, cover, and let it rise in a warm place for 1 hour.", "Roll out the dough into a rectangle about 1/4 inch thick.", "Spread the softened butter evenly over the dough.", "Fold the dough in thirds, like a letter.", "Wrap the dough in plastic wrap and refrigerate for 30 minutes.", "Repeat steps 7 and 8 two more times.", "Roll out the dough into a rectangle about 1/2 inch thick.", "Cut the dough into triangles.", "Roll up each triangle, starting from the wide end.", "Place the croissants on a baking sheet lined with parchment paper.", "Cover and let them rise for 1 hour.", "Brush the croissants with egg yolk and bake at 375 degrees Fahrenheit for 15-20 minutes, or until golden brown." ], "notes": "You can use a stand mixer with a dough hook to knead the dough. Make sure the butter is softened to room temperature before spreading it on the dough. The croissants will rise best in a warm place, like a turned-off oven with a bowl of hot water inside." }
from typing import Optional, List, Dict, Any from services.llm_service import LLMService class RecommendationService: """Generate recommendations with clear, professional prompts""" def __init__(self): self.llm = LLMService() def generate_haircuts( self, hair_type: str, face_shape: str, gender: str, preference: str, hair_length: str, age: int, ) -> Optional[str]: """Generate haircut recommendations with clear, detailed guidance""" prompt = f"""You are an experienced professional hair stylist. Provide 3 specific haircut recommendations for this client. CLIENT INFORMATION: - Hair Type: {hair_type} - Face Shape: {face_shape} - Gender: {gender} - Age: {age} years - Style Preference: {preference} - Desired Length: {hair_length} REQUIREMENTS: Recommend 3 DIFFERENT haircuts that: 1. Complement the {face_shape} face shape 2. Work well with {hair_type} hair 3. Match the {preference} style 4. Are appropriate for {age} years old 5. Achieve the {hair_length} length For each haircut, provide: - Specific haircut name (e.g., "Textured Layered Bob" not just "Bob") - Clear 2-3 sentence description of the cut - Explanation of why it works for this face shape and hair type - Styling difficulty: Easy/Medium/Advanced - Maintenance level: Low/Medium/High FACE SHAPE GUIDELINES: - Oval: Most versatile, suits almost any style - Round: Add height and angles, avoid width at cheeks - Square: Soften jawline with layers and texture - Heart: Balance wide forehead with volume at chin - Oblong: Add width at sides, avoid too much height - Diamond: Add volume at crown and chin area HAIR TYPE CONSIDERATIONS: - Straight: Needs texture and layers for movement - Wavy: Embrace natural texture, avoid excessive layers - Curly: Account for shrinkage, needs length and moisture - Fine: Avoid over-layering, create illusion of thickness - Thick: Needs thinning and internal layers FORMAT: 1. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 2. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 3. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] Answer: 1.""" response = self.llm.query(prompt, timeout=40) return "1." + response.strip() if response else None def generate_products(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations with care tips and home remedies""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and solutions for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Dove Intensive Repair Shampoo") 2. Include brand name 3. Specify size (e.g., 250ml, 400g, 16 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 3 practical care tips specifically for {hair_problem} with {hair_type} hair. Focus on: - Daily habits and techniques - Washing and styling methods - Protection and prevention - NOT product recommendations TASK 3 - HOME REMEDIES: Provide 3 home remedies for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements - Have clear step-by-step instructions - Explain benefits - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Home Remedies for {hair_problem}: Remedy 1: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 2: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 3: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_products_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations and care tips only""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and care tips for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Pantene Pro-V Daily Moisture Renewal Shampoo") 2. Include brand name 3. Specify size (e.g., 355ml, 16.9 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 5 practical, actionable care tips specifically for {hair_problem} with {hair_type} hair. Tips should: - Be specific daily habits or techniques (NOT product recommendations) - Be evidence-based for {hair_problem} - Be appropriate for {hair_type} hair - Cover different areas: washing, styling, diet, protection, etc. FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_remedies_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate home remedies only""" prompt = f"""You are a natural hair care expert. Provide home remedies for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK: Provide 3 home remedies specifically for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements (tablespoons, cups, etc.) - Have clear step-by-step instructions - Explain benefits and why it works - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) - Be safe for {age} years old - Consider {hair_type} hair characteristics FORMAT: Remedy 1: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 2: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 3: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Answer: Remedy 1:""" response = self.llm.query(prompt, timeout=40) return "Remedy 1:" + response.strip() if response else None def parse_haircuts(self, response: Optional[str]) -> List[Dict]: """Parse haircut response""" haircuts: List[Dict] = [] if not response: return haircuts lines = response.split("\n") current: Dict[str, str] = {} allowed_difficulty = {"easy", "medium", "advanced"} allowed_maintenance = {"low", "medium", "high"} for line in lines: line = line.strip() if not line: continue if line and line[0].isdigit() and "." in line: if current and "name" in current: haircuts.append(current) if len(haircuts) >= 3: break parts = line.split(".", 1) if len(parts) == 2: name = parts[1].strip() current = {"name": name, "description": "", "why_works": "", "difficulty": "", "maintenance": ""} elif "Description:" in line or "description:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: current["description"] = parts[1].strip() elif "Why it works:" in line or "why it works:" in line.lower() or "Why:" in line: parts = line.split(":", 1) if len(parts) == 2 and current: current["why_works"] = parts[1].strip() elif "Difficulty:" in line or "difficulty:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: difficulty = parts[1].strip().lower() for level in allowed_difficulty: if level in difficulty: current["difficulty"] = level.capitalize() break elif "Maintenance:" in line or "maintenance:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: maintenance = parts[1].strip().lower() for level in allowed_maintenance: if level in maintenance: current["maintenance"] = level.capitalize() break if current and "name" in current: haircuts.append(current) valid_haircuts = [] for haircut in haircuts[:3]: if all(key in haircut and haircut[key] for key in ["name", "description", "why_works"]): if not haircut.get("difficulty"): haircut["difficulty"] = "Medium" if not haircut.get("maintenance"): haircut["maintenance"] = "Medium" valid_haircuts.append(haircut) return valid_haircuts def parse_products(self, response: Optional[str]) -> Dict[str, Any]: """Parse product recommendations, care tips, and home remedies""" result: Dict[str, Any] = { "products": [], "care_tips": [], "home_remedies": [] } if not response: return result lines = response.split("\n") current: Optional[Dict[str, str]] = None current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None in_care_tips_section = False in_remedies_section = False product_count = 0 for line in lines: line = line.strip() if not line: if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) current_remedy = {} current_remedy_section = None continue lower = line.lower() if "care tips" in lower or "care tip" in lower: in_care_tips_section = True in_remedies_section = False if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 continue if "home remed" in lower or "remedy 1:" in lower or (lower.startswith("remedy") and ":" in line): in_remedies_section = True in_care_tips_section = False if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None continue if in_care_tips_section and not in_remedies_section: if line.startswith(("-", "•", "*", "–")): tip = line.lstrip("-•*– ").strip() if len(tip) > 5: result["care_tips"].append(tip) elif not any(keyword in lower for keyword in ["product", "remedy", "brand:", "quantity:", "tip:"]): if len(line) > 15 and not line[0].isdigit(): result["care_tips"].append(line) continue if in_remedies_section: if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*", "–")) and current_remedy_section: text = line.lstrip("-•*– ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: if current_remedy_section == "ingredients" and not any(keyword in lower for keyword in ["instructions", "frequency", "benefits", "precautions"]): current_remedy.setdefault("ingredients", []).append(line) elif current_remedy_section != "ingredients": existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + line).strip() continue if not in_care_tips_section and not in_remedies_section: if lower.startswith("product") and ":" in line and product_count < 3: if current and "name" in current: result["products"].append(current) product_count += 1 if product_count >= 3: current = None continue parts = line.split(":", 1) if len(parts) == 2: product_name = parts[1].strip() current = {"name": product_name} else: if not current: current = {} elif line.startswith("Brand:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["brand"] = parts[1].strip() elif "Quantity:" in line and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["quantity"] = parts[1].strip() elif line.startswith("Tip:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["tip"] = parts[1].strip() elif current and "name" not in current: if not any(keyword in line.lower() for keyword in ["brand:", "quantity:", "tip:", "product", "care tips"]): if len(line) > 3: current["name"] = line if current and "name" in current and product_count < 3: result["products"].append(current) product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) for product in result["products"]: if "name" in product and product["name"]: name = product["name"].strip() if ":" in name: parts = name.split(":", 1) if len(parts) == 2: before_colon = parts[0].strip() after_colon = parts[1].strip() if len(before_colon.split()) <= 3 and len(after_colon) > len(before_colon): product["name"] = after_colon else: product["name"] = name else: product["name"] = name else: product["name"] = name for i, product in enumerate(result["products"]): if "name" not in product or not product["name"]: product["name"] = f"Hair Care Product {i + 1}" def _clean_text_items(items: List[str], limit: int = 5) -> List[str]: cleaned: List[str] = [] seen = set() for item in items: if not item: continue normalized = " ".join(item.split()) if len(normalized) < 5: continue key = normalized.lower() if key in seen: continue seen.add(key) cleaned.append(normalized) if len(cleaned) >= limit: break return cleaned def _clean_remedies(remedies: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) ingredients = rem.get("ingredients") or [] ingredients = [ing.strip() for ing in ingredients if isinstance(ing, str) and ing.strip()] cleaned.append( { "name": name, "ingredients": ingredients[:5], "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip(), } ) if len(cleaned) >= limit: break return cleaned result["care_tips"] = _clean_text_items(result["care_tips"], limit=5) result["home_remedies"] = _clean_remedies(result["home_remedies"], limit=3) return result def parse_remedies_only(self, response: Optional[str]) -> List[Dict[str, Any]]: """Parse home remedies only""" remedies: List[Dict[str, Any]] = [] if not response: return remedies lines = response.split("\n") current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None for line in lines: line = line.strip() if not line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break current_remedy = {} current_remedy_section = None continue lower = line.lower() if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*")) and current_remedy_section: text = line.lstrip("-•* ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: current_value = current_remedy.get(current_remedy_section, "") if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(line) else: current_remedy[current_remedy_section] = (current_value + " " + line).strip() if current_remedy.get("name") and current_remedy.get("instructions") and len(remedies) < 3: remedies.append(current_remedy) def _clean_remedies(remedies_list: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies_list: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) cleaned.append({ "name": name, "ingredients": rem.get("ingredients", []), "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip() }) if len(cleaned) >= limit: break return cleaned return _clean_remedies(remedies, limit=3) i want this prompt will look like the image i have shared it will worked like that generate the images
The image shows a basket full of freshly baked croissants. They are golden brown and flaky, and some of them have a slightly burnt edge. They are piled high in the basket, and some of them are overlapping. The background is blurred, but it appears to be a kitchen counter or table. { "title": "Croissants", "ingredients": [ { "name": "All-purpose flour", "quantity": "500g" }, { "name": "Salt", "quantity": "10g" }, { "name": "Sugar", "quantity": "20g" }, { "name": "Instant yeast", "quantity": "7g" }, { "name": "Unsalted butter", "quantity": "250g" }, { "name": "Milk", "quantity": "250ml" }, { "name": "Egg yolk", "quantity": "1" } ], "instructions": [ "In a large bowl, combine the flour, salt, sugar, and yeast.", "Add the milk and mix until a dough forms.", "Knead the dough for 10 minutes, until it is smooth and elastic.", "Place the dough in a greased bowl, cover, and let it rise in a warm place for 1 hour.", "Roll out the dough into a rectangle about 1/4 inch thick.", "Spread the softened butter evenly over the dough.", "Fold the dough in thirds, like a letter.", "Wrap the dough in plastic wrap and refrigerate for 30 minutes.", "Repeat steps 7 and 8 two more times.", "Roll out the dough into a rectangle about 1/2 inch thick.", "Cut the dough into triangles.", "Roll up each triangle, starting from the wide end.", "Place the croissants on a baking sheet lined with parchment paper.", "Cover and let them rise for 1 hour.", "Brush the croissants with egg yolk and bake at 375 degrees Fahrenheit for 15-20 minutes, or until golden brown." ], "notes": "You can use a stand mixer with a dough hook to knead the dough. Make sure the butter is softened to room temperature before spreading it on the dough. The croissants will rise best in a warm place, like a turned-off oven with a bowl of hot water inside." }
from typing import Optional, List, Dict, Any from services.llm_service import LLMService class RecommendationService: """Generate recommendations with clear, professional prompts""" def __init__(self): self.llm = LLMService() def generate_haircuts( self, hair_type: str, face_shape: str, gender: str, preference: str, hair_length: str, age: int, ) -> Optional[str]: """Generate haircut recommendations with clear, detailed guidance""" prompt = f"""You are an experienced professional hair stylist. Provide 3 specific haircut recommendations for this client. CLIENT INFORMATION: - Hair Type: {hair_type} - Face Shape: {face_shape} - Gender: {gender} - Age: {age} years - Style Preference: {preference} - Desired Length: {hair_length} REQUIREMENTS: Recommend 3 DIFFERENT haircuts that: 1. Complement the {face_shape} face shape 2. Work well with {hair_type} hair 3. Match the {preference} style 4. Are appropriate for {age} years old 5. Achieve the {hair_length} length For each haircut, provide: - Specific haircut name (e.g., "Textured Layered Bob" not just "Bob") - Clear 2-3 sentence description of the cut - Explanation of why it works for this face shape and hair type - Styling difficulty: Easy/Medium/Advanced - Maintenance level: Low/Medium/High FACE SHAPE GUIDELINES: - Oval: Most versatile, suits almost any style - Round: Add height and angles, avoid width at cheeks - Square: Soften jawline with layers and texture - Heart: Balance wide forehead with volume at chin - Oblong: Add width at sides, avoid too much height - Diamond: Add volume at crown and chin area HAIR TYPE CONSIDERATIONS: - Straight: Needs texture and layers for movement - Wavy: Embrace natural texture, avoid excessive layers - Curly: Account for shrinkage, needs length and moisture - Fine: Avoid over-layering, create illusion of thickness - Thick: Needs thinning and internal layers FORMAT: 1. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 2. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 3. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] Answer: 1.""" response = self.llm.query(prompt, timeout=40) return "1." + response.strip() if response else None def generate_products(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations with care tips and home remedies""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and solutions for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Dove Intensive Repair Shampoo") 2. Include brand name 3. Specify size (e.g., 250ml, 400g, 16 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 3 practical care tips specifically for {hair_problem} with {hair_type} hair. Focus on: - Daily habits and techniques - Washing and styling methods - Protection and prevention - NOT product recommendations TASK 3 - HOME REMEDIES: Provide 3 home remedies for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements - Have clear step-by-step instructions - Explain benefits - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Home Remedies for {hair_problem}: Remedy 1: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 2: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 3: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_products_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations and care tips only""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and care tips for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Pantene Pro-V Daily Moisture Renewal Shampoo") 2. Include brand name 3. Specify size (e.g., 355ml, 16.9 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 5 practical, actionable care tips specifically for {hair_problem} with {hair_type} hair. Tips should: - Be specific daily habits or techniques (NOT product recommendations) - Be evidence-based for {hair_problem} - Be appropriate for {hair_type} hair - Cover different areas: washing, styling, diet, protection, etc. FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_remedies_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate home remedies only""" prompt = f"""You are a natural hair care expert. Provide home remedies for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK: Provide 3 home remedies specifically for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements (tablespoons, cups, etc.) - Have clear step-by-step instructions - Explain benefits and why it works - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) - Be safe for {age} years old - Consider {hair_type} hair characteristics FORMAT: Remedy 1: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 2: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 3: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Answer: Remedy 1:""" response = self.llm.query(prompt, timeout=40) return "Remedy 1:" + response.strip() if response else None def parse_haircuts(self, response: Optional[str]) -> List[Dict]: """Parse haircut response""" haircuts: List[Dict] = [] if not response: return haircuts lines = response.split("\n") current: Dict[str, str] = {} allowed_difficulty = {"easy", "medium", "advanced"} allowed_maintenance = {"low", "medium", "high"} for line in lines: line = line.strip() if not line: continue if line and line[0].isdigit() and "." in line: if current and "name" in current: haircuts.append(current) if len(haircuts) >= 3: break parts = line.split(".", 1) if len(parts) == 2: name = parts[1].strip() current = {"name": name, "description": "", "why_works": "", "difficulty": "", "maintenance": ""} elif "Description:" in line or "description:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: current["description"] = parts[1].strip() elif "Why it works:" in line or "why it works:" in line.lower() or "Why:" in line: parts = line.split(":", 1) if len(parts) == 2 and current: current["why_works"] = parts[1].strip() elif "Difficulty:" in line or "difficulty:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: difficulty = parts[1].strip().lower() for level in allowed_difficulty: if level in difficulty: current["difficulty"] = level.capitalize() break elif "Maintenance:" in line or "maintenance:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: maintenance = parts[1].strip().lower() for level in allowed_maintenance: if level in maintenance: current["maintenance"] = level.capitalize() break if current and "name" in current: haircuts.append(current) valid_haircuts = [] for haircut in haircuts[:3]: if all(key in haircut and haircut[key] for key in ["name", "description", "why_works"]): if not haircut.get("difficulty"): haircut["difficulty"] = "Medium" if not haircut.get("maintenance"): haircut["maintenance"] = "Medium" valid_haircuts.append(haircut) return valid_haircuts def parse_products(self, response: Optional[str]) -> Dict[str, Any]: """Parse product recommendations, care tips, and home remedies""" result: Dict[str, Any] = { "products": [], "care_tips": [], "home_remedies": [] } if not response: return result lines = response.split("\n") current: Optional[Dict[str, str]] = None current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None in_care_tips_section = False in_remedies_section = False product_count = 0 for line in lines: line = line.strip() if not line: if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) current_remedy = {} current_remedy_section = None continue lower = line.lower() if "care tips" in lower or "care tip" in lower: in_care_tips_section = True in_remedies_section = False if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 continue if "home remed" in lower or "remedy 1:" in lower or (lower.startswith("remedy") and ":" in line): in_remedies_section = True in_care_tips_section = False if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None continue if in_care_tips_section and not in_remedies_section: if line.startswith(("-", "•", "*", "–")): tip = line.lstrip("-•*– ").strip() if len(tip) > 5: result["care_tips"].append(tip) elif not any(keyword in lower for keyword in ["product", "remedy", "brand:", "quantity:", "tip:"]): if len(line) > 15 and not line[0].isdigit(): result["care_tips"].append(line) continue if in_remedies_section: if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*", "–")) and current_remedy_section: text = line.lstrip("-•*– ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: if current_remedy_section == "ingredients" and not any(keyword in lower for keyword in ["instructions", "frequency", "benefits", "precautions"]): current_remedy.setdefault("ingredients", []).append(line) elif current_remedy_section != "ingredients": existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + line).strip() continue if not in_care_tips_section and not in_remedies_section: if lower.startswith("product") and ":" in line and product_count < 3: if current and "name" in current: result["products"].append(current) product_count += 1 if product_count >= 3: current = None continue parts = line.split(":", 1) if len(parts) == 2: product_name = parts[1].strip() current = {"name": product_name} else: if not current: current = {} elif line.startswith("Brand:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["brand"] = parts[1].strip() elif "Quantity:" in line and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["quantity"] = parts[1].strip() elif line.startswith("Tip:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["tip"] = parts[1].strip() elif current and "name" not in current: if not any(keyword in line.lower() for keyword in ["brand:", "quantity:", "tip:", "product", "care tips"]): if len(line) > 3: current["name"] = line if current and "name" in current and product_count < 3: result["products"].append(current) product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) for product in result["products"]: if "name" in product and product["name"]: name = product["name"].strip() if ":" in name: parts = name.split(":", 1) if len(parts) == 2: before_colon = parts[0].strip() after_colon = parts[1].strip() if len(before_colon.split()) <= 3 and len(after_colon) > len(before_colon): product["name"] = after_colon else: product["name"] = name else: product["name"] = name else: product["name"] = name for i, product in enumerate(result["products"]): if "name" not in product or not product["name"]: product["name"] = f"Hair Care Product {i + 1}" def _clean_text_items(items: List[str], limit: int = 5) -> List[str]: cleaned: List[str] = [] seen = set() for item in items: if not item: continue normalized = " ".join(item.split()) if len(normalized) < 5: continue key = normalized.lower() if key in seen: continue seen.add(key) cleaned.append(normalized) if len(cleaned) >= limit: break return cleaned def _clean_remedies(remedies: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) ingredients = rem.get("ingredients") or [] ingredients = [ing.strip() for ing in ingredients if isinstance(ing, str) and ing.strip()] cleaned.append( { "name": name, "ingredients": ingredients[:5], "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip(), } ) if len(cleaned) >= limit: break return cleaned result["care_tips"] = _clean_text_items(result["care_tips"], limit=5) result["home_remedies"] = _clean_remedies(result["home_remedies"], limit=3) return result def parse_remedies_only(self, response: Optional[str]) -> List[Dict[str, Any]]: """Parse home remedies only""" remedies: List[Dict[str, Any]] = [] if not response: return remedies lines = response.split("\n") current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None for line in lines: line = line.strip() if not line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break current_remedy = {} current_remedy_section = None continue lower = line.lower() if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*")) and current_remedy_section: text = line.lstrip("-•* ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: current_value = current_remedy.get(current_remedy_section, "") if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(line) else: current_remedy[current_remedy_section] = (current_value + " " + line).strip() if current_remedy.get("name") and current_remedy.get("instructions") and len(remedies) < 3: remedies.append(current_remedy) def _clean_remedies(remedies_list: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies_list: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) cleaned.append({ "name": name, "ingredients": rem.get("ingredients", []), "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip() }) if len(cleaned) >= limit: break return cleaned return _clean_remedies(remedies, limit=3) i want this prompt will look like the image i have shared it will worked like that generate the images
The image shows a basket full of freshly baked croissants. They are golden brown and flaky, and some of them have a slightly burnt edge. They are piled high in the basket, and some of them are overlapping. The background is blurred, but it appears to be a kitchen counter or table. { "title": "Croissants", "ingredients": [ { "name": "All-purpose flour", "quantity": "500g" }, { "name": "Salt", "quantity": "10g" }, { "name": "Sugar", "quantity": "20g" }, { "name": "Instant yeast", "quantity": "7g" }, { "name": "Unsalted butter", "quantity": "250g" }, { "name": "Milk", "quantity": "250ml" }, { "name": "Egg yolk", "quantity": "1" } ], "instructions": [ "In a large bowl, combine the flour, salt, sugar, and yeast.", "Add the milk and mix until a dough forms.", "Knead the dough for 10 minutes, until it is smooth and elastic.", "Place the dough in a greased bowl, cover, and let it rise in a warm place for 1 hour.", "Roll out the dough into a rectangle about 1/4 inch thick.", "Spread the softened butter evenly over the dough.", "Fold the dough in thirds, like a letter.", "Wrap the dough in plastic wrap and refrigerate for 30 minutes.", "Repeat steps 7 and 8 two more times.", "Roll out the dough into a rectangle about 1/2 inch thick.", "Cut the dough into triangles.", "Roll up each triangle, starting from the wide end.", "Place the croissants on a baking sheet lined with parchment paper.", "Cover and let them rise for 1 hour.", "Brush the croissants with egg yolk and bake at 375 degrees Fahrenheit for 15-20 minutes, or until golden brown." ], "notes": "You can use a stand mixer with a dough hook to knead the dough. Make sure the butter is softened to room temperature before spreading it on the dough. The croissants will rise best in a warm place, like a turned-off oven with a bowl of hot water inside." }
from typing import Optional, List, Dict, Any from services.llm_service import LLMService class RecommendationService: """Generate recommendations with clear, professional prompts""" def __init__(self): self.llm = LLMService() def generate_haircuts( self, hair_type: str, face_shape: str, gender: str, preference: str, hair_length: str, age: int, ) -> Optional[str]: """Generate haircut recommendations with clear, detailed guidance""" prompt = f"""You are an experienced professional hair stylist. Provide 3 specific haircut recommendations for this client. CLIENT INFORMATION: - Hair Type: {hair_type} - Face Shape: {face_shape} - Gender: {gender} - Age: {age} years - Style Preference: {preference} - Desired Length: {hair_length} REQUIREMENTS: Recommend 3 DIFFERENT haircuts that: 1. Complement the {face_shape} face shape 2. Work well with {hair_type} hair 3. Match the {preference} style 4. Are appropriate for {age} years old 5. Achieve the {hair_length} length For each haircut, provide: - Specific haircut name (e.g., "Textured Layered Bob" not just "Bob") - Clear 2-3 sentence description of the cut - Explanation of why it works for this face shape and hair type - Styling difficulty: Easy/Medium/Advanced - Maintenance level: Low/Medium/High FACE SHAPE GUIDELINES: - Oval: Most versatile, suits almost any style - Round: Add height and angles, avoid width at cheeks - Square: Soften jawline with layers and texture - Heart: Balance wide forehead with volume at chin - Oblong: Add width at sides, avoid too much height - Diamond: Add volume at crown and chin area HAIR TYPE CONSIDERATIONS: - Straight: Needs texture and layers for movement - Wavy: Embrace natural texture, avoid excessive layers - Curly: Account for shrinkage, needs length and moisture - Fine: Avoid over-layering, create illusion of thickness - Thick: Needs thinning and internal layers FORMAT: 1. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 2. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 3. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] Answer: 1.""" response = self.llm.query(prompt, timeout=40) return "1." + response.strip() if response else None def generate_products(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations with care tips and home remedies""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and solutions for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Dove Intensive Repair Shampoo") 2. Include brand name 3. Specify size (e.g., 250ml, 400g, 16 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 3 practical care tips specifically for {hair_problem} with {hair_type} hair. Focus on: - Daily habits and techniques - Washing and styling methods - Protection and prevention - NOT product recommendations TASK 3 - HOME REMEDIES: Provide 3 home remedies for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements - Have clear step-by-step instructions - Explain benefits - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Home Remedies for {hair_problem}: Remedy 1: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 2: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 3: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_products_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations and care tips only""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and care tips for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Pantene Pro-V Daily Moisture Renewal Shampoo") 2. Include brand name 3. Specify size (e.g., 355ml, 16.9 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 5 practical, actionable care tips specifically for {hair_problem} with {hair_type} hair. Tips should: - Be specific daily habits or techniques (NOT product recommendations) - Be evidence-based for {hair_problem} - Be appropriate for {hair_type} hair - Cover different areas: washing, styling, diet, protection, etc. FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_remedies_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate home remedies only""" prompt = f"""You are a natural hair care expert. Provide home remedies for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK: Provide 3 home remedies specifically for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements (tablespoons, cups, etc.) - Have clear step-by-step instructions - Explain benefits and why it works - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) - Be safe for {age} years old - Consider {hair_type} hair characteristics FORMAT: Remedy 1: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 2: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 3: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Answer: Remedy 1:""" response = self.llm.query(prompt, timeout=40) return "Remedy 1:" + response.strip() if response else None def parse_haircuts(self, response: Optional[str]) -> List[Dict]: """Parse haircut response""" haircuts: List[Dict] = [] if not response: return haircuts lines = response.split("\n") current: Dict[str, str] = {} allowed_difficulty = {"easy", "medium", "advanced"} allowed_maintenance = {"low", "medium", "high"} for line in lines: line = line.strip() if not line: continue if line and line[0].isdigit() and "." in line: if current and "name" in current: haircuts.append(current) if len(haircuts) >= 3: break parts = line.split(".", 1) if len(parts) == 2: name = parts[1].strip() current = {"name": name, "description": "", "why_works": "", "difficulty": "", "maintenance": ""} elif "Description:" in line or "description:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: current["description"] = parts[1].strip() elif "Why it works:" in line or "why it works:" in line.lower() or "Why:" in line: parts = line.split(":", 1) if len(parts) == 2 and current: current["why_works"] = parts[1].strip() elif "Difficulty:" in line or "difficulty:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: difficulty = parts[1].strip().lower() for level in allowed_difficulty: if level in difficulty: current["difficulty"] = level.capitalize() break elif "Maintenance:" in line or "maintenance:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: maintenance = parts[1].strip().lower() for level in allowed_maintenance: if level in maintenance: current["maintenance"] = level.capitalize() break if current and "name" in current: haircuts.append(current) valid_haircuts = [] for haircut in haircuts[:3]: if all(key in haircut and haircut[key] for key in ["name", "description", "why_works"]): if not haircut.get("difficulty"): haircut["difficulty"] = "Medium" if not haircut.get("maintenance"): haircut["maintenance"] = "Medium" valid_haircuts.append(haircut) return valid_haircuts def parse_products(self, response: Optional[str]) -> Dict[str, Any]: """Parse product recommendations, care tips, and home remedies""" result: Dict[str, Any] = { "products": [], "care_tips": [], "home_remedies": [] } if not response: return result lines = response.split("\n") current: Optional[Dict[str, str]] = None current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None in_care_tips_section = False in_remedies_section = False product_count = 0 for line in lines: line = line.strip() if not line: if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) current_remedy = {} current_remedy_section = None continue lower = line.lower() if "care tips" in lower or "care tip" in lower: in_care_tips_section = True in_remedies_section = False if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 continue if "home remed" in lower or "remedy 1:" in lower or (lower.startswith("remedy") and ":" in line): in_remedies_section = True in_care_tips_section = False if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None continue if in_care_tips_section and not in_remedies_section: if line.startswith(("-", "•", "*", "–")): tip = line.lstrip("-•*– ").strip() if len(tip) > 5: result["care_tips"].append(tip) elif not any(keyword in lower for keyword in ["product", "remedy", "brand:", "quantity:", "tip:"]): if len(line) > 15 and not line[0].isdigit(): result["care_tips"].append(line) continue if in_remedies_section: if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*", "–")) and current_remedy_section: text = line.lstrip("-•*– ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: if current_remedy_section == "ingredients" and not any(keyword in lower for keyword in ["instructions", "frequency", "benefits", "precautions"]): current_remedy.setdefault("ingredients", []).append(line) elif current_remedy_section != "ingredients": existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + line).strip() continue if not in_care_tips_section and not in_remedies_section: if lower.startswith("product") and ":" in line and product_count < 3: if current and "name" in current: result["products"].append(current) product_count += 1 if product_count >= 3: current = None continue parts = line.split(":", 1) if len(parts) == 2: product_name = parts[1].strip() current = {"name": product_name} else: if not current: current = {} elif line.startswith("Brand:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["brand"] = parts[1].strip() elif "Quantity:" in line and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["quantity"] = parts[1].strip() elif line.startswith("Tip:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["tip"] = parts[1].strip() elif current and "name" not in current: if not any(keyword in line.lower() for keyword in ["brand:", "quantity:", "tip:", "product", "care tips"]): if len(line) > 3: current["name"] = line if current and "name" in current and product_count < 3: result["products"].append(current) product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) for product in result["products"]: if "name" in product and product["name"]: name = product["name"].strip() if ":" in name: parts = name.split(":", 1) if len(parts) == 2: before_colon = parts[0].strip() after_colon = parts[1].strip() if len(before_colon.split()) <= 3 and len(after_colon) > len(before_colon): product["name"] = after_colon else: product["name"] = name else: product["name"] = name else: product["name"] = name for i, product in enumerate(result["products"]): if "name" not in product or not product["name"]: product["name"] = f"Hair Care Product {i + 1}" def _clean_text_items(items: List[str], limit: int = 5) -> List[str]: cleaned: List[str] = [] seen = set() for item in items: if not item: continue normalized = " ".join(item.split()) if len(normalized) < 5: continue key = normalized.lower() if key in seen: continue seen.add(key) cleaned.append(normalized) if len(cleaned) >= limit: break return cleaned def _clean_remedies(remedies: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) ingredients = rem.get("ingredients") or [] ingredients = [ing.strip() for ing in ingredients if isinstance(ing, str) and ing.strip()] cleaned.append( { "name": name, "ingredients": ingredients[:5], "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip(), } ) if len(cleaned) >= limit: break return cleaned result["care_tips"] = _clean_text_items(result["care_tips"], limit=5) result["home_remedies"] = _clean_remedies(result["home_remedies"], limit=3) return result def parse_remedies_only(self, response: Optional[str]) -> List[Dict[str, Any]]: """Parse home remedies only""" remedies: List[Dict[str, Any]] = [] if not response: return remedies lines = response.split("\n") current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None for line in lines: line = line.strip() if not line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break current_remedy = {} current_remedy_section = None continue lower = line.lower() if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*")) and current_remedy_section: text = line.lstrip("-•* ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: current_value = current_remedy.get(current_remedy_section, "") if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(line) else: current_remedy[current_remedy_section] = (current_value + " " + line).strip() if current_remedy.get("name") and current_remedy.get("instructions") and len(remedies) < 3: remedies.append(current_remedy) def _clean_remedies(remedies_list: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies_list: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) cleaned.append({ "name": name, "ingredients": rem.get("ingredients", []), "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip() }) if len(cleaned) >= limit: break return cleaned return _clean_remedies(remedies, limit=3) i want this prompt will look like the image i have shared it will worked like that generate the images
from typing import Optional, List, Dict, Any from services.llm_service import LLMService class RecommendationService: """Generate recommendations with clear, professional prompts""" def __init__(self): self.llm = LLMService() def generate_haircuts( self, hair_type: str, face_shape: str, gender: str, preference: str, hair_length: str, age: int, ) -> Optional[str]: """Generate haircut recommendations with clear, detailed guidance""" prompt = f"""You are an experienced professional hair stylist. Provide 3 specific haircut recommendations for this client. CLIENT INFORMATION: - Hair Type: {hair_type} - Face Shape: {face_shape} - Gender: {gender} - Age: {age} years - Style Preference: {preference} - Desired Length: {hair_length} REQUIREMENTS: Recommend 3 DIFFERENT haircuts that: 1. Complement the {face_shape} face shape 2. Work well with {hair_type} hair 3. Match the {preference} style 4. Are appropriate for {age} years old 5. Achieve the {hair_length} length For each haircut, provide: - Specific haircut name (e.g., "Textured Layered Bob" not just "Bob") - Clear 2-3 sentence description of the cut - Explanation of why it works for this face shape and hair type - Styling difficulty: Easy/Medium/Advanced - Maintenance level: Low/Medium/High FACE SHAPE GUIDELINES: - Oval: Most versatile, suits almost any style - Round: Add height and angles, avoid width at cheeks - Square: Soften jawline with layers and texture - Heart: Balance wide forehead with volume at chin - Oblong: Add width at sides, avoid too much height - Diamond: Add volume at crown and chin area HAIR TYPE CONSIDERATIONS: - Straight: Needs texture and layers for movement - Wavy: Embrace natural texture, avoid excessive layers - Curly: Account for shrinkage, needs length and moisture - Fine: Avoid over-layering, create illusion of thickness - Thick: Needs thinning and internal layers FORMAT: 1. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 2. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 3. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] Answer: 1.""" response = self.llm.query(prompt, timeout=40) return "1." + response.strip() if response else None def generate_products(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations with care tips and home remedies""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and solutions for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Dove Intensive Repair Shampoo") 2. Include brand name 3. Specify size (e.g., 250ml, 400g, 16 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 3 practical care tips specifically for {hair_problem} with {hair_type} hair. Focus on: - Daily habits and techniques - Washing and styling methods - Protection and prevention - NOT product recommendations TASK 3 - HOME REMEDIES: Provide 3 home remedies for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements - Have clear step-by-step instructions - Explain benefits - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Home Remedies for {hair_problem}: Remedy 1: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 2: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 3: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_products_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations and care tips only""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and care tips for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Pantene Pro-V Daily Moisture Renewal Shampoo") 2. Include brand name 3. Specify size (e.g., 355ml, 16.9 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 5 practical, actionable care tips specifically for {hair_problem} with {hair_type} hair. Tips should: - Be specific daily habits or techniques (NOT product recommendations) - Be evidence-based for {hair_problem} - Be appropriate for {hair_type} hair - Cover different areas: washing, styling, diet, protection, etc. FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_remedies_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate home remedies only""" prompt = f"""You are a natural hair care expert. Provide home remedies for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK: Provide 3 home remedies specifically for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements (tablespoons, cups, etc.) - Have clear step-by-step instructions - Explain benefits and why it works - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) - Be safe for {age} years old - Consider {hair_type} hair characteristics FORMAT: Remedy 1: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 2: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 3: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Answer: Remedy 1:""" response = self.llm.query(prompt, timeout=40) return "Remedy 1:" + response.strip() if response else None def parse_haircuts(self, response: Optional[str]) -> List[Dict]: """Parse haircut response""" haircuts: List[Dict] = [] if not response: return haircuts lines = response.split("\n") current: Dict[str, str] = {} allowed_difficulty = {"easy", "medium", "advanced"} allowed_maintenance = {"low", "medium", "high"} for line in lines: line = line.strip() if not line: continue if line and line[0].isdigit() and "." in line: if current and "name" in current: haircuts.append(current) if len(haircuts) >= 3: break parts = line.split(".", 1) if len(parts) == 2: name = parts[1].strip() current = {"name": name, "description": "", "why_works": "", "difficulty": "", "maintenance": ""} elif "Description:" in line or "description:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: current["description"] = parts[1].strip() elif "Why it works:" in line or "why it works:" in line.lower() or "Why:" in line: parts = line.split(":", 1) if len(parts) == 2 and current: current["why_works"] = parts[1].strip() elif "Difficulty:" in line or "difficulty:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: difficulty = parts[1].strip().lower() for level in allowed_difficulty: if level in difficulty: current["difficulty"] = level.capitalize() break elif "Maintenance:" in line or "maintenance:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: maintenance = parts[1].strip().lower() for level in allowed_maintenance: if level in maintenance: current["maintenance"] = level.capitalize() break if current and "name" in current: haircuts.append(current) valid_haircuts = [] for haircut in haircuts[:3]: if all(key in haircut and haircut[key] for key in ["name", "description", "why_works"]): if not haircut.get("difficulty"): haircut["difficulty"] = "Medium" if not haircut.get("maintenance"): haircut["maintenance"] = "Medium" valid_haircuts.append(haircut) return valid_haircuts def parse_products(self, response: Optional[str]) -> Dict[str, Any]: """Parse product recommendations, care tips, and home remedies""" result: Dict[str, Any] = { "products": [], "care_tips": [], "home_remedies": [] } if not response: return result lines = response.split("\n") current: Optional[Dict[str, str]] = None current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None in_care_tips_section = False in_remedies_section = False product_count = 0 for line in lines: line = line.strip() if not line: if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) current_remedy = {} current_remedy_section = None continue lower = line.lower() if "care tips" in lower or "care tip" in lower: in_care_tips_section = True in_remedies_section = False if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 continue if "home remed" in lower or "remedy 1:" in lower or (lower.startswith("remedy") and ":" in line): in_remedies_section = True in_care_tips_section = False if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None continue if in_care_tips_section and not in_remedies_section: if line.startswith(("-", "•", "*", "–")): tip = line.lstrip("-•*– ").strip() if len(tip) > 5: result["care_tips"].append(tip) elif not any(keyword in lower for keyword in ["product", "remedy", "brand:", "quantity:", "tip:"]): if len(line) > 15 and not line[0].isdigit(): result["care_tips"].append(line) continue if in_remedies_section: if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*", "–")) and current_remedy_section: text = line.lstrip("-•*– ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: if current_remedy_section == "ingredients" and not any(keyword in lower for keyword in ["instructions", "frequency", "benefits", "precautions"]): current_remedy.setdefault("ingredients", []).append(line) elif current_remedy_section != "ingredients": existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + line).strip() continue if not in_care_tips_section and not in_remedies_section: if lower.startswith("product") and ":" in line and product_count < 3: if current and "name" in current: result["products"].append(current) product_count += 1 if product_count >= 3: current = None continue parts = line.split(":", 1) if len(parts) == 2: product_name = parts[1].strip() current = {"name": product_name} else: if not current: current = {} elif line.startswith("Brand:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["brand"] = parts[1].strip() elif "Quantity:" in line and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["quantity"] = parts[1].strip() elif line.startswith("Tip:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["tip"] = parts[1].strip() elif current and "name" not in current: if not any(keyword in line.lower() for keyword in ["brand:", "quantity:", "tip:", "product", "care tips"]): if len(line) > 3: current["name"] = line if current and "name" in current and product_count < 3: result["products"].append(current) product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) for product in result["products"]: if "name" in product and product["name"]: name = product["name"].strip() if ":" in name: parts = name.split(":", 1) if len(parts) == 2: before_colon = parts[0].strip() after_colon = parts[1].strip() if len(before_colon.split()) <= 3 and len(after_colon) > len(before_colon): product["name"] = after_colon else: product["name"] = name else: product["name"] = name else: product["name"] = name for i, product in enumerate(result["products"]): if "name" not in product or not product["name"]: product["name"] = f"Hair Care Product {i + 1}" def _clean_text_items(items: List[str], limit: int = 5) -> List[str]: cleaned: List[str] = [] seen = set() for item in items: if not item: continue normalized = " ".join(item.split()) if len(normalized) < 5: continue key = normalized.lower() if key in seen: continue seen.add(key) cleaned.append(normalized) if len(cleaned) >= limit: break return cleaned def _clean_remedies(remedies: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) ingredients = rem.get("ingredients") or [] ingredients = [ing.strip() for ing in ingredients if isinstance(ing, str) and ing.strip()] cleaned.append( { "name": name, "ingredients": ingredients[:5], "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip(), } ) if len(cleaned) >= limit: break return cleaned result["care_tips"] = _clean_text_items(result["care_tips"], limit=5) result["home_remedies"] = _clean_remedies(result["home_remedies"], limit=3) return result def parse_remedies_only(self, response: Optional[str]) -> List[Dict[str, Any]]: """Parse home remedies only""" remedies: List[Dict[str, Any]] = [] if not response: return remedies lines = response.split("\n") current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None for line in lines: line = line.strip() if not line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break current_remedy = {} current_remedy_section = None continue lower = line.lower() if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*")) and current_remedy_section: text = line.lstrip("-•* ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: current_value = current_remedy.get(current_remedy_section, "") if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(line) else: current_remedy[current_remedy_section] = (current_value + " " + line).strip() if current_remedy.get("name") and current_remedy.get("instructions") and len(remedies) < 3: remedies.append(current_remedy) def _clean_remedies(remedies_list: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies_list: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) cleaned.append({ "name": name, "ingredients": rem.get("ingredients", []), "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip() }) if len(cleaned) >= limit: break return cleaned return _clean_remedies(remedies, limit=3) i want this prompt will look like the image i have shared it will worked like that generate the images
The image shows a basket full of freshly baked croissants. They are golden brown and flaky, and some of them have a slightly burnt edge. They are piled high in the basket, and some of them are overlapping. The background is blurred, but it appears to be a kitchen counter or table. { "title": "Croissants", "ingredients": [ { "name": "All-purpose flour", "quantity": "500g" }, { "name": "Salt", "quantity": "10g" }, { "name": "Sugar", "quantity": "20g" }, { "name": "Instant yeast", "quantity": "7g" }, { "name": "Unsalted butter", "quantity": "250g" }, { "name": "Milk", "quantity": "250ml" }, { "name": "Egg yolk", "quantity": "1" } ], "instructions": [ "In a large bowl, combine the flour, salt, sugar, and yeast.", "Add the milk and mix until a dough forms.", "Knead the dough for 10 minutes, until it is smooth and elastic.", "Place the dough in a greased bowl, cover, and let it rise in a warm place for 1 hour.", "Roll out the dough into a rectangle about 1/4 inch thick.", "Spread the softened butter evenly over the dough.", "Fold the dough in thirds, like a letter.", "Wrap the dough in plastic wrap and refrigerate for 30 minutes.", "Repeat steps 7 and 8 two more times.", "Roll out the dough into a rectangle about 1/2 inch thick.", "Cut the dough into triangles.", "Roll up each triangle, starting from the wide end.", "Place the croissants on a baking sheet lined with parchment paper.", "Cover and let them rise for 1 hour.", "Brush the croissants with egg yolk and bake at 375 degrees Fahrenheit for 15-20 minutes, or until golden brown." ], "notes": "You can use a stand mixer with a dough hook to knead the dough. Make sure the butter is softened to room temperature before spreading it on the dough. The croissants will rise best in a warm place, like a turned-off oven with a bowl of hot water inside." }
The image shows a basket full of freshly baked croissants. They are golden brown and flaky, and some of them have a slightly burnt edge. They are piled high in the basket, and some of them are overlapping. The background is blurred, but it appears to be a kitchen counter or table. { "title": "Croissants", "ingredients": [ { "name": "All-purpose flour", "quantity": "500g" }, { "name": "Salt", "quantity": "10g" }, { "name": "Sugar", "quantity": "20g" }, { "name": "Instant yeast", "quantity": "7g" }, { "name": "Unsalted butter", "quantity": "250g" }, { "name": "Milk", "quantity": "250ml" }, { "name": "Egg yolk", "quantity": "1" } ], "instructions": [ "In a large bowl, combine the flour, salt, sugar, and yeast.", "Add the milk and mix until a dough forms.", "Knead the dough for 10 minutes, until it is smooth and elastic.", "Place the dough in a greased bowl, cover, and let it rise in a warm place for 1 hour.", "Roll out the dough into a rectangle about 1/4 inch thick.", "Spread the softened butter evenly over the dough.", "Fold the dough in thirds, like a letter.", "Wrap the dough in plastic wrap and refrigerate for 30 minutes.", "Repeat steps 7 and 8 two more times.", "Roll out the dough into a rectangle about 1/2 inch thick.", "Cut the dough into triangles.", "Roll up each triangle, starting from the wide end.", "Place the croissants on a baking sheet lined with parchment paper.", "Cover and let them rise for 1 hour.", "Brush the croissants with egg yolk and bake at 375 degrees Fahrenheit for 15-20 minutes, or until golden brown." ], "notes": "You can use a stand mixer with a dough hook to knead the dough. Make sure the butter is softened to room temperature before spreading it on the dough. The croissants will rise best in a warm place, like a turned-off oven with a bowl of hot water inside." }
from typing import Optional, List, Dict, Any from services.llm_service import LLMService class RecommendationService: """Generate recommendations with clear, professional prompts""" def __init__(self): self.llm = LLMService() def generate_haircuts( self, hair_type: str, face_shape: str, gender: str, preference: str, hair_length: str, age: int, ) -> Optional[str]: """Generate haircut recommendations with clear, detailed guidance""" prompt = f"""You are an experienced professional hair stylist. Provide 3 specific haircut recommendations for this client. CLIENT INFORMATION: - Hair Type: {hair_type} - Face Shape: {face_shape} - Gender: {gender} - Age: {age} years - Style Preference: {preference} - Desired Length: {hair_length} REQUIREMENTS: Recommend 3 DIFFERENT haircuts that: 1. Complement the {face_shape} face shape 2. Work well with {hair_type} hair 3. Match the {preference} style 4. Are appropriate for {age} years old 5. Achieve the {hair_length} length For each haircut, provide: - Specific haircut name (e.g., "Textured Layered Bob" not just "Bob") - Clear 2-3 sentence description of the cut - Explanation of why it works for this face shape and hair type - Styling difficulty: Easy/Medium/Advanced - Maintenance level: Low/Medium/High FACE SHAPE GUIDELINES: - Oval: Most versatile, suits almost any style - Round: Add height and angles, avoid width at cheeks - Square: Soften jawline with layers and texture - Heart: Balance wide forehead with volume at chin - Oblong: Add width at sides, avoid too much height - Diamond: Add volume at crown and chin area HAIR TYPE CONSIDERATIONS: - Straight: Needs texture and layers for movement - Wavy: Embrace natural texture, avoid excessive layers - Curly: Account for shrinkage, needs length and moisture - Fine: Avoid over-layering, create illusion of thickness - Thick: Needs thinning and internal layers FORMAT: 1. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 2. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 3. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] Answer: 1.""" response = self.llm.query(prompt, timeout=40) return "1." + response.strip() if response else None def generate_products(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations with care tips and home remedies""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and solutions for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Dove Intensive Repair Shampoo") 2. Include brand name 3. Specify size (e.g., 250ml, 400g, 16 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 3 practical care tips specifically for {hair_problem} with {hair_type} hair. Focus on: - Daily habits and techniques - Washing and styling methods - Protection and prevention - NOT product recommendations TASK 3 - HOME REMEDIES: Provide 3 home remedies for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements - Have clear step-by-step instructions - Explain benefits - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Home Remedies for {hair_problem}: Remedy 1: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 2: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 3: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_products_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations and care tips only""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and care tips for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Pantene Pro-V Daily Moisture Renewal Shampoo") 2. Include brand name 3. Specify size (e.g., 355ml, 16.9 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 5 practical, actionable care tips specifically for {hair_problem} with {hair_type} hair. Tips should: - Be specific daily habits or techniques (NOT product recommendations) - Be evidence-based for {hair_problem} - Be appropriate for {hair_type} hair - Cover different areas: washing, styling, diet, protection, etc. FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_remedies_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate home remedies only""" prompt = f"""You are a natural hair care expert. Provide home remedies for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK: Provide 3 home remedies specifically for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements (tablespoons, cups, etc.) - Have clear step-by-step instructions - Explain benefits and why it works - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) - Be safe for {age} years old - Consider {hair_type} hair characteristics FORMAT: Remedy 1: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 2: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 3: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Answer: Remedy 1:""" response = self.llm.query(prompt, timeout=40) return "Remedy 1:" + response.strip() if response else None def parse_haircuts(self, response: Optional[str]) -> List[Dict]: """Parse haircut response""" haircuts: List[Dict] = [] if not response: return haircuts lines = response.split("\n") current: Dict[str, str] = {} allowed_difficulty = {"easy", "medium", "advanced"} allowed_maintenance = {"low", "medium", "high"} for line in lines: line = line.strip() if not line: continue if line and line[0].isdigit() and "." in line: if current and "name" in current: haircuts.append(current) if len(haircuts) >= 3: break parts = line.split(".", 1) if len(parts) == 2: name = parts[1].strip() current = {"name": name, "description": "", "why_works": "", "difficulty": "", "maintenance": ""} elif "Description:" in line or "description:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: current["description"] = parts[1].strip() elif "Why it works:" in line or "why it works:" in line.lower() or "Why:" in line: parts = line.split(":", 1) if len(parts) == 2 and current: current["why_works"] = parts[1].strip() elif "Difficulty:" in line or "difficulty:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: difficulty = parts[1].strip().lower() for level in allowed_difficulty: if level in difficulty: current["difficulty"] = level.capitalize() break elif "Maintenance:" in line or "maintenance:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: maintenance = parts[1].strip().lower() for level in allowed_maintenance: if level in maintenance: current["maintenance"] = level.capitalize() break if current and "name" in current: haircuts.append(current) valid_haircuts = [] for haircut in haircuts[:3]: if all(key in haircut and haircut[key] for key in ["name", "description", "why_works"]): if not haircut.get("difficulty"): haircut["difficulty"] = "Medium" if not haircut.get("maintenance"): haircut["maintenance"] = "Medium" valid_haircuts.append(haircut) return valid_haircuts def parse_products(self, response: Optional[str]) -> Dict[str, Any]: """Parse product recommendations, care tips, and home remedies""" result: Dict[str, Any] = { "products": [], "care_tips": [], "home_remedies": [] } if not response: return result lines = response.split("\n") current: Optional[Dict[str, str]] = None current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None in_care_tips_section = False in_remedies_section = False product_count = 0 for line in lines: line = line.strip() if not line: if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) current_remedy = {} current_remedy_section = None continue lower = line.lower() if "care tips" in lower or "care tip" in lower: in_care_tips_section = True in_remedies_section = False if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 continue if "home remed" in lower or "remedy 1:" in lower or (lower.startswith("remedy") and ":" in line): in_remedies_section = True in_care_tips_section = False if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None continue if in_care_tips_section and not in_remedies_section: if line.startswith(("-", "•", "*", "–")): tip = line.lstrip("-•*– ").strip() if len(tip) > 5: result["care_tips"].append(tip) elif not any(keyword in lower for keyword in ["product", "remedy", "brand:", "quantity:", "tip:"]): if len(line) > 15 and not line[0].isdigit(): result["care_tips"].append(line) continue if in_remedies_section: if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*", "–")) and current_remedy_section: text = line.lstrip("-•*– ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: if current_remedy_section == "ingredients" and not any(keyword in lower for keyword in ["instructions", "frequency", "benefits", "precautions"]): current_remedy.setdefault("ingredients", []).append(line) elif current_remedy_section != "ingredients": existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + line).strip() continue if not in_care_tips_section and not in_remedies_section: if lower.startswith("product") and ":" in line and product_count < 3: if current and "name" in current: result["products"].append(current) product_count += 1 if product_count >= 3: current = None continue parts = line.split(":", 1) if len(parts) == 2: product_name = parts[1].strip() current = {"name": product_name} else: if not current: current = {} elif line.startswith("Brand:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["brand"] = parts[1].strip() elif "Quantity:" in line and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["quantity"] = parts[1].strip() elif line.startswith("Tip:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["tip"] = parts[1].strip() elif current and "name" not in current: if not any(keyword in line.lower() for keyword in ["brand:", "quantity:", "tip:", "product", "care tips"]): if len(line) > 3: current["name"] = line if current and "name" in current and product_count < 3: result["products"].append(current) product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) for product in result["products"]: if "name" in product and product["name"]: name = product["name"].strip() if ":" in name: parts = name.split(":", 1) if len(parts) == 2: before_colon = parts[0].strip() after_colon = parts[1].strip() if len(before_colon.split()) <= 3 and len(after_colon) > len(before_colon): product["name"] = after_colon else: product["name"] = name else: product["name"] = name else: product["name"] = name for i, product in enumerate(result["products"]): if "name" not in product or not product["name"]: product["name"] = f"Hair Care Product {i + 1}" def _clean_text_items(items: List[str], limit: int = 5) -> List[str]: cleaned: List[str] = [] seen = set() for item in items: if not item: continue normalized = " ".join(item.split()) if len(normalized) < 5: continue key = normalized.lower() if key in seen: continue seen.add(key) cleaned.append(normalized) if len(cleaned) >= limit: break return cleaned def _clean_remedies(remedies: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) ingredients = rem.get("ingredients") or [] ingredients = [ing.strip() for ing in ingredients if isinstance(ing, str) and ing.strip()] cleaned.append( { "name": name, "ingredients": ingredients[:5], "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip(), } ) if len(cleaned) >= limit: break return cleaned result["care_tips"] = _clean_text_items(result["care_tips"], limit=5) result["home_remedies"] = _clean_remedies(result["home_remedies"], limit=3) return result def parse_remedies_only(self, response: Optional[str]) -> List[Dict[str, Any]]: """Parse home remedies only""" remedies: List[Dict[str, Any]] = [] if not response: return remedies lines = response.split("\n") current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None for line in lines: line = line.strip() if not line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break current_remedy = {} current_remedy_section = None continue lower = line.lower() if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*")) and current_remedy_section: text = line.lstrip("-•* ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: current_value = current_remedy.get(current_remedy_section, "") if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(line) else: current_remedy[current_remedy_section] = (current_value + " " + line).strip() if current_remedy.get("name") and current_remedy.get("instructions") and len(remedies) < 3: remedies.append(current_remedy) def _clean_remedies(remedies_list: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies_list: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) cleaned.append({ "name": name, "ingredients": rem.get("ingredients", []), "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip() }) if len(cleaned) >= limit: break return cleaned return _clean_remedies(remedies, limit=3) i want this prompt will look like the image i have shared it will worked like that generate the images
The image shows a basket full of freshly baked croissants. They are golden brown and flaky, and some of them have a slightly burnt edge. They are piled high in the basket, and some of them are overlapping. The background is blurred, but it appears to be a kitchen counter or table. { "title": "Croissants", "ingredients": [ { "name": "All-purpose flour", "quantity": "500g" }, { "name": "Salt", "quantity": "10g" }, { "name": "Sugar", "quantity": "20g" }, { "name": "Instant yeast", "quantity": "7g" }, { "name": "Unsalted butter", "quantity": "250g" }, { "name": "Milk", "quantity": "250ml" }, { "name": "Egg yolk", "quantity": "1" } ], "instructions": [ "In a large bowl, combine the flour, salt, sugar, and yeast.", "Add the milk and mix until a dough forms.", "Knead the dough for 10 minutes, until it is smooth and elastic.", "Place the dough in a greased bowl, cover, and let it rise in a warm place for 1 hour.", "Roll out the dough into a rectangle about 1/4 inch thick.", "Spread the softened butter evenly over the dough.", "Fold the dough in thirds, like a letter.", "Wrap the dough in plastic wrap and refrigerate for 30 minutes.", "Repeat steps 7 and 8 two more times.", "Roll out the dough into a rectangle about 1/2 inch thick.", "Cut the dough into triangles.", "Roll up each triangle, starting from the wide end.", "Place the croissants on a baking sheet lined with parchment paper.", "Cover and let them rise for 1 hour.", "Brush the croissants with egg yolk and bake at 375 degrees Fahrenheit for 15-20 minutes, or until golden brown." ], "notes": "You can use a stand mixer with a dough hook to knead the dough. Make sure the butter is softened to room temperature before spreading it on the dough. The croissants will rise best in a warm place, like a turned-off oven with a bowl of hot water inside." }
from typing import Optional, List, Dict, Any from services.llm_service import LLMService class RecommendationService: """Generate recommendations with clear, professional prompts""" def __init__(self): self.llm = LLMService() def generate_haircuts( self, hair_type: str, face_shape: str, gender: str, preference: str, hair_length: str, age: int, ) -> Optional[str]: """Generate haircut recommendations with clear, detailed guidance""" prompt = f"""You are an experienced professional hair stylist. Provide 3 specific haircut recommendations for this client. CLIENT INFORMATION: - Hair Type: {hair_type} - Face Shape: {face_shape} - Gender: {gender} - Age: {age} years - Style Preference: {preference} - Desired Length: {hair_length} REQUIREMENTS: Recommend 3 DIFFERENT haircuts that: 1. Complement the {face_shape} face shape 2. Work well with {hair_type} hair 3. Match the {preference} style 4. Are appropriate for {age} years old 5. Achieve the {hair_length} length For each haircut, provide: - Specific haircut name (e.g., "Textured Layered Bob" not just "Bob") - Clear 2-3 sentence description of the cut - Explanation of why it works for this face shape and hair type - Styling difficulty: Easy/Medium/Advanced - Maintenance level: Low/Medium/High FACE SHAPE GUIDELINES: - Oval: Most versatile, suits almost any style - Round: Add height and angles, avoid width at cheeks - Square: Soften jawline with layers and texture - Heart: Balance wide forehead with volume at chin - Oblong: Add width at sides, avoid too much height - Diamond: Add volume at crown and chin area HAIR TYPE CONSIDERATIONS: - Straight: Needs texture and layers for movement - Wavy: Embrace natural texture, avoid excessive layers - Curly: Account for shrinkage, needs length and moisture - Fine: Avoid over-layering, create illusion of thickness - Thick: Needs thinning and internal layers FORMAT: 1. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 2. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] 3. [Haircut Name] Description: [What the haircut looks like] Why it works: [How it flatters face shape and complements hair type] Difficulty: [Easy/Medium/Advanced] Maintenance: [Low/Medium/High] Answer: 1.""" response = self.llm.query(prompt, timeout=40) return "1." + response.strip() if response else None def generate_products(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations with care tips and home remedies""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and solutions for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Dove Intensive Repair Shampoo") 2. Include brand name 3. Specify size (e.g., 250ml, 400g, 16 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 3 practical care tips specifically for {hair_problem} with {hair_type} hair. Focus on: - Daily habits and techniques - Washing and styling methods - Protection and prevention - NOT product recommendations TASK 3 - HOME REMEDIES: Provide 3 home remedies for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements - Have clear step-by-step instructions - Explain benefits - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Home Remedies for {hair_problem}: Remedy 1: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 2: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Remedy 3: [Remedy Name] Ingredients: - [Ingredient with measurement] - [Ingredient with measurement] Instructions: [Clear step-by-step instructions including preparation, application, duration, and removal] Frequency: [How often to use] Benefits: [Why this works for {hair_problem}] Precautions: [Safety warnings and allergy information] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_products_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate product recommendations and care tips only""" prompt = f"""You are a professional hair care specialist. Provide product recommendations and care tips for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK 1 - PRODUCT RECOMMENDATIONS: Recommend 3 REAL products from these brands: L'Oréal Paris, Dove, TRESemmé, Pantene, Garnier Fructis, Head & Shoulders, OGX, Neutrogena, Herbal Essences, Nizoral, Kérastase, Shea Moisture, or Redken. For each product: 1. Use EXACT product name (e.g., "Pantene Pro-V Daily Moisture Renewal Shampoo") 2. Include brand name 3. Specify size (e.g., 355ml, 16.9 fl oz) 4. Provide specific usage tip for {hair_problem} Choose products that: - Specifically address {hair_problem} - Are suitable for {hair_type} hair - Are age-appropriate for {age} years old - Include variety: cleanser, treatment, and styling product TASK 2 - CARE TIPS: Provide 5 practical, actionable care tips specifically for {hair_problem} with {hair_type} hair. Tips should: - Be specific daily habits or techniques (NOT product recommendations) - Be evidence-based for {hair_problem} - Be appropriate for {hair_type} hair - Cover different areas: washing, styling, diet, protection, etc. FORMAT: Product 1: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 2: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Product 3: [Exact Product Name] Brand: [Brand Name] Quantity: [Size with units] Tip: [Specific usage instruction for {hair_problem}] Care Tips for {hair_problem}: - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] - [Specific actionable tip] Answer: Product 1:""" response = self.llm.query(prompt, timeout=40) return "Product 1:" + response.strip() if response else None def generate_remedies_only(self, hair_problem: str, hair_type: str, age: int) -> Optional[str]: """Generate home remedies only""" prompt = f"""You are a natural hair care expert. Provide home remedies for this client. CLIENT INFORMATION: - Age: {age} years old - Hair Type: {hair_type} - Hair Concern: {hair_problem} TASK: Provide 3 home remedies specifically for {hair_problem}. Each remedy should: - Use common household ingredients - Include specific measurements (tablespoons, cups, etc.) - Have clear step-by-step instructions - Explain benefits and why it works - Include safety precautions - Use DIFFERENT primary ingredients (no overlap) - Be safe for {age} years old - Consider {hair_type} hair characteristics FORMAT: Remedy 1: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 2: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Remedy 3: [Descriptive Remedy Name] Ingredients: - [Ingredient with specific measurement] - [Ingredient with specific measurement] - [Additional ingredients as needed] Instructions: [Clear step-by-step instructions: preparation, application method, duration, and removal process] Frequency: [Specific frequency - e.g., "Once per week", "Twice weekly"] Benefits: [Explain why this works for {hair_problem} and how ingredients help] Precautions: [Safety warnings, allergy alerts, patch test recommendation] Answer: Remedy 1:""" response = self.llm.query(prompt, timeout=40) return "Remedy 1:" + response.strip() if response else None def parse_haircuts(self, response: Optional[str]) -> List[Dict]: """Parse haircut response""" haircuts: List[Dict] = [] if not response: return haircuts lines = response.split("\n") current: Dict[str, str] = {} allowed_difficulty = {"easy", "medium", "advanced"} allowed_maintenance = {"low", "medium", "high"} for line in lines: line = line.strip() if not line: continue if line and line[0].isdigit() and "." in line: if current and "name" in current: haircuts.append(current) if len(haircuts) >= 3: break parts = line.split(".", 1) if len(parts) == 2: name = parts[1].strip() current = {"name": name, "description": "", "why_works": "", "difficulty": "", "maintenance": ""} elif "Description:" in line or "description:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: current["description"] = parts[1].strip() elif "Why it works:" in line or "why it works:" in line.lower() or "Why:" in line: parts = line.split(":", 1) if len(parts) == 2 and current: current["why_works"] = parts[1].strip() elif "Difficulty:" in line or "difficulty:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: difficulty = parts[1].strip().lower() for level in allowed_difficulty: if level in difficulty: current["difficulty"] = level.capitalize() break elif "Maintenance:" in line or "maintenance:" in line.lower(): parts = line.split(":", 1) if len(parts) == 2 and current: maintenance = parts[1].strip().lower() for level in allowed_maintenance: if level in maintenance: current["maintenance"] = level.capitalize() break if current and "name" in current: haircuts.append(current) valid_haircuts = [] for haircut in haircuts[:3]: if all(key in haircut and haircut[key] for key in ["name", "description", "why_works"]): if not haircut.get("difficulty"): haircut["difficulty"] = "Medium" if not haircut.get("maintenance"): haircut["maintenance"] = "Medium" valid_haircuts.append(haircut) return valid_haircuts def parse_products(self, response: Optional[str]) -> Dict[str, Any]: """Parse product recommendations, care tips, and home remedies""" result: Dict[str, Any] = { "products": [], "care_tips": [], "home_remedies": [] } if not response: return result lines = response.split("\n") current: Optional[Dict[str, str]] = None current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None in_care_tips_section = False in_remedies_section = False product_count = 0 for line in lines: line = line.strip() if not line: if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) current_remedy = {} current_remedy_section = None continue lower = line.lower() if "care tips" in lower or "care tip" in lower: in_care_tips_section = True in_remedies_section = False if current and "name" in current and product_count < 3: result["products"].append(current) current = None product_count += 1 continue if "home remed" in lower or "remedy 1:" in lower or (lower.startswith("remedy") and ":" in line): in_remedies_section = True in_care_tips_section = False if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None continue if in_care_tips_section and not in_remedies_section: if line.startswith(("-", "•", "*", "–")): tip = line.lstrip("-•*– ").strip() if len(tip) > 5: result["care_tips"].append(tip) elif not any(keyword in lower for keyword in ["product", "remedy", "brand:", "quantity:", "tip:"]): if len(line) > 15 and not line[0].isdigit(): result["care_tips"].append(line) continue if in_remedies_section: if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*", "–")) and current_remedy_section: text = line.lstrip("-•*– ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: if current_remedy_section == "ingredients" and not any(keyword in lower for keyword in ["instructions", "frequency", "benefits", "precautions"]): current_remedy.setdefault("ingredients", []).append(line) elif current_remedy_section != "ingredients": existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + line).strip() continue if not in_care_tips_section and not in_remedies_section: if lower.startswith("product") and ":" in line and product_count < 3: if current and "name" in current: result["products"].append(current) product_count += 1 if product_count >= 3: current = None continue parts = line.split(":", 1) if len(parts) == 2: product_name = parts[1].strip() current = {"name": product_name} else: if not current: current = {} elif line.startswith("Brand:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["brand"] = parts[1].strip() elif "Quantity:" in line and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["quantity"] = parts[1].strip() elif line.startswith("Tip:") and current is not None: parts = line.split(":", 1) if len(parts) == 2: current["tip"] = parts[1].strip() elif current and "name" not in current: if not any(keyword in line.lower() for keyword in ["brand:", "quantity:", "tip:", "product", "care tips"]): if len(line) > 3: current["name"] = line if current and "name" in current and product_count < 3: result["products"].append(current) product_count += 1 if current_remedy.get("name") and current_remedy.get("instructions"): result["home_remedies"].append(current_remedy) for product in result["products"]: if "name" in product and product["name"]: name = product["name"].strip() if ":" in name: parts = name.split(":", 1) if len(parts) == 2: before_colon = parts[0].strip() after_colon = parts[1].strip() if len(before_colon.split()) <= 3 and len(after_colon) > len(before_colon): product["name"] = after_colon else: product["name"] = name else: product["name"] = name else: product["name"] = name for i, product in enumerate(result["products"]): if "name" not in product or not product["name"]: product["name"] = f"Hair Care Product {i + 1}" def _clean_text_items(items: List[str], limit: int = 5) -> List[str]: cleaned: List[str] = [] seen = set() for item in items: if not item: continue normalized = " ".join(item.split()) if len(normalized) < 5: continue key = normalized.lower() if key in seen: continue seen.add(key) cleaned.append(normalized) if len(cleaned) >= limit: break return cleaned def _clean_remedies(remedies: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) ingredients = rem.get("ingredients") or [] ingredients = [ing.strip() for ing in ingredients if isinstance(ing, str) and ing.strip()] cleaned.append( { "name": name, "ingredients": ingredients[:5], "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip(), } ) if len(cleaned) >= limit: break return cleaned result["care_tips"] = _clean_text_items(result["care_tips"], limit=5) result["home_remedies"] = _clean_remedies(result["home_remedies"], limit=3) return result def parse_remedies_only(self, response: Optional[str]) -> List[Dict[str, Any]]: """Parse home remedies only""" remedies: List[Dict[str, Any]] = [] if not response: return remedies lines = response.split("\n") current_remedy: Dict[str, Any] = {} current_remedy_section: Optional[str] = None for line in lines: line = line.strip() if not line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break current_remedy = {} current_remedy_section = None continue lower = line.lower() if lower.startswith("remedy") and ":" in line: if current_remedy.get("name") and current_remedy.get("instructions"): remedies.append(current_remedy) if len(remedies) >= 3: break name = line.split(":", 1)[1].strip() current_remedy = {"name": name, "ingredients": []} current_remedy_section = None elif lower.startswith("ingredients"): current_remedy_section = "ingredients" current_remedy.setdefault("ingredients", []) elif lower.startswith("instructions"): current_remedy_section = "instructions" current_remedy["instructions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("frequency"): current_remedy_section = "frequency" current_remedy["frequency"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("benefits"): current_remedy_section = "benefits" current_remedy["benefits"] = line.split(":", 1)[1].strip() if ":" in line else "" elif lower.startswith("precautions"): current_remedy_section = "precautions" current_remedy["precautions"] = line.split(":", 1)[1].strip() if ":" in line else "" elif line.startswith(("-", "•", "*")) and current_remedy_section: text = line.lstrip("-•* ").strip() if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(text) else: existing = current_remedy.get(current_remedy_section, "") current_remedy[current_remedy_section] = (existing + " " + text).strip() elif current_remedy_section and current_remedy: current_value = current_remedy.get(current_remedy_section, "") if current_remedy_section == "ingredients": current_remedy.setdefault("ingredients", []).append(line) else: current_remedy[current_remedy_section] = (current_value + " " + line).strip() if current_remedy.get("name") and current_remedy.get("instructions") and len(remedies) < 3: remedies.append(current_remedy) def _clean_remedies(remedies_list: List[Dict[str, Any]], limit: int = 3) -> List[Dict[str, Any]]: cleaned: List[Dict[str, Any]] = [] seen = set() for rem in remedies_list: if not isinstance(rem, dict): continue name = rem.get("name", "").strip() instructions = rem.get("instructions", "").strip() if len(name) < 3 or len(instructions) < 8: continue key = name.lower() if key in seen: continue seen.add(key) cleaned.append({ "name": name, "ingredients": rem.get("ingredients", []), "instructions": instructions, "frequency": rem.get("frequency", "").strip(), "benefits": rem.get("benefits", "").strip(), "precautions": rem.get("precautions", "").strip() }) if len(cleaned) >= limit: break return cleaned return _clean_remedies(remedies, limit=3) i want this prompt will look like the image i have shared it will worked like that generate the images