jisaacso219 commited on
Commit
917fa89
Β·
verified Β·
1 Parent(s): 5b130e9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -62
app.py CHANGED
@@ -12,15 +12,12 @@ import zipfile
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,10 +29,13 @@ def push(text):
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,49 +44,58 @@ def record_user_details(email, name="Name not provided", notes="not provided"):
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")
92
  self.linkedin = "".join(page.extract_text() or "" for page in reader.pages)
@@ -98,11 +107,14 @@ class Me:
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,63 +122,71 @@ If you can't answer something, call `record_unknown_question`. If a user seems i
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
 
162
  gr.ChatInterface(
163
  fn=me.chat_stream,
164
  chatbot=gr.Chatbot(show_copy_button=True),
165
- textbox=gr.Textbox(placeholder="Ask Jacob about his career...", container=False),
166
- title="Chat with Jacob Isaacson",
167
- description="Hello, my name is Jacob Isaacson. Ask any questions about my professional career!",
168
- type="messages"
169
  )
170
 
171
- iface.launch()
 
172
 
 
12
 
13
  load_dotenv(override=True)
14
 
 
 
 
 
 
15
  def push(text):
16
  try:
17
+ Path("chat_logs").mkdir(exist_ok=True)
18
+ keep_path = Path("chat_logs/.keep")
19
+ if not keep_path.exists():
20
+ keep_path.touch()
21
  requests.post(
22
  "https://api.pushover.net/1/messages.json",
23
  data={
 
29
  except Exception as e:
30
  print(f"Pushover error: {e}")
31
 
 
32
  def record_user_details(email, name="Name not provided", notes="not provided"):
33
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
34
+ filename = f"chat_logs/session_{timestamp}.json"
35
+ latest_log = "\n".join([
36
+ f"{entry['role'].capitalize()}: {entry['content'][:200]}"
37
+ for entry in me.session_log[-6:]
38
+ ])
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 = f"chat_logs/session_{timestamp}.json"
48
+ latest_log = "\n".join([
49
+ f"{entry['role'].capitalize()}: {entry['content'][:200]}"
50
+ for entry in me.session_log[-6:]
51
+ ])
52
  with open(filename, "w", encoding="utf-8") as f:
53
  json.dump(me.session_log, f, indent=2)
54
  msg = f"[Unknown Question]\nQ: {question}\n\nπŸ”— View log: {filename}"
55
  push(msg)
56
  return {"recorded": "ok"}
57
 
58
+ record_user_details_json = {
59
+ "name": "record_user_details",
60
+ "description": "Use this tool to record that a user is interested in being in touch and provided an email address",
61
+ "parameters": {
62
+ "type": "object",
63
+ "properties": {
64
+ "email": {"type": "string"},
65
+ "name": {"type": "string"},
66
+ "notes": {"type": "string"}
67
+ },
68
+ "required": ["email"],
69
+ "additionalProperties": False
70
+ }
71
+ }
72
+
73
+ record_unknown_question_json = {
74
+ "name": "record_unknown_question",
75
+ "description": "Record a question that couldn't be answered",
76
+ "parameters": {
77
+ "type": "object",
78
+ "properties": {
79
+ "question": {"type": "string"}
80
+ },
81
+ "required": ["question"],
82
+ "additionalProperties": False
83
+ }
84
+ }
85
+
86
  tools = [
87
+ {"type": "function", "function": record_user_details_json},
88
+ {"type": "function", "function": record_unknown_question_json}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  ]
90
 
 
91
  class Me:
92
  def __init__(self):
93
  self.openai = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
94
  self.name = "Jacob Isaacson"
95
  self.session_log = []
96
+ Path("chat_logs").mkdir(exist_ok=True)
97
 
98
+ # Download resume and summary
 
99
  gdown.download("https://drive.google.com/uc?id=1xz2RowkImpI8odYv8zvKdlRHaKfILn40", "linkedin.pdf", quiet=False)
100
  reader = PdfReader("linkedin.pdf")
101
  self.linkedin = "".join(page.extract_text() or "" for page in reader.pages)
 
107
  self.archive_logs()
108
 
109
  def system_prompt(self):
110
+ return f"""You are acting as {self.name}. You're answering questions on {self.name}'s website about his career, experience, and skills.
111
+ Be professional and conversational, as if talking to a potential employer or client.
112
+
113
  If you can't answer something, call `record_unknown_question`. If a user seems interested, ask for their email and use `record_user_details`.
114
+
115
  ## Summary:
116
  {self.summary}
117
+
118
  ## LinkedIn Profile:
119
  {self.linkedin}
120
  """
 
122
  def handle_tool_call(self, tool_calls):
123
  results = []
124
  for tool_call in tool_calls:
125
+ tool_name = tool_call.function.name
126
  arguments = json.loads(tool_call.function.arguments)
127
+ tool = globals().get(tool_name)
128
+ result = tool(**arguments) if tool else {}
129
+ results.append({"role": "tool", "tool_call_id": tool_call.id, "content": json.dumps(result)})
 
 
 
130
  return results
131
 
132
  def chat_stream(self, message, history):
133
  messages = [{"role": "system", "content": self.system_prompt()}]
134
 
135
+ if not history:
136
+ greeting = "Hello, my name is Jacob Isaacson. Please ask me any questions about my professional career and I will do my best to respond."
137
+ self.session_log.append({"role": "assistant", "content": greeting})
138
+ yield greeting
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=True
152
  )
153
 
154
+ full_response = ""
155
+ for chunk in response:
156
+ delta = chunk.choices[0].delta
157
+ if hasattr(delta, "content") and delta.content:
158
+ full_response += delta.content
159
+ yield full_response
160
 
161
  self.session_log.append({"role": "assistant", "content": full_response})
162
  self.save_session_log()
163
 
 
 
164
  def save_session_log(self):
165
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
166
+ filename = f"chat_logs/session_{timestamp}.json"
167
  with open(filename, "w", encoding="utf-8") as f:
168
  json.dump(self.session_log, f, indent=2)
169
 
170
  def archive_logs(self):
171
+ zip_path = "chat_logs/weekly_archive.zip"
172
+ with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as archive:
173
+ for log_file in Path("chat_logs").glob("session_*.json"):
174
  archive.write(log_file, arcname=log_file.name)
175
 
176
  me = Me()
177
 
178
  with gr.Blocks(title="Jacob Isaacson Chatbot") as iface:
179
  with gr.Row():
180
+ gr.Image("jacob.png", width=100, show_label=False)
181
+ gr.Markdown("### Chat with Jacob Isaacson\nAsk about Jacob's background, skills, or career. \nπŸ›‘οΈ *All chats are logged for improvement purposes.*")
182
 
183
  gr.ChatInterface(
184
  fn=me.chat_stream,
185
  chatbot=gr.Chatbot(show_copy_button=True),
186
+ type="messages",
187
+ additional_inputs=[],
 
 
188
  )
189
 
190
+ if __name__ == "__main__":
191
+ iface.launch()
192