| import gradio as gr |
| from openai import OpenAI |
| import os |
| import random |
| import asyncio |
|
|
| client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) |
|
|
| DEFAULT_LANGUAGE = "English" |
| WELCOME_MESSAGE_EN = "Hi! I'm Robin, your dialogue partner.\nWe're about to begin a conversation that includes nine questions. Are you ready?\nPlease tell me which language you'd like to use." |
|
|
| |
| NORMAL_SET_I = [ |
| "When was the last time you walked for more than an hour? Please describe what you saw.", |
| "What is the best gift you have ever received? Why?", |
| "If you had to leave your current city, where would you move to? What do you miss most about your current city?", |
| "How did you celebrate the New Year last year, if you still remember?", |
| "Do you read newspapers often? Why?", |
| "What is the ideal number of students to share a house with? Why?", |
| "If you could invent a new flavor of ice cream, what flavor would you create?", |
| "What is the best restaurant you have been to in the past month? Please describe it.", |
| "Please describe the pet you last got.", |
| "What is your favorite holiday? Why?", |
| "Can you tell me something funny that happened when you were spending time with a child?" |
| ] |
| NORMAL_SET_II = [ |
| "What gift did you get on your last birthday?", |
| "Please tell me something about your last trip to the zoo.", |
| "Is there someone in your family you feel especially close to? What makes your bond strong?", |
| "Imagine we were both stranded on a tropical island. What would be the first thing you would do?", |
| "Do you like to wake up early or stay up late? Has anything interesting ever happened to you because of this?", |
| "If you could choose to live anywhere, what city or environment would you choose?", |
| "What is your favorite subject in school and why?", |
| "What is your plan for the next holiday?", |
| "What gifts did you receive for Christmas or New Year last year?", |
| "Who is your favorite actor or actress? ", |
| "What was your impression of your university when you first came to it?", |
| "What is the best TV show you have seen in the past month? Please describe it a little bit.", |
| "Do you have a favorite season or time of year? Why do you like it?" |
| ] |
| NORMAL_SET_III = [ |
| "What do you remember most about your time in high school?", |
| "What is the best book you have read in the past three months? ", |
| "What country would you most like to visit? What attracts you to it?", |
| "Do you prefer digital or analog watches/clocks? Why?", |
| "Can you think of someone your mother or father is really close to? What do you think makes their friendship special?", |
| "What are the pros and cons of artificial Christmas trees?", |
| "How often do you get your hair cut? Have you ever had a bad haircut?", |
| "Did you have a class pet in elementary school? Do you remember its name?", |
| "Do you think left-handed people are more creative than right-handed people?", |
| "What was the last concert you attended? How was the concert?", |
| "What magazines do you subscribe to? What have you subscribed to in the past?", |
| "Have you ever participated in a school play? What role did you play? Did anything funny happen during the play?" |
| ] |
|
|
| def generate_question_set(): |
| return random.sample(NORMAL_SET_I, 3) + random.sample(NORMAL_SET_II, 3) + random.sample(NORMAL_SET_III, 3) |
|
|
| async def gpt_translate(text, target_lang): |
| if target_lang == "English": |
| return text |
| prompt = f"Translate the following into {target_lang}:\n\n{text}" |
| response = client.chat.completions.create( |
| model="gpt-3.5-turbo", |
| messages=[{"role": "user", "content": prompt}], |
| temperature=0.3 |
| ) |
| return response.choices[0].message.content.strip() |
|
|
| async def respond(user_input, history, step, language, questions, followup_mode): |
| history.append({"role": "user", "content": user_input}) |
|
|
| if language == "": |
| user_language = user_input.strip().capitalize() |
| questions_en = generate_question_set() |
| translated_questions = [await gpt_translate(q, user_language) for q in questions_en] |
| welcome = await gpt_translate("Great! We will now continue in your selected language.", user_language) |
| history.append({"role": "assistant", "content": ""}) |
| for c in f"{welcome}\n\n1. {translated_questions[0]}": |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
| return history, "", 1, user_language, translated_questions, False |
|
|
| if step >= len(questions): |
| thank_you = await gpt_translate("Thank you for your response! It was a pleasure talking with you. I hope you enjoyed the conversation.", language) |
| end_note = await gpt_translate("This concludes our questions. Please proceed with the rest of the survey. 📝", language) |
| for msg in [thank_you, end_note]: |
| history.append({"role": "assistant", "content": ""}) |
| for c in msg: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
| return history, "", step, language, questions, False |
|
|
| if followup_mode: |
| comment_prompt = [ |
| {"role": "system", "content": f"Write a short, empathetic comment in {language} responding to the user's last answer."}, |
| history[-2], |
| history[-1] |
| ] |
| comment_response = client.chat.completions.create( |
| model="gpt-3.5-turbo", |
| messages=comment_prompt, |
| temperature=0.7 |
| ) |
| comment = comment_response.choices[0].message.content.strip() |
|
|
| rand = random.random() |
| if rand < 0.1: |
| followup_prompt = [ |
| {"role": "system", "content": f"Ask one open-ended follow-up question in {language} based on the user's last answer."}, |
| history[-2], |
| history[-1] |
| ] |
| followup_response = client.chat.completions.create( |
| model="gpt-3.5-turbo", |
| messages=followup_prompt, |
| temperature=0.7 |
| ) |
| followup_question = followup_response.choices[0].message.content.strip() |
|
|
| history.append({"role": "assistant", "content": ""}) |
| for c in comment: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| history.append({"role": "assistant", "content": ""}) |
| for c in followup_question: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| return history, "", step, language, questions, True |
| else: |
| history.append({"role": "assistant", "content": ""}) |
| for c in comment: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| next_question = f"{step+1}. {questions[step]}" |
| history.append({"role": "assistant", "content": ""}) |
| for c in next_question: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| return history, "", step + 1, language, questions, False |
|
|
| comment_prompt = [ |
| {"role": "system", "content": f"Write a short, personalized comment in {language} responding to the user's answer. Add a light emoji."}, |
| history[-2], |
| history[-1] |
| ] |
| comment_response = client.chat.completions.create( |
| model="gpt-3.5-turbo", |
| messages=comment_prompt, |
| temperature=0.7 |
| ) |
| comment = comment_response.choices[0].message.content.strip() |
|
|
| rand = random.random() |
| if rand < 0.4: |
| followup_prompt = [ |
| {"role": "system", "content": f"Ask one open-ended follow-up question in {language} based on the user's answer."}, |
| history[-2], |
| history[-1] |
| ] |
| followup_response = client.chat.completions.create( |
| model="gpt-3.5-turbo", |
| messages=followup_prompt, |
| temperature=0.7 |
| ) |
| followup_question = followup_response.choices[0].message.content.strip() |
|
|
| history.append({"role": "assistant", "content": ""}) |
| for c in comment: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| history.append({"role": "assistant", "content": ""}) |
| for c in followup_question: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| return history, "", step, language, questions, True |
| else: |
| history.append({"role": "assistant", "content": ""}) |
| for c in comment: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| next_question = f"{step+1}. {questions[step]}" |
| history.append({"role": "assistant", "content": ""}) |
| for c in next_question: |
| history[-1]["content"] += c |
| await asyncio.sleep(0.03) |
|
|
| return history, "", step + 1, language, questions, False |
|
|
| def init(): |
| return [{"role": "assistant", "content": WELCOME_MESSAGE_EN}], 0, "", [], False |
|
|
|
|
| with gr.Blocks(css=""" |
| .send-btn { |
| background-color: #25D366 !important; |
| color: white !important; |
| border: none; |
| border-radius: 24px; |
| font-size: 20px; |
| padding: 8px 20px; |
| height: 48px; |
| width: 60px; |
| margin-left: 8px; |
| cursor: pointer; |
| } |
| #chatbox .avatar-container { |
| width: 54px !important; |
| height: 54px !important; |
| min-width: 54px !important; |
| min-height: 54px !important; |
| background-size: 100% 100% !important; |
| background-position: center center !important; |
| border-radius: 50% !important; |
| padding: 0 !important; |
| margin: 0 !important; |
| border: none !important; |
| box-shadow: none !important; |
| background-color: transparent !important; |
| } |
| #chatbox .message.user { background-color: #DCF8C6 !important; } |
| #chatbox .message { |
| display: inline-block !important; |
| font-size: 16px !important; |
| line-height: 1.3em !important; |
| min-width: 7ch !important; |
| max-width: 60ch !important; |
| padding: 2px 3px !important; |
| border-radius: 8px !important; |
| word-break: break-word !important; |
| white-space: normal !important; |
| } |
| @media screen and (max-width: 768px) { |
| #chatbox .message.user { |
| max-width: 90vw !important; |
| } |
| } |
| #chatbox .message.user { |
| background-color: #DCF8C6 !important; |
| min-width: 60px !important; |
| max-width: fit-content !important; |
| } |
| #chatbox .message.assistant { background-color: #ffffff !important; } |
| footer { display: none !important; } |
| .svelte-1ipelgc { display: none !important; } |
| .icon-button-wrapper { |
| display: none !important; |
| } |
| label.svelte-1to105q { |
| display: none !important; |
| } |
| """) as demo: |
| gr.HTML(""" |
| <script> |
| const waitForChatbox = () => { |
| const chatbox = document.getElementById("chatbox"); |
| if (chatbox) { |
| const observer = new MutationObserver(() => { |
| chatbox.scrollTop = chatbox.scrollHeight; |
| }); |
| observer.observe(chatbox, { childList: true, subtree: true }); |
| } else { |
| setTimeout(waitForChatbox, 500); |
| } |
| }; |
| waitForChatbox(); |
| </script> |
| """) |
|
|
| chatbot = gr.Chatbot( |
| elem_id="chatbox", |
| label="", |
| avatar_images=["user_avatar.jpg", "humanlike_avatar.png"], |
| bubble_full_width=False, |
| height=500, |
| show_copy_button=False, |
| type="messages" |
| ) |
|
|
| with gr.Row(): |
| user_input = gr.Textbox( |
| show_label=False, |
| placeholder="Type your message here and press send...", |
| container=True, |
| scale=10 |
| ) |
| send_btn = gr.Button(value="➤", elem_classes="send-btn") |
|
|
| state = gr.State([]) |
| step = gr.State(0) |
| language = gr.State("") |
| questions = gr.State([]) |
| followup_mode = gr.State(False) |
|
|
| demo.load(fn=init, outputs=[chatbot, step, language, questions, followup_mode]) |
| user_input.submit(respond, [user_input, state, step, language, questions, followup_mode], |
| [chatbot, user_input, step, language, questions, followup_mode]) |
| send_btn.click(respond, [user_input, state, step, language, questions, followup_mode], |
| [chatbot, user_input, step, language, questions, followup_mode]) |
|
|
| demo.queue().launch() |