narendrajatti commited on
Commit
61a5a78
·
verified ·
1 Parent(s): 4cf4462

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -105
app.py CHANGED
@@ -1,134 +1,74 @@
1
  from dotenv import load_dotenv
2
  from openai import OpenAI
3
- import json
4
- import os
5
- import requests
6
  from pypdf import PdfReader
7
  import gradio as gr
 
 
 
8
 
9
-
10
  load_dotenv(override=True)
11
 
12
- def push(text):
13
- requests.post(
14
- "https://api.pushover.net/1/messages.json",
15
- data={
16
- "token": os.getenv("PUSHOVER_TOKEN"),
17
- "user": os.getenv("PUSHOVER_USER"),
18
- "message": text,
19
- }
20
- )
21
-
22
-
23
- def record_user_details(email, name="Name not provided", notes="not provided"):
24
- push(f"Recording {name} with email {email} and notes {notes}")
25
- return {"recorded": "ok"}
26
-
27
- def record_unknown_question(question):
28
- push(f"Recording {question}")
29
- return {"recorded": "ok"}
30
-
31
- record_user_details_json = {
32
- "name": "record_user_details",
33
- "description": "Use this tool to record that a user is interested in being in touch and provided an email address",
34
- "parameters": {
35
- "type": "object",
36
- "properties": {
37
- "email": {
38
- "type": "string",
39
- "description": "The email address of this user"
40
- },
41
- "name": {
42
- "type": "string",
43
- "description": "The user's name, if they provided it"
44
- }
45
- ,
46
- "notes": {
47
- "type": "string",
48
- "description": "Any additional information about the conversation that's worth recording to give context"
49
- }
50
- },
51
- "required": ["email"],
52
- "additionalProperties": False
53
- }
54
- }
55
-
56
- record_unknown_question_json = {
57
- "name": "record_unknown_question",
58
- "description": "Always use this tool to record any question that couldn't be answered as you didn't know the answer",
59
- "parameters": {
60
- "type": "object",
61
- "properties": {
62
- "question": {
63
- "type": "string",
64
- "description": "The question that couldn't be answered"
65
- },
66
- },
67
- "required": ["question"],
68
- "additionalProperties": False
69
- }
70
- }
71
-
72
- tools = [{"type": "function", "function": record_user_details_json},
73
- {"type": "function", "function": record_unknown_question_json}]
74
 
75
 
76
  class Me:
77
-
78
  def __init__(self):
79
  self.openai = OpenAI()
80
- self.name = "Ed Donner"
 
 
81
  reader = PdfReader("me/linkedin.pdf")
82
  self.linkedin = ""
83
  for page in reader.pages:
84
  text = page.extract_text()
85
  if text:
86
  self.linkedin += text
 
 
87
  with open("me/summary.txt", "r", encoding="utf-8") as f:
88
  self.summary = f.read()
89
 
90
-
91
- def handle_tool_call(self, tool_calls):
92
- results = []
93
- for tool_call in tool_calls:
94
- tool_name = tool_call.function.name
95
- arguments = json.loads(tool_call.function.arguments)
96
- print(f"Tool called: {tool_name}", flush=True)
97
- tool = globals().get(tool_name)
98
- result = tool(**arguments) if tool else {}
99
- results.append({"role": "tool","content": json.dumps(result),"tool_call_id": tool_call.id})
100
- return results
101
-
102
  def system_prompt(self):
103
- system_prompt = f"You are acting as {self.name}. You are answering questions on {self.name}'s website, \
104
- particularly questions related to {self.name}'s career, background, skills and experience. \
105
- Your responsibility is to represent {self.name} for interactions on the website as faithfully as possible. \
106
- You are given a summary of {self.name}'s background and LinkedIn profile which you can use to answer questions. \
107
- Be professional and engaging, as if talking to a potential client or future employer who came across the website. \
108
- 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. \
109
- 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. "
 
 
 
110
 
111
- system_prompt += f"\n\n## Summary:\n{self.summary}\n\n## LinkedIn Profile:\n{self.linkedin}\n\n"
112
- system_prompt += f"With this context, please chat with the user, always staying in character as {self.name}."
113
- return system_prompt
114
-
115
  def chat(self, message, history):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  messages = [{"role": "system", "content": self.system_prompt()}] + history + [{"role": "user", "content": message}]
117
- done = False
118
- while not done:
119
- response = self.openai.chat.completions.create(model="gpt-4o-mini", messages=messages, tools=tools)
120
- if response.choices[0].finish_reason=="tool_calls":
121
- message = response.choices[0].message
122
- tool_calls = message.tool_calls
123
- results = self.handle_tool_call(tool_calls)
124
- messages.append(message)
125
- messages.extend(results)
126
- else:
127
- done = True
128
- return response.choices[0].message.content
129
-
130
 
131
  if __name__ == "__main__":
132
  me = Me()
133
  gr.ChatInterface(me.chat, type="messages").launch(share=True)
134
-
 
1
  from dotenv import load_dotenv
2
  from openai import OpenAI
 
 
 
3
  from pypdf import PdfReader
4
  import gradio as gr
5
+ import datetime
6
+ from collections import defaultdict
7
+ import os
8
 
9
+ # Load environment variables from .env (includes OPENAI_API_KEY)
10
  load_dotenv(override=True)
11
 
12
+ # In-memory daily question tracker
13
+ user_question_counter = defaultdict(lambda: {"date": None, "count": 0})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
 
16
  class Me:
 
17
  def __init__(self):
18
  self.openai = OpenAI()
19
+ self.name = "Narendra"
20
+
21
+ # Load LinkedIn profile text from PDF
22
  reader = PdfReader("me/linkedin.pdf")
23
  self.linkedin = ""
24
  for page in reader.pages:
25
  text = page.extract_text()
26
  if text:
27
  self.linkedin += text
28
+
29
+ # Load summary text
30
  with open("me/summary.txt", "r", encoding="utf-8") as f:
31
  self.summary = f.read()
32
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  def system_prompt(self):
34
+ return (
35
+ f"You are acting as {self.name}, an experienced Python technical interviewer. "
36
+ f"You are helping users by asking or answering Python-related technical questions. "
37
+ f"Always stay professional, helpful, and concise. Do not generate responses over 100 tokens. "
38
+ f"The user can only ask 3 questions per day—enforce this limit politely. "
39
+ f"\n\n## About {self.name} (your interviewer):\n"
40
+ f"{self.summary}\n\n"
41
+ f"## LinkedIn Profile:\n{self.linkedin}\n\n"
42
+ f"Use this background to answer in character as {self.name}."
43
+ )
44
 
 
 
 
 
45
  def chat(self, message, history):
46
+ user_id = "user" # Replace with session-based ID for real tracking
47
+ today = datetime.date.today()
48
+ record = user_question_counter[user_id]
49
+
50
+ # Reset question count if date changed
51
+ if record["date"] != today:
52
+ record["date"] = today
53
+ record["count"] = 0
54
+
55
+ # Check daily question limit
56
+ if record["count"] >= 3:
57
+ return "🚫 You've reached your daily limit of 3 questions. Please try again tomorrow."
58
+
59
+ # Prepare conversation
60
  messages = [{"role": "system", "content": self.system_prompt()}] + history + [{"role": "user", "content": message}]
61
+
62
+ response = self.openai.chat.completions.create(
63
+ model="gpt-4o-mini",
64
+ messages=messages,
65
+ max_tokens=100
66
+ )
67
+
68
+ record["count"] += 1
69
+ return f"👋 Narendra is your Python interviewer. Let's begin!\n\n{response.choices[0].message.content}"
70
+
 
 
 
71
 
72
  if __name__ == "__main__":
73
  me = Me()
74
  gr.ChatInterface(me.chat, type="messages").launch(share=True)