sagarnildass commited on
Commit
aa9ee4f
·
verified ·
1 Parent(s): 10b466b

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +40 -102
  2. requirements.txt +0 -4
app.py CHANGED
@@ -11,12 +11,10 @@ from collections import defaultdict
11
  import fastapi
12
  from gradio.context import Context
13
  import logging
14
- from rag_utils import RAGSystem
15
 
16
- # Set up logging
17
- logging.basicConfig(level=logging.INFO,
18
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
19
  logger = logging.getLogger(__name__)
 
 
20
 
21
  load_dotenv(override=True)
22
 
@@ -134,85 +132,39 @@ class Me:
134
  self.openai = OpenAI(api_key=os.getenv("GOOGLE_API_KEY"), base_url="https://generativelanguage.googleapis.com/v1beta/openai/")
135
  self.name = "Sagarnil Das"
136
  self.rate_limiter = RateLimiter(max_requests=5, time_window=60) # 5 messages per minute
137
-
138
- # Initialize RAG system
139
- self.rag = RAGSystem()
140
-
141
- # Try to load the RAG index
142
- try:
143
- rag_index_path = "me/rag_index"
144
- if os.path.exists(rag_index_path):
145
- logger.info(f"Loading RAG index from {rag_index_path}")
146
- self.rag.load_index(rag_index_path)
147
- logger.info(f"Loaded {len(self.rag.chunks)} chunks from index")
148
- self.rag_loaded = True
149
- else:
150
- logger.warning(f"RAG index not found at {rag_index_path}. Falling back to full document loading.")
151
- self.rag_loaded = False
152
- # Fall back to loading full documents
153
- self._load_full_documents()
154
- except Exception as e:
155
- logger.error(f"Error loading RAG index: {e}")
156
- logger.warning("Falling back to full document loading")
157
- self.rag_loaded = False
158
- # Fall back to loading full documents
159
- self._load_full_documents()
160
 
161
- def _load_full_documents(self):
162
- """Legacy method to load full documents if RAG fails"""
163
- logger.info("Loading full documents as fallback...")
164
- try:
165
- reader = PdfReader("me/linkedin.pdf")
166
- self.linkedin = ""
167
- for page in reader.pages:
168
- text = page.extract_text()
169
- if text:
170
- self.linkedin += text
171
- with open("me/summary.txt", "r", encoding="utf-8") as f:
172
- self.summary = f.read()
173
- logger.info("Full documents loaded successfully")
174
- except Exception as e:
175
- logger.error(f"Error loading full documents: {e}")
176
- self.linkedin = "LinkedIn profile not available."
177
- self.summary = "Professional summary not available."
178
 
179
  def handle_tool_call(self, tool_calls):
180
  results = []
181
  for tool_call in tool_calls:
182
  tool_name = tool_call.function.name
183
  arguments = json.loads(tool_call.function.arguments)
184
- logger.info(f"Tool called: {tool_name}")
185
  tool = globals().get(tool_name)
186
  result = tool(**arguments) if tool else {}
187
  results.append({"role": "tool","content": json.dumps(result),"tool_call_id": tool_call.id})
188
  return results
189
 
190
- def system_prompt(self, query=None):
191
- """Dynamic system prompt that includes RAG context if RAG is loaded and query is provided"""
192
  system_prompt = f"You are acting as {self.name}. You are answering questions on {self.name}'s website, \
193
  particularly questions related to {self.name}'s career, background, skills and experience. \
194
  Your responsibility is to represent {self.name} for interactions on the website as faithfully as possible. \
 
195
  Be professional and engaging, as if talking to a potential client or future employer who came across the website. \
196
  If you don't know the answer to any question, use your record_unknown_question tool to record the question that you couldn't answer, even if it's about something trivial or unrelated to career. \
197
  If the user is engaging in discussion, try to steer them towards getting in touch via email; ask for their email and record it using your record_user_details tool. \
198
  When a user provides their email, both a push notification and an email notification will be sent. If the user does not provide any note in the message \
199
  in which they provide their email, then give a summary of the conversation so far as the notes."
200
 
201
- # If we have a query and RAG is loaded, use RAG to retrieve relevant context
202
- if query and self.rag_loaded:
203
- try:
204
- context = self.rag.get_context_for_query(query, top_k=3)
205
- system_prompt += f"\n\n## Relevant Background Information:\n{context}\n\n"
206
- except Exception as e:
207
- logger.error(f"Error retrieving RAG context: {e}")
208
- # Fall back to full documents if RAG retrieval fails
209
- if hasattr(self, 'summary') and hasattr(self, 'linkedin'):
210
- system_prompt += f"\n\n## Summary:\n{self.summary}\n\n## LinkedIn Profile:\n{self.linkedin}\n\n"
211
- else:
212
- # Fall back to full documents if RAG is not loaded
213
- if hasattr(self, 'summary') and hasattr(self, 'linkedin'):
214
- system_prompt += f"\n\n## Summary:\n{self.summary}\n\n## LinkedIn Profile:\n{self.linkedin}\n\n"
215
-
216
  system_prompt += f"With this context, please chat with the user, always staying in character as {self.name}."
217
  return system_prompt
218
 
@@ -241,49 +193,35 @@ in which they provide their email, then give a summary of the conversation so fa
241
  if self.rate_limiter.is_rate_limited(user_id):
242
  return "You're sending messages too quickly. Please wait a moment before sending another message."
243
 
244
- try:
245
- # First message includes base system prompt (without query-specific context)
246
- messages = [{"role": "system", "content": self.system_prompt()}]
247
 
248
- # Check if history is a list of dicts (Gradio "messages" format)
249
- if isinstance(history, list) and all(isinstance(h, dict) for h in history):
250
- messages.extend(history)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  else:
252
- # Assume it's a list of [user_msg, assistant_msg] pairs
253
- for user_msg, assistant_msg in history:
254
- messages.append({"role": "user", "content": user_msg})
255
- messages.append({"role": "assistant", "content": assistant_msg})
256
 
257
- # Add the user's message
258
- messages.append({"role": "user", "content": message})
259
-
260
- # Update the system message with query-specific context
261
- try:
262
- messages[0] = {"role": "system", "content": self.system_prompt(query=message)}
263
- except Exception as e:
264
- logger.error(f"Error updating system prompt with RAG context: {e}")
265
- # Keep original system prompt if there's an error
266
-
267
- done = False
268
- while not done:
269
- response = self.openai.chat.completions.create(
270
- model="gemini-2.0-flash",
271
- messages=messages,
272
- tools=tools
273
- )
274
- if response.choices[0].finish_reason == "tool_calls":
275
- tool_calls = response.choices[0].message.tool_calls
276
- tool_result = self.handle_tool_call(tool_calls)
277
- messages.append(response.choices[0].message)
278
- messages.extend(tool_result)
279
- else:
280
- done = True
281
-
282
- return response.choices[0].message.content
283
-
284
- except Exception as e:
285
- logger.error(f"Error in chat method: {e}")
286
- return "I apologize, but I encountered an error processing your request. Please try again later."
287
 
288
 
289
 
 
11
  import fastapi
12
  from gradio.context import Context
13
  import logging
 
14
 
 
 
 
15
  logger = logging.getLogger(__name__)
16
+ logger.setLevel(logging.DEBUG)
17
+
18
 
19
  load_dotenv(override=True)
20
 
 
132
  self.openai = OpenAI(api_key=os.getenv("GOOGLE_API_KEY"), base_url="https://generativelanguage.googleapis.com/v1beta/openai/")
133
  self.name = "Sagarnil Das"
134
  self.rate_limiter = RateLimiter(max_requests=5, time_window=60) # 5 messages per minute
135
+ reader = PdfReader("me/linkedin.pdf")
136
+ self.linkedin = ""
137
+ for page in reader.pages:
138
+ text = page.extract_text()
139
+ if text:
140
+ self.linkedin += text
141
+ with open("me/summary.txt", "r", encoding="utf-8") as f:
142
+ self.summary = f.read()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
  def handle_tool_call(self, tool_calls):
146
  results = []
147
  for tool_call in tool_calls:
148
  tool_name = tool_call.function.name
149
  arguments = json.loads(tool_call.function.arguments)
150
+ print(f"Tool called: {tool_name}", flush=True)
151
  tool = globals().get(tool_name)
152
  result = tool(**arguments) if tool else {}
153
  results.append({"role": "tool","content": json.dumps(result),"tool_call_id": tool_call.id})
154
  return results
155
 
156
+ def system_prompt(self):
 
157
  system_prompt = f"You are acting as {self.name}. You are answering questions on {self.name}'s website, \
158
  particularly questions related to {self.name}'s career, background, skills and experience. \
159
  Your responsibility is to represent {self.name} for interactions on the website as faithfully as possible. \
160
+ You are given a summary of {self.name}'s background and LinkedIn profile which you can use to answer questions. \
161
  Be professional and engaging, as if talking to a potential client or future employer who came across the website. \
162
  If you don't know the answer to any question, use your record_unknown_question tool to record the question that you couldn't answer, even if it's about something trivial or unrelated to career. \
163
  If the user is engaging in discussion, try to steer them towards getting in touch via email; ask for their email and record it using your record_user_details tool. \
164
  When a user provides their email, both a push notification and an email notification will be sent. If the user does not provide any note in the message \
165
  in which they provide their email, then give a summary of the conversation so far as the notes."
166
 
167
+ system_prompt += f"\n\n## Summary:\n{self.summary}\n\n## LinkedIn Profile:\n{self.linkedin}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  system_prompt += f"With this context, please chat with the user, always staying in character as {self.name}."
169
  return system_prompt
170
 
 
193
  if self.rate_limiter.is_rate_limited(user_id):
194
  return "You're sending messages too quickly. Please wait a moment before sending another message."
195
 
196
+ messages = [{"role": "system", "content": self.system_prompt()}]
 
 
197
 
198
+ # Check if history is a list of dicts (Gradio "messages" format)
199
+ if isinstance(history, list) and all(isinstance(h, dict) for h in history):
200
+ messages.extend(history)
201
+ else:
202
+ # Assume it's a list of [user_msg, assistant_msg] pairs
203
+ for user_msg, assistant_msg in history:
204
+ messages.append({"role": "user", "content": user_msg})
205
+ messages.append({"role": "assistant", "content": assistant_msg})
206
+
207
+ messages.append({"role": "user", "content": message})
208
+
209
+ done = False
210
+ while not done:
211
+ response = self.openai.chat.completions.create(
212
+ model="gemini-2.0-flash",
213
+ messages=messages,
214
+ tools=tools
215
+ )
216
+ if response.choices[0].finish_reason == "tool_calls":
217
+ tool_calls = response.choices[0].message.tool_calls
218
+ tool_result = self.handle_tool_call(tool_calls)
219
+ messages.append(response.choices[0].message)
220
+ messages.extend(tool_result)
221
  else:
222
+ done = True
 
 
 
223
 
224
+ return response.choices[0].message.content
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
 
226
 
227
 
requirements.txt CHANGED
@@ -1,9 +1,5 @@
1
- numpy==1.23.5
2
  requests
3
  python-dotenv
4
  gradio
5
  pypdf
6
  openai
7
- faiss-cpu==1.7.4
8
- transformers>=4.30.0
9
- torch>=2.0.0
 
 
1
  requests
2
  python-dotenv
3
  gradio
4
  pypdf
5
  openai