{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "cell00",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "# Week 1 — Exercises\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "lx-8c5a9d",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Part A — Foundations & calculations"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell07",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Exercise 1 — Conditional probability from a joint table *(calculation)*\n",
    "\n",
    "Given the joint distribution $P(X,Y)$:\n",
    "\n",
    "| $X$ | $Y$ | $P$ |\n",
    "|-----|-----|-----|\n",
    "| 0 | 0 | 0.1 |\n",
    "| 0 | 1 | 0.2 |\n",
    "| 1 | 0 | 0.6 |\n",
    "| 1 | 1 | 0.1 |\n",
    "\n",
    "Compute the conditional distribution $P(X \\mid Y{=}1)$."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell09",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Exercise 2 — Build a joint via the chain rule *(calculation)*\n",
    "\n",
    "Given the marginal $P(W)$ and the conditional $P(D\\mid W)$:\n",
    "\n",
    "| $W$ | $P(W)$ |\n",
    "|-----|--------|\n",
    "| sun | 0.8 |\n",
    "| rain | 0.2 |\n",
    "\n",
    "| $P(D\\mid W)$ | $D=$ wet | $D=$ dry |\n",
    "|-----|-----|-----|\n",
    "| $W=$ sun | 0.1 | 0.9 |\n",
    "| $W=$ rain | 0.7 | 0.3 |\n",
    "\n",
    "Compute the joint table $P(W,D)=P(D\\mid W)\\,P(W)$."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell11",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Exercise 3 — Statistical independence *(calculation)*\n",
    "\n",
    "Marginals $P(T)$: hot 0.5, cold 0.5; $P(W)$: sun 0.6, rain 0.4. Joint $P(T,W)$:\n",
    "\n",
    "| $T$ | $W$ | $P(T,W)$ |\n",
    "|-----|-----|----------|\n",
    "| hot | sun | 0.4 |\n",
    "| hot | rain | 0.1 |\n",
    "| cold | sun | 0.2 |\n",
    "| cold | rain | 0.3 |\n",
    "\n",
    "Are $T$ and $W$ statistically independent? Justify."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell01",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Exercise 4 — Chain rule *(theory)*\n",
    "\n",
    "1. **Chain Rule**: Write $P(W_{1:3})$ for a 3-token sequence as a product of conditional probabilities.\n",
    "2. **Joint Space Size**: How many parameters are needed to store the full, unrepresented joint distribution $P(W_{1:T})$ in a lookup table for a vocabulary $\\vert{}V\\vert{}$ and length $T$?\n",
    "3. **The Conditional Bottleneck**: Why does the chain rule factorization in (1) fail to solve this exponential memory problem if we try to store the exact conditional probabilities $P(W_t \\mid W_{1:t-1})$ in a lookup table? What structural assumption do classical language models use to fix this?\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell03",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Exercise 5 — The training ladder *(conceptual)*\n",
    "\n",
    "Explain what each ladder stage adds, and why **only** a tool-calling-tuned model can drive an\n",
    "agent loop."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cell05",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Exercise 6 — Chatbot vs agent, and the three-layers *(conceptual)*\n",
    "\n",
    "(a) Classify each as **chatbot** or **agent**, and justify:\n",
    "- (i) a bot answering FAQs from a fixed text, no actions;\n",
    "- (ii) a system that reads your calendar, books a meeting, and emails attendees.\n",
    "\n",
    "(b) In the three-layer architecture, which **layer** \n",
    "- (i) talks to the messenger,\n",
    "- (ii) executes a tool,\n",
    "- (iii) calls the LLM?"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "lb-7d49d0",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Part B — Lab: Ollama + the OpenAI client\n",
    "\n",
    "**Install (no root needed).** Ollama runs without admin rights — install a user-local binary:\n",
    "\n",
    "```bash\n",
    "mkdir -p ~/.local\n",
    "curl -L https://ollama.com/download/ollama-linux-amd64.tgz | tar -xz -C ~/.local\n",
    "export PATH=\"$HOME/.local/bin:$PATH\"      # add this line to ~/.bashrc\n",
    "```\n",
    "\n",
    "**Start the server — each session** (lab machines have no auto-start service and no\n",
    "Docker/Podman):\n",
    "\n",
    "```bash\n",
    "ollama serve &        # local server on 127.0.0.1:11434 — leave it running while you work\n",
    "```\n",
    "\n",
    "**Pull a model and test it on the command line:**\n",
    "\n",
    "```bash\n",
    "ollama pull qwen2.5:3b\n",
    "ollama list                                    # list installed models\n",
    "ollama run qwen2.5:3b \"Say hello in one word.\" # quick sanity check that Ollama works\n",
    "```\n",
    "\n",
    "**Try different models** — depending on the machine's free RAM. Smaller = lighter and faster on\n",
    "CPU, but tool calling gets less reliable below ~3B:\n",
    "\n",
    "| free RAM | model | tool calling |\n",
    "|---|---|---|\n",
    "| ~4 GB | `llama3.2:1b`, `qwen2.5:1.5b` | flaky |\n",
    "| ~6–8 GB | `qwen2.5:3b`, `llama3.2:3b` | reliable ✅ |\n",
    "| 8+ GB | `qwen2.5:7b` | best |\n",
    "\n",
    "Pull a couple and **compare speed and answer quality** — set `MODEL` below to whichever you use.\n",
    "\n",
    "> *On your **own** computer you may auto-start Ollama with `systemctl --user` or Docker/Podman.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "lb-c9142b",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "-"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Run me first — defines `client` and `MODEL` used by all lab exercises below.\n",
    "from openai import OpenAI\n",
    "\n",
    "client = OpenAI(base_url=\"http://localhost:11434/v1\", api_key=\"ollama\")  # key is ignored\n",
    "MODEL = \"qwen2.5:3b\"   # try \"llama3.2:3b\", \"qwen2.5:1.5b\", or \"qwen2.5:7b\" (RAM permitting)\n",
    "# MODEL = \"qwen2.5:7b\" "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "lx-e3856b",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Exercise 7 — First API call *(lab)*\n",
    "\n",
    "Send a single user message with the **Chat Completions API** to the model and print its reply."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "lx-73bf5d",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Exercise 8 — The system prompt *(lab)*\n",
    "\n",
    "Send the *same* user question with the **Chat Completions API** with two different **system** prompts and compare the answers.\n",
    "What does the system message control?"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "lx-cfe904",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": "slide"
    },
    "tags": []
   },
   "source": [
    "## Exercise 9 — Statelessness & memory *(lab)*\n",
    "\n",
    "Tell the model your name in one request; in a **new** request ask for it **without** resending\n",
    "the history. Then repeat **with** the history. Use the **Chat Completions API**!\n",
    "Explain what you observe."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "lx-0e22d8",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## Exercise 10 — A structured tool call *(preview)*\n",
    "\n",
    "*A first look at **function calling** — the mechanics are **Week 2**. Here you only **advertise** a\n",
    "tool and **observe** the structured request the model emits (you don't invent the schema or run the\n",
    "tool).*\n",
    "\n",
    "Using the `tools` schema below, ask *\"What's the weather in Berlin?\"* and inspect\n",
    "`response.choices[0].message.tool_calls` — the **structured JSON** the model emits. Do **not**\n",
    "execute the tool. Use the **Chat Completions API**.\n",
    "\n",
    "```python\n",
    "tools = [{\n",
    "    \"type\": \"function\",\n",
    "    \"function\": {\n",
    "        \"name\": \"get_weather\",\n",
    "        \"description\": \"Get the current weather for a city.\",\n",
    "        \"parameters\": {\n",
    "            \"type\": \"object\",\n",
    "            \"properties\": {\"city\": {\"type\": \"string\"}},\n",
    "            \"required\": [\"city\"],\n",
    "        },\n",
    "    },\n",
    "}]\n",
    "```\n",
    "\n",
    "Pass `tools=tools` to `client.chat.completions.create(...)`. *(The tool-schema format itself is\n",
    "explained in Week 2 — you're just seeing the output here.)*"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71ccaf6f-9b4d-42eb-898a-49d7ffd6ddd8",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "## Part C — Reflection ⚖️\n",
    "\n",
    "## Exercise 11 — Can a language model think critically? *(discussion — open question)*\n",
    "\n",
    "> **Open question.** Are language models capable of **critical thinking** — or do they mainly\n",
    "> reproduce **majority opinion**, including its prejudices? Discuss this in terms of *how* they\n",
    "> generate language: **probabilistically**, from $P(W_t \\mid W_{1:t-1})$.\n",
    "\n",
    "Work through (a)–(d) and write a **~1 page** essay that takes a clear position *and* states the\n",
    "strongest objection to it.\n",
    "\n",
    "**(a) Start from the maths.** The model is fitted by maximum likelihood on a corpus, so\n",
    "$\\hat P(W_t \\mid W_{1:t-1})$ approximates the distribution *of that corpus*. If the corpus records\n",
    "many conflicting voices on a contested question, **what does the mode of that conditional\n",
    "correspond to** — the best-argued position, or the most frequent one? What follows for a minority\n",
    "view that is **well argued but rarely written down**? *(How a system then picks a token from the\n",
    "distribution — greedy vs. sampling, temperature — is **Week 2**, and W2's Exercise 13 measures it.)*\n",
    "\n",
    "**(b) Where could disagreement with the majority come from at all?** For each mechanism below,\n",
    "decide whether it produces a genuine **evaluation of reasons** or only a **shift of the\n",
    "distribution**:\n",
    "  1. **Conditioning** — the prompt or an attached document moves the model into a different region\n",
    "     of the distribution.\n",
    "  2. **Preference tuning** (SFT/RLHF — the alignment rung of the training ladder) — reshapes the\n",
    "     probabilities themselves toward helpful/harmless completions.\n",
    "  3. **Tools & retrieval** — evidence from outside the weights (W2, W8).\n",
    "  4. **Decoding knobs** — greedy vs. sampling, temperature (W2).\n",
    "\n",
    "**(c) Alignment is not obviously a fix.** Preference optimisation rewards answers that *raters\n",
    "prefer*, and Sharma et al. (2023) find that preference data systematically favours responses\n",
    "matching the **user's** stated view — sometimes over correct ones (**sycophancy**). Distinguish two\n",
    "different failures: a model echoing the **corpus majority**, and a model echoing **the person in\n",
    "front of it**. Which is more dangerous for an agent that *acts* (W12), and why?\n",
    "\n",
    "**(d) The counter-position.** Bender et al. (2021) argue an LM is a **\"stochastic parrot\"** — form\n",
    "without communicative intent. Mahowald et al. (2024) instead separate **formal** linguistic\n",
    "competence (mastering the rules and statistical regularities of a language) from **functional**\n",
    "competence (using language rationally in the world: reasoning, world knowledge, situation tracking,\n",
    "social cognition). Sort the ingredients of \"critical thinking\" — internal consistency, spotting a\n",
    "fallacy, weighing evidence, **changing one's mind when the evidence changes** — onto that\n",
    "distinction. Then state what would count as *evidence* that a model did more than repeat patterns:\n",
    "**design a concrete test**, and say **what result would falsify your own position**.\n",
    "\n",
    "**References.**\n",
    "- Bender, E. M., Gebru, T., McMillan-Major, A., & Shmitchell, S. (2021). *On the Dangers of\n",
    "  Stochastic Parrots: Can Language Models Be Too Big?* FAccT '21, 610–623. doi:10.1145/3442188.3445922.\n",
    "- Mahowald, K., Ivanova, A. A., Blank, I. A., Kanwisher, N., Tenenbaum, J. B., & Fedorenko, E.\n",
    "  (2024). *Dissociating Language and Thought in Large Language Models.* Trends in Cognitive\n",
    "  Sciences 28(6), 517–540. arXiv:2301.06627.\n",
    "- Sharma, M., et al. (2023). *Towards Understanding Sycophancy in Language Models.* arXiv:2310.13548.\n"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "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.12.3"
  },
  "rise": {
   "scroll": true,
   "theme": "simple",
   "transition": "none"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
