Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
348 changes: 348 additions & 0 deletions week8/community_contributions/IbrahimSheriff/week8_exercise.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,348 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Week 8 Exercise: The Price is Right — IbrahimSheriff\n",
"\n",
"## Overview\n",
"This notebook implements a complete Week 8–style pipeline:\n",
"- **SpecialistAgent**: Fine-tuned LLM deployed on Modal\n",
"- **FrontierAgent**: RAG + frontier model (GPT) with ChromaDB\n",
"- **ChromaDB**: Vector store of product embeddings (SentenceTransformer)\n",
"- **Ensemble**: Combined predictor (Specialist + Frontier)\n",
"- **Evaluation**: Official `evaluate()` on test set (average absolute error)\n",
"- **DealAgentFramework + Gradio UI**: Autonomous deal-hunting and table UI\n",
"\n",
"## Prerequisites\n",
"- Modal token set; HuggingFace secret in Modal (`huggingface-secret`)\n",
"- Deploy pricer: from **week8** folder run `uv run modal deploy -m pricer_service`\n",
"- `.env`: `HF_TOKEN`, `OPENAI_API_KEY` (for FrontierAgent)\n",
"---"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Setup: path and environment"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import sys\n",
"import logging\n",
"from pathlib import Path\n",
"from dotenv import load_dotenv\n",
"\n",
"load_dotenv(override=True)\n",
"os.environ.setdefault(\"PYTHONIOENCODING\", \"utf-8\")\n",
"\n",
"notebook_dir = Path.cwd()\n",
"week8_root = notebook_dir.parent.parent\n",
"if str(week8_root) not in sys.path:\n",
" sys.path.insert(0, str(week8_root))\n",
"\n",
"logging.getLogger().setLevel(logging.INFO)\n",
"print(f\"Week 8 root: {week8_root}\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"required = [\"HF_TOKEN\", \"OPENAI_API_KEY\"]\n",
"for var in required:\n",
" status = \"SET\" if os.getenv(var) else \"MISSING\"\n",
" print(f\" {var}: {status}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Load data (Item.from_hub)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from agents.items import Item\n",
"from huggingface_hub import login\n",
"\n",
"hf_token = os.environ.get(\"HF_TOKEN\")\n",
"if hf_token:\n",
" login(token=hf_token, add_to_git_credential=False)\n",
"\n",
"LITE_MODE = False\n",
"username = \"ed-donner\"\n",
"dataset = f\"{username}/items_lite\" if LITE_MODE else f\"{username}/items_full\"\n",
"\n",
"train, val, test = Item.from_hub(dataset)\n",
"print(f\"Loaded {len(train):,} train, {len(val):,} val, {len(test):,} test items\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. ChromaDB vector store\n",
"\n",
"We build the vector store in the current folder so DealAgentFramework can use it later. Use a subset for speed if you prefer."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import chromadb\n",
"from sentence_transformers import SentenceTransformer\n",
"from tqdm.notebook import tqdm\n",
"\n",
"DB = \"products_vectorstore\"\n",
"client = chromadb.PersistentClient(path=DB)\n",
"collection = client.get_or_create_collection(\"products\")\n",
"\n",
"def description(item):\n",
" return (item.summary or item.title or \"\").strip() or getattr(item, \"prompt\", \"\")[:500]\n",
"\n",
"N_DOCS = 20_000\n",
"existing = collection.count()\n",
"print(f\"Collection has {existing} documents.\")\n",
"if existing == 0:\n",
" print(f\"Populating with {N_DOCS} items...\")\n",
" encoder = SentenceTransformer(\"sentence-transformers/all-MiniLM-L6-v2\")\n",
" for i in tqdm(range(0, min(N_DOCS, len(train)), 1000)):\n",
" batch = train[i : i + 1000]\n",
" docs = [description(it) for it in batch]\n",
" vecs = encoder.encode(docs).astype(float).tolist()\n",
" metas = [{\"category\": getattr(it, \"category\", \"\"), \"price\": it.price} for it in batch]\n",
" ids = [f\"doc_{j}\" for j in range(i, i + len(batch))]\n",
" collection.add(ids=ids, documents=docs, embeddings=vecs, metadatas=metas)\n",
" print(f\"Done. Collection count: {collection.count()}\")\n",
"else:\n",
" print(\"Using existing vector store.\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 4. SpecialistAgent (Modal fine-tuned pricer)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from agents.specialist_agent import SpecialistAgent\n",
"\n",
"specialist = SpecialistAgent()\n",
"sample = test[0]\n",
"est = specialist.price(description(sample))\n",
"print(f\"Sample: {sample.title[:50]}...\")\n",
"print(f\"Actual: ${sample.price:.2f}, Specialist: ${est:.2f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5. FrontierAgent (RAG + frontier model)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from agents.frontier_agent import FrontierAgent\n",
"\n",
"frontier = FrontierAgent(collection)\n",
"est_f = frontier.price(description(sample))\n",
"print(f\"Frontier estimate: ${est_f:.2f}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 6. Predictors for evaluator\n",
"\n",
"Each takes an `Item` and returns a price (for `evaluate(predictor, test)`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def specialist_predictor(item):\n",
" return specialist.price(description(item))\n",
"\n",
"def frontier_predictor(item):\n",
" return frontier.price(description(item))\n",
"\n",
"def ensemble_predictor(item):\n",
" s = specialist.price(description(item))\n",
" f = frontier.price(description(item))\n",
" return 0.5 * s + 0.5 * f"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 7. Run evaluation (Week 8 implementation)\n",
"\n",
"Uses the same `evaluate()` as week8 day2: 200 items, report and charts. This **determines your result**."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from agents.evaluator import evaluate\n",
"\n",
"print(\"=== SpecialistAgent ===\")\n",
"evaluate(specialist_predictor, test)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"=== FrontierAgent ===\")\n",
"evaluate(frontier_predictor, test)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print(\"=== Ensemble (Specialist + Frontier) ===\")\n",
"evaluate(ensemble_predictor, test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 8. Optional: quick run with fewer items\n",
"\n",
"Uncomment to test with 50 items and 3 workers."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# evaluate(specialist_predictor, test, size=50, workers=3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 9. DealAgentFramework + Gradio UI\n",
"\n",
"Uses the same framework as week8 day5: planning agent, scanner, messenger. The UI shows a table of deals and a button to run one planning cycle. Ensure `products_vectorstore` is in the current directory (we built it above)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import gradio as gr\n",
"from deal_agent_framework import DealAgentFramework\n",
"from agents.deals import Opportunity, Deal\n",
"\n",
"agent_framework = DealAgentFramework()\n",
"agent_framework.init_agents_as_needed()\n",
"print(\"DealAgentFramework ready.\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def get_table(opps):\n",
" if not opps:\n",
" return [[\"No deals yet\", \"—\", \"—\", \"—\", \"—\"]]\n",
" return [\n",
" [\n",
" opp.deal.product_description[:80] + (\".\" if len(opp.deal.product_description) > 80 else \"\"),\n",
" f\"${opp.deal.price:.2f}\",\n",
" f\"${opp.estimate:.2f}\",\n",
" f\"${opp.discount:.2f}\",\n",
" opp.deal.url or \"—\",\n",
" ]\n",
" for opp in opps\n",
" ]\n",
"\n",
"def run_one_cycle():\n",
" agent_framework.run()\n",
" return get_table(agent_framework.memory)\n",
"\n",
"with gr.Blocks(title=\"The Price is Right\", fill_width=True) as ui:\n",
" gr.Markdown(\"<div style='text-align: center; font-size: 24px'>The Price is Right — IbrahimSheriff</div>\")\n",
" gr.Markdown(\"Deals surfaced by the autonomous agent (Specialist + Frontier + Scanner + Planner).\")\n",
" with gr.Row():\n",
" run_btn = gr.Button(\"Run one planning cycle\")\n",
" tbl = gr.Dataframe(\n",
" headers=[\"Description\", \"Price\", \"Estimate\", \"Discount\", \"URL\"],\n",
" wrap=True,\n",
" row_count=10,\n",
" col_count=5,\n",
" max_height=400,\n",
" )\n",
" run_btn.click(fn=run_one_cycle, outputs=[tbl])\n",
" ui.load(fn=lambda: get_table(agent_framework.memory), outputs=[tbl])\n",
"\n",
"ui.launch(inbrowser=True)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"name": "python",
"version": "3.11.0"
}
},
"nbformat": 4,
"nbformat_minor": 4
}