diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..7a284c6b03d55053517c0975d0c1e738aa5d8e3b Binary files /dev/null and b/.DS_Store differ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..13566b81b018ad684f3a35fee301741b2734c8f4 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/aws.xml b/.idea/aws.xml new file mode 100644 index 0000000000000000000000000000000000000000..56a6c7fe8fedb9872b34d5a4fbe8ac83136bfba8 --- /dev/null +++ b/.idea/aws.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000000000000000000000000000000000000..6c71566856503efcc2c7bd2522e14310ecb299b8 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..105ce2da2d6447d11dfe32bfb846c3d5b199fc99 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..ad4b73b267859eec1e6ccfa24aacff6d37c82308 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..973c9a66b236b0e5560521d226803d5a7ebf8899 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/wrAIte.iml b/.idea/wrAIte.iml new file mode 100644 index 0000000000000000000000000000000000000000..2cd169ccc51fff211554628b8eea2ae46b430003 --- /dev/null +++ b/.idea/wrAIte.iml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 99de7547c272094cd30b479bd2631c08ee515642..4174b86e2a57d367199355dbea2e2d0a168d522f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ --- title: WrAIte -emoji: 🏃 -colorFrom: gray -colorTo: pink +emoji: 📉 +colorFrom: pink +colorTo: blue sdk: gradio sdk_version: 4.28.3 app_file: app.py @@ -10,3 +10,12 @@ pinned: false --- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference + + +# Setup + +## Create and activate virtual environment +1. Create venv in writingmate directory: `python3 -m venv venv` +2. Activate virtual environment: `source venv/bin/activate` +## Install requirements +`pip3 install -r requirements.txt` \ No newline at end of file diff --git a/__pycache__/constants.cpython-311.pyc b/__pycache__/constants.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..80115f36c4a331dd7466a400e5bd9f097b73c26e Binary files /dev/null and b/__pycache__/constants.cpython-311.pyc differ diff --git a/__pycache__/data_storage.cpython-311.pyc b/__pycache__/data_storage.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb5975b28cc9f8a7fff5fad7833738f93943aab3 Binary files /dev/null and b/__pycache__/data_storage.cpython-311.pyc differ diff --git a/__pycache__/experiment_details.cpython-311.pyc b/__pycache__/experiment_details.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ccba73c7f09b92d1a62583c7cabda7ff47732d2d Binary files /dev/null and b/__pycache__/experiment_details.cpython-311.pyc differ diff --git a/__pycache__/model_generate.cpython-311.pyc b/__pycache__/model_generate.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6c97e77a6eab43633f0b28464978e535485ad17a Binary files /dev/null and b/__pycache__/model_generate.cpython-311.pyc differ diff --git a/__pycache__/pymongo_get_database.cpython-311.pyc b/__pycache__/pymongo_get_database.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bdd066fc5b02a7eb758cb9d921bead2daf49017b Binary files /dev/null and b/__pycache__/pymongo_get_database.cpython-311.pyc differ diff --git a/__pycache__/questionnaire.cpython-311.pyc b/__pycache__/questionnaire.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8146390f1daf443e1e15d3bf6693150827d78e4c Binary files /dev/null and b/__pycache__/questionnaire.cpython-311.pyc differ diff --git a/__pycache__/utils.cpython-311.pyc b/__pycache__/utils.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b2fe2213df9c053cb139ca04a32c6a9dbdf2ab7 Binary files /dev/null and b/__pycache__/utils.cpython-311.pyc differ diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..7b09ff9f2e42fd5aa40333682cc9ca593ea53564 --- /dev/null +++ b/app.py @@ -0,0 +1,311 @@ +import json +import os +import gradio as gr +from matplotlib import pyplot as plt + +from pymongo_get_database import MongoDBManager +from utils import process_markdown, save_answer, randomly_select_prompts, generate_unassisted_question, \ + generate_assisted_question, randomize_questions + +from experiment_details import problem_topics, problems_per_topic, writing_skills_questions +from questionnaire import generate_questionnaire +from data import problems +from datetime import datetime +from data_storage import store_user_data +import uuid + +mongo_manager = MongoDBManager() + +user_id = str(uuid.uuid4()) +mongo_manager.create_user_record(user_id) +# radio button and button rendering: https://www.gradio.app/docs/radio +questionnaire_results = { + 'Demographic Details': {}, + 'User Capabilities': {}, + 'Relationship to System': {}, + 'System Output Preferences': {} +} +question_answers = { + 'q1': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, + 'q2': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, + 'q3': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, + 'q4': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, + 'q5': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, + 'q6': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, + 'q7': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, + 'q8': { + 'Response': None, + 'Assistance': None, + 'CompletionTime': None, + 'StartTime': None, + 'EndTime': None + }, +} + +with gr.Blocks(title="wrAIte") as demo: + with gr.Column("Survey Complete", render=True, visible=False) as completed_screen: + instr_complete = process_markdown(False, 'instr_completed.md') + survey_complete = gr.Markdown(value=instr_complete) + + questionnaire = generate_questionnaire(questionnaire_results, completed_screen, user_id) + questionnaire.render() + + with gr.Column("", render=True, visible=False) as assessment: + selected_questions = randomly_select_prompts() + question_prompts = randomize_questions(selected_questions) + + + def next_q8(): + question_answers['q8']['EndTime'] = datetime.now().isoformat() + question_answers['q8']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q8']['EndTime']) - + datetime.fromisoformat(question_answers['q8']['StartTime'])) + store_user_data(user_id, "questions", question_answers) + mongo_manager.update_question_answers(user_id, question_answers) + return { + question8: gr.update(visible=False), + questionnaire: gr.update(visible=True) + } + + + def next_q7(): + question_answers['q7']['EndTime'] = datetime.now().isoformat() + question_answers['q7']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q7']['EndTime']) - + datetime.fromisoformat(question_answers['q7']['StartTime'])) + question_answers['q8']['StartTime'] = datetime.now().isoformat() + return { + question7: gr.update(visible=False), + question8: gr.update(visible=True) + } + + + def next_q6(): + question_answers['q6']['EndTime'] = datetime.now().isoformat() + question_answers['q6']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q6']['EndTime']) - + datetime.fromisoformat(question_answers['q6']['StartTime'])) + question_answers['q7']['StartTime'] = datetime.now().isoformat() + return { + question6: gr.update(visible=False), + question7: gr.update(visible=True) + } + + + def next_q5(): + question_answers['q5']['EndTime'] = datetime.now().isoformat() + question_answers['q5']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q5']['EndTime']) - + datetime.fromisoformat(question_answers['q5']['StartTime'])) + question_answers['q6']['StartTime'] = datetime.now().isoformat() + return { + question5: gr.update(visible=False), + question6: gr.update(visible=True) + } + + + def next_q4(): + question_answers['q4']['EndTime'] = datetime.now().isoformat() + question_answers['q4']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q4']['EndTime']) - + datetime.fromisoformat(question_answers['q4']['StartTime'])) + question_answers['q5']['StartTime'] = datetime.now().isoformat() + return { + question4: gr.update(visible=False), + question5: gr.update(visible=True) + } + + + def next_q3(): + question_answers['q3']['EndTime'] = datetime.now().isoformat() + question_answers['q3']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q3']['EndTime']) - + datetime.fromisoformat(question_answers['q3']['StartTime'])) + question_answers['q4']['StartTime'] = datetime.now().isoformat() + return { + question3: gr.update(visible=False), + question4: gr.update(visible=True) + } + + + def next_q2(): + question_answers['q2']['EndTime'] = datetime.now().isoformat() + question_answers['q2']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q2']['EndTime']) - + datetime.fromisoformat(question_answers['q2']['StartTime'])) + question_answers['q3']['StartTime'] = datetime.now().isoformat() + return { + question2: gr.update(visible=False), + question3: gr.update(visible=True) + } + + + def next_q1(): + question_answers['q1']['EndTime'] = datetime.now().isoformat() + question_answers['q1']['CompletionTime'] = str(datetime.fromisoformat(question_answers['q1']['EndTime']) - + datetime.fromisoformat(question_answers['q1']['StartTime'])) + question_answers['q2']['StartTime'] = datetime.now().isoformat() + return { + question1: gr.update(visible=False), + question2: gr.update(visible=True) + } + + + with gr.Column("Question 8", render=True, visible=False) as question8: + next_q8_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q8 = generate_assisted_question(question_prompts[7], next_q8_btn, 8, question_answers) + q8.render() + next_q8_btn.render() + next_q8_btn.click( + fn=next_q8, + inputs=[], + outputs=[question8, questionnaire] + ) + with gr.Column("Question 7", render=True, visible=False) as question7: + next_q7_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q7 = generate_unassisted_question(question_prompts[6], next_q7_btn, 7, question_answers) + q7.render() + next_q7_btn.render() + next_q7_btn.click( + fn=next_q7, + inputs=[], + outputs=[question7, question8] + ) + with gr.Column("Question 6", render=True, visible=False) as question6: + next_q6_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q6 = generate_unassisted_question(question_prompts[5], next_q6_btn, 6, question_answers) + q6.render() + next_q6_btn.render() + next_q6_btn.click( + fn=next_q6, + inputs=[], + outputs=[question6, question7] + ) + with gr.Column("Question 5", render=True, visible=False) as question5: + next_q5_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q5 = generate_unassisted_question(question_prompts[4], next_q5_btn, 5, question_answers) + q5.render() + next_q5_btn.render() + next_q5_btn.click( + fn=next_q5, + inputs=[], + outputs=[question5, question6] + ) + with gr.Column("Question 4", render=True, visible=False) as question4: + next_q4_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q4 = generate_assisted_question(question_prompts[3], next_q4_btn, 4, question_answers) + q4.render() + next_q4_btn.render() + next_q4_btn.click( + fn=next_q4, + inputs=[], + outputs=[question4, question5] + ) + with gr.Column("Question 3", render=True, visible=False) as question3: + next_q3_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q3 = generate_unassisted_question(question_prompts[2], next_q3_btn, 3, question_answers) + q3.render() + next_q3_btn.render() + next_q3_btn.click( + fn=next_q3, + inputs=[], + outputs=[question3, question4] + ) + with gr.Column("Question 2", render=True, visible=False) as question2: + next_q2_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q2 = generate_assisted_question(question_prompts[1], next_q2_btn, 2, question_answers) + q2.render() + next_q2_btn.render() + next_q2_btn.click( + fn=next_q2, + inputs=[], + outputs=[question2, question3] + ) + with gr.Column("Question 1", render=True, visible=True) as question1: + next_q1_btn = gr.Button("Next Question", render=False, visible=False, variant="primary") + q1 = generate_unassisted_question(question_prompts[0], next_q1_btn, 1, question_answers) + q1.render() + next_q1_btn.render() + next_q1_btn.click( + fn=next_q1, + inputs=[], + outputs=[question1, question2] + ) + + def start_assessment(): + question_answers['q1']['StartTime'] = datetime.now().isoformat() + return { + welcome_pg: gr.update(visible=False), + assessment: gr.update(visible=True) + } + + with gr.Column("Welcome to wrAIte", visible=True) as welcome_pg: + welcome_instr = process_markdown(False, 'instr_welcome.md') + welcome_text = gr.Markdown(value=welcome_instr, visible=True) + welcome_continue_btn = gr.Button("Continue", variant="primary", visible=True) + + study_instr = process_markdown(False, 'instr_study.md') + study_text = gr.Markdown(value=study_instr, visible=False) + study_continue_btn = gr.Button("Begin Study", variant="primary", visible=False) + + + def show_study_instructions(): + return { + welcome_text: gr.update(visible=False), + welcome_continue_btn: gr.update(visible=False), + study_text: gr.update(visible=True), + study_continue_btn: gr.update(visible=True), + } + + + welcome_continue_btn.click( + fn=show_study_instructions, + inputs=[], + outputs=[welcome_text, welcome_continue_btn, study_text, study_continue_btn] + ) + + study_continue_btn.click( + fn=start_assessment, + inputs=[], + outputs=[welcome_pg, assessment] + ) + + +# if __name__ == "__main__": +# demo.launch() +demo.launch(share=True) diff --git a/constants.py b/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..4671e1c0191e60c3beceea418455ec70605a12bf --- /dev/null +++ b/constants.py @@ -0,0 +1,23 @@ +MAX_CONVERSATION_LENGTH = 20 +MAX_TOKENS_PER_GENERATION = 512 +SAMPLING_TEMPERATURE = 0. + +plaintxt_instructions = [ + ["Welcome to our study!", + "In this task, you will be interacting with AI systems to explore how well AI systems can assist in various writing tasks.", + "Your responses will inform AI, writing, and potentially human-computer interaction research.", + "By participating in this study, you consent to having your responses stored and used for publication.", + "Your email and other identifying information (beyond level of mathematical expertise) will not be stored.", + "Please only continue if you are comfortable with the above."], + [ + "In this study, you will be posed with writing tasks (e.g., theorems) and asked to evaluate how good different AI systems are at helping to assist in that writing task.", + "You may evaluate a maximum of four problems (two sets of two writing tasks over the two models). You will be given a writing task per writing challenge (e.g. creative short story writing, informative email writing).", + "Note: You will be assisted based on your initial responses to our preliminary questions."] +] + +model_options = [ + "chatgpt", + "instructgpt", + "chatgpt4" +] + diff --git a/data/.DS_Store b/data/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..277afb7b67dea25d2c073d21815b89fe64c24631 Binary files /dev/null and b/data/.DS_Store differ diff --git a/data/__init__.py b/data/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/data/__pycache__/__init__.cpython-311.pyc b/data/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26f58af30f30900ffb7cc293fa32e7784265eeb5 Binary files /dev/null and b/data/__pycache__/__init__.cpython-311.pyc differ diff --git a/data/instructions/instr_assisted.md b/data/instructions/instr_assisted.md new file mode 100644 index 0000000000000000000000000000000000000000..643b680bca15d9df86fc809913952802c758fb32 --- /dev/null +++ b/data/instructions/instr_assisted.md @@ -0,0 +1 @@ +## Please read the instructions below. Interact with the writing helper to explore how it may assist you in answering the following prompt. Write your response in the following text box. \ No newline at end of file diff --git a/data/instructions/instr_completed.md b/data/instructions/instr_completed.md new file mode 100644 index 0000000000000000000000000000000000000000..c4b1166a9a5bebb16da5adede3068281aaf1a56a --- /dev/null +++ b/data/instructions/instr_completed.md @@ -0,0 +1 @@ +## Thank you! You have successfully completed this survey. \ No newline at end of file diff --git a/data/instructions/instr_editresponse.md b/data/instructions/instr_editresponse.md new file mode 100644 index 0000000000000000000000000000000000000000..89c12d26855b4daf60c778633546af5bcd9be64a --- /dev/null +++ b/data/instructions/instr_editresponse.md @@ -0,0 +1 @@ +### To edit your response, please click the button below. You will no longer be able to edit the previous question once you proceed. \ No newline at end of file diff --git a/data/instructions/instr_email.md b/data/instructions/instr_email.md new file mode 100644 index 0000000000000000000000000000000000000000..0afc23092cf77bcd5c4378aba8a8235eb0b7a4ea --- /dev/null +++ b/data/instructions/instr_email.md @@ -0,0 +1 @@ +## Instructions: Write an email for the following scenario in under 300 words. \ No newline at end of file diff --git a/data/instructions/instr_proceed.md b/data/instructions/instr_proceed.md new file mode 100644 index 0000000000000000000000000000000000000000..85736783c76e499d53b2545a11f095ef0db8fcc9 --- /dev/null +++ b/data/instructions/instr_proceed.md @@ -0,0 +1 @@ +## Please click on the button below to proceed to the next question. \ No newline at end of file diff --git a/data/instructions/instr_questionnaire.md b/data/instructions/instr_questionnaire.md new file mode 100644 index 0000000000000000000000000000000000000000..9f7cabf64f91f024f3d729551fa075d19d81fc6b --- /dev/null +++ b/data/instructions/instr_questionnaire.md @@ -0,0 +1,2 @@ +# Post-Assesment Questionnaire +## Please answer all of the questions below as objectively as you can. \ No newline at end of file diff --git a/data/instructions/instr_shortstory.md b/data/instructions/instr_shortstory.md new file mode 100644 index 0000000000000000000000000000000000000000..10b4cbb074696fbd5a614249f434c281632e1284 --- /dev/null +++ b/data/instructions/instr_shortstory.md @@ -0,0 +1 @@ +## Instructions: Write a short story (300 words or less) which only uses very simple words. \ No newline at end of file diff --git a/data/instructions/instr_study.md b/data/instructions/instr_study.md new file mode 100644 index 0000000000000000000000000000000000000000..939569a127a934010f9ab0c5bf326e96c6cb7c2d --- /dev/null +++ b/data/instructions/instr_study.md @@ -0,0 +1,7 @@ +## In this study, you will be posed with eight (8) writing prompts and asked to write a response to each of them. +## You will be given AI assistance for some prompts, and you will need to respond to others on your own. +## There will be a total of 4 writing categories (creative short story writing, informative email writing, title generation, and summarization). For each category you will be answering one assisted prompt and one unassisted prompt. +## +## After you finish answering the writing prompts, you will complete a questionnaire regarding your background information, writing skills, and experience interacting with LLMs (Large Language Models). +## +## Click the button below when you are ready to begin the study. \ No newline at end of file diff --git a/data/instructions/instr_submitsuccess.md b/data/instructions/instr_submitsuccess.md new file mode 100644 index 0000000000000000000000000000000000000000..d505d2d2834095a4b0d2ccb1d146da1c65af18f0 --- /dev/null +++ b/data/instructions/instr_submitsuccess.md @@ -0,0 +1 @@ +## The following response has been successfully submitted: \ No newline at end of file diff --git a/data/instructions/instr_summary.md b/data/instructions/instr_summary.md new file mode 100644 index 0000000000000000000000000000000000000000..f91bae91a473ea93e8bc7180c3a88fdebc5a841c --- /dev/null +++ b/data/instructions/instr_summary.md @@ -0,0 +1 @@ +## Instructions: Summarize the following article in 100 words or less. \ No newline at end of file diff --git a/data/instructions/instr_title.md b/data/instructions/instr_title.md new file mode 100644 index 0000000000000000000000000000000000000000..25edd2d17aaf8f3cf7bff1ca094f295327d69666 --- /dev/null +++ b/data/instructions/instr_title.md @@ -0,0 +1 @@ +## Instructions: Write a creative title for the following article using 10 words or less. \ No newline at end of file diff --git a/data/instructions/instr_unassisted.md b/data/instructions/instr_unassisted.md new file mode 100644 index 0000000000000000000000000000000000000000..2f902d943a34d75f2cebe17b778bb8372d45b2de --- /dev/null +++ b/data/instructions/instr_unassisted.md @@ -0,0 +1 @@ +## Please read the instructions and writing prompt below. Write your response in the following text box. \ No newline at end of file diff --git a/data/instructions/instr_welcome.md b/data/instructions/instr_welcome.md new file mode 100644 index 0000000000000000000000000000000000000000..be3a35e32b911fca1e11f0023920c6a0bb87938a --- /dev/null +++ b/data/instructions/instr_welcome.md @@ -0,0 +1,7 @@ +## Welcome to our study! + +## In this task, you will be interacting with AI systems to explore how well AI systems can assist in answering writing prompts. +## Your responses will inform AI, writing, and potentially human-computer interaction research. +## By participating in this study, you consent to having your responses stored and used for publication. +## Your email and other identifying information (beyond level of writing expertise) will not be stored. +## Please only continue if you are comfortable with the above. diff --git a/data/problems/p_email1.md b/data/problems/p_email1.md new file mode 100644 index 0000000000000000000000000000000000000000..5062b028537188580e65f1a9eac788a98d9335ca --- /dev/null +++ b/data/problems/p_email1.md @@ -0,0 +1 @@ +### You are organizing an outdoor team-building event aimed at improving team communication. Draft an email inviting colleagues, including details like date, time, and activities in your email. \ No newline at end of file diff --git a/data/problems/p_email10.md b/data/problems/p_email10.md new file mode 100644 index 0000000000000000000000000000000000000000..54fc1af7a3ec92386f49fdd1e6e3582c76313aa9 --- /dev/null +++ b/data/problems/p_email10.md @@ -0,0 +1 @@ +### You wish to receive guidance from a more experienced person in your company. Write an email to someone at your company that you admire, explaining your current position, your career goals, and politely asking if they would be willing to mentor you. \ No newline at end of file diff --git a/data/problems/p_email2.md b/data/problems/p_email2.md new file mode 100644 index 0000000000000000000000000000000000000000..8cf354f44ad7982095ae033fbf643dd0b648bdbf --- /dev/null +++ b/data/problems/p_email2.md @@ -0,0 +1 @@ +### You recently ordered a coffee maker online, CoffeeCreate 3.0, which arrived defective. Compose an email to CoffeeCreate to complain about your purchase, asking for a replacement or refund and mentioning that it won't turn on despite troubleshooting. diff --git a/data/problems/p_email3.md b/data/problems/p_email3.md new file mode 100644 index 0000000000000000000000000000000000000000..2818634eae0ab7983dde755221ebda9832617134 --- /dev/null +++ b/data/problems/p_email3.md @@ -0,0 +1 @@ +### You are planning a surprise birthday party for a friend and need a venue. Write an email to a local community center named City LCC inquiring about the availability of rooms for the event, including details on capacity and pricing. diff --git a/data/problems/p_email4.md b/data/problems/p_email4.md new file mode 100644 index 0000000000000000000000000000000000000000..20972f5b8ef500a7be4b64af823bc465ae889b44 --- /dev/null +++ b/data/problems/p_email4.md @@ -0,0 +1 @@ +### Your party decoration order purchase from Decor Co. was supposed to arrive last week but hasn't come yet. Compose an email to Decor Co. asking about the status of your order and expressing the urgency of receiving it. \ No newline at end of file diff --git a/data/problems/p_email5.md b/data/problems/p_email5.md new file mode 100644 index 0000000000000000000000000000000000000000..5839b9508930482526644226c59e87a7ac7d8a7e --- /dev/null +++ b/data/problems/p_email5.md @@ -0,0 +1 @@ +### After receiving career advice during a one-on-one session, write a thank-you email to your mentor, expressing your appreciation and discussing key takeaways, such as recommended training courses and networking strategies. \ No newline at end of file diff --git a/data/problems/p_email6.md b/data/problems/p_email6.md new file mode 100644 index 0000000000000000000000000000000000000000..50c8d1658d3bc7716299146c56f9d2e920c623e5 --- /dev/null +++ b/data/problems/p_email6.md @@ -0,0 +1 @@ +### You have been subscribed to a monthly gourmet snack delivery service, MonthlySnacks. While you enjoyed the deliveries, they don't fit your budget anymore. Write an email to the MonthlySnacks requesting the cancellation of your monthly subscription, including your financial reasons. \ No newline at end of file diff --git a/data/problems/p_email7.md b/data/problems/p_email7.md new file mode 100644 index 0000000000000000000000000000000000000000..f076af82cba1d2f6231bfadc5fa5d96a97d54d3c --- /dev/null +++ b/data/problems/p_email7.md @@ -0,0 +1 @@ +### You recently read a blog post on the impact of seasonal ingredients on cooking. You noticed that it did not include some key spices that could enhance the flavors further. Write an email to the food blog author providing constructive feedback, suggesting the inclusion of these spices and asking about their personal favorite seasonal recipes. \ No newline at end of file diff --git a/data/problems/p_email8.md b/data/problems/p_email8.md new file mode 100644 index 0000000000000000000000000000000000000000..e35fdab274ec748101a35ad70a54ff5d7e733cc4 --- /dev/null +++ b/data/problems/p_email8.md @@ -0,0 +1 @@ +### You have noticed your colleague often schedules meetings and cancels at the last minute, which has been frustrating for you. Write an email to express your feelings clearly and respectfully. \ No newline at end of file diff --git a/data/problems/p_email9.md b/data/problems/p_email9.md new file mode 100644 index 0000000000000000000000000000000000000000..dae02eb3b3e972bada82ff14ab066714046cf797 --- /dev/null +++ b/data/problems/p_email9.md @@ -0,0 +1 @@ +### You are interested in attending an upcoming seminar on leadership and personal development that is highly relevant to your current role. Write an email to the seminar organizers asking for more details about the topics to be covered, the speakers, and the registration process. \ No newline at end of file diff --git a/data/problems/p_shortstory1.md b/data/problems/p_shortstory1.md new file mode 100644 index 0000000000000000000000000000000000000000..f791ce327544dcef86f558373c5bc7b87225509a --- /dev/null +++ b/data/problems/p_shortstory1.md @@ -0,0 +1 @@ +## The story should use the verb "hang", the noun "foot" and the adjective "cute". The story should contain at least one dialogue. \ No newline at end of file diff --git a/data/problems/p_shortstory10.md b/data/problems/p_shortstory10.md new file mode 100644 index 0000000000000000000000000000000000000000..95a05c0927dd30f570e25e7a63c7f6a52375ee01 --- /dev/null +++ b/data/problems/p_shortstory10.md @@ -0,0 +1 @@ + ## The story should use the verb "jog", the noun "purple" and the adjective "noisy". The story should contain at least one dialogue, have a bad ending, and have a moral value. \ No newline at end of file diff --git a/data/problems/p_shortstory2.md b/data/problems/p_shortstory2.md new file mode 100644 index 0000000000000000000000000000000000000000..0ecfe22ec85b72a819d03a6d8bdacc88cf6d2abd --- /dev/null +++ b/data/problems/p_shortstory2.md @@ -0,0 +1 @@ +## In the story, try to at some point use the verb "hope", the noun "search" and the adjective "comfortable". \ No newline at end of file diff --git a/data/problems/p_shortstory3.md b/data/problems/p_shortstory3.md new file mode 100644 index 0000000000000000000000000000000000000000..1f19c2963a72bc3c9a3521baa03a58b458a15870 --- /dev/null +++ b/data/problems/p_shortstory3.md @@ -0,0 +1 @@ +## In the story, try to at some point use the verb "pull", the noun "idea" and the adjective "sad". The story should also have a bad ending. \ No newline at end of file diff --git a/data/problems/p_shortstory4.md b/data/problems/p_shortstory4.md new file mode 100644 index 0000000000000000000000000000000000000000..e4023d428c10d44659e924f70e454b74d666a2d8 --- /dev/null +++ b/data/problems/p_shortstory4.md @@ -0,0 +1 @@ +## The story should use the verb "say", the noun "herb" and the adjective "shy". \ No newline at end of file diff --git a/data/problems/p_shortstory5.md b/data/problems/p_shortstory5.md new file mode 100644 index 0000000000000000000000000000000000000000..83a61e4b4c9d5165229582d280295093d1ea2018 --- /dev/null +++ b/data/problems/p_shortstory5.md @@ -0,0 +1,2 @@ +## The story should use the verb "whistle", the noun "igloo" and the adjective "cheap". +## The story should use the verb "mention", the noun "library" and the adjective "lonely". Something unexpected should happen or there should be a plot twist. \ No newline at end of file diff --git a/data/problems/p_shortstory6.md b/data/problems/p_shortstory6.md new file mode 100644 index 0000000000000000000000000000000000000000..954fbe1f052869e902c3e7539c12b82a9739c9e9 --- /dev/null +++ b/data/problems/p_shortstory6.md @@ -0,0 +1 @@ +## In the story, try to at some point use the verb "rush", the noun "animal" and the adjective "blue". The story should contain at least one dialogue, and it should have a bad ending. \ No newline at end of file diff --git a/data/problems/p_shortstory7.md b/data/problems/p_shortstory7.md new file mode 100644 index 0000000000000000000000000000000000000000..a9685adab0f7765d52c8eb8986c898271488fa83 --- /dev/null +++ b/data/problems/p_shortstory7.md @@ -0,0 +1 @@ +## The story should use the verb "display", the noun "whistle" and the adjective "fierce". The story should use foreshadowing or setup and payoff. \ No newline at end of file diff --git a/data/problems/p_shortstory8.md b/data/problems/p_shortstory8.md new file mode 100644 index 0000000000000000000000000000000000000000..67d15aeb67b3e0d44d817e811cf7397d309d33c9 --- /dev/null +++ b/data/problems/p_shortstory8.md @@ -0,0 +1 @@ +## In the story, try to at some point use the verb "roar", the noun "zip" and the adjective "thoughtful". The story should contain at least one dialogue, and it should have a bad ending. \ No newline at end of file diff --git a/data/problems/p_shortstory9.md b/data/problems/p_shortstory9.md new file mode 100644 index 0000000000000000000000000000000000000000..d9a2712d91ac2d5719f3616306461df82d8470a2 --- /dev/null +++ b/data/problems/p_shortstory9.md @@ -0,0 +1 @@ +## The story should use the verb "strike", the noun "bin" and the adjective "empty". The narrative should use foreshadowing or setup and payoff. \ No newline at end of file diff --git a/data/problems/p_summary1.md b/data/problems/p_summary1.md new file mode 100644 index 0000000000000000000000000000000000000000..fe90750a4582afd692d9e97fe8ec4b2238bee9ac --- /dev/null +++ b/data/problems/p_summary1.md @@ -0,0 +1,7 @@ +### Spike Lee backs student directors + +Film-maker Spike Lee says black representation is stronger than ever in cinema and TV but the true power in entertainment lies behind the camera. + +The She Hate Me director urged students at his old Atlanta university, Morehouse College, to seek "gatekeeper positions" behind the scenes. Lee told them to "work up the corporate ladder because everybody can't be an actor, everybody can't make a record". He spoke as part of a discussion panel, then led a retrospective of his films. + +Returning to his old university, which educates only African American students, Lee discussed the challenges facing black people in the entertainment industry. "Even Denzel (Washington), he's getting $20m a movie. But when it comes time to do a movie, he has to go to one of those gatekeepers," Lee said. He told aspiring young film-makers in the audience not to ignore non-traditional routes to getting a movie made, including raising funds independently and releasing films straight to DVD. "It's a huge market," the 47-year-old director said. "It's not something that should be looked upon as a stepchild." Lee has made more than 25 films, including Jungle Fever, Do the Right Thing, Summer of Sam and 1986 hit She's Gotta Have It. diff --git a/data/problems/p_summary10.md b/data/problems/p_summary10.md new file mode 100644 index 0000000000000000000000000000000000000000..3c3a30912d0bfe5ae6bcddfa90f0708895be2552 --- /dev/null +++ b/data/problems/p_summary10.md @@ -0,0 +1,6 @@ +### De Niro film leads US box office +Film star Robert De Niro has returned to the top of the North American box office with his film Hide and Seek. + +The thriller shot straight to the number one spot after taking $22m (£11.7m) at the box office. De Niro recently spent three weeks at the top with comedy Meet The Fockers, which was at number five this week. Oscar hopefuls The Aviator, Million Dollar Baby and Sideways all cashed in on their multiple nominations with stronger ticket sales. + +In Hide and Seek, De Niro plays a widower whose daughter has a creepy imaginary friend. Despite lukewarm reviews from critics, the film took more than the expected $18m (£9.5m). "The element of a real actor in a psychological thriller certainly elevated it," said Bruce Snyder, president of domestic distribution at 20th Century Fox. Clint Eastwood's Million Dollar Baby led the Oscar hopefuls with $11.8m (£6.3m), coming in at number three during its first weekend of wide release. The Aviator, a film biography of Howard Hughes that leads the Oscar field with 11 nominations, was at number six for the weekend with $7.5m (£4m). Oscar best-picture nominee Sideways entered the top ten for the first time in its 15th week of release. It came in seventh $6.3 (£3.35m). Last week's top film, Ice Cube's road-trip comedy Are We There Yet?, slipped to second place with $17m (£9m), while Coach Carter fell two places to number four, taking $8m (£4.25m) in its third week. Rounding out the top ten were In Good Company - starring Dennis Quaid and Scarlett Johansson - Racing Stripes and Assault on Precinct 13. \ No newline at end of file diff --git a/data/problems/p_summary2.md b/data/problems/p_summary2.md new file mode 100644 index 0000000000000000000000000000000000000000..5aaf67763724951ead86353bf7a72bc056dede83 --- /dev/null +++ b/data/problems/p_summary2.md @@ -0,0 +1,9 @@ +### Famed music director Viotti dies + +Conductor Marcello Viotti, director of Venice's famous La Fenice Theatre, has died in Germany at 50. + +Viotti, director of La Fenice since 2002, conducted at renowned opera houses worldwide including Milan's La Scala and the Vienna State Opera. His time at La Fenice coincided with its reopening in 2003 after it was destroyed by fire in 1996. He fell into a coma after suffering a stroke during rehearsals for Jules Massenet's Manon last week. + +He conducted some of the best orchestras in the world including the Berlin Philharmonic and the English Chamber Orchestra. Viotti was born in Switzerland and studied the piano, cello and singing at the Lausanne Conservatory. His career breakthrough came in 1982 when he won first prize at the Gino Marinuzzi conducting competition in Italy. Viotti established himself as chief conductor of the Turin Opera and went on to become chief conductor of Munich's Radio Orchestra. At La Fenice Viotti was widely acclaimed for his production of the French composer Massenet's Thais and some of his other productions included Giuseppe Verdi's La Traviata and Richard Strauss's Ariadne auf Naxos. + +The last opera he directed at La Fenice was Massenet's Le Roi de Lahore. Viotti's debut at the New York's Metropolitan Opera came in 2000 with Giacomo Puccini's Madame Butterfly, followed by La Boheme, La Traviata and Fromental Halevy's La Juive. Giampaolo Vianello, superintendent of the Fenice Theatre Foundation, said: "I am filled with extreme sadness because, other than a great artist, he is missed as a friend - a main character in the latest joyous times, during the rebirth of our theatre." Viotti's last public performance was on 5 February when he conducted Vincenzo Bellini's Norma at the Vienna State Opera. \ No newline at end of file diff --git a/data/problems/p_summary3.md b/data/problems/p_summary3.md new file mode 100644 index 0000000000000000000000000000000000000000..6e186a18966f93b1680a82f7ac79e971ca03726e --- /dev/null +++ b/data/problems/p_summary3.md @@ -0,0 +1,7 @@ +### New Harry Potter tops book chart + +Harry Potter and the Half-Blood Prince has topped Amazon's book chart less than 24 hours after its release date - 16 July - was announced. + +Thousands of customers placed pre-orders on the amazon.co.uk website for the sixth book in the series. Rowling revealed she had completed the novel on Tuesday, ahead of the scheduled announcement on 25 December. It will be published simultaneously in the UK, the US, Canada, Australia, New Zealand and South Africa. JK Rowling's fifth book in the wizard series, Harry Potter and Order of the Phoenix was Amazon's largest pre-ordered item ever, with 420,000 copies pre-ordered prior to its release in June 2003. Customers who pre-order Harry Potter and the Half-Blood Prince avoid standing in long queues at bookshops on the day of the book's release next July. "The fact that the book has already hit number one in our Hot 100 books chart shows how incredibly excited customers are about the sixth Harry Potter," said Amazon's Robin Terrell. + +Harry Potter and the Half-Blood Prince takes up the story of Harry Potter's sixth year at Hogwarts School of Witchcraft and Wizardry as Lord Voldemort grows stronger. Rowling has already revealed that the Half-Blood Prince is neither Harry nor Voldemort. And she added that the opening chapter of the book had been brewing in her mind for 13 years. Rowling said she had plenty of time while pregnant "to tinker with the manuscript to my satisfaction and I am as happy as I have ever been with the end result". She also previously revealed that a character will be killed in the sixth book, but she has given no hints as to who it might be. Following publication of the sixth book, just one novel remains to complete the series. \ No newline at end of file diff --git a/data/problems/p_summary4.md b/data/problems/p_summary4.md new file mode 100644 index 0000000000000000000000000000000000000000..705a3b62d7ebaa066f3161c39a9e507d247163da --- /dev/null +++ b/data/problems/p_summary4.md @@ -0,0 +1,9 @@ +### UK's National Gallery in the pink + +The National Gallery, home to some of the UK's greatest artworks, has seen a big jump in visitor numbers. + +Five million visitors made the London gallery - which houses treasures like Raphael's Madonna of the Pinks - the UK's most visited museum in 2004. It recorded a 13.8% rise in numbers and was the country's second most visited tourist attraction, behind Blackpool Pleasure Beach. Charles Saumarez Smith, the gallery's director, said he was "delighted". He said the number of visitors through the doors had boosted figures to pre-11 September 2001 levels. Mr Saumarez Smith added that the pedestrianisation of Trafalgar Square, where the gallery is located, and strong temporary collections throughout 2004 had led to the strong performance. + +"Our 2004 exhibition programme of El Greco, Russian Landscape in the Age of Tolstoy and Raphael: From Urbino to Rome was particularly strong and exceeded all targets," he said. "The exceptional quality of the paintings in our permanent collection is also huge draw for the public. "The expectations of today's visitors are higher than ever and we have kept pace with their demands." Mr Saumarez Smith said he was confident the gallery could maintain the attendance. "With important exhibitions of the work of Caravaggio, Stubbs and Rubens in place for 2005, I am confident that the gallery is set for another highly successful year," he added. The figures were prepared by the Association of Leading Visitor Attractions (Alva). + +It found that the figures had been boosted by an increase in Europeans travelling to the UK on budget airlines. Popular cultural tourist spots such as the Tate Modern and the Natural History Museum all recorded increases of more than 10% in visitor numbers compared with 2003. But for legal or confidentiality reasons some Alva members did not submit figures for 2004, including Buckingham Palace, Windsor Castle, Madame Tussauds and Alton Towers. Alva director Robin Broke said: "Visits from Western Europe were up by 10% and from North America by some 9% compared to 2003, while numbers from the rest of the world rose 20%. "European figures were helped by the rapid growth of low-cost flights to Britain from Europe, especially from new EU countries." \ No newline at end of file diff --git a/data/problems/p_summary5.md b/data/problems/p_summary5.md new file mode 100644 index 0000000000000000000000000000000000000000..6fb14f9480313136aea7cc499ee0ea88d70bdf38 --- /dev/null +++ b/data/problems/p_summary5.md @@ -0,0 +1,6 @@ +### Baghdad Blogger on big screen +A film based on the internet musings of the "Baghdad Blogger" has been shown at the Rotterdam Film Festival. + +The film has been directed by the man who calls himself Salam Pax, the author of the weblog about Iraqi life during and after the war. The movie version comes in the form of a series of shorts made by Pax on a hand-held camera. Baghdad Blogger is among a number of films about Iraq showcased at the Dutch festival, which runs until Sunday. Following the fascination with the writing of Salam Pax - not his real name - he began a regular column in The Guardian newspaper and was given a crash course in documentary film-making. For the film he travelled Iraq to document the changing landscape of the country and the problems it has faced since the invasion, speaking to ordinary Iraqis about their experiences. The festival will also see the screening of Underexposure, one of Iraq's first features to emerge since the toppling of Saddam Hussein. + +Director Oday Rasheed made the film on discarded 1980s Kodak film taken from the remains for the former Ministry of Culture building. It centres on the lives of families and strangers going about their everyday business as Baghdad is under siege. Rasheed said the title was refers to the isolation felt by Iraqis under Saddam's regime and the difficult time the country is now experiencing. "Saddam's regime was hell, but now I think the hell has doubled," Rasheed said. The festival was also due to screen murdered Dutch film-maker Theo Van Gogh's film about the treatment of woman under Islam, but it was withdrawn due to safety fears. Van Gogh was shot and stabbed in November 2004, following death threats he received about his film Submission. \ No newline at end of file diff --git a/data/problems/p_summary6.md b/data/problems/p_summary6.md new file mode 100644 index 0000000000000000000000000000000000000000..fdfe38bda38bd00763c8ba0a7356d0bcccabba25 --- /dev/null +++ b/data/problems/p_summary6.md @@ -0,0 +1,7 @@ +### Brando 'rejected Godfather role' + +Late film star Marlon Brando is said to have repeatedly turned down his Oscar-winning role in The Godfather. + +The actor's friend Budd Schulberg told Vanity Fair magazine that Brando's assistant suggested he read the novel. The actor repeatedly refused, throwing the book at her and saying: "For the last time, I won't glorify the mafia". But Brando, who died last July at the age of 80, eventually took the role of Don Corleone, winning him an Oscar in 1973 which he notoriously refused. The actor sent a young woman dressed in Native American costume to refuse the award on his behalf and to draw attention to the plight of Native Americans. + +Schulberg told the magazine that Brando's assistant realised the film star had warmed to the idea of The Godfather role when he sported a drawn-on pencil moustache and asked: "How do I look?" His assistant, Alice Marchak, said that he looked like George Raft, an actor famed for playing gangsters on the silver screen. Every time she went to see Brando from then on, she added, he was wearing a different gangster-style moustache. Brando was asked to screen test for the role in The Godfather, as studio executives were said to be reluctant for the actor to play the part following problems on the set of Brando's previous film Mutiny on the Bounty . In fact Brando's Academy Award triumph revived his career. The actor was nominated for an Oscar the following year for his role in Bernardo Bertolucci's Last Tango in Paris. Before his death, Brando granted gaming company Electronic Arts the rights to use his voice and image in a video game based on the Godfather film and book and recorded voice-overs which closely resembled his role as Don Corleone. Brando's co-stars from The Godfather, James Caan and Robert Duvall, will also reprise their roles for the video game, it was confirmed on Wednesday. diff --git a/data/problems/p_summary7.md b/data/problems/p_summary7.md new file mode 100644 index 0000000000000000000000000000000000000000..9a24a82e5875e5a3d34111ec4539358a04db456a --- /dev/null +++ b/data/problems/p_summary7.md @@ -0,0 +1,11 @@ +### Stars gear up for Bafta ceremony + +Film stars from across the globe are preparing to walk the red carpet at this year's Bafta award ceremony. + +The 2005 Orange British Academy Film Awards are being held at The Odeon in London's Leicester Square. A host of Hollywood stars, including Cate Blanchett, Leonardo DiCaprio, Keanu Reeves and Richard Gere, are expected to attend Saturday's ceremony. Hosted by Stephen Fry, the glittering ceremony will be broadcast on BBC One at 2010 GMT. + +Other actors expected to add to the glamour of the biggest night in UK film are Gael Garcia Bernal, Imelda Staunton, Diane Kruger, Christian Slater, Anjelica Huston, Helen Mirren and former James Bond star Pierce Brosnan. Hollywood blockbuster The Aviator, starring DiCaprio, leads the field with 14 nominations, including best film. + +It is up against Eternal Sunshine of the Spotless Mind, Finding Neverland, The Motorcycle Diaries and British film Vera Drake, which has 11 nominations. British hope Imelda Staunton is one of the favourites to land the best actress award for her gritty role as a backstreet abortionist in the small-budget film. Other nominees in the best actress category include Charlize Theron for Monster, Ziyi Zhang for House of Flying Daggers and UK star Kate Winslet, who has two nods for her roles in Eternal Sunshine of the Spotless Mind and Finding Neverland. + +DiCaprio faces competition from Bernal, Jamie Foxx, Jim Carrey and Johnny Depp in the best actor category. And British actor Clive Owen is hoping to repeat his Golden Globe success with a best supporting actor award for his role in Closer. His co-star Natalie Portman is up against Blanchett, Heather Craney, Julie Cristie and Meryl Streep in the best supporting actress category. Mike Leigh is up for the best director award for Vera Drake, alongside Martin Scorsese for The Aviator, Michael Mann for Collateral, Michel Gondry for Eternal Sunshine of the Spotless Mind and Marc Forster for Finding Neverland. \ No newline at end of file diff --git a/data/problems/p_summary8.md b/data/problems/p_summary8.md new file mode 100644 index 0000000000000000000000000000000000000000..d7c5425afe1a874da6018d91fd2a5b76a90a7391 --- /dev/null +++ b/data/problems/p_summary8.md @@ -0,0 +1,9 @@ +### Stars pay tribute to actor Davis + +Hollywood stars including Spike Lee, Burt Reynolds and Oscar nominee Alan Alda have paid tribute to actor Ossie Davis at a funeral in New York. + +Veteran star Ossie Davis, a well-known civil rights activist, died in Miami at the age of 87 on 4 February 2005. Friends and family, including actress Ruby Dee his wife of 56 years, gathered at the Riverside Church on Saturday. Also present at the service was former US president Bill Clinton and singer Harry Belafonte, who gave the eulogy. "He would have been a very good president of the United States," said Mr Clinton. "Like most of you here, he gave more to me than I gave to him." + +The 87-year-old was found dead last weekend in his hotel room in Florida, where he was making a film. Police said that he appeared to have died of natural causes. Davis made his acting debut in 1950 in No Way Out starring Sidney Poiter. He frequently collaborated with director Spike Lee, starring in seven Lee films including Jungle Fever, Do The Right Thing and Malcolm X. Attallah Shabazz, the daughter of activist Malcolm X, recalled the famous eulogy delivered by Davis at her father's funeral. "Harlem has come to bid farewell to one of its finest hopes," she said, quoting the man she knew as Uncle Ossie. "Ditto." "Ossie was my hero, and he still is," said Aviator star Alan Alda, a family friend for over forty years. "Ossie was a thing of beauty." + +"I want so badly someday to have his dignity - a little of it anyway," added Burt Reynolds, Davis's co-star in the 90s TV comedy Evening Shade. Before the midday funeral, scores of Harlem residents formed a queue outside the church to pay their respects to Davis. "It is hard to fathom that we will no longer be able to call on his wisdom, his humour, his loyalty and his moral strength to guide us in the choices that are yet to be made and the battles that are yet to be fought," said Belafonte, himself an ardent civil rights activist who had been friends with Davis for over 60 years. "But how fortunate we were to have him as long as we did." \ No newline at end of file diff --git a/data/problems/p_summary9.md b/data/problems/p_summary9.md new file mode 100644 index 0000000000000000000000000000000000000000..955dc47aa46a7b4b5dc052a122984dcc7439dac0 --- /dev/null +++ b/data/problems/p_summary9.md @@ -0,0 +1,5 @@ +### Berlin applauds Hotel Rwanda + +Political thriller Hotel Rwanda was given a rousing reception by spectators at the Berlin Film Festival on Saturday. + +The movie's star Don Cheadle also received a standing ovation when he stepped onto the stage after the show. The film is the true story of the hotel manager who saved 1,200 Tutsis from death during the Rwandan genocide. The film, showing out of competition in Berlin, is nominated for three Oscars, including best actor for Cheadle. Sophie Okonedo, who plays Cheadle's wife Tatiana, is nominated for best supporting actress. The film is also in the running for best original screenplay. Cheadle, was joined on stage at Berlin by Paul Rusesabagina, the hotel manager he plays in the film, Mr Rusesabagina's wife and his extended family, who fled Rwanda and now live in Belgium. Mr Rusesabagina used his influence as a prominent Hutu businessman to shelter potential victims of the Rwandan genocide, contacting dignitaries including Bill Clinton, the King of Belgium as well as the French foreign ministry. Hotel Rwanda is one of two films addressing the genocide at the 55th Berlin Film Festival, which runs until 20 February. Sometimes in April is a feature by Raoul Peck competing for the festival's coveted Golden and Silver Bear awards. The film was made exclusively in Rwanda whereas Hotel Rwanda was shot mostly in South Africa, with some scenes made in Kigali. \ No newline at end of file diff --git a/data/problems/p_title1.md b/data/problems/p_title1.md new file mode 100644 index 0000000000000000000000000000000000000000..14ab6ae07b7d61b1a7be07943ba8af2a4f2be00d --- /dev/null +++ b/data/problems/p_title1.md @@ -0,0 +1,5 @@ +Two days of talks on the future of Gibraltar begin at Jack Straw's country residence later on Wednesday. + +Officials at the two-day summit at the foreign secretary's official Kent house, Chevening, will plan a new forum on the Rock's future. In October, Mr Straw and his Spanish counterpart Miguel Moratinos agreed to establish a body that would give Gibraltarians a voice in their future. Most Gibraltarians said in a referendum they wanted to remain British. + +Gibraltar's Chief Minister Peter Caruana will represent the British citizens living on the Rock, while Britain's Europe Director Dominick Chilcott will represent the UK. Madrid is being represented by Spain's director general for Europe, Jose Maria Pons. The initiative follows Spain's socialist government's decision to put its long-standing sovereignty ambitions on hold. Gibraltarians rejected plans for the Rock's sovereignty to be shared between Britain and Spain in a referendum organised by Gibraltar government. diff --git a/data/problems/p_title10.md b/data/problems/p_title10.md new file mode 100644 index 0000000000000000000000000000000000000000..ff1c38ecb075a304a1e23692a6eb0218dd42b6f6 --- /dev/null +++ b/data/problems/p_title10.md @@ -0,0 +1,5 @@ +The first children's commissioner for England has been appointed. + +Great Ormond Street Hospital professor of child health, Al Aynsley-Green, was chosen by the government and will start the £100,000-a-year job immediately. He will oversee a £2.5m annual budget and have the power to look into "any matter relating to the interests and well-being of children". Prof Aynsley-Green has also been the national clinical director for children in the Department of Health. He promised to make sure that children's opinions "count". + +"I will be drawing on my experience of working with children and young people to help ensure that those with the power to improve children's lives do live up to their responsibilities. "I want all children and young people to know that they can approach me to discuss any matter that affects them, knowing that I will value their opinion." Education Secretary Ruth Kelly said Prof Aynsley-Green would "strengthen the voice of children and young people". Prof Aynsley-Green was a lecturer at Oxford University, trained at Guy's Hospital Medical School, University of London; Oriel College, Oxford; and in Switzerland. He is described as "a proud grandfather" of four. Scotland, Wales and Northern Ireland already have children's commissioners. diff --git a/data/problems/p_title2.md b/data/problems/p_title2.md new file mode 100644 index 0000000000000000000000000000000000000000..d415b06c83e75642d25428fcf3ffbdb42c2c74e0 --- /dev/null +++ b/data/problems/p_title2.md @@ -0,0 +1,5 @@ +A decision on whether to allow Westminster to legislate on super-casinos is set to be made by the Scottish Parliament. + +The government has plans for up to eight Las Vegas style resorts in the UK, one of which is likely to be in Glasgow. Scottish ministers insist they will still have the final say on whether a super-casino will be built in Scotland. But opposition parties say that will not happen in practice. The vote is due to be taken on Wednesday and is expected to be close. + +The Scottish Executive believes that the legislation should be handled by Westminster. The new law will control internet gambling for the first time and is aimed at preventing children from becoming involved. A super-casino in Glasgow could be located at Ibrox or the Scottish Exhibition and Conference Centre. The new gambling bill going through Westminster will allow casino complexes to open to the public, have live entertainment and large numbers of fruit machines with unlimited prizes. But the Scottish National Party and the Tories say the issue of super-casinos should be decided in Scotland and believe the executive is shirking its responsibility. \ No newline at end of file diff --git a/data/problems/p_title3.md b/data/problems/p_title3.md new file mode 100644 index 0000000000000000000000000000000000000000..13ac71036313a4d2abd820ecf38e834ac5e0b2ec --- /dev/null +++ b/data/problems/p_title3.md @@ -0,0 +1,5 @@ +Chancellor Gordon Brown has said he hopes to announce a deal to suspend debt interest repayments by tsunami-hit nations later on Friday. + +The agreement by the G8 group of wealthy nations would save affected countries £3bn pounds a year, he said. The deal is thought to have been hammered out on Thursday night after Japan, one of the biggest creditor nations, finally signed up to it. Mr Brown first proposed the idea earlier this week. + +G8 ministers are also believed to have agreed to instruct the World Bank and the International Monetary Fund to complete a country by country analysis of the reconstruction problems faced by all states hit by the disaster. Mr Brown has been locked in talks with finance ministers of the G8, which Britain now chairs. Germany also proposed a freeze and Canada has begun its own moratorium. The expected deal comes as Foreign Secretary Jack Straw said the number of Britons dead or missing in the disaster have reached 440. diff --git a/data/problems/p_title4.md b/data/problems/p_title4.md new file mode 100644 index 0000000000000000000000000000000000000000..4ed118fd24c1e833a4a9abeafb68d80b8c0bb48f --- /dev/null +++ b/data/problems/p_title4.md @@ -0,0 +1,9 @@ +National Insurance will be raised if Labour wins the next election, Tory leader Michael Howard has claimed. + +Tony Blair has said he does not want higher tax rates for top earners but on Wednesday said other tax promises would be left to Labour's manifesto. Prime minister's questions also saw Mr Blair predict that new plans would probably cut net immigration. He attacked Tory plans to process asylum claims abroad - but Mr Howard said Labour had proposed the idea too. + +The Commons questions session again saw the leaders of the two biggest parties shape up for the forthcoming election campaign. The Tories have promised £4bn in tax cuts but have yet to say where they will fall. Mr Howard pointed to the Institute for Fiscal Studies' predictions that Labour will need to increase taxes to cover an £11bn gap in its spending plans. He accused ministers of wasting money on unsuccessful attempts to curb bad behaviour and truancy in schools and on slow asylum processing. It was no good Mr Blair claiming tax pledges were being left to the manifesto as he had given one to MPs on Tuesday about the top rate of income tax, argued Mr Howard. Pointing to national insurance, he added: "Everyone knows tax will go up under Labour: isn't it now clear which tax it would be?" + +Mr Blair instead hailed Labour's achievement in using a strong economy to invest in public services. "When we have money not only going into extra teachers and nurses but equipment in schools and hospitals, that money is not wasted," he said. On the tax questions, he added: "We will make commitments on tax at the time of the manifesto." Home Secretary Charles Clarke this week published plans for a new points system for economic migrants, with only high-skilled workers allowed into the UK from outside the European Union. + +Mr Blair said abuses would be weeded out and chain migration, where families automatically get the right to settle with immigrant workers, would end. That would probably create a fall in the migrant numbers, he said. The prime minister ridiculed the Tory plans for asylum quotas and for processing all asylum claims overseas. He challenged the Tories on which country would house their processing centres - what he called a "fantasy island". Mr Howard read from a letter about the government's own plans at the European Council of Ministers for processing asylum seekers outside the EU. But Mr Blair said: "All the other countries could not agree on the way forward, nor could the UN." diff --git a/data/problems/p_title5.md b/data/problems/p_title5.md new file mode 100644 index 0000000000000000000000000000000000000000..902d087ef24a612dc990b45e16194f4c7ea4405f --- /dev/null +++ b/data/problems/p_title5.md @@ -0,0 +1,7 @@ +A failed government scheme to offer UK university courses online has been branded a "disgraceful waste" by MPs. + +The e-University was scrapped last year, having attracted only 900 students at a cost of £50m. Chief executive John Beaumont was paid a bonus of £44,914, despite a failure to bring in private sector backers. The Commons education select committee called this "morally indefensible" but the government said the e-University project had "improved understanding". + +A Department for Education and Skills spokeswoman said the venture had been "ambitious and ground-breaking, but take-up had not been "sufficient to continue with the project". She added: "UK e-Universities was not the only organisation to have lost out on private sector investment in the collapse of the dotcom boom." The select committee found that those responsible for founding the e-University in 2000 had been caught up in the "general atmosphere of enthusiasm" surrounding the internet. Initial business plans forecast a quarter of a million students joining within a decade, bringing in at least £110m in profit. + +But virtually no market research was carried out and just £4.2m was spent on worldwide sales and marketing of courses. Some £14m went on developing the technology to make the e-University work. This was used by just 200 students, the rest preferring to work through existing university websites. With no significant private investors and no direct accountability to a government minister, the e-University had had "too much freedom to spend public money as it wished", the report found. Committee chairman Barry Sheerman said: "UK e-University was a terrible waste of public money. "The senior executives failed to interest any private investors and showed an extraordinary over-confidence in their ability to attract students to the scheme." The report warns that the government should not be scared off investment in innovative but potentially risky schemes by the failure of the e-University, but "should learn the lessons from this disaster". \ No newline at end of file diff --git a/data/problems/p_title6.md b/data/problems/p_title6.md new file mode 100644 index 0000000000000000000000000000000000000000..7ac1cb7d0f238c61da4621c2e0cf9a85e3658026 --- /dev/null +++ b/data/problems/p_title6.md @@ -0,0 +1,5 @@ +Chancellor Gordon Brown has visited Kenya's biggest shantytown as he opened a week-long visit to Africa. + +Mr Brown's trip is designed to highlight how the UK wants to make Africa's problems a priority of its chairmanship of the G8 this year. He will see an HIV/Aids orphanage in Tanzania and a women's credit union in Mozambique before chairing a meeting of the Commission for Africa in Cape Town. At slums in Narobi on Wednesday, he said education needs had to be tackled. + +Speaking outside the Olympic Primary School, Mr Brown said: "It is simply not acceptable in the modern age for the rest of the world to stand by and have hundreds of millions of children not getting the chance at education." He pointed to international plans to invest $10bn for education in Africa over the next decade. The school is on the edge of Kibera, where 800,000 live often in huts made of mud, scrap metal and cardboard. Mr Brown's aides say he wants to find out more about the Kenyan Government's education policies, which included introducing free primary education in early 2003. The chancellor has already unveiled proposals for a G8 aid package which he has likened to the Marshall Plan used by the United States to rebuild Europe after World War Two. The trip follows claims of infighting between Mr Brown and Tony Blair detailed in a new book. Conservative leader Michael Howard is expected to seize on those reports at prime minister's questions at 1200 GMT on Wednesday. \ No newline at end of file diff --git a/data/problems/p_title7.md b/data/problems/p_title7.md new file mode 100644 index 0000000000000000000000000000000000000000..20881900e558c084f644ee76d24a4ec8b3c5eba8 --- /dev/null +++ b/data/problems/p_title7.md @@ -0,0 +1,5 @@ +A former Home Office minister has called for an independent body to be set up to monitor UK immigration. + +Barbara Roche said an organisation should monitor and publish figures and be independent of government. She said this would counter "so-called independent" groups like Migration Watch, which she described as an anti-immigration body posing as independent. Migration Watch says it is not against all immigration and the government already publishes accurate figures. Sir Andrew Green, chairman of the organisation, says there is no need for an independent body because Office of National Statistics data are accurate. He says he opposes large-scale immigration "both on the grounds of overcrowding and culture". + +He said: "For example, over the next 20 years one household in three will be due to immigration. "We are already more overcrowded than India and we are four times more overcrowded than France." Ms Roche, Labour MP for Hornsey and Wood Green, believes legal migration is something we should welcome. She said her proposals mean "we wouldn't have so-called independent experts, like Migration Watch, who come into this debate from an anti-immigration point of view." She went on: "What I would like to see is there being a body which actually looked at the figures, published them, and was independent of government. "I think that would go a long way to allaying some of the fears that are sometimes whipped up during this debate." diff --git a/data/problems/p_title8.md b/data/problems/p_title8.md new file mode 100644 index 0000000000000000000000000000000000000000..f7931022986c5d28173c4154c6b2a728549fa1d6 --- /dev/null +++ b/data/problems/p_title8.md @@ -0,0 +1,5 @@ +Political parties cannot afford to take older UK voters for granted in the coming election, says Age Concern. + +A survey for the charity suggests 69% of over-55s say they always vote in a general election compared with just 17% of 18 to 24 year olds. Charity boss Gordon Lishman said if a "decisive blow" was struck at the election it would be by older voters who could be relied on to turn out. A total of 3,028 adults aged 18 or over were interviewed for the study. Mr Lishman urged the next government to boost state pension. + +He also called for measures to combat ageism and build effective public services to "support us all in an ageing society". "Older people want to see manifesto commitments that will make a difference to their lives," Mr Lishman said. "Political parties must wake up to the fact that unless they address the demands and concerns of older people they will not keep or attract their vote." In the survey carried out by ICM Research, 14% of people aged between 18 and 34 said they never voted in general elections. Among the over-65s, 70% said they would be certain to vote in an immediate election, compared with 39% of people under 55. Age Concern says the over-55s are "united around" key areas of policy they want the government to focus on. For 57%, pensions and the NHS were key issues, while the economy was important for a third, and tax was a crucial area for 25%. diff --git a/data/problems/p_title9.md b/data/problems/p_title9.md new file mode 100644 index 0000000000000000000000000000000000000000..b079ba1a51e7199a85a9865e1e6ac521da01f601 --- /dev/null +++ b/data/problems/p_title9.md @@ -0,0 +1,9 @@ +A rise has been recorded in the number of students from south of the border applying to universities in Scotland. + +However, Lifelong Learning Minister Jim Wallace said that this would not result in Scottish students missing out. Applications from England and Wales rose by 17% between January 2005 and the previous year, up 23,600 to 27,700. Fears had been expressed that a flood of "fee refugees" would try to avoid top-up fees of up to £3,000 a year being introduced in England. In June last year, Mr Wallace announced proposals to increase tuition fees for English students studying in Scotland by £2,000 in an attempt to prevent a cross-border flood, although no figure has yet been agreed. Legislation to introduce the top-up fees in England is not due to take effect until autumn 2006 and students who start before then will not have to pay additional fees at all. + +The figures were made public on Thursday by admissions service Ucas. Universities Scotland, which represents university principals, claimed that an increase in applications did not amount to Scottish students being squeezed out. Director, David Caldwell, said some students could be applying in an attempt to avoid the possible increase in annual fees at English universities, but this was not a major factor. He told BBC Radio Scotland's Good Morning Scotland programme: "The reason people are opting for Scottish universities is that they are perceived as being of very high quality, they offer very attractive courses and Scotland is seen as a very attractive place to study. + +"They know that when they take up their studies in 2006 they will be hit by top-up fees if they are going to a university in England and that may be part of the reason why the numbers coming to Scotland are so inflated. "However, it does not mean that we will see thousands of additional students from England studying here." Mr Wallace agreed and said the figures had to be looked at in context. He explained that when applications were translated into acceptances, the number was not huge - an additional figure of about 200. + +Also, the picture was further blurred by the fact that applications from Wales, where there are no plans for top-up fees, have also risen, by 19%. Mr Wallace said: "Accepting students from all parts of the world does show the high regard in which Scottish higher education is held, not just in Britain. "We want to make sure that when students are making their choice, they do so on the nature of the course and not because they are under some sort of financial pressure to go to Scotland. "We do not want to have a situation where it becomes impossible for Scottish students to get places at Scottish universities because we are seen as the cheap option. "Very often the quality of the university experience is enhanced by the fact there are students coming from a wide range of backgrounds so it would be wrong to go the other way and start excluding students." diff --git a/data_storage.py b/data_storage.py new file mode 100644 index 0000000000000000000000000000000000000000..860c31fd1d0cf6993173ffd4f1a39a0acd2fe3d8 --- /dev/null +++ b/data_storage.py @@ -0,0 +1,50 @@ +import uuid +import os +import json + + +def store_user_data(user_id, storage_type, storage_data): + # Set the base directory relative to the current script location + base_dir = "./user_data/" # Changed to a relative path + user_dir = base_dir + str(user_id) + os.makedirs(user_dir, exist_ok=True) + + file_path = os.path.join(user_dir, f"{storage_type}_{user_id}.json") + + # Check if user file exists and load existing data + if os.path.exists(file_path): + try: + with open(file_path, 'r') as file: + existing_data = json.load(file) + # Update existing data with new data + existing_data.update(storage_data) + data = existing_data + except json.JSONDecodeError: + # If JSON decoding fails, overwrite the corrupted file with new data + pass + + # Write the data to the file + with open(file_path, 'w') as file: + json.dump(storage_data, file, indent=4) + +def store_user_questionnaire(user_id, storage_data): + # Set the base directory relative to the current script location + + + + + # Check if user file exists and load existing data + if os.path.exists(file_path): + try: + with open(file_path, 'r') as file: + existing_data = json.load(file) + # Update existing data with new data + existing_data.update(storage_data) + data = existing_data + except json.JSONDecodeError: + # If JSON decoding fails, overwrite the corrupted file with new data + pass + + # Write the data to the file + with open(file_path, 'w') as file: + json.dump(storage_data, file, indent=4) diff --git a/experiment_details.py b/experiment_details.py new file mode 100644 index 0000000000000000000000000000000000000000..a24e2f28b1cfdc795d9d80faff8c8c0579c7a282 --- /dev/null +++ b/experiment_details.py @@ -0,0 +1,99 @@ +import numpy as np + +problem_topics = ["Creative Short Stories", "Informative Emails"] +problems_per_topic = {"Creative Short Stories": np.arange(2), + "Informative Emails": np.arange(2, 4)} + +writing_skills_questions = { + "Demographic Details": [ + {"Question": "What is your gender?", + "AnswerChoices": ["Male", "Female", "Non-binary", "Prefer not to say"]}, + {"Question": "Which of the following best describes your race or ethnicity?", + "AnswerChoices": ["Caucasian", "Hispanic or Latino", "African American", "Asian", "Native American", "Other", + "Prefer not to say"]}, + {"Question": "How would you describe your socioeconomic status?", + "AnswerChoices": ["Low", "Lower-middle", "Middle", "Upper-middle", "High"]}, + {"Question": "What is your primary language?", + "AnswerChoices": ["English", "Spanish", "Other"]}, + {"Question": "What is your age range?", + "AnswerChoices": ["18-24", "25-34", "35-44", "45-54", "55-64", "65 or older"]}, + {"Question": "What is the highest level of education you have completed?", + "AnswerChoices": ["Some high school", "High school graduate", "Some college", "Bachelor’s degree", + "Graduate degree"]}, + {"Question": "Which field best describes your current profession?", + "AnswerChoices": [ + "Arts and Entertainment", + "Business and Finance", + "Education", + "Engineering and Technology", + "Healthcare", + "Information Technology", + "Law and Governance", + "Science and Research", + "Service Industry", + "Other" + ]}, + {"Question": "How comfortable are you using LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?", + "AnswerChoices": ["Not comfortable at all", "Slightly comfortable", "Moderately comfortable", "Very comfortable", "Extremely comfortable"]}, + {"Question": "How much experience do you have using LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?", + "AnswerChoices": ["No experience", "Less than 6 months", "6 months to 1 year", "1 to 2 years", "More than 2 years"]}, + {"Question": "How often do you use LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?", + "AnswerChoices": ["Never", "Rarely (less than once a month)", "Occasionally (once a month to once a week)", "Frequently (several times a week)", "Daily"]} + ], + "User Capabilities": [ + {"Question": "How would you rate your expertise in writing?", + "AnswerChoices": ["Novice", "Intermediate", "Expert", "Professional writer"]}, + {"Question": "How efficient do you consider yourself in writing tasks?", + "AnswerChoices": ["Very inefficient", "Somewhat inefficient", "Neutral", "Somewhat efficient", + "Very efficient"]}, + {"Question": "How comfortable are you with using writing-related technology?", + "AnswerChoices": ["Not comfortable at all", "Slightly comfortable", "Moderately comfortable", + "Very comfortable", "Extremely comfortable"]}, + {"Question": "How confident do you feel about your writing?", + "AnswerChoices": ["Not confident", "Slightly confident", "Moderately confident", "Very confident", + "Extremely confident"]}, + {"Question": "How often do you engage in creative or thoughtful writing?", + "AnswerChoices": ["Never", "Rarely", "Sometimes", "Often", "Always"]}, + {"Question": "What is your typical emotional state when writing?", + "AnswerChoices": ["Very stressed", "Somewhat stressed", "Neutral", "Somewhat relaxed", "Very relaxed"]}, + {"Question": "How often do you feel that you can empathize with characters or subjects in your writing?", + "AnswerChoices": ["Never", "Rarely", "Sometimes", "Often", "Always"]}, + {"Question": "How often do you experience focus issues or writer’s block when writing?", + "AnswerChoices": ["Always", "Often", "Sometimes", "Rarely", "Never"]}, + {"Question": "Do you identify as neurotypical or neurodivergent?", + "AnswerChoices": ["Neurotypical", "Neurodivergent", "Prefer not to say"]} + ], + "Relationship to System": [ + {"Question": "How much control do you feel you have when using a writing assistant?", + "AnswerChoices": ["None", "Little", "Some", "A lot", "Complete control"]}, + {"Question": "How much ownership do you feel over your writings created with the help of a writing assistant?", + "AnswerChoices": ["None", "Little", "Some", "Most", "Complete"]}, + {"Question": "How concerned are you about plagiarism when using a writing assistant?", + "AnswerChoices": ["Not concerned", "Slightly concerned", "Moderately concerned", "Very concerned", + "Extremely concerned"]}, + {"Question": "How much do you trust the writing assistant to help you effectively?", + "AnswerChoices": ["Not at all", "A little", "Moderately", "A lot", "Completely"]}, + {"Question": "How important is it that the writing assistant is available whenever you need it?", + "AnswerChoices": ["Not important", "Slightly important", "Moderately important", "Very important", + "Extremely important"]}, + {"Question": "How concerned are you about your privacy when using a writing assistant?", + "AnswerChoices": ["Not concerned", "Slightly concerned", "Moderately concerned", "Very concerned", + "Extremely concerned"]}, + {"Question": "How well do you understand how the writing assistant works, including its capabilities and limitations?", + "AnswerChoices": ["Not at all", "Slightly", "Moderately", "Very well", "Completely"]} + ], + "System Output Preferences": [ + {"Question": "How important is it for the outputs from the writing assistant to be grammatically and contextually coherent?", + "AnswerChoices": ["Not important", "Slightly important", "Moderately important", "Very important", "Extremely important"]}, + {"Question": "How much do you value novelty and diversity in the outputs from the writing assistant?", + "AnswerChoices": ["Not at all", "A little", "Moderately", "A lot", "Extremely"]}, + {"Question": "How important is it for the writing assistant to provide explanations for its outputs?", + "AnswerChoices": ["Not important", "Slightly important", "Moderately important", "Very important", + "Extremely important"]}, + {"Question": "How concerned are you about potential biases in the outputs from the writing assistant?", + "AnswerChoices": ["Not concerned", "Slightly concerned", "Moderately concerned", "Very concerned", + "Extremely concerned"]}, + {"Question": "How important is personalization of the outputs from the writing assistant according to your specific needs and preferences?", + "AnswerChoices": ["Not important", "Slightly important", "Moderately important", "Very important", "Extremely important"]} + ] +} diff --git a/ignore_comments.py b/ignore_comments.py new file mode 100644 index 0000000000000000000000000000000000000000..e21496cd9e2795c32f8c42bbbd52619a04e15af7 --- /dev/null +++ b/ignore_comments.py @@ -0,0 +1,31 @@ +import os + +""" Initialize MongoDB connection. """ +# mongodb_uri = str(os.environ['MONGODB_URI']) +print(os.environ['MONGODB_URI']) +print(os.environ['DB_NAME']) +print(os.environ['COLLECTION_NAME']) +# db_name = str(os.environ['DB_NAME']) + +# from pymongo.mongo_client import MongoClient +# from pymongo.server_api import ServerApi +# +# uri = "mongodb+srv://wrAIteMaster:@wraitecluster.tpqpuj5.mongodb.net/?retryWrites=true&w=majority&appName=wrAIteCluster" +# # mongodb+srv://wrAIteMaster:@wraitecluster.tpqpuj5.mongodb.net/ +# # Create a new client and connect to the server +# client = MongoClient(uri, server_api=ServerApi('1')) +# +# # Send a ping to confirm a successful connection +# try: +# client.admin.command('ping') +# print("Pinged your deployment. You successfully connected to MongoDB!") +# except Exception as e: +# print(e) +# uri = "mongodb+srv://wrAIteMaster:@wraitecluster.tpqpuj5.mongodb.net/?retryWrites=true&w=majority&appName=wrAIteCluster" +# mongodb_uri = "mongodb+srv://wrAIteMaster:YqGvfJDUShY5nYu8@wraitecluster.tpqpuj5.mongodb.net/?retryWrites=true&w=majority&appName=wrAIteCluster" +# db_name = "wrAIteDB" +# collection_name = "wrAIteUsers" + + + +# oai_key = "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" # ADD YOUR KEY diff --git a/model_generate.py b/model_generate.py new file mode 100644 index 0000000000000000000000000000000000000000..b4524f031942be1a8e7547e86e5624890c3330ba --- /dev/null +++ b/model_generate.py @@ -0,0 +1,95 @@ +from constants import model_options, MAX_CONVERSATION_LENGTH, MAX_TOKENS_PER_GENERATION, SAMPLING_TEMPERATURE + +import gradio as gr +import openai +from openai import OpenAI +import os + +collection_name = str(os.getenv('COLLECTION_NAME')) + +oai_key = str(os.getenv('OAI_KEY')) +openai.api_key = oai_key + + +client = OpenAI( + api_key = oai_key +) + + +def query_a_chat_completion(model, messages): + # assert model in ["gpt-4"] + assert model in ["gpt-3.5-turbo", "gpt-4"] + completion = openai.ChatCompletion.create( + model=model, + messages=messages, + max_tokens=MAX_TOKENS_PER_GENERATION, + temperature=SAMPLING_TEMPERATURE + ) + return completion.choices[0].message.content + + +def query_chatbot(model, messages): + assert model in ["gpt-3.5-turbo", "gpt-4"] + chat_completion = client.chat.completions.create( + messages=messages, + model="gpt-3.5-turbo", + ) + return chat_completion.choices[0].message.content + + +def chatbot_generate(user_newest_input, history, model, current_answer, initial_txt): + """ + Generate the next response from the chatbot + :param user_newest_input: The newest input from the user + :param history: The history of the conversation + list[str], where each element starts with "User:" or "AI:" + :return: The chatbot state, the history, the text, the submit button + """ + # convert to openai model format + actual_model = { + "chatgpt4": "gpt-4", + "chatgpt": "gpt-3.5-turbo" + }[model] + + # Update the history with newest user input + history.append(f"User: {user_newest_input.strip()}") + + # construct chat messages + chat_messages = [{"role": "system", "content": "You are a helpful assistant to a writer."}] + + # chat_messages = [{"role": "system", "content": initial_txt}] + current_txt = "My current answer to the prompt is as follows: " + current_answer + '. Now help me answer my question: ' + for hist in history: + if hist.startswith("User:"): + chat_messages.append( + { + "role": "user", + "content": hist[5:].strip() + } + ) + elif hist.startswith("Writing Assistant:"): + content = current_txt + hist[18:].strip() + chat_messages.append( + { + "role": "assistant", + "content": content + } + ) + else: + raise NotImplementedError + + # Get the generation from OpenAI + if actual_model in ["gpt-3.5-turbo", "gpt-4"]: + ai_newest_output = query_chatbot(actual_model, chat_messages) + else: + raise NotImplementedError + + # Update the history with newest AI output + history.append(f"Writing Assistant: {ai_newest_output.strip()}") + conversations = [(history[i], history[i + 1]) for i in range(0, len(history) - 1, 2)] + + # Whether the textbox and the submit button should be hidden + if len(history) >= 2 * MAX_CONVERSATION_LENGTH: + return conversations, history, gr.update(visible=False), gr.update(visible=False) + else: + return conversations, history, gr.update(visible=True), gr.update(visible=True) \ No newline at end of file diff --git a/pymongo_get_database.py b/pymongo_get_database.py new file mode 100644 index 0000000000000000000000000000000000000000..444b20a42fd0064d3bd9df08bdfa1db9f22b41cf --- /dev/null +++ b/pymongo_get_database.py @@ -0,0 +1,42 @@ +import os + +from pymongo import MongoClient +from datetime import datetime + + +class MongoDBManager: + def __init__(self): + mongodb_uri = str(os.getenv('MONGODB_URI')) + db_name = str(os.getenv('DB_NAME')) + collection_name = str(os.getenv('COLLECTION_NAME')) + + self.client = MongoClient(mongodb_uri) + self.db = self.client[db_name] + self.collection = self.db[collection_name] + + def create_user_record(self, user_id): + """ Create a new user record with empty answers. """ + user_record = { + "_id": user_id, # using user_id as the unique identifier for the document + "createdAt": datetime.now(), + "questionnaireAnswers": {}, + "questionAnswers": {} + } + self.collection.insert_one(user_record) + + def update_questionnaire_answers(self, user_id, answers): + """ Update questionnaire answers for a specific user. """ + update_result = self.collection.update_one( + {"_id": user_id}, + {"$set": {"questionnaireAnswers": answers}} + ) + return update_result.modified_count + + def update_question_answers(self, user_id, answers): + """ Update question answers for a specific user. """ + update_result = self.collection.update_one( + {"_id": user_id}, + {"$set": {"questionAnswers": answers}} + ) + return update_result.modified_count + diff --git a/questionnaire.py b/questionnaire.py new file mode 100644 index 0000000000000000000000000000000000000000..ccf5c5c238de3e2cb502b82bc97f72a763d217af --- /dev/null +++ b/questionnaire.py @@ -0,0 +1,242 @@ +from pymongo_get_database import MongoDBManager +from utils import process_markdown, save_answer, randomly_select_prompts, generate_unassisted_question + +from experiment_details import problem_topics, problems_per_topic, writing_skills_questions +from data_storage import store_user_data + +import gradio as gr + +mongo_manager = MongoDBManager() +def generate_questionnaire(all_results, completed_screen, user_id): + dem_answers = {} + usercap_answers = {} + reln_answers = {} + pref_answers = {} + + with gr.Column("Questionnaire", render=False, visible=False) as questionnaire: + questionnaire_instr_md = process_markdown(False, 'instr_questionnaire.md') + questionnaire_instr = gr.Markdown(value=questionnaire_instr_md) + + def finish_pref(): + all_results['System Output Preferences'] = pref_answers + store_user_data(user_id, "questionnaire", all_results) + mongo_manager.update_questionnaire_answers(user_id, all_results) + return { + pref: gr.update(visible=False), + completed_screen: gr.update(visible=True), + questionnaire_instr: gr.update(visible=False) + } + + with gr.Column("System Output Preferences", render=True, visible=False) as pref: + + def save_results(question, answer, total_num_questions): + pref_answers[question] = answer + questions_answered = int(total_num_questions) == len(pref_answers) + if questions_answered: + return str(pref_answers), questions_answered, gr.Button(interactive=True) + else: + return str(pref_answers), questions_answered, gr.Button(interactive=False) + + q_num = 1 + pref_questions = writing_skills_questions['System Output Preferences'] + total_questions_len = str(len(pref_questions)) + + with gr.Row(visible=False): + radio_outputs = gr.Textbox(label="Choices") + all_questions_answered = gr.Textbox(label="All Questions Answered") + with gr.Row(render=False) as output_row: + finish_pref_btn = gr.Button( + "Next", + variant="primary", + interactive=False) + with gr.Group(): + for q in pref_questions: + with gr.Row(): + # Hidden textbox to hold the question value + question_input = gr.Textbox(value=q['Question'], visible=False) + total_num_questions = gr.Textbox(value=total_questions_len, visible=False) + single_question = gr.Radio( + choices=q['AnswerChoices'], + label=str(q_num) + '. ' + q['Question'], + interactive=True, + visible=True + ) + # Use the hidden textbox as part of the inputs + single_question.change( + fn=save_results, + inputs=[question_input, single_question, total_num_questions], + outputs=[radio_outputs, all_questions_answered, finish_pref_btn] + ) + q_num += 1 + output_row.render() + finish_pref_btn.click( + fn=finish_pref, + inputs=[], + outputs=[pref, completed_screen, questionnaire_instr] + ) + + def finish_reln(): + all_results['Relationship to System'] = reln_answers + return { + reln: gr.update(visible=False), + pref: gr.update(visible=True) + } + + with gr.Column("Relationship to System", render=True, visible=False) as reln: + + def save_results(question, answer, total_num_questions): + reln_answers[question] = answer + questions_answered = int(total_num_questions) == len(reln_answers) + if questions_answered: + return str(reln_answers), questions_answered, gr.Button(interactive=True) + else: + return str(reln_answers), questions_answered, gr.Button(interactive=False) + + q_num = 1 + reln_questions = writing_skills_questions['Relationship to System'] + total_questions_len = str(len(reln_questions)) + + with gr.Row(visible=False): + radio_outputs = gr.Textbox(label="Choices") + all_questions_answered = gr.Textbox(label="All Questions Answered") + with gr.Row(render=False) as output_row: + finish_reln_btn = gr.Button( + "Next", + variant="primary", + interactive=False) + with gr.Group(): + for q in reln_questions: + with gr.Row(): + # Hidden textbox to hold the question value + question_input = gr.Textbox(value=q['Question'], visible=False) + total_num_questions = gr.Textbox(value=total_questions_len, visible=False) + single_question = gr.Radio( + choices=q['AnswerChoices'], + label=str(q_num) + '. ' + q['Question'], + interactive=True, + visible=True + ) + # Use the hidden textbox as part of the inputs + single_question.change( + fn=save_results, + inputs=[question_input, single_question, total_num_questions], + outputs=[radio_outputs, all_questions_answered, finish_reln_btn] + ) + q_num += 1 + output_row.render() + finish_reln_btn.click( + fn=finish_reln, + inputs=[], + outputs=[reln, pref] + ) + + def finish_usercap(): + all_results['User Capabilities'] = usercap_answers + return { + usercap: gr.update(visible=False), + reln: gr.update(visible=True) + } + + with gr.Column("User Capabilities", render=True, visible=False) as usercap: + + def save_results(question, answer, total_num_questions): + usercap_answers[question] = answer + questions_answered = int(total_num_questions) == len(usercap_answers) + if questions_answered: + return str(usercap_answers), questions_answered, gr.Button(interactive=True) + else: + return str(usercap_answers), questions_answered, gr.Button(interactive=False) + + q_num = 1 + usercap_questions = writing_skills_questions['User Capabilities'] + total_questions_len = str(len(usercap_questions)) + + with gr.Row(visible=False): + radio_outputs = gr.Textbox(label="Choices") + all_questions_answered = gr.Textbox(label="All Questions Answered") + with gr.Row(render=False) as output_row: + finish_usercap_btn = gr.Button( + "Submit Questionnaire", + variant="primary", + interactive=False) + with gr.Group(): + for q in usercap_questions: + with gr.Row(): + # Hidden textbox to hold the question value + question_input = gr.Textbox(value=q['Question'], visible=False) + total_num_questions = gr.Textbox(value=total_questions_len, visible=False) + single_question = gr.Radio( + choices=q['AnswerChoices'], + label=str(q_num) + '. ' + q['Question'], + interactive=True, + visible=True + ) + # Use the hidden textbox as part of the inputs + single_question.change( + fn=save_results, + inputs=[question_input, single_question, total_num_questions], + outputs=[radio_outputs, all_questions_answered, finish_usercap_btn] + ) + q_num += 1 + output_row.render() + finish_usercap_btn.click( + fn=finish_usercap, + inputs=[], + outputs=[usercap, reln] + ) + + def finish_dem(): + all_results['Demographic Details'] = dem_answers + return { + dem: gr.update(visible=False), + usercap: gr.update(visible=True) + } + + with gr.Column("Demographic", render = True) as dem: + + def save_results(question, answer, total_num_questions): + dem_answers[question] = answer + questions_answered = int(total_num_questions) == len(dem_answers) + if questions_answered: + return str(dem_answers), questions_answered, gr.Button(interactive=True) + else: + return str(dem_answers), questions_answered, gr.Button(interactive=False) + + q_num = 1 + dem_questions = writing_skills_questions['Demographic Details'] + total_questions_len = str(len(dem_questions)) + + with gr.Row(visible=False): + radio_outputs = gr.Textbox(label="Choices") + all_questions_answered = gr.Textbox(label="All Questions Answered") + with gr.Row(render=False) as output_row: + finish_dem_btn = gr.Button( + "Next", + variant="primary", + interactive=False) + with gr.Group(): + for q in dem_questions: + with gr.Row(): + # Hidden textbox to hold the question value + question_input = gr.Textbox(value=q['Question'], visible=False) + total_num_questions = gr.Textbox(value=total_questions_len, visible=False) + single_question = gr.Radio( + choices=q['AnswerChoices'], + label=str(q_num) + '. ' + q['Question'], + interactive=True, + visible=True + ) + # Use the hidden textbox as part of the inputs + single_question.change( + fn=save_results, + inputs=[question_input, single_question, total_num_questions], + outputs=[radio_outputs, all_questions_answered, finish_dem_btn] + ) + q_num += 1 + output_row.render() + finish_dem_btn.click( + fn=finish_dem, + inputs=[], + outputs=[dem, usercap] + ) + return questionnaire diff --git a/test_mdb.py b/test_mdb.py new file mode 100644 index 0000000000000000000000000000000000000000..c4777e7e8c47ae66fbc10a3ac2e04fe65d631c91 --- /dev/null +++ b/test_mdb.py @@ -0,0 +1,23 @@ +from pymongo.mongo_client import MongoClient +from pymongo.server_api import ServerApi + +from urllib.parse import quote_plus +username = quote_plus('wrAIteMaster') +password = quote_plus('YqGvfJDUShY5nYu8') + + +# cluster = 'wraitecluster' +# authSource = '' +# authMechanism = '' +# uri = 'mongodb+srv://' + username + ':' + password + '@' + cluster + '/?authSource=' + authSource + '&authMechanism=' + authMechanism + + +uri = "mongodb+srv://wrAIteMaster:YqGvfJDUShY5nYu8@wraitecluster.tpqpuj5.mongodb.net/" +# Create a new client and connect to the server +client = MongoClient(uri, server_api=ServerApi('1')) +# Send a ping to confirm a successful connection +try: + client.admin.command('ping') + print("Pinged your deployment. You successfully connected to MongoDB!") +except Exception as e: + print(e) \ No newline at end of file diff --git a/user_data/14c40dff-badf-42af-b16b-57b9999ca0c0/questionnaire_14c40dff-badf-42af-b16b-57b9999ca0c0.json b/user_data/14c40dff-badf-42af-b16b-57b9999ca0c0/questionnaire_14c40dff-badf-42af-b16b-57b9999ca0c0.json new file mode 100644 index 0000000000000000000000000000000000000000..2e3021f57cbde27d3e1d030787eea3b42880ef3e --- /dev/null +++ b/user_data/14c40dff-badf-42af-b16b-57b9999ca0c0/questionnaire_14c40dff-badf-42af-b16b-57b9999ca0c0.json @@ -0,0 +1,41 @@ +{ + "Demographic Details": { + "What is your gender?": "Non-binary", + "Which of the following best describes your race or ethnicity?": "Asian", + "How would you describe your socioeconomic status?": "Upper-middle", + "What is your primary language?": "Other", + "What is your age range?": "55-64", + "What is the highest level of education you have completed?": "Some high school", + "Which field best describes your current profession?": "Education", + "How comfortable are you using LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?": "Slightly comfortable", + "How much experience do you have using LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?": "1 to 2 years", + "How often do you use LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?": "Rarely (less than once a month)" + }, + "User Capabilities": { + "How often do you engage in creative or thoughtful writing?": "Sometimes", + "What is your typical emotional state when writing?": "Neutral", + "How often do you feel that you can empathize with characters or subjects in your writing?": "Rarely", + "How often do you experience focus issues or writer\u2019s block when writing?": "Rarely", + "Do you identify as neurotypical or neurodivergent?": "Neurodivergent", + "How comfortable are you with using writing-related technology?": "Slightly comfortable", + "How confident do you feel about your writing?": "Slightly confident", + "How efficient do you consider yourself in writing tasks?": "Somewhat efficient", + "How would you rate your expertise in writing?": "Expert" + }, + "Relationship to System": { + "How concerned are you about your privacy when using a writing assistant?": "Slightly concerned", + "How important is it that the writing assistant is available whenever you need it?": "Very important", + "How much do you trust the writing assistant to help you effectively?": "A lot", + "How concerned are you about plagiarism when using a writing assistant?": "Moderately concerned", + "How much ownership do you feel over your writings created with the help of a writing assistant?": "Some", + "How much control do you feel you have when using a writing assistant?": "Complete control", + "How well do you understand how the writing assistant works, including its capabilities and limitations?": "Very well" + }, + "System Output Preferences": { + "How important is it for the outputs from the writing assistant to be grammatically and contextually coherent?": "Slightly important", + "How much do you value novelty and diversity in the outputs from the writing assistant?": "A little", + "How important is it for the writing assistant to provide explanations for its outputs?": "Moderately important", + "How concerned are you about potential biases in the outputs from the writing assistant?": "Moderately concerned", + "How important is personalization of the outputs from the writing assistant according to your specific needs and preferences?": "Moderately important" + } +} \ No newline at end of file diff --git a/user_data/14c40dff-badf-42af-b16b-57b9999ca0c0/questions_14c40dff-badf-42af-b16b-57b9999ca0c0.json b/user_data/14c40dff-badf-42af-b16b-57b9999ca0c0/questions_14c40dff-badf-42af-b16b-57b9999ca0c0.json new file mode 100644 index 0000000000000000000000000000000000000000..68c097b32f6b200e949a37be3bccd81852815f30 --- /dev/null +++ b/user_data/14c40dff-badf-42af-b16b-57b9999ca0c0/questions_14c40dff-badf-42af-b16b-57b9999ca0c0.json @@ -0,0 +1,74 @@ +{ + "q1": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:11.403808", + "StartTime": "2024-04-29T22:36:56.421608", + "EndTime": "2024-04-29T22:37:07.825416", + "Assist": false, + "AssistanceHistory": null + }, + "q2": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:03.406698", + "StartTime": "2024-04-29T22:37:07.825439", + "EndTime": "2024-04-29T22:37:11.232137", + "Assist": true, + "AssistanceHistory": [] + }, + "q3": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:04.386613", + "StartTime": "2024-04-29T22:37:11.232160", + "EndTime": "2024-04-29T22:37:15.618773", + "Assist": false, + "AssistanceHistory": null + }, + "q4": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:03.510069", + "StartTime": "2024-04-29T22:37:15.618799", + "EndTime": "2024-04-29T22:37:19.128868", + "Assist": true, + "AssistanceHistory": [] + }, + "q5": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:03.109200", + "StartTime": "2024-04-29T22:37:19.128890", + "EndTime": "2024-04-29T22:37:22.238090", + "Assist": false, + "AssistanceHistory": null + }, + "q6": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:03.934808", + "StartTime": "2024-04-29T22:37:22.238115", + "EndTime": "2024-04-29T22:37:26.172923", + "Assist": false, + "AssistanceHistory": null + }, + "q7": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:03.315112", + "StartTime": "2024-04-29T22:37:26.172946", + "EndTime": "2024-04-29T22:37:29.488058", + "Assist": false, + "AssistanceHistory": null + }, + "q8": { + "Response": "\"10:37pmmmmm\"", + "Assistance": null, + "CompletionTime": "0:00:04.129395", + "StartTime": "2024-04-29T22:37:29.488080", + "EndTime": "2024-04-29T22:37:33.617475", + "Assist": true, + "AssistanceHistory": [] + } +} \ No newline at end of file diff --git a/user_data/733d7eab-89bb-4e3d-a561-0f1ca072977d/questionnaire_733d7eab-89bb-4e3d-a561-0f1ca072977d.json b/user_data/733d7eab-89bb-4e3d-a561-0f1ca072977d/questionnaire_733d7eab-89bb-4e3d-a561-0f1ca072977d.json new file mode 100644 index 0000000000000000000000000000000000000000..0977a4e0314df040b667eab5eeb3ffb5b249360e --- /dev/null +++ b/user_data/733d7eab-89bb-4e3d-a561-0f1ca072977d/questionnaire_733d7eab-89bb-4e3d-a561-0f1ca072977d.json @@ -0,0 +1,41 @@ +{ + "Demographic Details": { + "What is your gender?": "Female", + "Which of the following best describes your race or ethnicity?": "Prefer not to say", + "How would you describe your socioeconomic status?": "Upper-middle", + "What is your primary language?": "English", + "What is your age range?": "18-24", + "What is the highest level of education you have completed?": "High school graduate", + "Which field best describes your current profession?": "Healthcare", + "How comfortable are you using LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?": "Slightly comfortable", + "How much experience do you have using LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?": "1 to 2 years", + "How often do you use LLMs (Large Language Models, such as ChatGPT, Claude, Gemini, etc.)?": "Occasionally (once a month to once a week)" + }, + "User Capabilities": { + "Do you identify as neurotypical or neurodivergent?": "Neurodivergent", + "How often do you experience focus issues or writer\u2019s block when writing?": "Rarely", + "How often do you feel that you can empathize with characters or subjects in your writing?": "Sometimes", + "What is your typical emotional state when writing?": "Somewhat stressed", + "How often do you engage in creative or thoughtful writing?": "Sometimes", + "How confident do you feel about your writing?": "Slightly confident", + "How comfortable are you with using writing-related technology?": "Not comfortable at all", + "How efficient do you consider yourself in writing tasks?": "Somewhat inefficient", + "How would you rate your expertise in writing?": "Intermediate" + }, + "Relationship to System": { + "How much control do you feel you have when using a writing assistant?": "A lot", + "How much ownership do you feel over your writings created with the help of a writing assistant?": "Most", + "How concerned are you about plagiarism when using a writing assistant?": "Slightly concerned", + "How much do you trust the writing assistant to help you effectively?": "Moderately", + "How important is it that the writing assistant is available whenever you need it?": "Slightly important", + "How concerned are you about your privacy when using a writing assistant?": "Moderately concerned", + "How well do you understand how the writing assistant works, including its capabilities and limitations?": "Moderately" + }, + "System Output Preferences": { + "How important is personalization of the outputs from the writing assistant according to your specific needs and preferences?": "Slightly important", + "How concerned are you about potential biases in the outputs from the writing assistant?": "Moderately concerned", + "How important is it for the writing assistant to provide explanations for its outputs?": "Slightly important", + "How much do you value novelty and diversity in the outputs from the writing assistant?": "A lot", + "How important is it for the outputs from the writing assistant to be grammatically and contextually coherent?": "Not important" + } +} \ No newline at end of file diff --git a/user_data/733d7eab-89bb-4e3d-a561-0f1ca072977d/questions_733d7eab-89bb-4e3d-a561-0f1ca072977d.json b/user_data/733d7eab-89bb-4e3d-a561-0f1ca072977d/questions_733d7eab-89bb-4e3d-a561-0f1ca072977d.json new file mode 100644 index 0000000000000000000000000000000000000000..7ff897ccd99a24f696fe4cf3300b76a998e908e8 --- /dev/null +++ b/user_data/733d7eab-89bb-4e3d-a561-0f1ca072977d/questions_733d7eab-89bb-4e3d-a561-0f1ca072977d.json @@ -0,0 +1,74 @@ +{ + "q1": { + "Response": "\"RESSSS\"", + "Assistance": null, + "CompletionTime": "0:01:18.973551", + "StartTime": "2024-04-29T22:29:56.509887", + "EndTime": "2024-04-29T22:31:15.483438", + "Assist": false, + "AssistanceHistory": null + }, + "q2": { + "Response": "\"YUHHHH\"", + "Assistance": null, + "CompletionTime": "0:00:11.061549", + "StartTime": "2024-04-29T22:31:15.483464", + "EndTime": "2024-04-29T22:31:26.545013", + "Assist": true, + "AssistanceHistory": [] + }, + "q3": { + "Response": "\"LESSGOOOOO\"", + "Assistance": null, + "CompletionTime": "0:00:05.198205", + "StartTime": "2024-04-29T22:31:26.545037", + "EndTime": "2024-04-29T22:31:31.743242", + "Assist": false, + "AssistanceHistory": null + }, + "q4": { + "Response": "\"IS IT WORKING \"", + "Assistance": null, + "CompletionTime": "0:00:07.930399", + "StartTime": "2024-04-29T22:31:31.743268", + "EndTime": "2024-04-29T22:31:39.673667", + "Assist": true, + "AssistanceHistory": [] + }, + "q5": { + "Response": "\"IS IT WORKING \"", + "Assistance": null, + "CompletionTime": "0:00:03.563272", + "StartTime": "2024-04-29T22:31:39.673692", + "EndTime": "2024-04-29T22:31:43.236964", + "Assist": false, + "AssistanceHistory": null + }, + "q6": { + "Response": "\"IS IT WORKING \"", + "Assistance": null, + "CompletionTime": "0:00:03.722451", + "StartTime": "2024-04-29T22:31:43.236990", + "EndTime": "2024-04-29T22:31:46.959441", + "Assist": false, + "AssistanceHistory": null + }, + "q7": { + "Response": "\"IS IT WORKING \"", + "Assistance": null, + "CompletionTime": "0:00:02.960702", + "StartTime": "2024-04-29T22:31:46.959468", + "EndTime": "2024-04-29T22:31:49.920170", + "Assist": false, + "AssistanceHistory": null + }, + "q8": { + "Response": "\"IS IT WORKING \"", + "Assistance": null, + "CompletionTime": "0:00:04.590047", + "StartTime": "2024-04-29T22:31:49.920195", + "EndTime": "2024-04-29T22:31:54.510242", + "Assist": true, + "AssistanceHistory": [] + } +} \ No newline at end of file diff --git a/utils.py b/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..eb869c4411af67309f44d556f49cd87fd052ba4d --- /dev/null +++ b/utils.py @@ -0,0 +1,429 @@ +import json +import os +import gradio as gr +from matplotlib import pyplot as plt + +from experiment_details import problem_topics, problems_per_topic, writing_skills_questions +from data import problems +from model_generate import chatbot_generate +import random +import re + +def process_markdown(prompt, question): + if prompt: + initial_path = './data/problems/' + else: + initial_path = './data/instructions/' + with open(initial_path + question, 'r') as md_file: + markdown_content = md_file.read() + return markdown_content + + +def strip_markdown(text): + """ + Strips common markdown formatting from a string. + """ + # Patterns to remove from the Markdown text + patterns = [ + r'\!\[[^\]]*\]\([^\)]+\)', # Images + r'\[[^\]]*\]\([^\)]+\)', # Links + r'\*\*(.*?)\*\*|__(.*?)__', # Bold + r'\*(.*?)\*|_(.*?)_', # Italics + r'\~\~(.*?)\~\~', # Strikethrough + r'\`{1,3}(.*?)\`{1,3}', # Inline code + r'\#{1,6}\s', # Headers + r'\>(.*?)\n', # Blockquotes + r'\-{3,}', # Horizontal rule + r'\n{2,}', # Multiple newlines + ] + + clean_text = text + for pattern in patterns: + clean_text = re.sub(pattern, '', clean_text) + + # Remove remaining newlines and leading/trailing whitespace + clean_text = clean_text.strip() + + return clean_text + + +def save_answer(question_answers, q_num, q_text, q_assist, q_assist_history=None): + q_num_key = 'q' + str(q_num) + question_answers[q_num_key]['Response'] = json.dumps(q_text, indent=4) + question_answers[q_num_key]['Assist'] = q_assist + question_answers[q_num_key]['AssistanceHistory'] = q_assist_history + + return question_answers + + +# Need to randomly select writing prompts for each of the 3 categories +def randomly_select_prompts(): + prompts = [] + # For each writing prompt, I need to randomly generate two numbers from 1-10 + shortstoryIDs = random.sample(range(1, 11), 2) + emailIDs = random.sample(range(1, 11), 2) + summaryIDs = random.sample(range(1, 11), 2) + titleIDs = random.sample(range(1, 11), 2) + for ssID in shortstoryIDs: + instr = 'instr_shortstory.md' + prompt_file = 'p_shortstory' + str(ssID) + '.md' + word_count = 300 + textfield_lines = 10 + question_details = { + 'instruction': instr, + 'prompt_file': prompt_file, + 'word_count': word_count, + 'textfield_lines': textfield_lines + } + prompts.append(question_details) + for eID in emailIDs: + instr = 'instr_email.md' + prompt_file = 'p_email' + str(eID) + '.md' + word_count = 300 + textfield_lines = 10 + question_details = { + 'instruction': instr, + 'prompt_file': prompt_file, + 'word_count': word_count, + 'textfield_lines': textfield_lines + } + prompts.append(question_details) + for sID in summaryIDs: + instr = 'instr_summary.md' + prompt_file = 'p_summary' + str(sID) + '.md' + word_count = 75 + textfield_lines = 5 + question_details = { + 'instruction': instr, + 'prompt_file': prompt_file, + 'word_count': word_count, + 'textfield_lines': textfield_lines + } + prompts.append(question_details) + for tID in titleIDs: + instr = 'instr_title.md' + prompt_file = 'p_title' + str(tID) + '.md' + word_count = 10 + textfield_lines = 2 + question_details = { + 'instruction': instr, + 'prompt_file': prompt_file, + 'word_count': word_count, + 'textfield_lines': textfield_lines + } + prompts.append(question_details) + return prompts + + +def randomize_questions(questions): + group1_indices = [0, 2, 4, 6] + group2_indices = [1, 3, 5, 7] + + # Extract items for each group + group1_items = [questions[i] for i in group1_indices] + group2_items = [questions[i] for i in group2_indices] + + # Shuffle each group + random.shuffle(group1_items) + random.shuffle(group2_items) + + # Re-insert shuffled items back into the original questions list + for idx, item in zip(group1_indices, group1_items): + questions[idx] = item + + for idx, item in zip(group2_indices, group2_items): + questions[idx] = item + + # Output the randomized list + return questions + + +def generate_unassisted_question(question_prompt, next_q_btn, q_num, question_answers): + with gr.Column("Unassisted Writing Task", render=False) as q_unassisted: + q_title_text = "#\n# Question " + str(q_num) + q_title = gr.Markdown(value=q_title_text) + + unassisted_instr = process_markdown(False, 'instr_unassisted.md') + unassisted_instr_md = gr.Markdown(value=unassisted_instr) + + instruction = question_prompt['instruction'] + prompt = question_prompt['prompt_file'] + max_word_count = question_prompt['word_count'] + textfield_lines = question_prompt['textfield_lines'] + + with gr.Column() as instructions: + # with gr.Group(): + gen_instr_text1 = process_markdown(False, instruction) + prompt_text1 = process_markdown(True, prompt) + gen_instr1 = gr.Markdown(value=gen_instr_text1) + with gr.Row(): + with gr.Column(scale=4): + prompt1 = gr.Markdown(value=prompt_text1) + with gr.Column(scale=1): + word_count = gr.Textbox( + label='Word Count', + interactive=False, + lines=1, + max_lines=1, + autoscroll=False, + autofocus=False, + # container=False + ) + + def count_words(x): + num_words = len(x.split()) + if num_words > max_word_count: + overflow = num_words-max_word_count + string_num = str(num_words) + " (REMOVE " + str(overflow) + " WORDS to submit your response)" + return { + text_button1: gr.Button(interactive=False), + word_count: gr.Textbox(string_num) + } + elif num_words < 1: + string_num = str(num_words) + " (Please enter your response)" + return { + text_button1: gr.Button(interactive=False), + word_count: gr.Textbox(string_num) + } + else: + string_num = str(num_words) + return { + text_button1: gr.Button(interactive=True), + word_count: gr.Textbox(string_num) + } + + success_submit_instr = process_markdown(False, 'instr_submitsuccess.md') + success_submitted = gr.Markdown(value=success_submit_instr, visible=False) + + tab_text1 = gr.Textbox( + lines=textfield_lines, + interactive=True, + show_copy_button=True, + container=True, + autoscroll=True, + autofocus=True, + label="Write your response here:") + + text_button1 = gr.Button("Submit Response", variant="primary", interactive=False) + tab_text1.input(count_words, tab_text1, [text_button1, word_count], show_progress="hidden") + + edit_response_instr = process_markdown(False, 'instr_editresponse.md') + edit_response = gr.Markdown(value=edit_response_instr, visible=False) + + back_btn = gr.Button("Return to previous question", visible=False) + proceed_instr = process_markdown(False, 'instr_proceed.md') + proceed_to_next = gr.Markdown(value=proceed_instr, visible=False) + + def click_back_btn(): + return { + success_submitted: gr.update(visible=False), + edit_response: gr.update(visible=False), + proceed_to_next: gr.update(visible=False), + back_btn: gr.update(visible=False), + gen_instr1: gr.update(visible=True), + prompt1: gr.update(visible=True), + tab_text1: gr.update(visible=True, interactive=True, show_label=True, show_copy_button=True, + container=True), + word_count: gr.update(visible=True), + text_button1: gr.update(visible=True), + next_q_btn: gr.update(visible=False), + unassisted_instr_md: gr.update(visible=True) + } + + back_btn.click( + fn=click_back_btn, + inputs=[], + outputs=[success_submitted, edit_response, proceed_to_next, back_btn, gen_instr1, prompt1, tab_text1, word_count, text_button1, next_q_btn, + unassisted_instr_md] + ) + + def submit_question(submission_text): + save_answer(question_answers, q_num, submission_text, False) + return { + success_submitted: gr.update(visible=True), + edit_response: gr.update(visible=True), + proceed_to_next: gr.update(visible=True), + back_btn: gr.update(visible=True), + gen_instr1: gr.update(visible=False), + prompt1: gr.update(visible=False), + tab_text1: gr.update(visible=True, interactive=False, show_label=False, show_copy_button=False, container=False), + word_count: gr.update(visible=False), + text_button1: gr.update(visible=False), + next_q_btn: gr.update(visible=True), + unassisted_instr_md: gr.update(visible=False) + } + text_button1.click( + fn=submit_question, + inputs=[tab_text1], + outputs=[success_submitted, edit_response, proceed_to_next, back_btn, gen_instr1, prompt1, tab_text1, word_count, + text_button1, next_q_btn, unassisted_instr_md] + ) + return q_unassisted + + +def generate_assisted_question(question_prompt, next_q_btn, q_num, question_answers): + with gr.Column("Assisted Writing Task", render=False) as q_assisted: + q_title_text = "#\n# Question " + str(q_num) + q_title = gr.Markdown(value=q_title_text) + + assisted_instr = process_markdown(False, 'instr_assisted.md') + assisted_instr_md = gr.Markdown(value=assisted_instr) + + instruction = question_prompt['instruction'] + prompt = question_prompt['prompt_file'] + max_word_count = question_prompt['word_count'] + textfield_lines = question_prompt['textfield_lines'] + + + + gen_instr_text2 = process_markdown(False, instruction) + prompt_text2 = process_markdown(True, prompt) + + instruction_txt = strip_markdown(gen_instr_text2) + prompt_txt = strip_markdown(prompt_text2) + + + gen_instr2 = gr.Markdown(value=gen_instr_text2) + with gr.Row(): + with gr.Column(scale=4): + prompt2 = gr.Markdown(value=prompt_text2) + with gr.Column(scale=1): + word_count = gr.Textbox( + label='Word Count', + interactive=False, + lines=1, + max_lines=1, + autoscroll=False, + autofocus=False, + # container=False + ) + + def count_words(x): + num_words = len(x.split()) + if num_words > max_word_count: + overflow = num_words-max_word_count + string_num = str(num_words) + " (REMOVE " + str(overflow) + " WORDS to submit your response)" + return { + text_button2: gr.Button(interactive=False), + word_count: gr.Textbox(string_num) + } + elif num_words < 1: + string_num = str(num_words) + " (Please enter your response)" + return { + text_button2: gr.Button(interactive=False), + word_count: gr.Textbox(string_num) + } + else: + string_num = str(num_words) + return { + text_button2: gr.Button(interactive=True), + word_count: gr.Textbox(string_num) + } + + initial_user_message = "You are my helpful writing assistant. " \ + "As the writer that you will assist, " \ + "I will ask you for help in answering a writing prompt. " \ + "You may answer all of my questions about the prompt and writing task. " \ + "However, if I ask you to answer the entire prompt, you may only provide me with the first three sentences. " \ + "Again, you can still answer all of the questions that I have and give me all of the help I desire, but you may NOT give me the entire answer. " \ + "Here are the instructions: " + instruction_txt + '. Here is the writing prompt: ' + prompt_txt + '. Wait until I ask you for help.' + + initial_conversation = [ + # initial_user_message, + # "AI: As a writing assistant, my goal is to help you with your writing task." + ] + with gr.Column() as chatbot_col: + chatbot = gr.Chatbot(initial_conversation, height=300, label="Writing Helper") + # Chat state + state = gr.State(initial_conversation) + # Model state + initial_usr_msg_state = gr.State(initial_user_message) + model_state = gr.State("chatgpt4") + with gr.Column() as chat_feature: + with gr.Group(): + with gr.Row(): + txt = gr.Textbox( + value="", + show_label=False, + placeholder="Enter text and press the Interact button", + lines=2, + container=False, + scale=4) + submit_button = gr.Button("Interact", variant="primary", scale=1, size="sm") + # Button for submission + + success_submit_instr = process_markdown(False, 'instr_submitsuccess.md') + success_submitted = gr.Markdown(value=success_submit_instr, visible=False) + + tab_text2 = gr.Textbox( + lines=textfield_lines, + interactive=True, + show_copy_button=True, + container=True, + autoscroll=True, + autofocus=True, + label="Write your response here:") + + submit_button.click(chatbot_generate, [txt, state, model_state, tab_text2, initial_usr_msg_state], [chatbot, state, txt, submit_button]) + + text_button2 = gr.Button("Submit Response", variant="primary", interactive=False) + tab_text2.input(count_words, tab_text2, [text_button2, word_count], show_progress="hidden") + + edit_response_instr = process_markdown(False, 'instr_editresponse.md') + edit_response = gr.Markdown(value=edit_response_instr, visible=False) + + back_btn = gr.Button("Return to question", visible=False) + proceed_instr = process_markdown(False, 'instr_proceed.md') + proceed_to_next = gr.Markdown(value=proceed_instr, visible=False) + + def click_back_btn(): + return { + success_submitted: gr.update(visible=False), + edit_response: gr.update(visible=False), + proceed_to_next: gr.update(visible=False), + back_btn: gr.update(visible=False), + gen_instr2: gr.update(visible=True), + prompt2: gr.update(visible=True), + tab_text2: gr.update(visible=True, interactive=True, show_label=True, show_copy_button=True, + container=True), + word_count: gr.update(visible=True), + text_button2: gr.update(visible=True), + chatbot_col: gr.update(visible=True), + chat_feature: gr.update(visible=True), + next_q_btn: gr.update(visible=False), + assisted_instr_md: gr.update(visible=True) + } + + back_btn.click( + fn=click_back_btn, + inputs=[], + outputs=[success_submitted, edit_response, proceed_to_next, back_btn, gen_instr2, prompt2, tab_text2, word_count, + chatbot_col, chat_feature, text_button2, next_q_btn, assisted_instr_md] + ) + + def submit_question(submission_text, assistance_history: None): + save_answer(question_answers, q_num, submission_text, True, assistance_history) + return { + success_submitted: gr.update(visible=True), + edit_response: gr.update(visible=True), + proceed_to_next: gr.update(visible=True), + back_btn: gr.update(visible=True), + gen_instr2: gr.update(visible=False), + prompt2: gr.update(visible=False), + tab_text2: gr.update(visible=True, interactive=False, show_label=False, show_copy_button=False, + container=False), + word_count: gr.update(visible=False), + text_button2: gr.update(visible=False), + chatbot_col: gr.update(visible=False), + chat_feature: gr.update(visible=False), + next_q_btn: gr.update(visible=True), + assisted_instr_md: gr.update(visible=False) + } + + text_button2.click( + fn=submit_question, + inputs=[tab_text2, state], + outputs=[success_submitted, edit_response, proceed_to_next, back_btn, gen_instr2, prompt2, tab_text2, word_count, + text_button2, chatbot_col, chat_feature, next_q_btn, assisted_instr_md] + ) + return q_assisted