KonuTech commited on
Commit
e682ae1
·
verified ·
1 Parent(s): df16c03

Delete 4_lab4.ipynb

Browse files
Files changed (1) hide show
  1. 4_lab4.ipynb +0 -559
4_lab4.ipynb DELETED
@@ -1,559 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "metadata": {},
6
- "source": [
7
- "## The first big project - Professionally You!\n",
8
- "\n",
9
- "### And, Tool use.\n",
10
- "\n",
11
- "### But first: introducing Pushover\n",
12
- "\n",
13
- "Pushover is a nifty tool for sending Push Notifications to your phone.\n",
14
- "\n",
15
- "It's super easy to set up and install!\n",
16
- "\n",
17
- "Simply visit https://pushover.net/ and click 'Login or Signup' on the top right to sign up for a free account, and create your API keys.\n",
18
- "\n",
19
- "Once you've signed up, on the home screen, click \"Create an Application/API Token\", and give it any name (like Agents) and click Create Application.\n",
20
- "\n",
21
- "Then add 2 lines to your `.env` file:\n",
22
- "\n",
23
- "PUSHOVER_USER=_put the key that's on the top right of your Pushover home screen and probably starts with a u_ \n",
24
- "PUSHOVER_TOKEN=_put the key when you click into your new application called Agents (or whatever) and probably starts with an a_\n",
25
- "\n",
26
- "Remember to save your `.env` file, and run `load_dotenv(override=True)` after saving, to set your environment variables.\n",
27
- "\n",
28
- "Finally, click \"Add Phone, Tablet or Desktop\" to install on your phone."
29
- ]
30
- },
31
- {
32
- "cell_type": "code",
33
- "execution_count": 4,
34
- "metadata": {},
35
- "outputs": [],
36
- "source": [
37
- "# imports\n",
38
- "\n",
39
- "from dotenv import load_dotenv\n",
40
- "from openai import OpenAI\n",
41
- "import json\n",
42
- "import os\n",
43
- "import requests\n",
44
- "from pypdf import PdfReader\n",
45
- "import gradio as gr"
46
- ]
47
- },
48
- {
49
- "cell_type": "code",
50
- "execution_count": 5,
51
- "metadata": {},
52
- "outputs": [],
53
- "source": [
54
- "# The usual start\n",
55
- "\n",
56
- "load_dotenv(override=True)\n",
57
- "openai = OpenAI()"
58
- ]
59
- },
60
- {
61
- "cell_type": "code",
62
- "execution_count": 6,
63
- "metadata": {},
64
- "outputs": [
65
- {
66
- "name": "stdout",
67
- "output_type": "stream",
68
- "text": [
69
- "Pushover user found and starts with u\n",
70
- "Pushover token found and starts with a\n"
71
- ]
72
- }
73
- ],
74
- "source": [
75
- "# For pushover\n",
76
- "\n",
77
- "pushover_user = os.getenv(\"PUSHOVER_USER\")\n",
78
- "pushover_token = os.getenv(\"PUSHOVER_TOKEN\")\n",
79
- "pushover_url = \"https://api.pushover.net/1/messages.json\"\n",
80
- "\n",
81
- "if pushover_user:\n",
82
- " print(f\"Pushover user found and starts with {pushover_user[0]}\")\n",
83
- "else:\n",
84
- " print(\"Pushover user not found\")\n",
85
- "\n",
86
- "if pushover_token:\n",
87
- " print(f\"Pushover token found and starts with {pushover_token[0]}\")\n",
88
- "else:\n",
89
- " print(\"Pushover token not found\")"
90
- ]
91
- },
92
- {
93
- "cell_type": "code",
94
- "execution_count": 7,
95
- "metadata": {},
96
- "outputs": [],
97
- "source": [
98
- "def push(message):\n",
99
- " print(f\"Push: {message}\")\n",
100
- " payload = {\"user\": pushover_user, \"token\": pushover_token, \"message\": message}\n",
101
- " requests.post(pushover_url, data=payload)"
102
- ]
103
- },
104
- {
105
- "cell_type": "code",
106
- "execution_count": 8,
107
- "metadata": {},
108
- "outputs": [
109
- {
110
- "name": "stdout",
111
- "output_type": "stream",
112
- "text": [
113
- "Push: HEY!!\n"
114
- ]
115
- }
116
- ],
117
- "source": [
118
- "push(\"HEY!!\")"
119
- ]
120
- },
121
- {
122
- "cell_type": "code",
123
- "execution_count": 9,
124
- "metadata": {},
125
- "outputs": [],
126
- "source": [
127
- "def record_user_details(email, name=\"Name not provided\", notes=\"not provided\"):\n",
128
- " push(f\"Recording interest from {name} with email {email} and notes {notes}\")\n",
129
- " return {\"recorded\": \"ok\"}"
130
- ]
131
- },
132
- {
133
- "cell_type": "code",
134
- "execution_count": 10,
135
- "metadata": {},
136
- "outputs": [],
137
- "source": [
138
- "def record_unknown_question(question):\n",
139
- " push(f\"Recording {question} asked that I couldn't answer\")\n",
140
- " return {\"recorded\": \"ok\"}"
141
- ]
142
- },
143
- {
144
- "cell_type": "code",
145
- "execution_count": 11,
146
- "metadata": {},
147
- "outputs": [],
148
- "source": [
149
- "record_user_details_json = {\n",
150
- " \"name\": \"record_user_details\",\n",
151
- " \"description\": \"Use this tool to record that a user is interested in being in touch and provided an email address\",\n",
152
- " \"parameters\": {\n",
153
- " \"type\": \"object\",\n",
154
- " \"properties\": {\n",
155
- " \"email\": {\n",
156
- " \"type\": \"string\",\n",
157
- " \"description\": \"The email address of this user\"\n",
158
- " },\n",
159
- " \"name\": {\n",
160
- " \"type\": \"string\",\n",
161
- " \"description\": \"The user's name, if they provided it\"\n",
162
- " }\n",
163
- " ,\n",
164
- " \"notes\": {\n",
165
- " \"type\": \"string\",\n",
166
- " \"description\": \"Any additional information about the conversation that's worth recording to give context\"\n",
167
- " }\n",
168
- " },\n",
169
- " \"required\": [\"email\"],\n",
170
- " \"additionalProperties\": False\n",
171
- " }\n",
172
- "}"
173
- ]
174
- },
175
- {
176
- "cell_type": "code",
177
- "execution_count": 12,
178
- "metadata": {},
179
- "outputs": [],
180
- "source": [
181
- "record_unknown_question_json = {\n",
182
- " \"name\": \"record_unknown_question\",\n",
183
- " \"description\": \"Always use this tool to record any question that couldn't be answered as you didn't know the answer\",\n",
184
- " \"parameters\": {\n",
185
- " \"type\": \"object\",\n",
186
- " \"properties\": {\n",
187
- " \"question\": {\n",
188
- " \"type\": \"string\",\n",
189
- " \"description\": \"The question that couldn't be answered\"\n",
190
- " },\n",
191
- " },\n",
192
- " \"required\": [\"question\"],\n",
193
- " \"additionalProperties\": False\n",
194
- " }\n",
195
- "}"
196
- ]
197
- },
198
- {
199
- "cell_type": "code",
200
- "execution_count": 13,
201
- "metadata": {},
202
- "outputs": [],
203
- "source": [
204
- "tools = [{\"type\": \"function\", \"function\": record_user_details_json},\n",
205
- " {\"type\": \"function\", \"function\": record_unknown_question_json}]"
206
- ]
207
- },
208
- {
209
- "cell_type": "code",
210
- "execution_count": 14,
211
- "metadata": {},
212
- "outputs": [
213
- {
214
- "data": {
215
- "text/plain": [
216
- "[{'type': 'function',\n",
217
- " 'function': {'name': 'record_user_details',\n",
218
- " 'description': 'Use this tool to record that a user is interested in being in touch and provided an email address',\n",
219
- " 'parameters': {'type': 'object',\n",
220
- " 'properties': {'email': {'type': 'string',\n",
221
- " 'description': 'The email address of this user'},\n",
222
- " 'name': {'type': 'string',\n",
223
- " 'description': \"The user's name, if they provided it\"},\n",
224
- " 'notes': {'type': 'string',\n",
225
- " 'description': \"Any additional information about the conversation that's worth recording to give context\"}},\n",
226
- " 'required': ['email'],\n",
227
- " 'additionalProperties': False}}},\n",
228
- " {'type': 'function',\n",
229
- " 'function': {'name': 'record_unknown_question',\n",
230
- " 'description': \"Always use this tool to record any question that couldn't be answered as you didn't know the answer\",\n",
231
- " 'parameters': {'type': 'object',\n",
232
- " 'properties': {'question': {'type': 'string',\n",
233
- " 'description': \"The question that couldn't be answered\"}},\n",
234
- " 'required': ['question'],\n",
235
- " 'additionalProperties': False}}}]"
236
- ]
237
- },
238
- "execution_count": 14,
239
- "metadata": {},
240
- "output_type": "execute_result"
241
- }
242
- ],
243
- "source": [
244
- "tools"
245
- ]
246
- },
247
- {
248
- "cell_type": "code",
249
- "execution_count": 16,
250
- "metadata": {},
251
- "outputs": [],
252
- "source": [
253
- "# This function can take a list of tool calls, and run them. This is the IF statement!!\n",
254
- "\n",
255
- "def handle_tool_calls(tool_calls):\n",
256
- " results = []\n",
257
- " for tool_call in tool_calls:\n",
258
- " tool_name = tool_call.function.name\n",
259
- " arguments = json.loads(tool_call.function.arguments)\n",
260
- " print(f\"Tool called: {tool_name}\", flush=True)\n",
261
- "\n",
262
- " # THE BIG IF STATEMENT!!!\n",
263
- "\n",
264
- " if tool_name == \"record_user_details\":\n",
265
- " result = record_user_details(**arguments)\n",
266
- " elif tool_name == \"record_unknown_question\":\n",
267
- " result = record_unknown_question(**arguments)\n",
268
- "\n",
269
- " results.append({\"role\": \"tool\",\"content\": json.dumps(result),\"tool_call_id\": tool_call.id})\n",
270
- " return results"
271
- ]
272
- },
273
- {
274
- "cell_type": "code",
275
- "execution_count": 17,
276
- "metadata": {},
277
- "outputs": [
278
- {
279
- "name": "stdout",
280
- "output_type": "stream",
281
- "text": [
282
- "Push: Recording this is a really hard question asked that I couldn't answer\n"
283
- ]
284
- },
285
- {
286
- "data": {
287
- "text/plain": [
288
- "{'recorded': 'ok'}"
289
- ]
290
- },
291
- "execution_count": 17,
292
- "metadata": {},
293
- "output_type": "execute_result"
294
- }
295
- ],
296
- "source": [
297
- "globals()[\"record_unknown_question\"](\"this is a really hard question\")"
298
- ]
299
- },
300
- {
301
- "cell_type": "code",
302
- "execution_count": 18,
303
- "metadata": {},
304
- "outputs": [],
305
- "source": [
306
- "# This is a more elegant way that avoids the IF statement.\n",
307
- "\n",
308
- "def handle_tool_calls(tool_calls):\n",
309
- " results = []\n",
310
- " for tool_call in tool_calls:\n",
311
- " tool_name = tool_call.function.name\n",
312
- " arguments = json.loads(tool_call.function.arguments)\n",
313
- " print(f\"Tool called: {tool_name}\", flush=True)\n",
314
- " tool = globals().get(tool_name)\n",
315
- " result = tool(**arguments) if tool else {}\n",
316
- " results.append({\"role\": \"tool\",\"content\": json.dumps(result),\"tool_call_id\": tool_call.id})\n",
317
- " return results"
318
- ]
319
- },
320
- {
321
- "cell_type": "code",
322
- "execution_count": 21,
323
- "metadata": {},
324
- "outputs": [],
325
- "source": [
326
- "reader = PdfReader(\"me/linkedin.pdf\")\n",
327
- "linkedin = \"\"\n",
328
- "for page in reader.pages:\n",
329
- " text = page.extract_text()\n",
330
- " if text:\n",
331
- " linkedin += text\n",
332
- "\n",
333
- "with open(\"me/summary.txt\", \"r\", encoding=\"utf-8\") as f:\n",
334
- " summary = f.read()"
335
- ]
336
- },
337
- {
338
- "cell_type": "code",
339
- "execution_count": 22,
340
- "metadata": {},
341
- "outputs": [],
342
- "source": [
343
- "name = \"Konrad Borowiec\""
344
- ]
345
- },
346
- {
347
- "cell_type": "code",
348
- "execution_count": 23,
349
- "metadata": {},
350
- "outputs": [],
351
- "source": [
352
- "system_prompt = f\"You are acting as {name}. You are answering questions on {name}'s website, \\\n",
353
- "particularly questions related to {name}'s career, background, skills and experience. \\\n",
354
- "Your responsibility is to represent {name} for interactions on the website as faithfully as possible. \\\n",
355
- "You are given a summary of {name}'s background and LinkedIn profile which you can use to answer questions. \\\n",
356
- "Be professional and engaging, as if talking to a potential client or future employer who came across the website. \\\n",
357
- "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. \\\n",
358
- "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. \"\n",
359
- "\n",
360
- "system_prompt += f\"\\n\\n## Summary:\\n{summary}\\n\\n## LinkedIn Profile:\\n{linkedin}\\n\\n\"\n",
361
- "system_prompt += f\"With this context, please chat with the user, always staying in character as {name}.\"\n"
362
- ]
363
- },
364
- {
365
- "cell_type": "code",
366
- "execution_count": 24,
367
- "metadata": {},
368
- "outputs": [],
369
- "source": [
370
- "def chat(message, history):\n",
371
- " messages = [{\"role\": \"system\", \"content\": system_prompt}] + history + [{\"role\": \"user\", \"content\": message}]\n",
372
- " done = False\n",
373
- " while not done:\n",
374
- "\n",
375
- " # This is the call to the LLM - see that we pass in the tools json\n",
376
- "\n",
377
- " response = openai.chat.completions.create(model=\"gpt-4o-mini\", messages=messages, tools=tools)\n",
378
- "\n",
379
- " finish_reason = response.choices[0].finish_reason\n",
380
- " \n",
381
- " # If the LLM wants to call a tool, we do that!\n",
382
- " \n",
383
- " if finish_reason==\"tool_calls\":\n",
384
- " message = response.choices[0].message\n",
385
- " tool_calls = message.tool_calls\n",
386
- " results = handle_tool_calls(tool_calls)\n",
387
- " messages.append(message)\n",
388
- " messages.extend(results)\n",
389
- " else:\n",
390
- " done = True\n",
391
- " return response.choices[0].message.content"
392
- ]
393
- },
394
- {
395
- "cell_type": "code",
396
- "execution_count": 25,
397
- "metadata": {},
398
- "outputs": [
399
- {
400
- "name": "stdout",
401
- "output_type": "stream",
402
- "text": [
403
- "* Running on local URL: http://127.0.0.1:7862\n",
404
- "* To create a public link, set `share=True` in `launch()`.\n"
405
- ]
406
- },
407
- {
408
- "data": {
409
- "text/html": [
410
- "<div><iframe src=\"http://127.0.0.1:7862/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
411
- ],
412
- "text/plain": [
413
- "<IPython.core.display.HTML object>"
414
- ]
415
- },
416
- "metadata": {},
417
- "output_type": "display_data"
418
- },
419
- {
420
- "data": {
421
- "text/plain": []
422
- },
423
- "execution_count": 25,
424
- "metadata": {},
425
- "output_type": "execute_result"
426
- },
427
- {
428
- "name": "stdout",
429
- "output_type": "stream",
430
- "text": [
431
- "Tool called: record_user_details\n",
432
- "Push: Recording interest from Konrad Borowiec with email borowiec.k@gmail.com and notes User is a data analyst creating a new team of data analysts.\n"
433
- ]
434
- }
435
- ],
436
- "source": [
437
- "gr.ChatInterface(chat, type=\"messages\").launch()"
438
- ]
439
- },
440
- {
441
- "cell_type": "markdown",
442
- "metadata": {},
443
- "source": [
444
- "## And now for deployment\n",
445
- "\n",
446
- "This code is in `app.py`\n",
447
- "\n",
448
- "We will deploy to HuggingFace Spaces.\n",
449
- "\n",
450
- "Before you start: remember to update the files in the \"me\" directory - your LinkedIn profile and summary.txt - so that it talks about you! Also change `self.name = \"Ed Donner\"` in `app.py`.. \n",
451
- "\n",
452
- "Also check that there's no README file within the 1_foundations directory. If there is one, please delete it. The deploy process creates a new README file in this directory for you.\n",
453
- "\n",
454
- "1. Visit https://huggingface.co and set up an account \n",
455
- "2. From the Avatar menu on the top right, choose Access Tokens. Choose \"Create New Token\". Give it WRITE permissions - it needs to have WRITE permissions! Keep a record of your new key. \n",
456
- "3. In the Terminal, run: `uv tool install 'huggingface_hub[cli]'` to install the HuggingFace tool, then `hf auth login` to login at the command line with your key. Afterwards, run `hf auth whoami` to check you're logged in \n",
457
- "4. Take your new token and add it to your .env file: `HF_TOKEN=hf_xxx` for the future\n",
458
- "5. From the 1_foundations folder, enter: `uv run gradio deploy` \n",
459
- "6. Follow its instructions: name it \"career_conversation\", specify app.py, choose cpu-basic as the hardware, say Yes to needing to supply secrets, provide your openai api key, your pushover user and token, and say \"no\" to github actions. \n",
460
- "\n",
461
- "Thank you Robert, James, Martins, Andras and Priya for these tips. \n",
462
- "Please read the next 2 sections - how to change your Secrets, and how to redeploy your Space (you may need to delete the README.md that gets created in this 1_foundations directory).\n",
463
- "\n",
464
- "#### More about these secrets:\n",
465
- "\n",
466
- "If you're confused by what's going on with these secrets: it just wants you to enter the key name and value for each of your secrets -- so you would enter: \n",
467
- "`OPENAI_API_KEY` \n",
468
- "Followed by: \n",
469
- "`sk-proj-...` \n",
470
- "\n",
471
- "And if you don't want to set secrets this way, or something goes wrong with it, it's no problem - you can change your secrets later: \n",
472
- "1. Log in to HuggingFace website \n",
473
- "2. Go to your profile screen via the Avatar menu on the top right \n",
474
- "3. Select the Space you deployed \n",
475
- "4. Click on the Settings wheel on the top right \n",
476
- "5. You can scroll down to change your secrets (Variables and Secrets section), delete the space, etc.\n",
477
- "\n",
478
- "#### And now you should be deployed!\n",
479
- "\n",
480
- "If you want to completely replace everything and start again with your keys, you may need to delete the README.md that got created in this 1_foundations folder.\n",
481
- "\n",
482
- "Here is mine: https://huggingface.co/spaces/ed-donner/Career_Conversation\n",
483
- "\n",
484
- "I just got a push notification that a student asked me how they can become President of their country 😂😂\n",
485
- "\n",
486
- "For more information on deployment:\n",
487
- "\n",
488
- "https://www.gradio.app/guides/sharing-your-app#hosting-on-hf-spaces\n",
489
- "\n",
490
- "To delete your Space in the future: \n",
491
- "1. Log in to HuggingFace\n",
492
- "2. From the Avatar menu, select your profile\n",
493
- "3. Click on the Space itself and select the settings wheel on the top right\n",
494
- "4. Scroll to the Delete section at the bottom\n",
495
- "5. ALSO: delete the README file that Gradio may have created inside this 1_foundations folder (otherwise it won't ask you the questions the next time you do a gradio deploy)\n"
496
- ]
497
- },
498
- {
499
- "cell_type": "markdown",
500
- "metadata": {},
501
- "source": [
502
- "<table style=\"margin: 0; text-align: left; width:100%\">\n",
503
- " <tr>\n",
504
- " <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
505
- " <img src=\"../assets/exercise.png\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
506
- " </td>\n",
507
- " <td>\n",
508
- " <h2 style=\"color:#ff7800;\">Exercise</h2>\n",
509
- " <span style=\"color:#ff7800;\">• First and foremost, deploy this for yourself! It's a real, valuable tool - the future resume..<br/>\n",
510
- " • Next, improve the resources - add better context about yourself. If you know RAG, then add a knowledge base about you.<br/>\n",
511
- " • Add in more tools! You could have a SQL database with common Q&A that the LLM could read and write from?<br/>\n",
512
- " • Bring in the Evaluator from the last lab, and add other Agentic patterns.\n",
513
- " </span>\n",
514
- " </td>\n",
515
- " </tr>\n",
516
- "</table>"
517
- ]
518
- },
519
- {
520
- "cell_type": "markdown",
521
- "metadata": {},
522
- "source": [
523
- "<table style=\"margin: 0; text-align: left; width:100%\">\n",
524
- " <tr>\n",
525
- " <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n",
526
- " <img src=\"../assets/business.png\" width=\"150\" height=\"150\" style=\"display: block;\" />\n",
527
- " </td>\n",
528
- " <td>\n",
529
- " <h2 style=\"color:#00bfff;\">Commercial implications</h2>\n",
530
- " <span style=\"color:#00bfff;\">Aside from the obvious (your career alter-ego) this has business applications in any situation where you need an AI assistant with domain expertise and an ability to interact with the real world.\n",
531
- " </span>\n",
532
- " </td>\n",
533
- " </tr>\n",
534
- "</table>"
535
- ]
536
- }
537
- ],
538
- "metadata": {
539
- "kernelspec": {
540
- "display_name": "Python 3 (ipykernel)",
541
- "language": "python",
542
- "name": "python3"
543
- },
544
- "language_info": {
545
- "codemirror_mode": {
546
- "name": "ipython",
547
- "version": 3
548
- },
549
- "file_extension": ".py",
550
- "mimetype": "text/x-python",
551
- "name": "python",
552
- "nbconvert_exporter": "python",
553
- "pygments_lexer": "ipython3",
554
- "version": "3.12.3"
555
- }
556
- },
557
- "nbformat": 4,
558
- "nbformat_minor": 4
559
- }