diff --git a/week1/day2 EXERCISE.ipynb b/week1/day2 EXERCISE_ollama_llama3.ipynb similarity index 57% rename from week1/day2 EXERCISE.ipynb rename to week1/day2 EXERCISE_ollama_llama3.ipynb index 81077ed..9576944 100644 --- a/week1/day2 EXERCISE.ipynb +++ b/week1/day2 EXERCISE_ollama_llama3.ipynb @@ -220,7 +220,12 @@ "cell_type": "code", "execution_count": null, "id": "cf9eb44e-fe5b-47aa-b719-0bb63669ab3d", - "metadata": {}, + "metadata": { + "collapsed": true, + "jupyter": { + "outputs_hidden": true + } + }, "outputs": [], "source": [ "!ollama pull deepseek-r1:1.5b" @@ -253,10 +258,230 @@ "Take the code from day1 and incorporate it here, to build a website summarizer that uses Llama 3.2 running locally instead of OpenAI; use either of the above approaches." ] }, + { + "cell_type": "markdown", + "id": "ffaa3470-884c-467e-b4ce-c1b8d39294da", + "metadata": {}, + "source": [ + "This is the code from day 1 notebook. Here we create the class to extract the text from the website, using BeautifulSoup library, and the we execute it to see the the results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d8c9f01-ca12-4018-b7fa-698c9fa1aa93", + "metadata": {}, + "outputs": [], + "source": [ + "# A class to represent a Webpage\n", + "# If you're not familiar with Classes, check out the \"Intermediate Python\" notebook\n", + "\n", + "# Some websites need you to use proper headers when fetching them:\n", + "headers = {\n", + " \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36\"\n", + "}\n", + "\n", + "class Website:\n", + "\n", + " def __init__(self, url):\n", + " \"\"\"\n", + " Create this Website object from the given url using the BeautifulSoup library\n", + " \"\"\"\n", + " self.url = url\n", + " response = requests.get(url, headers=headers)\n", + " soup = BeautifulSoup(response.content, 'html.parser')\n", + " self.title = soup.title.string if soup.title else \"No title found\"\n", + " for irrelevant in soup.body([\"script\", \"style\", \"img\", \"input\"]):\n", + " irrelevant.decompose()\n", + " self.text = soup.body.get_text(separator=\"\\n\", strip=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fd198df-bac5-42c5-83a0-06c5f71fb76a", + "metadata": {}, + "outputs": [], + "source": [ + "# Let's try one out. Change the website and add print statements to follow along.\n", + "\n", + "ed = Website(\"https://edwarddonner.com\")\n", + "print(ed.title)\n", + "print(ed.text)" + ] + }, + { + "cell_type": "markdown", + "id": "995b637d-a5db-4ad9-ac78-5980fd7ef112", + "metadata": {}, + "source": [ + "#### Define the system prompt, to instruct the model how we want to respond to our query. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee810d49-e88a-4137-a4be-98812e0d0748", + "metadata": {}, + "outputs": [], + "source": [ + "# Define our system prompt - you can experiment with this later, changing the last sentence to 'Respond in markdown in Spanish.\"\n", + "\n", + "system_prompt = \"You are an assistant that analyzes the contents of a website \\\n", + "and provides a short summary, ignoring text that might be navigation related. \\\n", + "Respond in markdown.\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "482b5d4c-69ed-4332-abb5-8b0986dcf368", + "metadata": {}, + "outputs": [], + "source": [ + "# A function that writes a User Prompt that asks for summaries of websites:\n", + "\n", + "def user_prompt_for(website):\n", + " user_prompt = f\"You are looking at a website titled {website.title}\"\n", + " user_prompt += \"\\nThe contents of this website is as follows; \\\n", + "please provide a short summary of this website in markdown. \\\n", + "If it includes news or announcements, then summarize these too.\\n\\n\"\n", + " user_prompt += website.text\n", + " return user_prompt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d966cb09-3ca2-49f7-8462-f6ef26c01159", + "metadata": {}, + "outputs": [], + "source": [ + "print(user_prompt_for(ed))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2f9be84f-4cd7-4ce7-8f33-e60d16f02852", + "metadata": {}, + "outputs": [], + "source": [ + "# For test purpose\n", + "\n", + "messages = [\n", + " {\"role\": \"system\", \"content\": \"You are a snarky assistant\"},\n", + " {\"role\": \"user\", \"content\": \"What is 2 + 2?\"}\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5cb0e9f-eb56-4633-ba4c-76817be98856", + "metadata": {}, + "outputs": [], + "source": [ + "# To give you a preview -- calling ollama with system and user messages:\n", + "\n", + "import ollama\n", + "\n", + "response = ollama.chat(model=MODEL, messages=messages)\n", + "print(response['message']['content'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c554903f-eb04-4a16-87fc-f1d9ff58f6d9", + "metadata": {}, + "outputs": [], + "source": [ + "# See how this function creates exactly the format above\n", + "\n", + "def messages_for(website):\n", + " return [\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": user_prompt_for(website)}\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b64b814-123f-436d-9366-4c762ac4b89a", + "metadata": {}, + "outputs": [], + "source": [ + "# Try this out, and then try for a few more websites\n", + "\n", + "messages_for(ed)" + ] + }, + { + "cell_type": "markdown", + "id": "d1ef4be2-ef3a-4b5d-8d18-f2eafa9d6a93", + "metadata": {}, + "source": [ + "### So, here let's run the summarize by using ollama and see how appears." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c46edc5-c85d-4ad0-89fd-39c4fdc44a5d", + "metadata": {}, + "outputs": [], + "source": [ + "# And now: call the ollama API. \n", + "\n", + "def summarize(url):\n", + " website = Website(url)\n", + " response = ollama.chat(\n", + " model = MODEL,\n", + " messages = messages_for(website)\n", + " )\n", + " return response['message']['content']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "466c2f78-91ca-4ed2-b60b-40661d0b6f68", + "metadata": {}, + "outputs": [], + "source": [ + "summarize(\"https://edwarddonner.com\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ab7c9a1-70fd-421c-be06-c36eb6c9aedf", + "metadata": {}, + "outputs": [], + "source": [ + "# A function to display this nicely in the Jupyter output, using markdown\n", + "\n", + "def display_summary(url):\n", + " summary = summarize(url)\n", + " display(Markdown(summary))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1cedc9d9-6a76-4225-82c1-82240da16260", + "metadata": {}, + "outputs": [], + "source": [ + "display_summary(\"https://edwarddonner.com\")" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "6de38216-6d1c-48c4-877b-86d403f4e0f8", + "id": "82c48586-33c8-4797-a24f-41602c1297b3", "metadata": {}, "outputs": [], "source": [] @@ -264,7 +489,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "llms", "language": "python", "name": "python3" },