oceddyyy commited on
Commit
6d6d07b
·
verified ·
1 Parent(s): b176bc8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +185 -183
app.py CHANGED
@@ -1,183 +1,185 @@
1
- import gradio as gr
2
- import json
3
- from sentence_transformers import SentenceTransformer
4
- from transformers import pipeline
5
- from sklearn.metrics.pairwise import cosine_similarity
6
- import numpy as np
7
- import os
8
-
9
- # === Custom PUP-themed CSS ===
10
- PUP_Themed_css = """
11
- html, body, .gradio-container, .gr-app {
12
- height: 100% !important;
13
- margin: 0 !important;
14
- padding: 0 !important;
15
- background: linear-gradient(to bottom right, #800000, #ff0000, #ffeb3b, #ffa500) !important;
16
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
17
- color: #1b4332 !important;
18
- }
19
- """
20
-
21
- # === Load Models and Data ===
22
- embedding_model = SentenceTransformer('paraphrase-mpnet-base-v2')
23
- llm = pipeline("text2text-generation", model="google/flan-t5-small")
24
-
25
- with open("dataset.json", "r") as f:
26
- dataset = json.load(f)
27
-
28
- questions = [item["question"] for item in dataset]
29
- answers = [item["answer"] for item in dataset]
30
- question_embeddings = embedding_model.encode(questions, convert_to_tensor=True)
31
-
32
- chat_history = []
33
- feedback_data = []
34
- feedback_questions = []
35
- feedback_answers = []
36
- feedback_embeddings = None
37
-
38
- if os.path.exists("feedback.json") and os.path.getsize("feedback.json") > 0:
39
- with open("feedback.json", "r") as f:
40
- try:
41
- feedback_data = json.load(f)
42
- feedback_questions = [item["question"] for item in feedback_data]
43
- feedback_answers = [item["response"] for item in feedback_data]
44
- if feedback_questions:
45
- feedback_embeddings = embedding_model.encode(feedback_questions, convert_to_tensor=True)
46
- except json.JSONDecodeError:
47
- feedback_data = []
48
-
49
- # === Chatbot Response Function ===
50
- def chatbot_response(query, chat_history):
51
- query_embedding = embedding_model.encode([query], convert_to_tensor=True)
52
-
53
- # === Feedback Matching ===
54
- if feedback_embeddings is not None:
55
- feedback_scores = cosine_similarity(query_embedding.cpu().numpy(), feedback_embeddings.cpu().numpy())[0]
56
- best_idx = int(np.argmax(feedback_scores))
57
- best_score = feedback_scores[best_idx]
58
- matched_feedback = feedback_data[best_idx]
59
-
60
- base_threshold = 0.8
61
- upvotes = matched_feedback.get("upvotes", 0)
62
- downvotes = matched_feedback.get("downvotes", 0)
63
- adjusted_threshold = base_threshold - (0.01 * upvotes) + (0.01 * downvotes)
64
- dynamic_threshold = min(max(adjusted_threshold, 0.4), 1.0)
65
-
66
- if best_score >= dynamic_threshold:
67
- response = matched_feedback["response"]
68
- chat_history.append((query, response))
69
- return "", chat_history, gr.update(visible=True)
70
-
71
- # === Main Handbook Matching ===
72
- similarity_scores = cosine_similarity(query_embedding.cpu().numpy(), question_embeddings.cpu().numpy())[0]
73
- best_idx = int(np.argmax(similarity_scores))
74
- best_score = similarity_scores[best_idx]
75
- matched_q = questions[best_idx]
76
- matched_a = answers[best_idx]
77
-
78
- if best_score < 0.4:
79
- response = "Sorry, I couldn't find a relevant answer."
80
- chat_history.append((query, response))
81
- return "", chat_history, gr.update(visible=True)
82
-
83
- prompt = (
84
- f"The following is an official university handbook statement:\n"
85
- f"\"{matched_a}\"\n\n"
86
- f"Please explain this to a student in a short, natural, and easy-to-understand way. "
87
- f"Use simple words, and do not add new information."
88
- )
89
-
90
- llm_response = llm(prompt, max_length=200, do_sample=True, temperature=0.7, top_p=0.9)[0]["generated_text"].strip()
91
- if not llm_response:
92
- llm_response = "I'm sorry, I couldn't simplify that at the moment."
93
-
94
- a_embedding = embedding_model.encode([matched_a], convert_to_tensor=True)
95
- llm_embedding = embedding_model.encode([llm_response], convert_to_tensor=True)
96
- explanation_similarity = cosine_similarity(a_embedding.cpu().numpy(), llm_embedding.cpu().numpy())[0][0]
97
-
98
- if explanation_similarity >= 0.95:
99
- final_response = f"According to the university handbook, {matched_a}"
100
- else:
101
- final_response = f"According to the university handbook, {matched_a} In simpler terms, {llm_response}"
102
-
103
- chat_history.append((query, final_response))
104
- return "", chat_history, gr.update(visible=True)
105
-
106
- # === Feedback Save & Upvote/Downvote Tracking ===
107
- def record_feedback(feedback, chat_history):
108
- global feedback_embeddings
109
- if chat_history:
110
- last_query, last_response = chat_history[-1]
111
- matched = False
112
-
113
- for item in feedback_data:
114
- existing_embedding = embedding_model.encode([item["question"]], convert_to_tensor=True)
115
- new_embedding = embedding_model.encode([last_query], convert_to_tensor=True)
116
- similarity = cosine_similarity(existing_embedding.cpu().numpy(), new_embedding.cpu().numpy())[0][0]
117
- if similarity >= 0.8 and item["response"] == last_response:
118
- matched = True
119
- votes = {"positive": "upvotes", "negative": "downvotes"}
120
- item[votes[feedback]] = item.get(votes[feedback], 0) + 1
121
- break
122
-
123
- if not matched:
124
- entry = {
125
- "question": last_query,
126
- "response": last_response,
127
- "feedback": feedback,
128
- "upvotes": 1 if feedback == "positive" else 0,
129
- "downvotes": 1 if feedback == "negative" else 0
130
- }
131
- feedback_data.append(entry)
132
-
133
- with open("feedback.json", "w") as f:
134
- json.dump(feedback_data, f, indent=4)
135
-
136
- # Update feedback embeddings
137
- feedback_questions = [item["question"] for item in feedback_data]
138
- if feedback_questions:
139
- feedback_embeddings = embedding_model.encode(feedback_questions, convert_to_tensor=True)
140
-
141
- return gr.update(visible=False)
142
-
143
- # === Gradio UI ===
144
- with gr.Blocks(css=PUP_Themed_css, title="University Handbook AI Chatbot") as demo:
145
- gr.Markdown(
146
- "<div style='"
147
- "background-color: #ffffff; "
148
- "border-radius: 16px; "
149
- "padding: 24px 16px; "
150
- "margin-bottom: 24px; "
151
- "box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15); "
152
- "max-width: 700px; "
153
- "margin-left: auto; "
154
- "margin-right: auto; "
155
- "text-align: center;'>"
156
- "<h1 style='font-size: 2.2rem; margin: 0;'>University Inquiries AI Chatbot</h1>"
157
- "</div>"
158
- )
159
-
160
- state = gr.State(chat_history)
161
- chatbot_ui = gr.Chatbot(label="Chat", show_label=False)
162
-
163
- with gr.Row():
164
- query_input = gr.Textbox(placeholder="Type your question here...", show_label=False)
165
- submit_btn = gr.Button("Submit")
166
-
167
- with gr.Row(visible=False) as feedback_row:
168
- gr.Markdown("Was this helpful?")
169
- thumbs_up = gr.Button("👍")
170
- thumbs_down = gr.Button("👎")
171
-
172
- def handle_submit(message, chat_state):
173
- return chatbot_response(message, chat_state)
174
-
175
- submit_btn.click(handle_submit, [query_input, state], [query_input, chatbot_ui, feedback_row])
176
- query_input.submit(handle_submit, [query_input, state], [query_input, chatbot_ui, feedback_row])
177
-
178
- thumbs_up.click(lambda state: record_feedback("positive", state), inputs=[state], outputs=[feedback_row])
179
- thumbs_down.click(lambda state: record_feedback("negative", state), inputs=[state], outputs=[feedback_row])
180
-
181
- # === Launch App ===
182
- if __name__ == "__main__":
183
- demo.launch()
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ from sentence_transformers import SentenceTransformer
4
+ from transformers import pipeline
5
+ from sklearn.metrics.pairwise import cosine_similarity
6
+ import numpy as np
7
+ import os
8
+
9
+ # === Custom PUP-themed CSS ===
10
+ PUP_Themed_css = """
11
+ html, body, .gradio-container, .gr-app {
12
+ height: 100% !important;
13
+ margin: 0 !important;
14
+ padding: 0 !important;
15
+ background: linear-gradient(to bottom right, #800000, #ff0000, #ffeb3b, #ffa500) !important;
16
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
17
+ color: #1b4332 !important;
18
+ }
19
+ """
20
+
21
+ # === Load Models and Data ===
22
+ embedding_model = SentenceTransformer('paraphrase-mpnet-base-v2')
23
+ llm = pipeline("text2text-generation", model="google/flan-t5-small")
24
+
25
+ with open("dataset.json", "r") as f:
26
+ dataset = json.load(f)
27
+
28
+ questions = [item["question"] for item in dataset]
29
+ answers = [item["answer"] for item in dataset]
30
+ question_embeddings = embedding_model.encode(questions, convert_to_tensor=True)
31
+
32
+ chat_history = []
33
+ feedback_data = []
34
+ feedback_questions = []
35
+ feedback_answers = []
36
+ feedback_embeddings = None
37
+
38
+ feedback_path = "outputs/feedback.json"
39
+ os.makedirs("outputs", exist_ok=True)
40
+
41
+ if os.path.exists(feedback_path) and os.path.getsize(feedback_path) > 0:
42
+ with open(feedback_path, "r") as f:
43
+ try:
44
+ feedback_data = json.load(f)
45
+ feedback_questions = [item["question"] for item in feedback_data]
46
+ feedback_answers = [item["response"] for item in feedback_data]
47
+ if feedback_questions:
48
+ feedback_embeddings = embedding_model.encode(feedback_questions, convert_to_tensor=True)
49
+ except json.JSONDecodeError:
50
+ feedback_data = []
51
+
52
+ # === Chatbot Response Function ===
53
+ def chatbot_response(query, chat_history):
54
+ query_embedding = embedding_model.encode([query], convert_to_tensor=True)
55
+
56
+ # === Feedback Matching ===
57
+ if feedback_embeddings is not None:
58
+ feedback_scores = cosine_similarity(query_embedding.cpu().numpy(), feedback_embeddings.cpu().numpy())[0]
59
+ best_idx = int(np.argmax(feedback_scores))
60
+ best_score = feedback_scores[best_idx]
61
+ matched_feedback = feedback_data[best_idx]
62
+
63
+ base_threshold = 0.8
64
+ upvotes = matched_feedback.get("upvotes", 0)
65
+ downvotes = matched_feedback.get("downvotes", 0)
66
+ adjusted_threshold = base_threshold - (0.01 * upvotes) + (0.01 * downvotes)
67
+ dynamic_threshold = min(max(adjusted_threshold, 0.4), 1.0)
68
+
69
+ if best_score >= dynamic_threshold:
70
+ response = matched_feedback["response"]
71
+ chat_history.append((query, response))
72
+ return "", chat_history, gr.update(visible=True)
73
+
74
+ # === Main Handbook Matching ===
75
+ similarity_scores = cosine_similarity(query_embedding.cpu().numpy(), question_embeddings.cpu().numpy())[0]
76
+ best_idx = int(np.argmax(similarity_scores))
77
+ best_score = similarity_scores[best_idx]
78
+ matched_q = questions[best_idx]
79
+ matched_a = answers[best_idx]
80
+
81
+ if best_score < 0.4:
82
+ response = "Sorry, I couldn't find a relevant answer."
83
+ chat_history.append((query, response))
84
+ return "", chat_history, gr.update(visible=True)
85
+
86
+ prompt = (
87
+ f"The following is an official university handbook statement:\n"
88
+ f"\"{matched_a}\"\n\n"
89
+ f"Please explain this to a student in a short, natural, and easy-to-understand way. "
90
+ f"Use simple words, and do not add new information."
91
+ )
92
+
93
+ llm_response = llm(prompt, max_length=200, do_sample=True, temperature=0.7, top_p=0.9)[0]["generated_text"].strip()
94
+ if not llm_response:
95
+ llm_response = "I'm sorry, I couldn't simplify that at the moment."
96
+
97
+ a_embedding = embedding_model.encode([matched_a], convert_to_tensor=True)
98
+ llm_embedding = embedding_model.encode([llm_response], convert_to_tensor=True)
99
+ explanation_similarity = cosine_similarity(a_embedding.cpu().numpy(), llm_embedding.cpu().numpy())[0][0]
100
+
101
+ if explanation_similarity >= 0.95:
102
+ final_response = f"According to the university handbook, {matched_a}"
103
+ else:
104
+ final_response = f"According to the university handbook, {matched_a} In simpler terms, {llm_response}"
105
+
106
+ chat_history.append((query, final_response))
107
+ return "", chat_history, gr.update(visible=True)
108
+
109
+ # === Feedback Save & Upvote/Downvote Tracking ===
110
+ def record_feedback(feedback, chat_history):
111
+ global feedback_embeddings
112
+ if chat_history:
113
+ last_query, last_response = chat_history[-1]
114
+ matched = False
115
+
116
+ for item in feedback_data:
117
+ existing_embedding = embedding_model.encode([item["question"]], convert_to_tensor=True)
118
+ new_embedding = embedding_model.encode([last_query], convert_to_tensor=True)
119
+ similarity = cosine_similarity(existing_embedding.cpu().numpy(), new_embedding.cpu().numpy())[0][0]
120
+ if similarity >= 0.8 and item["response"] == last_response:
121
+ matched = True
122
+ votes = {"positive": "upvotes", "negative": "downvotes"}
123
+ item[votes[feedback]] = item.get(votes[feedback], 0) + 1
124
+ break
125
+
126
+ if not matched:
127
+ entry = {
128
+ "question": last_query,
129
+ "response": last_response,
130
+ "feedback": feedback,
131
+ "upvotes": 1 if feedback == "positive" else 0,
132
+ "downvotes": 1 if feedback == "negative" else 0
133
+ }
134
+ feedback_data.append(entry)
135
+
136
+ with open(feedback_path, "w") as f:
137
+ json.dump(feedback_data, f, indent=4)
138
+
139
+ feedback_questions = [item["question"] for item in feedback_data]
140
+ if feedback_questions:
141
+ feedback_embeddings = embedding_model.encode(feedback_questions, convert_to_tensor=True)
142
+
143
+ return gr.update(visible=False)
144
+
145
+ # === Gradio UI ===
146
+ with gr.Blocks(css=PUP_Themed_css, title="University Handbook AI Chatbot") as demo:
147
+ gr.Markdown(
148
+ "<div style='"
149
+ "background-color: #ffffff; "
150
+ "border-radius: 16px; "
151
+ "padding: 24px 16px; "
152
+ "margin-bottom: 24px; "
153
+ "box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15); "
154
+ "max-width: 700px; "
155
+ "margin-left: auto; "
156
+ "margin-right: auto; "
157
+ "text-align: center;'>"
158
+ "<h1 style='font-size: 2.2rem; margin: 0;'>University Inquiries AI Chatbot</h1>"
159
+ "</div>"
160
+ )
161
+
162
+ state = gr.State(chat_history)
163
+ chatbot_ui = gr.Chatbot(label="Chat", show_label=False)
164
+
165
+ with gr.Row():
166
+ query_input = gr.Textbox(placeholder="Type your question here...", show_label=False)
167
+ submit_btn = gr.Button("Submit")
168
+
169
+ with gr.Row(visible=False) as feedback_row:
170
+ gr.Markdown("Was this helpful?")
171
+ thumbs_up = gr.Button("👍")
172
+ thumbs_down = gr.Button("👎")
173
+
174
+ def handle_submit(message, chat_state):
175
+ return chatbot_response(message, chat_state)
176
+
177
+ submit_btn.click(handle_submit, [query_input, state], [query_input, chatbot_ui, feedback_row])
178
+ query_input.submit(handle_submit, [query_input, state], [query_input, chatbot_ui, feedback_row])
179
+
180
+ thumbs_up.click(lambda state: record_feedback("positive", state), inputs=[state], outputs=[feedback_row])
181
+ thumbs_down.click(lambda state: record_feedback("negative", state), inputs=[state], outputs=[feedback_row])
182
+
183
+ # === Launch App ===
184
+ if __name__ == "__main__":
185
+ demo.launch()