{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c71df8f9-6782-4d7f-ae63-dc2d8edebdbd",
   "metadata": {},
   "source": [
    "# Chapter 2"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "da2fe42d-a428-4020-a2f7-d838b7c1172f",
   "metadata": {},
   "source": [
    "# OpenAI API prompt examples"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c5688cd-b2ae-47e8-bf5b-4d4222216c0e",
   "metadata": {},
   "source": [
    "## Minimal prompt execution"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1a00a004-c42b-49c6-8a67-4446a9f51d12",
   "metadata": {},
   "outputs": [
    {
     "name": "stdin",
     "output_type": "stream",
     "text": [
      "Enter your OPENAI_API_KEY ········\n"
     ]
    }
   ],
   "source": [
    "from openai import OpenAI\n",
    "import getpass\n",
    "\n",
    "OPENAI_API_KEY = getpass.getpass('Enter your OPENAI_API_KEY') "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "efe5a5c2-a624-4cb5-ba3f-a083fceb5a6c",
   "metadata": {},
   "outputs": [],
   "source": [
    "client = OpenAI(api_key=OPENAI_API_KEY)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "06226bd6-59cf-47ef-aa1a-7219e473ae4b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ChatCompletion(id='chatcmpl-CdOham7vtuWOojomkLs7E0N2tCIwy', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='Be vigilant against phishing: verify the sender, hover to check URLs, avoid unexpected attachments, and never share passwords. If something seems off, report it.', refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=None))], created=1763505782, model='gpt-5-nano-2025-08-07', object='chat.completion', service_tier='default', system_fingerprint=None, usage=CompletionUsage(completion_tokens=552, prompt_tokens=32, total_tokens=584, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=0, audio_tokens=0, reasoning_tokens=512, rejected_prediction_tokens=0), prompt_tokens_details=PromptTokensDetails(audio_tokens=0, cached_tokens=0)))\n"
     ]
    }
   ],
   "source": [
    "prompt_input = \"\"\"Write a coincise message to remind users \n",
    "to be vigilant about phishing attacks.\"\"\"\n",
    "response = client.chat.completions.create(\n",
    "  model=\"gpt-5-nano\",\n",
    "  messages=[\n",
    "    {\"role\": \"system\", \"content\": \"You are a helpful assistant.\"},\n",
    "    {\"role\": \"user\", \"content\": prompt_input}\n",
    "  ] \n",
    ")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "32cd8a1d-fb03-4a64-8b2b-9b908f9bef64",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Be vigilant against phishing: verify the sender, hover to check URLs, avoid unexpected attachments, and never share passwords. If something seems off, report it.\n"
     ]
    }
   ],
   "source": [
    "print(response.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9164dd5f-ea11-49b6-b248-49adbcbb61ec",
   "metadata": {},
   "source": [
    "# Running prompts with LangChain"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2aff29ac-7ca7-48ec-bd59-bd2c46c5e804",
   "metadata": {},
   "source": [
    "## Basic prompt with LangChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "d5e407d8-b060-4cbd-89e3-e8af1072702f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY,\n",
    "                 model_name=\"gpt-5-nano\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5df2b692-ac63-423c-8667-08984f4d4831",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Here are three concise options you can use:\n",
      "\n",
      "Option A:\n",
      "Reminder: Be vigilant against phishing. Verify the sender, don’t click unknown links, never share passwords, and report suspicious messages to IT.\n",
      "\n",
      "Option B:\n",
      "Phishing alert: If something seems off, pause, verify the sender, hover over links, and report it to security.\n",
      "\n",
      "Option C:\n",
      "Stay safe: Treat unexpected messages with caution—check the sender, avoid clicking links, and don’t enter credentials.\n"
     ]
    }
   ],
   "source": [
    "prompt_input = \"\"\"Write a coincise message to remind users \n",
    "to be vigilant about phishing attacks.\"\"\"\n",
    "\n",
    "response = llm.invoke(prompt_input)\n",
    "print(response.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d486eb8e-b785-4637-9dcd-e749ea8e8a45",
   "metadata": {},
   "source": [
    "# Prompt templates"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85141333-b2e0-4708-95db-0fa83e061578",
   "metadata": {},
   "source": [
    "## Prompt template - implementing it with a Python function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "041621aa-839a-4511-b235-463c9159a0ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_text_summary_prompt(text, num_words, tone):\n",
    "    return f\"You are an experienced copywriter. Write a {num_words} words summary the the following text, using a {tone} tone: {text}\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "c56dfb88-6cf0-4ca2-8385-881545fe0285",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Segovia's Roman Aqueduct, built in the 1st century AD to channel mountain springs, UNESCO-listed, completion debated circa 98–117 AD today.\n"
     ]
    }
   ],
   "source": [
    "segovia_aqueduct_text = \"\"\"The Aqueduct of Segovia (Spanish: \n",
    "Acueducto de Segovia) is a Roman aqueduct in Segovia, Spain. \n",
    "It was built around the first century AD to channel water from \n",
    "springs in the mountains 17 kilometres (11 mi) away to the \n",
    "city's fountains, public baths and private houses, and was in \n",
    "use until 1973. \n",
    "Its elevated section, with its complete arcade of 167 arches, \n",
    "is one of the best-preserved Roman aqueduct bridges and the \n",
    "foremost symbol of Segovia, as evidenced by its presence on the \n",
    "city's coat of arms. \n",
    "The Old Town of Segovia and the aqueduct, were declared a UNESCO \n",
    "World Heritage Site in 1985. As the aqueduct lacks a legible \n",
    "inscription (one was apparently located in the structure's attic, \n",
    "or top portion[citation needed]), the date of construction cannot be \n",
    "definitively determined. The general date of the Aqueduct's \n",
    "construction was long a mystery, although it was thought to have \n",
    "been during the 1st century AD, during the reigns of the Emperors \n",
    "Domitian, Nerva, and Trajan. At the end of the 20th century, \n",
    "Géza Alföldy deciphered the text on the dedication plaque by \n",
    "studying the anchors that held the now missing bronze letters \n",
    "in place. He determined that Emperor Domitian (AD 81–96) ordered \n",
    "its construction[1] and the year 98 AD was proposed as the most \n",
    "likely date of completion.[2] However, in 2016 archeological \n",
    "evidence was published which points to a slightly later date, \n",
    "after 112 AD, during the government of Trajan or in the \n",
    "beginning of the government of emperor Hadrian, \n",
    "from 117 AD.\"\"\"\n",
    "\n",
    "input_prompt = generate_text_summary_prompt(\n",
    "    text=segovia_aqueduct_text, \n",
    "    num_words=20,\n",
    "    tone=\"knowledgeable and engaging\")\n",
    "\n",
    "response = llm.invoke(input_prompt)\n",
    "print(response.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4e9343b1-3463-43c2-be92-077565f11bc1",
   "metadata": {},
   "source": [
    "## Prompt template - using LangChain's ChatPromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "3ff5a92f-e3b0-47a9-88e6-0ae9f4dbae73",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "\n",
    "prompt_template = PromptTemplate.from_template(\n",
    "\"\"\"You are an experienced copywriter. \n",
    "Write a {num_words} words summary the the following text, \n",
    "using a {tone} tone: {text}\"\"\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "76f457f9-9d7b-4d01-9db9-6e3bf6c500c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "prompt = prompt_template.format(\n",
    "    text=segovia_aqueduct_text,\n",
    "    num_words=20, \n",
    "    tone=\"knowledgeable and engaging\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "42dba96d-5b5b-47d5-aef3-ccae810cf6fc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Segovia’s Roman aqueduct carried water 17 km to fountains, baths, homes; 167 arches symbolize Segovia, UNESCO World Heritage site today.\n"
     ]
    }
   ],
   "source": [
    "response = llm.invoke(prompt)\n",
    "print(response.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3117386-5c78-4eef-a911-c02957aeddc9",
   "metadata": {},
   "source": [
    "# Few shot prompt with LangChain"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "240cab2b-b506-425d-b733-64ab3257d105",
   "metadata": {},
   "source": [
    "## Using standard prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "9c893189-e23d-478a-a9ed-5a671c697a7b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "llm = ChatOpenAI(openai_api_key=OPENAI_API_KEY,\n",
    "                 model_name=\"gpt-5-mini\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "581cb1f7-1e61-45c6-8132-0c97715c4a8f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3 -> None\n",
      "4 -> None\n",
      "5 -> Abra\n",
      "7 -> Kadabra\n",
      "8 -> None\n",
      "10 -> Abra\n",
      "11 -> None\n",
      "13 -> None\n",
      "35 -> Abra Kadabra\n"
     ]
    }
   ],
   "source": [
    "prompt_input = \"\"\"Classify the following numbers as Abra, Kadabra or Abra Kadabra:\n",
    "\n",
    "3, 4, 5, 7, 8, 10, 11, 13, 35\n",
    "\n",
    "Examples: \n",
    "6 // not divisible by 5, not divisible by 7 // None\n",
    "15 // divisible by 5, not divisible by 7 // Abra\n",
    "12 // not divisible by 5, not divisible by 7 // None\n",
    "21 // not divisible by 5, divisible by 7 // Kadabra\n",
    "70 // divisible by 5, divisible by 7 // Abra Kadabra\n",
    "\"\"\"\n",
    "\n",
    "response = llm.invoke(prompt_input)\n",
    "print(response.content)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "de2820de-7028-4fbb-8948-088327a450fc",
   "metadata": {},
   "source": [
    "## Using Langchain's FewShotPromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "982749c6-f3bf-4449-864e-7073b98766b0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3 — None\n",
      "4 — None\n",
      "5 — Abra\n",
      "7 — Kadabra\n",
      "8 — None\n",
      "10 — Abra\n",
      "11 — None\n",
      "13 — None\n",
      "35 — Abra Kadabra\n"
     ]
    }
   ],
   "source": [
    "from langchain_core.prompts.few_shot import FewShotPromptTemplate\n",
    "from langchain_core.prompts.prompt import PromptTemplate\n",
    "\n",
    "examples = [\n",
    "  {\n",
    "      \"number\": 6,\n",
    "      \"reasoning\": \"not divisible by 5 nor by 7\",\n",
    "      \"result\": \"None\"\n",
    "  },\n",
    "  {\n",
    "      \"number\": 15,\n",
    "      \"reasoning\": \"divisible by 5 but not by 7\",\n",
    "      \"result\": \"Abra\"\n",
    "  },\n",
    "  {\n",
    "      \"number\": 12,\n",
    "      \"reasoning\": \"not divisible by 5 nor by 7\",\n",
    "      \"result\": \"None\"\n",
    "  },\n",
    "  {\n",
    "      \"number\": 21,\n",
    "      \"reasoning\": \"divisible by 7 but not by 5\",\n",
    "      \"result\": \"Kadabra\"\n",
    "  },\n",
    "  {\n",
    "      \"number\": 70,\n",
    "      \"reasoning\": \"divisible by 5 and by 7\",\n",
    "      \"result\": \"Abra Kadabra\"\n",
    "  } ]\n",
    "\n",
    "example_prompt = PromptTemplate(input_variables=[\"number\", \"reasoning\", \"result\"], template=\"{number} \\\\ {reasoning} \\\\ {result}\")\n",
    "few_shot_prompt = FewShotPromptTemplate(\n",
    "    examples=examples,\n",
    "    example_prompt=example_prompt,\n",
    "    suffix=\"Classify the following numbers as Abra, Kadabra or Abra Kadabra: {comma_delimited_input_numbers}\",\n",
    "    input_variables=[\"comma_delimited_input_numbers\"]\n",
    ")\n",
    "\n",
    "prompt_input = few_shot_prompt.format(comma_delimited_input_numbers=\"3, 4, 5, 7, 8, 10, 11, 13, 35.\")\n",
    "\n",
    "response = llm.invoke(prompt_input)\n",
    "print(response.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.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
