-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
165 lines (139 loc) Β· 6.87 KB
/
Copy pathapp.py
File metadata and controls
165 lines (139 loc) Β· 6.87 KB
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
import os
import gradio as gr
from crewai import Agent, Task, Crew, Process, LLM
# --- 1. Configuration ---
# Ensure WATSONX_APIKEY, WATSONX_PROJECT_ID, and WATSONX_URL are set
# os.environ["WATSONX_APIKEY"] = os.getenv("WATSONX_APIKEY", "")
# os.environ["WATSONX_PROJECT_ID"] = os.getenv("WATSONX_PROJECT_ID", "")
# os.environ["WATSONX_URL"] = os.getenv("WATSONX_URL", "")
project_id = os.environ.get('WATSONX_AI_PROJECT_ID')
api_key = os.environ.get("WATSONX_APIKEY")
watsonx_llm = LLM(
model="watsonx/ibm/granite-4-h-small",
base_url="https://us-south.ml.cloud.ibm.com",
project_id=project_id,
temperature=0.7)
# --- 2. Agent Definitions (Researcher, Host, Santa) ---
noel_researcher = Agent(
role='Christmas Folklore Historian',
goal='Discover obscure Christmas facts based on a category.',
backstory="You are an expert in global traditions.",
llm=watsonx_llm
)
holly_host = Agent(
role='Head Elf of Entertainment',
goal='Turn facts into a festive MCQ with a ||| separator.',
backstory="You are a high-energy game show host elf.",
llm=watsonx_llm
)
santa_judge = Agent(
role='Santa Claus',
goal='Validate answers and spread Christmas cheer.',
backstory="You are Santa. You check the Nice List.",
llm=watsonx_llm
)
# --- 3. Logic Functions ---
def generate_christmas_challenge(category):
task_research = Task(description=f"Find one specific Christmas fact about {category}.", expected_output="A summary.", agent=noel_researcher)
question_task_format = """Create MCQ. Format:
[Question]:
A)
B)
C)
D)
||| [Answer Letter]: [Fact]
"""
task_format = Task(description=question_task_format, expected_output="Question block separated by |||", agent=holly_host, context=[task_research])
crew = Crew(agents=[noel_researcher, holly_host], tasks=[task_research, task_format])
return str(crew.kickoff())
def ask_santa(user_input, secret_key):
task_judge = Task(description=f"User answered '{user_input}'. Truth is '{secret_key}'. Reply as Santa.", expected_output="Santa's response.", agent=santa_judge)
crew = Crew(agents=[santa_judge], tasks=[task_judge])
return str(crew.kickoff())
# --- 4. UI Format and Logic ---
def format_question_card(text):
"""Wraps the question in a festive Markdown card."""
return f"""
<div style="border: 2px solid #2e7d32; border-radius: 15px; padding: 20px; background-color: #f1f8e9; color: #1b5e20;">
<h2 style="margin-top: 0;">π Christmas Challenge</h2>
{text.replace('|||', '').strip()}
</div>
"""
def format_santa_card(text):
"""Wraps Santa's response in a parchment-style card."""
return f"""
<div style="border: 2px dashed #d32f2f; border-radius: 15px; padding: 20px; background-color: #fff5f5; color: #b71c1c;">
<h2 style="margin-top: 0;">π
Santa's Verdict</h2>
{text}
</div>
"""
def game_logic(user_message, category, history, state):
if state is None: state = {'status': 'IDLE', 'secret_key': ''}
if history is None: history = []
# If message is empty (from a button click), provide a default
input_text = user_message if user_message else "Let's play!"
if state['status'] == 'IDLE':
history.append({"role": "user", "content": input_text})
history.append({"role": "assistant", "content": f"β¨ *Consulting the North Pole library for {category}...*"})
yield history, state, gr.update(visible=False), gr.update(visible=False)
full_output = generate_christmas_challenge(category)
parts = full_output.split("|||")
public_q = parts[0].strip() if len(parts) > 1 else full_output
state['secret_key'] = parts[1].strip() if len(parts) > 1 else "Hidden"
state['status'] = 'WAITING_FOR_ANSWER'
history[-1] = {"role": "assistant", "content": format_question_card(public_q)}
# Hide start/next, show text box for answer
yield history, state, gr.update(visible=False), gr.update(visible=False)
elif state['status'] == 'WAITING_FOR_ANSWER':
history.append({"role": "user", "content": input_text})
history.append({"role": "assistant", "content": "Checking the Nice List... π"})
yield history, state, gr.update(visible=False), gr.update(visible=False)
verdict = ask_santa(input_text, state['secret_key'])
state['status'] = 'IDLE'
history[-1] = {"role": "assistant", "content": format_santa_card(verdict)}
# Show 'Next Challenge' button now that we are IDLE
yield history, state, gr.update(visible=False), gr.update(visible=True)
# --- 5. "Heavier & Grayer" Snowfall Script ---
snow_js = """
function createSnow() {
const s = document.createElement('style');
s.innerHTML = `.sn { color: #a0a0a0; position: fixed; top: -10%; z-index: 9999; animation: f 8s linear infinite; pointer-events: none; } @keyframes f { to { top: 100vh; } }`;
document.head.appendChild(s);
setInterval(() => {
const b = document.createElement('div');
b.className = 'sn'; b.innerHTML = 'β';
b.style.left = Math.random() * 100 + 'vw';
b.style.fontSize = (Math.random() * 15 + 15) + 'px'; // Larger flakes
b.style.opacity = Math.random() * 0.8 + 0.2; // More opaque
document.body.appendChild(b);
setTimeout(() => b.remove(), 8000);
}, 150); // Faster interval for "heavier" snow
}
setTimeout(createSnow, 1000);
"""
# --- 6. Interface Assembly ---
santa_css = """
.gradio-container {
background-image: url('https://www.transparenttextures.com/patterns/snow.png'),
linear-gradient(rgba(255,255,255,0.8), rgba(255,255,255,0.8)),
url('https://cf-courses-data.s3.us.cloud-object-storage.appdomain.cloud/HPVuGgmOV81JMulqTtrukQ/santa.png');
background-size: cover;
background-attachment: fixed;
}
"""
with gr.Blocks(head=f"<script>{snow_js}</script>", css=santa_css, theme=gr.themes.Soft()) as demo:
gr.HTML("<h1 style='text-align: center; color: #d32f2f;'>βοΈ The Christmas Workshop βοΈ</h1>")
with gr.Row():
category_drop = gr.Dropdown(label="Category", choices=["Traditions", "Food", "Clothing", "Myths", "Music"], value="Traditions")
start_btn = gr.Button("π Start Workshop", variant="primary")
next_btn = gr.Button("π Next Challenge", visible=False)
chatbot = gr.Chatbot(height=450)
msg = gr.Textbox(label="Your Answer", placeholder="Type A, B, C, or D...")
state = gr.State({'status': 'IDLE', 'secret_key': ''})
# Logic Triggers
start_btn.click(game_logic, [gr.State("Start"), category_drop, chatbot, state], [chatbot, state, start_btn, next_btn])
next_btn.click(game_logic, [gr.State("Next"), category_drop, chatbot, state], [chatbot, state, start_btn, next_btn])
msg.submit(game_logic, [msg, category_drop, chatbot, state], [chatbot, state, start_btn, next_btn])
msg.submit(lambda: "", None, msg)
if __name__ == "__main__":
demo.launch(share=True)