Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,9 +1,12 @@
|
|
1 |
import gradio as gr
|
2 |
from PIL import Image
|
3 |
import numpy as np
|
|
|
|
|
|
|
4 |
|
5 |
#載入聊天機器人模型
|
6 |
-
from transformers import AutoTokenizer, AutoModelForCausalLM,TextIteratorStreamer
|
7 |
from threading import Thread
|
8 |
|
9 |
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
|
@@ -46,12 +49,143 @@ def chat(message, history):
|
|
46 |
partial_message += new_token
|
47 |
yield partial_message
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
avatar_images = ["https://cdn-icons-png.flaticon.com/128/3135/3135715.png",
|
50 |
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTIJYnfODgs7q_Q4k6RoUL592NBlSF7wUTEhT92lRyqc4HTunB-"]
|
51 |
|
52 |
custom_css = """
|
53 |
.gradio-container {background-color: #f0f0f0;padding-top: 0px !important;}
|
54 |
-
|
55 |
.header {background-color: #2c3e50; color: white; padding: 10px; text-align: center; border-radius: 10px 10px 0 0;margin-bottom: 0; /* Ensure no margin below header */}
|
56 |
.content {background-color: white; padding: 10px; border-radius: 0 0 10px 10px; margin: 0;margin-top: 0;}
|
57 |
.profile-pic {width: 150px; height: 150px; border-radius: 50%; margin: 20px auto; display: block;}
|
@@ -75,6 +209,27 @@ custom_css = """
|
|
75 |
margin: 0; /* 移除段落的默认外边距 */
|
76 |
}
|
77 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
"""
|
79 |
custom_footer = """
|
80 |
<div class="custom-footer">
|
@@ -306,5 +461,48 @@ with gr.Blocks(css=custom_css,title='我的履歷') as resume_app:# title可以
|
|
306 |
retry_btn='重新送出',
|
307 |
undo_btn=None
|
308 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
309 |
# gr.HTML(custom_footer)
|
310 |
resume_app.launch(allowed_paths=['./'],favicon_path='履歷資料/android-chrome-512x512.png')
|
|
|
1 |
import gradio as gr
|
2 |
from PIL import Image
|
3 |
import numpy as np
|
4 |
+
import faiss
|
5 |
+
import torch
|
6 |
+
|
7 |
|
8 |
#載入聊天機器人模型
|
9 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM,TextIteratorStreamer,AutoModel
|
10 |
from threading import Thread
|
11 |
|
12 |
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2-0.5B-Instruct")
|
|
|
49 |
partial_message += new_token
|
50 |
yield partial_message
|
51 |
|
52 |
+
|
53 |
+
#AI履歷助手(使用RAG)
|
54 |
+
embd= AutoModel.from_pretrained('jinaai/jina-embeddings-v2-base-zh', trust_remote_code=True, torch_dtype=torch.bfloat16)
|
55 |
+
doc={'技能':'python,深度學習,web開發,數據分析',
|
56 |
+
'經歷':'ICIM2024研討會、碩士期間擔任指導教授所開的類神經網路課程助教、大學專題實務成果展競賽亞軍,技術類業界評選第一名。',
|
57 |
+
'論文概述':'題為「基於情緒支持的對話:融合情緒感知和關鍵字識別的研究」。研究旨在通過聊天機器人為情緒困擾者提供陪伴,緩解其短期心理壓力。本文提出的模型結合情緒標籤和關鍵字識別技術,與其他基礎模型相比,能夠提供更精準的回復,從而更有效地支持用戶的情緒需求。',
|
58 |
+
'證照':'電腦硬體裝修丙級、電腦硬體裝修乙級、Database Administration Fundamentals、Software Development Fundamentals、Networking Fundamentals、CRM Merchandise Analyst、Enterprise Resource Planning',
|
59 |
+
'助教工作內容':'主要協助老師指導學生實作部分。包括使用 WEKA 軟體教導學生快速構建和分析機器學習模型,並解釋模型結果的含義。後期則引導學生安裝 Python 環境,撰寫並執行機器學習模型的程式碼,幫助學生在未來能夠運用 AI 技術更有效地完成工作。',
|
60 |
+
'專題內容':'專題名稱:熱影像結合人臉偵測暨網頁瀏覽系統。為因應新冠疫情,無接觸體溫檢測需求激增,本專題開發了利用紅外線熱影像和後端資料庫蒐集,最終實現異地閱覽和確保體溫監測的安全與效率。/n我的貢獻:硬體設備組裝、人臉偵測和後端資料庫及視覺化',
|
61 |
+
'專案':'學生點名系統、氣管插管預測、貨車車牌辨識、聊天機器人',
|
62 |
+
'學生點名系統簡述':'''
|
63 |
+
動機與目的: 鑒於每次上課點名都是老師的一大負擔,開發了這個學生點名系統,旨在幫助老師更有效地進行點名。本專案使用 Laravel 開源 PHP Web 框架開發,主要功能包括:
|
64 |
+
老師功能:
|
65 |
+
- 查看課表及點名記錄
|
66 |
+
- 查看學生出缺席和請假狀況
|
67 |
+
- 審核學生請假申請
|
68 |
+
學生功能:
|
69 |
+
- 查看課表及進行點名
|
70 |
+
- 查看出缺席和請假記錄
|
71 |
+
- 申請請假
|
72 |
+
該完整專案在github上,網址:https://github.com/WISD-2020/final02
|
73 |
+
''',
|
74 |
+
'氣管插管預測簡述':'動機與目的:為了協助醫生在執行插管時更精確地將氧氣管置入正確位置,我們利用影像分割技術(如 TransUnet、UNet++ 等)來實現該目標。最後,我們結合邊緣檢測與形態學技術,精確量化預測與實際的誤差,以提高插管的成功率並降低風險。',
|
75 |
+
'貨車車牌辨識簡述':'動機與目的:為了提高貨車進出倉庫的效率,我們建立一個車牌辨識系統,該系統基於深度學習技術,主要透過yolo來偵測車牌位置,再透過OCR技術來識別車牌號碼,最後將車牌號碼與倉庫數據庫進行比對,以確保進出貨物的準確性。 ',
|
76 |
+
'聊天機器人簡述':'過去在研究語言模型時,尚未設計與機器人對話的專屬介面,因此這次實作了一個簡單的聊天機器人介面。該聊天機器人基於 Qwen 大型預訓練語言模型,這是一個多語言支持的模型,供使用者進行互動體驗。',
|
77 |
+
}
|
78 |
+
docs=['主要的技能(技術)包含:python,深度學習,web開發,數據分析',
|
79 |
+
'特別經歷包含:ICIM2024研討會、碩士期間擔任指導教授所開的類神經網路課程助教、大學專題實務成果展競賽亞軍,技術類業界評選第一名。',
|
80 |
+
'論文概述:題為「基於情緒支持的對話:融合情緒感知和關鍵字識別的研究」。研究旨在通過聊天機器人為情緒困擾者提供陪伴,緩解其短期心理壓力。本文提出的模型結合情緒標籤和關鍵字識別技術,與其他基礎模型相比,能夠提供更精準的回復,從而更有效地支持用戶的情緒需求。',
|
81 |
+
'在高中和大學時期所拿到的證照有:電腦硬體裝修丙級、電腦硬體裝修乙級、Database Administration Fundamentals、Software Development Fundamentals、Networking Fundamentals、CRM Merchandise Analyst、Enterprise Resource Planning',
|
82 |
+
'助教工作內容:主要協助老師指導學生實作部分。包括使用 WEKA 軟體教導學生快速構建和分析機器學習模型,並解釋模型結果的含義。後期則引導學生安裝 Python 環境,撰寫並執行機器學習模型的程式碼,幫助學生在未來能夠運用 AI 技術更有效地完成工作。',
|
83 |
+
'大學專題內容:專題名稱:熱影像結合人臉偵測暨網頁瀏覽系統。為因應新冠疫情,無接觸體溫檢測需求激增,本專題開發了利用紅外線熱影像和後端資料庫蒐集,最終實現異地閱覽和確保體溫監測的安全與效率。/n我的貢獻:硬體設備組裝、人臉偵測和後端資料庫及視覺化',
|
84 |
+
'參與過的專案包含:學生點名系統、氣管插管預測、貨車車牌辨識、聊天機器人',
|
85 |
+
'''學生點名系統簡述:
|
86 |
+
動機與目的: 鑒於每次上課點名都是老師的一大負擔,開發了這個學生點名系統,旨在幫助老師更有效地進行點名。本專案使用 Laravel 開源 PHP Web 框架開發,主要功能包括:
|
87 |
+
老師功能:
|
88 |
+
- 查看課表及點名記錄
|
89 |
+
- 查看學生出缺席和請假狀況
|
90 |
+
- 審核學生請假申請
|
91 |
+
學生功能:
|
92 |
+
- 查看課表及進行點名
|
93 |
+
- 查看出缺席和請假記錄
|
94 |
+
- 申請請假
|
95 |
+
該完整專案在github上,網址:https://github.com/WISD-2020/final02
|
96 |
+
''',
|
97 |
+
'氣管插管預測簡述:動機與目的:為了協助醫生在執行插管時更精確地將氧氣管置入正確位置,我們利用影像分割技術(如 TransUnet、UNet++ 等)來實現該目標。最後,我們結合邊緣檢測與形態學技術,精確量化預測與實際的誤差,以提高插管的成功率並降低風險。',
|
98 |
+
'貨車車牌辨識簡述:動機與目的:為了提高貨車進出倉庫的效率,我們建立一個車牌辨識系統,該系統基於深度學習技術,主要透過yolo來偵測車牌位置,再透過OCR技術來識別車牌號碼,最後將車牌號碼與倉庫數據庫進行比對,以確保進出貨物的準確性。 ',
|
99 |
+
'聊天機器人簡述:過去在研究語言模型時,尚未設計與機器人對話的專屬介面,因此這次實作了一個簡單的聊天機器人介面。該聊天機器人基於 Qwen 大型預訓練語言模型,這是一個多語言支持的模型,供使用者進行互動體驗。',
|
100 |
+
]
|
101 |
+
def get_embedding(text):
|
102 |
+
embd_ = embd.encode(text)
|
103 |
+
embd_ = embd_ / np.linalg.norm(embd_) # 归一化
|
104 |
+
return embd_
|
105 |
+
|
106 |
+
#建立嵌入向量庫
|
107 |
+
def add_to_faiss_index(embeddings):
|
108 |
+
vector = np.array(embeddings)
|
109 |
+
# 设置检索维度
|
110 |
+
index = faiss.IndexFlatIP(vector.shape[1])
|
111 |
+
faiss.normalize_L2(vector)
|
112 |
+
index.add(vector)
|
113 |
+
return index
|
114 |
+
|
115 |
+
embedding_array = [get_embedding(text) for text in doc]
|
116 |
+
faiss_index =add_to_faiss_index(embedding_array)
|
117 |
+
embedding_array_1 = [get_embedding(text) for text in docs]
|
118 |
+
faiss_index_1 =add_to_faiss_index(embedding_array_1 )
|
119 |
+
def vector_search(index,index_1, query_embedding, k=3, threshold=0.5):
|
120 |
+
distances, indices = index.search(np.array([query_embedding]), k)
|
121 |
+
|
122 |
+
# 如果想要筛选相似度大于某个阈值的结果,可以这样做
|
123 |
+
results = []
|
124 |
+
for i in range(k):
|
125 |
+
if distances[0][i] > threshold: # 余弦相似度的距离应该是越大越相似
|
126 |
+
results.append(docs[indices[0][i]])
|
127 |
+
if not results:
|
128 |
+
distances, indices = index_1.search(np.array([query_embedding]), k)
|
129 |
+
for i in range(k):
|
130 |
+
if distances[0][i] > 0.4: # 余弦相似度的距离应该是越大越相似
|
131 |
+
results.append(docs[indices[0][i]])
|
132 |
+
print('\n'.join(results))
|
133 |
+
return results if results else None
|
134 |
+
def resume_QA(message, history):
|
135 |
+
query_embedding = get_embedding(message)
|
136 |
+
search_results = vector_search(faiss_index,faiss_index_1, query_embedding)
|
137 |
+
if search_results:
|
138 |
+
search_results='\n'.join(search_results)
|
139 |
+
prompt = [
|
140 |
+
{"role": "system", "content":f"""
|
141 |
+
你是一位助手,幫助人家了解巫宇哲這個人。你只能根據下列提供的資訊回答問題,並且所有回答必須完全符合已提供的資訊,不能添加任何新內容或自己推測的訊息。如果問題的答案不在提供的資訊中,請明確回答 "沒有這方面的資料"。所有回答必須基於已提供的資料。
|
142 |
+
並且**嚴禁提及自己是 AI 或無法回答問題**。所有回答必須基於已提供的資料,禁止出現類似「在這個特定的環境下,我無法提供詳細信息」、「我是AI,無法回答此問題」或任何與 AI 自身相關的回覆。
|
143 |
+
|
144 |
+
提供的資訊:
|
145 |
+
Name: 巫宇哲
|
146 |
+
{search_results}
|
147 |
+
|
148 |
+
請根據上面的資訊來回答問題。
|
149 |
+
"""}
|
150 |
+
]
|
151 |
+
for i in history:
|
152 |
+
prompt.append({"role": "user", "content": i[0]})
|
153 |
+
prompt.append({"role": "assisant", "content": i[1]})
|
154 |
+
prompt.append({"role": "user", "content": message})
|
155 |
+
|
156 |
+
messages = prompt
|
157 |
+
|
158 |
+
text = tokenizer.apply_chat_template(
|
159 |
+
messages,
|
160 |
+
tokenize=False,
|
161 |
+
add_generation_prompt=True
|
162 |
+
)
|
163 |
+
|
164 |
+
model_inputs = tokenizer([text], return_tensors="pt").to("cuda")
|
165 |
+
streamer = TextIteratorStreamer(tokenizer, timeout=50., skip_prompt=True, skip_special_tokens=True)
|
166 |
+
generate_kwargs = dict(
|
167 |
+
model_inputs,
|
168 |
+
streamer=streamer,
|
169 |
+
max_new_tokens=512,
|
170 |
+
do_sample=True,
|
171 |
+
temperature=0.9,
|
172 |
+
top_k=5,
|
173 |
+
top_p=0.95,
|
174 |
+
min_length=50,
|
175 |
+
)
|
176 |
+
t = Thread(target=model.generate, kwargs=generate_kwargs)
|
177 |
+
t.start()
|
178 |
+
partial_message = ""
|
179 |
+
for new_token in streamer:
|
180 |
+
partial_message += new_token
|
181 |
+
yield partial_message
|
182 |
+
|
183 |
avatar_images = ["https://cdn-icons-png.flaticon.com/128/3135/3135715.png",
|
184 |
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTIJYnfODgs7q_Q4k6RoUL592NBlSF7wUTEhT92lRyqc4HTunB-"]
|
185 |
|
186 |
custom_css = """
|
187 |
.gradio-container {background-color: #f0f0f0;padding-top: 0px !important;}
|
188 |
+
/*.container {max-width: 100px; margin: 0; font-family: 'Arial', sans-serif;}*/
|
189 |
.header {background-color: #2c3e50; color: white; padding: 10px; text-align: center; border-radius: 10px 10px 0 0;margin-bottom: 0; /* Ensure no margin below header */}
|
190 |
.content {background-color: white; padding: 10px; border-radius: 0 0 10px 10px; margin: 0;margin-top: 0;}
|
191 |
.profile-pic {width: 150px; height: 150px; border-radius: 50%; margin: 20px auto; display: block;}
|
|
|
209 |
margin: 0; /* 移除段落的默认外边距 */
|
210 |
}
|
211 |
|
212 |
+
|
213 |
+
/* 主要針對chatbot聊天對話框設計版面*/
|
214 |
+
.custom-chatbot {
|
215 |
+
background-color: #FBFBFF !important; /* 機器人對話框背景顏色 */
|
216 |
+
|
217 |
+
}
|
218 |
+
.custom-chatbot .flex-wrap.user {
|
219 |
+
background-color: #ECF5FF !important; /* 使用者訊息框的背景顏色 */
|
220 |
+
border: solid 1px #E6CAFF
|
221 |
+
}
|
222 |
+
.custom-chatbot .flex-wrap.bot {
|
223 |
+
background-color: #ECF5FF !important; /* 使用者訊息框的背景顏色 */
|
224 |
+
border: solid 1px #E6CAFF
|
225 |
+
}
|
226 |
+
.custom-chatbot label.svelte-1b6s6s {
|
227 |
+
background-color: #E8FFF5 !important; /* 設定背景顏色 */
|
228 |
+
}
|
229 |
+
button.lg.primary.svelte-cmf5ev {
|
230 |
+
background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%) !important; /* 按鈕背景顏色 */
|
231 |
+
color: #4F4F4F !important; /* 文字顏色 */
|
232 |
+
}
|
233 |
"""
|
234 |
custom_footer = """
|
235 |
<div class="custom-footer">
|
|
|
461 |
retry_btn='重新送出',
|
462 |
undo_btn=None
|
463 |
)
|
464 |
+
gr.Markdown("""<hr style="border-top: 2px solid;border-color:#169bf2;">""")
|
465 |
+
gr.HTML(f"""
|
466 |
+
<h2>其他專案</h2>
|
467 |
+
<h3>
|
468 |
+
<ul> <li>分類預測和回歸預測:</li> </ul>
|
469 |
+
</h3>
|
470 |
+
使用<a href="https://archive.ics.uci.edu/dataset/2/adult">成人資料集</a> 進行測試,針對收入(income)欄位進行分類預測,針對每週工時(hours-per-week)欄位進行回歸預測。我們應用了決策樹、隨機森林、支援向量機等機器學習演算法,並使用混淆矩陣、ROC 曲線、AUC 等指標來評估模型的表現。
|
471 |
+
<h3>
|
472 |
+
<ul> <li>分群預測:</li> </ul>
|
473 |
+
</h3>
|
474 |
+
使用<a href="https://archive.ics.uci.edu/ml/datasets/iris">IRIS資料集</a>進行分群預測,採用了 K-means、DBSCAN 和層次聚類演算法。模型表現的評估則基於 purity 指標。
|
475 |
+
<h3>
|
476 |
+
<ul> <li>關聯規則:</li> </ul>
|
477 |
+
</h3>
|
478 |
+
使用交易資料集進行關聯規則分析,採用了 Apriori 和 FP-Growth 演算法來找出產品之間的關聯,並以支持度與置信度來評估規則的強度。該完整內容如右:<a href="file/履歷資料/DM/DM_4.pdf" target="_blank">關聯規則文件檔案</a>
|
479 |
+
<h3>
|
480 |
+
<ul> <li>深度學習做分類和回歸預測:</li> </ul>
|
481 |
+
</h3>
|
482 |
+
與上述分類與回歸預測相似,使用 <a href="https://archive.ics.uci.edu/dataset/2/adult">成人資料集</a>作為測試,不同之處在於這次使用了自建的類神經網路進行預測,評估指標依然保持一致。
|
483 |
+
<h3>
|
484 |
+
<ul> <li>降維:</li> </ul>
|
485 |
+
</h3>
|
486 |
+
應用了多維縮放(MDS)與 t-SNE 等降維技術,將高維資料降至二維並進行視覺化展示。同時,對於名目尺度資料,我們除了使用 one-hot encoding,還特別測試了 word embedding 技術。該完整內容如右:<a href="file/履歷資料/ML/ML_4.pdf" target="_blank">降維文件檔案</a>
|
487 |
+
|
488 |
+
""")
|
489 |
+
|
490 |
+
with gr.Tab("AI小助手",elem_classes="content"):
|
491 |
+
gr.Markdown("""
|
492 |
+
## <div align='center' >AI履歷助手:巫宇哲的智能個人資料查詢</div>
|
493 |
+
<strong>主要用途:</strong>此語言模型運用檢索增強生成 (RAG) 技術,為巫宇哲的個人資訊提供客製化聊天服務。透過實��檢索相關資料,模型能夠準確且生成個性化回覆,無需額外訓練。
|
494 |
+
特別適合在有新資料時,模型能即時更新知識,而無需反覆進行訓練,或是在無法進行大規模模型訓練的情境下使用。<br>
|
495 |
+
※ 注意:該模型提供的資訊僅供參考,可能存在誤差,請根據履歷資料和專案展示頁面加以判斷。若是出現模型回答不好的情況也可以按重新發送按鈕,讓模型在回答一次。
|
496 |
+
""")
|
497 |
+
gr.ChatInterface(
|
498 |
+
resume_QA,
|
499 |
+
chatbot=gr.Chatbot(height=400, elem_classes="custom-chatbot",avatar_images=avatar_images),
|
500 |
+
textbox=gr.Textbox(placeholder="Ask me a yes or no question", container=False, scale=7),
|
501 |
+
examples=["有參與過那些專案?", "有哪些證照或是技能?", "有什麼特殊經歷?","貨車車牌辨識在做什麼?","會使用python嗎?"],
|
502 |
+
cache_examples=True,
|
503 |
+
retry_btn="Retry",
|
504 |
+
undo_btn="Delete Previous",
|
505 |
+
clear_btn="Clear",
|
506 |
+
)
|
507 |
# gr.HTML(custom_footer)
|
508 |
resume_app.launch(allowed_paths=['./'],favicon_path='履歷資料/android-chrome-512x512.png')
|