excercise wk1

This commit is contained in:
Dmitry Kisselev
2025-10-17 06:50:33 -07:00
parent 6dfd68ca87
commit 9a692289e4

View 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 Pythons 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
}