{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 🤖 Week 2 — Build Your First AI Agent (DataFetcher)\n",
    "### AI Trailblazers · runs on **Google Colab** · powered by **Google Gemini (free)**\n",
    "\n",
    "Today you build a real **agent**: it doesn't just answer — it *loops*, calling **tools** to fetch and summarize live info (the **ReAct** loop: Reason → Act → Observe → repeat).\n",
    "\n",
    "| Part | You'll do | ✅ Done when |\n",
    "|---|---|---|\n",
    "| **A · Setup** | Connect Gemini + imports | The setup test prints ✅ |\n",
    "| **B · DataFetcher** | Tools + the agent loop | The agent calls tools and returns a 3-bullet summary |\n",
    "| **C · Titanic** | Load real data, ask a question | You print average age by gender |\n",
    "\n",
    "> Run each grey **code cell** in order with **▶️ / Shift+Enter**. Read the note above it first."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 🅰️ Part A — Setup\n",
    "### 🔑 Get your free Gemini key (once)\n",
    "1. Open **https://aistudio.google.com/apikey** → **Create API key** → copy it.\n",
    "2. Run the cells below; paste the key when asked.\n",
    "\n",
    "🔒 An API key is a password — never paste it into a public doc, chat, or GitHub."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# Install everything we need this week\n",
    "!pip -q install google-genai pandas requests"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "from google import genai\n",
    "from google.genai import types\n",
    "import pandas as pd, getpass\n",
    "\n",
    "API_KEY = getpass.getpass('Paste your Gemini API key: ').strip()\n",
    "client = genai.Client(api_key=API_KEY)\n",
    "print('Client ready ✅')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Model names change, so we ask your key which models exist and pick a fast one automatically."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "model_names = [m.name for m in client.models.list()]\n",
    "flash = [m for m in model_names if 'flash' in m and 'embedding' not in m]\n",
    "MODEL = flash[0] if flash else 'models/gemini-2.5-flash'\n",
    "print('Using MODEL =', MODEL)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ✅ TEST: talk to Gemini once\n",
    "r = client.models.generate_content(model=MODEL, contents='In 5 words, what is an AI agent?')\n",
    "print(r.text)\n",
    "assert r.text, 'No reply — check your key/model.'\n",
    "print('\\n✅ Setup works!')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 🅱️ Part B — The DataFetcher agent\n",
    "An **agent** = an LLM that can call **tools** in a loop. We'll give it two tools, then let it drive.\n",
    "\n",
    "### Step 1 — Create the tools\n",
    "A *tool* is just a Python function. `search_web()` returns **mock news** (reliable for class — you can swap in a real API later). `summarize_text()` asks Gemini to shrink text to 3 bullets."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "MOCK_NEWS = '''\n",
    "1. New study: high-school AI clubs boost college CS enrollment by 22%.\n",
    "2. Google launches free Gemini tier for student developers in classrooms.\n",
    "3. Teachers report AI tutors help most when students verify answers themselves.\n",
    "4. Kaggle adds beginner 'Getting Started' tracks aimed at teen learners.\n",
    "'''\n",
    "\n",
    "def search_web(query: str) -> str:\n",
    "    \"\"\"Return recent headlines about a topic.\"\"\"\n",
    "    return MOCK_NEWS  # later: call a real news API here\n",
    "\n",
    "def summarize_text(text: str) -> str:\n",
    "    \"\"\"Summarize any text into exactly 3 bullets.\"\"\"\n",
    "    out = client.models.generate_content(\n",
    "        model=MODEL, contents=f'Summarize in exactly 3 bullet points:\\n{text}')\n",
    "    return out.text\n",
    "\n",
    "print('Tools ready:', search_web.__name__, '+', summarize_text.__name__)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Step 2 — The agent loop (this is the important part)\n",
    "We hand both tools to Gemini and **turn OFF auto-calling** so *we* run the loop and can watch every step. A system instruction forces it to use tools instead of guessing — exactly the discipline that stops hallucinations.\n",
    "\n",
    "Read the comments: each pass is **Thought → Action → Observation**, just like the energizer."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "TOOLS = {'search_web': search_web, 'summarize_text': summarize_text}\n",
    "\n",
    "config = types.GenerateContentConfig(\n",
    "    system_instruction=(\n",
    "        'You are DataFetcher, an agent. You do NOT know recent news. '\n",
    "        'To answer, you MUST call search_web, then summarize_text. Never guess.'),\n",
    "    tools=[search_web, summarize_text],\n",
    "    automatic_function_calling=types.AutomaticFunctionCallingConfig(disable=True),\n",
    ")\n",
    "\n",
    "task = 'Find the latest AI-education news and give me a 3-bullet summary.'\n",
    "history = [types.Content(role='user', parts=[types.Part(text=task)])]\n",
    "\n",
    "for step in range(6):  # safety cap so the loop can't run forever\n",
    "    resp = client.models.generate_content(model=MODEL, contents=history, config=config)\n",
    "    parts = resp.candidates[0].content.parts\n",
    "    calls = [p.function_call for p in parts if p.function_call]\n",
    "    if not calls:\n",
    "        print('\\n🏁 FINAL ANSWER:\\n', resp.text); break\n",
    "    history.append(resp.candidates[0].content)         # Memory: remember the action\n",
    "    for fc in calls:\n",
    "        print(f'🛠️  Action → {fc.name}({dict(fc.args)})')\n",
    "        result = TOOLS[fc.name](**dict(fc.args))        # Act: run the tool\n",
    "        history.append(types.Content(role='user',       # Observation: feed result back\n",
    "            parts=[types.Part.from_function_response(name=fc.name, response={'result': result})]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "🧪 **Test:** you should see one or more `🛠️ Action →` lines (the agent calling tools), then a **3-bullet final answer**. That loop — call a tool, read the result, repeat — is a working agent. 🎉"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Step 3 — The easy way (for later projects)\n",
    "Once you understand the loop, the SDK can run it for you: just pass the tools and leave auto-calling ON. Same result, less code."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "easy = client.models.generate_content(\n",
    "    model=MODEL,\n",
    "    contents='Find the latest AI-education news and summarize it in 3 bullets.',\n",
    "    config=types.GenerateContentConfig(tools=[search_web, summarize_text]),\n",
    ")\n",
    "print(easy.text)"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 🎯 YOUR TURN: add a THIRD tool and re-run the loop with a task that needs it.\n",
    "def word_count(text: str) -> int:\n",
    "    \"\"\"Count the words in some text.\"\"\"\n",
    "    return len(text.split())\n",
    "\n",
    "# Add word_count to tools=[...] above (both cells) and try:\n",
    "# 'Summarize the AI news in 3 bullets, then tell me how many words your summary is.'\n",
    "print('Try wiring word_count into the agent!')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 🅲 Part C — Meet real data: the Titanic\n",
    "Kaggle's classic beginner dataset. Load it in **one line**, then answer a simple question — a preview of Week 3's data-analysis agents."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "URL = 'https://raw.githubusercontent.com/datasciencedojo/datasets/master/titanic.csv'\n",
    "df = pd.read_csv(URL)\n",
    "print('Rows, columns:', df.shape)\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "🧪 **Test:** you should see a table of passengers (Name, Sex, Age, Survived, ...)."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# Agent task: 'What's the average age by gender?'\n",
    "avg_age = df.groupby('Sex')['Age'].mean().round(1)\n",
    "print(avg_age)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "🧪 **Test:** you get an average age for `female` and `male`. Next week you'll wrap queries like this in **tools** so an agent can answer data questions on its own."
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 🎯 YOUR TURN: what fraction of passengers survived? (hint: df['Survived'].mean())\n",
    "print('Survival rate:', round(df['Survived'].mean(), 3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "## 🎉 You built an agent!\n",
    "You gave an LLM **tools** and ran the **ReAct loop** (Reason → Act → Observe), then loaded real data.\n",
    "\n",
    "**Homework:** explore one 'Getting Started' Kaggle competition, and jot a first project idea in the shared template.\n",
    "\n",
    "**Next week — Data Analysis Agents:** you'll turn pandas queries and charts into agent tools, then scope your own project.\n",
    "\n",
    "_AI Trailblazers · LearnAI · part of MillionRoots._"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "name": "Week 2 — DataFetcher Agent",
   "provenance": []
  },
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}