Few-shot
Classify a support message into one label — billing, bug, feature_request,
Showcase — Few-shot
Classify a support message into one label — billing, bug, feature_request, praise, other. A checkbox flips the few-shot examples on and off. With the examples in the prompt, the label set and the one-line format stay put. Turn them off and the model starts inventing labels and wrapping them in prose.
Run
bash bootstrap-secrets.sh # reads ../../../../.env, writes secrets/
docker compose up --build # default: PROVIDER=openai
Open http://localhost:3000.
To run against Gemini instead:
PROVIDER=gemini docker compose up --build
What's where
backend/ai_openai.py— theINSTRUCTION+EXAMPLESblock (the lesson) and the OpenAI callbackend/ai_gemini.py— same prompt, Gemini callbackend/main.py— identical FastAPI loader; reads PROVIDER and dispatchesfrontend/app/page.tsx— textarea + few-shot checkbox + resultdocker-compose.yml— two services, secrets mounted from./secrets/
The frontend encodes <mode>\n---\n<message> (mode is zeroshot or
fewshot) into the single-string input, keeping the
def run(input: str) -> str contract identical across the week's showcases.
Stop
docker compose down
Ejecútalo en tu máquina
Descarga el proyecto como ZIP y córrelo con Docker. Levanta un backend FastAPI y un frontend Next.js en localhost:3000.
unzip few-shot.zip
cd few-shot
bash bootstrap-secrets.sh # one-time: pulls API keys into ./secrets
docker compose up --build # default provider: openai
# or: PROVIDER=gemini docker compose up --build
Escribe algo, elige un proveedor y ejecuta el mismo código de Código contra la API real. Requiere iniciar sesión.
Los mismos módulos que ejecuta el botón Run. El proyecto completo (frontend, Dockerfile, compose) está en el ZIP, pestaña README.
backend/ai_openai.py
"""Week 2 - Showcase 2 (OpenAI): zero-shot vs few-shot, side by side.
Same classification task, same instruction. The only thing the toggle
changes is whether a handful of worked examples ride along in the prompt.
Zero-shot drifts on the label set and the format; few-shot locks both.
The frontend encodes "<mode>\\n---\\n<text>" where mode is zeroshot|fewshot.
"""
from openai import OpenAI
_client = OpenAI()
LABELS = "billing, bug, feature_request, praise, other"
INSTRUCTION = (
"Classify the support message into exactly one of these labels: "
f"{LABELS}. Respond with only `label: <one label>` and nothing else."
)
# The few-shot block: three worked examples that pin the label vocabulary
# and the output line. This is the entire difference the toggle makes.
EXAMPLES = """
Message: My card got charged twice this month.
label: billing
Message: The export button does nothing when I click it.
label: bug
Message: Any chance you could add dark mode?
label: feature_request
""".strip()
def run(payload: str) -> str:
mode, _, text = payload.partition("\n---\n")
mode = (mode or "fewshot").strip()
text = (text or payload).strip()
if mode == "zeroshot":
prompt = f"{INSTRUCTION}\n\nMessage: {text}"
else:
prompt = f"{INSTRUCTION}\n\n{EXAMPLES}\n\nMessage: {text}"
response = _client.responses.create(
model="gpt-5.4-nano", input=prompt, max_output_tokens=20,
)
return response.output_text
backend/ai_gemini.py
"""Week 2 - Showcase 2 (Gemini): zero-shot vs few-shot, side by side."""
import os
from google import genai
from google.genai import types
_client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
LABELS = "billing, bug, feature_request, praise, other"
INSTRUCTION = (
"Classify the support message into exactly one of these labels: "
f"{LABELS}. Respond with only `label: <one label>` and nothing else."
)
EXAMPLES = """
Message: My card got charged twice this month.
label: billing
Message: The export button does nothing when I click it.
label: bug
Message: Any chance you could add dark mode?
label: feature_request
""".strip()
def run(payload: str) -> str:
mode, _, text = payload.partition("\n---\n")
mode = (mode or "fewshot").strip()
text = (text or payload).strip()
if mode == "zeroshot":
prompt = f"{INSTRUCTION}\n\nMessage: {text}"
else:
prompt = f"{INSTRUCTION}\n\n{EXAMPLES}\n\nMessage: {text}"
response = _client.models.generate_content(
model="gemini-3.1-flash-lite",
contents=prompt,
config=types.GenerateContentConfig(max_output_tokens=20),
)
return response.text
Archivos del proyecto
.gitignoreREADME.mdbackend/Dockerfilebackend/ai_gemini.pybackend/ai_openai.pybackend/main.pybackend/requirements.txtbootstrap-secrets.shdocker-compose.ymlfrontend/Dockerfilefrontend/app/layout.tsxfrontend/app/page.tsxfrontend/next.config.tsfrontend/package.jsonfrontend/tsconfig.json