This is your single submission for the day. It has two parts:
Part A · Tutorial — a hands-on Python primer, then your first call to a language model.
Part B · Corpus Lab — short Python exercises you complete and self-check.
You only edit the cells marked ✏️ YOU EDIT. Cells marked 🔧 Library cell are pre-written — run them, don’t change them.
➡️ Work top to bottom. When you’re done, Runtime → Run all, then File → Download → Download .ipynb and submit that file.
Part A · Tutorial — a 15-minute Python primer
No prior Python needed. Run each cell, read the output, then change a value and re-run to see what happens. Everything this week is built from these few ideas.
1. Variables & data types
A variable is a name for a value. Python’s core types you’ll use all week: string (str, text), integer (int) and float (decimal number), list (an ordered sequence), and dictionary (dict, key → value pairs).
Show code
sentence ="The cat sat on the mat."# str — text, in quotesword_count =6# int — whole numberscore =4.5# float — decimal numberlevels = ["A1", "A2", "B1"] # list — ordered, square bracketsitem = {"id": 1, "text": sentence, "label": "A1"} # dict — key: valueprint(type(sentence), type(word_count), type(score))print("levels[0] =", levels[0]) # lists are indexed from 0print("item['label'] =", item["label"]) # look up a dict value by its key
2. if statements — make a decision
Run one branch or another depending on a condition. Indentation (4 spaces) is how Python groups the lines that belong to each branch.
Show code
score =4.5if score <4: band ="Low"elif score <7: band ="Mid"else: band ="High"print("score", score, "→ band", band)
3. for loops — do something to every item
Loop over a list, or over a dictionary’s items. This is exactly how we’ll process every sentence in a dataset.
Show code
for level in levels:print("level:", level)print("---")for key, value in item.items():print(key, "→", value)
4. Functions — name a reusable piece of code
A function takes inputs (arguments) and returns a result. Define once, call as often as you like.
Show code
def band_of(score):"""Turn a numeric score into a Low/Mid/High band."""if score <4:return"Low"elif score <7:return"Mid"return"High"print(band_of(2), band_of(5), band_of(9))
5. Basic input / output
print(...) shows a value. To read data, we mostly parse JSON — the {id, text, label} shape you’ll see all week. (input() also reads from the keyboard, but it pauses Run all, so we avoid it here.)
Show code
raw ='[{"id": 1, "text": "Hello.", "label": "A1"}, {"id": 2, "text": "Nevertheless, the findings were inconclusive.", "label": "C1"}]'data = json.loads(raw) # JSON text → Python list of dictsprint("number of items:", len(data))for row in data:print(row["id"], row["label"], "|", row["text"])# (Reading from the keyboard — left commented so Run all does not pause:)# name = input("Your name: ")# print("Hello,", name)
6. Meet the model — your first LLM call
Run the setup cell (loads the LLM backend — in Colab that’s the free built-in Gemini, no key needed), then send the model a prompt with generate_text(...).
Show code
#@title 📦 Setup — run me first { display-mode: "form" }# Imports + the LLM backend. No pip install needed in Colab.import json, re, urllib.request, osfrom sklearn.metrics import classification_report, confusion_matriximport pandas as pd, seaborn as sns, matplotlib.pyplot as pltMODEL_ID ="gemini-2.5-flash"# pinned model for the reproducible (API) backenddef _resolve_gemini_key():"""Find a Gemini API key: Colab Secrets first (not auto-exported to env), then env."""try:from google.colab import userdata # only exists in Colab key = userdata.get("GEMINI_API_KEY")if key:return keyexceptException:pass# not in Colab, or secret not setreturn os.environ.get("GEMINI_API_KEY")def _make_api_backend(key):"""Reproducible backend: Gemini API with temperature=0 + a fixed seed."""from google import genaifrom google.genai import types client = genai.Client(api_key=key) cfg = types.GenerateContentConfig(temperature=0, seed=42)return (lambda p: client.models.generate_content( model=MODEL_ID, contents=p, config=cfg).text,f"Gemini API ({MODEL_ID}, temperature=0, seed=42)")# Prefer the API key when set (reproducible); else fall back to colab.ai (demo)._key = _resolve_gemini_key()if _key: generate_text, _backend = _make_api_backend(_key)else:try:from google.colab import ai # Colab's built-in Gemini — no key generate_text, _backend = (lambda p: ai.generate_text(p)), "Colab Gemini (demo, non-reproducible)"exceptImportError:raiseRuntimeError("No LLM backend found. Run this notebook in Google Colab (free built-in ""Gemini, no key needed), or set GEMINI_API_KEY — in Colab via the Secrets ""panel, or as an environment variable when running locally. ""See resources/tools/gemini-api-key.md.")print(f"Setup done. LLM backend: {_backend}. scikit-learn ready.")
✏️ YOU EDIT — change the prompt and re-run.
Show code
reply = generate_text("In one sentence, what is applied linguistics?")print(reply)
Part B · Corpus Lab — Python practice
Fill in each function so it does what its docstring says (replace the raise NotImplementedError(...) line). Then run the self-check cell at the bottom until every line prints ✅. No grader needed — the checks are your grader.
Show code
# ✏️ YOU EDIT — replace each NotImplementedError with your code.def label_of(item):"""Return the value stored under the key "label" in the dict `item`. Example: label_of({"id": 1, "text": "Hi", "label": "A1"}) -> "A1". """raiseNotImplementedError("Return item['label'].")def long_words(words, n):"""Return a LIST of the words whose length is greater than n. Example: long_words(["a", "cat", "elephant"], 3) -> ["elephant"]. """# HINT: build a result list; loop with `for w in words:`; keep w if len(w) > n.raiseNotImplementedError("Return the words longer than n characters.")def count_labels(items):"""Given a list of {id, text, label} dicts, return a dict mapping each label to how many times it appears. Example: count_labels([{"label":"A1"}, {"label":"A1"}, {"label":"B1"}]) -> {"A1": 2, "B1": 1}. """# HINT: start with counts = {}; for each item, add 1 to counts[label]# (use counts.get(label, 0) + 1 so the first time starts at 0).raiseNotImplementedError("Count how many items carry each label.")
Show code
#@title 🔎 Self-check — run me { display-mode: "form" }sample = [{"id": 1, "text": "Hi.", "label": "A1"}, {"id": 2, "text": "Hello there.", "label": "A1"}, {"id": 3, "text": "Nevertheless...", "label": "C1"}]checks = [ ("label_of", label_of(sample[0]) =="A1"), ("long_words", long_words(["a", "cat", "elephant"], 3) == ["elephant"]), ("count_labels", count_labels(sample) == {"A1": 2, "C1": 1}),]for name, ok in checks:print(("✅"if ok else"❌"), name)print("All passed ✅"ifall(ok for _, ok in checks)else"Some checks failed — fix them and re-run.")
✅ Before you submit
Runtime → Run all and check every cell ran without error.
Part A outputs are visible (tables / charts / the model’s answers).
Part B self-check prints ✅ (or your TODO answers are filled in).
File → Download → Download .ipynb and upload that one file.