haohsiang commited on
Commit
f6db358
·
verified ·
1 Parent(s): eadbc9b

initial commit

Browse files
Files changed (7) hide show
  1. requirements.txt +14 -0
  2. .gitattributes +1 -0
  3. CVAW_all_SD.csv +0 -0
  4. README.md +6 -11
  5. app.py +355 -0
  6. meditation_v2.mp3 +3 -0
  7. tbh368-sdxl.safetensors +3 -0
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ openai
2
+ gradio==4.36.1
3
+ transformers
4
+ diffusers
5
+ accelerate
6
+ sentencepiece
7
+ safetensors
8
+ peft
9
+ torch
10
+ numpy
11
+ opencv-python
12
+ Pillow
13
+ opencc-python-reimplemented
14
+ # git+https://github.com/initml/diffusers.git@clement/feature/flash_sd3
.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
+ meditation_v2.mp3 filter=lfs diff=lfs merge=lfs -text
CVAW_all_SD.csv ADDED
The diff for this file is too large to render. See raw diff
 
README.md CHANGED
@@ -1,12 +1,7 @@
1
- ---
2
- title: Self Healing Bot
3
- emoji: 👁
4
- colorFrom: purple
5
- colorTo: yellow
6
- sdk: gradio
7
- sdk_version: 4.42.0
8
- app_file: app.py
9
- pinned: false
10
- ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # -*- coding: utf-8 -*-
2
+ # Changelog
3
+ ## v0.3.2
4
+ * make UI layout for phone's user
5
+ * update meditation script and background music
 
 
 
 
 
6
 
7
+ # Conversation with Gradio Interface
app.py ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import torch
4
+ import numpy as np
5
+ import cv2
6
+ import base64
7
+ import time
8
+ from PIL import Image
9
+ from openai import OpenAI
10
+ from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipeline, EulerAncestralDiscreteScheduler
11
+ from peft import PeftModel
12
+ from transformers import AutoModel
13
+
14
+ # OpenAI API
15
+ api_key = os.getenv('OPENAI_API_KEY')
16
+ client = OpenAI(api_key=api_key)
17
+
18
+ # text to image 設定
19
+ access_token = os.getenv('HF_TOKEN')
20
+ model_id = "stabilityai/stable-diffusion-xl-base-1.0"
21
+ pipe_t2i = StableDiffusionXLPipeline.from_pretrained(model_id, torch_dtype=torch.float16, use_safetensors=True, token=access_token).to("cuda")
22
+ pipe_t2i.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe_t2i.scheduler.config)
23
+
24
+ # 載入 LoRA 權重
25
+ lora_path = "./tbh368-sdxl.safetensors"
26
+ pipe_t2i.load_lora_weights(lora_path, adapter_name="milton-glaser")
27
+ pipe_t2i.set_adapters(["milton-glaser"], adapter_weights=[1.0])
28
+
29
+ import jieba
30
+ import numpy as np
31
+ import pandas as pd
32
+
33
+ valence_scores = []
34
+ arousal_scores = []
35
+ conversation_times = 0
36
+
37
+ # 載入 CVAW Corpus 資料
38
+ cvaw_data = pd.read_csv('./CVAW_all_SD.csv', delimiter='\t')
39
+ cvaw_dict = dict(zip(cvaw_data['Word'], zip(cvaw_data['Valence_Mean'], cvaw_data['Arousal_Mean'])))
40
+
41
+ def analyze_sentiment_corpus(text):
42
+ words = jieba.cut(text)
43
+ global conversation_times
44
+ global valence_scores
45
+ global arousal_scores
46
+
47
+ conversation_times += 1
48
+
49
+ for word in words:
50
+ if word in cvaw_dict:
51
+ valence, arousal = cvaw_dict[word]
52
+ valence_scores.append(valence)
53
+ arousal_scores.append(arousal)
54
+ # 只保留最後三句使用者輸入的內容
55
+ valence_scores = valence_scores[-3:]
56
+ arousal_scores = arousal_scores[-3:]
57
+
58
+ if conversation_times < 4: # 當對話次數<4的時候,返回10,代表不會進入放鬆模式
59
+ return 10, 10
60
+ else:
61
+ avg_valence = np.mean(valence_scores)
62
+ avg_arousal = np.mean(arousal_scores)
63
+ return avg_valence, avg_arousal
64
+
65
+ def call_gpt(input_text, history):
66
+ messages = [{"role":"system", "content":"對話請以繁體中文進行:你是一位熟悉現象學的諮商實習生,擅長引導使用者描述他當下的所知覺到的事物。回答問題的時候必須有同理心,請同理使用者說的內容,再繼續回答,且不要超過20個字。"}]
67
+
68
+ for h in history:
69
+ messages.append({"role": "user", "content": h[0]})
70
+ messages.append({"role": "assistant", "content": h[1]})
71
+
72
+ messages.append({"role": "user", "content": input_text})
73
+
74
+ chat_reply = client.chat.completions.create(
75
+ model="gpt-4o",
76
+ messages=messages,
77
+ temperature=0.8
78
+ )
79
+
80
+ return chat_reply.choices[0].message.content
81
+
82
+ # Testing meditation function
83
+ meditation_flag = True # 判斷是否進入放鬆模式
84
+
85
+ def chat_with_bot(input_text, history):
86
+ global meditation_flag
87
+ response = ""
88
+ med_confirm_layout = False # 是否顯示放鬆選項
89
+ jump2med_btn = True # 是否允許跳轉到放鬆介面
90
+
91
+ # 進行情感分析
92
+ valence, arousal = analyze_sentiment_corpus(input_text)
93
+
94
+ # 判斷是否建議放鬆練習
95
+ if 3 <= arousal <= 4 and meditation_flag is True: # 詢問是否進行放鬆練習
96
+ response = "我知道你的處境了\n我有一個建議,我們來進行一個可以讓自己放鬆的呼吸覺察練習好嗎?"
97
+ history.append((input_text, response))
98
+ med_confirm_layout = True
99
+ return history, med_confirm_layout, jump2med_btn
100
+ elif meditation_flag is False: # 已經放鬆過,不顯示跳轉按鈕
101
+ response = call_gpt(input_text, history)
102
+ history.append((input_text, response))
103
+ jump2med_btn = False
104
+ return history, med_confirm_layout, jump2med_btn
105
+ else: # 繼續對話
106
+ response = call_gpt(input_text, history)
107
+ history.append((input_text, response))
108
+ return history, med_confirm_layout, jump2med_btn
109
+
110
+ def translate_to_english(text):
111
+ character = "You are a professional text to image prompt generator, please use the following text to generate prompt in English. It's very important to summarize it in 70 tokens."
112
+ messages = [{"role":"system", "content":character},
113
+ {"role": "user", "content": text}]
114
+
115
+ chat_reply = client.chat.completions.create(
116
+ messages=messages,
117
+ model="gpt-4o-mini",
118
+ )
119
+
120
+ return chat_reply.choices[0].message.content
121
+
122
+ generated_images = None
123
+ last_genimg_times = 0
124
+
125
+ def generate_images(history):
126
+ global generated_images # 使用全域變數來儲存圖片
127
+ global last_genimg_times
128
+
129
+ if generated_images is not None and last_genimg_times == conversation_times:
130
+ return generated_images # 如果圖片已生成,直接返回
131
+
132
+ user_story = " ".join([h[0] for h in history])
133
+ prompt = translate_to_english(user_story)
134
+
135
+ neg_prompt = "realistic, camera, 8k, words, sentence, text, Low quality, error, blurry, deformed, extra, nude, duplicate, ugly"
136
+
137
+ seeds = np.random.randint(0, 100000, 4)
138
+ generator = [torch.Generator().manual_seed(int(i)) for i in seeds]
139
+ images = []
140
+ last_genimg_times = conversation_times
141
+
142
+ for i in range(4):
143
+ img = pipe_t2i("style of Milton Glaser, mental image, "+prompt,
144
+ negative_prompt=neg_prompt,
145
+ height=720, width=512,
146
+ generator=generator[i],
147
+ num_inference_steps=40,
148
+ guidance_scale=7.5,
149
+ ).images[0]
150
+ images.append(img)
151
+
152
+ generated_images = images # 儲存生成的圖片
153
+ return images
154
+
155
+ def select_image(choice, img1, img2, img3, img4):
156
+ index = int(choice.split()[-1]) - 1
157
+ images = [img1, img2, img3, img4]
158
+ return images[index]
159
+
160
+ def chat_about_image(input_text, history, selected_image):
161
+ # 讀取並編碼圖像
162
+ _, buffer = cv2.imencode('.png', selected_image)
163
+ img_str = base64.b64encode(buffer).decode()
164
+
165
+ messages = [
166
+ {"role": "system", "content": "對話請以繁體中文進行:你是一位熟悉現象學的諮商實習生,請根據使用者對他所選出的圖像描述進行引導,指出這張圖像與先前對話的關聯,幫助使用者探索他們的分享與該圖像間的連結,並繼續對話"},
167
+ {"role": "user", "content": [
168
+ {"type": "text", "text": f"看到這張圖像,讓我想到 {input_text}"},
169
+ {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img_str}"}}
170
+ ]}
171
+ ]
172
+
173
+ chat_reply = client.chat.completions.create(
174
+ model="gpt-4o",
175
+ messages=messages,
176
+ max_tokens=300
177
+ )
178
+
179
+ reply = chat_reply.choices[0].message.content
180
+ history.append((input_text, reply))
181
+
182
+ return (
183
+ history,
184
+ history,
185
+ gr.update(visible=True) # chatbot_interface
186
+ )
187
+
188
+ audio_file = "./meditation_v2.mp3"
189
+
190
+ # UI handle functions
191
+ def handle_chat(input_text, history):
192
+ updated_history, meditation, jump2med_btn = chat_with_bot(input_text, history)
193
+ if meditation:
194
+ return (
195
+ updated_history,
196
+ gr.update(value="", placeholder="現在我們開始進行身體放鬆吧", interactive=False), # msg
197
+ gr.update(visible=False), # submit
198
+ gr.update(visible=False), # jump_to_med
199
+ gr.update(visible=True), # meditation_buttons
200
+ gr.update(visible=False) # clear
201
+ )
202
+ elif jump2med_btn is False:
203
+ return (
204
+ updated_history,
205
+ gr.update(value="", placeholder="今天想跟我分享什麼呢?", interactive=True), # msg
206
+ gr.update(visible=True), # submit
207
+ gr.update(visible=False), # jump_to_med
208
+ gr.update(visible=False), # meditation_buttons
209
+ gr.update(visible=True) # clear
210
+ )
211
+ else:
212
+ return (
213
+ updated_history,
214
+ gr.update(value="", placeholder="今天想跟我分享什麼呢?", interactive=True), # msg
215
+ gr.update(visible=True), # submit
216
+ gr.update(visible=True), # jump_to_med
217
+ gr.update(visible=False), # meditation_buttons
218
+ gr.update(visible=True) # clear
219
+ )
220
+
221
+ def start_meditation(history):
222
+ global meditation_flag
223
+ meditation_flag = False
224
+ audio = audio_file
225
+ return (
226
+ audio
227
+ )
228
+
229
+ def continue_chat():
230
+ return (
231
+ gr.update(value="", placeholder="今天想跟我分享什麼呢?", interactive=True), # msg
232
+ gr.update(visible=True), # submit
233
+ gr.update(visible=True), # jump_to_med
234
+ gr.update(visible=False), # meditation_buttons
235
+ gr.update(visible=True) # clear
236
+ )
237
+
238
+ def return_to_chat():
239
+ return (
240
+ None, # set audio_player to None will stop the audio
241
+ gr.update(visible=True), # main_interface
242
+ gr.update(visible=True), # chatbot_interface
243
+ gr.update(visible=True), # selected_image_interface
244
+ gr.update(visible=False), # audio_interface
245
+ gr.update(interactive=True, placeholder="今天想跟我分享什麼呢?"), # msg
246
+ gr.update(visible=True), # submit
247
+ gr.update(visible=True), # clear
248
+ gr.update(visible=False), # meditation_buttons
249
+ gr.update(visible=True), # gen_other_img
250
+ gr.update(visible=False) # jump_to_med
251
+ )
252
+
253
+ import asyncio
254
+
255
+ async def show_loading():
256
+ # 顯示載入訊息
257
+ yield (gr.update(visible=True), # loading_message
258
+ "載入時間約需十秒,建議戴上耳機體驗。\n在接下來的畫面,你會看到播放介面,按下播放鈕後就會開始播放指導語",
259
+ gr.update(visible=False), # main_interface
260
+ gr.update(visible=False)) # audio_interface
261
+ # 等待 10 秒
262
+ await asyncio.sleep(12)
263
+ # 清除訊息
264
+ yield (gr.update(visible=False), # loading_message
265
+ "",
266
+ gr.update(visible=False), # main_interface
267
+ gr.update(visible=True)) # audio_interface
268
+
269
+ # Testing meditation function
270
+ theme = gr.themes.Base(
271
+ primary_hue="amber",
272
+ secondary_hue="sky",
273
+ font=[gr.themes.GoogleFont('Noto Sans TC'), 'ui-sans-serif', 'system-ui', 'sans-serif'],
274
+ ).set(
275
+ checkbox_background_color_selected_dark='*secondary_400',
276
+ button_border_width='*checkbox_border_width',
277
+ button_shadow='*shadow_drop',
278
+ button_primary_background_fill_hover='*primary_400',
279
+ button_primary_background_fill_hover_dark='*primary_900',
280
+ button_secondary_background_fill='*secondary_100',
281
+ button_secondary_background_fill_dark='*secondary_700',
282
+ button_secondary_background_fill_hover='*secondary_300',
283
+ button_secondary_background_fill_hover_dark='*secondary_900',
284
+ button_secondary_border_color='*secondary_100',
285
+ button_secondary_border_color_dark='*secondary_600',
286
+ button_secondary_text_color='*secondary_700'
287
+ )
288
+
289
+ css = """
290
+ .graphic_parent {
291
+ display: flex;
292
+ flex-direction: row;
293
+ flex-wrap: wrap;
294
+ gap: 8px;
295
+ max-height: 100vh;
296
+ max-width: 100vw;
297
+ }
298
+ .graphic {
299
+ width: 48%;
300
+ }
301
+ """
302
+
303
+ with gr.Blocks(theme=theme, css=css) as demo:
304
+ loading_message = gr.Textbox(visible=False, show_label=False)
305
+ with gr.Column(visible=False) as audio_interface:
306
+ audio_player = gr.Audio(label="呼吸覺察練習", show_download_button=False, interactive=False)
307
+ back_to_chat = gr.Button("返回聊天")
308
+
309
+ with gr.Row() as main_interface:
310
+ with gr.Column() as chatbot_interface:
311
+ chatbot = gr.Chatbot(label="聊天機器人", bubble_full_width=False, scale=6)
312
+ msg = gr.Textbox(show_label=False, placeholder="今天想要跟我分享什麼呢?", autofocus=True, scale=2)
313
+ with gr.Row():
314
+ submit = gr.Button("送出", variant="primary", scale=2)
315
+ jump_to_med = gr.Button("我想要現在進行呼吸覺察練習", scale=2)
316
+ gen_other_img = gr.Button("結合聯想生成更多圖像", scale=2, visible=False)
317
+ clear = gr.Button("清除對話紀錄", scale=1)
318
+ with gr.Row(visible=False) as meditation_buttons:
319
+ relax_yes = gr.Button("好", variant="primary")
320
+ relax_no = gr.Button("我想再多分享一點")
321
+ with gr.Column(visible=False, elem_classes="graphic_parent") as image_selector_interface:
322
+ image_selector = gr.Radio(choices=["圖像 1", "圖像 2", "圖像 3", "圖像 4"], label="選擇一張圖像")
323
+ image_outputs = [gr.Image(label=f"圖像 {i+1}", interactive=False, elem_classes="graphic") for i in range(4)]
324
+ with gr.Column(visible=False) as selected_image_interface:
325
+ selected_image = gr.Image(interactive=False, label="你選擇的圖像")
326
+ image_chat_input = gr.Textbox(label="這張圖像讓你產生了什麼樣的聯想?")
327
+ image_chat_button = gr.Button("與聊天機器人分享", variant="primary")
328
+
329
+ # chatbot events handle
330
+ submit.click(handle_chat, [msg, chatbot], [chatbot, msg, submit, jump_to_med, meditation_buttons, clear])
331
+ msg.submit(handle_chat, [msg, chatbot], [chatbot, msg, submit, jump_to_med, meditation_buttons, clear])
332
+ clear.click(lambda: None, None, chatbot, queue=False)
333
+
334
+ # going to meditation events handle
335
+ jump_to_med.click(start_meditation, [chatbot], audio_player)
336
+ relax_yes.click(start_meditation, [chatbot], audio_player)
337
+ relax_no.click(continue_chat, None, [msg, submit, jump_to_med, meditation_buttons, clear])
338
+
339
+ # meditation events handle
340
+ jump_to_med.click(show_loading, None, [loading_message, loading_message, main_interface, audio_interface])
341
+ relax_yes.click(show_loading, None, [loading_message, loading_message, main_interface, audio_interface])
342
+ audio_player.play(generate_images, [chatbot], image_outputs)
343
+ audio_player.stop(return_to_chat, None, [audio_player, main_interface, chatbot_interface, selected_image_interface, audio_interface, msg, submit, clear, meditation_buttons, gen_other_img, jump_to_med])
344
+ back_to_chat.click(return_to_chat, None, [audio_player, main_interface, chatbot_interface, selected_image_interface, audio_interface, msg, submit, clear, meditation_buttons, gen_other_img, jump_to_med])
345
+
346
+ # images select events handle
347
+ image_selector.change(select_image, [image_selector] + image_outputs, selected_image)
348
+ image_chat_input.submit(chat_about_image, [image_chat_input, chatbot, selected_image], [chatbot, chatbot, chatbot_interface]).then(lambda: None, None, image_chat_input , queue=False)
349
+ image_chat_button.click(chat_about_image, [image_chat_input, chatbot, selected_image], [chatbot, chatbot, chatbot_interface]).then(lambda: None, None, image_chat_input , queue=False)
350
+
351
+ # generate other images event handle
352
+ gen_other_img.click(generate_images, [chatbot], image_outputs)
353
+
354
+ demo.queue()
355
+ demo.launch(max_threads=5, show_api=False)
meditation_v2.mp3 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:34dd8a2e17d26897fa9cd25751933bcab3dd89bf1871072bd9a660b7bb9f4200
3
+ size 10799040
tbh368-sdxl.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:24aefb109c3d0d60e796497086b6fd57b60371e3dc846e5cbf0e5644f6563b33
3
+ size 456487172