excercise wk1
This commit is contained in:
266
community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb
Normal file
266
community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb
Normal file
@@ -0,0 +1,266 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "markdown",
|
||||||
|
"id": "fe12c203-e6a6-452c-a655-afb8a03a4ff5",
|
||||||
|
"metadata": {},
|
||||||
|
"source": [
|
||||||
|
"# End of week 1 exercise\n",
|
||||||
|
"\n",
|
||||||
|
"To demonstrate your familiarity with OpenAI API, and also Ollama, build a tool that takes a technical question, \n",
|
||||||
|
"and responds with an explanation. This is a tool that you will be able to use yourself during the course!"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 2,
|
||||||
|
"id": "c1070317-3ed9-4659-abe3-828943230e03",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# imports\n",
|
||||||
|
"import os\n",
|
||||||
|
"import json\n",
|
||||||
|
"from dotenv import load_dotenv\n",
|
||||||
|
"from IPython.display import Markdown\n",
|
||||||
|
"from openai import OpenAI"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "4a456906-915a-4bfd-bb9d-57e505c5093f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# constants\n",
|
||||||
|
"\n",
|
||||||
|
"MODEL_GPT = 'gpt-4o-mini'\n",
|
||||||
|
"MODEL_LLAMA = 'llama3.2'\n",
|
||||||
|
"OLLAMA_BASE_URL = \"http://localhost:11434/v1\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "a8d7923c-5f28-4c30-8556-342d7c8497c1",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"API key looks good so far\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# set up environment\n",
|
||||||
|
"\n",
|
||||||
|
"load_dotenv(override=True)\n",
|
||||||
|
"api_key = os.getenv('OPENAI_API_KEY')\n",
|
||||||
|
"\n",
|
||||||
|
"if api_key and api_key.startswith('sk-proj-') and len(api_key)>10:\n",
|
||||||
|
" print(\"API key looks good so far\")\n",
|
||||||
|
"else:\n",
|
||||||
|
" print(\"There might be a problem with your API key? Please visit the troubleshooting notebook!\")\n",
|
||||||
|
" \n",
|
||||||
|
"openai = OpenAI()\n",
|
||||||
|
"ollama = OpenAI(base_url=OLLAMA_BASE_URL, api_key='ollama')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 5,
|
||||||
|
"id": "3f0d0137-52b0-47a8-81a8-11a90a010798",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# here is the question; type over this to ask something new\n",
|
||||||
|
"\n",
|
||||||
|
"question = \"\"\"\n",
|
||||||
|
"Please explain what this code does and why:\n",
|
||||||
|
"yield from {book.get(\"author\") for book in books if book.get(\"author\")}\n",
|
||||||
|
"\"\"\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 6,
|
||||||
|
"id": "df0d958f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"system_prompt = \"\"\"You are individual that possesses a unique\n",
|
||||||
|
"and highly valuable combination of deep technical\n",
|
||||||
|
"expertise and excellent communication skills.\n",
|
||||||
|
"You grasp complex, specialized concepts and then distill\n",
|
||||||
|
"them into simple, understandable terms for people without\n",
|
||||||
|
"the same technical background.\n",
|
||||||
|
"\n",
|
||||||
|
"Present your answer as markdown\n",
|
||||||
|
"\"\"\""
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 7,
|
||||||
|
"id": "13506dd4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"messages = [\n",
|
||||||
|
" {\"role\": \"system\", \"content\": system_prompt},\n",
|
||||||
|
" {\"role\": \"user\", \"content\": question}\n",
|
||||||
|
" ]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 8,
|
||||||
|
"id": "60ce7000-a4a5-4cce-a261-e75ef45063b4",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/markdown": [
|
||||||
|
"Certainly! Let's break down the code you've provided:\n",
|
||||||
|
"\n",
|
||||||
|
"### Code Explanation\n",
|
||||||
|
"\n",
|
||||||
|
"```python\n",
|
||||||
|
"yield from {book.get(\"author\") for book in books if book.get(\"author\")}\n",
|
||||||
|
"```\n",
|
||||||
|
"\n",
|
||||||
|
"#### Components of the Code:\n",
|
||||||
|
"\n",
|
||||||
|
"1. **Set Comprehension**:\n",
|
||||||
|
" - `{book.get(\"author\") for book in books if book.get(\"author\")}`: This part of the code is a **set comprehension**. It creates a set of authors by iterating through a collection called `books`.\n",
|
||||||
|
" - `book.get(\"author\")`: This method retrieves the value associated with the key `\"author\"` from each `book` dictionary. If the specified key does not exist, `None` is returned.\n",
|
||||||
|
" - `if book.get(\"author\")`: This condition filters out any authors that are `None` or any falsy value, ensuring that only valid authors are included in the set.\n",
|
||||||
|
"\n",
|
||||||
|
"2. **Yielding Values**:\n",
|
||||||
|
" - `yield from`: This keyword is used in Python to yield values from a generator or an iterable. In this context, it takes the set created from the set comprehension and yields each author one at a time.\n",
|
||||||
|
"\n",
|
||||||
|
"### What the Code Does\n",
|
||||||
|
"\n",
|
||||||
|
"- The code iterates over a collection of `books`, each of which is expected to be a dictionary. For each book, it checks if the `\"author\"` key exists and has a valid value (not `None` or falsy).\n",
|
||||||
|
"- It collects all unique authors into a set to ensure no duplicates are included. The use of a set here also makes looking up authors efficient.\n",
|
||||||
|
"- Finally, it yields each author one at a time, allowing the consuming code to process each author individually.\n",
|
||||||
|
"\n",
|
||||||
|
"### Why Use This Code?\n",
|
||||||
|
"\n",
|
||||||
|
"- **Unique Values**: Using a set guarantees that each author is only yielded once, even if multiple books have the same author.\n",
|
||||||
|
"- **Memory Efficiency**: Using `yield from` allows handling potentially large collections of authors efficiently without having to store them all in memory at once.\n",
|
||||||
|
"- **Ease of Use**: This pattern is useful for generating a stream of results where the number of authors is not known in advance, and the consumer can process each author as it arrives.\n",
|
||||||
|
"\n",
|
||||||
|
"### Summary\n",
|
||||||
|
"\n",
|
||||||
|
"This code is effective for extracting unique authors from a list of book dictionaries, yielding each author for further processing without duplicates and in an efficient manner."
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
"<IPython.core.display.Markdown object>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Get gpt-4o-mini to answer, with streaming\n",
|
||||||
|
"\n",
|
||||||
|
"response = openai.chat.completions.create(model=MODEL_GPT, messages=messages)\n",
|
||||||
|
"result = response.choices[0].message.content\n",
|
||||||
|
"display(Markdown(result))\n",
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 9,
|
||||||
|
"id": "8f7c8ea8-4082-4ad0-8751-3301adcf6538",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/markdown": [
|
||||||
|
"**Understanding Recursive Yield**\n",
|
||||||
|
"\n",
|
||||||
|
"```python\n",
|
||||||
|
"yield from {book.get(\"author\") for book in books if book.get(\"author\")}\n",
|
||||||
|
"```\n",
|
||||||
|
"is a piece of Python code that utilizes the `yield from` syntax to delegate iterations over a sub-generators. This allows us to generate an iterable sequence one step at a time, avoiding memory overhead.\n",
|
||||||
|
"\n",
|
||||||
|
"### Breakdown\n",
|
||||||
|
"\n",
|
||||||
|
"* `{book.get(\"author\") for book in books if book.get(\"author\")}` is a generator expression:\n",
|
||||||
|
" * It defines a small, anonymous function (lambda-like) that takes `books` as input.\n",
|
||||||
|
" * For each item `book` in `books`, it calls another function (`get`) to retrieve the `\"author\"` attribute from an object.\n",
|
||||||
|
" * The resulting values are generated on-the-fly and sent through the generator expression.\n",
|
||||||
|
"* `yield from …`: The outer expression uses `yield from` to delegate control over iterations to the inner nested generator.\n",
|
||||||
|
" * Instead of dealing with each iterable individually, `yield from` sends its arguments down into the first argument, which it executes and yields values on.\n",
|
||||||
|
"\n",
|
||||||
|
"**Equivalent Code**\n",
|
||||||
|
"\n",
|
||||||
|
"Here is an equivalent version of this code using traditional loops:\n",
|
||||||
|
"\n",
|
||||||
|
"```python\n",
|
||||||
|
"def book_authors(books):\n",
|
||||||
|
" authors = []\n",
|
||||||
|
" for book in books:\n",
|
||||||
|
" if \"author\" in book:\n",
|
||||||
|
" author_name = book[\"author\"]\n",
|
||||||
|
" yield from (author_name,)\n",
|
||||||
|
" authors.append(author_name)\n",
|
||||||
|
"\n",
|
||||||
|
"# To use this function with our recursive yield version \n",
|
||||||
|
"# you can use it like so\n",
|
||||||
|
"for author_name in book_authors(books):\n",
|
||||||
|
" # Use this here\n",
|
||||||
|
"```\n",
|
||||||
|
"\n",
|
||||||
|
"### Why is Yield From useful?\n",
|
||||||
|
"\n",
|
||||||
|
"In programming languages that natively don't support nested generator iterations (like CPython), using `yield from` allows for elegant implementation of cooperative multitasking. It also simplifies the logic of writing generators.\n",
|
||||||
|
"\n",
|
||||||
|
"Note: However, all such recursive-yield constructions rely on Python’s behavior towards generator expressions in its specific use-case."
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
"<IPython.core.display.Markdown object>"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "display_data"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# Get Llama 3.2 to answer\n",
|
||||||
|
"\n",
|
||||||
|
"response = ollama.chat.completions.create(model=MODEL_LLAMA, messages=messages)\n",
|
||||||
|
"result = response.choices[0].message.content\n",
|
||||||
|
"display(Markdown(result))"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": ".venv",
|
||||||
|
"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.10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user