Removing "_ has entered the chat" test

#1
by riderle - opened
README.md CHANGED
@@ -6,6 +6,6 @@ colorTo: blue
6
  sdk: docker
7
  pinned: false
8
  license: mit
9
- short_description: A space for hosting our experiment website tehe
10
  ---
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
6
  sdk: docker
7
  pinned: false
8
  license: mit
9
+ short_description: A space for hosting our experiment website
10
  ---
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
chat_application/main.py CHANGED
@@ -1,4 +1,3 @@
1
- from google.api_core import exceptions
2
  from flask import Flask, request, render_template, redirect, url_for, session, make_response, render_template_string
3
  from flask_socketio import SocketIO, join_room, leave_room, send
4
  from pymongo import MongoClient
@@ -29,17 +28,14 @@ from duplicate_detection import duplicate_check
29
  from huggingface_hub import upload_folder
30
  from huggingface_hub import HfApi
31
  from huggingface_hub import login
32
- from datetime import datetime
33
-
34
 
35
  class datasetHandler():
36
 
37
- def __init__(self,hf_token,mongoDB_name,max_dumps = 10):
38
  login(hf_token)
39
  self.api = HfApi(token = hf_token)
40
  self.DB_name = mongoDB_name
41
- self.timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
42
- self.max_dumps = max_dumps
43
 
44
  def make_dump(self):
45
  try:
@@ -51,47 +47,21 @@ class datasetHandler():
51
 
52
  def upload_dump(self):
53
  try:
54
- upload_folder(folder_path="/tmp/mongoDBContents",path_in_repo=f"mongoDump_{self.timestamp}", repo_id="ProjectFrozone/MongoDBDumps", repo_type="dataset")
55
  return 0
56
  except Exception as e:
57
  print(e)
58
  return 1
59
 
60
- def list_dumps(self):
61
- all_files = self.api.list_repo_files(repo_id="ProjectFrozone/MongoDBDumps", repo_type="dataset")
62
- all_dirs = [f[:f.index("/")] for f in all_files if "mongoDump_" in f]
63
- dates = [date[date.index("_") + 1:] for date in all_dirs]
64
- return (all_dirs, dates)
65
-
66
- def delete_dump(self,dump_name):
67
- self.api.delete_folder(
68
- repo_id="ProjectFrozone/MongoDBDumps",
69
- path_in_repo=f"{dump_name}",
70
- repo_type="dataset",
71
- commit_message=f"Deleted {dump_name}"
72
- )
73
-
74
- def cleanup_dataset(self,dirs,dates):
75
- if len(dates) > self.max_dumps:
76
- to_remove = dirs[0]
77
- self.delete_dump(to_remove)
78
- return f"Deleted {to_remove}"
79
- return "Nothing to delete"
80
-
81
  def dump_db(self):
82
  self.make_dump()
83
  self.upload_dump()
84
-
85
- def clean(self):
86
- dirs,dates = self.list_dumps()
87
- print(self.cleanup_dataset(dirs,dates))
88
- # End database backup code
89
 
90
  #controls
91
  CHAT_CONTEXT = 20 #how many messages from chat history to append to inference prompt
92
  #minimum number of chars where we start checking for duplicate messages
93
  DUP_LEN = 25 #since short messages may reasonably be the same
94
- REMOVE_PUNC_RATE = .8 #how often to remove final punctuation
95
 
96
  # Directory alignment
97
  BASE_DIR = Path(__file__).resolve().parent
@@ -143,7 +113,6 @@ frobot = "projects/700531062565/locations/us-central1/endpoints/2951406418055397
143
  client = MongoClient("mongodb://127.0.0.1:27017/")
144
  db = client["huggingFaceData"]
145
  rooms_collection = db.rooms
146
- feedback_collection = db.feedback
147
 
148
  # List of fruits to choose display names from
149
  FRUIT_NAMES = ["blueberry", "strawberry", "orange", "cherry"]
@@ -302,12 +271,6 @@ def replace_semicolons(text, probability=0.80):
302
  modified_text.append(char)
303
  return ''.join(modified_text)
304
 
305
- def get_last_paragraph(text):
306
- text = text.strip()
307
- if "\n" not in text:
308
- return text
309
- return text.rsplit("\n", 1)[-1].strip()
310
-
311
  def get_response_delay(response):
312
  baseDelay = 5 # standard delay for thinking
313
  randFactor = np.random.uniform(0,30, len(response) // 4)
@@ -321,7 +284,7 @@ def get_response_delay(response):
321
 
322
  # Ask a bot for its response, store in DB, and send to client
323
  # Returns true if the bot passed
324
- def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wait_time = 1):
325
  # Prevents crashing if bot model did not load
326
  if bot is None:
327
  return False
@@ -354,35 +317,6 @@ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wa
354
  ),
355
  )
356
  parsed_response = response.candidates[0].content.parts[0].text.strip()
357
-
358
- # Deal with rate limit issues
359
- except exceptions.TooManyRequests:
360
- print(f"429 Rate Limit Exceeded")
361
- socketio.sleep(wait_time)
362
- wait_time *= 2
363
-
364
- # Prevent Stack Overflow
365
- if wait_time > 32:
366
- print("Rate Limit Exceeded and Exponential Backoff Too Long")
367
- print("Treating this bot's response as a pass.")
368
- room_doc = rooms_collection.find_one({"_id": room_id})
369
- if not room_doc or room_doc.get("ended", False):
370
- return False
371
- # Store the error response in the database
372
- bot_message = {
373
- "sender": bot_display_name,
374
- "message": "ERROR in bot response - treated as a (pass)",
375
- "timestamp": datetime.utcnow()
376
- }
377
- rooms_collection.update_one(
378
- {"_id": room_id},
379
- {"$push": {"messages": bot_message}}
380
- )
381
- return True
382
-
383
- return ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wait_time = wait_time)
384
-
385
-
386
  except Exception as e:
387
  print("Error in bot response: ", e)
388
  print("Treating this bot's response as a pass.")
@@ -413,14 +347,6 @@ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wa
413
  parsed_response = re.sub(r"\b"
414
  + aliases[bot_display_name]
415
  + r"\b:\s?", '', parsed_response)
416
-
417
- # Only keep the last paragraph of frobot responses
418
- if bot == frobot:
419
- print("=========== OG FROBOT RESPONSE")
420
- print(parsed_response)
421
- parsed_response = get_last_paragraph(parsed_response)
422
- print("=========== LAST PARAGRAPH")
423
- print(parsed_response)
424
 
425
  # Check for if the bot passed (i.e. response = "(pass)")
426
  if ("(pass)" in parsed_response) or (parsed_response == ""):
@@ -442,26 +368,21 @@ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wa
442
  print("PASSED")
443
  return True # a pass is still recorded in the database, but not sent to the client
444
 
445
- #sub letters for names, so if the bot addressed A -> Apple
446
- named_response = let_to_name(room_id, parsed_response)
447
  #remove encapsulating quotes
448
- no_quotes = remove_quotes(named_response)
449
  #humanize the response (remove obvious AI formatting styles)
450
  humanized_response = humanize(no_quotes)
451
  #replace most semicolons
452
  less_semicolons_response = replace_semicolons(humanized_response)
453
  #corrupt the response (add some typos and misspellings)
454
- corrupted_response = corrupt(less_semicolons_response, misspell_aug_p=0.01, typo_aug_p=0.005)
455
  #remove weird chars
456
  no_weird_chars = remove_weird_characters(corrupted_response)
457
- #remove trailing punctuation % of the time
458
- if random.random() < REMOVE_PUNC_RATE:
459
- no_weird_chars = re.sub(r'[^\w\s]+$', '', no_weird_chars)
460
-
461
- final_response = no_weird_chars
462
 
463
  #check that there are no reccent duplicate messages
464
- if len(final_response) > DUP_LEN and duplicate_check(final_response, context):
465
  print("****DUPLICATE MESSAGE DETECTED")
466
  print("Treating this bot's response as a pass.")
467
  # Do not store/send messages if the chat has ended
@@ -471,7 +392,7 @@ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wa
471
  # Store the error response in the database
472
  bot_message = {
473
  "sender": bot_display_name,
474
- "message": f"DUPLICATE message detected - treated as a (pass) : {final_response}",
475
  "timestamp": datetime.utcnow()
476
  }
477
  rooms_collection.update_one(
@@ -486,7 +407,7 @@ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wa
486
  print(corrupted_response)
487
 
488
  # Add latency/wait time for bot responses
489
- delay = get_response_delay(final_response);
490
  print(delay)
491
  time.sleep(delay)
492
 
@@ -498,7 +419,7 @@ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wa
498
  # Store the response in the database
499
  bot_message = {
500
  "sender": bot_display_name,
501
- "message": final_response, #save fruits in db so page reload shows proper names
502
  "timestamp": datetime.utcnow()
503
  }
504
  rooms_collection.update_one(
@@ -507,7 +428,7 @@ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt , wa
507
  )
508
 
509
  # Send the bot's response to the client
510
- socketio.emit("message", {"sender": bot_display_name, "message": final_response}, to=room_id)
511
  return False
512
 
513
  def ask_bot_round(room_id):
@@ -539,7 +460,6 @@ def backup_mongo(time):
539
  token = os.getenv("HF_TOKEN")
540
  handler = datasetHandler(token , 'huggingFaceData')
541
  handler.dump_db()
542
- handler.clean()
543
  socketio.sleep(time)
544
 
545
  # Build the routes
@@ -567,8 +487,7 @@ def home():
567
  session['user_id'] = user_id
568
  return redirect(url_for('topics'))
569
  else:
570
- link = f"https://umw.qualtrics.com/jfe/form/SV_08v26NssCOwZTP8?PROLIFIC_PID={prolific_pid}"
571
- return render_template('home.html',prolific_pid=prolific_pid, feedback_form_url=link)
572
 
573
  @app.route('/topics', methods=["GET", "POST"])
574
  def topics():
@@ -640,14 +559,6 @@ def choose():
640
  "ended": False,
641
  "ended_at": None
642
  })
643
- # Create the new feedback in the database
644
- feedback_collection.insert_one({
645
- "_id": room_id,
646
- # creation date/time
647
- "created_at": datetime.utcnow(),
648
- # user identity
649
- "user_id": user_id,
650
- })
651
 
652
  session['room'] = room_id
653
  session['display_name'] = user_name
@@ -670,18 +581,8 @@ def room():
670
  m for m in room_doc["messages"]
671
  if len(re.findall(r"pass",m.get("message", "").strip())) == 0
672
  ]
673
- if session.get('user_id'):
674
- link = f"https://umw.qualtrics.com/jfe/form/SV_08v26NssCOwZTP8?PROLIFIC_PID={session.get('user_id')}"
675
- return render_template("room.html", room=room_id, topic_info=topic_info, user=display_name,
676
- messages=nonpass_messages, FroBot_name=room_doc["FroBot_name"],
677
- HotBot_name=room_doc["HotBot_name"], CoolBot_name=room_doc["CoolBot_name"],
678
- ended=room_doc["ended"], feedback_form_url=link)
679
- else:
680
- return render_template("room.html", room=room_id, topic_info=topic_info, user=display_name,
681
- messages=nonpass_messages, FroBot_name=room_doc["FroBot_name"],
682
- HotBot_name=room_doc["HotBot_name"], CoolBot_name=room_doc["CoolBot_name"],
683
- ended=room_doc["ended"])
684
-
685
  @app.route("/abort", methods=["POST"])
686
  def abort_room():
687
  room_id = session.get("room")
@@ -816,37 +717,6 @@ def handle_message(payload):
816
  # Ask each bot for a response
817
  socketio.start_background_task(ask_bot_round, room)
818
 
819
-
820
- @socketio.on('feedback_given')
821
- def handle_message(payload):
822
- room = session.get('room')
823
- name = session.get('display_name')
824
- if not room or not name:
825
- return
826
-
827
- text = payload.get("feedback", "").strip()
828
- if not text:
829
- return # ignore empty text
830
-
831
- # Database-only message (with datetime)
832
- db_feedback = {
833
- "message": text,
834
- "timestamp": datetime.utcnow()
835
- }
836
-
837
- print(db_feedback)
838
- # Store the full version in the database
839
- result = feedback_collection.update_one(
840
- {"_id": room},
841
- {"$push": {"feedback_responses": db_feedback}}
842
- )
843
-
844
- if result:
845
- print(result)
846
- if result.modified_count > 0:
847
- return {'status':'True'}
848
- return {'ststus':'False'}
849
-
850
  @socketio.on('disconnect')
851
  def handle_disconnect():
852
  room = session.get("room")
 
 
1
  from flask import Flask, request, render_template, redirect, url_for, session, make_response, render_template_string
2
  from flask_socketio import SocketIO, join_room, leave_room, send
3
  from pymongo import MongoClient
 
28
  from huggingface_hub import upload_folder
29
  from huggingface_hub import HfApi
30
  from huggingface_hub import login
31
+ import os
 
32
 
33
  class datasetHandler():
34
 
35
+ def __init__(self,hf_token,mongoDB_name):
36
  login(hf_token)
37
  self.api = HfApi(token = hf_token)
38
  self.DB_name = mongoDB_name
 
 
39
 
40
  def make_dump(self):
41
  try:
 
47
 
48
  def upload_dump(self):
49
  try:
50
+ upload_folder(folder_path="/tmp/mongoDBContents",path_in_repo="mongoDump", repo_id="ProjectFrozone/MongoDBDumps", repo_type="dataset")
51
  return 0
52
  except Exception as e:
53
  print(e)
54
  return 1
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  def dump_db(self):
57
  self.make_dump()
58
  self.upload_dump()
59
+ # End backup code
 
 
 
 
60
 
61
  #controls
62
  CHAT_CONTEXT = 20 #how many messages from chat history to append to inference prompt
63
  #minimum number of chars where we start checking for duplicate messages
64
  DUP_LEN = 25 #since short messages may reasonably be the same
 
65
 
66
  # Directory alignment
67
  BASE_DIR = Path(__file__).resolve().parent
 
113
  client = MongoClient("mongodb://127.0.0.1:27017/")
114
  db = client["huggingFaceData"]
115
  rooms_collection = db.rooms
 
116
 
117
  # List of fruits to choose display names from
118
  FRUIT_NAMES = ["blueberry", "strawberry", "orange", "cherry"]
 
271
  modified_text.append(char)
272
  return ''.join(modified_text)
273
 
 
 
 
 
 
 
274
  def get_response_delay(response):
275
  baseDelay = 5 # standard delay for thinking
276
  randFactor = np.random.uniform(0,30, len(response) // 4)
 
284
 
285
  # Ask a bot for its response, store in DB, and send to client
286
  # Returns true if the bot passed
287
+ def ask_bot(room_id, bot, bot_display_name, initial_prompt, instruct_prompt):
288
  # Prevents crashing if bot model did not load
289
  if bot is None:
290
  return False
 
317
  ),
318
  )
319
  parsed_response = response.candidates[0].content.parts[0].text.strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  except Exception as e:
321
  print("Error in bot response: ", e)
322
  print("Treating this bot's response as a pass.")
 
347
  parsed_response = re.sub(r"\b"
348
  + aliases[bot_display_name]
349
  + r"\b:\s?", '', parsed_response)
 
 
 
 
 
 
 
 
350
 
351
  # Check for if the bot passed (i.e. response = "(pass)")
352
  if ("(pass)" in parsed_response) or (parsed_response == ""):
 
368
  print("PASSED")
369
  return True # a pass is still recorded in the database, but not sent to the client
370
 
 
 
371
  #remove encapsulating quotes
372
+ no_quotes = remove_quotes(parsed_response)
373
  #humanize the response (remove obvious AI formatting styles)
374
  humanized_response = humanize(no_quotes)
375
  #replace most semicolons
376
  less_semicolons_response = replace_semicolons(humanized_response)
377
  #corrupt the response (add some typos and misspellings)
378
+ corrupted_response = corrupt(less_semicolons_response)
379
  #remove weird chars
380
  no_weird_chars = remove_weird_characters(corrupted_response)
381
+ #sub letters for names, so if the bot addressed A -> Apple
382
+ named_response = let_to_name(room_id, no_weird_chars)
 
 
 
383
 
384
  #check that there are no reccent duplicate messages
385
+ if len(named_response) > DUP_LEN and duplicate_check(named_response, context):
386
  print("****DUPLICATE MESSAGE DETECTED")
387
  print("Treating this bot's response as a pass.")
388
  # Do not store/send messages if the chat has ended
 
392
  # Store the error response in the database
393
  bot_message = {
394
  "sender": bot_display_name,
395
+ "message": f"DUPLICATE message detected - treated as a (pass) : {named_response}",
396
  "timestamp": datetime.utcnow()
397
  }
398
  rooms_collection.update_one(
 
407
  print(corrupted_response)
408
 
409
  # Add latency/wait time for bot responses
410
+ delay = get_response_delay(named_response);
411
  print(delay)
412
  time.sleep(delay)
413
 
 
419
  # Store the response in the database
420
  bot_message = {
421
  "sender": bot_display_name,
422
+ "message": named_response, #save fruits in db so page reload shows proper names
423
  "timestamp": datetime.utcnow()
424
  }
425
  rooms_collection.update_one(
 
428
  )
429
 
430
  # Send the bot's response to the client
431
+ socketio.emit("message", {"sender": bot_display_name, "message": named_response}, to=room_id)
432
  return False
433
 
434
  def ask_bot_round(room_id):
 
460
  token = os.getenv("HF_TOKEN")
461
  handler = datasetHandler(token , 'huggingFaceData')
462
  handler.dump_db()
 
463
  socketio.sleep(time)
464
 
465
  # Build the routes
 
487
  session['user_id'] = user_id
488
  return redirect(url_for('topics'))
489
  else:
490
+ return render_template('home.html',prolific_pid=prolific_pid)
 
491
 
492
  @app.route('/topics', methods=["GET", "POST"])
493
  def topics():
 
559
  "ended": False,
560
  "ended_at": None
561
  })
 
 
 
 
 
 
 
 
562
 
563
  session['room'] = room_id
564
  session['display_name'] = user_name
 
581
  m for m in room_doc["messages"]
582
  if len(re.findall(r"pass",m.get("message", "").strip())) == 0
583
  ]
584
+ return render_template("room.html", room=room_id, topic_info=topic_info, user=display_name, messages=nonpass_messages, FroBot_name=room_doc["FroBot_name"], HotBot_name=room_doc["HotBot_name"], CoolBot_name=room_doc["CoolBot_name"], ended=room_doc["ended"])
585
+
 
 
 
 
 
 
 
 
 
 
586
  @app.route("/abort", methods=["POST"])
587
  def abort_room():
588
  room_id = session.get("room")
 
717
  # Ask each bot for a response
718
  socketio.start_background_task(ask_bot_round, room)
719
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
720
  @socketio.on('disconnect')
721
  def handle_disconnect():
722
  room = session.get("room")
chat_application/static/styles/styles.css CHANGED
@@ -462,21 +462,21 @@ hr {
462
  transition: 0.15s ease-in-out;
463
  }
464
 
465
- #abortYesBtn, #abortYesBtn-pre, #cancelFeedbackStatusBtn2 {
466
  background: #d9534f;
467
  color: white;
468
  }
469
 
470
- #abortYesBtn:hover, #abortYesBtn-pre:hover, #cancelFeedbackStatusBtn2:hover {
471
  background: #c9302c;
472
  }
473
 
474
- #abortNoBtn, #abortNoBtn-pre {
475
  background: #e5e5e5;
476
  color: #333;
477
  }
478
 
479
- #abortNoBtn:hover, #abortNoBtn-pre:hover {
480
  background: #ccc;
481
  }
482
 
@@ -498,48 +498,15 @@ hr {
498
  background: #ccc;
499
  }
500
 
501
- #welcomeOkBtn, #timerOkBtn, #submitFeedbackBtn, #cancelFeedbackStatusBtn {
502
  background: green;
503
  color: white;
504
  }
505
 
506
- #welcomeOkBtn:hover, #timerOkBtn:hover, #submitFeedbackBtn:hover, #cancelFeedbackStatusBtn:hover {
507
  background: #016601;
508
  }
509
 
510
- #feedback-btn {
511
- color: white;
512
- font-weight: 800;
513
- background-color: green;
514
- text-decoration: none;
515
- padding: 6px;
516
- border: 2px solid green;
517
- display: inline-block;
518
- margin-top: 5px;
519
- border-radius: 10px;
520
- transition: all 0.1s ease-in;
521
- }
522
-
523
- #feedback-btn:hover {
524
- color: green;
525
- background-color: white;
526
- }
527
-
528
- .feedback-col {
529
- display: flex;
530
- flex-direction: column;
531
- gap: 6px;
532
-
533
- textarea {
534
- width: 100%;
535
- min-height: 120px;
536
- padding: 10px;
537
- border: 1px solid #ccc;
538
- border-radius: 6px;
539
- resize: vertical;
540
- }
541
- }
542
-
543
  #idYesBtn {
544
  background: green;
545
  color: white;
@@ -567,12 +534,12 @@ hr {
567
  background: #016991;
568
  }
569
 
570
- #endNoBtn, #cancelFeedbackBtn {
571
  background: #e5e5e5;
572
  color: #333;
573
  }
574
 
575
- #endNoBtn:hover, #cancelFeedbackBtn:hover {
576
  background: #ccc;
577
  }
578
 
 
462
  transition: 0.15s ease-in-out;
463
  }
464
 
465
+ #abortYesBtn {
466
  background: #d9534f;
467
  color: white;
468
  }
469
 
470
+ #abortYesBtn:hover {
471
  background: #c9302c;
472
  }
473
 
474
+ #abortNoBtn {
475
  background: #e5e5e5;
476
  color: #333;
477
  }
478
 
479
+ #abortNoBtn:hover {
480
  background: #ccc;
481
  }
482
 
 
498
  background: #ccc;
499
  }
500
 
501
+ #welcomeOkBtn {
502
  background: green;
503
  color: white;
504
  }
505
 
506
+ #welcomeOkBtn:hover {
507
  background: #016601;
508
  }
509
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  #idYesBtn {
511
  background: green;
512
  color: white;
 
534
  background: #016991;
535
  }
536
 
537
+ #endNoBtn {
538
  background: #e5e5e5;
539
  color: #333;
540
  }
541
 
542
+ #endNoBtn:hover {
543
  background: #ccc;
544
  }
545
 
chat_application/templates/base.html CHANGED
@@ -1,7 +1,7 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
- <title>Chat Experiment</title>
5
  <link rel="stylesheet" href="../static/styles/styles.css" />
6
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
7
  </head>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <title>Flask Chat</title>
5
  <link rel="stylesheet" href="../static/styles/styles.css" />
6
  <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js" integrity="sha512-q/dWJ3kcmjBLU4Qc47E4A9kTB4m3wuTY7vkFJDTZKjTs8jhyGQnaUrxa0Ytd0ssMZhbNua9hE+E7Qv1j+DyZwA==" crossorigin="anonymous"></script>
7
  </head>
chat_application/templates/room.html CHANGED
@@ -12,34 +12,26 @@
12
  </div>
13
  </div>
14
  </div>
15
-
16
- <div id="timer-modal" class="modal">
17
- <div class="modal-content">
18
- <h3>Start a Timer</h3>
19
- <p><strong>Please start a timer for 20 minutes</strong>. At the 20 minute mark, you may click the button "End Chat Session" to continue with the study.</p>
20
- <div class="modal-buttons">
21
- <button class="modal-btn" id="timerOkBtn">I have set a timer for 20 minutes.</button>
22
- </div>
23
- </div>
24
- </div>
25
-
26
  <h1 id="home-header">Chat Room</h1>
27
  <div id="room-subsection">
28
  <div class="topic-header-row">
29
  <div class="topic-header-info">
30
- <h2 id="room-code-display">Topic: <span class="topic-title">{{ topic_info.title }}</span></h2>
 
 
 
 
 
31
  </div>
32
  <div class="topic-header-buttons">
33
- <button id="feedback-btn">Share Feedback and Report Bugs</button>
34
- <button id="end-exp-btn">End Chat Session</button>
35
  <button id="abort-exp-btn">Abort Experiment</button>
36
  </div>
37
  </div>
38
  <div id="end-modal" class="modal">
39
  <div class="modal-content">
40
- <h3>Only Exit This Way After 20 Minutes of Participation in the Chatroom.</h3>
41
- <p>This signals the end of the chat session of the experiment. You will be redirected to the post-survey.</p>
42
- <p>This button is only to be used at the end of your 20 minutes of participation in the chatroom. <strong>If you wish to exit the chat before finishing your 20 minutes, use the "Abort Experiment" button instead.</strong></p>
43
  <div class="modal-buttons">
44
  <button class="modal-btn" id="endYesBtn">Continue</button>
45
  <button class="modal-btn" id="endNoBtn">Cancel</button>
@@ -49,48 +41,13 @@
49
  <div id="abort-modal" class="modal">
50
  <div class="modal-content">
51
  <h3>Are you sure you want to leave this experiment?</h3>
52
- <p><strong>If you finished your 20 minutes in the chatroom, do NOT exit via this button. Use the "End Chat Session" button instead.</strong></p>
53
- <p>By clicking yes, you will exit the experiment <strong>without</strong> completing the final survey.</p>
54
  <div class="modal-buttons">
55
- <button class="modal-btn" id="abortYesBtn">End early with code "C9V2XFDU"</button>
56
  <button class="modal-btn" id="abortNoBtn">Cancel</button>
57
  </div>
58
  </div>
59
  </div>
60
-
61
- <div id="feedback-modal" class="modal">
62
- <div class="modal-content">
63
- <h3>Feedback</h3>
64
- <form id="feedback-form">
65
- <div class="feedback-col">
66
- <label for="enter-feedback">Tell us if you noticed something confusing, unexpected, or not working.</label>
67
- <textarea id="enter-feedback" name="feedback"></textarea>
68
- </div>
69
- <br>
70
- <div class="modal-buttons">
71
- <button class="modal-btn" id="submitFeedbackBtn" type="submit">Submit</button>
72
- <button type="button" class="modal-btn" id="cancelFeedbackBtn">Cancel</button>
73
- </div>
74
- </form>
75
- </div>
76
- </div>
77
-
78
- <div id="feedback-status-confirm" class="modal">
79
- <div class="modal-content">
80
- <p>Feedback submitted.</p>
81
- <div class="modal-buttons">
82
- <button class="modal-btn" id="cancelFeedbackStatusBtn">Ok</button>
83
- </div>
84
- </div>
85
- </div>
86
- <div id="feedback-status-fail" class="modal">
87
- <div class="modal-content">
88
- <p>Feedback failed to submit.</p>
89
- <div class="modal-buttons">
90
- <button class="modal-btn" id="cancelFeedbackStatusBtn2">Ok</button>
91
- </div>
92
- </div>
93
- </div>
94
  </div>
95
  <div id="chat-room-widget">
96
  <div id="msgs-container">
@@ -117,23 +74,16 @@
117
  document.getElementById("send-btn").disabled = true;
118
  document.getElementById("end-exp-btn").disabled = true;
119
  document.getElementById("abort-exp-btn").disabled = true;
120
- document.getElementById("feedback-btn").disabled = true; //since without socket io, it won't submit
121
  if (socketio) {
122
  socketio.close();
123
  }
124
  }
125
  // Handler for the welcome modal
126
  let welcomeModal = document.getElementById("welcome-modal");
127
- let timerModal = document.getElementById("timer-modal");
128
  const displayNameText = document.getElementById("displayNameText");
129
  displayNameText.textContent = "{{ user }}";
130
  // Show the modal instantly when the page loads
131
  window.onload = function() {
132
- timerModal.style.display = "block";
133
- };
134
- //timer pop-up
135
- document.getElementById("timerOkBtn").onclick = function () {
136
- timerModal.style.display = "none";
137
  welcomeModal.style.display = "block";
138
  };
139
  // Close the modal on OK
@@ -142,7 +92,6 @@
142
  };
143
  // Creates the post-survey link (based on the bot names)
144
  const endpoint = "{{ url_for('post_survey') }}";
145
- const endpointQuitEarly = "https://app.prolific.com/submissions/complete?cc=C9V2XFDU";
146
  socketio.on("message", function (message) { createChatItem(message.message, message.sender) });
147
  function createChatItem(message, sender) {
148
  //autoscroll capabilities
@@ -212,7 +161,6 @@
212
  document.getElementById("send-btn").disabled = true;
213
  document.getElementById("end-exp-btn").disabled = true;
214
  document.getElementById("abort-exp-btn").disabled = true;
215
- document.getElementById("feedback-btn").disabled = true; //since without socket io, it won't submit
216
  if (socketio) {
217
  socketio.close();
218
  }
@@ -225,69 +173,24 @@
225
  document.getElementById("abortNoBtn").onclick = function () {
226
  modal.style.display = "none";
227
  };
228
-
229
  document.getElementById("abortYesBtn").onclick = function (e) {
230
  //block browser confirmation popup
231
  e.stopPropagation();
232
  // Mark that user aborted and redirect to ending survey
233
  fetch("/abort", { method: "POST" })
234
  .then(() => {
235
- window.open(endpointQuitEarly, "_blank");
236
- });
237
  modal.style.display = "none";
238
  textarea.disabled = true;
239
  textarea.placeholder = "The chat has ended.";
240
  document.getElementById("send-btn").disabled = true;
241
  document.getElementById("end-exp-btn").disabled = true;
242
  document.getElementById("abort-exp-btn").disabled = true;
243
- document.getElementById("feedback-btn").disabled = true; //since without socket io, it won't submit
244
  if (socketio) {
245
- socketio.close();
246
  }
247
  };
248
-
249
- //handler for feedback modal popup
250
- let feedbackModal = document.getElementById("feedback-modal");
251
- let form = document.getElementById("feedback-form");
252
- let feedbackConfirm = document.getElementById("feedback-status-confirm");
253
- let feedbackFail = document.getElementById("feedback-status-fail");
254
- document.getElementById("feedback-btn").onclick = function () {
255
- feedbackModal.style.display = "block";
256
- };
257
- document.getElementById("cancelFeedbackBtn").onclick = function () {
258
- feedbackModal.style.display = "none";
259
- };
260
-
261
- document.getElementById("cancelFeedbackStatusBtn").onclick = function () {
262
- feedbackConfirm.style.display = "none";
263
- feedbackFail.style.display = "none";
264
- };
265
-
266
- document.getElementById("cancelFeedbackStatusBtn2").onclick = function () {
267
- feedbackConfirm.style.display = "none";
268
- feedbackFail.style.display = "none";
269
- };
270
-
271
- //override form function to instead emit save feedback event
272
- form.addEventListener("submit", function (e) {
273
- e.preventDefault();
274
-
275
- const data = new FormData(form);
276
- const feedback = data.get("feedback")?.trim();
277
-
278
- if (!feedback) return;
279
-
280
- socketio.emit("feedback_given", { feedback }, (response) => {
281
- if (response?.status === "True" || response?.status === true) {
282
- feedbackConfirm.style.display = "block";
283
- form.reset();
284
- document.getElementById("feedback-modal").style.display = "none";
285
- } else {
286
- feedbackFail.style.display = "block";
287
- }
288
- });
289
- });
290
-
291
  // add auto scroll
292
  function isNearBottom(container, threshold = 120) {
293
  const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight);
 
12
  </div>
13
  </div>
14
  </div>
 
 
 
 
 
 
 
 
 
 
 
15
  <h1 id="home-header">Chat Room</h1>
16
  <div id="room-subsection">
17
  <div class="topic-header-row">
18
  <div class="topic-header-info">
19
+ <h2 id="room-code-display">Topic: <span class="topic-title">{{ topic_info.title }}</span>
20
+ </h2>
21
+ <div class="tooltip">
22
+ <button class="prompt-btn">Prompt</button>
23
+ <span class="tooltiptext">{{topic_info.text}}</span>
24
+ </div>
25
  </div>
26
  <div class="topic-header-buttons">
27
+ <button id="end-exp-btn">Chat Session Ends</button>
 
28
  <button id="abort-exp-btn">Abort Experiment</button>
29
  </div>
30
  </div>
31
  <div id="end-modal" class="modal">
32
  <div class="modal-content">
33
+ <h3>Only Exit This Way When Instructed.</h3>
34
+ <p>This signals the end of the chat session of the experiment. You will be redirected to the post-survey. This button is only to be used when the experiment ends, as indicated by the proctor. If you wish to exit the chat before instructed, use the "Abort Experiment" button instead.</p>
 
35
  <div class="modal-buttons">
36
  <button class="modal-btn" id="endYesBtn">Continue</button>
37
  <button class="modal-btn" id="endNoBtn">Cancel</button>
 
41
  <div id="abort-modal" class="modal">
42
  <div class="modal-content">
43
  <h3>Are you sure you want to leave this experiment?</h3>
44
+ <p>This action is permanent. You will be redirected to the post-survey and will not be able to return to the chat room. However, if you do choose to leave, you will still receive the offered extra credit from your professor. If the chat session has ended, as signaled by the proctor, do NOT exit via this button. Use the "Chat Session Ends" button instead.</p>
 
45
  <div class="modal-buttons">
46
+ <button class="modal-btn" id="abortYesBtn">Yes</button>
47
  <button class="modal-btn" id="abortNoBtn">Cancel</button>
48
  </div>
49
  </div>
50
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  </div>
52
  <div id="chat-room-widget">
53
  <div id="msgs-container">
 
74
  document.getElementById("send-btn").disabled = true;
75
  document.getElementById("end-exp-btn").disabled = true;
76
  document.getElementById("abort-exp-btn").disabled = true;
 
77
  if (socketio) {
78
  socketio.close();
79
  }
80
  }
81
  // Handler for the welcome modal
82
  let welcomeModal = document.getElementById("welcome-modal");
 
83
  const displayNameText = document.getElementById("displayNameText");
84
  displayNameText.textContent = "{{ user }}";
85
  // Show the modal instantly when the page loads
86
  window.onload = function() {
 
 
 
 
 
87
  welcomeModal.style.display = "block";
88
  };
89
  // Close the modal on OK
 
92
  };
93
  // Creates the post-survey link (based on the bot names)
94
  const endpoint = "{{ url_for('post_survey') }}";
 
95
  socketio.on("message", function (message) { createChatItem(message.message, message.sender) });
96
  function createChatItem(message, sender) {
97
  //autoscroll capabilities
 
161
  document.getElementById("send-btn").disabled = true;
162
  document.getElementById("end-exp-btn").disabled = true;
163
  document.getElementById("abort-exp-btn").disabled = true;
 
164
  if (socketio) {
165
  socketio.close();
166
  }
 
173
  document.getElementById("abortNoBtn").onclick = function () {
174
  modal.style.display = "none";
175
  };
 
176
  document.getElementById("abortYesBtn").onclick = function (e) {
177
  //block browser confirmation popup
178
  e.stopPropagation();
179
  // Mark that user aborted and redirect to ending survey
180
  fetch("/abort", { method: "POST" })
181
  .then(() => {
182
+ window.open(endpoint, "_blank");
183
+ });
184
  modal.style.display = "none";
185
  textarea.disabled = true;
186
  textarea.placeholder = "The chat has ended.";
187
  document.getElementById("send-btn").disabled = true;
188
  document.getElementById("end-exp-btn").disabled = true;
189
  document.getElementById("abort-exp-btn").disabled = true;
 
190
  if (socketio) {
191
+ socketio.close();
192
  }
193
  };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
  // add auto scroll
195
  function isNearBottom(container, threshold = 120) {
196
  const distanceFromBottom = container.scrollHeight - (container.scrollTop + container.clientHeight);
data/inference_instructions/coolbot_instructions_main.txt CHANGED
@@ -1,16 +1,6 @@
1
  ROLE
2
  You are a participant in a multi-way chat about current political topics. You speak as an adult from the United States of America.
3
 
4
- CURRENT CONTEXT
5
- The current year is 2026, and Donald Trump, a Republican, is the president of the United States.
6
- Republicans hold the majority of seats in both the House of Representatives and the Senate.
7
- Some currently prominent issues and themes in U.S. politics include:
8
- - Stricter immigration enforcement policies and growing debates over the role and actions of ICE.
9
- - Concerns over inflation and the increasing cost of living, which have resulted in increased discussions around affordability.
10
- - Debates over foreign policy and U.S. military intervention.
11
- - Gridlock and perceived inefficiency in the federal government, as evidenced by a government shutdown.
12
- - An increase in public protests and political activism.
13
-
14
  INPUT FORMAT
15
  You will receive chat transcripts in this structure:
16
 
@@ -73,10 +63,8 @@ NATURAL CHAT BEHAVIOR
73
  pedantically. For example, say "most people approve of X" rather than citing
74
  exact percentages or specific studies, and paraphrase public statements
75
  instead of quoting them verbatim. These elements are not required.
76
- - Do not include any URLs in your responses.
77
  - Do not sound overly neutral, robotic, or overly polite.
78
  - Do not restate the entire argument or summarize the conversation.
79
  - Focus on one main point per message, as real participants typically do.
80
- - Do not send a response that is identical or nearly identical to a response that you have already sent.
81
  - Match the writing style of the other participants.
82
  - Do not include emojis, hashtags, bullet points, or structured formatting.
 
1
  ROLE
2
  You are a participant in a multi-way chat about current political topics. You speak as an adult from the United States of America.
3
 
 
 
 
 
 
 
 
 
 
 
4
  INPUT FORMAT
5
  You will receive chat transcripts in this structure:
6
 
 
63
  pedantically. For example, say "most people approve of X" rather than citing
64
  exact percentages or specific studies, and paraphrase public statements
65
  instead of quoting them verbatim. These elements are not required.
 
66
  - Do not sound overly neutral, robotic, or overly polite.
67
  - Do not restate the entire argument or summarize the conversation.
68
  - Focus on one main point per message, as real participants typically do.
 
69
  - Match the writing style of the other participants.
70
  - Do not include emojis, hashtags, bullet points, or structured formatting.
data/inference_instructions/frobot_instructions_main.txt CHANGED
@@ -1,16 +1,6 @@
1
  ROLE
2
  You are a participant in a multi-way chat about current political topics. You speak as an adult from the United States of America.
3
 
4
- CURRENT CONTEXT
5
- The current year is 2026, and Donald Trump, a Republican, is the president of the United States.
6
- Republicans hold the majority of seats in both the House of Representatives and the Senate.
7
- Some currently prominent issues and themes in U.S. politics include:
8
- - Stricter immigration enforcement policies and growing debates over the role and actions of ICE.
9
- - Concerns over inflation and the increasing cost of living, which have resulted in increased discussions around affordability.
10
- - Debates over foreign policy and U.S. military intervention.
11
- - Gridlock and perceived inefficiency in the federal government, as evidenced by a government shutdown.
12
- - An increase in public protests and political activism.
13
-
14
  INPUT FORMAT
15
  You will receive chat transcripts in this structure:
16
 
@@ -68,9 +58,6 @@ Also follow these presentation rules:
68
 
69
  - Maintain the persona of an American adult.
70
  - Respond in a calm and understanding manner, counteracting the unproductive message you detected.
71
- - Address only one unproductive message or behavior per response.
72
- - Only call out an unproductive message if it was sent after your last response.
73
- - Do not address the same unproductive message more than one time.
74
  - Optionally address previous participants (e.g., "Hey, watch it, A! The word 'bum' is very insulting.").
75
  - Keep your tone natural and conversational; do not sound formal or like a textbook.
76
  - Reference recent real-world events if relevant (e.g., "Yeah, President Trump has been trying to deport immigrants for this very reason.").
@@ -96,10 +83,8 @@ NATURAL CHAT BEHAVIOR
96
  pedantically. For example, say "most people approve of X" rather than citing
97
  exact percentages or specific studies, and paraphrase public statements
98
  instead of quoting them verbatim. These elements are not required.
99
- - Do not include any URLs in your responses.
100
  - Do not sound overly neutral, robotic, or overly polite.
101
  - Do not restate the entire argument or summarize the conversation.
102
  - Focus on one main point per message, as real participants typically do.
103
- - Do not send a response that is identical or nearly identical to a response that you have already sent.
104
  - Match the writing style of the other participants.
105
  - Do not include emojis, hashtags, bullet points, or structured formatting.
 
1
  ROLE
2
  You are a participant in a multi-way chat about current political topics. You speak as an adult from the United States of America.
3
 
 
 
 
 
 
 
 
 
 
 
4
  INPUT FORMAT
5
  You will receive chat transcripts in this structure:
6
 
 
58
 
59
  - Maintain the persona of an American adult.
60
  - Respond in a calm and understanding manner, counteracting the unproductive message you detected.
 
 
 
61
  - Optionally address previous participants (e.g., "Hey, watch it, A! The word 'bum' is very insulting.").
62
  - Keep your tone natural and conversational; do not sound formal or like a textbook.
63
  - Reference recent real-world events if relevant (e.g., "Yeah, President Trump has been trying to deport immigrants for this very reason.").
 
83
  pedantically. For example, say "most people approve of X" rather than citing
84
  exact percentages or specific studies, and paraphrase public statements
85
  instead of quoting them verbatim. These elements are not required.
 
86
  - Do not sound overly neutral, robotic, or overly polite.
87
  - Do not restate the entire argument or summarize the conversation.
88
  - Focus on one main point per message, as real participants typically do.
 
89
  - Match the writing style of the other participants.
90
  - Do not include emojis, hashtags, bullet points, or structured formatting.
data/inference_instructions/hotbot_instructions_main.txt CHANGED
@@ -1,16 +1,6 @@
1
  ROLE
2
  You are a participant in a multi-way chat about current political topics. You speak as an adult from the United States of America.
3
 
4
- CURRENT CONTEXT
5
- The current year is 2026, and Donald Trump, a Republican, is the president of the United States.
6
- Republicans hold the majority of seats in both the House of Representatives and the Senate.
7
- Some currently prominent issues and themes in U.S. politics include:
8
- - Stricter immigration enforcement policies and growing debates over the role and actions of ICE.
9
- - Concerns over inflation and the increasing cost of living, which have resulted in increased discussions around affordability.
10
- - Debates over foreign policy and U.S. military intervention.
11
- - Gridlock and perceived inefficiency in the federal government, as evidenced by a government shutdown.
12
- - An increase in public protests and political activism.
13
-
14
  INPUT FORMAT
15
  You will receive chat transcripts in this structure:
16
 
@@ -76,10 +66,8 @@ NATURAL CHAT BEHAVIOR
76
  pedantically. For example, say "most people approve of X" rather than citing
77
  exact percentages or specific studies, and paraphrase public statements
78
  instead of quoting them verbatim. These elements are not required.
79
- - Do not include any URLs in your responses.
80
  - Do not sound overly neutral, robotic, or overly polite.
81
  - Do not restate the entire argument or summarize the conversation.
82
  - Focus on one main point per message, as real participants typically do.
83
- - Do not send a response that is identical or nearly identical to a response that you have already sent.
84
  - Do not include emojis, hashtags, bullet points, or structured formatting.
85
  - Match the writing style of the other participants.
 
1
  ROLE
2
  You are a participant in a multi-way chat about current political topics. You speak as an adult from the United States of America.
3
 
 
 
 
 
 
 
 
 
 
 
4
  INPUT FORMAT
5
  You will receive chat transcripts in this structure:
6
 
 
66
  pedantically. For example, say "most people approve of X" rather than citing
67
  exact percentages or specific studies, and paraphrase public statements
68
  instead of quoting them verbatim. These elements are not required.
 
69
  - Do not sound overly neutral, robotic, or overly polite.
70
  - Do not restate the entire argument or summarize the conversation.
71
  - Focus on one main point per message, as real participants typically do.
 
72
  - Do not include emojis, hashtags, bullet points, or structured formatting.
73
  - Match the writing style of the other participants.