File size: 9,022 Bytes
73d2dd0
 
 
44bc7e4
73d2dd0
 
e88e821
bb78e25
4b4e74e
 
 
 
57b710d
 
 
 
 
 
 
 
 
 
73d2dd0
497e545
d678ec4
497e545
57b710d
d678ec4
497e545
57b710d
497e545
2b7543b
497e545
e72c121
4bf3314
011a997
ad3f02e
e10d86a
e72c121
e58d934
497e545
 
 
434948d
e72c121
 
e58d934
bf9dd3c
c591b30
7677b68
434948d
ea69799
434948d
497e545
c591b30
497e545
c5cf242
c591b30
 
497e545
 
 
 
 
c591b30
 
 
497e545
 
c591b30
497e545
c591b30
ad3f02e
950bde0
 
 
 
 
 
 
 
 
 
c591b30
 
 
 
bb78e25
 
 
 
0aac908
bb78e25
 
2d63b2a
b4d74c5
497e545
 
d678ec4
497e545
4b4e74e
73d2dd0
02b212b
6f70394
97f3ce3
02b212b
 
f620b50
 
97750f2
011a997
65cc2e2
f620b50
 
40a1eec
7bff1d2
 
 
 
f620b50
 
157adeb
 
 
 
86206de
 
c591b30
a021d94
f1c382f
 
a021d94
427764a
bb78e25
ebc2272
d678ec4
 
0dfb96b
 
d678ec4
ebc5eac
0dfb96b
cd5381e
73d2dd0
d678ec4
 
ebc2272
d678ec4
97b94e9
 
 
 
 
 
 
d678ec4
 
f14787d
ebc2272
427764a
76863f7
04e6d96
73d2dd0
4b4e74e
73d2dd0
4b4e74e
97b94e9
57b710d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import os
import gradio as gr
import json
import re
from datetime import datetime
import openai
import random
from html2image import Html2Image

user_db = { 
           os.environ["username"]: os.environ["password"],
          }

music_files = [
    "RPReplay_Final1712757356.mp3",
    "RPReplay_Final1712801927.mp3",
    "RPReplay_Final1712802362.mp3",
    "RPReplay_Final1712802406.mp3",
    "RPReplay_Final1712757356.mp3",
    "RPReplay_Final1712802448.mp3",
    "RPReplay_Final1712802599.mp3"
]

# Function to play background music
def play_music():
    """Returns the path to the music file and makes the audio player visible."""
    music_path = random.choice(music_files)
    return music_path, gr.update(visible=True)


# Main function to generate a cocktail recipe based on user preferences
def generate_cocktail(mood, sweetness, sour, savory, bitter, flavor_association, drinking_experience, soberness_level, allergies, additional_requests):
    """Generates a cocktail recipe using OpenAI's GPT-4 based on user input."""
    client = openai.OpenAI(api_key=os.environ["API_TOKEN"])
    instruction = "Please provide a cocktail recipe given the mood and preference of the user.\n\n"
    user_prompt = f"Mood: {mood}\nTaste: Sweetness {sweetness}/10, Sour {sour}/10, Savory {savory}/10, Bitter {bitter}/10\nFlavor: {flavor_association}\nDrinking Experience: {drinking_experience}\nLevel of Soberness: {soberness_level}\nAllergies: {allergies}\nAdditional Requests: {additional_requests}\n\nMake sure to avoid all allergic ingredients.\n\n"
    output_format = "Please strictly follow this output format:\n\nCocktail Name:[name]\nQuote:[one sentence quote related to the cocktail and the mood description]\nIngredients:[ingredient 1]\n[ingredient 2]\n...\nInstruction:1. [step 1]\n2. [step 2]\n...\nNotes:[notes]"
    prompt = instruction + user_prompt + output_format

    messages=[
        {"role": "system", "content": "You are a helpful bartender assistant."},
        {"role": "user", "content": prompt}
    ]
    try:
        response = client.chat.completions.create(
            model="gpt-4-0125-preview", 
            messages=messages,
            max_tokens=1024)
        name, quote, ingredients, instruction, notes = extract_info(response.choices[0].message.content)
        return format_cocktail_output(name, quote, ingredients, instruction, notes), True, True
    except Exception as e:
        return f'<p style="color: white; font-size: 20px;">{str(e)}</p>'

# Extract information from the response generated by OpenAI
def extract_info(output_text):
    """Extracts the cocktail recipe information from the response text."""
    pattern = r"Cocktail Name:(.*?)Quote:(.*?)Ingredients:(.*?)Instruction:(.*?)Notes:(.*?)$"
    match = re.search(pattern, output_text, re.DOTALL)
    if match:
        name = match.group(1).strip()
        quote = match.group(2).strip()
        ingredients = match.group(3).strip().replace('\n', '<br>')
        instruction = match.group(4).strip().replace('\n', '<br>')
        notes = match.group(5).strip()
        return name, quote, ingredients, instruction, notes
    else:
        return None

# Format the cocktail recipe for display
def format_cocktail_output(name, quote, ingredients, instruction, notes):
    """Formats the cocktail recipe into HTML for display."""
    html_output = f'''
    <div style="text-align: center; font-family: 'Verdana', sans-serif; color: white;">
        <h1 style="font-size: 48px; color: white;">{name}</h1>
        <p style="font-size: 36px; margin-top: -15px; font-style: italic; color: white;">{quote}</p>
        <p style="font-size: 20px; color: white;">
            <strong style="color: white;">Ingredients:</strong><br>
            {ingredients}<br>
            <strong style="color: white;">Instruction:</strong><br>
            {instruction}<br>
            <strong style="color: white;">Notes:</strong><br>
            {notes}<br>
        </p>
    </div>
    '''
    return html_output

def save_as_png(html_content):
    """Converts HTML content to PDF, encodes it in base64, and returns a download link."""
    hti = Html2Image()
    css = 'body {background: url("https://images.unsplash.com/photo-1514361726087-38371321b5cd?q=80&w=2370&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D");}'

    # screenshot an HTML string (css is optional)
    hti.screenshot(html_str=html_content, css_str=css, save_as="CocktailRecipe.png")

        
with open('style.css', 'r') as file:
    css_styles = file.read()

# Creating the Gradio interface
with gr.Blocks(css=css_styles) as MoodShaker:
    with gr.Row():
        gr.HTML('''
        <div style="text-align: center; margin: 0;">
            <img src="https://huggingface.co/spaces/WhartonHackAIthon/MoodShaker/resolve/main/MoodShaker_Slogan.png" alt="MoodShaker Cocktail Generator" class="centered-image">
        </div>
        ''')
        
    with gr.Row():
        mood = gr.Textbox(label="How are you feeling today?", elem_classes=["custom-input"])
        flavor_association = gr.CheckboxGroup(label="Flavor", choices=["Fruity", "Herbal", "Spicy", "Floral", "Nutty", "Woody", "Earthy"], elem_classes=["custom-checkbox-group1"])
        drinking_experience = gr.CheckboxGroup(label="Drinking Experience", choices=["Refreshing", "Warming", "Comforting", "Energizing", "Relaxing"], elem_classes=["custom-checkbox-group2"])
        
    with gr.Row():
        sweetness = gr.Slider(label="Sweetness", minimum=0, maximum=10, elem_id="slider-sweetness",elem_classes=["slider-sweetness"])
        sour = gr.Slider(label="Sour", minimum=0, maximum=10, elem_id="slider-sour", elem_classes=["slider-sour"])
        savory = gr.Slider(label="Savory", minimum=0, maximum=10, elem_id="slider-savory", elem_classes=["slider-savory"])
        bitter = gr.Slider(label="Bitter", minimum=0, maximum=10, elem_id="slider-bitter", elem_classes=["slider-bitter"])
        soberness_level = gr.Slider(label="Level of Soberness", minimum=0, maximum=10, value=10, elem_id="slider-soberness_level", elem_classes=["slider-soberness_level"])

    with gr.Row():
        allergies = gr.Textbox(label="Allergies", scale=6, elem_classes=["custom-input1"])
        additional_requests = gr.Textbox(label="Anything else you would like to address", scale=6, elem_classes=["custom-input2"])
        generate_button = gr.Button("Generate Your Cocktail Recipe", scale=3, elem_classes=["generate-button"])
        clear_button = gr.Button("Clear", scale=1)

    with gr.Row():
        output_recipe = gr.HTML(label="Your Cocktail Recipe")
        
    play_button = gr.Button("Play Music", visible=False, elem_classes=["generate-button"], scale=1)  # Initially not visible
    background_music = gr.Audio(label="Background Music", autoplay=True, visible=False, scale=4)  # Initially not visible
    pdf_download_link = gr.HTML(visible=False)  # For displaying the PDF download link

    with gr.Row():
        save_png_button = gr.Button("Download Recipe as PNG", visible=False)

    def on_generate_click(*args):
        recipe, show_play_button, show_save_button = generate_cocktail(*args)
        return recipe, gr.update(visible=show_play_button), gr.update(visible=show_save_button)

    def reset():
        return "", 0, 0, 0, 0, [], [], 10, "", "", "", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
        
    generate_button.click(
        fn=on_generate_click,
        inputs=[mood, sweetness, sour, savory, bitter, flavor_association, drinking_experience, soberness_level, allergies, additional_requests],
        outputs=[output_recipe, play_button, save_png_button]
    )

    with gr.Row():
        gr.Examples(examples=[["Celebratory", 7, 3, 1, 2, ["Fruity", "Floral"], ["Energizing"], 5, "Nuts", "No ice"],
                              ["Relaxed", 4, 6, 0, 5, ["Herbal", "Woody"], ["Comforting"], 2, "", "Extra mint"],
                              ["Adventurous", 5, 5, 5, 0, ["Spicy", "Earthy"], ["Refreshing"], 8, "Shellfish", "Make it a double"]], 
                    inputs=[mood, sweetness, sour, savory, bitter, flavor_association, drinking_experience, soberness_level, allergies, additional_requests], 
                    outputs=[output_recipe, play_button], fn=on_generate_click)
    
    play_button.click(fn=play_music, inputs=[], outputs=[background_music, background_music])

    save_png_button.click(fn=save_as_png, inputs=[output_recipe], outputs=[pdf_download_link])
    
    clear_button.click(fn=reset, inputs=[], outputs=[mood, sweetness, sour, savory, bitter, flavor_association, drinking_experience, soberness_level, allergies, additional_requests, output_recipe, play_button, background_music, save_png_button])
        
if __name__ == "__main__":
    MoodShaker.launch(#enable_queue=False,
        # Creates an auth screen 
        auth=lambda u, p: user_db.get(u) == p,
        auth_message="Welcome to MoodShaker! \nEnter a Username and Password"
               ).queue()