File size: 12,769 Bytes
a165284
 
 
 
 
 
 
 
 
72f43eb
a165284
03018fc
4c76de1
 
 
 
 
 
 
9963fbb
4c76de1
 
 
9963fbb
4c76de1
 
 
 
 
 
9963fbb
4c76de1
 
 
9ccbf1a
4c76de1
 
9963fbb
4c76de1
 
 
 
 
f2c7cd1
1d9176d
4c76de1
9963fbb
4c76de1
 
 
 
9963fbb
4c76de1
9963fbb
43c6951
4c76de1
a165284
 
2de0f4c
a165284
 
 
 
 
 
 
 
 
 
 
 
24590e9
a165284
4bb1e77
a165284
 
 
 
 
4bb1e77
 
 
 
24590e9
08607d0
a165284
d8a603a
a8a4d3a
4bb1e77
 
 
 
 
24590e9
08607d0
a165284
 
 
24590e9
 
a165284
03018fc
 
 
 
 
a165284
24590e9
 
 
 
4bb1e77
24590e9
 
 
 
 
 
 
 
 
4bb1e77
24590e9
4bb1e77
24590e9
 
2bc4b3c
4bb1e77
 
 
 
 
24590e9
 
2bc4b3c
 
 
 
 
4bb1e77
24590e9
2bc4b3c
24590e9
 
2bc4b3c
24590e9
b633ee2
 
4bb1e77
24590e9
 
b633ee2
03018fc
 
 
 
 
 
 
 
4bb1e77
03018fc
24590e9
 
 
03018fc
 
 
 
 
 
24590e9
4bb1e77
24590e9
4bb1e77
24590e9
 
2bc4b3c
4bb1e77
 
 
 
 
24590e9
 
2bc4b3c
 
 
 
 
4bb1e77
24590e9
2bc4b3c
24590e9
 
2bc4b3c
24590e9
8e63755
a165284
03018fc
 
0da6549
03018fc
 
 
 
 
baf0c96
 
 
 
 
 
03018fc
 
 
0da6549
 
 
 
 
 
 
 
 
 
 
 
03018fc
0da6549
b0ded68
bdefb73
e50a1cf
0da6549
5e0f91b
fbcbb33
0da6549
 
b0ded68
0da6549
 
 
 
 
 
b0ded68
8fa2ca7
 
c53e581
 
8fa2ca7
c58c216
0da6549
 
 
 
 
20642f3
3e1210d
 
294d559
03018fc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40f79af
03018fc
 
 
a165284
40f79af
 
 
 
 
 
 
 
a165284
 
 
 
 
 
 
03018fc
 
 
 
 
 
3e1210d
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
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."

# === Question Bank ===
SET_I = [
    "Given the choice of anyone in the world, whom would you want as a dinner guest?",
    "Would you like to be famous? In what way?",
    "Before making a telephone call, do you ever rehearse what you are going to say? Why?",
    "What would constitute a 'perfect' day for you?",
    "When did you last sing to yourself? To someone else?",
    "If you were able to live to the age of 90 and retain either the mind or body of a 30-year-old for the last 60 years of your life, which would you want?",
    "Have you ever thought about how you would like to be remembered in the future?",
    "Name three things you and me appear to have in common.",
    "For what in your life do you feel most grateful?",
    "If you could change anything about the way you were raised, what would it be?",
    "Could you please tell me one of your life stories in detail?",
    "If you could wake up tomorrow having gained any one quality or ability, what would it be?"
]

SET_II = [
    "If a crystal ball could tell you the truth about yourself, your life, the future or anything else, what would you want to know?",
    "Is there something that you’ve dreamed of doing for a long time? Why haven’t you done it?",
    "What is the greatest accomplishment of your life you think?",
    "What do you value most in a friendship?",
    "What is your most treasured memory?",
    "What is your most terrible memory?",
    "If you knew that in one year you were going to Mars and wouldn’t be coming back, would you change the way you’re currently living? Why?",
    "What does friendship mean to you?",
    "What roles do love and affection play in your life?",
    "Please share what you think are my strengths so far, I would be grateful.",
    "How close and warm is your family? Do you feel your childhood was happier than most other people’s?",
    "How do you feel about your relationship with your mother?"
]

SET_III = [
    "Let's try something fun: Can you write one sentence that start with 'We' and describe something true about us — you and me, chatting here together? (For example: 'We are all happy with this conversation.')",
    "Let’s complete this sentence together: 'I wish I had someone I could share ___ with.' What would you say?",
    "If you were going to become a close friend with me, please share what would be important for me to know.",
    "Tell me how you feel about me",
    "Share with me an embarrassing moment in your life.",
    "When did you last cry in front of another person? By yourself?",
    "Tell me something that you like about me already.",
    "What, if anything, is too serious to be joked about?",
    "If you were leaving for Mars tonight and wouldn’t be able to contact anyone again, what would you most regret not having told someone? Why haven’t you told them yet?",
    "Your house, containing everything you own, catches fire. After saving your loved ones and pets, you have time to safely make a final dash to save any one item. What would it be? Why?",
    "If one member of your family had to go on a long mission to Mars and you wouldn’t see them for many years, whose absence would affect you the most? Why?",
    "Think of a personal problem you're facing right now, big or small, and tell me about it. I'd love to hear how you're feeling about it — and if you'd like, I can share how I might deal with something similar."
]

def generate_question_set():
    return random.sample(SET_I, 3) + random.sample(SET_II, 3) + random.sample(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()