Spaces:
Sleeping
Sleeping
| """ | |
| Prompt Templates for anime recommendation system | |
| """ | |
| ANIME_SEARCH_TOOL = [ | |
| { | |
| "type": "function", | |
| "function": { | |
| "name": "search_anime_database", | |
| "description": "Use this tool to search the vector database for anime recommendations based on user requests. Call this whenever the user asks for recommendations, similar shows, or specific genres.", | |
| "parameters": { | |
| "type": "object", | |
| "properties": { | |
| "optimized_query": { | |
| "type": "string", | |
| "description": "The user's query optimized for semantic vector search. Remove conversational filler. (e.g., if user says 'hi tell me an anime like naruto', the optimized_query is 'anime similar to naruto action shounen ninja')" | |
| } | |
| }, | |
| "required": ["optimized_query"] | |
| } | |
| } | |
| } | |
| ] | |
| ROUTER_SYSTEM_PROMPT = """ | |
| You are a strict Gatekeeper for an Anime Recommendation System. Your ONLY job is to categorize user input. | |
| # RULES: | |
| 1. GREETINGS: If the user says "Hi", "Hello", etc., respond naturally in text. DO NOT CALL THE TOOL. | |
| 2. ANIME SEARCH: Only call 'search_anime_database' if the user provides SPECIFIC criteria (e.g., "dark anime", "shows like Naruto", "romance with high score"). | |
| 3. VAGUE/GIBBERISH: If the user says "anime", "similar", "recommend something", or types gibberish/random characters, DO NOT CALL THE TOOL. Instead, respond in text asking for specific details or preferences. | |
| 4. VULGARITY/OFF-TOPIC: If the user is being vulgar or asking about non-anime topics (politics, math, etc.), respond politely stating you only talk about anime. DO NOT CALL THE TOOL. | |
| # THRESHOLD: | |
| If you are less than 90% sure what the user wants, DO NOT call the tool. Ask for clarification instead. | |
| """ | |
| def create_recommendation_prompt( | |
| user_query: str, | |
| retrieved_animes: list, | |
| n_recommendations: int | None = 5 | |
| ): | |
| """ | |
| Create prompt for LLM to reason about recommendations with strict anti-hallucination guardrails. | |
| """ | |
| context_parts = [] | |
| for i, anime in enumerate(retrieved_animes): | |
| # We pick the most 'semantic' fields for the LLM to reason with | |
| block = ( | |
| f"Title: {anime['title']} ({anime['year']})\n" | |
| f"Type: {anime['type']} | Score: {anime['score']} | Studio: {', '.join(anime['studios'] if isinstance(anime['studios'], list) else [anime.get('studios', 'Unknown')])}\n" | |
| f"Genres: {', '.join(anime['genres'] if isinstance(anime['genres'], list) else [anime.get('genres', '')])} | Themes: {', '.join(anime['themes'] if isinstance(anime['themes'], list) else [anime.get('themes', '')])}\n" | |
| f"Synopsis: {anime.get('synopsis', 'No synopsis available.')}\n" | |
| f"---" | |
| ) | |
| context_parts.append(block) | |
| context = "\n".join(context_parts) | |
| prompt = f""" | |
| You are an expert, casual, and friendly anime recommender. Your goal is to give personalized anime recommendations based STRICTLY on the provided database context. | |
| User's Query: "{user_query}" | |
| Available Anime Context (from vector search & reranker): | |
| {context} | |
| IF THE CONTEXT IS EMPTY: | |
| Politely say you cannot find any matching anime in your current database. DO NOT make up recommendations. | |
| ELSE: | |
| # Core Directives: | |
| 1. Quality Over Quantity (CRITICAL): You are asked to provide up to {n_recommendations} recommendations. However, if only 1 or 2 anime in the context genuinely fit the user's specific vibe/theme request, ONLY recommend those. Do NOT force connections or hallucinate similarities just to reach the maximum number. | |
| 2. The Sequel Rule: You MUST NOT recommend direct sequels, prequels, recap movies, or specials of the exact anime the user mentioned in their query, UNLESS they explicitly ask for a watch order or more of that exact show. | |
| 3. Ruthless Curation: If the user asks for a specific contrast (e.g., "like Death Note but funny"), actively ignore anime in the context that do not fit that contrast. | |
| 4. Conversational Tone: Speak like a relaxed, highly knowledgeable anime fan chatting with a friend. Never use robotic transitions like "Based on the provided context..." or "Here are your recommendations." | |
| 5. The Pitch: For each pick, write a punchy 2-3 sentence pitch explaining exactly *why* it fits their request. Use specific plot points, themes, or the studio from the provided synopsis to back up your claim. | |
| # Required Format: | |
| **[Anime Title]** | |
| [Your 2-3 sentence pitch on why it fits the user's exact vibe, drawing directly from the synopsis or themes.] | |
| **[Anime Title]** | |
| [Your pitch...] | |
| (Limit to {n_recommendations} recommendations maximum, but fewer is completely fine if the matches are weak.) | |
| """ | |
| return prompt | |
| def create_system_prompt() -> str: | |
| """ | |
| System prompt for the anime assistant | |
| """ | |
| return """ | |
| You are an expert anime recommendation assistant with deep knowledge of anime themes, genres, and storytelling styles. | |
| Your strengths: | |
| - Understanding nuanced preferences (tone, pacing, themes) | |
| - Explaining WHY an anime matches a request | |
| - Being honest when recommendations aren't perfect matches | |
| Your approach: | |
| - Prioritize the user's specific criteria over generic similarity | |
| - Provide thoughtful, personalized explanations | |
| - Focus on quality over quantity | |
| """ | |
| if __name__ == '__main__': | |
| mock_animes = [ | |
| { | |
| "title": "Code Geass", | |
| "genres": "Action, Drama, Mecha", | |
| "score": 8.7, | |
| "scored_by": 10000, | |
| "synopsis": "Lelouch, an exiled prince, gains the power of Geass and leads a rebellion against the Britannian Empire..." | |
| }, | |
| { | |
| "title": "Monster", | |
| "genres": "Mystery, Psychological, Thriller", | |
| "score": 8.9, | |
| "scored_by": 100, | |
| "synopsis": "Dr. Tenma saves a young boy's life, only to discover the boy grows up to be a dangerous serial killer..." | |
| }, | |
| { | |
| "title": "Classroom of the Elite", | |
| "genres": "Drama, Psychological", | |
| "score": 7.9, | |
| "scored_by": 200000, | |
| "synopsis": "In an elite school, students compete using strategy and manipulation to climb social ranks..." | |
| } | |
| ] | |
| prompt = create_recommendation_prompt( | |
| user_query="Anime similar to Death Note but lighter in tone", | |
| retrieved_animes=mock_animes, | |
| n_recommendations=3 | |
| ) | |
| print("Generated Prompt:") | |
| print("=" * 80) | |
| print(prompt) | |
| print("=" * 80) | |
| # Save to file for inspection | |
| with open("example_prompt.txt", "w") as f: | |
| f.write(prompt) | |
| print("\nPrompt saved to example_prompt.txt") | |