File size: 6,690 Bytes
59284e7
cbf7d58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59284e7
cbf7d58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0280a69
cbf7d58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0280a69
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
170
171
172
173
174
175
176
177
178
import os
import gradio as gr
from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, InferenceClientModel, Tool, tool, VisitWebpageTool


# โ”€โ”€ Tools โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

@tool
def suggest_menu(occasion: str) -> str:
    """
    Suggests a menu based on the occasion.
    Args:
        occasion: The type of occasion for the party (casual, formal, superhero).
    """
    menus = {
        "casual": "Pizza, sliders, nachos, and a selection of craft beers & soft drinks.",
        "formal": "3-course dinner: shrimp cocktail starter, filet mignon entrรฉe, crรจme brรปlรฉe dessert with wine pairing.",
        "superhero": "High-energy buffet: protein bowls, power smoothies, and hero-themed cupcakes.",
        "villain masquerade": "Dark elegance spread: black caviar, smoked meats, red-velvet cake, and 'Poison Ivy' mocktails.",
    }
    return menus.get(occasion.lower(), "Custom gourmet menu crafted by the Wayne Manor chef.")


@tool
def catering_service_tool(query: str) -> str:
    """
    Returns the highest-rated catering service in Gotham City.
    Args:
        query: A search term for finding catering services.
    """
    services = {
        "Gotham Catering Co.": 4.9,
        "Wayne Manor Catering": 4.8,
        "Gotham City Events": 4.7,
    }
    best_service = max(services, key=services.get)
    return f"{best_service} (rated {services[best_service]}/5)"


@tool
def party_checklist_tool(theme: str) -> str:
    """
    Generates a party planning checklist for a given theme.
    Args:
        theme: The party theme (e.g., villain masquerade, superhero gala).
    """
    base = [
        "โœ… Book the venue (Wayne Manor Grand Hall)",
        "โœ… Send invitations 2 weeks in advance",
        "โœ… Arrange catering & bar service",
        "โœ… Set up a photo booth with themed props",
        "โœ… Hire a DJ or live band",
        "โœ… Arrange valet parking",
    ]
    theme_extras = {
        "villain masquerade": [
            "๐ŸŽญ Provide masquerade masks at the entrance",
            "๐Ÿ•ฏ๏ธ Use dramatic candlelit dรฉcor",
            "๐ŸŒน Add rose & smoke machine effects",
        ],
        "classic heroes": [
            "๐Ÿฆธ Set up a cape & costume station",
            "๐Ÿ† Run a 'Best Costume' contest",
            "๐ŸŽจ Commission hero-themed artwork",
        ],
        "futuristic gotham": [
            "๐Ÿ”ต Install neon LED lighting throughout",
            "๐Ÿค– Feature tech/gadget displays",
            "๐ŸŽฎ Set up a VR experience zone",
        ],
    }
    extras = theme_extras.get(theme.lower(), ["๐ŸŽ‰ Custom dรฉcor to match your unique theme"])
    return "\n".join(base + extras)


class SuperheroPartyThemeTool(Tool):
    name = "superhero_party_theme_generator"
    description = (
        "Suggests creative superhero-themed party ideas based on a category. "
        "Returns a unique party theme concept with dรฉcor and activity ideas."
    )
    inputs = {
        "category": {
            "type": "string",
            "description": "Type of superhero party: 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.",
        }
    }
    output_type = "string"

    def forward(self, category: str) -> str:
        themes = {
            "classic heroes": (
                "โšก Justice League Gala โ€” Guests dress as DC heroes. "
                "Themed cocktails like 'The Kryptonite Punch'. Giant hero murals as photo backdrops."
            ),
            "villain masquerade": (
                "๐ŸŽญ Gotham Rogues' Ball โ€” Mysterious masquerade where guests dress as Batman villains. "
                "Dark floral dรฉcor, candlelight, and a 'Who's Behind the Mask?' contest."
            ),
            "futuristic gotham": (
                "๐ŸŒ† Neo-Gotham Night โ€” Cyberpunk party inspired by Batman Beyond. "
                "Neon decorations, holographic displays, and futuristic gadget showcases."
            ),
        }
        return themes.get(
            category.lower(),
            "Theme not found. Try 'classic heroes', 'villain masquerade', or 'futuristic Gotham'.",
        )


# โ”€โ”€ Agent setup โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

def build_agent() -> CodeAgent:
    return CodeAgent(
        tools=[
            DuckDuckGoSearchTool(),
            VisitWebpageTool(),
            suggest_menu,
            catering_service_tool,
            party_checklist_tool,
            SuperheroPartyThemeTool(),
            FinalAnswerTool(),
        ],
        model=InferenceClientModel(token=os.environ.get("HF_TOKEN")),
        max_steps=10,
        verbosity_level=1,
    )


# โ”€โ”€ Gradio UI โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

SYSTEM_NOTE = (
    "๐Ÿฆ‡ **Alfred at your service.** I am the Wayne Manor party planning assistant. "
    "Ask me about themes, menus, playlists, catering, or full party plans!"
)

EXAMPLE_QUERIES = [
    "Plan a villain masquerade party at Wayne Manor",
    "Suggest a menu for a superhero gala",
    "Give me a party checklist for a futuristic Gotham theme",
    "Find the best catering service in Gotham City",
    "What playlist fits a classic heroes party?",
]


def respond(message: str, history: list) -> str:
    agent = build_agent()
    try:
        answer = agent.run(message)
        return str(answer)
    except Exception as e:
        return f"Alfred encountered an issue: {e}"


with gr.Blocks(title="Wayne Manor Party Planner") as demo:
    gr.HTML(
        """
        <div style="text-align:center; padding: 1rem 0 0.5rem;">
            <h1 style="font-size:2rem;">๐Ÿฆ‡ Wayne Manor Party Planner</h1>
            <p style="color:#888;">Powered by <strong>Alfred</strong> &mdash; your AI butler &amp; event coordinator</p>
        </div>
        """
    )

    gr.ChatInterface(
        fn=respond,
        chatbot=gr.Chatbot(height=480, placeholder=SYSTEM_NOTE),
        textbox=gr.Textbox(
            placeholder="Ask Alfred to plan your party...",
            container=False,
            scale=7,
        ),
        examples=EXAMPLE_QUERIES,
        cache_examples=False,
    )

if __name__ == "__main__":
    demo.launch(theme=gr.themes.Base(primary_hue="slate", neutral_hue="zinc"))