Wanswan commited on
Commit
a165284
·
verified ·
1 Parent(s): e27b345

Upload 5 files

Browse files
Files changed (6) hide show
  1. .gitattributes +1 -0
  2. README.md +34 -7
  3. app.py +241 -0
  4. humanlike_avatar.png +3 -0
  5. requirements.txt +2 -0
  6. user_avatar.jpg +0 -0
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ humanlike_avatar.png filter=lfs diff=lfs merge=lfs -text
README.md CHANGED
@@ -1,13 +1,40 @@
1
  ---
2
- title: Bot A
3
- emoji: 👁
4
- colorFrom: purple
5
- colorTo: yellow
6
  sdk: gradio
7
- sdk_version: 5.31.0
8
  app_file: app.py
9
  pinned: false
10
- short_description: Bot_A
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: 调查小秘书
3
+ emoji: 📋
4
+ colorFrom: indigo
5
+ colorTo: blue
6
  sdk: gradio
7
+ sdk_version: 5.29.1
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
+ 这是一个内嵌问卷用的 GPT 聊天机器人,具有用户/助手头像、逐字打印动画、自定义气泡样式和发送按钮。
13
+
14
+ # 🛍️ SwansGPTBot - 问卷调查聊天机器人
15
+
16
+ 这是一个用于在线问卷的定制化交互式聊天机器人,基于 Gradio + OpenAI GPT 构建。
17
+
18
+ ## 🧠 功能特色
19
+
20
+ - 和用户互动提出 9 个预设问题
21
+ - 每次回应包括:简短评价 + 下一问题
22
+ - 聊天机器人头像展示 + 气泡式布局
23
+ - 支持 emoji 情感回应和偶尔加入机器人“想法”
24
+ - 可嵌入 Qualtrics 问卷 iframe 使用
25
+
26
+ ## 🚀 如何运行
27
+
28
+ 确保你在 Hugging Face Spaces 中上传以下三个文件:
29
+
30
+ - `app.py`
31
+ - `requirements.txt`
32
+ - `bot_avatar.png`
33
+
34
+ 环境会自动安装依赖并运行。你也可以点击右上角 “App” 标签页进行交互测试。
35
+
36
+ ## 🤖 技术栈
37
+
38
+ - Gradio 5.29.1
39
+ - OpenAI GPT-3.5
40
+ - Hugging Face Spaces
app.py ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from openai import OpenAI
3
+ import os
4
+ import random
5
+ import asyncio
6
+
7
+ client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
8
+
9
+ DEFAULT_LANGUAGE = "English"
10
+ WELCOME_MESSAGE_EN = "Hi! I'm your friendly assistant 🤖 Let's begin!\n\nPlease tell me which language you'd like to use."
11
+
12
+ # === Question Bank ===
13
+ SET_I = [
14
+ "Given the choice of anyone in the world, whom would you want as a dinner guest?",
15
+ "Would you like to be famous? In what way?",
16
+ "Before making a telephone call, do you ever rehearse what you are going to say? Why?",
17
+ "What would constitute a 'perfect' day for you?",
18
+ "When did you last sing to yourself? To someone else?",
19
+ "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?",
20
+ "Do you have a secret hunch about how you will die?",
21
+ "Name three things you and me appear to have in common.",
22
+ "For what in your life do you feel most grateful?",
23
+ "If you could change anything about the way you were raised, what would it be?",
24
+ "Take one minutes and tell me your life story in as much detail as possible.",
25
+ "If you could wake up tomorrow having gained any one quality or ability, what would it be?"
26
+ ]
27
+
28
+ SET_II = [
29
+ "If a crystal ball could tell you the truth about yourself, your life, the future or anything else, what would you want to know?",
30
+ "Is there something that you’ve dreamed of doing for a long time? Why haven’t you done it?",
31
+ "What is the greatest accomplishment of your life?",
32
+ "What do you value most in a friendship?",
33
+ "What is your most treasured memory?",
34
+ "What is your most terrible memory?",
35
+ "If you knew that in one year you would die suddenly, would you change anything about the way you are now living? Why?",
36
+ "What does friendship mean to you?",
37
+ "What roles do love and affection play in your life?",
38
+ "Alternate sharing something you consider a positive characteristic of me. Share a total of three items.",
39
+ "How close and warm is your family? Do you feel your childhood was happier than most other people’s?",
40
+ "How do you feel about your relationship with your mother?"
41
+ ]
42
+
43
+ SET_III = [
44
+ "Make three true 'we' statements each. For instance, 'We are both in this chatroom feeling ...'",
45
+ "Complete this sentence: 'I wish I had someone with whom I could share ...'",
46
+ "If you were going to become a close friend with me, please share what would be important for me to know.",
47
+ "Tell me what you like about me; be very honest this time, saying things that you might not say to someone you’ve just met.",
48
+ "Share with me an embarrassing moment in your life.",
49
+ "When did you last cry in front of another person? By yourself?",
50
+ "Tell me something that you like about me already.",
51
+ "What, if anything, is too serious to be joked about?",
52
+ "If you were to die this evening with no opportunity to communicate with anyone, what would you most regret not having told someone? Why haven’t you told them yet?",
53
+ "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?",
54
+ "Of all the people in your family, whose death would you find most disturbing? Why?",
55
+ "Share a personal problem and ask my advice on how I might handle it. Also, ask me to reflect back to you how you seem to be feeling about the problem you have chosen."
56
+ ]
57
+
58
+ def generate_question_set():
59
+ return random.sample(SET_I, 3) + random.sample(SET_II, 3) + random.sample(SET_III, 3)
60
+
61
+ async def gpt_translate(text, target_lang):
62
+ if target_lang == "English":
63
+ return text
64
+ prompt = f"Translate the following into {target_lang}:\n\n{text}"
65
+ response = client.chat.completions.create(
66
+ model="gpt-3.5-turbo",
67
+ messages=[{"role": "user", "content": prompt}],
68
+ temperature=0.3
69
+ )
70
+ return response.choices[0].message.content.strip()
71
+
72
+ async def respond(user_input, history, step, language, questions, followup_mode):
73
+ history.append({"role": "user", "content": user_input})
74
+ if language == "":
75
+ user_language = user_input.strip().capitalize()
76
+ questions_en = generate_question_set()
77
+ translated_questions = [await gpt_translate(q, user_language) for q in questions_en]
78
+ welcome = await gpt_translate("Great! We will now continue in your selected language.", user_language)
79
+ history.append({"role": "assistant", "content": f"{welcome}\n\n1. {translated_questions[0]}"})
80
+ return history, "", 1, user_language, translated_questions, False
81
+ if step >= len(questions):
82
+ thank_you = await gpt_translate("Thank you for your response!", language)
83
+ end_note = await gpt_translate("This concludes our questions. Please proceed with the rest of the survey. 📝", language)
84
+ history.append({"role": "assistant", "content": thank_you})
85
+ history.append({"role": "assistant", "content": end_note})
86
+ return history, "", step, language, questions, False
87
+ if followup_mode:
88
+ comment_prompt = [
89
+ {"role": "system", "content": f"Write a short, empathetic comment in {language} responding to the user's last answer."},
90
+ history[-2],
91
+ history[-1]
92
+ ]
93
+ comment_response = client.chat.completions.create(
94
+ model="gpt-3.5-turbo",
95
+ messages=comment_prompt,
96
+ temperature=0.7
97
+ )
98
+ comment = comment_response.choices[0].message.content.strip()
99
+ history.append({"role": "assistant", "content": ""})
100
+ for c in comment:
101
+ history[-1]["content"] += c
102
+ await asyncio.sleep(0.03)
103
+ next_question = f"{step+1}. {questions[step]}"
104
+ history.append({"role": "assistant", "content": ""})
105
+ for c in next_question:
106
+ history[-1]["content"] += c
107
+ await asyncio.sleep(0.03)
108
+ return history, "", step + 1, language, questions, False
109
+
110
+ comment_prompt = [
111
+ {"role": "system", "content": f"You are a friendly and witty assistant. Write a short, personalized comment on the user's answer in {language}. Add a light emoji at the end."},
112
+ history[-2],
113
+ history[-1]
114
+ ]
115
+ comment_response = client.chat.completions.create(
116
+ model="gpt-3.5-turbo",
117
+ messages=comment_prompt,
118
+ temperature=0.8
119
+ )
120
+ bot_reply = comment_response.choices[0].message.content.strip()
121
+
122
+ followup_count = 0
123
+ rand = random.random()
124
+ if rand < 0.1:
125
+ followup_count = 2
126
+ elif rand < 0.5:
127
+ followup_count = 1
128
+
129
+ if followup_count > 0:
130
+ followup_prompt = [
131
+ {"role": "system", "content": f"Ask {followup_count} open-ended follow-up question(s) based on the user's last answer in {language}."},
132
+ history[-2],
133
+ history[-1]
134
+ ]
135
+ followup_response = client.chat.completions.create(
136
+ model="gpt-3.5-turbo",
137
+ messages=followup_prompt,
138
+ temperature=0.7
139
+ )
140
+ bot_reply += "\n\n" + followup_response.choices[0].message.content.strip()
141
+ history.append({"role": "assistant", "content": ""})
142
+ for c in bot_reply:
143
+ history[-1]["content"] += c
144
+ await asyncio.sleep(0.03)
145
+ return history, "", step, language, questions, True
146
+
147
+ history.append({"role": "assistant", "content": ""})
148
+ for c in bot_reply:
149
+ history[-1]["content"] += c
150
+ await asyncio.sleep(0.03)
151
+ next_question = f"{step+1}. {questions[step]}"
152
+ history.append({"role": "assistant", "content": ""})
153
+ for c in next_question:
154
+ history[-1]["content"] += c
155
+ await asyncio.sleep(0.03)
156
+ return history, "", step + 1, language, questions, False
157
+
158
+ def init():
159
+ return [{"role": "assistant", "content": WELCOME_MESSAGE_EN}], 0, "", [], False
160
+
161
+ with gr.Blocks(css="""
162
+ .send-btn {
163
+ background-color: #25D366 !important;
164
+ color: white !important;
165
+ border: none;
166
+ border-radius: 24px;
167
+ font-size: 20px;
168
+ padding: 8px 20px;
169
+ height: 48px;
170
+ width: 60px;
171
+ margin-left: 8px;
172
+ cursor: pointer;
173
+ }
174
+ #chatbox .avatar-container {
175
+ width: 64px !important;
176
+ height: 64px !important;
177
+ min-width: 64px !important;
178
+ min-height: 64px !important;
179
+ background-size: 100% 100% !important;
180
+ background-position: center center !important;
181
+ border-radius: 50% !important;
182
+ padding: 0 !important;
183
+ margin: 0 !important;
184
+ border: none !important;
185
+ box-shadow: none !important;
186
+ background-color: transparent !important;
187
+ }
188
+ #chatbox .message.user { background-color: #DCF8C6 !important; }
189
+ #chatbox .message.assistant { background-color: #ffffff !important; }
190
+
191
+ """) as demo:
192
+ gr.HTML("""
193
+ <script>
194
+ const waitForChatbox = () => {
195
+ const chatbox = document.getElementById("chatbox");
196
+ if (chatbox) {
197
+ const observer = new MutationObserver(() => {
198
+ chatbox.scrollTop = chatbox.scrollHeight;
199
+ });
200
+ observer.observe(chatbox, { childList: true, subtree: true });
201
+ } else {
202
+ setTimeout(waitForChatbox, 500);
203
+ }
204
+ };
205
+ waitForChatbox();
206
+ </script>
207
+ """)
208
+
209
+ chatbot = gr.Chatbot(
210
+ elem_id="chatbox",
211
+ label="",
212
+ avatar_images=["user_avatar.jpg", "bot_avatar.png"],
213
+ bubble_full_width=False,
214
+ height=500,
215
+ show_copy_button=False,
216
+ type="messages"
217
+ )
218
+
219
+ with gr.Row():
220
+ user_input = gr.Textbox(
221
+ show_label=False,
222
+ placeholder="Type your message here and press send...",
223
+ container=True,
224
+ scale=10
225
+ )
226
+ send_btn = gr.Button(value="➤", elem_classes="send-btn")
227
+
228
+ state = gr.State([])
229
+ step = gr.State(0)
230
+ language = gr.State("")
231
+ questions = gr.State([])
232
+ followup_mode = gr.State(False)
233
+
234
+ demo.load(fn=init, outputs=[chatbot, step, language, questions, followup_mode])
235
+ user_input.submit(respond, [user_input, state, step, language, questions, followup_mode],
236
+ [chatbot, user_input, step, language, questions, followup_mode])
237
+ send_btn.click(respond, [user_input, state, step, language, questions, followup_mode],
238
+ [chatbot, user_input, step, language, questions, followup_mode])
239
+
240
+ demo.queue().launch()
241
+
humanlike_avatar.png ADDED

Git LFS Details

  • SHA256: 0e15895c9b895fb64c16876dc560ef05d4f08ee4b75c0a09ea9549721c5ab8ae
  • Pointer size: 131 Bytes
  • Size of remote file: 119 kB
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ gradio>=4.0.0
2
+ openai>=1.0.0
user_avatar.jpg ADDED