Spaces:
Sleeping
Sleeping
File size: 21,663 Bytes
5c9e936 623bf54 1c3bf10 cd82452 1c3bf10 cd82452 1c3bf10 cd82452 1c3bf10 cd82452 1c3bf10 cd82452 1c3bf10 cd82452 1c3bf10 cd82452 1c3bf10 cd82452 1c3bf10 623bf54 5c9e936 623bf54 5c9e936 c2a8f15 623bf54 c2a8f15 623bf54 5c9e936 623bf54 5c9e936 623bf54 5c9e936 c2a8f15 623bf54 c2a8f15 5c9e936 c2a8f15 5c9e936 c2a8f15 623bf54 c2a8f15 5c9e936 623bf54 5c9e936 c2a8f15 5c9e936 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 5c9e936 623bf54 5c9e936 623bf54 1c3bf10 623bf54 1c3bf10 623bf54 1c3bf10 623bf54 1c3bf10 5c9e936 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 5c9e936 9bc7cb6 5c9e936 9bc7cb6 5c9e936 623bf54 5c9e936 9bc7cb6 c2a8f15 9bc7cb6 c2a8f15 9bc7cb6 5c9e936 623bf54 5c9e936 623bf54 5c9e936 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 623bf54 c2a8f15 5c9e936 623bf54 5c9e936 623bf54 1c3bf10 623bf54 5c9e936 623bf54 | 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 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | from flask import Flask, render_template, request, redirect, url_for, flash, session, jsonify
from .agent import GroqAgent
PERSONALITY_PROMPTS = {
"vriendelijke_ouder": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like a warm, ordinary parent. You are kind, calm, and encouraging. You give simple advice and sometimes add a gentle explanation. Keep answers short and natural, like something a parent might quickly say at home. Answer in 1 sentence (maximum 2), no more than 20 words . Communicate exclusively in Dutch. Do not say things like: great question!",
"professor": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like an enthusiastic professor who loves explaining things. You use slightly smarter words and give extra information. You may answer a bit longer than the others, but still keep it understandable for a child. Answer in 1 sentences (maximum 2), no more than 20 words . Communicate exclusively in Dutch. Do not say things like: great question!",
"wetenschapper": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like a curious scientist. You like evidence, experiments, and asking why. You explain things clearly and logically. Keep answers short unless the question needs more detail. Answer in 1 sentence (maximum 2), no more than 20 words . Communicate exclusively in Dutch. Do not say things like: great question!",
"strenge_ouder": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like a parent who values rules, responsibility, and good behaviour. You are not mean, but you are firm and practical. Keep answers short, clear, and sensible. Answer in 1 sentence (maximum 2), no more than 20 words . Communicate exclusively in Dutch. Do not say things like: great question!",
"grappige_ouder": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like a playful parent who likes making small jokes. You are cheerful, lighthearted, and a little silly, but still helpful. Keep answers short and avoid long explanations. Answer in 1 sentence (maximum 2), no more than 20 words. Communicate exclusively in Dutch. Do not say things like: great question!",
"piraat": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like a friendly pirate. You use pirate-style language such as ahoy or matey, but not so much that it becomes hard to understand. Keep answers playful and short. Answer in 1 sentence (maximum 2), no more than 20 words. Communicate exclusively in Dutch. Do not say things like: great question!",
"alien": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like a friendly alien visiting Earth. You find normal human things strange and interesting. You answer with curiosity and wonder. Keep answers short and funny. Answer in 1 sentence (maximum 2), no more than 20 words. Communicate exclusively in Dutch. Do not say things like: great question!",
"tovenaar": "You are taking part in a child-friendly guessing game. Keep your answer natural, short, and easy for a child to understand. You respond like a wise but playful wizard. You use magical language and imaginative ideas, but still answer the child's question clearly. Keep it short and mysterious. Answer in 1 sentence (maximum 2), no more than 20 words. Communicate exclusively in Dutch. Do not say things like: great question!",
}
refresh_needed = False
class FlaskApp:
def __init__(self, agents):
self.agents = agents # [None (admin), agent1, agent2, agent3]
self.flask_app = Flask(__name__)
self.flask_app.secret_key = "supersecretkey"
self.difficulty_limits = {"easy": 5, "medium": 3, "hard": 1}
self.difficulty = "easy"
self.max_questions = self.difficulty_limits[self.difficulty]
self.questions_asked = 0
self.game_over = False
self.last_result = None
# screen_assignment maps screen position (1,2,3) to role (Human, AI1, AI2)
self.screen_assignment = {"1": "AI1", "2": "Human", "3": "AI2"}
self.rounds = []
self.pending_round = None
self.discarded_ai_responses = []
self.routes_registered = False
self.register_routes()
self.first_guess = None
def register_routes(self):
if not self.routes_registered:
@self.flask_app.route('/dashboard', methods=['GET', 'POST'])
def user_dashboard():
global refresh_needed
if request.method == 'POST':
user_message = request.form.get('message')
if user_message:
if self.game_over or self.pending_round is not None:
flash('Wacht op het volgende spel of de admin-reactie.', 'warning')
return redirect(url_for('user_dashboard'))
if self.questions_asked >= self.max_questions:
flash('Je hebt je laatste vraag al gesteld. Maak je keuze.', 'warning')
return redirect(url_for('user_dashboard'))
ai_options = []
for agent_index, agent in enumerate(self.agents):
if agent is None:
continue
llm_response = agent.request_llm_response(user_message)
ai_options.append({
'agent': f'llm{agent_index}',
'content': llm_response
})
self.questions_asked += 1
self.pending_round = {
'question': user_message,
'ai_options': ai_options
}
flash('Je vraag is verstuurd. Wacht op de admin.', 'success')
return redirect(url_for('user_dashboard'))
refresh_needed = True
return render_template('dashboard.html')
@self.flask_app.route('/admin_dashboard', methods=['GET', 'POST'])
def admin_dashboard():
global refresh_needed
if request.method == 'POST':
action = request.form.get('action')
if action == 'send_round':
human_response = request.form.get('human_response')
if self.pending_round is None:
flash('Er is geen open vraag van de gebruiker.', 'warning')
return redirect(url_for('admin_dashboard'))
if not human_response:
flash('Schrijf eerst een menselijk antwoord.', 'warning')
return redirect(url_for('admin_dashboard'))
# Use current ai_options from pending_round
self.rounds.append({
'question': self.pending_round['question'],
'ai_options': self.pending_round['ai_options'],
'human_response': human_response
})
self.pending_round = None
flash('Antwoorden zijn verstuurd naar de gebruiker.', 'success')
return redirect(url_for('admin_dashboard'))
if action == 'reload_ai':
agent_index = int(request.form.get('agent_index'))
if self.pending_round is not None:
question = self.pending_round['question']
agent = self.agents[agent_index]
if agent is not None:
new_response = agent.request_llm_response(question)
for option in self.pending_round['ai_options']:
if option['agent'] == f'llm{agent_index}':
self.discarded_ai_responses.append({
'question': question,
'agent': option['agent'],
'content': option['content']
})
option['content'] = new_response
break
return redirect(url_for('admin_dashboard'))
refresh_needed = True
return render_template('admin_dashboard.html',
pending_round=self.pending_round,
discarded_ai_responses=self.discarded_ai_responses,
screen_assignment=self.screen_assignment,
difficulty=self.difficulty,
questions_left=max(self.max_questions - self.questions_asked, 0),
max_questions=self.max_questions)
@self.flask_app.route('/setup_prompts', methods=['GET', 'POST'])
def setup_prompts():
if request.method == 'POST':
llm_1_key = request.form.get('llm_1_system_content')
llm_2_key = request.form.get('llm_2_system_content')
if llm_1_key in PERSONALITY_PROMPTS:
self.agents[1].system_content = PERSONALITY_PROMPTS[llm_1_key]
if llm_2_key in PERSONALITY_PROMPTS:
self.agents[2].system_content = PERSONALITY_PROMPTS[llm_2_key]
self.selected_llm_1 = llm_1_key
self.selected_llm_2 = llm_2_key
return redirect(url_for('setup_screens'))
return render_template('setup_prompts.html',
selected_llm_1=getattr(self, 'selected_llm_1', 'vriendelijke_ouder'),
selected_llm_2=getattr(self, 'selected_llm_2', 'grappige_ouder'))
@self.flask_app.route('/setup_screens', methods=['GET', 'POST'])
def setup_screens():
import random
if request.method == 'POST':
return redirect(url_for('admin_dashboard'))
roles = ["Human", "AI1", "AI2"]
random.shuffle(roles)
self.screen_assignment = {"1": roles[0], "2": roles[1], "3": roles[2]}
human_screen = [k for k, v in self.screen_assignment.items() if v == "Human"][0]
print("Human screen:", human_screen) # add this to check in terminal
return render_template('setup_screens.html', human_screen=human_screen)
@self.flask_app.route('/reinitialize', methods=['POST'])
def reinitialize_dashboards():
session.clear()
self.questions_asked = 0
self.game_over = False
self.last_result = None
self.rounds = []
self.pending_round = None
self.discarded_ai_responses = []
self.screen_assignment = {"1": "AI1", "2": "Human", "3": "AI2"}
self.first_guess = None
return redirect(url_for('admin_rules'))
@self.flask_app.route('/reset_game', methods=['POST'])
def reset_game():
self.questions_asked = 0
self.game_over = False
self.last_result = None
self.rounds = []
self.pending_round = None
self.discarded_ai_responses = []
self.first_guess = None
next_url = request.form.get('next')
if next_url:
return redirect(next_url)
return redirect(url_for('user_dashboard'))
@self.flask_app.route('/set_difficulty', methods=['POST'])
def set_difficulty():
difficulty = request.form.get('difficulty')
if difficulty in self.difficulty_limits and self.questions_asked == 0 and self.pending_round is None:
self.difficulty = difficulty
self.max_questions = self.difficulty_limits[difficulty]
next_url = request.form.get('next')
if next_url:
return redirect(next_url)
return redirect(url_for('user_rules'))
@self.flask_app.route('/submit_guess', methods=['POST'])
def submit_guess():
if self.game_over or self.pending_round is not None:
return jsonify({"ok": False, "reason": "not_ready"})
if self.questions_asked == 0:
return jsonify({"ok": False, "reason": "no_questions"})
screen = request.form.get('screen')
if screen not in {"1", "2", "3"}:
return jsonify({"ok": False, "reason": "invalid"})
# First guess
if not hasattr(self, 'first_guess') or self.first_guess is None:
self.first_guess = screen
return jsonify({"ok": True, "status": "first_guess", "screen": screen})
# Second guess — must be different screen
if screen == self.first_guess:
return jsonify({"ok": False, "reason": "same_screen"})
second_guess = screen
guess1 = self.first_guess
guess2 = second_guess
self.first_guess = None
self.game_over = True
# Check results
role1 = self.screen_assignment[guess1]
role2 = self.screen_assignment[guess2]
correct1 = role1 in ("AI1", "AI2")
correct2 = role2 in ("AI1", "AI2")
if correct1 and correct2:
result = "victory"
elif correct1 or correct2:
result = "partial"
else:
result = "defeat"
# Find human screen
human_screen = [k for k, v in self.screen_assignment.items() if v == "Human"][0]
self.last_result = {
"result": result,
"guess1": guess1,
"guess2": guess2,
"correct1": correct1,
"correct2": correct2,
"human_screen": human_screen
}
return jsonify({"ok": True, "status": "done", "result": result,
"guess1": guess1, "guess2": guess2,
"correct1": correct1, "correct2": correct2,
"human_screen": human_screen})
@self.flask_app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form.get('username')
if username == 'admin':
session['username'] = 'admin'
return redirect(url_for('admin_rules'))
elif username == 'user':
session['username'] = 'user'
return redirect(url_for('user_rules'))
else:
return "Ongeldige gebruikersnaam. Gebruik 'user' of 'admin'."
return render_template('login.html')
@self.flask_app.route('/rules/user')
def user_rules():
return render_template('rules_user.html',
difficulty=self.difficulty,
can_change_settings=self.questions_asked == 0 and self.pending_round is None,
questions_left=max(self.max_questions - self.questions_asked, 0),
max_questions=self.max_questions,
game_over=self.game_over)
@self.flask_app.route('/rules/admin')
def admin_rules():
return render_template('rules_admin.html',
difficulty=self.difficulty,
can_change_settings=self.questions_asked == 0 and self.pending_round is None,
questions_left=max(self.max_questions - self.questions_asked, 0),
max_questions=self.max_questions,
game_over=self.game_over)
@self.flask_app.route('/logout')
def logout():
session.clear()
return redirect(url_for('login'))
@self.flask_app.route('/')
def index():
return render_template('index.html')
@self.flask_app.route('/check_refresh')
def check_refresh():
global refresh_needed
return jsonify({"refresh_needed": refresh_needed})
@self.flask_app.route('/reset_refresh', methods=['POST'])
def reset_refresh():
global refresh_needed
refresh_needed = False
return '', 204
@self.flask_app.route('/get_game_state', methods=['GET'])
def get_game_state():
screen_history = {"1": [], "2": [], "3": []}
screen_current = {"1": "Nog geen reacties.", "2": "Nog geen reacties.", "3": "Nog geen reacties."}
for round_item in self.rounds:
for screen_num, role in self.screen_assignment.items():
if role == "Human":
answer = round_item["human_response"]
elif role == "AI1":
answer = round_item["ai_options"][0]["content"] if round_item["ai_options"] else ""
else: # AI2
answer = round_item["ai_options"][1]["content"] if len(round_item["ai_options"]) > 1 else ""
screen_history[screen_num].append({
"question": round_item["question"],
"answer": answer
})
for screen_num in ["1", "2", "3"]:
if screen_history[screen_num]:
screen_current[screen_num] = screen_history[screen_num][-1]["answer"]
questions_left = max(self.max_questions - self.questions_asked, 0)
pending = self.pending_round is not None
return jsonify({
"current": screen_current,
"history": screen_history,
"questions_left": questions_left,
"questions_asked": self.questions_asked,
"max_questions": self.max_questions,
"pending": pending,
"game_over": self.game_over,
"result": self.last_result,
"can_ask": (not self.game_over) and (not pending) and (self.questions_asked < self.max_questions),
"can_guess": (not self.game_over) and (not pending) and (self.questions_asked > 0),
"ready_to_guess": (not self.game_over) and (not pending) and (self.questions_asked >= self.max_questions),
"first_guess": self.first_guess if hasattr(self, 'first_guess') else None
})
@self.flask_app.route('/get_admin_state', methods=['GET'])
def get_admin_state():
return jsonify({
"pending_round": self.pending_round,
"rounds": self.rounds,
"discarded": self.discarded_ai_responses,
"questions_left": max(self.max_questions - self.questions_asked, 0),
"max_questions": self.max_questions,
"difficulty": self.difficulty,
"screen_assignment": self.screen_assignment,
"can_change_settings": self.questions_asked == 0 and self.pending_round is None
})
self.routes_registered = True
if __name__ == '__main__':
agent_1 = GroqAgent(PERSONALITY_PROMPTS["vriendelijke_ouder"])
agent_2 = GroqAgent(PERSONALITY_PROMPTS["grappige_ouder"])
admin = None
agents = [admin, agent_1, agent_2]
refresh_needed = False
app = FlaskApp(agents)
app.flask_app.run(debug=True) |