From the uDemy course on LLM engineering.
https://www.udemy.com/course/llm-engineering-master-ai-and-large-language-models
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1184 lines
57 KiB
1184 lines
57 KiB
{ |
|
"cells": [ |
|
{ |
|
"cell_type": "markdown", |
|
"id": "e426cd04-c053-43e8-b505-63cee7956a53", |
|
"metadata": {}, |
|
"source": [ |
|
"# Welcome to a very busy Week 8 folder\n", |
|
"\n", |
|
"## We have lots to do this week!\n", |
|
"\n", |
|
"We'll move at a faster pace than usual, particularly as you're becoming proficient LLM engineers.\n" |
|
] |
|
}, |
|
{ |
|
"cell_type": "markdown", |
|
"id": "b3cf5389-93c5-4523-bc48-78fabb91d8f6", |
|
"metadata": {}, |
|
"source": [ |
|
"<table style=\"margin: 0; text-align: left;\">\n", |
|
" <tr>\n", |
|
" <td style=\"width: 150px; height: 150px; vertical-align: middle;\">\n", |
|
" <img src=\"../important.jpg\" width=\"150\" height=\"150\" style=\"display: block;\" />\n", |
|
" </td>\n", |
|
" <td>\n", |
|
" <h2 style=\"color:#900;\">Especially important this week: pull the latest</h2>\n", |
|
" <span style=\"color:#900;\">I'm continually improving these labs, adding more examples and exercises.\n", |
|
" At the start of each week, it's worth checking you have the latest code.<br/>\n", |
|
" First do a <a href=\"https://chatgpt.com/share/6734e705-3270-8012-a074-421661af6ba9\">git pull and merge your changes as needed</a>. Any problems? Try asking ChatGPT to clarify how to merge - or contact me!<br/><br/>\n", |
|
" After you've pulled the code, from the llm_engineering directory, in an Anaconda prompt (PC) or Terminal (Mac), run:<br/>\n", |
|
" <code>conda env update --f environment.yml --prune</code><br/>\n", |
|
" Or if you used virtualenv rather than Anaconda, then run this from your activated environment in a Powershell (PC) or Terminal (Mac):<br/>\n", |
|
" <code>pip install -r requirements.txt</code>\n", |
|
" <br/>Then restart the kernel (Kernel menu >> Restart Kernel and Clear Outputs Of All Cells) to pick up the changes.\n", |
|
" </span>\n", |
|
" </td>\n", |
|
" </tr>\n", |
|
"</table>" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 46, |
|
"id": "bc0e1c1c-be6a-4395-bbbd-eeafc9330d7e", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [ |
|
"# Just one import to start with!!\n", |
|
"\n", |
|
"import modal" |
|
] |
|
}, |
|
{ |
|
"cell_type": "markdown", |
|
"id": "ab5c8533-9f66-448f-b9b2-133d1ff50639", |
|
"metadata": {}, |
|
"source": [ |
|
"# Setting up the modal tokens\n", |
|
"\n", |
|
"The first time you run this, please uncomment the next line and execute it. \n", |
|
"This is the same as running `modal setup` from the command line. It connects with Modal and installs your tokens. \n", |
|
"\n", |
|
"## Debugging some common problems on Windows\n", |
|
"\n", |
|
"If this command fails in the next cell, or if any of the modal commands with the `!` fail, please try running them directly on the command line in an activated environment (without the `!`)\n", |
|
"\n", |
|
"A student on Windows mentioned that on Windows, you might also need to run this command from a command prompt in an activated environment afterwards: \n", |
|
"`modal token new` \n", |
|
"(Thank you Ed B. for that!)\n", |
|
"\n", |
|
"Another Windows student Minh N. mentioned you may need to use this approach, from an activated environment in the command line: \n", |
|
"`modal token set --token-id <your_token_id> --token-secret <your_token_secret>`\n", |
|
"\n", |
|
"Also, a student David S. mentioned the following: \n", |
|
"> In case anyone else using Windows hits this problem: Along with having to run `modal token new` from a command prompt, you have to move the generated token file. It will deploy the token file (.modal.toml) to your Windows profile folder. The virtual environment couldn't see that location (strangely, it couldn't even after I set environment variables for it and rebooted). I moved that token file to the folder I'm operating out of for the lab and it stopped throwing auth errors.\n", |
|
"\n", |
|
"And another Windows student (Robert M. - thank you!!) added another possible step:\n", |
|
"\n", |
|
"\n", |
|
"> I could not get modal to see my tokens (resulting in an 'auth error'), even after copying the \".modal.toml\" file to the \"week8\" folder and restarting JupyterLab. The fix was to manually set the environment variables (the standard way). This config method is explained by modal on their [web site](https://modal.com/docs/reference/modal.config) \n", |
|
"```\n", |
|
"import os\n", |
|
"os.environ[\"MODAL_TOKEN_ID\"] = \"xxx\"\n", |
|
"os.environ[\"MODAL_TOKEN_SECRET\"] = \"yyy\" \n", |
|
"```\n", |
|
"\n", |
|
"Finally: I've also heard that in some situations, you might need to restart the Kernel of this jupyter notebook after running this. (Kernel menu >> Restart Kernel and Clear Outputs of All Cells)." |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": null, |
|
"id": "0d240622-8422-4c99-8464-c04d063e4cb6", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [ |
|
"# Remove the '# ' from the next line and run the cell, or run this command without the excalamation mark from an activated command prompt\n", |
|
"# !modal setup" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 47, |
|
"id": "3b133701-f550-44a1-a67f-eb7ccc4769a9", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [ |
|
"from hello import app, hello, hello_europe" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 48, |
|
"id": "0f3f73ae-1295-49f3-9099-b8b41fc3429b", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"data": { |
|
"text/plain": [ |
|
"'Hello from San Diego, California, US!!'" |
|
] |
|
}, |
|
"execution_count": 48, |
|
"metadata": {}, |
|
"output_type": "execute_result" |
|
} |
|
], |
|
"source": [ |
|
"with app.run():\n", |
|
" reply=hello.local()\n", |
|
"reply" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 49, |
|
"id": "c1d8c6f9-edc7-4e52-9b3a-c07d7cff1ac7", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"data": { |
|
"text/plain": [ |
|
"'Hello from Ashburn, Virginia, US!!'" |
|
] |
|
}, |
|
"execution_count": 49, |
|
"metadata": {}, |
|
"output_type": "execute_result" |
|
} |
|
], |
|
"source": [ |
|
"#NOTE: .remote()\n", |
|
"with app.run():\n", |
|
" reply=hello.remote()\n", |
|
"reply" |
|
] |
|
}, |
|
{ |
|
"cell_type": "markdown", |
|
"id": "a1c075e9-49c7-4ebd-812f-83196d32de32", |
|
"metadata": {}, |
|
"source": [ |
|
"## Added thanks to student Tue H.\n", |
|
"\n", |
|
"If you look in hello.py, I've added a simple function hello_europe\n", |
|
"\n", |
|
"That uses the decorator: \n", |
|
"`@app.function(image=image, region=\"eu\")`\n", |
|
"\n", |
|
"See the result below! More region specific settings are [here](https://modal.com/docs/guide/region-selection)\n", |
|
"\n", |
|
"Note that it does consume marginally more credits to specify a region." |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 50, |
|
"id": "b027da1a-c79d-42cb-810d-32ddca31aa02", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"data": { |
|
"text/plain": [ |
|
"'Hello from Frankfurt am Main, Hesse, DE!!'" |
|
] |
|
}, |
|
"execution_count": 50, |
|
"metadata": {}, |
|
"output_type": "execute_result" |
|
} |
|
], |
|
"source": [ |
|
"with app.run():\n", |
|
" reply=hello_europe.remote()\n", |
|
"reply" |
|
] |
|
}, |
|
{ |
|
"cell_type": "markdown", |
|
"id": "22e8d804-c027-45fb-8fef-06e7bba6295a", |
|
"metadata": {}, |
|
"source": [ |
|
"# Before we move on -\n", |
|
"\n", |
|
"## We need to set your HuggingFace Token as a secret in Modal\n", |
|
"\n", |
|
"1. Go to modal.com, sign in and go to your dashboard\n", |
|
"2. Click on Secrets in the nav bar\n", |
|
"3. Create new secret, click on Hugging Face, this new secret needs to be called **hf-secret** because that's how we refer to it in the code\n", |
|
"4. Fill in your HF_TOKEN where it prompts you\n", |
|
"\n", |
|
"### And now back to business: time to work with Llama" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 51, |
|
"id": "cb8b6c41-8259-4329-b1c4-a1f67d26d1be", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [ |
|
"from llama import app, generate" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 52, |
|
"id": "db4a718a-d95d-4f61-9688-c9df21d88fe6", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"data": { |
|
"application/vnd.jupyter.widget-view+json": { |
|
"model_id": "21b08d398a254e60b7d51933e3416108", |
|
"version_major": 2, |
|
"version_minor": 0 |
|
}, |
|
"text/plain": [ |
|
"Output()" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">✓</span> Initialized. <span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2\">View run at </span><span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2; text-decoration: underline\">https://modal.com/apps/craigprobus/main/ap-a1zKRQGpj8VmuyIJtBeWSk</span>\n", |
|
"</pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[32m✓\u001b[0m Initialized. \u001b[38;5;249mView run at \u001b[0m\u001b[4;38;5;249mhttps://modal.com/apps/craigprobus/main/ap-a1zKRQGpj8VmuyIJtBeWSk\u001b[0m\n" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n" |
|
], |
|
"text/plain": [] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"application/vnd.jupyter.widget-view+json": { |
|
"model_id": "2c42ac514b904938a52e692f77ab6042", |
|
"version_major": 2, |
|
"version_minor": 0 |
|
}, |
|
"text/plain": [ |
|
"Output()" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n" |
|
], |
|
"text/plain": [] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">✓</span> Created objects.\n", |
|
"<span style=\"color: #808080; text-decoration-color: #808080\">├── </span>🔨 Created mount /Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/llama.py\n", |
|
"<span style=\"color: #808080; text-decoration-color: #808080\">├── </span>🔨 Created mount PythonPackage:hello\n", |
|
"<span style=\"color: #808080; text-decoration-color: #808080\">└── </span>🔨 Created function generate.\n", |
|
"</pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[32m✓\u001b[0m Created objects.\n", |
|
"\u001b[38;5;244m├── \u001b[0m🔨 Created mount /Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/llama.py\n", |
|
"\u001b[38;5;244m├── \u001b[0m🔨 Created mount PythonPackage:hello\n", |
|
"\u001b[38;5;244m└── \u001b[0m🔨 Created function generate.\n" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"application/vnd.jupyter.widget-view+json": { |
|
"model_id": "ece6417840304983acb4c6a6ec9abfdd", |
|
"version_major": 2, |
|
"version_minor": 0 |
|
}, |
|
"text/plain": [ |
|
"Output()" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1AFetching 4 files: 0%| | 0/4 [00:00<?, ?it/s]</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1AFetching 4 files: 0%| | 0/4 [00:00<?, ?it/s]\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1AFetching 4 files: 25%|██▌ | 1/4 [01:12<03:38, 72.90s/it]Fetching 4 files: 100%|██████████| 4/4 [01:12<00:00, 18.23s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1AFetching 4 files: 25%|██▌ | 1/4 [01:12<03:38, 72.90s/it]Fetching 4 files: 100%|██████████| 4/4 [01:12<00:00, 18.23s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 0%| | 0/4 [00:00<?, ?it/s]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 0%| | 0/4 [00:00<?, ?it/s]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 25%|██▌ | 1/4 [00:04<00:12, 4.10s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 25%|██▌ | 1/4 [00:04<00:12, 4.10s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 50%|█████ | 2/4 [00:08<00:08, 4.46s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 50%|█████ | 2/4 [00:08<00:08, 4.46s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 75%|███████▌ | 3/4 [00:13<00:04, 4.53s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 75%|███████▌ | 3/4 [00:13<00:04, 4.53s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 2.86s/it]Loading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 3.43s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 2.86s/it]Loading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 3.43s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31mSetting `pad_token_id` to `eos_token_id`:128001 for open-end generation.\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n" |
|
], |
|
"text/plain": [] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000\">Stopping app - local entrypoint completed.\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[33mStopping app - local entrypoint completed.\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">✓</span> App completed. <span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2\">View run at </span><span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2; text-decoration: underline\">https://modal.com/apps/craigprobus/main/ap-a1zKRQGpj8VmuyIJtBeWSk</span>\n", |
|
"</pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[32m✓\u001b[0m App completed. \u001b[38;5;249mView run at \u001b[0m\u001b[4;38;5;249mhttps://modal.com/apps/craigprobus/main/ap-a1zKRQGpj8VmuyIJtBeWSk\u001b[0m\n" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/plain": [ |
|
"'<|begin_of_text|>Life is a mystery, everyone must stand alone, I hear you call my name,'" |
|
] |
|
}, |
|
"execution_count": 52, |
|
"metadata": {}, |
|
"output_type": "execute_result" |
|
} |
|
], |
|
"source": [ |
|
"with modal.enable_output():\n", |
|
" with app.run():\n", |
|
" result=generate.remote(\"Life is a mystery, everyone must stand alone, I hear\")\n", |
|
"result" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 53, |
|
"id": "9a9a6844-29ec-4264-8e72-362d976b3968", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [ |
|
"import modal\n", |
|
"from pricer_ephemeral import app, price" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 54, |
|
"id": "50e6cf99-8959-4ae3-ba02-e325cb7fff94", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"data": { |
|
"application/vnd.jupyter.widget-view+json": { |
|
"model_id": "e951ef75eef245c8bf36f04fc0d10083", |
|
"version_major": 2, |
|
"version_minor": 0 |
|
}, |
|
"text/plain": [ |
|
"Output()" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">✓</span> Initialized. <span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2\">View run at </span><span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2; text-decoration: underline\">https://modal.com/apps/craigprobus/main/ap-jj4lCu9XtEr4VTT14wMcpK</span>\n", |
|
"</pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[32m✓\u001b[0m Initialized. \u001b[38;5;249mView run at \u001b[0m\u001b[4;38;5;249mhttps://modal.com/apps/craigprobus/main/ap-jj4lCu9XtEr4VTT14wMcpK\u001b[0m\n" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n" |
|
], |
|
"text/plain": [] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"application/vnd.jupyter.widget-view+json": { |
|
"model_id": "0aa9f1e2d2f849f997b4edd25555efaa", |
|
"version_major": 2, |
|
"version_minor": 0 |
|
}, |
|
"text/plain": [ |
|
"Output()" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n" |
|
], |
|
"text/plain": [] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">✓</span> Created objects.\n", |
|
"<span style=\"color: #808080; text-decoration-color: #808080\">├── </span>🔨 Created mount /Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_ephemeral.py\n", |
|
"<span style=\"color: #808080; text-decoration-color: #808080\">├── </span>🔨 Created mount PythonPackage:hello\n", |
|
"<span style=\"color: #808080; text-decoration-color: #808080\">├── </span>🔨 Created mount PythonPackage:llama\n", |
|
"<span style=\"color: #808080; text-decoration-color: #808080\">└── </span>🔨 Created function price.\n", |
|
"</pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[32m✓\u001b[0m Created objects.\n", |
|
"\u001b[38;5;244m├── \u001b[0m🔨 Created mount /Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_ephemeral.py\n", |
|
"\u001b[38;5;244m├── \u001b[0m🔨 Created mount PythonPackage:hello\n", |
|
"\u001b[38;5;244m├── \u001b[0m🔨 Created mount PythonPackage:llama\n", |
|
"\u001b[38;5;244m└── \u001b[0m🔨 Created function price.\n" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"application/vnd.jupyter.widget-view+json": { |
|
"model_id": "7b95c170bb954e48b45db743437e9d91", |
|
"version_major": 2, |
|
"version_minor": 0 |
|
}, |
|
"text/plain": [ |
|
"Output()" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1AFetching 4 files: 0%| | 0/4 [00:00<?, ?it/s]</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1AFetching 4 files: 0%| | 0/4 [00:00<?, ?it/s]\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1AFetching 4 files: 25%|██▌ | 1/4 [01:03<03:09, 63.06s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1AFetching 4 files: 25%|██▌ | 1/4 [01:03<03:09, 63.06s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1AFetching 4 files: 50%|█████ | 2/4 [01:05<00:54, 27.26s/it]Fetching 4 files: 100%|██████████| 4/4 [01:05<00:00, 16.31s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1AFetching 4 files: 50%|█████ | 2/4 [01:05<00:54, 27.26s/it]Fetching 4 files: 100%|██████████| 4/4 [01:05<00:00, 16.31s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 0%| | 0/4 [00:00<?, ?it/s]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 0%| | 0/4 [00:00<?, ?it/s]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 25%|██▌ | 1/4 [00:04<00:13, 4.64s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 25%|██▌ | 1/4 [00:04<00:13, 4.64s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 50%|█████ | 2/4 [00:09<00:09, 4.58s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 50%|█████ | 2/4 [00:09<00:09, 4.58s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 75%|███████▌ | 3/4 [00:13<00:04, 4.34s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 75%|███████▌ | 3/4 [00:13<00:04, 4.34s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">\u001b[1ALoading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 2.77s/it]Loading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 3.40s/it]\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31m\u001b[1ALoading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 2.77s/it]Loading checkpoint shards: 100%|██████████| 4/4 [00:13<00:00, 3.40s/it]\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #800000; text-decoration-color: #800000\">Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[31mSetting `pad_token_id` to `eos_token_id`:128001 for open-end generation.\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"></pre>\n" |
|
], |
|
"text/plain": [] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #808000; text-decoration-color: #808000\">Stopping app - local entrypoint completed.\n", |
|
"</span></pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[33mStopping app - local entrypoint completed.\n", |
|
"\u001b[0m" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/html": [ |
|
"<pre style=\"white-space:pre;overflow-x:auto;line-height:normal;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace\"><span style=\"color: #008000; text-decoration-color: #008000\">✓</span> App completed. <span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2\">View run at </span><span style=\"color: #b2b2b2; text-decoration-color: #b2b2b2; text-decoration: underline\">https://modal.com/apps/craigprobus/main/ap-jj4lCu9XtEr4VTT14wMcpK</span>\n", |
|
"</pre>\n" |
|
], |
|
"text/plain": [ |
|
"\u001b[32m✓\u001b[0m App completed. \u001b[38;5;249mView run at \u001b[0m\u001b[4;38;5;249mhttps://modal.com/apps/craigprobus/main/ap-jj4lCu9XtEr4VTT14wMcpK\u001b[0m\n" |
|
] |
|
}, |
|
"metadata": {}, |
|
"output_type": "display_data" |
|
}, |
|
{ |
|
"data": { |
|
"text/plain": [ |
|
"220.0" |
|
] |
|
}, |
|
"execution_count": 54, |
|
"metadata": {}, |
|
"output_type": "execute_result" |
|
} |
|
], |
|
"source": [ |
|
"with modal.enable_output():\n", |
|
" with app.run():\n", |
|
" result=price.remote(\"Quadcast HyperX condenser mic, connects via usb-c to your computer for crystal clear audio\")\n", |
|
"result" |
|
] |
|
}, |
|
{ |
|
"cell_type": "markdown", |
|
"id": "04d8747f-8452-4077-8af6-27e03888508a", |
|
"metadata": {}, |
|
"source": [ |
|
"## Transitioning From Ephemeral Apps to Deployed Apps\n", |
|
"\n", |
|
"From a command line, `modal deploy xxx` will deploy your code as a Deployed App\n", |
|
"\n", |
|
"This is how you could package your AI service behind an API to be used in a Production System.\n", |
|
"\n", |
|
"You can also build REST endpoints easily, although we won't cover that as we'll be calling direct from Python.\n", |
|
"\n", |
|
"## Important note for Windows people:\n", |
|
"\n", |
|
"On the next line, I call `modal deploy` from within Jupyter lab; I've heard that on some versions of Windows this gives a strange unicode error because modal prints emojis to the output which can't be displayed. If that happens to you, simply use an Anaconda Prompt window or a Powershell instead, with your environment activated, and type `modal deploy pricer_service` there. Follow the same approach the next time we do `!modal deploy` too.\n", |
|
"\n", |
|
"As an alternative, a few students have mentioned you can run this code within Jupyter Lab if you want to run it from here:\n", |
|
"```\n", |
|
"# Check the default encoding\n", |
|
"print(locale.getpreferredencoding()) # Should print 'UTF-8'\n", |
|
"\n", |
|
"# Ensure UTF-8 encoding\n", |
|
"os.environ['PYTHONIOENCODING'] = 'utf-8'\n", |
|
"```" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 55, |
|
"id": "7f90d857-2f12-4521-bb90-28efd917f7d1", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"name": "stdout", |
|
"output_type": "stream", |
|
"text": [ |
|
"\u001b[2K\u001b[34m⠸\u001b[0m Creating objects.....\n", |
|
"\u001b[37m└── \u001b[0m\u001b[34m⠋\u001b[0m Creating mount \n", |
|
"\u001b[37m \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[34m⠦\u001b[0m Creating objects...\n", |
|
"\u001b[37m├── \u001b[0m🔨 Created mount \n", |
|
"\u001b[37m│ \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[37m│ \u001b[0me.py\n", |
|
"\u001b[37m└── \u001b[0m🔨 Created function price.\n", |
|
"\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[32m✓\u001b[0m Created objects.\n", |
|
"\u001b[37m├── \u001b[0m🔨 Created mount \n", |
|
"\u001b[37m│ \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[37m│ \u001b[0me.py\n", |
|
"\u001b[37m└── \u001b[0m🔨 Created function price.\n", |
|
"\u001b[32m✓\u001b[0m App deployed in 0.902s! 🎉\n", |
|
"\n", |
|
"View Deployment: \u001b[35mhttps://modal.com/apps/craigprobus/main/deployed/pricer-service\u001b[0m\n" |
|
] |
|
} |
|
], |
|
"source": [ |
|
"!modal deploy -m pricer_service" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 56, |
|
"id": "1dec70ff-1986-4405-8624-9bbbe0ce1f4a", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [ |
|
"pricer = modal.Function.from_name(\"pricer-service\", \"price\")" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 57, |
|
"id": "17776139-0d9e-4ad0-bcd0-82d3a92ca61f", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"data": { |
|
"text/plain": [ |
|
"220.0" |
|
] |
|
}, |
|
"execution_count": 57, |
|
"metadata": {}, |
|
"output_type": "execute_result" |
|
} |
|
], |
|
"source": [ |
|
"pricer.remote(\"Quadcast HyperX condenser mic, connects via usb-c to your computer for crystal clear audio\")" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 66, |
|
"id": "d5a2d7a8-a88d-4b50-a21f-4d115f4eb2e6", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"name": "stdout", |
|
"output_type": "stream", |
|
"text": [ |
|
"\u001b[31m╭─\u001b[0m\u001b[31m Error: Already exists \u001b[0m\u001b[31m─────────────────────────────────────────────────────\u001b[0m\u001b[31m─╮\u001b[0m\n", |
|
"\u001b[31m│\u001b[0m Can't overwrite existing volume \u001b[31m│\u001b[0m\n", |
|
"\u001b[31m╰──────────────────────────────────────────────────────────────────────────────╯\u001b[0m\n" |
|
] |
|
} |
|
], |
|
"source": [ |
|
"!modal volume create hf-hub-cache" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 67, |
|
"id": "f56d1e55-2a03-4ce2-bb47-2ab6b9175a02", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"name": "stdout", |
|
"output_type": "stream", |
|
"text": [ |
|
"\u001b[2K\u001b[34m⠸\u001b[0m Creating objects.....\n", |
|
"\u001b[37m└── \u001b[0m\u001b[34m⠋\u001b[0m Creating mount \n", |
|
"\u001b[37m \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[34m⠦\u001b[0m Creating objects...\n", |
|
"\u001b[37m└── \u001b[0m\u001b[34m⠸\u001b[0m Creating mount \n", |
|
"\u001b[37m \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[34m⠏\u001b[0m Creating objects...\n", |
|
"\u001b[37m└── \u001b[0m\u001b[34m⠦\u001b[0m Creating mount \n", |
|
"\u001b[37m \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[34m⠹\u001b[0m Creating objects...\n", |
|
"\u001b[37m├── \u001b[0m🔨 Created mount \n", |
|
"\u001b[37m│ \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[37m│ \u001b[0me2.py\n", |
|
"\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[34m⠼\u001b[0m Creating objects...\n", |
|
"\u001b[37m├── \u001b[0m🔨 Created mount \n", |
|
"\u001b[37m│ \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[37m│ \u001b[0me2.py\n", |
|
"\u001b[37m└── \u001b[0m🔨 Created function Pricer.*.\n", |
|
"\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[1A\u001b[2K\u001b[32m✓\u001b[0m Created objects.\n", |
|
"\u001b[37m├── \u001b[0m🔨 Created mount \n", |
|
"\u001b[37m│ \u001b[0m/Users/craigprobus/Repos/ed-donner-class/llm_engineering/week8/pricer_servic\n", |
|
"\u001b[37m│ \u001b[0me2.py\n", |
|
"\u001b[37m└── \u001b[0m🔨 Created function Pricer.*.\n", |
|
"\u001b[32m✓\u001b[0m App deployed in 1.531s! 🎉\n", |
|
"\n", |
|
"View Deployment: \u001b[35mhttps://modal.com/apps/craigprobus/main/deployed/pricer-service\u001b[0m\n" |
|
] |
|
} |
|
], |
|
"source": [ |
|
"# You can also run \"modal deploy -m pricer_service2\" at the command line in an activated environment\n", |
|
"!modal deploy -m pricer_service2" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 68, |
|
"id": "9e19daeb-1281-484b-9d2f-95cc6fed2622", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"ename": "RemoteError", |
|
"evalue": "", |
|
"output_type": "error", |
|
"traceback": [ |
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
|
"\u001b[0;31mRemoteError\u001b[0m Traceback (most recent call last)", |
|
"Cell \u001b[0;32mIn[68], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m Pricer \u001b[38;5;241m=\u001b[39m modal\u001b[38;5;241m.\u001b[39mCls\u001b[38;5;241m.\u001b[39mfrom_name(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mpricer-service\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPricer\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 2\u001b[0m pricer \u001b[38;5;241m=\u001b[39m Pricer()\n\u001b[0;32m----> 3\u001b[0m reply \u001b[38;5;241m=\u001b[39m \u001b[43mpricer\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mprice\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mremote\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mQuadcast HyperX condenser mic, connects via usb-c to your computer for crystal clear audio\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28mprint\u001b[39m(reply)\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/synchronicity/synchronizer.py:592\u001b[0m, in \u001b[0;36mSynchronizer._wrap_proxy_method.<locals>.proxy_method\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 590\u001b[0m instance \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__dict__\u001b[39m[synchronizer_self\u001b[38;5;241m.\u001b[39m_original_attr]\n\u001b[1;32m 591\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 592\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mwrapped_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43minstance\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 593\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m UserCodeException \u001b[38;5;28;01mas\u001b[39;00m uc_exc:\n\u001b[1;32m 594\u001b[0m uc_exc\u001b[38;5;241m.\u001b[39mexc\u001b[38;5;241m.\u001b[39m__suppress_context__ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/synchronicity/combined_types.py:29\u001b[0m, in \u001b[0;36mFunctionWithAio.__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m UserCodeException \u001b[38;5;28;01mas\u001b[39;00m uc_exc:\n\u001b[1;32m 28\u001b[0m uc_exc\u001b[38;5;241m.\u001b[39mexc\u001b[38;5;241m.\u001b[39m__suppress_context__ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[0;32m---> 29\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m uc_exc\u001b[38;5;241m.\u001b[39mexc\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/modal/_object.py:286\u001b[0m, in \u001b[0;36mlive_method.<locals>.wrapped\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 283\u001b[0m \u001b[38;5;129m@wraps\u001b[39m(method)\n\u001b[1;32m 284\u001b[0m \u001b[38;5;28;01masync\u001b[39;00m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21mwrapped\u001b[39m(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 285\u001b[0m \u001b[38;5;28;01mawait\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mhydrate()\n\u001b[0;32m--> 286\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mawait\u001b[39;00m method(\u001b[38;5;28mself\u001b[39m, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/modal/_functions.py:1408\u001b[0m, in \u001b[0;36m_Function.remote\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1403\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_is_generator:\n\u001b[1;32m 1404\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m InvalidError(\n\u001b[1;32m 1405\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mA generator function cannot be called with `.remote(...)`. Use `.remote_gen(...)` instead.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 1406\u001b[0m )\n\u001b[0;32m-> 1408\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mawait\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call_function(args, kwargs)\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/modal/_functions.py:1358\u001b[0m, in \u001b[0;36m_Function._call_function\u001b[0;34m(self, args, kwargs)\u001b[0m\n\u001b[1;32m 1349\u001b[0m \u001b[38;5;28;01masync\u001b[39;00m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21m_call_function\u001b[39m(\u001b[38;5;28mself\u001b[39m, args, kwargs) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m ReturnType:\n\u001b[1;32m 1350\u001b[0m invocation \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m _Invocation\u001b[38;5;241m.\u001b[39mcreate(\n\u001b[1;32m 1351\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 1352\u001b[0m args,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1355\u001b[0m function_call_invocation_type\u001b[38;5;241m=\u001b[39mapi_pb2\u001b[38;5;241m.\u001b[39mFUNCTION_CALL_INVOCATION_TYPE_SYNC,\n\u001b[1;32m 1356\u001b[0m )\n\u001b[0;32m-> 1358\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mawait\u001b[39;00m invocation\u001b[38;5;241m.\u001b[39mrun_function()\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/modal/_functions.py:257\u001b[0m, in \u001b[0;36m_Invocation.run_function\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 249\u001b[0m ctx \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_retry_context\n\u001b[1;32m 250\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[1;32m 251\u001b[0m \u001b[38;5;129;01mnot\u001b[39;00m ctx\n\u001b[1;32m 252\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m ctx\u001b[38;5;241m.\u001b[39mretry_policy\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 255\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m ctx\u001b[38;5;241m.\u001b[39msync_client_retries_enabled\n\u001b[1;32m 256\u001b[0m ):\n\u001b[0;32m--> 257\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mawait\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_single_output()\n\u001b[1;32m 259\u001b[0m \u001b[38;5;66;03m# User errors including timeouts are managed by the user specified retry policy.\u001b[39;00m\n\u001b[1;32m 260\u001b[0m user_retry_manager \u001b[38;5;241m=\u001b[39m RetryManager(ctx\u001b[38;5;241m.\u001b[39mretry_policy)\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/modal/_functions.py:245\u001b[0m, in \u001b[0;36m_Invocation._get_single_output\u001b[0;34m(self, expected_jwt)\u001b[0m\n\u001b[1;32m 236\u001b[0m \u001b[38;5;28;01masync\u001b[39;00m \u001b[38;5;28;01mdef\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;21m_get_single_output\u001b[39m(\u001b[38;5;28mself\u001b[39m, expected_jwt: Optional[\u001b[38;5;28mstr\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any:\n\u001b[1;32m 237\u001b[0m \u001b[38;5;66;03m# waits indefinitely for a single result for the function, and clear the outputs buffer after\u001b[39;00m\n\u001b[1;32m 238\u001b[0m item: api_pb2\u001b[38;5;241m.\u001b[39mFunctionGetOutputsItem \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m 239\u001b[0m \u001b[38;5;28;01mawait\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mpop_function_call_outputs(\n\u001b[1;32m 240\u001b[0m timeout\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 243\u001b[0m )\n\u001b[1;32m 244\u001b[0m )\u001b[38;5;241m.\u001b[39moutputs[\u001b[38;5;241m0\u001b[39m]\n\u001b[0;32m--> 245\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mawait\u001b[39;00m _process_result(item\u001b[38;5;241m.\u001b[39mresult, item\u001b[38;5;241m.\u001b[39mdata_format, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstub, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclient)\n", |
|
"File \u001b[0;32m/opt/anaconda3/envs/llms/lib/python3.11/site-packages/modal/_utils/function_utils.py:497\u001b[0m, in \u001b[0;36m_process_result\u001b[0;34m(result, data_format, stub, client)\u001b[0m\n\u001b[1;32m 495\u001b[0m uc_exc \u001b[38;5;241m=\u001b[39m UserCodeException(exc_with_hints(exc))\n\u001b[1;32m 496\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m uc_exc\n\u001b[0;32m--> 497\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m RemoteError(result\u001b[38;5;241m.\u001b[39mexception)\n\u001b[1;32m 499\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m 500\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m deserialize_data_format(data, data_format, client)\n", |
|
"\u001b[0;31mRemoteError\u001b[0m: " |
|
] |
|
} |
|
], |
|
"source": [ |
|
"Pricer = modal.Cls.from_name(\"pricer-service\", \"Pricer\")\n", |
|
"pricer = Pricer()\n", |
|
"reply = pricer.price.remote(\"Quadcast HyperX condenser mic, connects via usb-c to your computer for crystal clear audio\")\n", |
|
"print(reply)" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 37, |
|
"id": "c29b8c58-4cb7-44b0-ab7e-6469d3a318e8", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"name": "stdout", |
|
"output_type": "stream", |
|
"text": [ |
|
"Requirement already satisfied: modal in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (0.73.155)\n", |
|
"Requirement already satisfied: aiohttp in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (3.11.12)\n", |
|
"Requirement already satisfied: certifi in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (2025.1.31)\n", |
|
"Requirement already satisfied: click>=8.1.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (8.1.8)\n", |
|
"Requirement already satisfied: fastapi in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (0.115.8)\n", |
|
"Requirement already satisfied: grpclib==0.4.7 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (0.4.7)\n", |
|
"Requirement already satisfied: protobuf!=4.24.0,<6.0,>=3.19 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (5.29.3)\n", |
|
"Requirement already satisfied: rich>=12.0.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (13.9.4)\n", |
|
"Requirement already satisfied: synchronicity~=0.9.10 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (0.9.11)\n", |
|
"Requirement already satisfied: toml in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (0.10.2)\n", |
|
"Requirement already satisfied: typer>=0.9 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (0.15.1)\n", |
|
"Requirement already satisfied: types-certifi in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (2021.10.8.3)\n", |
|
"Requirement already satisfied: types-toml in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (0.10.8.20240310)\n", |
|
"Requirement already satisfied: watchfiles in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (1.0.4)\n", |
|
"Requirement already satisfied: typing_extensions~=4.6 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from modal) (4.12.2)\n", |
|
"Requirement already satisfied: h2<5,>=3.1.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from grpclib==0.4.7->modal) (4.2.0)\n", |
|
"Requirement already satisfied: multidict in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from grpclib==0.4.7->modal) (6.1.0)\n", |
|
"Requirement already satisfied: markdown-it-py>=2.2.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from rich>=12.0.0->modal) (3.0.0)\n", |
|
"Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from rich>=12.0.0->modal) (2.19.1)\n", |
|
"Requirement already satisfied: sigtools>=4.0.1 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from synchronicity~=0.9.10->modal) (4.0.1)\n", |
|
"Requirement already satisfied: shellingham>=1.3.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from typer>=0.9->modal) (1.5.4)\n", |
|
"Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from aiohttp->modal) (2.4.6)\n", |
|
"Requirement already satisfied: aiosignal>=1.1.2 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from aiohttp->modal) (1.3.2)\n", |
|
"Requirement already satisfied: attrs>=17.3.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from aiohttp->modal) (25.1.0)\n", |
|
"Requirement already satisfied: frozenlist>=1.1.1 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from aiohttp->modal) (1.5.0)\n", |
|
"Requirement already satisfied: propcache>=0.2.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from aiohttp->modal) (0.2.1)\n", |
|
"Requirement already satisfied: yarl<2.0,>=1.17.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from aiohttp->modal) (1.18.3)\n", |
|
"Requirement already satisfied: starlette<0.46.0,>=0.40.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from fastapi->modal) (0.45.3)\n", |
|
"Requirement already satisfied: pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from fastapi->modal) (2.10.6)\n", |
|
"Requirement already satisfied: anyio>=3.0.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from watchfiles->modal) (4.8.0)\n", |
|
"Requirement already satisfied: idna>=2.8 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from anyio>=3.0.0->watchfiles->modal) (3.10)\n", |
|
"Requirement already satisfied: sniffio>=1.1 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from anyio>=3.0.0->watchfiles->modal) (1.3.1)\n", |
|
"Requirement already satisfied: hyperframe<7,>=6.1 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from h2<5,>=3.1.0->grpclib==0.4.7->modal) (6.1.0)\n", |
|
"Requirement already satisfied: hpack<5,>=4.1 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from h2<5,>=3.1.0->grpclib==0.4.7->modal) (4.1.0)\n", |
|
"Requirement already satisfied: mdurl~=0.1 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from markdown-it-py>=2.2.0->rich>=12.0.0->modal) (0.1.2)\n", |
|
"Requirement already satisfied: annotated-types>=0.6.0 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4->fastapi->modal) (0.7.0)\n", |
|
"Requirement already satisfied: pydantic-core==2.27.2 in /opt/anaconda3/envs/llms/lib/python3.11/site-packages (from pydantic!=1.8,!=1.8.1,!=2.0.0,!=2.0.1,!=2.1.0,<3.0.0,>=1.7.4->fastapi->modal) (2.27.2)\n" |
|
] |
|
} |
|
], |
|
"source": [ |
|
"!pip install --upgrade modal" |
|
] |
|
}, |
|
{ |
|
"cell_type": "markdown", |
|
"id": "9c1b1451-6249-4462-bf2d-5937c059926c", |
|
"metadata": {}, |
|
"source": [ |
|
"# Optional: Keeping Modal warm\n", |
|
"\n", |
|
"## A way to improve the speed of the Modal pricer service\n", |
|
"\n", |
|
"A student mentioned to me that he was concerned by how slow Modal seems to be. The reason is that Modal puts our service to sleep if we don't use it, and then it takes 2.5 minutes to spin back up.\n", |
|
"\n", |
|
"I've added a utility called `keep_warm.py` that will keep our Modal warm by pinging it every 30 seconds.\n", |
|
"\n", |
|
"To use the utliity, bring up a new Terminal (Mac) or Anaconda prompt (Windows), ensure the environment is activated with `conda activate llms`\n", |
|
"\n", |
|
"Then run: `python keep_warm.py` from within the week8 drectory.\n", |
|
"\n", |
|
"Remember to press ctrl+C or exit the window when you no longer need Modal running.\n" |
|
] |
|
}, |
|
{ |
|
"cell_type": "markdown", |
|
"id": "3754cfdd-ae28-47c8-91f2-6e060e2c91b3", |
|
"metadata": {}, |
|
"source": [ |
|
"## And now introducing our Agent class" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 44, |
|
"id": "ba9aedca-6a7b-4d30-9f64-59d76f76fb6d", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [ |
|
"from agents.specialist_agent import SpecialistAgent" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": 45, |
|
"id": "fe5843e5-e958-4a65-8326-8f5b4686de7f", |
|
"metadata": {}, |
|
"outputs": [ |
|
{ |
|
"data": { |
|
"text/plain": [ |
|
"299.0" |
|
] |
|
}, |
|
"execution_count": 45, |
|
"metadata": {}, |
|
"output_type": "execute_result" |
|
} |
|
], |
|
"source": [ |
|
"agent = SpecialistAgent()\n", |
|
"agent.price(\"iPad Pro 2nd generation\")" |
|
] |
|
}, |
|
{ |
|
"cell_type": "code", |
|
"execution_count": null, |
|
"id": "f5a3181b-1310-4102-8d7d-52caf4c00538", |
|
"metadata": {}, |
|
"outputs": [], |
|
"source": [] |
|
} |
|
], |
|
"metadata": { |
|
"kernelspec": { |
|
"display_name": "Python 3 (ipykernel)", |
|
"language": "python", |
|
"name": "python3" |
|
}, |
|
"language_info": { |
|
"codemirror_mode": { |
|
"name": "ipython", |
|
"version": 3 |
|
}, |
|
"file_extension": ".py", |
|
"mimetype": "text/x-python", |
|
"name": "python", |
|
"nbconvert_exporter": "python", |
|
"pygments_lexer": "ipython3", |
|
"version": "3.11.11" |
|
} |
|
}, |
|
"nbformat": 4, |
|
"nbformat_minor": 5 |
|
}
|
|
|