From a490884a329c005c10469ecb393598581b2b45fc Mon Sep 17 00:00:00 2001 From: Daniel Fernandez Colon Date: Fri, 29 Aug 2025 20:46:55 +0200 Subject: [PATCH 1/2] Added my contribution to week1 day1 exercise --- .../day1-email-subject-implementation.ipynb | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 week1/community-contributions/day1-email-subject-implementation.ipynb diff --git a/week1/community-contributions/day1-email-subject-implementation.ipynb b/week1/community-contributions/day1-email-subject-implementation.ipynb new file mode 100644 index 0000000..e968e7c --- /dev/null +++ b/week1/community-contributions/day1-email-subject-implementation.ipynb @@ -0,0 +1,115 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "4e2a9393-7767-488e-a8bf-27c12dca35bd", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import os\n", + "from dotenv import load_dotenv\n", + "from openai import OpenAI\n", + "\n", + "# If you get an error running this cell, then please head over to the troubleshooting notebook!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7b87cadb-d513-4303-baee-a37b6f938e4d", + "metadata": {}, + "outputs": [], + "source": [ + "# Load environment variables in a file called .env\n", + "\n", + "load_dotenv(override=True)\n", + "api_key = os.getenv('OPENAI_API_KEY')\n", + "\n", + "# Check the key\n", + "\n", + "if not api_key:\n", + " print(\"No API key was found - please head over to the troubleshooting notebook in this folder to identify & fix!\")\n", + "elif not api_key.startswith(\"sk-proj-\"):\n", + " print(\"An API key was found, but it doesn't start sk-proj-; please check you're using the right key - see troubleshooting notebook\")\n", + "elif api_key.strip() != api_key:\n", + " print(\"An API key was found, but it looks like it might have space or tab characters at the start or end - please remove them - see troubleshooting notebook\")\n", + "else:\n", + " print(\"API key found and looks good so far!\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "019974d9-f3ad-4a8a-b5f9-0a3719aea2d3", + "metadata": {}, + "outputs": [], + "source": [ + "openai = OpenAI()\n", + "\n", + "# If this doesn't work, try Kernel menu >> Restart Kernel and Clear Outputs Of All Cells, then run the cells from the top of this notebook down.\n", + "# If it STILL doesn't work (horrors!) then please see the Troubleshooting notebook in this folder for full instructions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00743dac-0e70-45b7-879a-d7293a6f68a6", + "metadata": {}, + "outputs": [], + "source": [ + "# Step 1: Create your prompts\n", + "\n", + "system_prompt = \"Eres un analista acostumbrado a trabajar con correos electrónicos que contiene un gran conocimiento sobre la mejor manera de resumir contenido releveante \\\n", + "dejando de lado cualquier información que no despierte interés o no sea el tema principal del correo. Tu función será leer contenido de correos y definir un listado de las 3 mejores opciones con el formato: Opción *numero de la opción*: *sujeto* Motivo: *que palabras clave dentro del texto has utilizado para llegar a esa conclusion y la relación semántica con tu idea\"\n", + "user_prompt = \"\"\"\n", + "Tengo un correo que le quiero enviar a mi profesor pero no se muy bien como llamarlo, ayudame. El correo es el siguiente:\n", + "Hola profe,\n", + "Ultimamente estoy disfrutando mucho sus clases y la información que presenta me parece muy importante. Este fin de semana me voy de vacaciones y no podré\n", + "ir a sus clases la semana que viene. Me gustaría si pudiera pasarme los pdfs de la siguiente semana para echarle un vistazo por mi cuenta durante mi ausencia en Francia.\n", + "\n", + "Un saludo,\n", + "Daniel.\n", + "\"\"\"\n", + "\n", + "# Step 2: Make the messages list\n", + "\n", + "messages = [{\"role\" : \"system\" , \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\": user_prompt}]\n", + "\n", + "# Step 3: Call OpenAI\n", + "\n", + "response = openai.chat.completions.create( \n", + " model = \"gpt-4o-mini\",\n", + " messages = messages)\n", + "\n", + "# Step 4: print the result\n", + "\n", + "print(response.choices[0].message.content)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From f126a5aba0eaa4e4fa943ad4d8baa5cd3c16a990 Mon Sep 17 00:00:00 2001 From: Daniel Fernandez Colon Date: Fri, 29 Aug 2025 22:51:10 +0200 Subject: [PATCH 2/2] week 1 day 2 exercise contribution --- .../day2_exercise_using_input.ipynb | 319 ++++++++++++++++++ 1 file changed, 319 insertions(+) create mode 100644 week1/community-contributions/day2_exercise_using_input.ipynb diff --git a/week1/community-contributions/day2_exercise_using_input.ipynb b/week1/community-contributions/day2_exercise_using_input.ipynb new file mode 100644 index 0000000..f616d96 --- /dev/null +++ b/week1/community-contributions/day2_exercise_using_input.ipynb @@ -0,0 +1,319 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "d15d8294-3328-4e07-ad16-8a03e9bbfdb9", + "metadata": {}, + "source": [ + "# Welcome to your first assignment!\n", + "\n", + "Instructions are below. Please give this a try, and look in the solutions folder if you get stuck (or feel free to ask me!)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e2a9393-7767-488e-a8bf-27c12dca35bd", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import requests\n", + "from bs4 import BeautifulSoup\n", + "from IPython.display import Markdown, display" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "29ddd15d-a3c5-4f4e-a678-873f56162724", + "metadata": {}, + "outputs": [], + "source": [ + "# Constants\n", + "\n", + "OLLAMA_API = \"http://localhost:11434/api/chat\"\n", + "HEADERS = {\"Content-Type\": \"application/json\"}\n", + "MODEL = \"llama3.2\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dac0a679-599c-441f-9bf2-ddc73d35b940", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a messages list using the same format that we used for OpenAI\n", + "\n", + "messages = [\n", + " {\"role\": \"user\", \"content\": \"Describe some of the business applications of Generative AI\"}\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7bb9c624-14f0-4945-a719-8ddb64f66f47", + "metadata": {}, + "outputs": [], + "source": [ + "payload = {\n", + " \"model\": MODEL,\n", + " \"messages\": messages,\n", + " \"stream\": False\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7745b9c4-57dc-4867-9180-61fa5db55eb8", + "metadata": {}, + "outputs": [], + "source": [ + "import ollama\n", + "\n", + "response = ollama.chat(model=MODEL, messages=messages)\n", + "print(response['message']['content'])" + ] + }, + { + "cell_type": "markdown", + "id": "a4704e10-f5fb-4c15-a935-f046c06fb13d", + "metadata": {}, + "source": [ + "## Alternative approach - using OpenAI python library to connect to Ollama" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23057e00-b6fc-4678-93a9-6b31cb704bff", + "metadata": {}, + "outputs": [], + "source": [ + "# There's actually an alternative approach that some people might prefer\n", + "# You can use the OpenAI client python library to call Ollama:\n", + "\n", + "from openai import OpenAI\n", + "ollama_via_openai = OpenAI(base_url='http://localhost:11434/v1', api_key='ollama')\n", + "\n", + "response = ollama_via_openai.chat.completions.create(\n", + " model=MODEL,\n", + " messages=messages\n", + ")\n", + "\n", + "print(response.choices[0].message.content)" + ] + }, + { + "cell_type": "markdown", + "id": "1622d9bb-5c68-4d4e-9ca4-b492c751f898", + "metadata": {}, + "source": [ + "# NOW the exercise for you\n", + "\n", + "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": "code", + "execution_count": 12, + "id": "0c1f84c4-4cc0-4085-8ea5-871a8ca46a47", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import ollama" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "890852ab-2cd4-41dc-b168-6bd1360b967a", + "metadata": {}, + "outputs": [], + "source": [ + "MODEL = \"llama3.2\"" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "6de38216-6d1c-48c4-877b-86d403f4e0f8", + "metadata": {}, + "outputs": [], + "source": [ + "# A class to represent a Webpage\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": 16, + "id": "9d398f9a-c66e-42b5-91b4-5417944b8408", + "metadata": {}, + "outputs": [], + "source": [ + "def user_prompt_generator(website) -> str:\n", + " user_prompt = f\"You will act as a website summarizer with knowledge of Web Content Accessibility Guidelines. You will look into the web: {website.title} and \"\n", + " user_prompt += \"break down the relevant information about it in this categories: What is the website about, \\\n", + " to whom the website belongs and what practises should improve to have a better user experience. \\n\\n\"\n", + " user_prompt += website.text\n", + "\n", + " return user_prompt" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "156d7c67-b714-4156-9f69-faf0c50aaf13", + "metadata": {}, + "outputs": [], + "source": [ + "def messages_generator(user_prompt : str) -> list[dict[str, str]]:\n", + " messages = [{\"role\" : \"user\", \"content\" : user_prompt}]\n", + "\n", + " return messages" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "f07c4143-6cc5-4d28-846c-a373564e9264", + "metadata": {}, + "outputs": [], + "source": [ + "def user_request_reader() -> str:\n", + " while True:\n", + " website_url = input(\"Define what website you want to summarize by giving the url: \")\n", + " if website_url.lower().startswith(\"http\"):\n", + " return website_url\n", + " print(\"URL not valid. Please provide a full url.\\n\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "94933255-2ca8-40b5-8f74-865d3e781058", + "metadata": {}, + "outputs": [], + "source": [ + "def summarizer_bot():\n", + " website_url = user_request_reader()\n", + " website = Website(website_url)\n", + " \n", + " user_prompt = user_prompt_generator(website)\n", + " messages = messages_generator(user_prompt)\n", + "\n", + " response = ollama.chat(model=MODEL, messages=messages)\n", + " print(response['message']['content'])" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "2d81faa4-25b3-4d5d-8f36-93772e449b5c", + "metadata": {}, + "outputs": [ + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Define what website you want to summarize by giving the url: test.com\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "URL not valid. Please provide a full url.\n", + "\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Define what website you want to summarize by giving the url: https://edwarddonner.com\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "**Summary:**\n", + "\n", + "The website \"Home - Edward Donner\" belongs to Edward Donner, a co-founder and CTO of Nebula.io, an AI startup. The website is about Edward's interests in writing code, experimenting with Large Language Models (LLMs), and DJing, as well as his work in applying AI to help people discover their potential.\n", + "\n", + "**Categories:**\n", + "\n", + "### What is the website about?\n", + "\n", + "The website is primarily about Edward Donner's personal brand, showcasing his expertise in AI and LLMs. It includes information about his work at Nebula.io, which applies AI to talent management. The website also features a \"Connect Four\" arena where LLMs compete against each other, as well as sections for learning more about LLMs and staying up-to-date with Edward's courses and publications.\n", + "\n", + "### To whom does the website belong?\n", + "\n", + "The website belongs to Edward Donner, a co-founder and CTO of Nebula.io. It appears to be a personal website or blog, showcasing his expertise and interests in AI and LLMs.\n", + "\n", + "### Practices to improve for better user experience:\n", + "\n", + "1. **Clearer navigation**: The website's menu is simple but not intuitive. Adding clear categories or sections would help users quickly find the information they're looking for.\n", + "2. **More detailed about section**: The \"About\" section provides a brief overview of Edward's work and interests, but it could be more detailed and comprehensive.\n", + "3. **Improved accessibility**: While the website is likely following general web accessibility guidelines, there are no clear indications of this on the page. Adding alt text to images, providing a clear font size and color scheme, and ensuring sufficient contrast between background and foreground would improve the user experience for people with disabilities.\n", + "4. **Better calls-to-action (CTAs)**: The website could benefit from more prominent CTAs, guiding users towards specific actions such as signing up for courses or following Edward on social media.\n", + "5. **SEO optimization**: The website's content and meta tags appear to be optimized for search engines, but a more thorough SEO analysis would help identify areas for improvement.\n", + "\n", + "Overall, the website provides a clear overview of Edward Donner's interests and expertise in AI and LLMs, but could benefit from some tweaks to improve accessibility, navigation, and CTAs.\n" + ] + } + ], + "source": [ + "# The call\n", + "summarizer_bot()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}