Omogbolahan commited on
Commit
dec867e
·
1 Parent(s): 22b3bd0

cleaned app

Browse files
Files changed (1) hide show
  1. app.py +0 -304
app.py CHANGED
@@ -195,216 +195,6 @@ tools = [{"type": "function", "function": record_user_details_json},
195
  {"type": "function", "function": list_github_repos_json}]
196
 
197
 
198
- class Me:
199
-
200
- def __init__(self):
201
- self.openai_api_key = os.getenv('OPENAI_API_KEY')
202
- self.name = "Gabriel Olatunji"
203
- self.profiles = {'linkedin': '', 'resume': ''}
204
- self.summary = ""
205
-
206
- DATASET_ID = "O-G-O/about_me_bot_docs"
207
-
208
- # Download all dataset files from HF
209
- files = list_repo_files(DATASET_ID, repo_type="dataset")
210
- hf_paths = {}from dotenv import load_dotenv
211
- from openai import OpenAI
212
- import json
213
- import os
214
- import requests
215
- import re
216
- from pypdf import PdfReader
217
-
218
- from huggingface_hub import hf_hub_download, list_repo_files
219
-
220
- import gradio as gr
221
-
222
-
223
- load_dotenv(override=True)
224
-
225
- def push(text):
226
- payload = {"token": os.getenv("PUSHOVER_TOKEN"),
227
- "user": os.getenv("PUSHOVER_USER"),
228
- "message": text
229
- }
230
- pushover_url = "https://api.pushover.net/1/messages.json"
231
- requests.post(pushover_url, data=payload)
232
-
233
-
234
- def record_user_details(email, name="Name not provided", notes="not provided"):
235
- """
236
- Records user details and sends a push notification about the new entry.
237
-
238
- This function takes a user's email, optional name, and optional notes.
239
- It then sends a push notification (to my window chrome) summarizing
240
- the recorded interest. It's intended to be used in conjunction with information or a structure
241
- defined by `record_user_details_json`.
242
-
243
- Args:
244
- email (str): The email address of the user. This is a mandatory field.
245
- name (str, optional): The name of the user. Defaults to "Name not provided".
246
- notes (str, optional): Any additional notes or information about the user's interest.
247
- Defaults to "not provided".
248
-
249
- Returns:
250
- dict: A dictionary indicating the status of the recording.
251
- Currently returns `{"recorded": "ok"}` regardless of actual storage.
252
- """
253
- # use information of record_user_details_json
254
- push(f"Recording interest from {name} with email {email} and notes {notes}")
255
- return {"recorded": "ok"}
256
-
257
-
258
- def record_unknown_question(question):
259
- """
260
- Records a user's question that the system was unable to answer and sends a push notification.
261
-
262
- This function takes a question string, sends a push notification
263
- to alert about the unanswerable question, and indicates that the question has been
264
- "recorded". It is intended to integrate the structure from `record_unknown_question_json`
265
- for storage and logging.
266
-
267
- Args:
268
- question (str): The specific question that the system could not answer.
269
-
270
- Returns:
271
- dict: A dictionary indicating the status of the recording.
272
- Currently returns `{"recorded": "ok"}` regardless of actual storage.
273
- """
274
- # use information of record_unknown_question_json
275
- push(f"Recording {question} asked that I couldn't answer")
276
- return {"recorded": "ok"}
277
-
278
-
279
- def list_github_repos(profile_url: str):
280
- """
281
- Lists all public repositories name, url and description
282
-
283
- Args:
284
- profile_url (str): GitHub profile URL.
285
-
286
- Returns:
287
- dict: A dictionary containing a list of public repository details if successful.
288
- Returns a dictionary with an "error" key if the username cannot be extracted,
289
- or the API request fails.
290
- """
291
- # 1. Extract username from the URL
292
- match = re.search(r'github\.com/([^/]+)', profile_url)
293
- username = match.group(1)
294
-
295
- base_api_url = f"https://api.github.com/users/{username}/repos"
296
-
297
- headers = {
298
- "Accept": "application/vnd.github.v3+json"
299
- }
300
-
301
- all_repos = []
302
- page = 1
303
- per_page = 100
304
-
305
- print(f"Attempting to list PUBLIC repositories for {username}...", flush=True)
306
-
307
- try:
308
- while True:
309
- params = {"page": page, "per_page": per_page, "type": "public"}
310
- response = requests.get(base_api_url, headers=headers, params=params)
311
- response.raise_for_status()
312
-
313
- repos_on_page = response.json()
314
- if not repos_on_page:
315
- break
316
-
317
-
318
- for repo in repos_on_page:
319
- if not repo.get("private"):
320
- all_repos.append({
321
- "name": repo.get("name"),
322
- "html_url": repo.get("html_url"),
323
- "description": repo.get("description"),
324
- })
325
-
326
- # Check for 'Link' header to determine if there are more pages
327
- if 'link' not in response.headers or 'rel="next"' not in response.headers['link']:
328
- break # No more pages
329
-
330
- page += 1
331
-
332
- return {"repositories": all_repos, "count": len(all_repos)}
333
-
334
- except requests.exceptions.ConnectionError as errc:
335
- return {"error": f"Connection error fetching public repositories: {errc}. Check internet connection."}
336
-
337
- except requests.exceptions.Timeout as errt:
338
- return {"error": f"Timeout error fetching public repositories: {errt}. GitHub API took too long to respond."}
339
-
340
- except requests.exceptions.RequestException as err:
341
- return {"error": f"An unexpected error occurred during GitHub API request: {err}"}
342
-
343
- except json.JSONDecodeError:
344
- return {"error": "Failed to decode JSON response from GitHub API. Invalid API response."}
345
-
346
-
347
- record_user_details_json = {
348
- "name": "record_user_details",
349
- "description": "Use this tool to record that a user is interested in being in touch and provided an email address",
350
- "parameters": {
351
- "type": "object",
352
- "properties": {
353
- "email": {
354
- "type": "string",
355
- "description": "The email address of this user"
356
- },
357
- "name": {
358
- "type": "string",
359
- "description": "The user's name, if they provided it"
360
- }
361
- ,
362
- "notes": {
363
- "type": "string",
364
- "description": "Any additional information about the conversation that's worth recording to give context"
365
- }
366
- },
367
- "required": ["email"],
368
- "additionalProperties": False
369
- }
370
- }
371
-
372
- record_unknown_question_json = {
373
- "name": "record_unknown_question",
374
- "description": "Always use this tool to record any question that couldn't be answered as you didn't know the answer",
375
- "parameters": {
376
- "type": "object",
377
- "properties": {
378
- "question": {
379
- "type": "string",
380
- "description": "The question that couldn't be answered"
381
- },
382
- },
383
- "required": ["question"]
384
- }
385
- }
386
-
387
- list_github_repos_json = {
388
- "name": "list_github_repos",
389
- "description": "Always use this tool to list all public repository names, URLs, and descriptions.",
390
- "parameters": {
391
- "type": "object",
392
- "properties": {
393
- "profile_url": {
394
- "type": "string",
395
- "description": "The full GitHub profile URL (e.g. https://github.com/omogbolahan94)"
396
- }
397
- },
398
- "required": ["profile_url"],
399
- "additionalProperties": False
400
- }
401
- }
402
-
403
- tools = [{"type": "function", "function": record_user_details_json},
404
- {"type": "function", "function": record_unknown_question_json},
405
- {"type": "function", "function": list_github_repos_json}]
406
-
407
-
408
  class Me:
409
 
410
  def __init__(self):
@@ -502,100 +292,6 @@ class Me:
502
  return response.choices[0].message.content
503
 
504
 
505
- if __name__ == "__main__":
506
- me = Me()
507
- gr.ChatInterface(me.chat, type="messages").launch()
508
-
509
-
510
-
511
-
512
- for f in files:
513
- if f.endswith((".pdf", ".txt")):
514
- hf_paths[f] = hf_hub_download(
515
- repo_id=DATASET_ID,
516
- filename=f,
517
- repo_type="dataset"
518
- )
519
-
520
- # Load PDF files for profiles
521
- for profile in self.profiles:
522
- pdf_filename = f"{profile}.pdf"
523
- if pdf_filename in hf_paths:
524
- reader = PdfReader(hf_paths[pdf_filename])
525
- result_str = ""
526
- for page in reader.pages:
527
- text = page.extract_text()
528
- if text:
529
- result_str += text
530
- self.profiles[profile] += result_str
531
-
532
- self.linkedin = self.profiles['linkedin']
533
- self.resume = self.profiles['resume']
534
-
535
- # Load summary.txt from HF
536
- summary_filename = "summary.txt"
537
- if summary_filename in hf_paths:
538
- with open(hf_paths[summary_filename], "r", encoding="utf-8") as f:
539
- self.summary = f.read()
540
-
541
- def handle_tool_calls(self, tool_calls):
542
- results = []
543
- for tool_call in tool_calls:
544
- tool_name = tool_call.function.name
545
- arguments = json.loads(tool_call.function.arguments)
546
- print(f"Tool called: {tool_name}", flush=True)
547
- tool = globals().get(tool_name)
548
- result = tool(**arguments) if tool else {}
549
- results.append({"role": "tool","content": json.dumps(result),"tool_call_id": tool_call.id})
550
- return results
551
-
552
-
553
- def system_prompt(self):
554
- system_prompt = f"You are acting as {self.name}. You are answering questions on {self.name}'s website, \
555
- particularly questions related to {self.name}'s career, background, skills and experience. \
556
- Your responsibility is to represent {self.name} for interactions on the website as faithfully as possible. \
557
- You are given a summary of {self.name}'s background and LinkedIn profile which you can use to answer questions. \
558
- Be professional and engaging, as if talking to a potential client or future employer who came across the website. \
559
- 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. \
560
- 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.\
561
- If the user requested to know about any projects you have worked on, use your list_github_repos tool to access your github repository and list repos with their names, url and description and then describe all relevant project in a well structured format even if it has to be in a bullet point format."
562
-
563
- system_prompt += f"\n\n## Summary:\n{self.summary}\n\n## LinkedIn Profile:\n{self.linkedin}\n\n"
564
- system_prompt += f"With this context, please chat with the user, always staying in character as {self.name}."
565
- return system_prompt
566
-
567
-
568
- def chat(self, message, history):
569
- messages = [{"role": "system", "content": self.system_prompt()}] + history + [{"role": "user", "content": message}]
570
-
571
- done = False
572
- while not done:
573
- # gemini = OpenAI(api_key=self.google_api_key, base_url=self.google_gai_url)
574
- # model_name = "gemini-2.0-flash"
575
- # response = gemini.chat.completions.create(model=model_name, messages=messages, tools=tools)
576
- # finish_reason = response.choices[0].finish_reason
577
- openai_client = OpenAI(api_key=self.openai_api_key)
578
-
579
- model_name = "gpt-3.5-turbo"
580
-
581
- response = openai_client.chat.completions.create(
582
- model=model_name,
583
- messages=messages,
584
- tools=tools
585
- )
586
- finish_reason = response.choices[0].finish_reason
587
-
588
- if finish_reason=="tool_calls":
589
- message = response.choices[0].message
590
- tool_calls = message.tool_calls
591
- results = self.handle_tool_calls(tool_calls)
592
- messages.append(message)
593
- messages.extend(results)
594
- else:
595
- done = True
596
- return response.choices[0].message.content
597
-
598
-
599
  if __name__ == "__main__":
600
  me = Me()
601
  gr.ChatInterface(me.chat, type="messages").launch()
 
195
  {"type": "function", "function": list_github_repos_json}]
196
 
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  class Me:
199
 
200
  def __init__(self):
 
292
  return response.choices[0].message.content
293
 
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  if __name__ == "__main__":
296
  me = Me()
297
  gr.ChatInterface(me.chat, type="messages").launch()