Merge branch 'myrepo' of https://github.com/nisargvp/nisargs_llmops_project into myrepo
Browse files
app/Programatically_Accessing_OpenAI_Endpoints_with_Python.ipynb
ADDED
@@ -0,0 +1,334 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "markdown",
|
5 |
+
"metadata": {
|
6 |
+
"id": "UIuhLOcmCdyR"
|
7 |
+
},
|
8 |
+
"source": [
|
9 |
+
"### Using the OpenAI Library to Programmatically Access GPT-3.5-turbo!\n",
|
10 |
+
"\n",
|
11 |
+
"This notebook was authored by [Chris Alexiuk](https://www.linkedin.com/in/csalexiuk/)"
|
12 |
+
]
|
13 |
+
},
|
14 |
+
{
|
15 |
+
"cell_type": "code",
|
16 |
+
"execution_count": 1,
|
17 |
+
"metadata": {
|
18 |
+
"colab": {
|
19 |
+
"base_uri": "https://localhost:8080/"
|
20 |
+
},
|
21 |
+
"id": "3qCKaH6vD-jZ",
|
22 |
+
"outputId": "b9898a5f-36a7-4d8d-d760-310187cf31fa"
|
23 |
+
},
|
24 |
+
"outputs": [],
|
25 |
+
"source": [
|
26 |
+
"# !pip install openai cohere tiktoken -qU"
|
27 |
+
]
|
28 |
+
},
|
29 |
+
{
|
30 |
+
"cell_type": "markdown",
|
31 |
+
"metadata": {
|
32 |
+
"id": "XxS23_1zpYid"
|
33 |
+
},
|
34 |
+
"source": [
|
35 |
+
"### OpenAI API Key"
|
36 |
+
]
|
37 |
+
},
|
38 |
+
{
|
39 |
+
"cell_type": "code",
|
40 |
+
"execution_count": 2,
|
41 |
+
"metadata": {
|
42 |
+
"colab": {
|
43 |
+
"base_uri": "https://localhost:8080/"
|
44 |
+
},
|
45 |
+
"id": "tpnsDCfEbsqS",
|
46 |
+
"outputId": "1011f74e-624b-4800-89ff-c83152d34c1f"
|
47 |
+
},
|
48 |
+
"outputs": [],
|
49 |
+
"source": [
|
50 |
+
"import os\n",
|
51 |
+
"import openai\n",
|
52 |
+
"import getpass\n",
|
53 |
+
"\n",
|
54 |
+
"# set the OPENAI_API_KEY environment variable\n",
|
55 |
+
"openai.api_key = getpass.getpass(\"OpenAI API Key:\")"
|
56 |
+
]
|
57 |
+
},
|
58 |
+
{
|
59 |
+
"cell_type": "markdown",
|
60 |
+
"metadata": {
|
61 |
+
"id": "YHD49z39pbIS"
|
62 |
+
},
|
63 |
+
"source": [
|
64 |
+
"### Our First Prompt\n",
|
65 |
+
"\n",
|
66 |
+
"You can reference OpenAI's [documentation](https://platform.openai.com/docs/api-reference/authentication?lang=python) if you get stuck!\n",
|
67 |
+
"\n",
|
68 |
+
"Let's create a `ChatCompletion` model to kick things off!\n",
|
69 |
+
"\n",
|
70 |
+
"There are three \"roles\" available to use:\n",
|
71 |
+
"\n",
|
72 |
+
"- `system`\n",
|
73 |
+
"- `assistant`\n",
|
74 |
+
"- `user`\n",
|
75 |
+
"\n",
|
76 |
+
"OpenAI provides some context for these roles [here](https://help.openai.com/en/articles/7042661-chatgpt-api-transition-guide)\n",
|
77 |
+
"\n",
|
78 |
+
"Let's just stick to the `user` role for now and send our first message to the endpoint!\n",
|
79 |
+
"\n",
|
80 |
+
"If we check the documentation, we'll see that it expects it in a list of prompt objects - so we'll be sure to do that!"
|
81 |
+
]
|
82 |
+
},
|
83 |
+
{
|
84 |
+
"cell_type": "code",
|
85 |
+
"execution_count": 3,
|
86 |
+
"metadata": {
|
87 |
+
"id": "g0AL4VTwyWLN"
|
88 |
+
},
|
89 |
+
"outputs": [
|
90 |
+
{
|
91 |
+
"data": {
|
92 |
+
"text/plain": [
|
93 |
+
"ChatCompletion(id='chatcmpl-9D4ZMhNvYSJaf3Rx8cDkyW2ypwPog', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='A woodchuck could chuck as much wood as a woodchuck would chuck if a woodchuck could chuck wood.', role='assistant', function_call=None, tool_calls=None))], created=1712902856, model='gpt-3.5-turbo-0125', object='chat.completion', system_fingerprint='fp_c2295e73ad', usage=CompletionUsage(completion_tokens=25, prompt_tokens=25, total_tokens=50))"
|
94 |
+
]
|
95 |
+
},
|
96 |
+
"execution_count": 3,
|
97 |
+
"metadata": {},
|
98 |
+
"output_type": "execute_result"
|
99 |
+
}
|
100 |
+
],
|
101 |
+
"source": [
|
102 |
+
"from openai import OpenAI\n",
|
103 |
+
"\n",
|
104 |
+
"client = OpenAI(api_key=openai.api_key)\n",
|
105 |
+
"\n",
|
106 |
+
"YOUR_PROMPT = \"How much wood could a woodchuck chuck if a woodchuck could chuck wood?\"\n",
|
107 |
+
"\n",
|
108 |
+
"client.chat.completions.create(\n",
|
109 |
+
" model=\"gpt-3.5-turbo\",\n",
|
110 |
+
" messages=[{\"role\" : \"user\", \"content\" : YOUR_PROMPT}]\n",
|
111 |
+
")"
|
112 |
+
]
|
113 |
+
},
|
114 |
+
{
|
115 |
+
"cell_type": "markdown",
|
116 |
+
"metadata": {
|
117 |
+
"id": "FD_Z64hGy6RV"
|
118 |
+
},
|
119 |
+
"source": [
|
120 |
+
"As you can see, the prompt comes back with a tonne of information that we can use when we're building our applications!\n",
|
121 |
+
"\n",
|
122 |
+
"Let's focus on extending that a bit, and incorporate a `system` message as well!\n",
|
123 |
+
"\n",
|
124 |
+
"Also, we'll be building some helper functions to display the prompts with Markdown!\n",
|
125 |
+
"\n",
|
126 |
+
"We'll also wrap our prompts so we don't have to keep making dictionaries for them!"
|
127 |
+
]
|
128 |
+
},
|
129 |
+
{
|
130 |
+
"cell_type": "code",
|
131 |
+
"execution_count": 4,
|
132 |
+
"metadata": {
|
133 |
+
"id": "QSQMFfWKbsqT"
|
134 |
+
},
|
135 |
+
"outputs": [],
|
136 |
+
"source": [
|
137 |
+
"from IPython.display import display, Markdown\n",
|
138 |
+
"\n",
|
139 |
+
"def get_response(messages: str, model: str = \"gpt-3.5-turbo\") -> str:\n",
|
140 |
+
" return client.chat.completions.create(\n",
|
141 |
+
" model=model,\n",
|
142 |
+
" messages=messages\n",
|
143 |
+
" )\n",
|
144 |
+
"\n",
|
145 |
+
"def wrap_prompt(message: str, role: str) -> dict:\n",
|
146 |
+
" return {\"role\": role, \"content\": message}\n",
|
147 |
+
"\n",
|
148 |
+
"def m_print(message: str) -> str:\n",
|
149 |
+
" display(Markdown(message.choices[0].message.content))"
|
150 |
+
]
|
151 |
+
},
|
152 |
+
{
|
153 |
+
"cell_type": "code",
|
154 |
+
"execution_count": 5,
|
155 |
+
"metadata": {
|
156 |
+
"colab": {
|
157 |
+
"base_uri": "https://localhost:8080/",
|
158 |
+
"height": 348
|
159 |
+
},
|
160 |
+
"id": "7aEd_p1sbsqT",
|
161 |
+
"outputId": "d32cf1ff-d4aa-48a9-ebf5-f670c1750110"
|
162 |
+
},
|
163 |
+
"outputs": [
|
164 |
+
{
|
165 |
+
"data": {
|
166 |
+
"text/markdown": [
|
167 |
+
"Sure! Here's a Python function that calculates the Nth Fibonacci number using recursion:\n",
|
168 |
+
"\n",
|
169 |
+
"```python\n",
|
170 |
+
"def fibonacci(n):\n",
|
171 |
+
" if n <= 0:\n",
|
172 |
+
" return \"Invalid input. Please enter a positive integer.\"\n",
|
173 |
+
" elif n == 1:\n",
|
174 |
+
" return 0\n",
|
175 |
+
" elif n == 2:\n",
|
176 |
+
" return 1\n",
|
177 |
+
" else:\n",
|
178 |
+
" return fibonacci(n-1) + fibonacci(n-2)\n",
|
179 |
+
"\n",
|
180 |
+
"n = 10\n",
|
181 |
+
"result = fibonacci(n)\n",
|
182 |
+
"print(f\"The {n}th Fibonacci number is: {result}\")\n",
|
183 |
+
"```\n",
|
184 |
+
"\n",
|
185 |
+
"You can replace the value of `n` with any positive integer to get the corresponding Fibonacci number."
|
186 |
+
],
|
187 |
+
"text/plain": [
|
188 |
+
"<IPython.core.display.Markdown object>"
|
189 |
+
]
|
190 |
+
},
|
191 |
+
"metadata": {},
|
192 |
+
"output_type": "display_data"
|
193 |
+
}
|
194 |
+
],
|
195 |
+
"source": [
|
196 |
+
"system_prompt = wrap_prompt(\"You are a Python Programmer.\", \"system\")\n",
|
197 |
+
"user_prompt = wrap_prompt(\"Can you write me a function in Python that calculates the Nth Fibonacci number?\", \"user\")\n",
|
198 |
+
"\n",
|
199 |
+
"openai_response = get_response([system_prompt, user_prompt])\n",
|
200 |
+
"m_print(openai_response)"
|
201 |
+
]
|
202 |
+
},
|
203 |
+
{
|
204 |
+
"cell_type": "code",
|
205 |
+
"execution_count": 6,
|
206 |
+
"metadata": {
|
207 |
+
"colab": {
|
208 |
+
"base_uri": "https://localhost:8080/"
|
209 |
+
},
|
210 |
+
"id": "N7EproZ5ztKt",
|
211 |
+
"outputId": "a7ca3b15-87cf-4c27-8173-6534d9f70421"
|
212 |
+
},
|
213 |
+
"outputs": [
|
214 |
+
{
|
215 |
+
"name": "stdout",
|
216 |
+
"output_type": "stream",
|
217 |
+
"text": [
|
218 |
+
"ChatCompletion(id='chatcmpl-9D4cOPbhi0rrPQGQC1bDUrDBUNTGs', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='Sure! Here\\'s a Python function that calculates the Nth Fibonacci number using recursion:\\n\\n```python\\ndef fibonacci(n):\\n if n <= 0:\\n return \"Invalid input. Please enter a positive integer.\"\\n elif n == 1:\\n return 0\\n elif n == 2:\\n return 1\\n else:\\n return fibonacci(n-1) + fibonacci(n-2)\\n\\nn = 10\\nresult = fibonacci(n)\\nprint(f\"The {n}th Fibonacci number is: {result}\")\\n```\\n\\nYou can replace the value of `n` with any positive integer to get the corresponding Fibonacci number.', role='assistant', function_call=None, tool_calls=None))], created=1712903044, model='gpt-3.5-turbo-0125', object='chat.completion', system_fingerprint='fp_b28b39ffa8', usage=CompletionUsage(completion_tokens=129, prompt_tokens=33, total_tokens=162))\n"
|
219 |
+
]
|
220 |
+
}
|
221 |
+
],
|
222 |
+
"source": [
|
223 |
+
"print(openai_response)"
|
224 |
+
]
|
225 |
+
},
|
226 |
+
{
|
227 |
+
"cell_type": "markdown",
|
228 |
+
"metadata": {
|
229 |
+
"id": "YdhHoeo5zxbl"
|
230 |
+
},
|
231 |
+
"source": [
|
232 |
+
"You can add the `assistant` role to send messages as-if they're from the model itself - which can help us do \"few-shot\" prompt engineering!\n",
|
233 |
+
"\n",
|
234 |
+
"That's where we show the LLM a few examples of the output we'd like to see to help guide the model to our desired outputs!\n",
|
235 |
+
"\n",
|
236 |
+
"Let's see it in action!"
|
237 |
+
]
|
238 |
+
},
|
239 |
+
{
|
240 |
+
"cell_type": "code",
|
241 |
+
"execution_count": 7,
|
242 |
+
"metadata": {
|
243 |
+
"id": "DLCT0o5i0AEw"
|
244 |
+
},
|
245 |
+
"outputs": [],
|
246 |
+
"source": [
|
247 |
+
"prompt_list = [\n",
|
248 |
+
" wrap_prompt(\"You are an expert food critic, and also a pirate.\", \"system\"),\n",
|
249 |
+
" wrap_prompt(\"Hi, are apples any good?\", \"user\"),\n",
|
250 |
+
" wrap_prompt(\"Ahoy matey. Apples be the finest of the edible treasures.\", \"assistant\"),\n",
|
251 |
+
" wrap_prompt(\"Hello there, is the combination of cheese and plums a good combination?\", \"user\"),\n",
|
252 |
+
" wrap_prompt(\"Arrrrrr. That be a dish only land-lubbers could enjoy. If that grub be on my ship, I'd toss it overboard!\", \"assistant\")\n",
|
253 |
+
"]"
|
254 |
+
]
|
255 |
+
},
|
256 |
+
{
|
257 |
+
"cell_type": "markdown",
|
258 |
+
"metadata": {
|
259 |
+
"id": "i1k3xWIP0x5u"
|
260 |
+
},
|
261 |
+
"source": [
|
262 |
+
"Now we can append our *actual* prompt to the list!"
|
263 |
+
]
|
264 |
+
},
|
265 |
+
{
|
266 |
+
"cell_type": "code",
|
267 |
+
"execution_count": 8,
|
268 |
+
"metadata": {
|
269 |
+
"colab": {
|
270 |
+
"base_uri": "https://localhost:8080/",
|
271 |
+
"height": 64
|
272 |
+
},
|
273 |
+
"id": "CFeNREBW03G_",
|
274 |
+
"outputId": "4ff66e0f-b38d-486d-d125-dcb8b876b150"
|
275 |
+
},
|
276 |
+
"outputs": [
|
277 |
+
{
|
278 |
+
"data": {
|
279 |
+
"text/markdown": [
|
280 |
+
"Aye, pears be a fine addition to a salad, adding a sweet and juicy element to balance the savory and crunchy components. You won't be walkin' the plank for addin' them to your salad, that be for sure!"
|
281 |
+
],
|
282 |
+
"text/plain": [
|
283 |
+
"<IPython.core.display.Markdown object>"
|
284 |
+
]
|
285 |
+
},
|
286 |
+
"metadata": {},
|
287 |
+
"output_type": "display_data"
|
288 |
+
}
|
289 |
+
],
|
290 |
+
"source": [
|
291 |
+
"prompt_list.append(wrap_prompt(\"Are pears a good choice for a salad?\", \"user\"))\n",
|
292 |
+
"\n",
|
293 |
+
"openai_response = get_response(prompt_list)\n",
|
294 |
+
"m_print(openai_response)"
|
295 |
+
]
|
296 |
+
},
|
297 |
+
{
|
298 |
+
"cell_type": "markdown",
|
299 |
+
"metadata": {
|
300 |
+
"id": "ZJ2IuNHT1E8r"
|
301 |
+
},
|
302 |
+
"source": [
|
303 |
+
"Feel free to send some prompts and try out different things!\n",
|
304 |
+
"\n",
|
305 |
+
"Let us know if you find anything interesting!"
|
306 |
+
]
|
307 |
+
}
|
308 |
+
],
|
309 |
+
"metadata": {
|
310 |
+
"colab": {
|
311 |
+
"provenance": []
|
312 |
+
},
|
313 |
+
"kernelspec": {
|
314 |
+
"display_name": "open_ai",
|
315 |
+
"language": "python",
|
316 |
+
"name": "python3"
|
317 |
+
},
|
318 |
+
"language_info": {
|
319 |
+
"codemirror_mode": {
|
320 |
+
"name": "ipython",
|
321 |
+
"version": 3
|
322 |
+
},
|
323 |
+
"file_extension": ".py",
|
324 |
+
"mimetype": "text/x-python",
|
325 |
+
"name": "python",
|
326 |
+
"nbconvert_exporter": "python",
|
327 |
+
"pygments_lexer": "ipython3",
|
328 |
+
"version": "3.11.8"
|
329 |
+
},
|
330 |
+
"orig_nbformat": 4
|
331 |
+
},
|
332 |
+
"nbformat": 4,
|
333 |
+
"nbformat_minor": 0
|
334 |
+
}
|
app/hello_world.ipynb
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 1,
|
6 |
+
"metadata": {},
|
7 |
+
"outputs": [],
|
8 |
+
"source": [
|
9 |
+
"import pandas as pd\n",
|
10 |
+
"import numpy as np\n",
|
11 |
+
"import matplotlib.pyplot as plt"
|
12 |
+
]
|
13 |
+
},
|
14 |
+
{
|
15 |
+
"cell_type": "code",
|
16 |
+
"execution_count": 2,
|
17 |
+
"metadata": {},
|
18 |
+
"outputs": [
|
19 |
+
{
|
20 |
+
"data": {
|
21 |
+
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGzCAYAAADHdKgcAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA5+klEQVR4nO3de3zO9R//8eeO/Jprzm0s1kJ8Q4vUt4VUQ6YDlaj0ZRShfCtKzTehA33LIUnli7b11Vc6kYrRcohyiDIjYox0YSyHDZsdvH9/9HP9XHZgc12uXfs87rfb+5bP+/P+fD6v67Nr7bnP5/255iPJCAAAwEJ8PV0AAADApUYAAgAAlkMAAgAAlkMAAgAAlkMAAgAAlkMAAgAAlkMAAgAAlkMAAgAAlkMAAgAAlkMAAjxs2bJlWrZsmWM5PDxcxhj17dvXrccdPXq0jHH+IPj09HTFx8e79bhS8a8xPj5e2dnZbj+2q1yqc+UK8fHxSk9P93QZbtO3b18ZYxQeHu7pUuBFCECo8M78zy0nJ0f169cvsn7ZsmVKTU31QGWQpJiYGI0ePdrTZRSrItcGwLMIQPAaVatW1QsvvODpMiq1pk2basCAAWXapmvXrhozZkyZttmzZ4+qVq2q//73v2XarqzKUxsAayAAwWv88ssvGjBggOrVq+fW41StWtWt+6/I8vLyVFBQ4Lb9+/n5KSAgQJJ06tQpnT592m3HqqjOPgcAPIcABK8xbtw4+fn5XdBVID8/P7344otKS0tTbm6u0tPT9dprrykwMNBpXHp6ur766it17txZP/30k3JycvT444+rQ4cOMsbogQce0EsvvaQ//vhDWVlZ+vTTTxUcHKzAwEBNnjxZGRkZys7O1gcffFBk37Gxsfruu++UkZGh3NxcbdmyRYMGDSrz646NjZUxRtddd12RdXFxcSooKCj21uDZ2rZtq3Xr1iknJ0dpaWkaOHBgsePOndfi7++vl156Sdu3b1dOTo4yMzO1cuVKdezYUdJfc0uefPJJSZIxxtGk/z/PZ/jw4XrqqaeUlpamU6dO6Zprril1nlNERISSkpJ0/Phx2e12jRo1ymn9ma9Nhw4dnPrP3WdptUmSj4+PnnrqKW3evFk5OTk6cOCA3n//fdWoUaNITf/617+0d+9enThxQkuXLtU111xT6vk+t6bizkFAQIDGjh2r9evX6+jRozp+/Li+//573XrrrSXuY8CAAY739Lp169SmTZsix+zWrZtSU1OVk5Oj1NRUde/evdjaLrvsMk2YMEG///67cnNztW3bNg0fPrzIOGOMpk6dqh49emjLli06efKkfvzxR7Vo0UKSNHDgQO3YsUM5OTlatmzZeefh3H///TLG6JZbbimybuDAgTLGqHnz5pKkli1bKj4+Xjt37lROTo7279+vWbNmqVatWqUe40zdxd3+LG7uVvXq1TV58mTHudixY4dGjBghHx8fp3G9evXS+vXrlZWVpWPHjmnTpk365z//ed5aUDH5e7oA4EKlp6frww8/1IABA/T6669r//79JY6dOXOmYmNj9emnn2rixIn6+9//rpEjR+pvf/ub7rvvPqexTZs21Zw5czR9+nTNmDFDv/32m2NdXFyccnJy9Prrr6tx48YaOnSo8vPzdfr0adWsWVNjxozRTTfdpH79+ik9PV2vvPKKY9vBgwdry5YtWrBggQoKCnT33Xfrvffek6+vr959990Lft2fffaZpk2bpt69e2vjxo1O63r37q3ly5dr3759JW7fokULLVmyRIcOHdKYMWPk7++vsWPHKiMj47zHHjNmjOLi4jRz5kytW7dOwcHBatOmjVq3bq3k5GRNnz5d9evXV+fOnfXII48Uu49+/fqpatWq+s9//qNTp07p8OHD8vUt/ncvPz8/JSUlac2aNRoxYoS6dOmil19+Wf7+/mWey3O+2qZPn67Y2FjFx8fr7bffVkREhJ588km1atVKbdu2dVwJe/nllzVq1Ch98803WrhwoVq3bq0lS5YUCbylKe4cBAcH67HHHtOcOXM0Y8YM2Ww2Pfroo1q8eLFuvPFGpaSkOO3j4Ycfls1m0/Tp02WM0YgRI/TFF1/oqquuctTaqVMnff755/r1118VFxen2rVrKz4+Xn/88UeRmhYsWKDbbrtNs2bN0saNG3XHHXdowoQJCgsL07Bhw5zGtm/fXvfcc4+mTZsm6a/vi6+//lpvvPGGhgwZonfffVc1a9bUiBEj9MEHHyg6OrrEc/HNN98oOztbPXv21Pfff++0rlevXtq8ebO2bNnieD1XXXWV4uPjdeDAATVv3lwDBw5U8+bNddNNN13w+S/N//k//0crVqxQWFiYpk+frt9//10333yzxo8fr3r16umZZ56RJHXs2FEff/yx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ys7O9nQZAACgDGw22wXNkyQAFaN+/fqy2+2eLgMAAJRDWFjYeUMQAagYZ678hIWFcRUIAAAvYbPZZLfbL+hnNwGoFNnZ2QQgAAAqISZBAwAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAyyEAAQAAy/H3dAEAcKlNTF3t6RLKbHjLKE+XAFQqXAECAACWQwACAACWQwACAACWQwACAACWQwACAACW49EA1L59ey1YsEB2u13GGHXr1s1pvTGm2Pbss8+WuM/Ro0cXGb9161Z3vxQAAOBFPBqAgoKClJKSoieeeKLY9aGhoU6tX79+On36tD7//PNS97t582an7dq1a+eO8gEAgJfy6OcAJSUlKSkpqcT1GRkZTsvdunXTsmXLlJ6eXup+CwoKimwLAABwhtfMAbr88st15513atasWecd26RJE9ntdu3cuVOzZ89WgwYNSh0fGBgom83m1AAAQOXlNQGob9++ys7O1hdffFHquLVr1yo2NlZdunTR4MGDFRERoZUrV6patWolbhMXF6esrCxHs9vtri4fAABUIF4TgPr376+PPvpIp06dKnVcUlKSPvvsM6WmpmrJkiXq2rWratSooZ49e5a4zfjx4xUcHOxoYWFhri4fAABUIF7xt8DatWunZs2aqVevXmXe9tixY9q+fbsaN25c4pi8vDzl5eVdTIkAAMCLeMUVoEcffVTr16/Xpk2byrxtUFCQGjVqpP3797uhMgAA4I08/hh8ZGSkIiMjJUkRERGKjIx0mrRss9n0wAMPaObMmcXuIzk52ekx+jfffFO33HKLwsPDFRUVpXnz5qmwsFBz5sxx74sBAABew6O3wNq0aaPly5c7lidPnixJSkhIUL9+/SRJDz74oHx8fEoMMI0aNVKdOnUcy1dccYXmzJmj2rVr69ChQ1q1apVuuukmZWZmuu+FAAAAr+IjyXi6iIrGZrMpKytLwcHBys7O9nQ5AFxsYupqT5dQZsNbRnm6BKDCK8vPb6+YAwQAAOBKBCAAAGA5BCAAAGA5XvE5QAAqLm+cTwMAXAECAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACWQwACAACW4+/pAgAA5zcxdbWnSyiz4S2jPF0CUCKuAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMshAAEAAMvxaABq3769FixYILvdLmOMunXr5rQ+Pj5exhintmjRovPud8iQIUpPT1dOTo7WrFmjG264wV0vAQAAeCGPBqCgoCClpKToiSeeKHHMokWLFBoa6mgPPfRQqfvs2bOnJk2apLFjx6p169ZKSUnR4sWLVbduXVeXDwAAvJS/Jw+elJSkpKSkUsecOnVKGRkZF7zPYcOGacaMGUpISJAkDRo0SHfeeaf69++vf//73xdTLgAAqCQq/BygW2+9VRkZGdq2bZveffdd1apVq8SxAQEBuv7665WcnOzoM8YoOTlZUVFRJW4XGBgom83m1AAAQOVVoQNQUlKS+vTpo+joaD3//PPq0KGDFi1aJF/f4suuU6eO/P39i1wxysjIUGhoaInHiYuLU1ZWlqPZ7XaXvg4AAFCxePQW2PnMnTvX8e/Nmzdr06ZN2rVrl2699VYtXbrUZccZP368Jk2a5Fi22WyEIAAAKrEKfQXoXOnp6Tp06JAaN25c7PrMzEwVFBQoJCTEqT8kJEQHDhwocb95eXnKzs52agAAoPLyqgAUFham2rVra//+/cWuz8/P14YNGxQdHe3o8/HxUXR0tFavXn2pygQAABWcxx+Dj4yMVGRkpCQpIiJCkZGRatCggYKCgvTGG2/o73//u8LDw3X77bfryy+/VFpamhYvXuzYR3JystNj9JMmTdKAAQPUp08fNWvWTO+9956CgoIUHx9/yV8fAAComDw6B6hNmzZavny5Y3ny5MmSpISEBA0ePFjXXnut+vbtqxo1amjfvn1asmSJRo0apby8PMc2jRo1Up06dRzLn3zyierWrauXX35ZoaGh2rhxo7p06aKDBw9estcFAAAqNh9JxtNFVDQ2m01ZWVkKDg5mPhBwHhNTub2M4g1vWfLHjwDuUJaf3141BwgAAMAVCEAAAMByCEAAAMByCEAAAMByCEAAAMByCEAAAMByCEAAAMByCEAAAMByCEAAAMByCEAAAMBy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V7VgwQKlpqaqT58+ql+/vrp3717iPocNG6YZM2YoISFBW7du1aBBg3Ty5En179//ousFAACVQ7kC0MSJE/XUU0+5uhYnERERqlevnpKTkx19WVlZWrt2raKioordJiAgQNdff73TNsYYJScnl7iNJAUGBspmszk1AABQeZXrFli7du102223KSYmRlu2bFF+fr7T+vvvv/+iCwsNDZUkZWRkOPVnZGQ41p2rTp068vf3L3abZs2alXisuLg4jRkz5uIKBgAAXqNcAejo0aPFztnxVuPHj9ekSZMcyzabTXa73YMVAQAAdypXALoU82kOHDggSQoJCXH8+8zyxo0bi90mMzNTBQUFCgkJceo/dx/nysvLU15e3sUXDQAAvEK55gBJkp+fn6KjozVw4EBVq1ZNklSvXj0FBQW5pLD09HTt37/f6TOFbDab/v73v2v16tXFbpOfn68NGzY4bePj46Po6OgStwEAANZTritADRs2VFJSkho2bKgqVaro22+/1fHjx/X888+rSpUqGjx48AXtJygoyOlzfSIiIhQZGanDhw9r7969euutt/Tiiy9qx44djsfg9+3b5/TUWHJysubNm6dp06ZJkiZNmqTExEStX79e69at09NPP62goCDFx8eX56UCAIBKqFwBaMqUKVq/fr0iIyP1559/OvrnzZunGTNmXPB+2rRpo+XLlzuWJ0+eLElKSEhQv3799MYbbygoKEj/+c9/VKNGDa1atUpdunRx+gygRo0aqU6dOo7lTz75RHXr1tXLL7+s0NBQbdy4UV26dNHBgwfL81IBAEAl5CPJlHWjzMxM3Xzzzdq+fbuysrIUGRmp9PR0hYeH69dff3XZbTBPsdlsysrKUnBwsLKzsz1dDixkYiq3agFPGt6y5I9MQcVXlp/f5ZoD5OvrKz8/vyL9V1xxBYEBAABUeOUKQEuWLNHTTz/tWDbGKCgoSGPHjtXChQtdVRsAAIBblGsO0PDhw7V48WJt2bJFVatW1f/+9z81adJEmZmZeuihh1xdIwAAgEuVKwDZ7XZFRkbqwQcf1LXXXqtq1app1qxZ+uijj5Sbm+vqGgEAAFyqXAFIkgoLC/XRRx/po48+cmU9AAAAbleuAPSPf/yj1PX//e9/y1UMAADApVDuzwE6W0BAgC677DLl5eXp5MmTBCAAAFChlespsFq1ajk1m82m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717icQIDA1WlShXHss1mc/qvqwX6+rllvwAAeAN3/Xwty34rdACqU6eO/P39lZGR4dSfkZGhZs2aFbtNaGhoseNDQ0NLPE5cXJzGjBlTpN9ut5e9aAAAUKons7Lcun+bzebdV4AulfHjxxe5alSrVi0dPnzYQxV5B5vNJrvdrrCwMLfcKkTxOO+XHufcMzjvl15lOOc2m0379u0777gKHYAyMzNVUFCgkJAQp/6QkBAdOHCg2G0OHDhQpvGSlJeXp7y8PKc+b/3Ce0J2djbnywM475ce59wzOO+Xnjef8wutu0I/BZafn68NGzYoOjra0efj46Po6GitXl38ROLVq1c7jZekTp06lTgeAABYk6nIrWfPniYnJ8f06dPHNGvWzLz//vvm8OHD5vLLLzeSTGJiohk3bpxjfFRUlMnLyzPDhg0zTZs2NaNHjzanTp0yzZs39/hrqWzNZrMZY4yx2Wwer8VKjfPOObdK47xzzt3cPF7AedsTTzxhdu/ebXJzc82aNWvMjTfe6Fi3bNkyEx8f7zS+R48eZtu2bSY3N9ekpqaamJgYj7+GytgCAwPN6NGjTWBgoMdrsVLjvHPOrdI475xzd7YK/zlAAAAArlah5wABAAC4AwEIAABYDgEIAABYDgEIAABYDgEIAABYDgEILhEeHq6ZM2dq165dOnnypNLS0jRmzBgFBAR4urRKbeTIkfrhhx904sQJHTlyxNPlVFpDhgxRenq6cnJytGbNGt1www2eLqlSa9++vRYsWCC73S5jjLp16+bpkiq9F154QevWrVNWVpYyMjI0b948XX311Z4uy60IQHCJZs2aydfXV48//riaN2+uZ555RoMGDdK4ceM8XVqlFhgYqE8//VTvvfeep0uptHr27KlJkyZp7Nixat26tVJSUrR48WLVrVvX06VVWkFBQUpJSdETTzzh6VIso0OHDpo2bZpuuukmderUSQEBAVqyZIkuu+wyT5fmVh7/MCJa5WzPPvus2blzp8frsELr27evOXLkiMfrqIxtzZo1ZurUqY5lHx8f88cff5jnn3/e47VZoRljTLdu3Txeh9VanTp1jDHGtG/f3uO1uKtxBQhuU716dR0+fNjTZQDlFhAQoOuvv17JycmOPmOMkpOTFRUV5cHKAPeqXr26JFXq/4cTgOAWjRo10tChQzV9+nRPlwKUW506deTv76+MjAyn/oyMDIWGhnqoKsC9fHx89NZbb2nVqlXasmWLp8txGwIQSjV+/HgZY0ptTZs2ddqmfv36SkpK0qeffqqZM2d6qHLvVZ5zDgCuMm3aNLVo0UIPPvigp0txK39PF4CKbeLEiUpISCh1zK5duxz/rlevnpYtW6Yff/xRAwcOdHN1lVNZzzncJzMzUwUFBQoJCXHqDwkJ0YEDBzxUFeA+U6dO1V133aVbbrlFdrvd0+W4FQEIpcrMzFRmZuYFja1fv76WLVumDRs2qF+/fjLGuLm6yqks5xzulZ+frw0bNig6OlpffvmlpL9uD0RHR+udd97xcHWAa02dOlX33nuvbr31Vu3evdvT5bgdAQguUb9+fS1fvlx79uzRs88+6/SI8LnzJ+A6DRo0UK1atdSwYUP5+fkpMjJSkpSWlqYTJ054uLrKYdKkSUpMTNT69eu1bt06Pf300woKClJ8fLynS6u0goKC1LhxY8dyRESEIiMjdfjwYe3du9eDlVVe06ZN08MPP6xu3bopOzvbcdXz2LFjys3N9XB17uPxR9Fo3t/69u1rSuLp2ipzi4+PL/acd+jQweO1Vab2xBNPmN27d5vc3FyzZs0ac+ONN3q8psrcOnToUOz7Oj4+3uO1VdZWkr59+3q8Nnc1n//3DwAAAMvgKTAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5BCAAAGA5/xdkG2K4b6jvCwAAAABJRU5ErkJggg==",
|
22 |
+
"text/plain": [
|
23 |
+
"<Figure size 640x480 with 1 Axes>"
|
24 |
+
]
|
25 |
+
},
|
26 |
+
"metadata": {},
|
27 |
+
"output_type": "display_data"
|
28 |
+
}
|
29 |
+
],
|
30 |
+
"source": [
|
31 |
+
"np.random.seed(0)\n",
|
32 |
+
"\n",
|
33 |
+
"values = np.random.randn(100) # array of normally distributed random numbers\n",
|
34 |
+
"s = pd.Series(values) # generate a pandas series\n",
|
35 |
+
"s.plot(kind='hist', title='Normally distributed random values') # hist computes distribution\n",
|
36 |
+
"plt.show() "
|
37 |
+
]
|
38 |
+
},
|
39 |
+
{
|
40 |
+
"cell_type": "code",
|
41 |
+
"execution_count": null,
|
42 |
+
"metadata": {},
|
43 |
+
"outputs": [],
|
44 |
+
"source": []
|
45 |
+
}
|
46 |
+
],
|
47 |
+
"metadata": {
|
48 |
+
"kernelspec": {
|
49 |
+
"display_name": "llmops-course",
|
50 |
+
"language": "python",
|
51 |
+
"name": "python3"
|
52 |
+
},
|
53 |
+
"language_info": {
|
54 |
+
"codemirror_mode": {
|
55 |
+
"name": "ipython",
|
56 |
+
"version": 3
|
57 |
+
},
|
58 |
+
"file_extension": ".py",
|
59 |
+
"mimetype": "text/x-python",
|
60 |
+
"name": "python",
|
61 |
+
"nbconvert_exporter": "python",
|
62 |
+
"pygments_lexer": "ipython3",
|
63 |
+
"version": "3.11.8"
|
64 |
+
}
|
65 |
+
},
|
66 |
+
"nbformat": 4,
|
67 |
+
"nbformat_minor": 2
|
68 |
+
}
|
app/hello_world.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
print("hello world! let's do some ml ops!")
|