Spaces:
Sleeping
Sleeping
| import os | |
| import gradio as gr | |
| import random | |
| import base64 | |
| from openai import OpenAI | |
| client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) | |
| def response(user_message, history): | |
| messages = [{"role": "system", "content": """System Prompt – FIVESTAR (freundlich, gemütlich, interaktiv)** | |
| Du bist FIVESTAR, ein freundlicher und gemütlicher Film-Empfehlungs-Chatbot. Deine Aufgabe ist es, Nutzer:innen dabei zu helfen, passende Filme zu finden. Du verwendest dafür die bereitgestellte Datenbasis (Ausschnitt der IMDb-Datenbank: alle Filme ab dem Jahr 2000 mit einer Bewertung über 7). Am Ende deiner Empfehlungen gibst du genau fünf passende Filme aus – das sind die „Five Stars". | |
| Tonfall & Stil: | |
| Sei warm, einladend, positiv und persönlich. | |
| Reagiere immer empathisch und wertschätzend auf Aussagen des Nutzers. | |
| Keine knappen Stichpunkt-Antworten – kurze, freundliche ganze Sätze. | |
| Stelle höchstens eine einzige Rückfrage pro Nachricht. | |
| Verwende eine entspannte Umgangssprache, nicht übertrieben formell. | |
| Interaktion & Informationsverarbeitung: | |
| Frage zu Beginn: „Hey, Wilkommen bei FIVESTAR! Nach was für einem Genre steht dir heute der Sinn?" | |
| Nachdem der User das erste mal geantwortet hat, Stelle danach deine erste Frage zu weiteren Themen, wie Schauspieler, Erscheinungsjahr, ähnlichen Filmen, Stimmung, Regisseuren etc.. Frage aber wie immer pro Frage immer nur was zu einem Thema. | |
| schreibe zusätzlich unter deine Frage mit einem leeren Absatz Platz folgendes aus: | |
| "Übrigens: Für eine Schnellausgabe nenne mir ein paar Stichpunkte und ich gebe dir sofort deine Fivestars aus. " Gebe diese Nachricht aber nur ein einziges mal im ganzen chat aus. bei deinen nächsten nachrichten nicht mehr! das ist wichtig! | |
| Antwortet der User normal auf deine Rückfrage mit nur einem Wort, stelle weitere Rückfragen zu den genannten themen. Antwortet der User mit mehreren Stichpunkten, gebe ihm direkt seine passenden fünf Filme auf Basis der Stichpunkte aus. | |
| Lasse das den Satz: "Übrigens: Für eine Schnellausgabe nenne mir ein paar Stichpunkte und ich gebe dir sofort deine Fivestars aus. " ab dann komplett weg bei den Nachrichten. Es reicht, dass du das einmal ageboten hast. | |
| Der Nutzer kann nach Genre, Schauspielern, Stimmung, Vergleichsfilm, Zeitraum oder anderen Kriterien fragen. | |
| Je mehr Informationen vom Nutzer kommen, desto präziser die späteren Filmempfehlungen. | |
| Wenn der Nutzer unsicher ist oder mehr Gesprächsbedarf hat, stelle eine vorsichtige, offene Frage, z. B.: | |
| „Nach welcher Stimmung steht dir heute der Sinn?" | |
| „Hast du Lieblingsschauspieler:innen?" | |
| „Lieber etwas Neues oder einen Klassiker nach 2000?" | |
| stelle immer nur eine Frage auf einmal und erst die nächste wieder nach der nächsten eingabe des Nutzers. Wenn du merkst der nutzer hat zwei fragen beantwortet, frage ihn ob du ihm jetzt schon eine auswahl ausgeben sollst auf basis von dem was du weisst oder du noch weitere rückfragen stellen sollst. | |
| Filmempfehlungen: | |
| Am Ende zeigst du genau fünf Filme als Ergebnis. | |
| Für jeden Film gib folgende Informationen aus: | |
| Titel und Erscheinungsjahr | |
| Genre | |
| Bewertung auf IMDB (Rating + Anzahl Votes) | |
| Hauptschauspieler*innen | |
| Kurzbeschreibung / Plot | |
| Ich wünsche viel Spaß beim Schauen! | |
| Füge keine weiteren Erklärungen nach dieser Liste hinzu. | |
| Keine Spoiler, keine Handlungserklärung – höchstens 1 kurzer, maximal zweisätziger Kommentar pro Titel, falls hilfreich. | |
| Regeln: | |
| Empfehle nur Filme aus der bereitgestellten Datenbasis. Gib nur Filme mit IMDB-Bewertung über 6.9 und dem Erscheinungsjahr ab 2000 aus. | |
| Erfinde keine Filme und gebe keine Serien aus. | |
| Verwende gesammelt alle Kriterien des Nutzers, falls vorhanden, aber fordere niemals zwingend Informationen ein. | |
| Keine technischen Details über die Datenbank offenlegen. | |
| Nutze Konversation aktiv, aber nicht aufdringlich. Falls der Nutzer Sachen sagt, die nichts mit Filmen zutun haben, lenke ihn klar aber feundlich zum Theme zurück und sage, dass du ein Assistent für die Filmfindung bist. | |
| Antworte ohne Emojis. | |
| """}] | |
| for msg in history: | |
| if msg["role"] == "user": | |
| messages.append({"role": "user", "content": msg["content"]}) | |
| else: | |
| messages.append({"role": "assistant", "content": msg["content"]}) | |
| messages.append({"role": "user", "content": user_message}) | |
| response = client.chat.completions.create( | |
| model="gpt-4o-mini", | |
| messages=messages, | |
| temperature=0.7, | |
| max_tokens=2000 | |
| ) | |
| return response.choices[0].message.content | |
| def get_base64_image(image_path): | |
| """Konvertiert ein Bild zu Base64 für CSS background-image""" | |
| try: | |
| with open(image_path, "rb") as image_file: | |
| encoded = base64.b64encode(image_file.read()).decode() | |
| return f"data:image/png;base64,{encoded}" | |
| except: | |
| return None | |
| def main(): | |
| # Wähle ein zufälliges Hintergrundbild beim Start | |
| background_images = [ | |
| "./background_images/nosferatu.png", | |
| #"./background_images/aftersun.png", | |
| "./background_images/anora.png", | |
| "./background_images/arrival.png", | |
| "./background_images/harry_potter.png", | |
| #"./background_images/batman.png", | |
| #"./background_images/blackswan.png", | |
| "./background_images/bladerunner.png", | |
| #"./background_images/bonesandall.png", | |
| #"./background_images/city-of-god.jpg", | |
| #"./background_images/drive.png", | |
| "./background_images/dune.png", | |
| #"./background_images/fightclub.png", | |
| "./background_images/handmaiden.png", | |
| "./background_images/her.png", | |
| "./background_images/lalaland.png", | |
| #"./background_images/lighthouse.png", | |
| "./background_images/littlewomen.png", | |
| #"./background_images/memento.png", | |
| "./background_images/pastlives.png", | |
| #"./background_images/spiderman.png", | |
| ] | |
| selected_bg = random.choice(background_images) | |
| # Konvertiere Bild zu Base64 | |
| bg_base64 = get_base64_image(selected_bg) | |
| # Custom CSS | |
| if bg_base64: | |
| background_style = f"background: url('{bg_base64}') center/cover no-repeat !important;" | |
| else: | |
| background_style = "background: #4a0000 !important;" | |
| custom_css = f""" | |
| /* Globale Schriftart */ | |
| * {{ | |
| font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", Helvetica, Arial, sans-serif !important; | |
| }} | |
| /* Haupt-Container mit Hintergrundbild */ | |
| .gradio-container {{ | |
| {background_style} | |
| min-height: 100vh; | |
| }} | |
| /* Zentriertes Chat-Fenster */ | |
| #chat-container {{ | |
| max-width: 800px; | |
| margin: 0 auto; | |
| padding: 40px 20px; | |
| }} | |
| /* Logo Container */ | |
| #logo-container {{ | |
| text-align: center; | |
| margin-bottom: 30px; | |
| }} | |
| #logo-container .download-button-container {{ | |
| display: none !important; | |
| }} | |
| #logo-container button[aria-label] {{ | |
| display: none !important; | |
| }} | |
| /* Chatbot Header Buttons verstecken (Mülleimer und HF Logo) */ | |
| #chatbot .header-buttons {{ | |
| display: none !important; | |
| }} | |
| #chatbot button[aria-label*="Clear"] {{ | |
| display: none !important; | |
| }} | |
| #chatbot button[aria-label*="Like"] {{ | |
| display: none !important; | |
| }} | |
| #chatbot button[aria-label*="Dislike"] {{ | |
| display: none !important; | |
| }} | |
| #chatbot .chatbot-header {{ | |
| display: none !important; | |
| }} | |
| /* Alle Buttons im Chatbot-Header ausblenden */ | |
| .chatbot-header button {{ | |
| display: none !important; | |
| }} | |
| /* Zusätzliche Selektoren für Gradio Buttons - aber Submit und Clear ausschließen */ | |
| #chatbot-box button:not(.clear-btn):not(.submit-btn) {{ | |
| display: none !important; | |
| }} | |
| #chatbot button:not(.submit-btn) {{ | |
| display: none !important; | |
| }} | |
| /* Clear Button Styling */ | |
| .clear-btn {{ | |
| background: transparent !important; | |
| border: none !important; | |
| color: #8E8E93 !important; | |
| font-size: 18px !important; | |
| font-weight: 400 !important; | |
| padding: 0 !important; | |
| cursor: pointer !important; | |
| transition: color 0.2s ease !important; | |
| width: 32px !important; | |
| height: 32px !important; | |
| border-radius: 50% !important; | |
| display: flex !important; | |
| align-items: center !important; | |
| justify-content: center !important; | |
| visibility: visible !important; | |
| opacity: 1 !important; | |
| }} | |
| .clear-btn:hover {{ | |
| color: #3C3C43 !important; | |
| }} | |
| /* Chat-Box Styling */ | |
| #chatbot-box {{ | |
| background: rgba(255, 255, 255, 0.95); | |
| border-radius: 25px; | |
| padding: 30px; | |
| box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); | |
| backdrop-filter: blur(10px); | |
| position: relative; | |
| }} | |
| /* Clear Button positioniert in der rechten oberen Ecke der weißen Box */ | |
| #clear-row {{ | |
| position: absolute !important; | |
| top: 33px !important; | |
| right: 33px !important; | |
| z-index: 10 !important; | |
| margin: 0 !important; | |
| width: auto !important; | |
| }} | |
| /* Chatbot Nachrichten - Bubble Style */ | |
| .message-wrap {{ | |
| border-radius: 35px !important; | |
| padding: 14px 18px !important; | |
| }} | |
| /* USER MESSAGE – überschreibt Gradio Inline Styles */ | |
| #chatbot .message.user, | |
| #chatbot .message.user *, | |
| #chatbot .user, | |
| #chatbot .user * {{ | |
| background: #D1D1D6 !important; | |
| background-color: #D1D1D6 !important; | |
| border: none !important; | |
| color: #1C1C1E !important; | |
| }} | |
| #chatbot .message.user .message-wrap {{ | |
| background: #C0C0C8 !important; | |
| background-color: #C0C0C8 !important; | |
| border: none !important; | |
| color: #1C1C1E !important; | |
| box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08) !important; | |
| }} | |
| /* Text innerhalb der User Message */ | |
| #chatbot .message.user p, | |
| #chatbot .message.user span, | |
| #chatbot .message.user div {{ | |
| color: #1C1C1E !important; | |
| }} | |
| /* Entferne blauen Rahmen */ | |
| #chatbot .message.user .message-wrap[style] {{ | |
| background: #C0C0C8 !important; | |
| background-color: #C0C0C8 !important; | |
| border: none !important; | |
| outline: none !important; | |
| color: #1C1C1E !important; | |
| }} | |
| #chatbot .message.bot .message-wrap {{ | |
| background: rgba(142, 142, 147, 0.15) !important; | |
| border: 1px solid rgba(142, 142, 147, 0.25) !important; | |
| }} | |
| #chatbot .message.user .avatar-container img {{ | |
| display: none !important; | |
| }} | |
| #chatbot .message.bot .avatar-container img {{ | |
| display: none !important; | |
| }} | |
| /* Input-Feld - Bubble Style */ | |
| .input-wrap {{ | |
| border-radius: 35px !important; | |
| background: rgba(255, 255, 255, 0.9) !important; | |
| border: 1.5px solid rgba(142, 142, 147, 0.3) !important; | |
| backdrop-filter: blur(10px) !important; | |
| padding: 10px 20px !important; | |
| }} | |
| .input-wrap:focus-within {{ | |
| border-color: rgba(142, 142, 147, 0.5) !important; | |
| box-shadow: 0 0 0 3px rgba(142, 142, 147, 0.08) !important; | |
| }} | |
| /* Submit Button - Rechteckig mit gerundeten Ecken */ | |
| .submit-btn {{ | |
| min-width: 60px !important; | |
| max-width: 60px !important; | |
| width: 60px !important; | |
| height: 44px !important; | |
| border-radius: 30px !important; | |
| background: rgba(142, 142, 147, 0.15) !important; | |
| border: 1.5px solid rgba(142, 142, 147, 0.3) !important; | |
| backdrop-filter: blur(10px) !important; | |
| padding: 0 !important; | |
| display: flex !important; | |
| align-items: center !important; | |
| justify-content: center !important; | |
| font-size: 20px !important; | |
| color: #8E8E93 !important; | |
| transition: all 0.2s ease !important; | |
| visibility: visible !important; | |
| opacity: 1 !important; | |
| }} | |
| .submit-btn:active {{ | |
| transform: scale(0.95) !important; | |
| }} | |
| /* Input Row Styling */ | |
| #input-row {{ | |
| gap: 12px !important; | |
| }} | |
| /* Footer ausblenden */ | |
| footer {{ | |
| display: none !important; | |
| }} | |
| """ | |
| with gr.Blocks(css=custom_css, theme=gr.themes.Soft()) as demo: | |
| with gr.Column(elem_id="chat-container"): | |
| # Logo | |
| with gr.Row(elem_id="logo-container"): | |
| gr.Image( | |
| "./logo/five-star-logo-fin.png", | |
| show_label=False, | |
| show_download_button=False, | |
| container=False, | |
| height=150, | |
| width=150, | |
| interactive=False | |
| ) | |
| # Chat-Box | |
| with gr.Column(elem_id="chatbot-box"): | |
| # Clear Button in der rechten oberen Ecke | |
| with gr.Row(elem_id="clear-row"): | |
| clear = gr.Button( | |
| "↻", | |
| scale=0, | |
| elem_classes="clear-btn", | |
| size="sm" | |
| ) | |
| chatbot = gr.Chatbot( | |
| value=[{ | |
| "role": "assistant", | |
| "content": "Hey! Wilkommen bei FIVESTAR! Nach was für einem Genre steht dir heute der Sinn?" | |
| }], | |
| type="messages", | |
| show_label=False, | |
| avatar_images=( | |
| None, | |
| None, | |
| ), | |
| height=400, | |
| elem_id="chatbot", | |
| show_copy_button=False, | |
| show_share_button=False | |
| ) | |
| with gr.Row(elem_id="input-row"): | |
| msg = gr.Textbox( | |
| placeholder="...hier tippen", | |
| show_label=False, | |
| scale=11, | |
| container=False | |
| ) | |
| submit = gr.Button( | |
| "↑", | |
| scale=1, | |
| elem_classes="submit-btn" | |
| ) | |
| # Event Handlers | |
| def user_message(user_msg, history): | |
| return "", history + [{"role": "user", "content": user_msg}] | |
| def bot_response(history): | |
| user_msg = history[-1]["content"] | |
| bot_msg = response(user_msg, history) | |
| history.append({"role": "assistant", "content": bot_msg}) | |
| return history | |
| def clear_chat(): | |
| return [{ | |
| "role": "assistant", | |
| "content": "Hey! Willkommen bei Fivestars! Was kann ich für dich tun?" | |
| }] | |
| msg.submit(user_message, [msg, chatbot], [msg, chatbot]).then( | |
| bot_response, chatbot, chatbot | |
| ) | |
| submit.click(user_message, [msg, chatbot], [msg, chatbot]).then( | |
| bot_response, chatbot, chatbot | |
| ) | |
| clear.click(clear_chat, None, chatbot) | |
| demo.launch(inbrowser=True) | |
| if __name__ == "__main__": | |
| main() |