JohnsonMLEngineer commited on
Commit
2475c3e
Β·
verified Β·
1 Parent(s): 1a3f8a2

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +275 -0
app.py ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import streamlit as st
3
+ from dotenv import load_dotenv
4
+ from pinecone import Pinecone
5
+ from langchain_pinecone import PineconeVectorStore
6
+ from langchain.chains import create_retrieval_chain
7
+ from langchain.chains.combine_documents import create_stuff_documents_chain
8
+ from langchain_core.prompts import ChatPromptTemplate
9
+ import pandas as pd
10
+ from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings
11
+ import json
12
+ from datetime import datetime
13
+
14
+ load_dotenv()
15
+
16
+ # Constants
17
+ PAGE_TITLE = "PTE Assistant - Multi-Model Comparison"
18
+ PAGE_ICON = "πŸŽ“"
19
+ MODELS = {
20
+ "Gemini 1.5 Pro": "gemini-1.5-pro",
21
+ "Gemini 1.5 Flash": "gemini-1.5-flash",
22
+ "Gemini 1.5 Flash-8B": "gemini-1.5-flash-8b"
23
+ }
24
+ TRAINING_DATA_FILE = "training_data.json"
25
+
26
+ # Initialize session state
27
+ if "chat_history" not in st.session_state:
28
+ st.session_state.chat_history = []
29
+ if "selected_responses" not in st.session_state:
30
+ st.session_state.selected_responses = {}
31
+ if "feedback_messages" not in st.session_state:
32
+ st.session_state.feedback_messages = {}
33
+
34
+ def load_training_data():
35
+ """Load existing training data or return empty list if file doesn't exist"""
36
+ try:
37
+ if os.path.exists(TRAINING_DATA_FILE) and os.path.getsize(TRAINING_DATA_FILE) > 0:
38
+ with open(TRAINING_DATA_FILE, 'r') as f:
39
+ return json.load(f)
40
+ return []
41
+ except json.JSONDecodeError:
42
+ st.warning("Found invalid training data file. Creating new one.")
43
+ return []
44
+ except Exception as e:
45
+ st.error(f"Error loading training data: {str(e)}")
46
+ return []
47
+
48
+ def save_training_data(data):
49
+ """Save data for future training"""
50
+ try:
51
+ # Load existing data
52
+ existing_data = load_training_data()
53
+
54
+ # Append new data
55
+ existing_data.append(data)
56
+
57
+ # Save updated data
58
+ with open(TRAINING_DATA_FILE, 'w') as f:
59
+ json.dump(existing_data, f, indent=2)
60
+
61
+ return True
62
+ except Exception as e:
63
+ st.error(f"Error saving training data: {str(e)}")
64
+ return False
65
+
66
+ def show_feedback_message(idx, message, is_error=False):
67
+ """Show feedback message and store it in session state"""
68
+ st.session_state.feedback_messages[idx] = {
69
+ "message": message,
70
+ "is_error": is_error,
71
+ "timestamp": datetime.now().isoformat()
72
+ }
73
+
74
+ def display_feedback(idx):
75
+ """Display feedback message if it exists"""
76
+ if idx in st.session_state.feedback_messages:
77
+ feedback = st.session_state.feedback_messages[idx]
78
+ if feedback["is_error"]:
79
+ st.error(feedback["message"])
80
+ else:
81
+ st.success(feedback["message"])
82
+
83
+ def set_page_config():
84
+ st.set_page_config(page_title=PAGE_TITLE, page_icon=PAGE_ICON, layout="wide")
85
+
86
+ @st.cache_resource
87
+ def initialize_rag_components():
88
+ # Initialize Pinecone
89
+ Pinecone(api_key=os.environ.get("PINECONE_API_KEY"))
90
+
91
+ # Initialize vector store
92
+ docsearch = PineconeVectorStore.from_existing_index(
93
+ index_name = "dataset2",
94
+ embedding = GoogleGenerativeAIEmbeddings(model="models/text-embedding-004")
95
+ )
96
+
97
+ # Create retriever
98
+ retriever = docsearch.as_retriever(search_type="similarity", search_kwargs={"k": 10})
99
+
100
+ # Initialize models
101
+ llms = {
102
+ model_name: ChatGoogleGenerativeAI(
103
+ model=model_id,
104
+ temperature=0,
105
+ max_output_tokens=800
106
+ ) for model_name, model_id in MODELS.items()
107
+ }
108
+
109
+ # System prompt remains the same...
110
+ system_prompt = """
111
+ You are an advanced AI assistant specialized in PTE (Pearson Test of English) exam preparation. Your role is to provide expert guidance, explanations, and strategies to help students excel in all aspects of the PTE exam.
112
+ Core Responsibilities:
113
+
114
+ Provide accurate, detailed information about PTE exam structure, scoring, and recent updates.
115
+ Offer tailored advice and strategies for each PTE section: Speaking, Writing, Reading, and Listening.
116
+ Suggest effective study plans and time management techniques.
117
+ Provide constructive feedback on practice responses (when given).
118
+
119
+ Guidelines for Responses:
120
+
121
+ Use the following retrieved context to inform your answers: {context}
122
+ If the context doesn't provide sufficient information or
123
+ If you don't know the answer or are unsure, clearly state this and suggest reliable resources for further information.
124
+ Tailor your language complexity to the user's apparent level of understanding.
125
+ Be concise yet thorough. Aim for clear, actionable advice.
126
+ Use bullet points or numbered lists for step-by-step instructions or multiple tips.
127
+
128
+ Ethical Considerations:
129
+ Topic Limitation: If a question is outside the scope of the PTE exam, kindly inform the user that you are only equipped to address PTE-related topics.
130
+ Never provide or encourage cheating methods.
131
+ Emphasize the importance of genuine language skill development over exam tricks.
132
+ Respect copyright; produce exact questions from official PTE materials.
133
+ """
134
+
135
+ prompt = ChatPromptTemplate.from_messages([
136
+ ("system", system_prompt),
137
+ ("human", "{input}")
138
+ ])
139
+
140
+ # Create chains for each model
141
+ chains = {}
142
+ for model_name, llm in llms.items():
143
+ question_answer_chain = create_stuff_documents_chain(llm, prompt)
144
+ chains[model_name] = create_retrieval_chain(retriever, question_answer_chain)
145
+
146
+ return chains
147
+
148
+ def display_chat_history():
149
+ for idx, interaction in enumerate(st.session_state.chat_history):
150
+ # Display user message
151
+ st.write("πŸ‘€ **You:**", interaction["user_input"])
152
+
153
+ # Create columns for model responses
154
+ cols = st.columns(len(MODELS))
155
+ for col, (model_name, response) in zip(cols, interaction["model_responses"].items()):
156
+ with col:
157
+ st.write(f"πŸ€– **{model_name}:**")
158
+ st.write(response)
159
+
160
+ # Add selection button if response hasn't been selected yet
161
+ if idx not in st.session_state.selected_responses:
162
+ if st.button(f"Select this response", key=f"select_{idx}_{model_name}"):
163
+ st.session_state.selected_responses[idx] = {
164
+ "selected_model": model_name,
165
+ "selected_response": response
166
+ }
167
+ if save_training_data({
168
+ "timestamp": datetime.now().isoformat(),
169
+ "question": interaction["user_input"],
170
+ "model_responses": interaction["model_responses"],
171
+ "selected_model": model_name,
172
+ "selected_response": response,
173
+ "custom_response": None
174
+ }):
175
+ show_feedback_message(
176
+ idx,
177
+ f"βœ… Response from {model_name} has been selected and saved successfully! This response will be used to improve future answers."
178
+ )
179
+ else:
180
+ show_feedback_message(
181
+ idx,
182
+ "❌ Failed to save the selected response. Please try again.",
183
+ is_error=True
184
+ )
185
+
186
+ # Show custom response input if no response is selected yet
187
+ if idx not in st.session_state.selected_responses:
188
+ st.write("πŸ’‘ **If none of the responses are satisfactory, provide a custom answer:**")
189
+ custom_response = st.text_area("Custom response:", key=f"custom_{idx}")
190
+ if st.button("Submit custom response", key=f"submit_custom_{idx}"):
191
+ if not custom_response.strip():
192
+ show_feedback_message(
193
+ idx,
194
+ "❌ Please enter a custom response before submitting.",
195
+ is_error=True
196
+ )
197
+ else:
198
+ st.session_state.selected_responses[idx] = {
199
+ "selected_model": "custom",
200
+ "selected_response": custom_response
201
+ }
202
+ if save_training_data({
203
+ "timestamp": datetime.now().isoformat(),
204
+ "question": interaction["user_input"],
205
+ "model_responses": interaction["model_responses"],
206
+ "selected_model": "custom",
207
+ "selected_response": custom_response,
208
+ "custom_response": custom_response
209
+ }):
210
+ show_feedback_message(
211
+ idx,
212
+ "βœ… Your custom response has been submitted and saved successfully! This will help improve future responses."
213
+ )
214
+ else:
215
+ show_feedback_message(
216
+ idx,
217
+ "❌ Failed to save your custom response. Please try again.",
218
+ is_error=True
219
+ )
220
+ #else:
221
+ # Display the selected response
222
+ #selected = st.session_state.selected_responses[idx]
223
+ # st.success(f"βœ… Selected response from: {selected['selected_model']}")
224
+
225
+ # Display any feedback messages for this interaction
226
+ display_feedback(idx)
227
+
228
+ st.divider()
229
+
230
+ def main():
231
+ set_page_config()
232
+
233
+ st.header("PTE Assistant - Multi-Model Comparison πŸŽ“")
234
+ st.subheader("Compare responses and select the best answer")
235
+
236
+ # Initialize RAG chains for all models
237
+ rag_chains = initialize_rag_components()
238
+
239
+ # Chat input
240
+ user_input = st.chat_input("Your question:")
241
+
242
+ if user_input:
243
+ # Container for responses
244
+ model_responses = {}
245
+
246
+ # Progress bar
247
+ progress_bar = st.progress(0)
248
+ status_text = st.empty()
249
+
250
+ # Get responses from each model
251
+ for i, (model_name, chain) in enumerate(rag_chains.items()):
252
+ status_text.text(f"Getting response from {model_name}...")
253
+ with st.spinner(f"Thinking... ({model_name})"):
254
+ response = chain.invoke({"input": user_input})
255
+ model_responses[model_name] = response["answer"]
256
+ progress_bar.progress((i + 1) / len(MODELS))
257
+
258
+ # Clear progress indicators
259
+ progress_bar.empty()
260
+ status_text.empty()
261
+
262
+ # Store the interaction in chat history
263
+ st.session_state.chat_history.append({
264
+ "user_input": user_input,
265
+ "model_responses": model_responses
266
+ })
267
+
268
+ # Display chat history with response selection
269
+ display_chat_history()
270
+
271
+
272
+
273
+
274
+ if __name__ == "__main__":
275
+ main()