jisaacso219 commited on
Commit
2e03377
Β·
verified Β·
1 Parent(s): 84cbbed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -121
app.py CHANGED
@@ -12,14 +12,15 @@ import zipfile
12
 
13
  load_dotenv(override=True)
14
 
15
- # ─── Pushover Notifications ───────────────────────────────────────────────
 
 
16
 
 
17
  def push(text):
18
  try:
19
- Path("chat_logs").mkdir(exist_ok=True)
20
- keep_path = Path("chat_logs/.keep")
21
- if not keep_path.exists():
22
- keep_path.touch()
23
  requests.post(
24
  "https://api.pushover.net/1/messages.json",
25
  data={
@@ -31,15 +32,10 @@ def push(text):
31
  except Exception as e:
32
  print(f"Pushover error: {e}")
33
 
34
- # ─── Tool Functions ────────────────────────────────────────────────────────
35
-
36
  def record_user_details(email, name="Name not provided", notes="not provided"):
37
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
38
- filename = f"chat_logs/session_{timestamp}.json"
39
- latest_log = "\n".join([
40
- f"{entry['role'].capitalize()}: {entry['content'][:200]}"
41
- for entry in me.session_log[-6:]
42
- ])
43
  with open(filename, "w", encoding="utf-8") as f:
44
  json.dump(me.session_log, f, indent=2)
45
  msg = f"[New Contact]\nName: {name}\nEmail: {email}\nNotes: {notes}\n\nπŸ”— View log: {filename}"
@@ -48,58 +44,48 @@ def record_user_details(email, name="Name not provided", notes="not provided"):
48
 
49
  def record_unknown_question(question):
50
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
51
- filename = f"chat_logs/session_{timestamp}.json"
52
- latest_log = "\n".join([
53
- f"{entry['role'].capitalize()}: {entry['content'][:200]}"
54
- for entry in me.session_log[-6:]
55
- ])
56
  with open(filename, "w", encoding="utf-8") as f:
57
  json.dump(me.session_log, f, indent=2)
58
  msg = f"[Unknown Question]\nQ: {question}\n\nπŸ”— View log: {filename}"
59
  push(msg)
60
  return {"recorded": "ok"}
61
 
62
- record_user_details_json = {
63
- "name": "record_user_details",
64
- "description": "Use this tool to record that a user is interested in being in touch and provided an email address",
65
- "parameters": {
66
- "type": "object",
67
- "properties": {
68
- "email": {"type": "string"},
69
- "name": {"type": "string"},
70
- "notes": {"type": "string"}
71
- },
72
- "required": ["email"],
73
- "additionalProperties": False
74
- }
75
- }
76
-
77
- record_unknown_question_json = {
78
- "name": "record_unknown_question",
79
- "description": "Record a question that couldn't be answered",
80
- "parameters": {
81
- "type": "object",
82
- "properties": {
83
- "question": {"type": "string"}
84
- },
85
- "required": ["question"],
86
- "additionalProperties": False
87
- }
88
- }
89
-
90
  tools = [
91
- {"type": "function", "function": record_user_details_json},
92
- {"type": "function", "function": record_unknown_question_json}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  ]
94
 
95
- # ─── Core Chatbot Class ────────────────────────────────────────────────────
96
-
97
  class Me:
98
  def __init__(self):
99
  self.openai = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
100
  self.name = "Jacob Isaacson"
101
  self.session_log = []
102
- Path("chat_logs").mkdir(exist_ok=True)
 
103
 
104
  gdown.download("https://drive.google.com/uc?id=1xz2RowkImpI8odYv8zvKdlRHaKfILn40", "linkedin.pdf", quiet=False)
105
  reader = PdfReader("linkedin.pdf")
@@ -112,14 +98,11 @@ class Me:
112
  self.archive_logs()
113
 
114
  def system_prompt(self):
115
- return f"""You are acting as {self.name}. You're answering questions on {self.name}'s website about his career, experience, and skills.
116
- Be professional and conversational, as if talking to a potential employer or client.
117
-
118
  If you can't answer something, call `record_unknown_question`. If a user seems interested, ask for their email and use `record_user_details`.
119
-
120
  ## Summary:
121
  {self.summary}
122
-
123
  ## LinkedIn Profile:
124
  {self.linkedin}
125
  """
@@ -127,105 +110,64 @@ If you can't answer something, call `record_unknown_question`. If a user seems i
127
  def handle_tool_call(self, tool_calls):
128
  results = []
129
  for tool_call in tool_calls:
130
- tool_name = tool_call.function.name
131
  arguments = json.loads(tool_call.function.arguments)
132
- tool = globals().get(tool_name)
133
- result = tool(**arguments) if tool else {}
134
- results.append({"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)})
 
 
 
135
  return results
136
 
137
  def chat_stream(self, message, history):
138
  messages = [{"role": "system", "content": self.system_prompt()}]
139
 
140
  for msg in history:
141
- if isinstance(msg, dict) and msg.get("role") in ["user", "assistant"]:
142
- messages.append(msg)
143
 
144
  messages.append({"role": "user", "content": message})
145
  self.session_log.append({"role": "user", "content": message})
146
 
147
  response = self.openai.chat.completions.create(
148
- model="gpt-4o",
149
- messages=messages,
150
- tools=tools,
151
- stream=False
152
  )
153
 
154
  reply = response.choices[0].message
 
 
 
 
155
 
156
- if reply.tool_calls:
157
- tool_results = self.handle_tool_call(reply.tool_calls)
158
- messages.append(reply)
159
- messages.extend(tool_results)
160
-
161
- final_response = self.openai.chat.completions.create(
162
- model="gpt-4o",
163
- messages=messages,
164
- tools=tools,
165
- stream=True
166
- )
167
-
168
- full_response = ""
169
- for chunk in final_response:
170
- delta = chunk.choices[0].delta
171
- if hasattr(delta, "content") and delta.content:
172
- full_response += delta.content
173
- yield full_response
174
-
175
- full_response += "\n\nπŸ’¬ Let me know if you’d like to follow up or need help connecting with Jacob."
176
- self.session_log.append({"role": "assistant", "content": full_response})
177
- self.save_session_log()
178
- else:
179
- stream = self.openai.chat.completions.create(
180
- model="gpt-4o",
181
- messages=messages,
182
- tools=tools,
183
- stream=True
184
- )
185
-
186
- full_response = ""
187
- for chunk in stream:
188
- delta = chunk.choices[0].delta
189
- if hasattr(delta, "content") and delta.content:
190
- full_response += delta.content
191
- yield full_response
192
-
193
- full_response += "\n\nπŸ’¬ Let me know if you’d like to follow up or need help connecting with Jacob."
194
- self.session_log.append({"role": "assistant", "content": full_response})
195
- self.save_session_log()
196
 
197
  def save_session_log(self):
198
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
199
- filename = f"chat_logs/session_{timestamp}.json"
200
  with open(filename, "w", encoding="utf-8") as f:
201
  json.dump(self.session_log, f, indent=2)
202
 
203
  def archive_logs(self):
204
- zip_path = "chat_logs/weekly_archive.zip"
205
- with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as archive:
206
- for log_file in Path("chat_logs").glob("session_*.json"):
207
  archive.write(log_file, arcname=log_file.name)
208
 
209
- # ─── UI Interface ───────────────────────────────────────────────────────────
210
-
211
  me = Me()
212
 
213
  with gr.Blocks(title="Jacob Isaacson Chatbot") as iface:
214
  with gr.Row():
215
- gr.Image("jacob.png", width=100, show_label=False)
216
- gr.Markdown("### Chat with Jacob Isaacson\nAsk about Jacob's background, skills, or career. \nπŸ›‘οΈ *All chats are logged for improvement purposes.*")
217
-
218
  gr.ChatInterface(
219
  fn=me.chat_stream,
220
  chatbot=gr.Chatbot(show_copy_button=True),
221
  type="messages",
222
- additional_inputs=[],
223
- retry_btn=None,
224
- undo_btn=None,
225
- clear_btn=None,
226
- chatbot_initial_message={"role": "assistant", "content": "Hello, my name is Jacob Isaacson. Please ask me any questions about my professional career and I will do my best to respond."}
227
  )
228
 
229
- if __name__ == "__main__":
230
- iface.launch()
231
 
 
12
 
13
  load_dotenv(override=True)
14
 
15
+ # ─── Ensure chat_logs Folder Exists ───
16
+ logs_path = Path("chat_logs")
17
+ logs_path.mkdir(exist_ok=True)
18
 
19
+ # ─── Pushover Notifications ───────────
20
  def push(text):
21
  try:
22
+ keep_path = logs_path / ".keep"
23
+ keep_path.touch(exist_ok=True)
 
 
24
  requests.post(
25
  "https://api.pushover.net/1/messages.json",
26
  data={
 
32
  except Exception as e:
33
  print(f"Pushover error: {e}")
34
 
35
+ # ─── Tool Functions ───────────────────
 
36
  def record_user_details(email, name="Name not provided", notes="not provided"):
37
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
38
+ filename = logs_path / f"session_{timestamp}.json"
 
 
 
 
39
  with open(filename, "w", encoding="utf-8") as f:
40
  json.dump(me.session_log, f, indent=2)
41
  msg = f"[New Contact]\nName: {name}\nEmail: {email}\nNotes: {notes}\n\nπŸ”— View log: {filename}"
 
44
 
45
  def record_unknown_question(question):
46
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
47
+ filename = logs_path / f"session_{timestamp}.json"
 
 
 
 
48
  with open(filename, "w", encoding="utf-8") as f:
49
  json.dump(me.session_log, f, indent=2)
50
  msg = f"[Unknown Question]\nQ: {question}\n\nπŸ”— View log: {filename}"
51
  push(msg)
52
  return {"recorded": "ok"}
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  tools = [
55
+ {"type": "function", "function": {
56
+ "name": "record_user_details",
57
+ "description": "Record user contact information.",
58
+ "parameters": {
59
+ "type": "object",
60
+ "properties": {
61
+ "email": {"type": "string"},
62
+ "name": {"type": "string"},
63
+ "notes": {"type": "string"}
64
+ },
65
+ "required": ["email"]
66
+ }
67
+ }},
68
+ {"type": "function", "function": {
69
+ "name": "record_unknown_question",
70
+ "description": "Record questions unable to be answered.",
71
+ "parameters": {
72
+ "type": "object",
73
+ "properties": {
74
+ "question": {"type": "string"}
75
+ },
76
+ "required": ["question"]
77
+ }
78
+ }}
79
  ]
80
 
81
+ # ─── Core Chatbot Class ───────────────
 
82
  class Me:
83
  def __init__(self):
84
  self.openai = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
85
  self.name = "Jacob Isaacson"
86
  self.session_log = []
87
+
88
+ logs_path.mkdir(exist_ok=True)
89
 
90
  gdown.download("https://drive.google.com/uc?id=1xz2RowkImpI8odYv8zvKdlRHaKfILn40", "linkedin.pdf", quiet=False)
91
  reader = PdfReader("linkedin.pdf")
 
98
  self.archive_logs()
99
 
100
  def system_prompt(self):
101
+ return f"""You are acting as {self.name}. You're answering questions about {self.name}'s career, experience, and skills.
102
+ Be professional and conversational.
 
103
  If you can't answer something, call `record_unknown_question`. If a user seems interested, ask for their email and use `record_user_details`.
 
104
  ## Summary:
105
  {self.summary}
 
106
  ## LinkedIn Profile:
107
  {self.linkedin}
108
  """
 
110
  def handle_tool_call(self, tool_calls):
111
  results = []
112
  for tool_call in tool_calls:
113
+ func = globals()[tool_call.function.name]
114
  arguments = json.loads(tool_call.function.arguments)
115
+ result = func(**arguments)
116
+ results.append({
117
+ "role": "tool",
118
+ "tool_call_id": tool_call.id,
119
+ "content": json.dumps(result)
120
+ })
121
  return results
122
 
123
  def chat_stream(self, message, history):
124
  messages = [{"role": "system", "content": self.system_prompt()}]
125
 
126
  for msg in history:
127
+ messages.append(msg)
 
128
 
129
  messages.append({"role": "user", "content": message})
130
  self.session_log.append({"role": "user", "content": message})
131
 
132
  response = self.openai.chat.completions.create(
133
+ model="gpt-4o", messages=messages, tools=tools, stream=False
 
 
 
134
  )
135
 
136
  reply = response.choices[0].message
137
+ full_response = reply.content or ""
138
+
139
+ self.session_log.append({"role": "assistant", "content": full_response})
140
+ self.save_session_log()
141
 
142
+ yield full_response + "\n\nπŸ’¬ Let me know if you’d like to follow up or need help connecting with Jacob."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
  def save_session_log(self):
145
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
146
+ filename = logs_path / f"session_{timestamp}.json"
147
  with open(filename, "w", encoding="utf-8") as f:
148
  json.dump(self.session_log, f, indent=2)
149
 
150
  def archive_logs(self):
151
+ zip_path = logs_path / "weekly_archive.zip"
152
+ with zipfile.ZipFile(zip_path, "w") as archive:
153
+ for log_file in logs_path.glob("session_*.json"):
154
  archive.write(log_file, arcname=log_file.name)
155
 
 
 
156
  me = Me()
157
 
158
  with gr.Blocks(title="Jacob Isaacson Chatbot") as iface:
159
  with gr.Row():
160
+ gr.Markdown("# Chat with Jacob Isaacson")
 
 
161
  gr.ChatInterface(
162
  fn=me.chat_stream,
163
  chatbot=gr.Chatbot(show_copy_button=True),
164
  type="messages",
165
+ chatbot_initial_message={
166
+ "role": "assistant",
167
+ "content": "Hello, my name is Jacob Isaacson. Ask any questions about my professional career!"
168
+ }
 
169
  )
170
 
171
+ iface.launch()
172
+
173