Spaces:
Runtime error
Runtime error
File size: 25,010 Bytes
26646d1 fa332bc 9645af1 788c8dd 74712a2 26646d1 fd6872e ac64b10 26646d1 443350b 22c55ae dfea164 c3194b6 443350b a4aa3ce f3eea8c 4e565d4 f3eea8c 0cdfb60 2fd49c8 4e565d4 2fd49c8 478ab9e 4e565d4 e52bf75 9a5dc5f 812a128 e52bf75 9a5dc5f e52bf75 9a5dc5f 81dbd3f e52bf75 9a5dc5f 81dbd3f ec025ad 9a5dc5f e52bf75 4e565d4 0cdfb60 697d123 478ab9e 4e565d4 478ab9e 4e565d4 e3da687 fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 cf552d5 fd6872e fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 cf552d5 fc2b768 b12953f 7165525 dfea164 fc2b768 cf552d5 e3da687 fc2b768 9b6ecc8 cf552d5 e0c3074 cf552d5 d495438 e0c3074 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cf552d5 507bb2d cf552d5 d495438 e0c3074 507bb2d cf552d5 e0c3074 cfa53ba e0c3074 fc2b768 e3da687 706a0f2 e0c3074 0e65a32 fc2b768 706a0f2 0e65a32 706a0f2 e0c3074 706a0f2 e3da687 706a0f2 8ef2454 706a0f2 9501bbf e85f285 9501bbf e3da687 71e148e 97c8a43 71e148e 242c62f 71e148e 706a0f2 242c62f 706a0f2 242c62f 706a0f2 242c62f 706a0f2 242c62f 706a0f2 71e148e e3da687 71e148e 9501bbf 9b6ecc8 9501bbf b2f23d4 71e148e dd62bca 9645af1 1fd6e46 8ef2454 1fd6e46 9645af1 1fd6e46 9645af1 71e148e 74712a2 a4aa3ce 26646d1 e3da687 478ab9e e52bf75 a4aa3ce 26646d1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 |
import gradio as gr
import random
import time
import os
import re
import time
import openai
# Set up OpenAI API key
#valapikey = ""
system_message = "You are an assistant simulating the behavior of the participants in a focus group and answer a set of questions. Your first task will be to generate the profiles of the focus group then to simulate their answers to the question for each member."
with gr.Blocks() as demo:
with gr.Row():
gr.Markdown("Author: Taeko Sakai")
with gr.Row():
gr.Markdown("This application generates a focus group to answer your questions.\nFirst, list your topic and questions, then generate the focus group profile, finally get their answers and access the summary report")
with gr.Row():
gr.Markdown("DISCLAIMER: The content generated will be depending on the input you integrated in the respective fields and the behavior of the large language model (GPT4) used for the text generation.")
with gr.Row(visible = True) as apicheck:
with gr.Column(scale = 6):
apikey = gr.Textbox(label='Paste here your OpenAI - API key', info='No API key is stored and only you will see it.', lines = 1)
with gr.Column(scale = 1):
useapi = gr.Button("Use this API key")
with gr.Row():
language = gr.Textbox(label='Input your language for the results', lines = 1, value = 'English')
with gr.Row(visible = False) as fullblock:
with gr.Tab("Enquiry Description"):
with gr.Row():
gr.Markdown("Describe your project or study")
with gr.Row():
title = gr.Textbox(label='Topic you would like to submit to your focus group', lines = 5, placeholder = "ex: Ice cream tastes or smartphone features")
with gr.Row():
gr.Markdown("List all your questions")
with gr.Row():
question1 = gr.Textbox(label="Question 1", lines=2, placeholder = "ex: What are your favorite features for a smartphone?")
with gr.Row():
question2 = gr.Textbox(label="Question 2", lines=2, placeholder = "ex: How much would you be willing to pay for x, y , z (in USD)?")
with gr.Row():
question3 = gr.Textbox(label="Question 3", lines=2, placeholder = "ex: If you had no budget limit, what would be your dream functionality for a smartphone?")
with gr.Tab("Focus Group Profiles Generation"):
with gr.Row():
gr.Markdown("Describe types of profiles you want in your focus group")
with gr.Row():
focusgroupdescription = gr.Textbox(label="Describe your focus group desired characteristics", info= "For example: women in their 30s, teenagers, mixed ethnicity from Vietnam, ...", lines=5)
with gr.Row():
generategroup = gr.Button("Generate my focus group")
with gr.Row():
gr.Markdown("Participants")
with gr.Row():
expert1 = gr.Textbox(label="Participant 1", lines=5)
expert2 = gr.Textbox(label="Participant 2", lines=5)
with gr.Row():
expert3 = gr.Textbox(label="Participant 3", lines=5)
expert4 = gr.Textbox(label="Participant 4", lines=5)
with gr.Row():
expert5 = gr.Textbox(label="Participant 5", lines=5)
expert6 = gr.Textbox(label="Participant 6", lines=5)
with gr.Row():
expert7 = gr.Textbox(label="Participant 7", lines=5)
expert8 = gr.Textbox(label="Participant 8", lines=5)
with gr.Row():
expert9 = gr.Textbox(label="Participant 9", lines=5)
expert10 = gr.Textbox(label="Participant 10", lines=5)
with gr.Tab("Results"):
with gr.Row():
generateresults = gr.Button("Generate focus group answers")
with gr.Row():
gr.Markdown("Responses from the focus group participants")
with gr.Row():
response1 = gr.Textbox(label="Response 1", lines=10)
response2 = gr.Textbox(label="Response 2", lines=10)
with gr.Row():
response3 = gr.Textbox(label="Response 3", lines=10)
response4 = gr.Textbox(label="Response 4", lines=10)
with gr.Row():
response5 = gr.Textbox(label="Response 5", lines=10)
response6 = gr.Textbox(label="Response 6", lines=10)
with gr.Row():
response7 = gr.Textbox(label="Response 7", lines=10)
response8 = gr.Textbox(label="Response 8", lines=10)
with gr.Row():
response9 = gr.Textbox(label="Response 9", lines=10)
response10 = gr.Textbox(label="Response 10", lines=10)
with gr.Tab("Summary"):
with gr.Row():
generatesummary = gr.Button("Generate the focus group summary")
with gr.Row():
summary = gr.Textbox(label="Report summary", lines=50)
with gr.Row():
with gr.Accordion("Restore", open = False):
restore = gr.Button("Restore data from report")
clear = gr.Button("Clear", visible = False)
def uploaddetailsfromreport(report):
# Extract title
title = re.search(r'which title is:(.+)\n', report).group(1)
# Extract questions from summary report
questions = re.findall(r'Question \d: (.+)', report)[:3]
# Extract participant profiles and answers
participant_profiles = re.findall(r'// Profile (\d+) //\n(.+?)\n={10}', report, re.DOTALL)
participant_answers = re.findall(r'Participant answers:\n(.+?)\-{5}', report, re.DOTALL)
# Combine all the extracted values
output = [title] + questions
for (profile_num, profile), answer in zip(participant_profiles, participant_answers):
output.append(profile_num)
output.append(profile.strip())
output.append(answer.strip())
#print(output)
return output[0], output[1], output[2], output[3], output[5], output[8], output[11], output[14], output[17], output[20], output[23], output[26], output[29], output[32], output[6], output[9], output[12], output[15], output[18], output[21], output[24], output[27], output[30], output[33]
def checkapiinput(apikey):
if apikey != "" and apikey is not None and len(apikey) >=25 and len(apikey) <= 130:
OPENAI_API_KEY =apikey
openai.api_key = OPENAI_API_KEY
return gr.update(visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=True)
else:
return gr.update(visible=False), gr.update(visible=True), gr.update(value="", placeholder="Use a valid API key"), gr.update(visible=False)
def summarize(title, language, question1, question2, question3, expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10, response1, response2, response3, response4, response5, response6, response7, response8, response9, response10):
prompt = f"""
You are asked to make a report summarizing the inputs from 10 participants from a focus groups on this topic:
{title}
The questions asked were:
Question 1: {question1}
Question 2: {question2}
Question 3: {question3}
The profiles and their answers are:
Profile 1:
{expert1}
Participant answers:
{response1}
=====================
Profile 2:
{expert2}
Participant answers:
{response2}
=====================
Profile 3:
{expert3}
Participant answers:
{response3}
=====================
Profile
{expert4}
Participant answers:
{response4}
=====================
Profile 5:
{expert5}
Participant answers:
{response5}
=====================
Profile 6:
{expert6}
Participant answers:
{response6}
=====================
Profile 7:
{expert7}
Participant answers:
{response7}
=====================
Profile 8:
{expert8}
Participant answers:
{response8}
=====================
Profile 9:
{expert9}
Participant answers:
{response9}
=====================
Profile 10:
{expert10}
Participant answers:
{response10}
Follow these rules:
- Combine each points from the participants answers per question, start with 'Question 1:' and repeat the question then provide the arguments brought by the participants below. Then do the same for Question 2 and Question 3
- Provide all the arguments brought by the participants per question, breaking down the nuance per demographic or profession or any social / profiling category you see fit
- Keep all the points raised by the participants with details, break them down in a rational and professional way - do not loose details.
- For each question, provide a recommendation for action to address the needs expressed in the answers for each question, start it with "Recommendation:" then add your prespecriptions on bullet points just asfter
Now please provide your summary and recommendations for each of the questions using the following language: {language}
"""
formattedprompt = [{'role':'system','content':system_message},{'role':'user','content':prompt}]
result = answer(formattedprompt, "gpt-4")
result = f"""This is summary report on a focus group which title is: {title}
--- Summary report ---
{result}
----------------------------- APPENDIX / Profiles and Raw results from participants -----------------------------
// Profile 1 //
{expert1}
=====================
Participant answers:
{response1}
------------------------------------------------------------------------------------------------------------------
// Profile 2 //
{expert2}
=====================
Participant answers:
{response2}
------------------------------------------------------------------------------------------------------------------
// Profile 3 //
{expert3}
=====================
Participant answers:
{response3}
------------------------------------------------------------------------------------------------------------------
// Profile 4 //
{expert4}
=====================
Participant answers:
{response4}
------------------------------------------------------------------------------------------------------------------
// Profile 5 //
{expert5}
=====================
Participant answers:
{response5}
------------------------------------------------------------------------------------------------------------------
// Profile 6 //
{expert6}
=====================
Participant answers:
{response6}
------------------------------------------------------------------------------------------------------------------
// Profile 7 //
{expert7}
=====================
Participant answers:
{response7}
------------------------------------------------------------------------------------------------------------------
// Profile 8 //
{expert8}
=====================
Participant answers:
{response8}
------------------------------------------------------------------------------------------------------------------
// Profile 9 //
{expert9}
=====================
Participant answers:
{response9}
------------------------------------------------------------------------------------------------------------------
// Profile 10 //
{expert10}
=====================
Participant answers:
{response10}
------------------------------------------------------------------------------------------------------------------
"""
return result
def generateanswers(title, language, question1, question2, question3, expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10):
personalities = [expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10]
results = []
for personality in personalities:
prompt = f"""
You are simulating this profile:
{personality}.
With this personality profile impersonation, please answer the 3 questions related to this topic:
{title}
The questions are:
Question 1: {question1}
Question 2: {question2}
Question 3: {question3}
Follow these rules:
- Repeat the question first starting with "Question 1: ... then provide the answer at the line
- Answer as the personality specified would, don't give answers that would not match this persona
- Don't start by reminding your identity, provide your answer directly (we know who you are impersonating)
- Answer in minimum 10 sentences for each question
- Don't be too moralizing (environment safety, social impact...)
- Use the style and vernacular language or the age and location (in English though)
- Add a high level of burstiness and perplexity to your answers
Here is 1 example of answers for inspiration for a focus group on outdoor activities in Hong Kong Lantau island from a profile who is Age: 19, Gender: Male, Location: Hong Kong, Occupation: University Student
Marital Status: Single
Question 1: What are the criteria for you to choose your outing activities?
When I’m picking my activities, it boils down to three things really - fun, friends, and a bit of a workout. Like, I’m super into sports, so something like hiking or basketball is totally up my alley. And of course, my mates have got to be there, it’s always more fun when the gang’s together!
Question 2: What activities would you recommend for teenagers in summer?
Well, for my fellow teens in Hong Kong, I have to say, don’t miss out on the hikes on Lantau Island or any of the fab beach outings. There’s no better way to beat the heat than a dip in the sea after a killer hike. And sports, guys - just grab a ball and hit the nearest park, works every time. Summer in the city isn’t complete without a few local events too, brings everyone together.
Question 3: What are your views about junk boats?
In my opinion, junk boats are wicked! They’re like a slice of Old Hong Kong in the here and now. Perfect for a party with pals, you know. But, I reckon we’ve all got a part to play in looking after our nature and wildlife, so we should make sure our fun on the junks isn’t harming the aquatic life around us. Let’s party, but let’s also keep it green, folks!
Now please provide your results using the following language: {language}
"""
formattedprompt = [{'role':'system','content':system_message},{'role':'user','content':prompt}]
result = answer(formattedprompt, "gpt-4")
results.append(result)
return results[0], results[1], results[2], results[3], results[4], results[5], results[6], results[7], results[8], results[9]
def parse_participants(input_string: str) -> list:
# Replace <br> tags with newline characters
input_string = input_string.replace("<br>", "\n")
# Split the input string using a regular expression for “Participant X”
participants = re.split(r'Participant \d+:\n', input_string)[1:] # Ignore the first split item since it’s empty
# Parse each participant’s details and add them to a list
participant_details = []
for participant in participants:
details = '\n'.join(participant.strip().split("\n"))
participant_details.append(details)
return participant_details
def generateprofiles(title, language, question1, question2, question3, focusgroupdescription):
prompt = f"""
Please generate 10 profiles for a focus group that would have the following features:
- Title: {title}
- Questions the focus group participants will have to answer:
o Question 1: {question1}
o Question 2: {question2}
o Question 3: {question3}
- These are the desired characteristics provided by the user for the focus group:
{focusgroupdescription}
Now generate 10 (ten) profiles aligned with these features following these rules:
- Each profile will start with: 'Participant x:' (with x being the reference number of the profile) then the profile details would be on the following line
- Profiles will be separated by an empy line, see examples below
- Profiles should not be more than 20 lines long
- Do not start with any introductory wording, directly provide the results, the first line should be 'Participant 1:'
- Do not add any conclusion to your result
Here are 2 examples of profiles for inspiration (for a focus group on sparkling drinks), One from Hong Kong, another one from Singapore:
Participant 1:
Name: Lai Mei Chen / Age: 30 years old / Gender: Female / Location: Hong Kong
Occupation: Marketing Specialist
Marital Status: Single
Education: Bachelor’s Degree in Business Administration
- Background: Lai Mei Chen is a young professional working in the marketing sector with a focus on consumer goods and lifestyle products. She has always been interested in the psychology of consumer behavior and how it influences purchasing decisions. During her university years, she took part in a number of focus groups for marketing research projects, which only fueled her passion for the field.
- Interests:
Lai Mei enjoys the everyday hustle in the busy city of Hong Kong and is always eager to try out new places and experiences. She has a particular interest in food and beverages, being an amateur at food photography and frequently post about new and upcoming trends on her personal blog and social media accounts.
Lai Mei is also an environmental enthusiast and is mindful of the ecological impact of the products she consumes. This has led her to adopt a “greener” lifestyle by trying to reduce waste, recycling, and frequently supporting sustainable local businesses.
- Relationship with the topic of the focus group:
During her childhood, Lai Mei’s family wouldn’t consume a lot of sparkling drinks, but she still developed a love for them as an adult. She enjoys the bubbly sensation and refreshing taste, especially during the hot summer months in Hong Kong.
Lai Mei perceives sparkling drinks as a treat for herself after a long day at work. She is always interested in discovering new brands and flavors, and she often chooses those with unique or exotic ingredients.
- Attitude Towards the topic of the focus group:
Lai Mei prefers sparkling drinks that are made with natural ingredients and use less artificial sweeteners. She believes that indulging in these drinks should not compromise her health or have detrimental effects on the environment. Therefore, she searches for drinks that come in recyclable packaging and have a reduced carbon footprint.
What Lai Mei Can Offer As A Participant In The Focus Group:
Coming from a marketing background gives Lai Mei the expertise to provide feedback on product packaging, messaging, and market positioning strategies. Additionally, being a social media-savvy individual and an influencer in her circle, she can suggest innovative ways to engage with the target audience and advocate for sustainable and healthier options in the sparkling drinks market. Furthermore, Lai Mei’s environment-conscious attitude and keen interest in the F&B industry allows her to provide valuable insights and preferences, which cater to the ever-growing eco-aware consumer base.
Participant 2:
Name: Nurul Amira Binti Iskandar / Age: 30 years old / Gender: Female / Location: Singapore
Occupation: Interior Designer
Marital Status: Married
Education: Bachelor’s Degree in Interior Design
- Background: Nurul Amira is a talented interior designer working for a reputable design firm in Singapore, with several successful projects under her belt. She enjoys working with various clients to create beautiful and functional spaces in homes, offices, and commercial establishments.
Nurul Amira is married to her husband, Syafiq, and together they share a love for traveling and exploring diverse cultures. They often participate in local events and community programs as a way of giving back to their society.
- Interests:
In her spare time, Nurul Amira enjoys visiting art exhibitions and galleries to stay updated on the latest design trends and draw inspiration for her projects. She also has a strong interest in fashion and follows several local and international designers on social media platforms.
Nurul Amira is also health-conscious and actively practices yoga and Pilates to maintain a balanced lifestyle. She is an advocate for healthy eating and often cooks nutritious meals for herself and her husband.
- Relationship with the topic of the focus group:
Coming from a tropical country, Nurul Amira is no stranger to the refreshing quality of sparkling drinks. She enjoys their effervescent texture and often indulges in them during social gatherings, family dinners, and festive occasions.
Nurul Amira prefers fruity flavors in her sparkling drinks but also likes to experiment with different combinations. She often goes for sugar-free or reduced sugar options to maintain a healthier lifestyle.
- Attitude Towards the topic of the focus group:
As a health-conscious individual, Nurul Amira is particular about the sparkling drinks she consumes, especially when it comes to ingredients and calorie content. She looks for options that are made from natural ingredients and have lower sugar levels, without compromising on taste and flavor.
What Nurul Amira Can Offer as a Participant in the Focus Group:
As an interior designer with a keen eye for detail, Nurul Amira can provide valuable insights into the packaging, visual appeal, and design elements of sparkling drinks. Her understanding of contemporary lifestyle trends and her focus on healthy living can help brands identify potential avenues for product improvement and promotion.
Nurul Amira’s experience in social events and gatherings also allows her to gauge how specific products may fare in various social scenarios and how they may fit into, or be adapted to, the ever-evolving preferences and tastes of the Singaporean consumer. Her participation in the focus group would provide an accurate representation of a health-conscious, modern consumer in Singapore and contribute meaningfully to the discussion.
Now please provide your results using the following language: {language}.
"""
formattedprompt = [{'role':'system','content':system_message},{'role':'user','content':prompt}]
list = []
while len(list) <10:
result = answer(formattedprompt, "gpt-4")
#break it down
list = parse_participants(result)
return list[0], list[1], list[2], list[3], list[4], list[5], list[6], list[7], list[8], list[9]
def answer(formattedprompt, model):
#Now let's try 10 times
for attempt in range(10):
try:
response = openai.ChatCompletion.create(
model=model,
messages=formattedprompt
)
result = response['choices'][0]['message']['content']
break
except Exception as e:
print(f"Error occurred on attempt {attempt + 1}: {e}")
if attempt < 10:
time.sleep(10)
else:
raise e
return result
def init_history(title):
return "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""
generategroup.click(generateprofiles, [title, language, question1, question2, question3, focusgroupdescription], [expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10])
generateresults.click(generateanswers, [title, language, question1, question2, question3, expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10], [response1, response2, response3, response4, response5, response6, response7, response8, response9, response10])
generatesummary.click(summarize, [title, language, question1, question2, question3, expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10, response1, response2, response3, response4, response5, response6, response7, response8, response9, response10], summary)
useapi.click(checkapiinput, apikey, [fullblock, apicheck, apikey, clear])
restore.click(uploaddetailsfromreport, summary, [title, question1, question2, question3, expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10, response1, response2, response3, response4, response5, response6, response7, response8, response9, response10])
clear.click(init_history, title, [title, question1, question2, question3, focusgroupdescription, expert1, expert2, expert3, expert4, expert5, expert6, expert7, expert8, expert9, expert10, response1, response2, response3, response4, response5, response6, response7, response8, response9, response10, summary])
demo.launch() |