From 9a692289e4e77c6998f0dcf269c0b48d05f28e41 Mon Sep 17 00:00:00 2001 From: Dmitry Kisselev <956988+dkisselev-zz@users.noreply.github.com> Date: Fri, 17 Oct 2025 06:50:33 -0700 Subject: [PATCH 1/2] excercise wk1 --- .../dkisselev-zz/week1/week1 EXERCISE.ipynb | 266 ++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb diff --git a/community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb b/community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb new file mode 100644 index 0000000..ef18461 --- /dev/null +++ b/community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb @@ -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": [ + "" + ] + }, + "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": [ + "" + ] + }, + "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 +} From 352498981c9fb7db578e685ff431b6e176b4ceda Mon Sep 17 00:00:00 2001 From: Dmitry Kisselev <956988+dkisselev-zz@users.noreply.github.com> Date: Fri, 17 Oct 2025 07:06:23 -0700 Subject: [PATCH 2/2] cleanup of the output --- .../dkisselev-zz/week1/week1 EXERCISE.ipynb | 127 ++---------------- 1 file changed, 11 insertions(+), 116 deletions(-) diff --git a/community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb b/community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb index ef18461..5b4df5d 100644 --- a/community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb +++ b/community-contributions/dkisselev-zz/week1/week1 EXERCISE.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "c1070317-3ed9-4659-abe3-828943230e03", "metadata": {}, "outputs": [], @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "4a456906-915a-4bfd-bb9d-57e505c5093f", "metadata": {}, "outputs": [], @@ -42,18 +42,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "a8d7923c-5f28-4c30-8556-342d7c8497c1", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "API key looks good so far\n" - ] - } - ], + "outputs": [], "source": [ "# set up environment\n", "\n", @@ -71,7 +63,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "3f0d0137-52b0-47a8-81a8-11a90a010798", "metadata": {}, "outputs": [], @@ -86,7 +78,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "df0d958f", "metadata": {}, "outputs": [], @@ -104,7 +96,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "13506dd4", "metadata": {}, "outputs": [], @@ -117,55 +109,10 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Get gpt-4o-mini to answer, with streaming\n", "\n", @@ -177,62 +124,10 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "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": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# Get Llama 3.2 to answer\n", "\n",