diff --git a/community-contributions/muhammad_qasim_sheikh/Week 7/fine_tuned_open_source.ipynb b/community-contributions/muhammad_qasim_sheikh/Week 7/fine_tuned_open_source.ipynb new file mode 100644 index 0000000..dfe57e2 --- /dev/null +++ b/community-contributions/muhammad_qasim_sheikh/Week 7/fine_tuned_open_source.ipynb @@ -0,0 +1,463 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 9, + "id": "f0c31d90", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import torch\n", + "import wandb\n", + "from datetime import datetime\n", + "from datasets import load_dataset\n", + "from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, EarlyStoppingCallback, set_seed\n", + "from peft import LoraConfig, PeftModel\n", + "from trl import SFTTrainer, SFTConfig, DataCollatorForCompletionOnlyLM\n", + "import math\n", + "import matplotlib.pyplot as plt\n", + "import torch.nn.functional as F" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "768666b4", + "metadata": {}, + "outputs": [], + "source": [ + "# Testing it on the lite pricer data that I have created\n", + "DATASET_NAME = f\"qshaikh/lite-pricer-data\"\n", + "dataset = load_dataset(DATASET_NAME)\n", + "train = dataset['train']\n", + "test = dataset['test']\n", + "split_ratio = 0.10 # 10% for validation\n", + "\n", + "TRAIN_SIZE = 15000\n", + "train = train.select(range(TRAIN_SIZE))\n", + "\n", + "total_size = len(train)\n", + "val_size = int(total_size * split_ratio)\n", + "\n", + "val_data = train.select(range(val_size))\n", + "train_data = train.select(range(val_size, total_size))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "12e2b634", + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"Train data size : {len(train_data)}\")\n", + "print(f\"Validation data size: {len(val_data)}\")\n", + "print(f\"Test data size : {len(test)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1a75961f", + "metadata": {}, + "outputs": [], + "source": [ + "PROJECT_NAME = \"llama3-new-pricer\"\n", + "RUN_NAME = f\"{datetime.now():%Y-%m-%d_%H.%M.%S}-size{total_size}\"\n", + "PROJECT_RUN_NAME = f\"{PROJECT_NAME}-{RUN_NAME}\"\n", + "HUB_MODEL_NAME = f\"qshaikh/{PROJECT_RUN_NAME}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf9bca38", + "metadata": {}, + "outputs": [], + "source": [ + "LOG_TO_WANDB = True\n", + "os.environ[\"WANDB_PROJECT\"] = PROJECT_NAME\n", + "os.environ[\"WANDB_LOG_MODEL\"] = \"checkpoint\" if LOG_TO_WANDB else \"end\"\n", + "os.environ[\"WANDB_WATCH\"] = \"gradients\"\n", + "\n", + "if LOG_TO_WANDB:\n", + " wandb.init(project=PROJECT_NAME, name=RUN_NAME)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77e0ee8c", + "metadata": {}, + "outputs": [], + "source": [ + "BASE_MODEL = \"meta-llama/Llama-3.2-1B\"\n", + "\n", + "quant_config = BitsAndBytesConfig(\n", + " load_in_4bit=True, \n", + " bnb_4bit_use_double_quant=True,\n", + " bnb_4bit_compute_dtype=torch.bfloat16,\n", + " bnb_4bit_quant_type=\"nf4\"\n", + ")\n", + "\n", + "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True)\n", + "tokenizer.pad_token = tokenizer.eos_token\n", + "tokenizer.padding_side = \"right\"\n", + "\n", + "base_model = AutoModelForCausalLM.from_pretrained(\n", + " BASE_MODEL,\n", + " quantization_config=quant_config,\n", + " device_map=\"auto\",\n", + ")\n", + "base_model.generation_config.pad_token_id = tokenizer.pad_token_id\n", + "\n", + "print(f\"Memory footprint: {base_model.get_memory_footprint() / 1e6:.1f} MB\")" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "bf4a0187", + "metadata": {}, + "outputs": [], + "source": [ + "response_template = \"Price is $\"\n", + "collator = DataCollatorForCompletionOnlyLM(response_template, tokenizer=tokenizer)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "25ce4f40", + "metadata": {}, + "outputs": [], + "source": [ + "LORA_R = 32\n", + "LORA_ALPHA = 64\n", + "TARGET_MODULES = [\"q_proj\", \"v_proj\", \"k_proj\", \"o_proj\"]\n", + "LORA_DROPOUT = 0.1" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "e1e6c237", + "metadata": {}, + "outputs": [], + "source": [ + "lora_parameters = LoraConfig(\n", + " r=LORA_R,\n", + " lora_alpha=LORA_ALPHA,\n", + " lora_dropout=LORA_DROPOUT,\n", + " target_modules=TARGET_MODULES,\n", + " bias=\"none\",\n", + " task_type=\"CAUSAL_LM\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f68d0fdc", + "metadata": {}, + "outputs": [], + "source": [ + "EPOCHS = 1\n", + "BATCH_SIZE = 8 # Tested it with 4 first to be on the safer side, however was taking too long. Increased it upto 8 then.\n", + "GRADIENT_ACCUMULATION_STEPS = 1\n", + "MAX_SEQUENCE_LENGTH = 182\n", + "LEARNING_RATE = 1e-4\n", + "LR_SCHEDULER_TYPE = 'cosine'\n", + "WARMUP_RATIO = 0.03\n", + "OPTIMIZER = \"paged_adamw_32bit\"\n", + "\n", + "SAVE_STEPS = 200\n", + "STEPS = 20\n", + "save_total_limit = 10\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37c3ab80", + "metadata": {}, + "outputs": [], + "source": [ + "train_parameters = SFTConfig(\n", + " output_dir=PROJECT_RUN_NAME,\n", + " run_name=RUN_NAME,\n", + " dataset_text_field=\"text\",\n", + " max_seq_length=MAX_SEQUENCE_LENGTH,\n", + "\n", + " num_train_epochs=EPOCHS,\n", + " per_device_train_batch_size=BATCH_SIZE,\n", + " gradient_accumulation_steps=GRADIENT_ACCUMULATION_STEPS,\n", + " max_steps=-1,\n", + " group_by_length=True,\n", + "\n", + " eval_strategy=\"steps\",\n", + " eval_steps=STEPS,\n", + " per_device_eval_batch_size=1,\n", + "\n", + " learning_rate=LEARNING_RATE,\n", + " lr_scheduler_type=LR_SCHEDULER_TYPE,\n", + " warmup_ratio=WARMUP_RATIO,\n", + " optim=OPTIMIZER,\n", + " weight_decay=0.001,\n", + " max_grad_norm=0.3,\n", + "\n", + " fp16=False,\n", + " bf16=True,\n", + "\n", + " logging_steps=STEPS,\n", + " save_strategy=\"steps\",\n", + " save_steps=SAVE_STEPS,\n", + " save_total_limit=save_total_limit,\n", + " report_to=\"wandb\" if LOG_TO_WANDB else None,\n", + "\n", + " push_to_hub=True,\n", + " hub_strategy=\"every_save\",\n", + " load_best_model_at_end=True,\n", + " metric_for_best_model=\"eval_loss\",\n", + " greater_is_better=False\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56abe69d", + "metadata": {}, + "outputs": [], + "source": [ + "fine_tuning = SFTTrainer(\n", + " model=base_model,\n", + " train_dataset=train_data,\n", + " eval_dataset=val_data,\n", + " peft_config=lora_parameters, \n", + " args=train_parameters, \n", + " data_collator=collator,\n", + " callbacks=[EarlyStoppingCallback(early_stopping_patience=5)] \n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17ed25ec", + "metadata": {}, + "outputs": [], + "source": [ + "fine_tuning.train()\n", + "print(f\"Best model pushed to HF Hub: {HUB_MODEL_NAME}\")" + ] + }, + { + "cell_type": "markdown", + "id": "7230239e", + "metadata": {}, + "source": [ + "## Evaluating Model Performance" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "61c2955c", + "metadata": {}, + "outputs": [], + "source": [ + "GREEN = \"\\033[92m\"\n", + "YELLOW = \"\\033[93m\"\n", + "RED = \"\\033[91m\"\n", + "RESET = \"\\033[0m\"\n", + "COLOR_MAP = {\"red\":RED, \"orange\": YELLOW, \"green\": GREEN}\n", + "\n", + "class Tester:\n", + "\n", + " def __init__(self, predictor, data, title=None, size=250):\n", + " self.predictor = predictor\n", + " self.data = data\n", + " self.title = title or predictor.__name__.replace(\"_\", \" \").title()\n", + " self.size = size\n", + " self.guesses = []\n", + " self.truths = []\n", + " self.errors = []\n", + " self.sles = []\n", + " self.colors = []\n", + "\n", + " def color_for(self, error, truth):\n", + " if error<40 or error/truth < 0.2:\n", + " return \"green\"\n", + " elif error<80 or error/truth < 0.4:\n", + " return \"orange\"\n", + " else:\n", + " return \"red\"\n", + "\n", + " def run_datapoint(self, i):\n", + " datapoint = self.data[i]\n", + " guess = self.predictor(datapoint[\"text\"])\n", + " truth = datapoint[\"price\"]\n", + " error = abs(guess - truth)\n", + " log_error = math.log(truth+1) - math.log(guess+1)\n", + " sle = log_error ** 2\n", + " color = self.color_for(error, truth)\n", + " self.guesses.append(guess)\n", + " self.truths.append(truth)\n", + " self.errors.append(error)\n", + " self.sles.append(sle)\n", + " self.colors.append(color)\n", + "\n", + " def chart(self, title):\n", + " plt.figure(figsize=(12, 8))\n", + " max_val = max(max(self.truths), max(self.guesses))\n", + " plt.plot([0, max_val], [0, max_val], color='deepskyblue', lw=2, alpha=0.6)\n", + " plt.scatter(self.truths, self.guesses, s=3, c=self.colors)\n", + " plt.xlabel('Ground Truth')\n", + " plt.ylabel('Model Estimate')\n", + " plt.xlim(0, max_val)\n", + " plt.ylim(0, max_val)\n", + " plt.title(title)\n", + "\n", + " from matplotlib.lines import Line2D\n", + " legend_elements = [\n", + " Line2D([0], [0], marker='o', color='w', label='Accurate (green)', markerfacecolor='green', markersize=8),\n", + " Line2D([0], [0], marker='o', color='w', label='Medium error (orange)', markerfacecolor='orange', markersize=8),\n", + " Line2D([0], [0], marker='o', color='w', label='High error (red)', markerfacecolor='red', markersize=8)\n", + " ]\n", + " plt.legend(handles=legend_elements, loc='upper right')\n", + "\n", + " plt.show()\n", + "\n", + "\n", + " def report(self):\n", + " average_error = sum(self.errors) / self.size\n", + " rmsle = math.sqrt(sum(self.sles) / self.size)\n", + " hits = sum(1 for color in self.colors if color==\"green\")\n", + " title = f\"{self.title} Error=${average_error:,.2f} RMSLE={rmsle:,.2f} Hits={hits/self.size*100:.1f}%\"\n", + " self.chart(title)\n", + "\n", + " def run(self):\n", + " self.error = 0\n", + " for i in range(self.size):\n", + " self.run_datapoint(i)\n", + " self.report()\n", + "\n", + " @classmethod\n", + " def test(cls, function, data):\n", + " cls(function, data).run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1ff9de0", + "metadata": {}, + "outputs": [], + "source": [ + "test[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b88ec79", + "metadata": {}, + "outputs": [], + "source": [ + "FINETUNED_MODEL = \"qshaikh/llama3-new-pricer-2025-10-29_00.32.54-size15000\"\n", + "fine_tuned_model = PeftModel.from_pretrained(base_model, FINETUNED_MODEL)\n", + "print(f\"Memory footprint: {fine_tuned_model.get_memory_footprint() / 1e6:.1f} MB\")\n", + "fine_tuned_model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb2d3a22", + "metadata": {}, + "outputs": [], + "source": [ + "top_K = 3\n", + "\n", + "def improved_model_predict(prompt, device=\"cuda\"):\n", + " set_seed(42) \n", + " inputs = tokenizer.encode(prompt, return_tensors=\"pt\").to(device)\n", + " attention_mask = torch.ones(inputs.shape, device=device)\n", + "\n", + " with torch.no_grad(): \n", + " outputs = fine_tuned_model(inputs, attention_mask=attention_mask)\n", + " next_token_logits = outputs.logits[:, -1, :].to('cpu')\n", + "\n", + " next_token_probs = F.softmax(next_token_logits, dim=-1)\n", + " top_prob, top_token_id = next_token_probs.topk(top_K)\n", + "\n", + " prices, weights = [], [] \n", + "\n", + " for i in range(top_K):\n", + " predicted_token = tokenizer.decode(top_token_id[0][i])\n", + " probability = top_prob[0][i]\n", + "\n", + " try:\n", + " result = float(predicted_token)\n", + " except ValueError as e:\n", + " result = 0.0\n", + "\n", + " if result > 0:\n", + " prices.append(result)\n", + " weights.append(probability)\n", + "\n", + " if not prices:\n", + " return 0.0, 0.0\n", + "\n", + " total = sum(weights)\n", + "\n", + " weighted_prices = [price * weight / total for price, weight in zip(prices, weights)]\n", + "\n", + " return sum(weighted_prices).item()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc47ff1e", + "metadata": {}, + "outputs": [], + "source": [ + "improved_model_predict(test[0][\"text\"], device=\"cuda\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3dbecfff", + "metadata": {}, + "outputs": [], + "source": [ + "Tester.test(improved_model_predict, test)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/community-contributions/muhammad_qasim_sheikh/Week 8/Ensemble_Model.ipynb b/community-contributions/muhammad_qasim_sheikh/Week 8/Ensemble_Model.ipynb new file mode 100644 index 0000000..1269895 --- /dev/null +++ b/community-contributions/muhammad_qasim_sheikh/Week 8/Ensemble_Model.ipynb @@ -0,0 +1,538 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "mzYB4XYQeWRQ", + "metadata": { + "id": "mzYB4XYQeWRQ" + }, + "outputs": [], + "source": [ + "!pip install tqdm huggingface_hub numpy sentence-transformers datasets chromadb catboost peft torch bitsandbytes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b3caecd1-8712-4acd-80b5-e8059c16f43f", + "metadata": { + "id": "b3caecd1-8712-4acd-80b5-e8059c16f43f" + }, + "outputs": [], + "source": [ + "import os\n", + "import re\n", + "import zipfile\n", + "import chromadb\n", + "import joblib\n", + "import numpy as np\n", + "import pandas as pd\n", + "import requests\n", + "import torch\n", + "from datasets import load_dataset\n", + "from google.colab import userdata\n", + "from huggingface_hub import HfApi, hf_hub_download, login\n", + "from openai import OpenAI\n", + "from peft import PeftModel\n", + "from sentence_transformers import SentenceTransformer\n", + "from sklearn.linear_model import LinearRegression\n", + "from sklearn.metrics import r2_score, mean_squared_error\n", + "from tqdm import tqdm\n", + "from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig\n", + "from catboost import CatBoostRegressor" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "05d9523f-b6c9-4132-bd2b-6712772b3cd2", + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "05d9523f-b6c9-4132-bd2b-6712772b3cd2", + "outputId": "f6bb70c7-58f8-4e3c-a592-83cfb4f395a7" + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Mounted at /content/drive\n" + ] + } + ], + "source": [ + "from google.colab import drive\n", + "drive.mount(\"/content/drive\")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "z9735RD_TUHw", + "metadata": { + "id": "z9735RD_TUHw" + }, + "outputs": [], + "source": [ + "openai_api_key = userdata.get(\"OPENAI_API_KEY\")\n", + "openai = OpenAI(api_key=openai_api_key)\n", + "\n", + "hf_token = userdata.get(\"HF_TOKEN\")\n", + "login(hf_token, add_to_git_credential=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "DtswsfBQxxJF", + "metadata": { + "id": "DtswsfBQxxJF" + }, + "outputs": [], + "source": [ + "# Configuration\n", + "HF_USER = \"qshaikh\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0eKakxSFTVcA", + "metadata": { + "collapsed": true, + "id": "0eKakxSFTVcA" + }, + "outputs": [], + "source": [ + "DATASET_NAME = f\"{HF_USER}/pricer-data\"\n", + "dataset = load_dataset(DATASET_NAME)\n", + "test = dataset[\"test\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cWqvs8JRTggE", + "metadata": { + "collapsed": true, + "id": "cWqvs8JRTggE" + }, + "outputs": [], + "source": [ + "def description(item):\n", + " text = item[\"text\"].replace(\n", + " \"How much does this cost to the nearest dollar?\\n\\n\", \"\"\n", + " )\n", + " text = text.split(\"\\n\\nPrice is $\")[0]\n", + " return f\"passage: {text}\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "pjPBEgXqmHOA", + "metadata": { + "id": "pjPBEgXqmHOA" + }, + "outputs": [], + "source": [ + "CHROMA_PATH = \"/content/drive/MyDrive/chroma\"\n", + "COLLECTION_NAME = \"price_items\"\n", + "\n", + "print(f\"Attempting to load ChromaDB from: {CHROMA_PATH}\")\n", + "\n", + "client = chromadb.PersistentClient(path=CHROMA_PATH)\n", + "collection = client.get_or_create_collection(name=COLLECTION_NAME)\n", + "\n", + "print(f\"Successfully loaded ChromaDB collection '{COLLECTION_NAME}'.\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8fi1BS71XCv1", + "metadata": { + "id": "8fi1BS71XCv1" + }, + "outputs": [], + "source": [ + "embedding_model = SentenceTransformer(\"intfloat/e5-small-v2\", device=\"cuda\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "zmwIbufXUzMo", + "metadata": { + "id": "zmwIbufXUzMo" + }, + "outputs": [], + "source": [ + "BASE_MODEL = \"meta-llama/Llama-3.1-8B\"\n", + "FINETUNED_MODEL = \"ed-donner/pricer-2024-09-13_13.04.39\"\n", + "REVISION = \"e8d637df551603dc86cd7a1598a8f44af4d7ae36\"\n", + "\n", + "quant_config = BitsAndBytesConfig(\n", + " load_in_4bit=True,\n", + " bnb_4bit_use_double_quant=True,\n", + " bnb_4bit_compute_dtype=torch.bfloat16,\n", + " bnb_4bit_quant_type=\"nf4\",\n", + ")\n", + "\n", + "tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True)\n", + "tokenizer.pad_token = tokenizer.eos_token\n", + "tokenizer.padding_side = \"right\"\n", + "\n", + "base_model = AutoModelForCausalLM.from_pretrained(\n", + " BASE_MODEL, quantization_config=quant_config, device_map=\"auto\"\n", + ")\n", + "\n", + "fine_tuned_model = PeftModel.from_pretrained(\n", + " base_model, FINETUNED_MODEL, revision=REVISION\n", + ")\n", + "\n", + "fine_tuned_model.generation_config.pad_token_id = tokenizer.pad_token_id\n", + "\n", + "print(f\"Memory footprint: {fine_tuned_model.get_memory_footprint() / 1e6:.1f} MB\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0IHiJNU7a4XC", + "metadata": { + "id": "0IHiJNU7a4XC" + }, + "outputs": [], + "source": [ + "#Cat Boost Trained Model\n", + "catboost_model_path = \"/content/drive/MyDrive/catboost_model.pkl\"\n", + "catboost_model = joblib.load(catboost_model_path)\n", + "print(f\"Successfully loaded CatBoost model from {catboost_model_path}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "LgGmUKJxayZ6", + "metadata": { + "id": "LgGmUKJxayZ6" + }, + "outputs": [], + "source": [ + "def extract_tagged_price(output: str):\n", + " try:\n", + " contents = output.split(\"Price is $\")[1].replace(\",\", \"\")\n", + " match = re.search(r\"[-+]?\\d*\\.\\d+|\\d+\", contents)\n", + " return float(match.group()) if match else 0.0\n", + " except Exception:\n", + " return 0.0" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "ggKf1nSQbAnv", + "metadata": { + "id": "ggKf1nSQbAnv" + }, + "outputs": [], + "source": [ + "def ft_llama_price(description: str):\n", + " prompt = (\n", + " f\"How much does this cost to the nearest dollar?\\n\\n{description}\\n\\nPrice is $\"\n", + " )\n", + " inputs = tokenizer(prompt, return_tensors=\"pt\").to(\"cuda\")\n", + "\n", + " outputs = fine_tuned_model.generate(\n", + " **inputs, max_new_tokens=5, num_return_sequences=1\n", + " )\n", + "\n", + " result = tokenizer.decode(outputs[0])\n", + " price = extract_tagged_price(result)\n", + " return price" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "_cWyYUd4Ub-K", + "metadata": { + "id": "_cWyYUd4Ub-K" + }, + "outputs": [], + "source": [ + "def catboost_price(description: str):\n", + " vector = embedding_model.encode([description], normalize_embeddings=True)[0]\n", + " pred = catboost_model.predict([vector])[0]\n", + " return round(float(max(0, pred)), 2)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "3Skod8juXgnN", + "metadata": { + "id": "3Skod8juXgnN" + }, + "outputs": [], + "source": [ + "def gpt4o_price(item):\n", + " def get_embedding(text):\n", + " return embedding_model.encode([text], normalize_embeddings=True)\n", + "\n", + " def find_similars(text):\n", + " results = collection.query(\n", + " query_embeddings=get_embedding(text).astype(float).tolist(), n_results=5\n", + " )\n", + " docs = results[\"documents\"][0]\n", + " prices = [m[\"price\"] for m in results[\"metadatas\"][0]]\n", + " return docs, prices\n", + "\n", + " def format_context(similars, prices):\n", + " context = (\n", + " \"To provide some context, here are similar products and their prices:\\n\\n\"\n", + " )\n", + " for sim, price in zip(similars, prices):\n", + " context += f\"Product:\\n{sim}\\nPrice is ${price:.2f}\\n\\n\"\n", + " return context\n", + "\n", + " def build_messages(description, similars, prices):\n", + " system_message = (\n", + " \"You are a pricing expert. \"\n", + " \"Given a product description and a few similar products with their prices, \"\n", + " \"estimate the most likely price. \"\n", + " \"Respond ONLY with a number, no words.\"\n", + " )\n", + " context = format_context(similars, prices)\n", + " user_prompt = (\n", + " \"Estimate the price for the following product:\\n\\n\"\n", + " + description\n", + " + \"\\n\\n\"\n", + " + context\n", + " )\n", + " return [\n", + " {\"role\": \"system\", \"content\": system_message},\n", + " {\"role\": \"user\", \"content\": user_prompt},\n", + " {\"role\": \"assistant\", \"content\": \"Price is $\"},\n", + " ]\n", + "\n", + " docs, prices = find_similars(description(item))\n", + " messages = build_messages(description(item), docs, prices)\n", + " response = openai.chat.completions.create(\n", + " model=\"gpt-4o-mini\", messages=messages, seed=42, max_tokens=5\n", + " )\n", + " reply = response.choices[0].message.content\n", + " return float(\n", + " re.search(r\"[-+]?\\d*\\.\\d+|\\d+\", reply.replace(\"$\", \"\").replace(\",\", \"\")).group()\n", + " or 0\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8XQK5yrk8On4", + "metadata": { + "id": "8XQK5yrk8On4" + }, + "outputs": [], + "source": [ + "print(\"Splitting entire dataset...\")\n", + "np.random.seed(42)\n", + "all_indices = list(range(len(test)))\n", + "np.random.shuffle(all_indices)\n", + "\n", + "train_split_size = int(0.8 * len(all_indices))\n", + "train_indices = all_indices[:train_split_size] # 80%\n", + "test_indices = all_indices[train_split_size:] # 20%\n", + "\n", + "train_indices = train_indices[:250]\n", + "test_indices = test_indices[:50]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "XN7P5fkkXfgP", + "metadata": { + "id": "XN7P5fkkXfgP" + }, + "outputs": [], + "source": [ + "ft_llama_preds_train = []\n", + "gpt4omini_preds_train = []\n", + "catboost_preds_train = []\n", + "true_prices_train = []\n", + "\n", + "for i in tqdm(train_indices):\n", + " item = test[i]\n", + " text = description(item)\n", + " true_prices_train.append(item[\"price\"])\n", + " ft_llama_preds_train.append(ft_llama_price(text))\n", + " gpt4omini_preds_train.append(gpt4o_price(item))\n", + " catboost_preds_train.append(catboost_price(text))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1_6_atEgHnFR", + "metadata": { + "id": "1_6_atEgHnFR" + }, + "outputs": [], + "source": [ + "print(\"True Prices:\", true_prices_train)\n", + "print(\"FT-LLaMA Predictions:\", ft_llama_preds_train)\n", + "print(\"GPT-4o-mini Predictions:\", gpt4omini_preds_train)\n", + "print(\"CatBoost Predictions:\", catboost_preds_train)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "tYWMhTrXcA7x", + "metadata": { + "id": "tYWMhTrXcA7x" + }, + "outputs": [], + "source": [ + "maxes_train = [\n", + " max(a, b, c)\n", + " for a, b, c in zip(ft_llama_preds_train, gpt4omini_preds_train, catboost_preds_train)\n", + "]\n", + "means_train = [\n", + " np.mean([a, b, c])\n", + " for a, b, c in zip(ft_llama_preds_train, gpt4omini_preds_train, catboost_preds_train)\n", + "]\n", + "\n", + "X_train = pd.DataFrame(\n", + " {\n", + " \"FT_LLaMA\": ft_llama_preds_train,\n", + " \"GPT4oMini\": gpt4omini_preds_train,\n", + " \"CatBoost\": catboost_preds_train,\n", + " \"Max\": maxes_train,\n", + " \"Mean\": means_train,\n", + " }\n", + ")\n", + "\n", + "y_train = pd.Series(true_prices_train)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "-WsFABEicOyo", + "metadata": { + "id": "-WsFABEicOyo" + }, + "outputs": [], + "source": [ + "np.random.seed(42)\n", + "lr = LinearRegression()\n", + "lr.fit(X_train, y_train)\n", + "\n", + "feature_columns = X_train.columns.tolist()\n", + "for feature, coef in zip(feature_columns, lr.coef_):\n", + " print(f\"{feature}: {coef:.2f}\")\n", + "print(f\"Intercept={lr.intercept_:.2f}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "W3F0nNBXlrUJ", + "metadata": { + "id": "W3F0nNBXlrUJ" + }, + "outputs": [], + "source": [ + "ft_llama_preds_test = []\n", + "gpt4omini_preds_test = []\n", + "catboost_preds_test = []\n", + "true_prices_test = []\n", + "\n", + "print(\"Processing TEST data (50 items)...\")\n", + "for i in tqdm(test_indices):\n", + " item = test[i]\n", + " text = description(item)\n", + " true_prices_test.append(item[\"price\"])\n", + " ft_llama_preds_test.append(ft_llama_price(text))\n", + " gpt4omini_preds_test.append(gpt4o_price(item))\n", + " catboost_preds_test.append(catboost_price(text))\n", + "\n", + "maxes_test = [\n", + " max(a, b, c)\n", + " for a, b, c in zip(ft_llama_preds_test, gpt4omini_preds_test, catboost_preds_test)\n", + "]\n", + "means_test = [\n", + " np.mean([a, b, c])\n", + " for a, b, c in zip(ft_llama_preds_test, gpt4omini_preds_test, catboost_preds_test)\n", + "]\n", + "\n", + "X_test = pd.DataFrame(\n", + " {\n", + " \"FT_LLaMA\": ft_llama_preds_test,\n", + " \"GPT4oMini\": gpt4omini_preds_test,\n", + " \"CatBoost\": catboost_preds_test,\n", + " \"Max\": maxes_test,\n", + " \"Mean\": means_test,\n", + " }\n", + ")\n", + "\n", + "y_test = pd.Series(true_prices_test)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "y25l8rR791wG", + "metadata": { + "id": "y25l8rR791wG" + }, + "outputs": [], + "source": [ + "print(\"Evaluating model...\")\n", + "y_pred = lr.predict(X_test)\n", + "r2 = r2_score(y_test, y_pred)\n", + "print(f\"R² score: {r2:.4f}\")\n", + "\n", + "rmse = np.sqrt(mean_squared_error(y_test, y_pred))\n", + "print(f\"RMSE: {rmse:.2f}\")\n", + "\n", + "mape = np.mean(np.abs((y_test - y_pred) / y_test)) * 100\n", + "print(f\"MAPE: {mape:.2f}%\")" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "gpuType": "T4", + "provenance": [] + }, + "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.11.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/community-contributions/sach91-bootcamp/week6-exercise.ipynb b/community-contributions/sach91-bootcamp/week6-exercise.ipynb new file mode 100644 index 0000000..79bdcbb --- /dev/null +++ b/community-contributions/sach91-bootcamp/week6-exercise.ipynb @@ -0,0 +1,1167 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "db8736a7-ed94-441c-9556-831fa57b5a10", + "metadata": {}, + "source": [ + "# Trying some approaches inline in the course notebook\n", + "## 1. XGBoost Algorithm\n", + "## 2. Mix of experts (XGBoost, RandomForest, ) - Two variants: (1) Simple average (2) Average of 2 nearest predictions\n", + "## 3. Named Entity Recognition (NER) - Filter text to include only entities in the feature vectors\n", + "## 4. MinMax and Standard Scaler for normalizing word2vec embeddings\n", + "## Alas, None improved the performance from Random Forest. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "681c717b-4c24-4ac3-a5f3-3c5881d6e70a", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import os\n", + "import math\n", + "import json\n", + "import random\n", + "from dotenv import load_dotenv\n", + "from huggingface_hub import login\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pickle\n", + "from collections import Counter" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "933b6e75-3661-4f30-b0b5-c28d04e3748e", + "metadata": {}, + "outputs": [], + "source": [ + "# More imports for our traditional machine learning\n", + "import pandas as pd\n", + "import numpy as np\n", + "from sklearn.linear_model import LinearRegression\n", + "from sklearn.metrics import mean_squared_error, r2_score\n", + "from sklearn.preprocessing import StandardScaler, MinMaxScaler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "42cf33b7-7abd-44ba-9780-c156b70473b5", + "metadata": {}, + "outputs": [], + "source": [ + "# NLP related imports\n", + "from sklearn.feature_extraction.text import CountVectorizer\n", + "from gensim.models import Word2Vec\n", + "from gensim.utils import simple_preprocess" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a1ac3ec0-183c-4a12-920b-b06397f86815", + "metadata": {}, + "outputs": [], + "source": [ + "# Finally, more imports for more advanced machine learning\n", + "from sklearn.svm import LinearSVR\n", + "from sklearn.ensemble import RandomForestRegressor\n", + "from sklearn.ensemble import GradientBoostingRegressor\n", + "from polire import IDW" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c01ee5f-c4fc-44fe-9d3a-907e8a0426d2", + "metadata": {}, + "outputs": [], + "source": [ + "# Constants - used for printing to stdout in color\n", + "\n", + "GREEN = \"\\033[92m\"\n", + "YELLOW = \"\\033[93m\"\n", + "RED = \"\\033[91m\"\n", + "RESET = \"\\033[0m\"\n", + "COLOR_MAP = {\"red\":RED, \"orange\": YELLOW, \"green\": GREEN}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c830ed3e-24ee-4af6-a07b-a1bfdcd39278", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "markdown", + "id": "5105e13c-bca0-4c70-bfaa-649345f53322", + "metadata": {}, + "source": [ + "## Loading the pkl files" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c9b05f4-c9eb-462c-8d86-de9140a2d985", + "metadata": {}, + "outputs": [], + "source": [ + "with open('./train.pkl', 'rb') as file:\n", + " train = pickle.load(file)\n", + "\n", + "with open('./test.pkl', 'rb') as file:\n", + " test = pickle.load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66459184-535b-4195-9dea-a0de1b349605", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5793f5c-e23e-4a74-9496-1e30dd1e8935", + "metadata": {}, + "outputs": [], + "source": [ + "class Tester:\n", + "\n", + " def __init__(self, predictor, title=None, data=test, size=250):\n", + " self.predictor = predictor\n", + " self.data = data\n", + " self.title = title or predictor.__name__.replace(\"_\", \" \").title()\n", + " self.size = size\n", + " self.guesses = []\n", + " self.truths = []\n", + " self.errors = []\n", + " self.sles = []\n", + " self.colors = []\n", + "\n", + " def color_for(self, error, truth):\n", + " if error<40 or error/truth < 0.2:\n", + " return \"green\"\n", + " elif error<80 or error/truth < 0.4:\n", + " return \"orange\"\n", + " else:\n", + " return \"red\"\n", + " \n", + " def run_datapoint(self, i):\n", + " datapoint = self.data[i]\n", + " guess = self.predictor(datapoint)\n", + " truth = datapoint.price\n", + " error = abs(guess - truth)\n", + " log_error = math.log(truth+1) - math.log(guess+1)\n", + " sle = log_error ** 2\n", + " color = self.color_for(error, truth)\n", + " title = datapoint.title if len(datapoint.title) <= 40 else datapoint.title[:40]+\"...\"\n", + " self.guesses.append(guess)\n", + " self.truths.append(truth)\n", + " self.errors.append(error)\n", + " self.sles.append(sle)\n", + " self.colors.append(color)\n", + " print(f\"{COLOR_MAP[color]}{i+1}: Guess: ${guess:,.2f} Truth: ${truth:,.2f} Error: ${error:,.2f} SLE: {sle:,.2f} Item: {title}{RESET}\")\n", + "\n", + " def chart(self, title):\n", + " max_error = max(self.errors)\n", + " plt.figure(figsize=(12, 8))\n", + " max_val = max(max(self.truths), max(self.guesses))\n", + " plt.plot([0, max_val], [0, max_val], color='deepskyblue', lw=2, alpha=0.6)\n", + " plt.scatter(self.truths, self.guesses, s=3, c=self.colors)\n", + " plt.xlabel('Ground Truth')\n", + " plt.ylabel('Model Estimate')\n", + " plt.xlim(0, max_val)\n", + " plt.ylim(0, max_val)\n", + " plt.title(title)\n", + " plt.show()\n", + "\n", + " def report(self):\n", + " average_error = sum(self.errors) / self.size\n", + " rmsle = math.sqrt(sum(self.sles) / self.size)\n", + " hits = sum(1 for color in self.colors if color==\"green\")\n", + " title = f\"{self.title} Error=${average_error:,.2f} RMSLE={rmsle:,.2f} Hits={hits/self.size*100:.1f}%\"\n", + " self.chart(title)\n", + "\n", + " def run(self):\n", + " self.error = 0\n", + " for i in range(self.size):\n", + " self.run_datapoint(i)\n", + " self.report()\n", + "\n", + " @classmethod\n", + " def test(cls, function):\n", + " cls(function).run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66ea68e8-ab1b-4f0d-aba4-a59574d8f85e", + "metadata": {}, + "outputs": [], + "source": [ + "def random_pricer(item):\n", + " return random.randrange(1,1000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53d941cb-5b73-44ea-b893-3a0ce9997066", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Set the random seed\n", + "\n", + "random.seed(42)\n", + "\n", + "# Run our TestRunner\n", + "Tester.test(random_pricer)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97451c73-9c1b-43a8-b3b9-9c41942e48a2", + "metadata": {}, + "outputs": [], + "source": [ + "# That was fun!\n", + "# We can do better - here's another rather trivial model\n", + "\n", + "training_prices = [item.price for item in train]\n", + "training_average = sum(training_prices) / len(training_prices)\n", + "\n", + "def constant_pricer(item):\n", + " return training_average" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8cf384eb-30c2-40d8-b7e5-48942ac6a969", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# Run our constant predictor\n", + "Tester.test(constant_pricer)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ce16eee8-bb34-4914-9aa5-57e30a567842", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a new \"features\" field on items, and populate it with json parsed from the details dict\n", + "\n", + "for item in train:\n", + " item.features = json.loads(item.details)\n", + "for item in test:\n", + " item.features = json.loads(item.details)\n", + "\n", + "# Look at one" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac702a10-dccb-43d4-887b-6f92a0fb298f", + "metadata": {}, + "outputs": [], + "source": [ + "train[0].features.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd7a41c5-0c51-41be-a61d-8e80c3e90930", + "metadata": {}, + "outputs": [], + "source": [ + "# Look at 20 most common features in training set\n", + "\n", + "feature_count = Counter()\n", + "for item in train:\n", + " for f in item.features.keys():\n", + " feature_count[f]+=1\n", + "\n", + "feature_count.most_common(40)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3cef84a9-4932-48fd-9f7a-51cfc06e3216", + "metadata": {}, + "outputs": [], + "source": [ + "# Now some janky code to pluck out the Item Weight\n", + "# Don't worry too much about this: spoiler alert, it's not going to be much use in training!\n", + "\n", + "def get_weight(item):\n", + " weight_str = item.features.get('Item Weight')\n", + " if weight_str:\n", + " parts = weight_str.split(' ')\n", + " amount = float(parts[0])\n", + " unit = parts[1].lower()\n", + " if unit==\"pounds\":\n", + " return amount\n", + " elif unit==\"ounces\":\n", + " return amount / 16\n", + " elif unit==\"grams\":\n", + " return amount / 453.592\n", + " elif unit==\"milligrams\":\n", + " return amount / 453592\n", + " elif unit==\"kilograms\":\n", + " return amount / 0.453592\n", + " elif unit==\"hundredths\" and parts[2].lower()==\"pounds\":\n", + " return amount / 100\n", + " else:\n", + " print(weight_str)\n", + " return None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f4848b4a-3c5a-4168-83a5-57a1f3ff270d", + "metadata": {}, + "outputs": [], + "source": [ + "weights = [get_weight(t) for t in train]\n", + "weights = [w for w in weights if w]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0cd11cc8-f16e-4991-b531-482189ddc4b6", + "metadata": {}, + "outputs": [], + "source": [ + "average_weight = sum(weights)/len(weights)\n", + "average_weight" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "efe8ec7f-9777-464f-a809-b06b7033bdb2", + "metadata": {}, + "outputs": [], + "source": [ + "def get_weight_with_default(item):\n", + " weight = get_weight(item)\n", + " return weight or average_weight" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c2659fef-a455-431a-9a0e-59342b80084b", + "metadata": {}, + "outputs": [], + "source": [ + "def get_rank(item):\n", + " rank_dict = item.features.get(\"Best Sellers Rank\")\n", + " if rank_dict:\n", + " ranks = rank_dict.values()\n", + " return sum(ranks)/len(ranks)\n", + " return None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "20b9b5be-30bc-4d3a-8492-fbae119421a0", + "metadata": {}, + "outputs": [], + "source": [ + "ranks = [get_rank(t) for t in train]\n", + "ranks = [r for r in ranks if r]\n", + "average_rank = sum(ranks)/len(ranks)\n", + "average_rank" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "081e646a-ea50-4ec3-9512-6d5f96f8aef6", + "metadata": {}, + "outputs": [], + "source": [ + "def get_rank_with_default(item):\n", + " rank = get_rank(item)\n", + " return rank or average_rank" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "afd5daf7-cb2b-47af-bf17-dd71a9db65d0", + "metadata": {}, + "outputs": [], + "source": [ + "def get_text_length(item):\n", + " return len(item.test_prompt())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85c89012-a922-401b-8a3b-94af641bf27a", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# investigate the brands\n", + "\n", + "brands = Counter()\n", + "for t in train:\n", + " brand = t.features.get(\"Brand\")\n", + " if brand:\n", + " brands[brand]+=1\n", + "\n", + "# Look at most common 40 brands\n", + "\n", + "brands.most_common(40)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "386dde54-e028-4a6d-b291-cce889ac1fa3", + "metadata": {}, + "outputs": [], + "source": [ + "TOP_ELECTRONICS_BRANDS = [\"hp\", \"dell\", \"lenovo\", \"samsung\", \"asus\", \"sony\", \"canon\", \"apple\", \"intel\"]\n", + "def is_top_electronics_brand(item):\n", + " brand = item.features.get(\"Brand\")\n", + " return brand and brand.lower() in TOP_ELECTRONICS_BRANDS" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c31c9c59-9d0d-47a8-a046-f20ed8d38d4c", + "metadata": {}, + "outputs": [], + "source": [ + "def get_features(item):\n", + " return {\n", + " \"weight\": get_weight_with_default(item),\n", + " \"rank\": get_rank_with_default(item),\n", + " \"text_length\": get_text_length(item),\n", + " \"is_top_electronics_brand\": 1 if is_top_electronics_brand(item) else 0\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88850855-f5bd-4be2-9d7c-75bf8a21609b", + "metadata": {}, + "outputs": [], + "source": [ + "# Look at features in a training item\n", + "get_features(train[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ee9b5298-68b7-497d-8b2e-875287bb25b2", + "metadata": {}, + "outputs": [], + "source": [ + "# A utility function to convert our features into a pandas dataframe\n", + "\n", + "def list_to_dataframe(items):\n", + " features = [get_features(item) for item in items]\n", + " df = pd.DataFrame(features)\n", + " df['price'] = [item.price for item in items]\n", + " return df\n", + "\n", + "train_df = list_to_dataframe(train)\n", + "test_df = list_to_dataframe(test[:250])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cc1d68e0-ab33-40f4-9334-461d426af25c", + "metadata": {}, + "outputs": [], + "source": [ + "# Traditional Linear Regression!\n", + "\n", + "np.random.seed(42)\n", + "\n", + "# Separate features and target\n", + "feature_columns = ['weight', 'rank', 'text_length', 'is_top_electronics_brand']\n", + "\n", + "X_train = train_df[feature_columns]\n", + "y_train = train_df['price']\n", + "X_test = test_df[feature_columns]\n", + "y_test = test_df['price']\n", + "\n", + "# Train a Linear Regression\n", + "model = LinearRegression()\n", + "model.fit(X_train, y_train)\n", + "\n", + "for feature, coef in zip(feature_columns, model.coef_):\n", + " print(f\"{feature}: {coef}\")\n", + "print(f\"Intercept: {model.intercept_}\")\n", + "\n", + "# Predict the test set and evaluate\n", + "y_pred = model.predict(X_test)\n", + "mse = mean_squared_error(y_test, y_pred)\n", + "r2 = r2_score(y_test, y_pred)\n", + "\n", + "print(f\"Mean Squared Error: {mse}\")\n", + "print(f\"R-squared Score: {r2}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6561c3c7-ac7f-458b-983c-4a164b9d02c3", + "metadata": {}, + "outputs": [], + "source": [ + "# Function to predict price for a new item\n", + "\n", + "def linear_regression_pricer(item):\n", + " features = get_features(item)\n", + " features_df = pd.DataFrame([features])\n", + " return model.predict(features_df)[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9bf2caa4-657a-4fc6-9dcb-bed7eaf8dd65", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# test it\n", + "\n", + "Tester.test(linear_regression_pricer)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "79e1574b-52ef-49cc-bfb5-e97252ed5db8", + "metadata": {}, + "outputs": [], + "source": [ + "# For the next few models, we prepare our documents and prices\n", + "# Note that we use the test prompt for the documents, otherwise we'll reveal the answer!!\n", + "\n", + "prices = np.array([float(item.price) for item in train])\n", + "documents = [item.test_prompt() for item in train]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e126c22e-53e7-4967-9ebb-6b7dd7fe4ade", + "metadata": {}, + "outputs": [], + "source": [ + "# Use the CountVectorizer for a Bag of Words model\n", + "\n", + "np.random.seed(42)\n", + "vectorizer = CountVectorizer(max_features=1000, stop_words='english')\n", + "X = vectorizer.fit_transform(documents)\n", + "regressor = LinearRegression()\n", + "regressor.fit(X, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b7148d3-3202-4536-a75c-1627495c51d3", + "metadata": {}, + "outputs": [], + "source": [ + "def bow_lr_pricer(item):\n", + " x = vectorizer.transform([item.test_prompt()])\n", + " return max(regressor.predict(x)[0], 0)\n", + "pred_lr = {}\n", + "for i in range(len(test)):\n", + " pred_lr[test[i]] = bow_lr_pricer(test[i])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38f7f7d0-d22c-4282-92e5-9666a7b8535d", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# test it\n", + "def get_pred_lr(item):\n", + " return pred_lr[item]\n", + "Tester.test(get_pred_lr)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a82f0a3-191c-4653-b9d6-5622730a6c94", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "354b631d-de40-4dee-91fc-adb2ab094c4f", + "metadata": {}, + "outputs": [], + "source": [ + "xgb = GradientBoostingRegressor()\n", + "xgb.fit(X, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05e7d00b-db89-4f80-bca6-69d251d8cf62", + "metadata": {}, + "outputs": [], + "source": [ + "def bow_xgb_pricer(item):\n", + " x = vectorizer.transform([item.test_prompt()])\n", + " return max(xgb.predict(x)[0], 0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4a3109d3-ecb6-42df-970c-b798968d467c", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "# test\n", + "pred_xgb = {}\n", + "for i in range(len(test)):\n", + " pred_xgb[test[i]] = bow_xgb_pricer(test[i])\n", + "def get_pred_xgb(item):\n", + " return pred_xgb[item]\n", + "Tester.test(get_pred_xgb)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "21a5ce93-e58e-48f7-ab94-407e4c2269c6", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a19b662c-d0ad-40c8-8116-f57c368a841d", + "metadata": {}, + "outputs": [], + "source": [ + "import spacy \n", + "nlp = spacy.load(\"en_core_web_sm\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c52fc528-d8af-4b01-9e58-8502033884cc", + "metadata": {}, + "outputs": [], + "source": [ + "def ner_doc(doc):\n", + " d = nlp(doc.replace('\\n',' '))\n", + " ents = []\n", + " for ent in d.ents:\n", + " ents.extend(ent.text.split(' '))\n", + " return ' '.join(list(set(ents)))\n", + "def ner_docs(docs):\n", + " ret = []\n", + " for i,doc in enumerate(docs):\n", + " ret.append(ner_doc(doc))\n", + " if i%1000 == 0:\n", + " print(i, ret[-1])\n", + " return ret" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7b1745e1-5aca-4239-b33c-99a1d13ba567", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "if os.path.exists('docs.pkl'):\n", + " docs2 = pickle.load(open('docs.pkl','rb'))\n", + "else:\n", + " docs2 = ner_doc(documents)\n", + " pickle.dump(docs2, open('docs.pkl','wb'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19f69fc0-fbc5-4069-b45c-e5f5c0fb14a1", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90597133-f057-4597-bb2b-d0b8986342ae", + "metadata": {}, + "outputs": [], + "source": [ + "np.random.seed(42)\n", + "vectorizer2 = CountVectorizer(max_features=1000, stop_words='english')\n", + "X2 = vectorizer2.fit_transform(docs2)\n", + "regressor2 = LinearRegression()\n", + "regressor2.fit(X2, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "362875d7-a6b1-4965-ae9b-0d7a0104245f", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "def ner_pricer(item):\n", + " x = vectorizer2.transform([ner_doc(item.test_prompt())])\n", + " return max(regressor2.predict(x)[0], 0)\n", + "# test\n", + "pred_ner = {}\n", + "for i in range(len(test)):\n", + " pred_ner[test[i]] = ner_pricer(test[i])\n", + "def get_pred_ner(item):\n", + " return pred_ner[item]\n", + "Tester.test(get_pred_ner)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a44bd333-9577-4338-9da5-6947f7e19849", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b623079e-54fa-418f-b209-7d54ebbcc23a", + "metadata": {}, + "outputs": [], + "source": [ + "# The amazing word2vec model, implemented in gensim NLP library\n", + "\n", + "np.random.seed(42)\n", + "\n", + "# Preprocess the documents\n", + "processed_docs = [simple_preprocess(doc) for doc in documents]\n", + "\n", + "# Train Word2Vec model\n", + "w2v_model = Word2Vec(sentences=processed_docs, vector_size=400, window=5, min_count=1, workers=8)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3de4efc7-68a6-4443-b9fd-70ee9d722362", + "metadata": {}, + "outputs": [], + "source": [ + "# This step of averaging vectors across the document is a weakness in our approach\n", + "\n", + "def document_vector(doc):\n", + " doc_words = simple_preprocess(doc)\n", + " word_vectors = [w2v_model.wv[word] for word in doc_words if word in w2v_model.wv]\n", + " return np.mean(word_vectors, axis=0) if word_vectors else np.zeros(w2v_model.vector_size)\n", + "\n", + "# Create feature matrix\n", + "X_w2v = np.array([document_vector(doc) for doc in documents])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f05eeec-dab8-4007-8e8c-dcf4175b8861", + "metadata": {}, + "outputs": [], + "source": [ + "# Run Linear Regression on word2vec\n", + "\n", + "word2vec_lr_regressor = LinearRegression()\n", + "word2vec_lr_regressor.fit(X_w2v, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e43d3fb9-e013-4573-90bf-9a522132b555", + "metadata": {}, + "outputs": [], + "source": [ + "def word2vec_lr_pricer(item):\n", + " doc = item.test_prompt()\n", + " doc_vector = document_vector(doc)\n", + " return max(0, word2vec_lr_regressor.predict([doc_vector])[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6740319d-5c8e-4125-9106-97e2e8ab72c7", + "metadata": { + "scrolled": true + }, + "outputs": [], + "source": [ + "pred_lr_w2v = {}\n", + "for i in range(len(test)):\n", + " pred_lr_w2v[test[i]] = word2vec_lr_pricer(test[i])\n", + "def get_pred_lr_w2v(item):\n", + " return pred_lr_w2v[item]\n", + "Tester.test(get_pred_lr_w2v)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd894bae-ef2a-47e1-b2dd-7aed0d8da75c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5edf290b-ed91-42a2-ae6a-1a6cfdf190ee", + "metadata": {}, + "outputs": [], + "source": [ + "# MIXTURE OF EXPERTS" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a500794-9fc2-473e-adc8-955789cf49c4", + "metadata": {}, + "outputs": [], + "source": [ + "def get_pred_best2_mean(item):\n", + " v1 = pred_lr[item]\n", + " v2 = pred_lr_w2v[item]\n", + " v3 = pred_xgb[item]\n", + " d1 = abs(v1-v2)\n", + " d2 = abs(v2-v3)\n", + " d3 = abs(v3-v1)\n", + " if d1 <= min(d2,d3):\n", + " v = (v1+v2)/2\n", + " elif d2 <= min(d1,d3):\n", + " v = (v2+v3)/2\n", + " else:\n", + " v = (v1+v3)/2\n", + " return v\n", + "Tester.test(get_pred_best2_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "134029c2-a9a4-44e5-b057-712a7147aec8", + "metadata": {}, + "outputs": [], + "source": [ + "def get_pred_mean(item):\n", + " v1 = pred_lr[item]\n", + " v2 = pred_lr_w2v[item]\n", + " v3 = pred_xgb[item]\n", + " return (v1+v2+v3)/3\n", + "Tester.test(get_pred_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "61318267-222d-43de-a63d-4bef09ac8838", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9913c2f-d004-44dc-ac71-485811bbad73", + "metadata": {}, + "outputs": [], + "source": [ + "# Apply MinMax and Standard Scaler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ec519cbe-6d96-4d04-be56-274cc360d8d9", + "metadata": {}, + "outputs": [], + "source": [ + "scalar = [MinMaxScaler, StandardScaler][0]().fit(X_w2v)\n", + "X_w2v_scaled = scalar.transform(X_w2v)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "600df04d-8c81-448a-aab7-2da70650274c", + "metadata": {}, + "outputs": [], + "source": [ + "word2vec_lr_reg_scaled = LinearRegression().fit(X_w2v_scaled, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f5f1f33-a4d8-44bb-a899-5c71478cf7f1", + "metadata": {}, + "outputs": [], + "source": [ + "def word2vec_lr_pricer_scaled(item):\n", + " doc = item.test_prompt()\n", + " doc_vector = document_vector(doc)\n", + " doc_vector_scaled = stdscalar.transform([doc_vector])\n", + " return max(0, word2vec_lr_reg_scaled.predict([doc_vector_scaled[0]])[0])\n", + "\n", + "Tester.test(word2vec_lr_pricer_scaled)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "194796e9-c07e-47d9-8908-f75dd1787ab4", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1bb5957e-780d-4e85-80bc-50d52350aa58", + "metadata": {}, + "outputs": [], + "source": [ + "# Run XGB on word2vec\n", + "\n", + "word2vec_xgb_regressor = GradientBoostingRegressor()\n", + "word2vec_xgb_regressor.fit(X_w2v, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4281d224-b16a-4276-a48f-fa1829c49c71", + "metadata": {}, + "outputs": [], + "source": [ + "def word2vec_xgb_pricer(item):\n", + " doc = item.test_prompt()\n", + " doc_vector = document_vector(doc)\n", + " return max(0, word2vec_xgb_regressor.predict([doc_vector])[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "72adf5b4-3781-452e-ba0e-69dfaceec91d", + "metadata": {}, + "outputs": [], + "source": [ + "Tester.test(word2vec_xgb_pricer)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40791fa8-5ff4-4cc7-8813-9abdc6a037fa", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9d6d3265-37c1-464c-a489-5be4df0a7276", + "metadata": {}, + "outputs": [], + "source": [ + "# Support Vector Machines\n", + "\n", + "np.random.seed(42)\n", + "svr_regressor = LinearSVR()\n", + "\n", + "svr_regressor.fit(X_w2v, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fcc289e6-56a1-4119-864f-2fdf8efde643", + "metadata": {}, + "outputs": [], + "source": [ + "def svr_pricer(item):\n", + " np.random.seed(42)\n", + " doc = item.test_prompt()\n", + " doc_vector = document_vector(doc)\n", + " return max(float(svr_regressor.predict([doc_vector])[0]),0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "80286a48-7cca-40e6-af76-a814a23bb9dc", + "metadata": {}, + "outputs": [], + "source": [ + "Tester.test(svr_pricer)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5b5b2758-35ce-4401-943c-3221ac2c6d2d", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6c44fe4-e4d9-4559-a8ed-d8f97e25b69f", + "metadata": {}, + "outputs": [], + "source": [ + "# And the powerful Random Forest regression\n", + "mfile = 'random_forest_model.pkl'\n", + "if os.path.exists(mfile):\n", + " rf_model = pickle.load(open(mfile,'rb'))\n", + "else:\n", + " rf_model = RandomForestRegressor(n_estimators=100, random_state=42, n_jobs=8)\n", + " rf_model.fit(X_w2v, prices)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a38812d0-913b-400b-804f-51434d895d05", + "metadata": {}, + "outputs": [], + "source": [ + "def random_forest_pricer(item):\n", + " doc = item.test_prompt()\n", + " doc_vector = document_vector(doc)\n", + " return max(0, rf_model.predict([doc_vector])[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "88b51c01-c791-4fdc-8010-00b2e486b8ce", + "metadata": {}, + "outputs": [], + "source": [ + "Tester.test(random_forest_pricer)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc85b271-4c92-480c-8843-2d7713b0fa57", + "metadata": {}, + "outputs": [], + "source": [ + "pred_rf = {}\n", + "for i in range(len(test)):\n", + " pred_rf[test[i]] = random_forest_pricer(test[i])\n", + "def get_pred_rf(item):\n", + " return pred_rf[item]\n", + "Tester.test(get_pred_rf)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "222ce4e3-9816-4674-bdf7-40ece20d23eb", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/week1/community-contributions/philip/README.md b/week1/community-contributions/philip/README.md new file mode 100644 index 0000000..4ee8507 --- /dev/null +++ b/week1/community-contributions/philip/README.md @@ -0,0 +1,44 @@ +# Week 1 Exercise - Tech Question Explainer + +**Author:** Philip Omoigui + +## Description + +A technical question explainer tool that demonstrates familiarity with both OpenAI API and Ollama. This tool: + +- Takes a technical question +- Gets responses from both GPT-4o-mini and Llama 3.2 +- Compares the two responses using GPT-5-nano +- Evaluates which explanation is better for beginners + +## Features + +- **Dual Model Response**: Uses both OpenAI's GPT-4o-mini and local Llama 3.2 +- **Streaming Output**: Real-time display of responses as they're generated +- **Automated Comparison**: Uses GPT-5-nano to evaluate and rank both responses +- **Beginner-Focused**: Optimized for educational content with clear, beginner-friendly explanations + +## Evaluation Criteria + +The comparison evaluates responses on: +1. **Beginner Friendliness** - How easy is it for a beginner to understand? +2. **Tackles Main Point** - How well does it address the core concept? +3. **Clear Examples** - How effective are the examples and explanations? + +## Files + +- `week1_EXERCISE.ipynb` - Main notebook with the tech explainer implementation + +## Usage + +Simply modify the `question` variable with your technical question, and the tool will: +1. Generate explanations from both models +2. Stream the responses in real-time +3. Automatically compare and evaluate which explanation is better + +## Requirements + +- OpenAI API key +- Ollama running locally with llama3.2 model +- Python packages: openai, python-dotenv, IPython + diff --git a/week1/community-contributions/philip/week1_EXERCISE.ipynb b/week1/community-contributions/philip/week1_EXERCISE.ipynb new file mode 100644 index 0000000..550cd13 --- /dev/null +++ b/week1/community-contributions/philip/week1_EXERCISE.ipynb @@ -0,0 +1,335 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "fe12c203-e6a6-452c-a655-afb8a03a4ff5", + "metadata": {}, + "source": [ + "# End of week 1 exercise\n", + "\n", + "To demonstrate your familiarity with OpenAI API, and also Ollama, build a tool that takes a technical question, \n", + "and responds with an explanation. This is a tool that you will be able to use yourself during the course!" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "c1070317-3ed9-4659-abe3-828943230e03", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "from IPython.display import display, update_display, Markdown\n", + "import os\n", + "from dotenv import load_dotenv\n", + "from openai import OpenAI \n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "4a456906-915a-4bfd-bb9d-57e505c5093f", + "metadata": {}, + "outputs": [], + "source": [ + "# constants\n", + "\n", + "MODEL_GPT = 'gpt-4o-mini'\n", + "MODEL_LLAMA = 'llama3.2'" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a8d7923c-5f28-4c30-8556-342d7c8497c1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "API key found and looks good so far!\n" + ] + } + ], + "source": [ + "# set up environment\n", + "load_dotenv(override=True)\n", + "api_key = os.getenv('OPENAI_API_KEY')\n", + "\n", + "if not api_key:\n", + " print(\"No API key was found - please head over to the troubleshooting notebook in this folder to identify & fix!\")\n", + "elif not api_key.startswith(\"sk-proj-\"):\n", + " print(\"An API key was found, but it doesn't start sk-proj-; please check you're using the right key - see troubleshooting notebook\")\n", + "else:\n", + " print(\"API key found and looks good so far!\")" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "3f0d0137-52b0-47a8-81a8-11a90a010798", + "metadata": {}, + "outputs": [], + "source": [ + "# here is the question; type over this to ask something new\n", + "question = \"\"\"\n", + "Please explain what this code does and why:\n", + "yield from {book.get(\"author\") for book in books if book.get(\"author\")}\n", + "\"\"\"\n", + "\n", + "system_prompt = \"\"\"\n", + "You are python expert who is skilled in explaining code and helping people understand it.\n", + "Make sure to explain the code in a way that is easy to understand.\n", + "Keep your explanations concise and to the point.\n", + "Make sure to make it beginner friendly.\n", + "\"\"\"\n", + "\n", + "messages = [\n", + " {\"role\": \"system\", \"content\": system_prompt},\n", + " {\"role\": \"user\", \"content\" : question}\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "60ce7000-a4a5-4cce-a261-e75ef45063b4", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "Certainly! Let's break down the code snippet you provided:\n", + "\n", + "```python\n", + "yield from {book.get(\"author\") for book in books if book.get(\"author\")}\n", + "```\n", + "\n", + "### Explanation:\n", + "\n", + "1. **`{book.get(\"author\") for book in books if book.get(\"author\")}`**:\n", + " - This part is a **set comprehension**. A set comprehension is used to create a set (a collection of unique items) in Python.\n", + " - It iterates over a list called `books` (which is expected to be a collection of book data).\n", + " - For each `book`, it tries to get the value associated with the key `\"author\"` using `book.get(\"author\")`. \n", + " - If the author exists (meaning it’s not `None` or an empty string), it adds that author to the set.\n", + " - The result is a set of unique author names from the list of books.\n", + "\n", + "2. **`yield from`**:\n", + " - This keyword is used in generator functions. It allows you to yield all values from an iterable (like a set or a list) one by one.\n", + " - In this case, it means that for each unique author in the set that was created, a value will be returned each time the generator is iterated over. \n", + "\n", + "### Why It Matters:\n", + "- **Efficiency**: By using a set, it ensures that each author is unique and there are no duplicates.\n", + "- **Generator Function**: The use of `yield from` indicates that this code is likely part of a generator function, making it memory efficient since it generates values on-the-fly rather than storing them all in memory.\n", + "\n", + "### Summary:\n", + "This code snippet efficiently gathers unique authors from a list of books and yields each author one at a time when the generator is iterated upon. It's a concise way to collect and return unique data from potentially large datasets without memory overhead." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Get gpt-4o-mini to answer, with streaming\n", + "openai = OpenAI()\n", + "\n", + "stream = openai.chat.completions.create(model=MODEL_GPT, \n", + " messages= messages,\n", + " stream=True)\n", + "\n", + "gpt_response = \"\"\n", + "display_handle = display(Markdown(\"\"), display_id=True)\n", + "\n", + "for chunk in stream:\n", + " gpt_response += chunk.choices[0].delta.content or ''\n", + " update_display(Markdown(gpt_response), display_id=display_handle.display_id)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "8f7c8ea8-4082-4ad0-8751-3301adcf6538", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Explanation:**\n", + "\n", + "This code snippet is using a technique called \"generator expression\" to extract author names from a list of dictionaries. Let's break it down:\n", + "\n", + "* `yield from`: This keyword is used to yield values from an iterable (in this case, a generator).\n", + "* `{book.get(\"author\") for book in books if book.get(\"author\")}`: This is a tuple-comprehension that performs the following operations:\n", + "\t+ `for book in books`: Iterates over each dictionary (book) in the `books` list.\n", + "\t+ `if book.get(\"author\")`: Filters out dictionaries that don't have an author name. It uses the `.get()` method to safely retrieve a value from the dictionary, avoiding a KeyError if \"author\" doesn't exist.\n", + "\t+ `book.get(\"author\")`: Extracts the author's name (or None if it doesn't exist) from each filtered dictionary.\n", + "* `{...}`: This is an empty dictionary. It's used as a container to hold the extracted values.\n", + "\n", + "**Why?**\n", + "\n", + "The purpose of this code snippet is likely to provide a list of authors' names, where:\n", + "\n", + "1. Not all books have an author name (in which case `None` will be included in the result).\n", + "2. The input data (`books`) might contain dictionaries with only certain keys (e.g., `title`, `description`, etc.), while this code assumes that each book dictionary must have a key named \"author\".\n", + "\n", + "**Example use cases:**\n", + "\n", + "When working with large datasets or data structures, generator expressions like this one can help you:\n", + "\n", + "* Process data in chunks, avoiding excessive memory consumption\n", + "* Work with complex, nested data structures (in this case, a list of dictionaries)\n", + "* Improve code readability by encapsulating logic within a single expression\n", + "\n", + "Keep in mind that the resulting values will be yielded on-the-fly as you iterate over them, rather than having all authors' names stored in memory at once." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Get Llama 3.2 to answer\n", + "OLLAMA_BASE_URL = \"http://localhost:11434/v1\"\n", + "ollama = OpenAI(base_url=OLLAMA_BASE_URL, api_key='ollama')\n", + "\n", + "stream = ollama.chat.completions.create(model=MODEL_LLAMA, \n", + " messages= messages,\n", + " stream=True)\n", + "\n", + "ollama_response = \"\"\n", + "display_handle = display(Markdown(\"\"), display_id=True)\n", + "\n", + "for chunk in stream:\n", + " ollama_response += chunk.choices[0].delta.content or ''\n", + " update_display(Markdown(ollama_response), display_id=display_handle.display_id)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "08c5f646", + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "## 📊 Comparison Results\n", + "\n", + "Here’s a side-by-side rating and justification for each criterion.\n", + "\n", + "Response A (GPT-4o-mini)\n", + "\n", + "- Beginner Friendliness: 4/5\n", + " - Why: It explains the two main parts (set comprehension and yield from) in straightforward terms and uses bullet points. It’s easy to follow for someone with basic Python knowledge. Minor improvement could be more emphasis on what a generator function is and when you’d use this pattern.\n", + "\n", + "- Tackles Main Point: 4/5\n", + " - Why: It correctly identifies the core ideas: using a set comprehension to collect unique authors and using yield from to yield items from that iterable. It also notes potential memory-related considerations and the generator nature. The nuance about memory efficiency could be clarified (the set is built in memory first), but the core point is solid.\n", + "\n", + "- Clear Examples: 4/5\n", + " - Why: It provides a succinct, concrete breakdown of each piece of the expression and a concise summary of the result. It would be even better with a short concrete example of input and the yielded values, but the explanation is clear and actionable.\n", + "\n", + "Response B (Llama 3.2)\n", + "\n", + "- Beginner Friendliness: 2/5\n", + " - Why: Contains several incorrect or misleading statements (calls the comprehension a “tuple-comprehension,” says the container is an empty dictionary, misdescribes yield from usage, and incorrectly claims that None would be yielded). These errors can confuse beginners and propagate misconceptions.\n", + "\n", + "- Tackles Main Point: 2/5\n", + " - Why: Several core misunderstandings (generator expression vs set comprehension, the effect of the if filter, and the nature of the resulting container) obscure the main concept. The explanation diverges from what the code does, reducing its usefulness as a core clarifier.\n", + "\n", + "- Clear Examples: 2/5\n", + " - Why: While it attempts to describe use cases and benefits of generator-like processing, the inaccuracies undermine the usefulness of the examples. It also incorrectly describes the resulting container and behavior of the code, making the examples less reliable for learning.\n", + "\n", + "Overall recommendation\n", + "\n", + "- Better for a beginner: Response A\n", + " - Rationale: Response A is accurate, coherent, and focused on the essential ideas (set comprehension, deduplication, and how yield from works). It avoids the factual errors present in Response B and offers a clearer path to understanding the snippet. Response B contains multiple conceptual mistakes that could mislead beginners. If you want to improve Response B, you’d need to correct terminology (set vs. dict, generator vs. set comprehension) and fix the behavior description (no None is yielded due to the filter)." + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Compare the two responses using GPT-5-nano\n", + "comparison_prompt = f\"\"\"\n", + "You are an expert evaluator of educational content. Compare the following two explanations of the same Python code and rank them on a scale of 1-5 for each criterion:\n", + "\n", + "**Criteria:**\n", + "1. **Beginner Friendliness**: How easy is it for a beginner to understand?\n", + "2. **Tackles Main Point**: How well does it address the core concept?\n", + "3. **Clear Examples**: How effective are the examples and explanations?\n", + "\n", + "**Response A (GPT-4o-mini):**\n", + "{gpt_response}\n", + "\n", + "**Response B (Llama 3.2):**\n", + "{ollama_response}\n", + "\n", + "**Instructions:**\n", + "- Rate each response on each criterion from 1 (poor) to 5 (excellent)\n", + "- Provide a brief justification for each rating\n", + "- Give an overall recommendation on which response is better for a beginner\n", + "\n", + "Please format your response clearly with the ratings and justifications.\n", + "\"\"\"\n", + "\n", + "comparison_messages = [\n", + " {\"role\": \"user\", \"content\": comparison_prompt}\n", + "]\n", + "\n", + "stream = openai.chat.completions.create(\n", + " model=\"gpt-5-nano\",\n", + " messages=comparison_messages,\n", + " stream=True\n", + ")\n", + "\n", + "comparison_response = \"\"\n", + "display_handle = display(Markdown(\"## 📊 Comparison Results\\n\\n\"), display_id=True)\n", + "\n", + "for chunk in stream:\n", + " comparison_response += chunk.choices[0].delta.content or ''\n", + " update_display(Markdown(\"## 📊 Comparison Results\\n\\n\" + comparison_response), display_id=display_handle.display_id)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13deb6e6", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/week3/community-contributions/kwabena/Week3 Resume and Job Description Data Generator.ipynb b/week3/community-contributions/kwabena/Week3 Resume and Job Description Data Generator.ipynb new file mode 100644 index 0000000..b4ff44f --- /dev/null +++ b/week3/community-contributions/kwabena/Week3 Resume and Job Description Data Generator.ipynb @@ -0,0 +1,5181 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "s7zEKhq9h6eb" + }, + "source": [ + "# Resume and Job Description Data Generator" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cH3arpfLiAWR" + }, + "source": [ + "The purpose of this notebook is to generate resumes and job description data for training a model that will assist job applicants finetune their resumes to an advertised role; we will use an open source model and create a ui with gradio" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "executionInfo": { + "elapsed": 9567, + "status": "ok", + "timestamp": 1761736938504, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "p2cGxlB2j5r5", + "outputId": "a025aa62-d896-45e8-b3bd-6e615cedc455" + }, + "outputs": [], + "source": [ + "!pip install -q transformers accelerate bitsandbytes torch gradio" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 24516, + "status": "ok", + "timestamp": 1761736965621, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "Hhqp912jj_Fb" + }, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import os\n", + "import requests\n", + "from huggingface_hub import login\n", + "from google.colab import userdata\n", + "from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig, pipeline\n", + "import torch\n", + "import json\n", + "import pandas as pd\n", + "import gradio as gr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 688, + "status": "ok", + "timestamp": 1761736970821, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "1GlDBWg2kYW9" + }, + "outputs": [], + "source": [ + "# Sign in to HuggingFace Hub\n", + "\n", + "hf_token = userdata.get('HF_TOKEN')\n", + "login(hf_token, add_to_git_credential=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 6, + "status": "ok", + "timestamp": 1761736993552, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "CF1l129DlaD6" + }, + "outputs": [], + "source": [ + "# Available models\n", + "AVAILABLE_MODELS = {\n", + " \"Mistral-7B\": \"mistralai/Mistral-7B-Instruct-v0.2\",\n", + " \"Phi-2\": \"microsoft/phi-2\",\n", + " \"Gemma-2B\": \"google/gemma-2b-it\",\n", + " \"TinyLlama\": \"TinyLlama/TinyLlama-1.1B-Chat-v1.0\",\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 11, + "status": "ok", + "timestamp": 1761737009179, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "KdPYdC9tmoEy" + }, + "outputs": [], + "source": [ + "# Available industries with roles\n", + "AVAILABLE_INDUSTRIES = {\n", + " \"Technology\": [\"Software Engineer\", \"Data Scientist\", \"Product Manager\", \"DevOps Engineer\", \"Frontend Developer\"],\n", + " \"Healthcare\": [\"Registered Nurse\", \"Medical Assistant\", \"Healthcare Administrator\", \"Pharmacist\", \"Physical Therapist\"],\n", + " \"Finance\": [\"Financial Analyst\", \"Accountant\", \"Investment Banker\", \"Risk Manager\", \"Portfolio Manager\"],\n", + " \"Marketing\": [\"Digital Marketing Manager\", \"Content Strategist\", \"SEO Specialist\", \"Brand Manager\", \"Social Media Manager\"],\n", + " \"Sales\": [\"Account Executive\", \"Sales Manager\", \"Business Development Rep\", \"Sales Engineer\", \"Customer Success Manager\"],\n", + " \"Education\": [\"Teacher\", \"Curriculum Developer\", \"Academic Advisor\", \"Education Consultant\", \"Training Coordinator\"],\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "spQDmFzOtfn0" + }, + "source": [ + "## Load Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 11, + "status": "ok", + "timestamp": 1761737069184, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "LBXsJk8Ith7j" + }, + "outputs": [], + "source": [ + "\n", + "# Global variables for model\n", + "current_model = None\n", + "current_pipeline = None\n", + "current_model_name = None\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 43, + "status": "ok", + "timestamp": 1761737106153, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "he0q6JGCtmRd" + }, + "outputs": [], + "source": [ + "def load_model(model_name):\n", + " \"\"\"Load the selected model\"\"\"\n", + " global current_model, current_pipeline, current_model_name\n", + "\n", + " # If model is already loaded, return\n", + " if current_model_name == model_name and current_pipeline is not None:\n", + " return f\"✅ {model_name} already loaded!\"\n", + "\n", + " # Clear previous model\n", + " if current_model is not None:\n", + " del current_model\n", + " del current_pipeline\n", + " torch.cuda.empty_cache()\n", + "\n", + " print(f\"🤖 Loading {model_name}...\")\n", + "\n", + " # Quantization config\n", + " bnb_config = BitsAndBytesConfig(\n", + " load_in_4bit=True,\n", + " bnb_4bit_quant_type=\"nf4\",\n", + " bnb_4bit_compute_dtype=torch.float16,\n", + " )\n", + "\n", + " # Load model\n", + " model_path = AVAILABLE_MODELS[model_name]\n", + " tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)\n", + " current_model = AutoModelForCausalLM.from_pretrained(\n", + " model_path,\n", + " quantization_config=bnb_config,\n", + " device_map=\"auto\",\n", + " trust_remote_code=True\n", + " )\n", + "\n", + " # Create pipeline\n", + " current_pipeline = pipeline(\n", + " \"text-generation\",\n", + " model=current_model,\n", + " tokenizer=tokenizer,\n", + " max_new_tokens=800,\n", + " temperature=0.8,\n", + " top_p=0.95,\n", + " do_sample=True\n", + " )\n", + "\n", + " current_model_name = model_name\n", + " return f\"✅ {model_name} loaded successfully!\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "lnfqfrVztx3t" + }, + "source": [ + "## Data Generation Functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1761737187566, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "bl0iTahzt24r" + }, + "outputs": [], + "source": [ + "def generate_job_description(role, industry):\n", + " \"\"\"Generate a realistic job description\"\"\"\n", + " prompt = f\"\"\"Create a detailed job description for a {role} position in the {industry} industry.\n", + "\n", + " Include:\n", + " - Job title and company type\n", + " - Job overview (2-3 sentences)\n", + " - Key responsibilities (4-5 bullet points)\n", + " - Required qualifications (3-4 items)\n", + " - Preferred skills (2-3 items)\n", + "\n", + " Job Description:\n", + " \"\"\"\n", + "\n", + " result = current_pipeline(prompt, return_full_text=False)[0]['generated_text']\n", + " return result.strip()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 5, + "status": "ok", + "timestamp": 1761737230115, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "XEgO5PvXuE3x" + }, + "outputs": [], + "source": [ + "def generate_matching_resume(role, industry, job_description):\n", + " \"\"\"Generate a resume that matches the job description\"\"\"\n", + " prompt = f\"\"\"Create a professional resume for a qualified {role} candidate applying to this position in {industry}.\n", + "\n", + " Job Requirements Summary:\n", + " {job_description[:400]}...\n", + "\n", + " Generate a resume with:\n", + " - Name and contact info\n", + " - Professional summary (2-3 sentences)\n", + " - Work experience (2-3 relevant positions with bullet points)\n", + " - Skills section (matching job requirements)\n", + " - Education\n", + "\n", + " Resume:\n", + " \"\"\"\n", + "\n", + " result = current_pipeline(prompt, return_full_text=False)[0]['generated_text']\n", + " return result.strip()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 9, + "status": "ok", + "timestamp": 1761737302930, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "RhtLuV3huNbK" + }, + "outputs": [], + "source": [ + "# main generation function\n", + "def generate_synthetic_data(model_name, industry, selected_roles, num_samples):\n", + " \"\"\"Main function to generate synthetic data\"\"\"\n", + "\n", + " # Validate inputs\n", + " if not selected_roles:\n", + " return \"❌ Please select at least one role!\", None, None\n", + "\n", + " # Load model if needed\n", + " status = load_model(model_name)\n", + " if \"❌\" in status:\n", + " return status, None, None\n", + "\n", + " synthetic_data = []\n", + " progress_text = f\"🚀 Generating data with {model_name}...\\n\\n\"\n", + "\n", + " for role in selected_roles:\n", + " progress_text += f\"🔹 Generating {num_samples} samples for: {role}\\n\"\n", + "\n", + " for i in range(num_samples):\n", + " # Generate job description\n", + " job_desc = generate_job_description(role, industry)\n", + "\n", + " # Generate matching resume\n", + " resume = generate_matching_resume(role, industry, job_desc)\n", + "\n", + " # Store the pair\n", + " synthetic_data.append({\n", + " 'id': len(synthetic_data) + 1,\n", + " 'industry': industry,\n", + " 'role': role,\n", + " 'job_description': job_desc,\n", + " 'resume': resume\n", + " })\n", + "\n", + " progress_text += f\" ✅ Sample {i+1}/{num_samples}\\n\"\n", + "\n", + " progress_text += f\"\\n✨ Generated {len(synthetic_data)} job-resume pairs!\\n\"\n", + "\n", + " # Save as JSON\n", + " json_file = 'synthetic_resume_data.json'\n", + " with open(json_file, 'w') as f:\n", + " json.dump(synthetic_data, f, indent=2)\n", + "\n", + " # Save as CSV\n", + " csv_file = 'synthetic_resume_data.csv'\n", + " df = pd.DataFrame(synthetic_data)\n", + " df.to_csv(csv_file, index=False)\n", + "\n", + " # Create preview\n", + " preview = f\"{'='*80}\\n\"\n", + " preview += f\"📊 GENERATED DATA SUMMARY\\n\"\n", + " preview += f\"{'='*80}\\n\\n\"\n", + " preview += f\"Total Samples: {len(synthetic_data)}\\n\"\n", + " preview += f\"Industry: {industry}\\n\"\n", + " preview += f\"Roles: {', '.join(selected_roles)}\\n\\n\"\n", + "\n", + " # Show first sample\n", + " sample = synthetic_data[0]\n", + " preview += f\"{'='*80}\\n\"\n", + " preview += f\"📄 SAMPLE #1\\n\"\n", + " preview += f\"{'='*80}\\n\\n\"\n", + " preview += f\"Role: {sample['role']}\\n\\n\"\n", + " preview += f\"JOB DESCRIPTION:\\n{'-'*80}\\n{sample['job_description'][:400]}...\\n\\n\"\n", + " preview += f\"MATCHING RESUME:\\n{'-'*80}\\n{sample['resume'][:400]}...\\n\\n\"\n", + "\n", + " return progress_text, preview, [json_file, csv_file]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "5DpmmFlpuhOI" + }, + "source": [ + "## Gradio UI" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "executionInfo": { + "elapsed": 185, + "status": "ok", + "timestamp": 1761737389227, + "user": { + "displayName": "Kwabena Baah-Boakye", + "userId": "14758998715370101460" + }, + "user_tz": 240 + }, + "id": "I_WI5ZHcujfv" + }, + "outputs": [], + "source": [ + "with gr.Blocks(title=\"Resume Data Generator\", theme=gr.themes.Soft()) as demo:\n", + "\n", + " gr.Markdown(\"\"\"\n", + " # 🎯 Synthetic Resume & Job Description Generator\n", + " Generate realistic job descriptions and matching resumes using AI\n", + " \"\"\")\n", + "\n", + " with gr.Row():\n", + " with gr.Column(scale=1):\n", + " gr.Markdown(\"### ⚙️ Configuration\")\n", + "\n", + " model_dropdown = gr.Dropdown(\n", + " choices=list(AVAILABLE_MODELS.keys()),\n", + " value=\"Phi-2\",\n", + " label=\"Select Model\",\n", + " info=\"Phi-2 is fastest, Mistral-7B is highest quality\"\n", + " )\n", + "\n", + " industry_dropdown = gr.Dropdown(\n", + " choices=list(AVAILABLE_INDUSTRIES.keys()),\n", + " value=\"Technology\",\n", + " label=\"Select Industry\"\n", + " )\n", + "\n", + " roles_checkbox = gr.CheckboxGroup(\n", + " choices=AVAILABLE_INDUSTRIES[\"Technology\"],\n", + " value=[\"Software Engineer\"],\n", + " label=\"Select Roles\",\n", + " info=\"Choose one or more roles\"\n", + " )\n", + "\n", + " num_samples_slider = gr.Slider(\n", + " minimum=1,\n", + " maximum=5,\n", + " value=2,\n", + " step=1,\n", + " label=\"Samples per Role\",\n", + " info=\"Number of job-resume pairs per role\"\n", + " )\n", + "\n", + " generate_btn = gr.Button(\"🚀 Generate Data\", variant=\"primary\", size=\"lg\")\n", + "\n", + " with gr.Column(scale=2):\n", + " gr.Markdown(\"### 📊 Generation Progress\")\n", + " progress_output = gr.Textbox(\n", + " label=\"Status\",\n", + " lines=10,\n", + " interactive=False\n", + " )\n", + "\n", + " gr.Markdown(\"### 👀 Data Preview\")\n", + " preview_output = gr.Textbox(\n", + " label=\"Sample Output\",\n", + " lines=15,\n", + " interactive=False\n", + " )\n", + "\n", + " download_files = gr.Files(\n", + " label=\"📥 Download Generated Data\",\n", + " interactive=False\n", + " )\n", + "\n", + " # Update roles when industry changes\n", + " def update_roles(industry):\n", + " return gr.CheckboxGroup(\n", + " choices=AVAILABLE_INDUSTRIES[industry],\n", + " value=[AVAILABLE_INDUSTRIES[industry][0]]\n", + " )\n", + "\n", + " industry_dropdown.change(\n", + " fn=update_roles,\n", + " inputs=[industry_dropdown],\n", + " outputs=[roles_checkbox]\n", + " )\n", + "\n", + " # Generate button click\n", + " generate_btn.click(\n", + " fn=generate_synthetic_data,\n", + " inputs=[model_dropdown, industry_dropdown, roles_checkbox, num_samples_slider],\n", + " outputs=[progress_output, preview_output, download_files]\n", + " )\n", + "\n", + " gr.Markdown(\"\"\"\n", + " ---\n", + " ### 📝 Instructions:\n", + " 1. Select your preferred AI model (Phi-2 recommended for speed)\n", + " 2. Choose an industry\n", + " 3. Select one or more job roles\n", + " 4. Set number of samples per role\n", + " 5. Click \"Generate Data\"\n", + " 6. Download the JSON and CSV files\n", + "\n", + " **Note:** First generation will take longer as the model loads (~1-2 min)\n", + " \"\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000, + "referenced_widgets": [ + "fe77515ae60c473f9fd8f14d277d8018", + "d19ac9d8e7164a81bfea0fc7755008c2", + "fda8ed07f5134d17baafe93802fcbb65", + "6ccd464fc32c4442ae536363f698c15a", + "9cc58686388c4eba84073f915651c9fd", + "b0cfd59674144bf3867d5fe71afc3d8d", + "10c32a6e39c4461989507ec82faed89b", + "69ef7bb7af4146e19e5395574551a5a9", + "a3b5f02b92f64b10bd6d1be9f273874a", + "75824129edc64bad89546692ee7c29ed", + "86d074fedac54474aea3e9949c4acf16", + "32a0dc8c74a14cf0be563f68b4564730", + "bffe914c77f847dd9fcd90edc0b4b138", + "a9536eebcb254487a1e13f56cd206790", + "c6c8968c670b4609a55c47f6f0cf7a75", + "09751e1d4b8b43eea2ee8d7f8db4dea2", + "05cef2803a7443ec87962d4eca917b8b", + "e8574b0fb8004963a0784e6716b2cb39", + "7340abb9f7164daea130ea0b3e3a4a15", + "a79aaa9a4f474a818ada2370ed7b9b90", + "e6c1db9e739d455d8c1aec72462f4d0d", + "ed1bfe71116a4220a2b40d38b758d56e", + "bebe9b3d6d1349a5821a6d4ec27966db", + "2c108876737247ab91d44678a0d26e5d", + "d6b4b0abe1ec4302af1a8c08df86d12e", + "8e264a6e23a844fc99b55cb2cf796ffe", + "b6fdc5bda4464d1db53ec515c8a29326", + "efa27007da42405abd22c7769cfacb86", + "e60470937944412188c39401e7180ccc", + "5e646c4728934ceea4d431d0057fcc43", + "79753b5ddee246908626ad748bdce8e6", + "1809b8d551d64a5bab1bbc4f9842c396", + "1bf578436929490a8aff3fa556e59383", + "5b9bb153c13943449c33f2bca460373d", + "b20ae079666543d990a4a75b05e7b812", + "697774c0b1b449cab9bff5a52b0af19a", + "352cd919d3144a32a31291f5cf8708ef", + "fe5fce525c454df3bad9119ca139f827", + "6eeb1601fa634ea09c1bbce438d92250", + "20d0693bbaee419996a8fb60f538bda6", + "d0a0447c66b94e9b857941acf09411a4", + "84ead0ed5fcc428b82569e6559da19e3", + "bdec3876461546039be17f73ee22d93b", + "50c012b9974648fc944dd619fc2f8fd7", + "fde717f31c31403d9cea29631ae3fd3f", + "3111841513b741428b0c1eb969115423", + "d1a8a63d535146dfaeab7b11f9124e01", + "02b22bed461842b5bd1f059a36ad15e9", + "8c41d1252b1b47cf85db189ba113131b", + "c0012429f772404b9294c0a7f7813668", + "0e6f2a71098649b89f92c241c879322e", + "0ecf653fc9b34323963d527d31394a5f", + "9f021c8fdd1a4c5ebaf776cef4c3c6e5", + "b874f7cb74cd484ea9d439fed902413f", + "5eb1cd7471d541078083c4c65757dae3", + "03db753561414d7486ec74f1e088f36f", + "47b007b7088343299cf6dcdb5914b81f", + "3d7e815062ad45c3850b629d690ce083", + "2c02ee17eaf64c9e9ad2ebf45e28b228", + "19459df330004fc296f325b1ca5e9848", + "a398a448765d4039bcabd618b6cf9b9e", + "60edfa9fa0664fc6a325654e2c1f82ac", + "353a7f4c0a4c4dc9acf6bb1b9a82c785", + "b4c7e11132fb4485848b0e3da773c670", + "3b7bae1791f84ed98820981a09c77d71", + "1f1d84ed40904433ad8d39f4c2fd1102", + "6b7acd3a1217492e8df12d3bebb307ad", + "a4e7392fda9943df909997e4396a505a", + "50cdfb1773e44efb86ff58ecea54eb83", + "eaffaf768b3b418e8b0155db7b1e69b7", + "a0621443367a4916aa174c7a3f35b423", + "b057dececf27483d8f10b2d26bd33889", + "62191f7b25034058a3142f31efac4a14", + "e33e29c1f46546b3804a689ceb535eb6", + "eae7e9370d1a4ff1aca3ff7085abefe7", + "d3866bd194224c86854f750c1e554e0a", + "f7d91c33573b4d8cb7daad1fe91c0326", + "c498f0f94fa9469aa747a8268b1f2b9d", + "a0c170bc6704442f82511721c1679157", + "a208763a089442349dd02b2124ea8ee2", + "59d3f8b71282403baf2108d8572bcbba", + "8098bf281c6e4d739458dac320b9b4d9", + "ba1102f5a0de4f84b1b667873a695714", + "1bcb249785cb43ccbb7599c24dc5b32c", + "2f91c35ffac440fb809b191ddfdd4470", + "0b9f3c40eefa485f9fb4cb04cc2cbfd4", + "393a11916fc74cb0b06ff9883a277ce0", + "a0be20313ec341618fe21dd823505f25", + "c63cc27484314fb39b3e90ac08cbd634", + "f9996f628896422b9d7ca245cf5778f2", + "5b4c390602e543f9ba2c0b4d2791302e", + "a08a2842e4304d10b70b6ff8ec4e6cf1", + "6ce28d74c4fb43428c032522ad182a5a", + "5affca0205774fdebbb704f6c203f5d5", + "2e3152408e7c46548859aaee8bfb7026", + "f7a1533042d147d98a47517020ddc381", + "0570c9f9834b4a688308699091562237", + "32def674c22340a2a767a19382e529af", + "8b3883f4904d49ac9952e2e9d35fbb59", + "639d1efbed734d64a589c56d484e3db4", + "4bb37e9bbd144501ba47f9ef25e80820", + "70ddda588de84ee2b7bcd0b7577b04ce", + "d8d60e54d9aa40cd92ff9277163b87b8", + "64b2adb406b5450c9d8fdede4824cedf", + "9f66476fa2144929b7c3b1858057e504", + "0a055622a7604d2e8841c7b4b4df2f4c", + "26f95ed5b70542ae9bb2ad9cf9a757b2", + "dc3fcd04380c48938b6e1aac6f0e8678", + "6bc087f53ec04e1ca3d20fe904047a32", + "921ce416d4334bb8a0f23ecbb63fd475", + "65ae76a96baf4658bc9bc453fa996701", + "b64873a0b0f54794891f901c682df7f4", + "edf946295cd54cd5bd0d6e71b4e5bfd4", + "509220b9285b47beb6035b85f210b83a", + "df8cbe65ea41453688bacf26703982ce", + "2b3c564351244f6f95501d09008e8730", + "d0fbd998d4e04792b9095396be5b4e68", + "f6b0a899746a4e699ee275a7e3cab2f1", + "ef2158ffa54045748e6c99a11fd82a52", + "b02fe22e55c7447fb956a56d2e7c0dd5", + "36843acf56b14173b3cc48c175d1d1ff", + "5087a99e167b4e158ed00b428ebcb3fc", + "1ef5e3536b2543afbc81d9e39275e6e5", + "6018b6d3446f41518074eee309792225", + "87053b3ea0d5488c931f5992372f2f83", + "3d727982123f4905a6b27813860b27de", + "47e112c94103409da75406ee9fbc3c17", + "f72ec70b61c34b90a63aa60c9e318b18", + "b709a427d9f04fcd98e73788068abc99", + "5f8ff905a0184c14b42dabc7e8a35ce5", + "10e75af421ba42ff96364359b4a47391", + "4a6c3518e7e445a4ac4c89477c84af37", + "07854d945da54d84a57f7fc1543ed9bb", + "3d6499a0cdc8410fb0a2b28424d230de", + "5138a8080786484c9d6b02c8cfae5cf5", + "bb6e8f4386c84dfd84748fe653e8b014", + "bc4b1b1d7fdd4cf5b5f48be21556de5d", + "354e42a9ea8d436da42d997b2ac140c4", + "0a1336117cf446ec8235bfbdc810dfe0", + "a89df1d1d39e439b91a1374203d454a9", + "470181b67bed4fadb0a239e13ce7c63a", + "95b04410d3f3437d8921503ff42fdc1f", + "7ef3ae6da79a4740b9fbe4a67d4db175" + ] + }, + "id": "Rp3ehz4Su0cD", + "outputId": "1e649af9-f76b-4509-924b-719450d1f2e3" + }, + "outputs": [], + "source": [ + "#launch\n", + "demo.launch(share=True, debug=True)" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "authorship_tag": "ABX9TyPcbugH3DRZQYhvuORmaE+D", + "gpuType": "A100", + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "02b22bed461842b5bd1f059a36ad15e9": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b874f7cb74cd484ea9d439fed902413f", + "placeholder": "​", + "style": "IPY_MODEL_5eb1cd7471d541078083c4c65757dae3", + "value": " 1.08k/? [00:00<00:00, 131kB/s]" + } + }, + "03db753561414d7486ec74f1e088f36f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_47b007b7088343299cf6dcdb5914b81f", + "IPY_MODEL_3d7e815062ad45c3850b629d690ce083", + "IPY_MODEL_2c02ee17eaf64c9e9ad2ebf45e28b228" + ], + "layout": "IPY_MODEL_19459df330004fc296f325b1ca5e9848" + } + }, + "0570c9f9834b4a688308699091562237": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "05cef2803a7443ec87962d4eca917b8b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "07854d945da54d84a57f7fc1543ed9bb": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_3d6499a0cdc8410fb0a2b28424d230de", + "IPY_MODEL_5138a8080786484c9d6b02c8cfae5cf5", + "IPY_MODEL_bb6e8f4386c84dfd84748fe653e8b014" + ], + "layout": "IPY_MODEL_bc4b1b1d7fdd4cf5b5f48be21556de5d" + } + }, + "09751e1d4b8b43eea2ee8d7f8db4dea2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "0a055622a7604d2e8841c7b4b4df2f4c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "0a1336117cf446ec8235bfbdc810dfe0": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "0b9f3c40eefa485f9fb4cb04cc2cbfd4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "0e6f2a71098649b89f92c241c879322e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "0ecf653fc9b34323963d527d31394a5f": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "10c32a6e39c4461989507ec82faed89b": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "10e75af421ba42ff96364359b4a47391": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "1809b8d551d64a5bab1bbc4f9842c396": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "19459df330004fc296f325b1ca5e9848": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "1bcb249785cb43ccbb7599c24dc5b32c": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "1bf578436929490a8aff3fa556e59383": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "1ef5e3536b2543afbc81d9e39275e6e5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_47e112c94103409da75406ee9fbc3c17", + "placeholder": "​", + "style": "IPY_MODEL_f72ec70b61c34b90a63aa60c9e318b18", + "value": "Loading checkpoint shards: 100%" + } + }, + "1f1d84ed40904433ad8d39f4c2fd1102": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "20d0693bbaee419996a8fb60f538bda6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "26f95ed5b70542ae9bb2ad9cf9a757b2": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "2b3c564351244f6f95501d09008e8730": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "2c02ee17eaf64c9e9ad2ebf45e28b228": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_3b7bae1791f84ed98820981a09c77d71", + "placeholder": "​", + "style": "IPY_MODEL_1f1d84ed40904433ad8d39f4c2fd1102", + "value": " 99.0/99.0 [00:00<00:00, 12.7kB/s]" + } + }, + "2c108876737247ab91d44678a0d26e5d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_efa27007da42405abd22c7769cfacb86", + "placeholder": "​", + "style": "IPY_MODEL_e60470937944412188c39401e7180ccc", + "value": "merges.txt: " + } + }, + "2e3152408e7c46548859aaee8bfb7026": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "2f91c35ffac440fb809b191ddfdd4470": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "3111841513b741428b0c1eb969115423": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_c0012429f772404b9294c0a7f7813668", + "placeholder": "​", + "style": "IPY_MODEL_0e6f2a71098649b89f92c241c879322e", + "value": "added_tokens.json: " + } + }, + "32a0dc8c74a14cf0be563f68b4564730": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_bffe914c77f847dd9fcd90edc0b4b138", + "IPY_MODEL_a9536eebcb254487a1e13f56cd206790", + "IPY_MODEL_c6c8968c670b4609a55c47f6f0cf7a75" + ], + "layout": "IPY_MODEL_09751e1d4b8b43eea2ee8d7f8db4dea2" + } + }, + "32def674c22340a2a767a19382e529af": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "352cd919d3144a32a31291f5cf8708ef": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_bdec3876461546039be17f73ee22d93b", + "placeholder": "​", + "style": "IPY_MODEL_50c012b9974648fc944dd619fc2f8fd7", + "value": " 2.11M/? [00:00<00:00, 16.0MB/s]" + } + }, + "353a7f4c0a4c4dc9acf6bb1b9a82c785": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "354e42a9ea8d436da42d997b2ac140c4": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "36843acf56b14173b3cc48c175d1d1ff": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "393a11916fc74cb0b06ff9883a277ce0": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "3b7bae1791f84ed98820981a09c77d71": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "3d6499a0cdc8410fb0a2b28424d230de": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_354e42a9ea8d436da42d997b2ac140c4", + "placeholder": "​", + "style": "IPY_MODEL_0a1336117cf446ec8235bfbdc810dfe0", + "value": "generation_config.json: 100%" + } + }, + "3d727982123f4905a6b27813860b27de": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "3d7e815062ad45c3850b629d690ce083": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_353a7f4c0a4c4dc9acf6bb1b9a82c785", + "max": 99, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_b4c7e11132fb4485848b0e3da773c670", + "value": 99 + } + }, + "470181b67bed4fadb0a239e13ce7c63a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "47b007b7088343299cf6dcdb5914b81f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_a398a448765d4039bcabd618b6cf9b9e", + "placeholder": "​", + "style": "IPY_MODEL_60edfa9fa0664fc6a325654e2c1f82ac", + "value": "special_tokens_map.json: 100%" + } + }, + "47e112c94103409da75406ee9fbc3c17": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "4a6c3518e7e445a4ac4c89477c84af37": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "4bb37e9bbd144501ba47f9ef25e80820": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_9f66476fa2144929b7c3b1858057e504", + "placeholder": "​", + "style": "IPY_MODEL_0a055622a7604d2e8841c7b4b4df2f4c", + "value": "model-00002-of-00002.safetensors: 100%" + } + }, + "5087a99e167b4e158ed00b428ebcb3fc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_1ef5e3536b2543afbc81d9e39275e6e5", + "IPY_MODEL_6018b6d3446f41518074eee309792225", + "IPY_MODEL_87053b3ea0d5488c931f5992372f2f83" + ], + "layout": "IPY_MODEL_3d727982123f4905a6b27813860b27de" + } + }, + "509220b9285b47beb6035b85f210b83a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b02fe22e55c7447fb956a56d2e7c0dd5", + "placeholder": "​", + "style": "IPY_MODEL_36843acf56b14173b3cc48c175d1d1ff", + "value": " 5.00G/5.00G [00:17<00:00, 559MB/s]" + } + }, + "50c012b9974648fc944dd619fc2f8fd7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "50cdfb1773e44efb86ff58ecea54eb83": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e33e29c1f46546b3804a689ceb535eb6", + "max": 735, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_eae7e9370d1a4ff1aca3ff7085abefe7", + "value": 735 + } + }, + "5138a8080786484c9d6b02c8cfae5cf5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_a89df1d1d39e439b91a1374203d454a9", + "max": 124, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_470181b67bed4fadb0a239e13ce7c63a", + "value": 124 + } + }, + "59d3f8b71282403baf2108d8572bcbba": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_393a11916fc74cb0b06ff9883a277ce0", + "placeholder": "​", + "style": "IPY_MODEL_a0be20313ec341618fe21dd823505f25", + "value": " 35.7k/? [00:00<00:00, 4.25MB/s]" + } + }, + "5affca0205774fdebbb704f6c203f5d5": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "5b4c390602e543f9ba2c0b4d2791302e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_f7a1533042d147d98a47517020ddc381", + "max": 2, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_0570c9f9834b4a688308699091562237", + "value": 2 + } + }, + "5b9bb153c13943449c33f2bca460373d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_b20ae079666543d990a4a75b05e7b812", + "IPY_MODEL_697774c0b1b449cab9bff5a52b0af19a", + "IPY_MODEL_352cd919d3144a32a31291f5cf8708ef" + ], + "layout": "IPY_MODEL_fe5fce525c454df3bad9119ca139f827" + } + }, + "5e646c4728934ceea4d431d0057fcc43": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "5eb1cd7471d541078083c4c65757dae3": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "5f8ff905a0184c14b42dabc7e8a35ce5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "6018b6d3446f41518074eee309792225": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b709a427d9f04fcd98e73788068abc99", + "max": 2, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_5f8ff905a0184c14b42dabc7e8a35ce5", + "value": 2 + } + }, + "60edfa9fa0664fc6a325654e2c1f82ac": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "62191f7b25034058a3142f31efac4a14": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "639d1efbed734d64a589c56d484e3db4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_4bb37e9bbd144501ba47f9ef25e80820", + "IPY_MODEL_70ddda588de84ee2b7bcd0b7577b04ce", + "IPY_MODEL_d8d60e54d9aa40cd92ff9277163b87b8" + ], + "layout": "IPY_MODEL_64b2adb406b5450c9d8fdede4824cedf" + } + }, + "64b2adb406b5450c9d8fdede4824cedf": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "65ae76a96baf4658bc9bc453fa996701": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_b64873a0b0f54794891f901c682df7f4", + "IPY_MODEL_edf946295cd54cd5bd0d6e71b4e5bfd4", + "IPY_MODEL_509220b9285b47beb6035b85f210b83a" + ], + "layout": "IPY_MODEL_df8cbe65ea41453688bacf26703982ce" + } + }, + "697774c0b1b449cab9bff5a52b0af19a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_d0a0447c66b94e9b857941acf09411a4", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_84ead0ed5fcc428b82569e6559da19e3", + "value": 1 + } + }, + "69ef7bb7af4146e19e5395574551a5a9": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "6b7acd3a1217492e8df12d3bebb307ad": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_a4e7392fda9943df909997e4396a505a", + "IPY_MODEL_50cdfb1773e44efb86ff58ecea54eb83", + "IPY_MODEL_eaffaf768b3b418e8b0155db7b1e69b7" + ], + "layout": "IPY_MODEL_a0621443367a4916aa174c7a3f35b423" + } + }, + "6bc087f53ec04e1ca3d20fe904047a32": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "6ccd464fc32c4442ae536363f698c15a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_75824129edc64bad89546692ee7c29ed", + "placeholder": "​", + "style": "IPY_MODEL_86d074fedac54474aea3e9949c4acf16", + "value": " 7.34k/? [00:00<00:00, 773kB/s]" + } + }, + "6ce28d74c4fb43428c032522ad182a5a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "6eeb1601fa634ea09c1bbce438d92250": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "70ddda588de84ee2b7bcd0b7577b04ce": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_26f95ed5b70542ae9bb2ad9cf9a757b2", + "max": 563832976, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_dc3fcd04380c48938b6e1aac6f0e8678", + "value": 563832976 + } + }, + "7340abb9f7164daea130ea0b3e3a4a15": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "75824129edc64bad89546692ee7c29ed": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "79753b5ddee246908626ad748bdce8e6": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "7ef3ae6da79a4740b9fbe4a67d4db175": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "8098bf281c6e4d739458dac320b9b4d9": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "84ead0ed5fcc428b82569e6559da19e3": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "86d074fedac54474aea3e9949c4acf16": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "87053b3ea0d5488c931f5992372f2f83": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_10e75af421ba42ff96364359b4a47391", + "placeholder": "​", + "style": "IPY_MODEL_4a6c3518e7e445a4ac4c89477c84af37", + "value": " 2/2 [00:05<00:00,  2.25s/it]" + } + }, + "8b3883f4904d49ac9952e2e9d35fbb59": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "8c41d1252b1b47cf85db189ba113131b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "8e264a6e23a844fc99b55cb2cf796ffe": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_1809b8d551d64a5bab1bbc4f9842c396", + "placeholder": "​", + "style": "IPY_MODEL_1bf578436929490a8aff3fa556e59383", + "value": " 456k/? [00:00<00:00, 37.2MB/s]" + } + }, + "921ce416d4334bb8a0f23ecbb63fd475": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "95b04410d3f3437d8921503ff42fdc1f": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "9cc58686388c4eba84073f915651c9fd": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "9f021c8fdd1a4c5ebaf776cef4c3c6e5": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "9f66476fa2144929b7c3b1858057e504": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "a0621443367a4916aa174c7a3f35b423": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "a08a2842e4304d10b70b6ff8ec4e6cf1": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_32def674c22340a2a767a19382e529af", + "placeholder": "​", + "style": "IPY_MODEL_8b3883f4904d49ac9952e2e9d35fbb59", + "value": " 2/2 [00:17<00:00, 17.71s/it]" + } + }, + "a0be20313ec341618fe21dd823505f25": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "a0c170bc6704442f82511721c1679157": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_ba1102f5a0de4f84b1b667873a695714", + "placeholder": "​", + "style": "IPY_MODEL_1bcb249785cb43ccbb7599c24dc5b32c", + "value": "model.safetensors.index.json: " + } + }, + "a208763a089442349dd02b2124ea8ee2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_2f91c35ffac440fb809b191ddfdd4470", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_0b9f3c40eefa485f9fb4cb04cc2cbfd4", + "value": 1 + } + }, + "a398a448765d4039bcabd618b6cf9b9e": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "a3b5f02b92f64b10bd6d1be9f273874a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "a4e7392fda9943df909997e4396a505a": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b057dececf27483d8f10b2d26bd33889", + "placeholder": "​", + "style": "IPY_MODEL_62191f7b25034058a3142f31efac4a14", + "value": "config.json: 100%" + } + }, + "a79aaa9a4f474a818ada2370ed7b9b90": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "a89df1d1d39e439b91a1374203d454a9": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "a9536eebcb254487a1e13f56cd206790": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_7340abb9f7164daea130ea0b3e3a4a15", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_a79aaa9a4f474a818ada2370ed7b9b90", + "value": 1 + } + }, + "b02fe22e55c7447fb956a56d2e7c0dd5": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b057dececf27483d8f10b2d26bd33889": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b0cfd59674144bf3867d5fe71afc3d8d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b20ae079666543d990a4a75b05e7b812": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_6eeb1601fa634ea09c1bbce438d92250", + "placeholder": "​", + "style": "IPY_MODEL_20d0693bbaee419996a8fb60f538bda6", + "value": "tokenizer.json: " + } + }, + "b4c7e11132fb4485848b0e3da773c670": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "b64873a0b0f54794891f901c682df7f4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_2b3c564351244f6f95501d09008e8730", + "placeholder": "​", + "style": "IPY_MODEL_d0fbd998d4e04792b9095396be5b4e68", + "value": "model-00001-of-00002.safetensors: 100%" + } + }, + "b6fdc5bda4464d1db53ec515c8a29326": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b709a427d9f04fcd98e73788068abc99": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b874f7cb74cd484ea9d439fed902413f": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "ba1102f5a0de4f84b1b667873a695714": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "bb6e8f4386c84dfd84748fe653e8b014": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_95b04410d3f3437d8921503ff42fdc1f", + "placeholder": "​", + "style": "IPY_MODEL_7ef3ae6da79a4740b9fbe4a67d4db175", + "value": " 124/124 [00:00<00:00, 17.6kB/s]" + } + }, + "bc4b1b1d7fdd4cf5b5f48be21556de5d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "bdec3876461546039be17f73ee22d93b": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "bebe9b3d6d1349a5821a6d4ec27966db": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_2c108876737247ab91d44678a0d26e5d", + "IPY_MODEL_d6b4b0abe1ec4302af1a8c08df86d12e", + "IPY_MODEL_8e264a6e23a844fc99b55cb2cf796ffe" + ], + "layout": "IPY_MODEL_b6fdc5bda4464d1db53ec515c8a29326" + } + }, + "bffe914c77f847dd9fcd90edc0b4b138": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_05cef2803a7443ec87962d4eca917b8b", + "placeholder": "​", + "style": "IPY_MODEL_e8574b0fb8004963a0784e6716b2cb39", + "value": "vocab.json: " + } + }, + "c0012429f772404b9294c0a7f7813668": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "c498f0f94fa9469aa747a8268b1f2b9d": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_a0c170bc6704442f82511721c1679157", + "IPY_MODEL_a208763a089442349dd02b2124ea8ee2", + "IPY_MODEL_59d3f8b71282403baf2108d8572bcbba" + ], + "layout": "IPY_MODEL_8098bf281c6e4d739458dac320b9b4d9" + } + }, + "c63cc27484314fb39b3e90ac08cbd634": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_f9996f628896422b9d7ca245cf5778f2", + "IPY_MODEL_5b4c390602e543f9ba2c0b4d2791302e", + "IPY_MODEL_a08a2842e4304d10b70b6ff8ec4e6cf1" + ], + "layout": "IPY_MODEL_6ce28d74c4fb43428c032522ad182a5a" + } + }, + "c6c8968c670b4609a55c47f6f0cf7a75": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_e6c1db9e739d455d8c1aec72462f4d0d", + "placeholder": "​", + "style": "IPY_MODEL_ed1bfe71116a4220a2b40d38b758d56e", + "value": " 798k/? [00:00<00:00, 44.6MB/s]" + } + }, + "d0a0447c66b94e9b857941acf09411a4": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": "20px" + } + }, + "d0fbd998d4e04792b9095396be5b4e68": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "d19ac9d8e7164a81bfea0fc7755008c2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_b0cfd59674144bf3867d5fe71afc3d8d", + "placeholder": "​", + "style": "IPY_MODEL_10c32a6e39c4461989507ec82faed89b", + "value": "tokenizer_config.json: " + } + }, + "d1a8a63d535146dfaeab7b11f9124e01": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_0ecf653fc9b34323963d527d31394a5f", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_9f021c8fdd1a4c5ebaf776cef4c3c6e5", + "value": 1 + } + }, + "d3866bd194224c86854f750c1e554e0a": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "d6b4b0abe1ec4302af1a8c08df86d12e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_5e646c4728934ceea4d431d0057fcc43", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_79753b5ddee246908626ad748bdce8e6", + "value": 1 + } + }, + "d8d60e54d9aa40cd92ff9277163b87b8": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_6bc087f53ec04e1ca3d20fe904047a32", + "placeholder": "​", + "style": "IPY_MODEL_921ce416d4334bb8a0f23ecbb63fd475", + "value": " 564M/564M [00:03<00:00, 302MB/s]" + } + }, + "dc3fcd04380c48938b6e1aac6f0e8678": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "df8cbe65ea41453688bacf26703982ce": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e33e29c1f46546b3804a689ceb535eb6": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e60470937944412188c39401e7180ccc": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "e6c1db9e739d455d8c1aec72462f4d0d": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "e8574b0fb8004963a0784e6716b2cb39": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "eae7e9370d1a4ff1aca3ff7085abefe7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "eaffaf768b3b418e8b0155db7b1e69b7": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_d3866bd194224c86854f750c1e554e0a", + "placeholder": "​", + "style": "IPY_MODEL_f7d91c33573b4d8cb7daad1fe91c0326", + "value": " 735/735 [00:00<00:00, 98.5kB/s]" + } + }, + "ed1bfe71116a4220a2b40d38b758d56e": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "edf946295cd54cd5bd0d6e71b4e5bfd4": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_f6b0a899746a4e699ee275a7e3cab2f1", + "max": 4995584424, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_ef2158ffa54045748e6c99a11fd82a52", + "value": 4995584424 + } + }, + "ef2158ffa54045748e6c99a11fd82a52": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "ProgressStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "ProgressStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "bar_color": null, + "description_width": "" + } + }, + "efa27007da42405abd22c7769cfacb86": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f6b0a899746a4e699ee275a7e3cab2f1": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f72ec70b61c34b90a63aa60c9e318b18": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "f7a1533042d147d98a47517020ddc381": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "f7d91c33573b4d8cb7daad1fe91c0326": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "DescriptionStyleModel", + "state": { + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "DescriptionStyleModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "StyleView", + "description_width": "" + } + }, + "f9996f628896422b9d7ca245cf5778f2": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HTMLModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HTMLModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HTMLView", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_5affca0205774fdebbb704f6c203f5d5", + "placeholder": "​", + "style": "IPY_MODEL_2e3152408e7c46548859aaee8bfb7026", + "value": "Fetching 2 files: 100%" + } + }, + "fda8ed07f5134d17baafe93802fcbb65": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "FloatProgressModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "FloatProgressModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "ProgressView", + "bar_style": "success", + "description": "", + "description_tooltip": null, + "layout": "IPY_MODEL_69ef7bb7af4146e19e5395574551a5a9", + "max": 1, + "min": 0, + "orientation": "horizontal", + "style": "IPY_MODEL_a3b5f02b92f64b10bd6d1be9f273874a", + "value": 1 + } + }, + "fde717f31c31403d9cea29631ae3fd3f": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_3111841513b741428b0c1eb969115423", + "IPY_MODEL_d1a8a63d535146dfaeab7b11f9124e01", + "IPY_MODEL_02b22bed461842b5bd1f059a36ad15e9" + ], + "layout": "IPY_MODEL_8c41d1252b1b47cf85db189ba113131b" + } + }, + "fe5fce525c454df3bad9119ca139f827": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "fe77515ae60c473f9fd8f14d277d8018": { + "model_module": "@jupyter-widgets/controls", + "model_module_version": "1.5.0", + "model_name": "HBoxModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/controls", + "_model_module_version": "1.5.0", + "_model_name": "HBoxModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/controls", + "_view_module_version": "1.5.0", + "_view_name": "HBoxView", + "box_style": "", + "children": [ + "IPY_MODEL_d19ac9d8e7164a81bfea0fc7755008c2", + "IPY_MODEL_fda8ed07f5134d17baafe93802fcbb65", + "IPY_MODEL_6ccd464fc32c4442ae536363f698c15a" + ], + "layout": "IPY_MODEL_9cc58686388c4eba84073f915651c9fd" + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/week4/community-contributions/kwabena/unit_test_writer.ipynb b/week4/community-contributions/kwabena/unit_test_writer.ipynb new file mode 100644 index 0000000..4830ffb --- /dev/null +++ b/week4/community-contributions/kwabena/unit_test_writer.ipynb @@ -0,0 +1,294 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "50bd7e7c", + "metadata": {}, + "source": [ + "# Unit Test Writer" + ] + }, + { + "cell_type": "markdown", + "id": "ad339d11", + "metadata": {}, + "source": [ + "### Welcome to the Unit Test Writer - an AI-powered tool that automatically generates comprehensive unit tests for your code across multiple programming languages. Simply paste your code, select your language, and let AI create thorough test suites in seconds!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "27e4e719", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import os\n", + "import io\n", + "import sys\n", + "from dotenv import load_dotenv\n", + "from openai import OpenAI\n", + "import gradio as gr\n", + "import subprocess\n", + "from IPython.display import Markdown, display" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3572f5fa", + "metadata": {}, + "outputs": [], + "source": [ + "load_dotenv(override=True)\n", + "openai_api_key = os.getenv('OPENAI_API_KEY')\n", + "anthropic_api_key = os.getenv('ANTHROPIC_API_KEY')\n", + "google_api_key = os.getenv('GOOGLE_API_KEY')\n", + "grok_api_key = os.getenv('GROK_API_KEY')\n", + "groq_api_key = os.getenv('GROQ_API_KEY')\n", + "openrouter_api_key = os.getenv('OPENROUTER_API_KEY')\n", + "\n", + "if openai_api_key:\n", + " print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n", + "else:\n", + " print(\"OpenAI API Key not set\")\n", + " \n", + "if anthropic_api_key:\n", + " print(f\"Anthropic API Key exists and begins {anthropic_api_key[:7]}\")\n", + "else:\n", + " print(\"Anthropic API Key not set (and this is optional)\")\n", + "\n", + "if google_api_key:\n", + " print(f\"Google API Key exists and begins {google_api_key[:2]}\")\n", + "else:\n", + " print(\"Google API Key not set (and this is optional)\")\n", + "\n", + "if grok_api_key:\n", + " print(f\"Grok API Key exists and begins {grok_api_key[:4]}\")\n", + "else:\n", + " print(\"Grok API Key not set (and this is optional)\")\n", + "\n", + "if groq_api_key:\n", + " print(f\"Groq API Key exists and begins {groq_api_key[:4]}\")\n", + "else:\n", + " print(\"Groq API Key not set (and this is optional)\")\n", + "\n", + "if openrouter_api_key:\n", + " print(f\"OpenRouter API Key exists and begins {openrouter_api_key[:6]}\")\n", + "else:\n", + " print(\"OpenRouter API Key not set (and this is optional)\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05293821", + "metadata": {}, + "outputs": [], + "source": [ + "# Connect to client libraries\n", + "\n", + "openai = OpenAI()\n", + "\n", + "anthropic_url = \"https://api.anthropic.com/v1/\"\n", + "gemini_url = \"https://generativelanguage.googleapis.com/v1beta/openai/\"\n", + "grok_url = \"https://api.x.ai/v1\"\n", + "groq_url = \"https://api.groq.com/openai/v1\"\n", + "ollama_url = \"http://localhost:11434/v1\"\n", + "openrouter_url = \"https://openrouter.ai/api/v1\"\n", + "\n", + "anthropic = OpenAI(api_key=anthropic_api_key, base_url=anthropic_url)\n", + "gemini = OpenAI(api_key=google_api_key, base_url=gemini_url)\n", + "grok = OpenAI(api_key=grok_api_key, base_url=grok_url)\n", + "groq = OpenAI(api_key=groq_api_key, base_url=groq_url)\n", + "ollama = OpenAI(api_key=\"ollama\", base_url=ollama_url)\n", + "openrouter = OpenAI(api_key=openrouter_api_key, base_url=openrouter_url)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "41eec7d3", + "metadata": {}, + "outputs": [], + "source": [ + "models = [\"gpt-5\", \"claude-sonnet-4-5-20250929\", \"grok-4\", \"gemini-2.5-pro\", \"qwen2.5-coder\", \"deepseek-coder-v2\", \"gpt-oss:20b\", \"qwen/qwen3-coder-30b-a3b-instruct\", \"openai/gpt-oss-120b\", ]\n", + "\n", + "clients = {\"gpt-5\": openai, \"claude-sonnet-4-5-20250929\": anthropic, \"grok-4\": grok, \"gemini-2.5-pro\": gemini, \"openai/gpt-oss-120b\": groq, \"qwen2.5-coder\": ollama, \"deepseek-coder-v2\": ollama, \"gpt-oss:20b\": ollama, \"qwen/qwen3-coder-30b-a3b-instruct\": openrouter}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05ca8fcc", + "metadata": {}, + "outputs": [], + "source": [ + "# Function to generate unit tests\n", + "def generate_unit_tests(code, language, model_name):\n", + " \"\"\"Generate unit tests for the provided code\"\"\"\n", + " \n", + " if not code.strip():\n", + " return \"Please provide some code to generate tests for.\"\n", + " \n", + " # Select the appropriate client\n", + " client = clients.get(model_name, openai)\n", + " \n", + " # Create the prompt based on language\n", + " test_frameworks = {\n", + " \"Python\": \"pytest\",\n", + " \"JavaScript\": \"Jest\",\n", + " \"TypeScript\": \"Jest\",\n", + " \"Java\": \"JUnit\",\n", + " \"C#\": \"NUnit\",\n", + " \"Go\": \"testing package\",\n", + " \"Ruby\": \"RSpec\",\n", + " \"PHP\": \"PHPUnit\",\n", + " \"Rust\": \"built-in test framework\"\n", + " }\n", + " \n", + " framework = test_frameworks.get(language, \"appropriate testing framework\")\n", + " \n", + " prompt = f\"\"\"You are a unit test expert. Generate comprehensive unit tests for the following {language} code using {framework}.\n", + "\n", + " Code to test:\n", + " ```{language.lower()}\n", + " {code}\n", + " ```\n", + "\n", + " Requirements:\n", + " - Create thorough unit tests covering normal cases, edge cases, and error cases\n", + " - Use {framework} syntax and best practices\n", + " - Include clear test names that describe what is being tested\n", + " - Add comments explaining complex test scenarios\n", + " - Ensure tests are independent and can run in any order\n", + "\n", + " Provide ONLY the test code, no explanations.\"\"\"\n", + "\n", + " try:\n", + " # Call the API\n", + " response = client.chat.completions.create(\n", + " model=model_name,\n", + " messages=[\n", + " {\"role\": \"user\", \"content\": prompt}\n", + " ],\n", + " temperature=0.7,\n", + " )\n", + " \n", + " return response.choices[0].message.content\n", + " \n", + " except Exception as e:\n", + " return f\"Error generating tests: {str(e)}\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d51e13d3", + "metadata": {}, + "outputs": [], + "source": [ + "# Create Gradio interface\n", + "def create_interface():\n", + " with gr.Blocks(title=\"Unit Test Generator\") as demo:\n", + " gr.Markdown(\"# 🧪 Unit Test Generator\")\n", + " gr.Markdown(\"Paste your code, select the language, and generate comprehensive unit tests!\")\n", + " \n", + " with gr.Row():\n", + " with gr.Column():\n", + " code_input = gr.TextArea(\n", + " label=\"Your Code\",\n", + " placeholder=\"Paste your code here...\",\n", + " lines=15\n", + " )\n", + " \n", + " with gr.Row():\n", + " language_dropdown = gr.Dropdown(\n", + " choices=[\"Python\", \"JavaScript\", \"TypeScript\", \"Java\", \"C#\", \"Go\", \"Ruby\", \"PHP\", \"Rust\"],\n", + " value=\"Python\",\n", + " label=\"Language\"\n", + " )\n", + " \n", + " model_dropdown = gr.Dropdown(\n", + " choices=models,\n", + " value=\"gpt-5\",\n", + " label=\"Model\"\n", + " )\n", + " \n", + " generate_btn = gr.Button(\"Generate Unit Tests\", variant=\"primary\")\n", + " \n", + " with gr.Column():\n", + " output = gr.TextArea(\n", + " label=\"Generated Unit Tests\",\n", + " lines=15\n", + " )\n", + " \n", + " # Example\n", + " gr.Markdown(\"### Example\")\n", + " gr.Examples(\n", + " examples=[\n", + " [\"\"\"def add(a, b):\n", + " return a + b\n", + "\n", + "def multiply(a, b):\n", + " return a * b\n", + "\n", + "def divide(a, b):\n", + " if b == 0:\n", + " raise ValueError(\"Cannot divide by zero\")\n", + " return a / b\"\"\", \"Python\", \"gpt-5\"],\n", + " [\"\"\"function isPalindrome(str) {\n", + " const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');\n", + " return cleaned === cleaned.split('').reverse().join('');\n", + "}\"\"\", \"JavaScript\", \"gpt-5\"]\n", + " ],\n", + " inputs=[code_input, language_dropdown, model_dropdown]\n", + " )\n", + " \n", + " # Connect the button\n", + " generate_btn.click(\n", + " fn=generate_unit_tests,\n", + " inputs=[code_input, language_dropdown, model_dropdown],\n", + " outputs=output\n", + " )\n", + " \n", + " return demo" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8eff8ac", + "metadata": {}, + "outputs": [], + "source": [ + "# Launch the interface\n", + "demo = create_interface()\n", + "demo.launch(share=False)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/week5/community-contributions/kwabena/expert resume creator.ipynb b/week5/community-contributions/kwabena/expert resume creator.ipynb new file mode 100644 index 0000000..e431b26 --- /dev/null +++ b/week5/community-contributions/kwabena/expert resume creator.ipynb @@ -0,0 +1,511 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "85b93c49", + "metadata": {}, + "source": [ + "# Expert Resume Creator" + ] + }, + { + "cell_type": "markdown", + "id": "8f90fe9a", + "metadata": {}, + "source": [ + " In this exercise, we'll build a RAG-powered resume refinement tool that helps tailor resumes to specific job descriptions.\n", + " \n", + " What We'll Build\n", + " An AI assistant that takes a job description and current resume, then produces an optimized version using resume writing best practices.\n", + " \n", + " The Approach (RAG)\n", + " 1. **Generate Knowledge Base** - Use an LLM to create expert resume writing guides\n", + " 2. **Create Vector Database** - Store the knowledge in Chroma for semantic search\n", + " 3. **Build Interface** - Create a Gradio app where users can refine their resumes\n", + " \n", + " Steps\n", + " - **STEP 1**: Generate synthetic resume writing knowledge using LLM\n", + " - **STEP 2**: Load documents and create RAG with Chroma vector database\n", + " - **STEP 3**: Build Gradio interface for users to input job description and resume\n", + " \n", + " ---\n", + " \n", + " Let's get started! 🚀" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f889c1d", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import os\n", + "import glob\n", + "from dotenv import load_dotenv\n", + "import gradio as gr" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3711bc34", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.document_loaders import DirectoryLoader, TextLoader\n", + "from langchain.text_splitter import CharacterTextSplitter\n", + "from langchain.schema import Document\n", + "from langchain_openai import OpenAIEmbeddings, ChatOpenAI\n", + "from langchain_chroma import Chroma\n", + "from langchain.memory import ConversationBufferMemory\n", + "from langchain.chains import ConversationalRetrievalChain\n", + "from langchain.embeddings import HuggingFaceEmbeddings" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "840999d8", + "metadata": {}, + "outputs": [], + "source": [ + "# Configuration\n", + "MODEL = \"gpt-4o-mini\"\n", + "db_name = \"resume_vector_db\"\n", + "KNOWLEDGE_BASE_DIR = \"resume-knowledge-base\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4695238c", + "metadata": {}, + "outputs": [], + "source": [ + "#load environment variables\n", + "load_dotenv(override=True)\n", + "os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-if-not-using-env')" + ] + }, + { + "cell_type": "markdown", + "id": "37ce61e4", + "metadata": {}, + "source": [ + "### STEP 1 - Programmatically Generate Synthetic Resume Knowledge Base" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6257788", + "metadata": {}, + "outputs": [], + "source": [ + "def generate_content_with_llm(topic, category):\n", + " \"\"\"Use LLM to generate content for a specific topic\"\"\"\n", + " \n", + " llm = ChatOpenAI(temperature=0.8, model_name=MODEL)\n", + " \n", + " prompts = {\n", + " \"best-practices\": f\"\"\"You are an expert resume writer and career coach. Write a comprehensive guide about: {topic}\n", + "\n", + " Create a detailed markdown document with:\n", + " - Clear section headers\n", + " - Specific, actionable advice\n", + " - Multiple concrete examples\n", + " - Do's and don'ts\n", + " - Real-world tips that hiring managers look for\n", + "\n", + " Write 500-800 words in markdown format. Be specific and practical.\"\"\",\n", + " \n", + " \"industry-specific\": f\"\"\"You are an expert resume writer specializing in {topic} industry resumes.\n", + "\n", + " Write a comprehensive industry guide covering:\n", + " - Key skills and technologies to highlight for {topic} roles\n", + " - How to structure experience for this industry\n", + " - Important keywords and terminology\n", + " - 5-8 example bullet points showing strong achievements with specific metrics\n", + " - Common mistakes to avoid\n", + " - What hiring managers in {topic} look for\n", + "\n", + " Write 600-900 words in markdown format with specific examples.\"\"\",\n", + " \n", + " \"examples\": f\"\"\"You are an expert resume writer. Create detailed examples for: {topic}\n", + "\n", + " Provide:\n", + " - 3-4 complete, realistic examples showing proper formatting\n", + " - Each example should include company name, dates, and 4-6 bullet points\n", + " - Bullet points must include quantified achievements (numbers, percentages, dollar amounts)\n", + " - Show variety in roles (junior, mid-level, senior)\n", + " - Use strong action verbs\n", + " - Demonstrate clear impact and results\n", + "\n", + " Write in markdown format. Make examples realistic and impressive.\"\"\",\n", + " \n", + " \"specialized\": f\"\"\"You are an expert in resume writing for {topic}.\n", + "\n", + " Create a comprehensive guide covering:\n", + " - Unique considerations for {topic}\n", + " - Best practices and formatting tips\n", + " - 6-10 strong example bullet points with metrics\n", + " - Common questions and how to address them\n", + " - What makes a standout resume in this area\n", + "\n", + " Write 500-700 words in markdown format.\"\"\"\n", + " }\n", + " \n", + " prompt = prompts.get(category, prompts[\"best-practices\"])\n", + " response = llm.invoke(prompt)\n", + " return response.content" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a3e0c62", + "metadata": {}, + "outputs": [], + "source": [ + "def create_resume_knowledge_base():\n", + " \"\"\"Programmatically generate comprehensive resume knowledge base using LLM\"\"\"\n", + " \n", + " print(\"🤖 Starting LLM-powered knowledge base generation...\")\n", + " print(\"⏳ This may take 2-3 minutes to generate all content...\\n\")\n", + " \n", + " # Create directory structure\n", + " os.makedirs(f\"{KNOWLEDGE_BASE_DIR}/best-practices\", exist_ok=True)\n", + " os.makedirs(f\"{KNOWLEDGE_BASE_DIR}/examples\", exist_ok=True)\n", + " os.makedirs(f\"{KNOWLEDGE_BASE_DIR}/industry-specific\", exist_ok=True)\n", + " os.makedirs(f\"{KNOWLEDGE_BASE_DIR}/specialized\", exist_ok=True)\n", + " \n", + " # Define topics for each category\n", + " topics = {\n", + " \"best-practices\": [\n", + " \"Resume Formatting and Structure\",\n", + " \"Powerful Action Verbs and Keywords\",\n", + " \"Quantifying Achievements and Impact\",\n", + " \"Tailoring Resume to Job Descriptions\",\n", + " \"ATS (Applicant Tracking System) Optimization\",\n", + " \"Common Resume Mistakes to Avoid\"\n", + " ],\n", + " \"industry-specific\": [\n", + " \"Software Engineering and Technology\",\n", + " \"Data Science and Machine Learning\",\n", + " \"Business and Marketing\",\n", + " \"Finance and Accounting\",\n", + " \"Healthcare and Medical\",\n", + " \"Product Management\"\n", + " ],\n", + " \"examples\": [\n", + " \"Strong Experience Section Examples\",\n", + " \"Skills Section Formatting\",\n", + " \"Project Descriptions for Technical Roles\",\n", + " \"Leadership and Management Achievements\",\n", + " \"Entry-Level Resume Examples\"\n", + " ],\n", + " \"specialized\": [\n", + " \"Career Changers and Transitions\",\n", + " \"Recent Graduates and Internships\",\n", + " \"Executive and C-Level Resumes\",\n", + " \"Freelance and Contract Work\",\n", + " \"Career Gaps and Explanations\"\n", + " ]\n", + " }\n", + " \n", + " total_files = sum(len(topic_list) for topic_list in topics.values())\n", + " current_file = 0\n", + " \n", + " # Generate content for each category and topic\n", + " for category, topic_list in topics.items():\n", + " for topic in topic_list:\n", + " current_file += 1\n", + " print(f\"[{current_file}/{total_files}] Generating: {category}/{topic}...\")\n", + " \n", + " try:\n", + " # Generate content using LLM\n", + " content = generate_content_with_llm(topic, category)\n", + " \n", + " # Create filename from topic\n", + " filename = topic.lower().replace(\" \", \"-\").replace(\"(\", \"\").replace(\")\", \"\") + \".md\"\n", + " filepath = f\"{KNOWLEDGE_BASE_DIR}/{category}/{filename}\"\n", + " \n", + " # Add title to content\n", + " full_content = f\"# {topic}\\n\\n{content}\"\n", + " \n", + " # Write to file\n", + " with open(filepath, \"w\", encoding=\"utf-8\") as f:\n", + " f.write(full_content)\n", + " \n", + " print(f\" ✅ Saved to {category}/{filename}\")\n", + " \n", + " except Exception as e:\n", + " print(f\" ❌ Error generating {topic}: {str(e)}\")\n", + " continue\n", + " \n", + " print(f\"\\n✅ Knowledge base generation complete!\")\n", + " print(f\"📁 Created {total_files} files across 4 categories:\")\n", + " print(f\" - {len(topics['best-practices'])} best practice guides\")\n", + " print(f\" - {len(topics['industry-specific'])} industry-specific guides\")\n", + " print(f\" - {len(topics['examples'])} example collections\")\n", + " print(f\" - {len(topics['specialized'])} specialized guides\")\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7257b2b", + "metadata": {}, + "outputs": [], + "source": [ + "# Run this to create the knowledge base\n", + "create_resume_knowledge_base()" + ] + }, + { + "cell_type": "markdown", + "id": "292a8d84", + "metadata": {}, + "source": [ + "### Load and Process Documents" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d8c18a52", + "metadata": {}, + "outputs": [], + "source": [ + " # Read in documents using LangChain's loaders\n", + "folders = glob.glob(f\"{KNOWLEDGE_BASE_DIR}/*\")\n", + "\n", + "def add_metadata(doc, doc_type):\n", + " doc.metadata[\"doc_type\"] = doc_type\n", + " return doc\n", + "\n", + "text_loader_kwargs = {'encoding': 'utf-8'}\n", + "\n", + "documents = []\n", + "for folder in folders:\n", + " doc_type = os.path.basename(folder)\n", + " loader = DirectoryLoader(folder, glob=\"**/*.md\", loader_cls=TextLoader, loader_kwargs=text_loader_kwargs)\n", + " folder_docs = loader.load()\n", + " documents.extend([add_metadata(doc, doc_type) for doc in folder_docs])\n", + "\n", + "text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=200)\n", + "chunks = text_splitter.split_documents(documents)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "567829d5", + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"Total number of chunks: {len(chunks)}\")\n", + "print(f\"Document types found: {set(doc.metadata['doc_type'] for doc in documents)}\")" + ] + }, + { + "cell_type": "markdown", + "id": "12e5dfb1", + "metadata": {}, + "source": [ + "Create Vector Store" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94239c9d", + "metadata": {}, + "outputs": [], + "source": [ + "# Using OpenAI embeddings (you can switch to HuggingFace for free alternative)\n", + "embeddings = OpenAIEmbeddings()\n", + "\n", + "# Alternative free option:\n", + "# embeddings = HuggingFaceEmbeddings(model_name=\"sentence-transformers/all-MiniLM-L6-v2\")\n", + "\n", + "# Delete if already exists\n", + "if os.path.exists(db_name):\n", + " Chroma(persist_directory=db_name, embedding_function=embeddings).delete_collection()\n", + "\n", + "# Create vectorstore\n", + "vectorstore = Chroma.from_documents(documents=chunks, embedding=embeddings, persist_directory=db_name)\n", + "print(f\"✅ Vectorstore created with {vectorstore._collection.count()} documents\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "62554189", + "metadata": {}, + "source": [ + "Set up RAG Chain" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e2b349f5", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "llm = ChatOpenAI(temperature=0.7, model_name=MODEL)\n", + "\n", + "# Alternative - use Ollama locally:\n", + "# llm = ChatOpenAI(temperature=0.7, model_name='llama3.2', base_url='http://localhost:11434/v1', api_key='ollama')\n", + "\n", + "memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)\n", + "retriever = vectorstore.as_retriever(search_kwargs={\"k\": 10})\n", + "conversation_chain = ConversationalRetrievalChain.from_llm(llm=llm, retriever=retriever, memory=memory)\n", + "\n", + "print(\"✅ RAG chain configured and ready\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "280ad157", + "metadata": {}, + "source": [ + "Create Resume Refinement Function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f54e5573", + "metadata": {}, + "outputs": [], + "source": [ + "def refine_resume(job_description, current_resume, history=None):\n", + " \"\"\"\n", + " Refines a resume based on job description using RAG knowledge base\n", + " \"\"\"\n", + " # Reset memory for each new refinement\n", + " global conversation_chain, memory, llm, retriever\n", + " memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True)\n", + " conversation_chain = ConversationalRetrievalChain.from_llm(llm=llm, retriever=retriever, memory=memory)\n", + " \n", + " prompt = f\"\"\"You are an expert resume writer with access to best practices and successful examples.\n", + "\n", + " JOB DESCRIPTION:\n", + " {job_description}\n", + "\n", + " CURRENT RESUME:\n", + " {current_resume}\n", + "\n", + " Please analyze the current resume and provide a refined version that:\n", + " 1. Aligns keywords and skills with the job description\n", + " 2. Uses strong action verbs and quantified achievements\n", + " 3. Follows formatting best practices\n", + " 4. Highlights most relevant experience for this role\n", + " 5. Removes or de-emphasizes less relevant information\n", + "\n", + " Provide the refined resume in a clear, professional format. Also include a brief \"KEY IMPROVEMENTS\" section at the end explaining the main changes you made and why.\n", + " \"\"\"\n", + " \n", + " result = conversation_chain.invoke({\"question\": prompt})\n", + " return result[\"answer\"]\n" + ] + }, + { + "cell_type": "markdown", + "id": "4efdfe8b", + "metadata": {}, + "source": [ + "Create Gradio Interface" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dacb51de", + "metadata": {}, + "outputs": [], + "source": [ + "def create_gradio_interface():\n", + " with gr.Blocks(title=\"Expert Resume Creator\") as interface:\n", + " gr.Markdown(\"# 📄 Expert Resume Creator\")\n", + " gr.Markdown(\"Refine your resume using AI-powered best practices and tailored optimization\")\n", + " \n", + " with gr.Row():\n", + " with gr.Column():\n", + " job_desc_input = gr.Textbox(\n", + " label=\"Job Description\",\n", + " placeholder=\"Paste the job description here...\",\n", + " lines=10\n", + " )\n", + " resume_input = gr.Textbox(\n", + " label=\"Your Current Resume\",\n", + " placeholder=\"Paste your current resume here...\",\n", + " lines=15\n", + " )\n", + " submit_btn = gr.Button(\"✨ Refine My Resume\", variant=\"primary\", size=\"lg\")\n", + " \n", + " with gr.Column():\n", + " output = gr.Textbox(\n", + " label=\"Refined Resume\",\n", + " lines=30,\n", + " show_copy_button=True\n", + " )\n", + " \n", + " gr.Markdown(\"### 💡 Tips\")\n", + " gr.Markdown(\"\"\"\n", + " - Include complete job description with requirements and responsibilities\n", + " - Paste your full resume including experience, education, and skills\n", + " - The AI will optimize your resume to match the job requirements\n", + " - Review the KEY IMPROVEMENTS section to understand the changes\n", + " \"\"\")\n", + " \n", + " submit_btn.click(\n", + " fn=refine_resume,\n", + " inputs=[job_desc_input, resume_input],\n", + " outputs=output\n", + " )\n", + " \n", + " return interface" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e01ddd13", + "metadata": {}, + "outputs": [], + "source": [ + "# Launch the interface\n", + "interface = create_gradio_interface()\n", + "interface.launch(inbrowser=True, share=False)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/week6/community-contributions/kwabena/fine_tune_train.jsonl b/week6/community-contributions/kwabena/fine_tune_train.jsonl new file mode 100644 index 0000000..7f6d391 --- /dev/null +++ b/week6/community-contributions/kwabena/fine_tune_train.jsonl @@ -0,0 +1,200 @@ +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMovo Wireless Microphone System with Plug-on XLR Transmitter Adapter and Portable Receiver - Converts Self Powered Shotgun Mics, Lavs, Dynamic Microphones to Wireless - for Stage, Film\nCRYSTAL CLEAR SOUND Transmitter picks up crisp audio signals and broadcasts them with zero interference POWERFUL TRANSMISSION Plug-in wireless transmitter broadcasts audio signal up to 300 feet away without obstructions 1-YEAR WARRANTY We\u2019ve got your back! Our products are designed to ease your technical woes, not add to them. Our friendly US-Based support team is here to help MOUNT IT YOUR WAY Receiver can be clipped onto belt or attached to DSLR cameras and phone video rigs via cold shoe mount INCLUDES TXLR Wireless Plug-in Transmitter, RX Wireless Receiver Weight 1.28 pounds,"}, {"role": "assistant", "content": "Price is $109.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBOYA Wireless USB-C Lavalier Microphone System for Samsung Google Pixel Smartphones Livestream, 2.4GHz Mic with Buit-in Battery for Pad, Tablets, DSLR Camera, Camcoder, Home Video Vlog Interview\n2.4G DIGITAL RF TECHNOLOGY WIRELESS MIC | BOYA BY-WM3 is designed for reliable and trouble-free performance.Working distance up to 66ft and our frequencies has no conflict with the govt frequencies for safe usage. 20M TRANSMITTION WIRELESS RANGE | BY-WM3 transmitter to receiver transfers stable and anti-interference signals up to long distance. Optimize audio instanly, which is efficient in post processing and offers a high quality audio performance in live broadcasting. LONG WORKING TIME"}, {"role": "assistant", "content": "Price is $99.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHozan C-200 Pedal Wrench\nx 15 x 15mm O.A.L. 310mm Hozan Pedal Wrench 15mm Offset and 15mm 90 Degree. Dimensions L x W x H 15.75 x 3.86 x 0.75 inches, Weight 0.78 Pounds, Dimensions LxWxH 12.9 x 4 x 0.65 inches, Weight 0.33 Kilograms, Brand Name Hozan, Color X, s 1, Manufacturer Hozan, Part C-200, Model Year 2017, Size 10, Sport Type X, Rank Musical Instruments 78978, Guitar & Bass Pedal Boards & Cases 329, Available September "}, {"role": "assistant", "content": "Price is $28.49"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDryer Drum Roller Kit Whirlpool Kenmore Amana Support Part Replacement\n\ud83d\udca1 Drum Roller - An equivalent for parts 3436, 8170, 8205, Roller Kit is compatible with Whirlpool, Maytag, KitchenAid, Jenn-Air, Amana, Magic Chef, Admiral, Norge, Roper appliances. The Part is designed to support the drum and help it rotate smoothly during operation. Kit fits hundred of models and can be easily install. \ud83d\udd27 DIY eTips Included - Not sure how to replace the Dryer Drum Roller Helpful information can be found on the page below. Scroll down to get more repair tips. Acquire valuable skills during the DIY repair project. Whirlpool Drum Roller will help if your appliance does not tumble, is noisy"}, {"role": "assistant", "content": "Price is $7.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nReplacement Icemaker Kit Compatible With Frigidaire Refrigerators\nCompatible with the following brands Electrolux, Frigidaire, Gibson, White Westinghouse and Kelvinator and Kenmore Refrigerators (model specific). Replacement Icemaker Kit. High Quality Replacement Part. 90 Day Manufacturer Warranty. Compatible with the following brands Electrolux, Frigidaire, Gibson, White Westinghouse and Kelvinator and Kenmore Refrigerators (model specific). Replacement Icemaker Kit. High Quality Replacement Part. 90 Day Manufacturer Warranty. Manufacturer Midwest Appliance Parts, Part model number Material Other, Quantity 1, Rank Tools & Home Improvement Refrigerator Replacement Ice Makers 1225, Available May 29, 2020"}, {"role": "assistant", "content": "Price is $66.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSiwdoy Ice Maker Compatible with Ken-More Refrigerators\nIce Maker for Refrigerator. Specifications Suitable for Ice Makers Malfunctioning or completely broken ice makers The housing is made of industrial strength materials. Durable arm to keep from common breaks. Comes with a mechanical motor instead of electronic making for a longer lasting ice maker. Designed to outlast the original. Fixes the following problems Ice maker not making ice Ice maker won\u2019t dispense ice Noisy Siwdoy Customer Service Siwdoy is committed to providing each customer best customer service. If any question, please don't hesitate to contact us. \u2705 Ideal Replacement Ice maker is used on top freezer refrigerators and side-by-side refrigerators. Comes with a new built-in harness. Simply unplug and install the new unit. \ufffd"}, {"role": "assistant", "content": "Price is $65.57"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nNEW SealPro compatible Washing Machine Door Boot Gasket for LG Kenmore with Drain Port and - 1 YEAR WARRANTY\nSealPro Door boot replaces original front-load washer door boot part numbers and SealPro Door boot replaces original front-load washer door boot part numbers and SealPro Quality Backed By 1 Year Warranty This door boot includes a drain port; If your LG front-load washer was made before September 2007, use door boot instead, because those washers don't have a drain port Replaces part #'s Part number ATTENTION READ BEFORE PURCHASING ; PLEASE CONTACT US WITH YOUR MODEL # TO CONFIRM COMPATABILITY BEFORE PURCHASING Brand Name Seal Pro, Model Info Weight 3.5 pounds, Dimensions 16.81 x 11.46 x "}, {"role": "assistant", "content": "Price is $47.46"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHQRP AC Power Cord Compatible with Bosch 1581 1581VS 1582 Jig Saw Mains Cable Repair\nHQRP\u00ae Replacement AC Power Cord; This cord is made for double insulated tools; Length 8ft, Wire Size 18 AWG, Input 10A, 125V AC; Compatible with Original AC Power Cord; 200 days warranty! Compatible With Bosch 1289D 1290 1290D Orbital Sander, Electric Screwdriver, 1587VS 3230VS B4100 B4200 B4201 Jig Saw 1581 1581VS 1582 Brand HQRP, Connector Gender Male-to-Male, Voltage 125 Volts, Input Current 10 Amps, Plug Format Type B"}, {"role": "assistant", "content": "Price is $10.91"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nM MAKA Flat Low Profile Guitar Patch Cable 6 inch for Effects Pedals, 1/4 inch Right-Angle, Black, 3-Pack New Version\nMAKA Flat Patch Cable is designed to reduce space on your pedalboard while still provides great sound quality. The special flat outer PVC jacket and moduled plugs improve the flexibility and durability. Purest OFC copper conductors for signal and ground PVC and PE coats for insulation Crystal clear sounding which doesn't affect your original tone The new version has smaller plugs, which allows you to use the cables for close jackets easily.The new version has smaller plugs, which allows you to use the cables for close jackets easily. Brand M MAKA, Compatible Devices Musical Instrument, Color Black, Connector Gender Male-to-Male, Unit Count 1."}, {"role": "assistant", "content": "Price is $12.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHamilton Beach Permanent Gold Tone Filter, Fits Most 8 to 12-Cup Coffee Makers )\nThe Hamilton Beach\u00ae 8-12 Cup Reusable Coffee Filter fits most 8 to 12 cup coffee makers with basket-style filters. It has a handle and is dishwasher safe. Fill with your favorite ground coffee. Replaces disposable paper filters to reduce waste. FITS MOST COFFEE MAKERS \u2014 This basket-style drip coffee filter fits most 8-12 cup coffee makers with basket-style filters. The gold-tone filter's handle makes it easy to pull out of the coffee maker for refilling and cleaning. EASY TO CLEAN The reusable coffee filter is dishwasher safe or can be easily washed clean under running water. ENVIRONMENTALLY FRIENDLY \u2014 REDUCE WASTE & SAVE MONEY Use our"}, {"role": "assistant", "content": "Price is $7.49"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMagic Singalong Song Chip - Spanish 10 - 180 Songs\nPlease check to see if your Enter-Tech MagicSing Karaoke Microphone is compatible with this song chip. Compatible Models 180 Songs ( Full song list available upon request ) Dimensions 9.3 x 4.8 x 0.3 inches, Weight 0.353 ounces, Manufacturer EnterTech, Rank Musical Instruments 99379, Karaoke Portable Systems 470, Is Discontinued No, Available October 31, 2011, Power Source Corded Electric, Signal-to-Noise Ratio 78 dB, Hardware Platform Karaoke Machine, Channels 1, Recommended Uses For Product Karaoke, Brand Magic Sing, Connectivity Technology XLR, Connector Type 40 pins, Special Feature Voice Activated Recording, Compatible"}, {"role": "assistant", "content": "Price is $34.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMusiclily Pro Left Handed Imperial Inch Size Control Speed Knobs for USA Made Les Paul Style Electric Guitar, Black (Set of 4)\nIdeal for Lefty USA Les Paul guitar like Les Paul, SG, ES-335 etc. If your guitar is Epiphone style and use imperial inch size pots, it will work as well. Fits common 1/4 inch split shaft imperial size pots, fits most USA made guitar and fine-knurled shafts USA CTS/Fender/Bourns/Dimarzio standard pots If your pots are coarse-knurled shafts or import metric size, do not buy it Made of acrylic Numbers 0-10 Weight 0.774 ounces, Dimensions 3.86 x 2.48 x 0.91"}, {"role": "assistant", "content": "Price is $13.16"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTama 1st Chair Ergo-Rider Drum Throne with Backrest Black\n1st Chair Ergo-Rider Drum Throne with Backrest Black. Tama's Ergo-Rider Throne provides absolute ergonomic comfort and support. The hybrid of a round seat and a saddle style seat, it offers the maneuverability of the former, and the playing support of the latter. The front cutaway allows unimpeded thigh movement even during the most rapid double bass patterns. Both the height and angle of the backrest unit are adjustable, giving you the support you need no matter how you sit. And now there's another user-friendly feature you can fold the backrest itself onto the seat without disassembling it for easier transport. The backrest unit is also sold individually (HTB5) and"}, {"role": "assistant", "content": "Price is $399.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUHURU USB Recording Microphone Condenser Cardioid Microphone Kit with Boom Arm, Shock Mount, Pop Filter and Windscreen, for Broadcasting, Recording, YouTube\n\u266a\u266a A Professional USB Condenser Microphone \u266a\u266a This usb microphone uses the most advanced chipset. Its sampling rate is up to while the other microphone's rate only up to Therefore, this USB microphone would provide a clearer,smoother, flatter voice. \u266a\u266a Cardioid Polar Pattern \u266a\u266a Cardioid pattern design enables this usb microphone kit to cancel noise from surroundings, making a clearer and more real sound. Moreover, with help of Pop Filter in package, it would record a better and clearer voice for words with pronunciation of b, p, f. \u266a\u266a Easy to Set"}, {"role": "assistant", "content": "Price is $54.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nESP 5 String LTD TL-5 Thinline Bass, Natural, Right,\nThe LTD Thinline TL-4 and TL-5 basses are perfect for bass players looking for the best of both acoustic and electric worlds. They offer a chambered mahogany body with spruce top in Natural finish, paired to a comfortable three-piece thin U-shaped mahogany neck and roasted jatoba fingerboard using set-neck construction at 34\u201d scale. High-quality components on the TL-4 and TL-5 include a Graphtech Nubone XB nut, Grover tuners, and an active Fishman SONICORE pickup and TL-3 preamp with onboard tuner. These pro-quality basses are ready for just about any musical style including pop, jazz, R&B, reg"}, {"role": "assistant", "content": "Price is $799.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n24 Pieces Alto Tenor Saxophone Mouthpiece Cushions, Eison 0.8mm Thick Food Grade Sax Clarinet Mouthpiece Patches Pads Strong Adhesive, Black\nEison Alto Tenor Sax Mouthpiece Cushions Clarinet Mouthpiece Patches Pads Cushions 0.8mm Thick Food Grade Rubber Pack, Black These are of mouthpiece patches for alto saxophone, \u266dB tenor saxophone,\u266dE alto saxophone and clarinet. They can also be used in horns jaz and more. Easy application and stay put well. These sax mouthpiece cushions are very helpful accessory for alto/tenor saxophones beginners to lay a solid foundation and help masters to show your performance skill better. Features - Greatly reduce the vibrations on top of your"}, {"role": "assistant", "content": "Price is $11.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nNC AYUBOUSA Guitar String Trees String Retainer Guides Compatible with Strat Tele Style Electric Guitar Bass Parts Replacement Pack of 4pcs with Mounting Screws Black.\nFeature Material zinc alloy. Color Black. Base Size (L x W) Approx. 0.43 x 0.28 inch / 11 x 7mm. Total Height Approx. / 3.5mm. Screw length Approx. / 11mm. Description 1 YEAR QUALITY This 2 set of 4 guitar string tree guide retainer can retain the string perfectly and reduce string friction to save string, and more accurate tuning. Most commonly fitted on the D, G, B and high E strings. This pair are the correct match of 2 differing height trees, the taller 5mm"}, {"role": "assistant", "content": "Price is $8.98"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDryer Drum Glide Replacement Fits for Whirlpool Amana Magic Chef Replaces (2 Pack)\n\u2705 Function - The dryer drum glide supports the drum on the front side and allows the drum to move smoothly \u2705 Suitable Brands - Whirlpool,Roper,Admiral,Jenn-Air,Estate,Magic Chef,Crosley,Inglis,Modern Maid,Amana,Kenmore,May-tag,Speed Queen,Kitchen-Aid \u2705 Replaces Part Numbers - \u2705 High Quality - The component is made of high-quality materials and lasts for a long time,meet your needs \u2705 LIFETIME WARRANTY - If you have any problems or there is any damage to the product, we will offer a 100% money-back guarantee. Welcome to contact us, we will try"}, {"role": "assistant", "content": "Price is $9.29"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCustom Guitar Picks 6-pack Personalized Add Your Own Picture Text Name LOGO Image Guitar Plectrums For Guitar Bass Ukuleles\nHow to Custom 1. Clicking Customize now button. 2. Choose a background color you like. 3. Click Browse button to upload picture.you can use resize/rotate/move tool that is part of the image placement tool to make your picture fit the area. 4. You can type your text and choose the font and text color, your can use resize/rotate/move tool that is part of the text placement tool to make your text fit the area Each pick is more beautiful than the previous one, and you\u00a1\u00afre simply guaranteed to love playing your guitar while adding a personal, elegant touch.Picks make the guitar"}, {"role": "assistant", "content": "Price is $5.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nReusable Cups Stainless Steel Coffee Filters Compataible for K-Duo Keurig,K select K80, K-Elite, K-mini Plus, and 2.0 & 1.0 Brewer, Reusable Coffee Pod Metal Filter (2 Pods+ 1 Scoop)\n1.Safe to use,stainless steel mesh filter make perfect filtering,in purle lid can be recognize by the machine Models which we mention for Keurig K select K80, K-Elite, K-classic, K145, Plus K-cafe, K-Duo friendly, BPA Free and recyclable of this keurig k refillable pods 4,Save up to 80% over pods, (4-5 Cup) for 1.0 and 2.0 Brewing Systems 5,"}, {"role": "assistant", "content": "Price is $19.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTRUSTECH Ice Maker Machine for Countertop, Automatic Ice Makers Countertop Self Cleaning, 9 Cubes Ready in 6 Mins, 26 lbs in 24 Hours, Perfect for Home/Kitchen/Office, Ice Scoop&Basket, Black\nSelf-cleaning function - Ice makers countertop self cleaning, just press on/off button for 5S to start self-cleaning mode! Popular bullet-shaped ice is not easy to melt or stick 9 cubes ready in 6 minutes - Our ice maker produces 9 ice cubes within only 6-8 minutes. It can even produces up to 26.5 pounds of ice per day, having fresh ice every day Two sizes of ice available - Large or small ice with popular bullet shape is not easy to melt"}, {"role": "assistant", "content": "Price is $89.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n2-Pack Replacement for LG Refrigerator Water Filter - Compatible with LG LT500P Fridge Water Filter Cartridge\nThis is a Denali Pure Brand replacement part, NOT an OEM product. All mentions of brand names or model descriptions are made strictly to illustrate compatibility. All brand names and logos are registered trademarks of their respective owners. This product is not affiliated with any OEM brands and is not covered under any warranties offered by the original manufacturers. Any warranties for this product are offered solely by Denali Pure. Compatible Filter for LG Refrigerator, Quantity 2 Compatible Replacement for LT500P Fridge Water Filter Cartridge NSF 42 certified refrigerator water filter by IAPMO and WQA Reduces impurities & substances without restricting the flow rate of the water. For the highest quality water replace the filter"}, {"role": "assistant", "content": "Price is $22.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nmffmffm Audio Instrument Cable 20 ft, Bass AMP Cord for Electric Guitar, 1/4 Inch Guitar Cable Pro Audio, Black & Glod Braided Tweed (Right Angle to Straight)\n\ud83c\udfb8 NEW DISIGN Unlike any other guitar cables on the market,MFFMFFM guitar cable add carbon fiber shell at the TRS connectors, make the instrument cable more beautiful and better quality. \ud83c\udfb8 NOISE-FREE, HIGH-FIDELITY Mffmffm guitar cord uses copper wire high density braid + tin foil + semiconductor material triple processing shielding layer,can better reduce noise and protect sound quality. \ud83c\udfb8 ORIGINAL SOUND TRANSMISSION Instrument guitar cord with 20AWG conductor is made of oxygen-free-copper\uff08OFC\uff09"}, {"role": "assistant", "content": "Price is $23.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKVKA Set of 3pcs Chakra Frosted Quartz Crystal Singing Bowl 6-10 inch with case \uff0810''F 8''G 6''B)\nThis crystal singing bowl is made with 99.99% pure quartz crystal, used in music appreciation.Quartz crystal vibrations sound energy comes from pure quartz, crystal sound healing and chakras meditation is also base upon purity quartz energy. How To Play\uff1a The operator maintains a calm mood, divides the bowl mouth into three equal parts, taps at these three points, or taps 6 times with the method of drawing a large satellite, and rubs the part of the bowl wall close to the bowl mouth clockwise or counterclockwise. Replenish energy clockwise, release energy counterclockwise, When using multiple"}, {"role": "assistant", "content": "Price is $179.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSlotted Nut For 4 Strings Bass Guitar Flat-bottom 42mm\nOur replacement guitar nuts are designed to transfer the right frequencies more efficiently from the string to the guitar body. Acoustic guitars come alive. Electric guitars will get a brighter sound and increased harmonic content. Dimensions long ; 2/16 thick ; 4/16 high (42mm x 3mm x 6mm) Made of High quality ABS material. Color Black Flat-bottom /hollow interior string space or 34mm Quantity 1 Pcs Rank Musical Instruments 82631, Acoustic & Classical Guitar Nuts 119, Is Discontinued No, Available August 12, 2016, Color Name Black, Material Type Abs, Brand MLaval Guitar Parts, Color Black, Instrument Bass Guitar"}, {"role": "assistant", "content": "Price is $6.50"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nYamaha STAGEPAS 600I Portable PA System\nThe new STAGEPAS feature two sleek, lightweight speakers and a detachable powered mixer, along with one pair of speaker cables and a power cord, giving you a complete, extremely portable sound solution that can be set up quickly and easily in a variety of configurations and environments. By combining new high-efficiency amplifiers, newly designed speakers, and high performance DSP, the new STAGEPAS delivers a significant increase in power output ( 400W for the 400i and 680W for the 600i) as well as substantial improvements in sound quality and reliability. Complementing the boost in performance, the addition of iPod/ iPhone connectivity, SPX digital reverbs, an onboard feedback suppressor and more versatile"}, {"role": "assistant", "content": "Price is $999.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKopul Premium Performance 3000 Series XLR M to XLR F Microphone Cable - 100' (30.5 m)\nThe Kopul Premium Performance 3000 Series XLR M to XLR F Microphone Cable (100') is designed to be an extremely quiet and flexible cable that is ideal for the most demanding live sound and performance applications. The cable is engineered to be durable and to provide protection against EMI, RFI, and static noise.Premium Performance 3000 Series cables are made from 24 AWG OFC copper wire that's wrapped with PE insulation and a conductive PVC inner shield. A cotton-yarn inner layer helps reduce electrostatic and microphonic noise. 95% dual-spiral shielding makes the cable resistant to EMI and"}, {"role": "assistant", "content": "Price is $39.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMist Water Filter Replacement, Compatible withModels Kenmore 469981 & LT120F Combo Pack\nWater Filter Replaces LG Kenmore 9980, | Fits the following refrigerators Air Filter Replaces LG LT120F and Kenmore Elite CleanFlow Air Filter & Each air and water filter will last about 6 months. The water filter reduces chlorine to deliver pure clean and refreshing water, and the air filter is effective at keeping refrigerator fresh and odor free. Water filter is tested and certified by NSF International IAPMO R&T to NSF/ANSI Standard 42. Will fit and lock in all compatible refrigerators. Guaranteed. Dimensions 6 x 8 x 2 inches, Weight 1.4 Pounds, Manufacturer Mist, Country of Origin China, model number Rank"}, {"role": "assistant", "content": "Price is $37.98"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJackson JS32 Dinky DKA Electric Guitar Pavo Purple\nBody Body shape Double cutaway Body type Solid body Body material Solid wood Top wood Not applicable Body wood Basswood Body finish Gloss Orientation Right handed Neck Neck shape Dinky Neck wood Maple with graphite reinforcement Joint Bolt-on Scale length 25.5 in. Truss rod Standard Neck finish Satin Fretboard Material Rosewood Radius Compound Fret size Jumb Swift, deadly and affordable, Jackson JS Series guitars take an epic leap forward, making it easier than ever to get classic Jackson tone, looks and playability without breaking the bank Upgraded features such as arched tops, new high-output ceramic-magnet pickups, graphite-reinforced maple necks, bound fingerboards and headstocks, and black hardware deliver more for less The JS"}, {"role": "assistant", "content": "Price is $369.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nProMark Matt Strauss General Concert Persimmon Drumsticks, Wood Tip, One Pair\nThe Matthew Strauss Concert General Drumstick is the perfect implement for any percussionist looking for a premium, general use concert stick. This drumstick was designed with Matthew Strauss, renowned percussionist from the Houston Symphony, as part of a series of premium concert drumsticks to accommodate the wide range of playing situations and repertoire demands that he faces. The General model features a long taper for a rebound feel, and a long, arrow shaped tip which creates full bodied tone and greater ease in playing rolls through greater surface contact with the drumhead. The Matthew Strauss Concert General Drumstick is the perfect implement for any percussionist looking for a premium, general use concert stick. This drumstick was designed with Matthew Strauss, renowned"}, {"role": "assistant", "content": "Price is $27.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nStedman PS101\nThe Stedman Proscreen 101 uses the same unique patented metal screen as the PS100. The Proscreen 101 has an attached 13 inch flexible goose neck with adjustable clamp. This clamp allows the PS101 to be attached to any microphone stand or boom while allowing easy positioning of the screen with the flexible goose neck. Like the PS100, the Stedman Proscreen 101 can be cleaned with detergent and hot water and will outperform and outlast fabric filter designs. Includes a lifetime warranty. Made in U.S.A. Length 20'' Screen diameter 4.6'' Clamp opening diameter.5 Weight 5.8 oz. Weight 9.6 ounces, Dimensions 12.3 x 6.1 x 2 inches,"}, {"role": "assistant", "content": "Price is $44.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nClimaTek Upgraded Refrigerator/Freezer Icemaker for Whirlpool IMKIT\nThis is a brand new ClimaTek Refrigerator / Freezer Ice Maker \u25b6 This is a brand new ClimaTek Refrigerator / Freezer Ice Maker \u25b6 This ClimaTek Part Replaces Part # IMKIT \u25b6 Top Quality ClimaTek Replacement Part, Built to Last! \u25b6 This is the Base Icemaker Kit, Don't Pay for Harnesses You Don't Need! \u25b6 Works with Whirlpool and more! Dimensions 6 x 10 x 8 inches; 2.65 Pounds, model number ClimaTek Rplm for ADML # Available March 30, 2020, Manufacturer ClimaTek"}, {"role": "assistant", "content": "Price is $62.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nZAWAGIIK Refrigerator Door Handle Covers Set of 6 Kitchen Appliance Handle Covers Decor Protector for Fridge Microwave Oven Dishwasher Handles, Keep Clean from Fingerprints Food Stains\nRefrigerator Door Handle Covers Material Made of thick and skin-friendly short plush fabrics. With quality Velcro, the handle covers don't slide up or down. They just stay in the right place. Appliance Handle Protector Length and both fit for perimeter of handles Meet your different use needs. Perfect for fridge, microwave, stove, oven, dishwasher handles in shape round or flat. Keep Kitchen Appliance Handle Clean No more food stains, sauces, oils, water drips, smudges and fingerprints. Save your cleaning time! Kindly Reminder Measure the perimeter of your handle with a soft ruler before"}, {"role": "assistant", "content": "Price is $17.49"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nADT Mini Fridge 1.6 Cu.Ft Mini Refrigerator Retro Design (Vintage green)\nBrand Name ADT, Weight 31.9 pounds, Dimensions 17.52\\ D x 18.31\\ W x 19.29\\ H, Is Discontinued No, Energy Use 0.3 Kilowatt Hours, Capacity 1.6 Cubic Feet, Refrigerator Fresh Food Capacity 1.6 Cubic Feet, Installation Type Tabletop, Part 1, Form Factor Compact, Special Features Portable, Color Vintage green, Voltage 110 Volts, Manufacturer Warranty I YEAR WARRANTY, Available August 20, 2020, Brand ADT, Configuration Compact Freezerless, Special Feature Portable, Doors 1, Finish Type Matte"}, {"role": "assistant", "content": "Price is $159.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGuitar Display Bracket Wall Mounted Mandolin/Ukulele/Guitar Hanger Hook Stand Rack (4 Pcs Blcck Square Base)\nPackage include 4 pcs Hooks. Easy to assemble and install in no time, mounting screws and drywall anchors are included. Suitable for a variety of string instruments such as guitars, basses, violins, mandolins, ukeleles and so on. Have a soft sponge cover on the guitar hanger, no imprint on your guitar. Package include 4 pcs Hooks. Size Manufacturer Merryshop, Brand Merryshop, Weight 1.35 pounds, Dimensions 4.5 x 3.8 x 2 inches, Is Discontinued No, Color 4 Pcs Blcck Square Base, Material Type Iron, Size Manufacturer"}, {"role": "assistant", "content": "Price is $16.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBeaquicy Oven Bake Element - Replacement for Hot-point G-E Oven - Replaces 3358,\nHigh temperature resistant nickel stainless steel \u2705 PRODUCT DESCRIPTION The Range Oven Bake Heating Element is located at the bottom of the oven and have screw-on terminals. Used to provide heat to the oven. The element has a rated power of and a rated voltage of The dimensions from the bracket to the front of the element are 17.75 inches wide x 17 inches long,and the terminal extending approximately 2.25 inches beyond the bracket. \u2705 MATERIALS The Oven Bake Element is made from high quality materials and rigorously manufactured to ensure a long service life.The two terminals and the small holder at the top are made of metal and have a nickel-plated surface for increased resistance to high temperatures and"}, {"role": "assistant", "content": "Price is $27.77"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nVandoren CR152 Contrabass Clarinet Traditional Reeds Strength 2; Box of 5\nThe most widely played reeds in the world, with a superiority proven over the years, these reeds suit all styles of music. Traditional reeds are known for their excellent response in all registers, allowing a pianissimo attack in even highest notes. Extremely flexible, allowing the legato or staccato execution of large intervals while maintaining a richness of tone that gives body and clarity to the sound, which is a hallmark of Vandoren reeds. Traditional reeds are available for all clarinets and saxophones in various strengths. Every reed sealed in 'Flow Pack' to ensure freshness. Weight 0.01 Ounces, Dimensions 1.63 x "}, {"role": "assistant", "content": "Price is $58.59"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPaiste 2002 Sound Edge Hi-Hats 17 in. Pair\n2002 Sound Edge Hi-Hats 17 in. Pair The bright, clear sound of the Paiste 2002 Sound Edge Hi-Hats makes them particularly well-suited for high-energy performances. Their precise, splashy sound projects loudly so they are never lost in the mix. Formed from CuSn8 bronze, these hi-hats are bright and energetic for a live performance but also have the precision needed for studio recording. A classic cymbal, the Sound Edge Hi-Hats features a unique rippled bottom which eliminates airlock for a sharp sound. Heavier models are also available for increased volume. Enjoy focused, splashy sounds when you play the classic Paiste 2002 Sound Edge Hi-H"}, {"role": "assistant", "content": "Price is $528.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUpgraded Dryer Thermostat Kit DIY Tips Below by PartsBroz - Compatible Maytag Dryer Parts - Replaces - Includes Thermostat, Thermal Fuse\n\ud83d\udca1 High Limit Kit - An equivalent for 3344, ET403, ET405, \ud83d\udd27 DIY Tips Included - Not sure how to replace the part? Helpful information can be found on the page below. Scroll down to get more repair tips. Acquire valuable skills during the DIY repair project. \ud83d\udca1 Compatibility With Major Brands - Dryer thermal fuse is compatible with Maytag, Admiral, Amana, Crosley, Hoover, Jenn-Air, Magic Chef, Norge. Fuse kit fits hundreds of models. \ud83d\udca1 Helps With The Following Issues - LA1053 Thermal Fuse Kit will help if your appliance doesn't start,"}, {"role": "assistant", "content": "Price is $8.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFLOYD ROSE TREMOLO CLAW & SCREWS\nWith the invention of the world\u2019s first locking vibrato system in 1977, Floyd D. Rose completely revolutionised the electric guitar, and with it a whole new generation of players. 40 years later Floyd Rose offers a vast array of replacement vibrato systems, upgrades and spares, and are used and trusted by some of the most influential and famous guitar players on the planet. Genuine Floyd Rose replacement tremolo spring claw and screws (set of 2 screws, 1 claw) Genuine Floyd Rose replacement tremolo spring claw and screws set of 2 screws, 1 claw Made in Germany Weight 0.704 ounces, Dimensions 7.87 x 4.72 x 2.36 inches,"}, {"role": "assistant", "content": "Price is $11.38"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGE Genuine OEM Evaporator Fan Motor for GE Refrigerators\nProduct Description This high quality Genuine OEM GE Appliances Evaporator Fan Motor circulates air through the fresh food compartment for efficient cooling. The Evaporator Fan Motor has electrical specifications of and 4.2W. Please be aware that it is recommended to disconnect the appliance from all utilities prior to installation of the Evaporator Fan Motor. From the Manufacturer This is a genuine replacement part. The model number and name for the following item is General Electric Evaporator Motor The GE Appliances Evaporator Fan Motor is a genuine OEM (Original Equipment Manufacturer) part designed and engineered to exact specifications Replacement GE Appliances Refrigerator Evaporator Fan Motor circulates air through the fresh food compartment for efficient cooling GE Appliances Refrigerator Evaporator Fan"}, {"role": "assistant", "content": "Price is $104.85"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDunlop MXR M116 Fullbore Metal Distortion Guitar Pedal with AC Power Supply, 2 Patch Cable and 6 Guitar Picks\nUltimate riff power is yours with the Fullbore Metal Distortion pedal from MXR. This compact but powerful device is all you need to unleash the most devastating contemporary metal guitar tones ever heard. The Fullbore Metal Distortion turbo-charges your guitar signal with lethal amounts of ultra high gain. This is combined with a built-in Noise Gate to knock out the noise associated with extreme gain levels while also adding definition and tightness to syncopated metal riffs. Plug into the MXR Fullbore Metal high-gain distortion pedal and experience the full force of what your guitar can do for you! Equipped with all the tools"}, {"role": "assistant", "content": "Price is $119.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFogWorx Fog Juice - 1 Quart of Premium Odorless Fog Fluid (32 oz) - Medium Density, High Output, Long Lasting Fog Machine Fluid for 400 Watt to 1500 Watt Machines\nOne quart of premium water based fog machine fluid - remains clean, dry and ODORLESS!!! Medium density formulation delivers good hang time and excellent dispersion FogWorx Fog Juice is designed for use with any water based fog machine - Optimized for machines with as little as 400 watts Weight 2.25 pounds, Dimensions 7.48 x 5.08 x 2.28 inches, model number Rank Musical Instruments 269, Stage Fog Machines & Accessories 3, Is Discontinued No, Available June 2, 2017, Size Quart"}, {"role": "assistant", "content": "Price is $18.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nZildjian 8 inch K Custom Dark Splash Cymbal\nK Custom Dark Splashes deliver a dark splash sound that is warm and highly responsive from their very thin weight. The extra K Custom hammering gives these splashes a comparatively drier effect than splashes within the K Zildjian Series. K Custom Dark cymbals are a great choice for drummers who lean towards a mixed blend of darker tonal colors that project with more character and nuance. 8 Cast Bronze Thin Splash Cymbal with Traditional Finish Weight 0.37 Pounds, Dimensions 8 x 7.95 x 0.85 inches, Domestic Shipping Currently, item can be shipped only within the U.S. and to APO/FPO addresses. For APO/FPO shipments, please"}, {"role": "assistant", "content": "Price is $164.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMFL. DJ Light Bar, Stage Light Bar Cob Led RGBW Quad Colors DMX Pixel Control Metal Body for DJ Stage Lighting Club Party\n4 MODES AVAILABLE FOR PROFESSIONAL USES This Light Bar can be operated via 4 modes to suit all professional needs, which are DMX 512, sound active, auto and master/slave. VARIOUS EFFECTS FOR DIFFERENT OCCASIONS Compatible with DMX controller, each LED of this Black Light Bar can be controlled individually, allowing you to mix and match & create different lighting effects for various occasions. PERFECT FOR MULTIPLE SETTINGS Equipped with 9 pieces of 8 watts 4 in 1 COB LED, this LED Light Bar provides uniform illumination, which creates spectacular lighting for stages, clubs, parties"}, {"role": "assistant", "content": "Price is $117.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBetty Crocker Portable Dual Electric Burner, Black\nWhen the top of the stove is full or you're looking to work somewhere other than the kitchen, this Betty Crocker portable double burner will come in handy. Cook, heat or reheat on either the large burner or the small burner. Take advantage of the independent temperature controls. The low-profile design makes it easy to store when not in use. PORTABLE COOKTOP This BETTY CROCKER electric burner is great for small kitchens, apartments and living spaces with limited space or no kitchen access whatsoever. This compact cooktop features 2 electric burners. TWO BURNER TOP Our countertop cooktop comes with 2 electric burners; one 1,000 watt with 4 burner coils and one 500 watt heating"}, {"role": "assistant", "content": "Price is $25.57"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPerformance Plus Impact Activated Purple LED Light-Up Clear Acrylic Drumsticks With Free Drum Key\nFIRESTIX are light-up drumsticks that bring excitement to any drummer's performance. FIRESTIX aren't just glow-in-the-dark drumsticks; they really light up! Batteries in the base of each stick power bright lights each time you strike a drum or cymbal. The light triggers in FIRESTIX are extremely sensitive and the lights are super bright. FIRESTIX are made of durable, heat-resistant polymer and come in pairs with batteries. Add some spark to your drum performance with FIRESTIX. Bonus includes free lug nut drum key with each pair Fires tix light-up drumsticks Purple by Performance Plus with free drum key! Pair of light-up drumsticks made of heavy duty"}, {"role": "assistant", "content": "Price is $21.07"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nE Guitar Nut, 2 Pieces 42mm Slotted Strings Nut Replacement Part for 6 Strings Electric Guitar\nSpecification Condition 100% brand new Material Faux cattle bone color white Quantity 2 pieces Suitable for electric guitar Size (L * W) Approx. 42 * 3.5mm / 1.6 * 0.1 inches Two side height approx. 3.5 mm / 0.1 inches, 4.5 mm / 0.2 inches String clearance Approx. 6.5 mm / 0.3 inches Approximate weight. 4g Packing List 1 x pack with only 2 pieces of guitar nuts * The other terms listed in our pictures are not included. Faux Cattle Bone Material Adopting premium faux cattle bone"}, {"role": "assistant", "content": "Price is $6.17"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLuna Artistic Great Wave Soprano Uke w/Strings,Tuner & PC\nLuna Great Wave Soprano Ukulele Includes Extra set of Aquila Strings Tuner Gigbag TMS Polishing Cloth The Great Wave off Kanagawa also known as The Great Wave is a woodblock print by the Japanese artist Hokusai. Copies of the print are in many collections, including the Metropolitan Museum of Art in New York City and The British Museum in London. Featured on the front of Luna's 21 Great Wave Soprano and 23 Great Wave Concert, this masterpiece can now be in your own personal ukulele collection! Specifications MODEL UKE GWS Great Wave art by Hokusai Body 21 Soprano Top Select Mahogany Back/Sides Trans Blue"}, {"role": "assistant", "content": "Price is $145.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nNordyne Pressure Switch\nThis is a genuine replacement part. The model number and name for the following item is Nordyne Pressure Switch This is a Genuine OEM replacement part The Package Length of the product is 1 inches The Package Width of the product is 1 inches The Package Height of the product is 1 inches Brand Nordyne, Switch Type Pressure Switch, Dimensions LxWxH 4 x 3.8 x 1.7 inches, International Protection Rating IP00, Connectivity Protocol X-10, Unit Count 1.0 Count, s 1, Brand Name Nordyne, Model Info Weight 0.01 ounces, Dimensions 4 x 3.8 x 1.7 inches, model number Part Rank Tools & Home Improvement Range Accessories 2124,"}, {"role": "assistant", "content": "Price is $32.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDiMarzio DP216 Mo' Joe Bridge Pickup Black F-Spaced\nMade in response to Joe Satriani's request for a hotter pickup, with power, clarity, and dynamics. Enhanced harmonics and output make a perfect match with a PAF Joe, in the neck. Joe Satriani asked us for a hotter and bigger version of the Fred for his new Ibanez guitar. The new Mo' Joe has more power than the Fred, but it doesn't sacrifice the clarity, dynamics or the unique guitar. The new Mo' Joe has more power than the Fred, but it doesn't sacrifice the clarity, dynamic or the unique harmonics that made the Fred famous. The Mo' Joe in the bridge position is a perfect match for the PAF Joe in the neck position"}, {"role": "assistant", "content": "Price is $99.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSeymour Duncan Hot P-90 Soapbar Neck Pickup, Cream Cover\nThe Seymour Duncan SP90-2 is a high output P-90 soapbar pickup. Excellent for heavy blues, classic rock, hard rock, punk and metal. Extra coil windings combined with dual (small) ceramic magnets produce higher output, increased sustain, and more sensitivity to subtle string movements. Most noticeable, when compared to the is the pronounced upper mid-range detail that makes this pickup really cut through the mix. Comes with single-conductor hookup cable. Slightly shorter.585 height profile. Available for both neck and bridge positions in a balanced set. Also popular, is an SP90-2 Hot in the bridge position with an SP90-1 Vintage in the neck for tonal versatility. For balanced and"}, {"role": "assistant", "content": "Price is $109.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTC-Helicon VoiceTone H1\nWith TC-Helicon's VoiceTone H1, vocalists can have fun with stompboxes, just as guitarists have been doing all along. VoiceTone H1 adds one or two voices of rich, realistic harmony to your voice. You can use the key selector to dial in harmonies to fit a song, while the cool guitar-sensing feature keeps your harmonies in tune. Although VoiceTone H1 fits the form factor, to call it a stompbox would be misleading. As a member of TC Helicon's VoiceTone lineup, VoiceTone H1 is strictly studio grade - complete with a clean, quiet mic preamp and studio-quality A/D conversion. So give your backup singers the night off"}, {"role": "assistant", "content": "Price is $149.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHouseShape Indoor Dryer Vent Kit For Electric Dryer Purify Air - Save Energy - Laundry Room Wall Decor (Double Filters)\nNot only good looking, but also good function. we do have instruction and Please watch the installation video. No drilling solution you can put the dryer vent box on the floor if you don't want to drill any hole on the wall. >> Perfect Venting Efficiency Upper and lower two sides large fiter area double ensure the function, better venting effeciency; The dryer vent box is tightly sealed, no leakage. >> Perfect Filtering Effect Originally cabin air filter materal for car air condition system, capture lint,dust and small particals, PM2.5 standard, better filtering effect; heat and moisture can get through the filters, but stop the lint,dust"}, {"role": "assistant", "content": "Price is $49.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCasematix Digital Stereo Interface Case Compatible with Tascam Portastudio Pocketstudio Dr 680, Dp 03Sd, Hd p2, Dr Dp 03, Dp 008ex, Dp 006 and More, Includes Case Only\nCASEMATIX Studio Case Multi-Track Recorder Case with Dense Internal Customizable Foam - Built TOUGHThis hard shell case's exterior is made of a dense composite plastic for superior external protection against blunt forces, drops, dings and other unforeseen mishaps that can befall your high value possessions. Interior protection consists of a tri-layer arrangement of two convoluted egg-crate foam layers measuring 1.75 each, and a dense diced foam layer measuring 1.25 thick. With the combination of a highly durable"}, {"role": "assistant", "content": "Price is $44.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nYinfente Unfinished Electric Guitar Neck Replacement 24 Fret 25.5 Inch Maple wood Fretboard (rosewood-fretboard)\nYinfente Brand electric guitar neck. All solid wood made. Many years guitar master make. With High quality wood material. This guitar neck is For Many style guitar neck or your own style guitar neck replacement. You can set up it on your guitar body. New Yinfente 24 Fret Electric Guitar Neck 42.5mm Nut Width, 56mm Heel Width 24 fret. 25.5 inch, Jackson headstock, Maple wood Neck, Rosewood Fretboard Shark Tooth Inlay Floyd Rose Locking Nut, Truss Rod Installed At Headstock 9-10mm Tuner Peg Hole Diameter, 26"}, {"role": "assistant", "content": "Price is $56.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUnique Replacement Guitar Saddle Parts, Guitar Saddle, Beautiful Design Durable Rose Wood for Guitar Guitar Bridge\nFeature A great and durable rosewood guitar bridge. Specially designed for folk guitars. Sound vibrations are better transmitted to the guitar when playing. Beautiful design makes your guitar unique. Normal sized string nail hole and saddle groove, suitable for the replacement and installation of most folk guitars. Spec Condition Brand NewMaterial Rose WoodColor Wooden ColorDistance from the 1st hole center to 6th hole center Approx. 54mm/ of the groove (L x W) Approx. 71 * 3mm/ 2.8 * 0.1in Size Approx. 16.4 * 4cm / 6.4 * Approx. 26g Package List 1"}, {"role": "assistant", "content": "Price is $5.46"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJangleBox The Byrds 50th Anniversary Compressor\nTo honor the 50th Anniversary of The Byrds' debut 1965 albums, Mr. Tambourine Man and Turn! Turn! Turn! as well as Byrds' founder and long-time JangleBox endorser Roger McGuinn Janglebox created this distinctive limited edition model. This is the award-winning, flagship JangleBox compressor with a beautiful gold powder coating and special graphic appointments. What is it about the 1965 compressed jangle of the Beatles, Byrds, and so many others that continues to captivate guitar players everywhere? It seems as if every band, regardless of musical genre, employs that sound for at least a few tunes in their repertoire. Who doesn't love jam"}, {"role": "assistant", "content": "Price is $230.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nErmik Portable Guitar Amp 20W Electric Guitar Amplifier Built in Speaker Headphone Jack Input and Aux Jack Drive Button 4 Knobs Gain Bass Treble and Volume - Black\n\u266a 20W AMP The Ermik 20 Watt Electric Guitar Amplifier is equipped with a power plug and operates on 110V DC. The amplifier has a key power switch and power indicator light, with a built-in speaker. The panel design is simple and intuitive, and the operation is simple \u266a INTEGRATED CONTROL SYSTEM The amplifier has four control knobs GAIN, BASS, TREBLE, and VOLUME. The GAIN knob increases the volume and makes the sound more transparent. You can play different styles of music by experimenting with various controls \u266a MULTIPLE SOUND EFFECTS The Drive"}, {"role": "assistant", "content": "Price is $48.89"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBlueStars Unbreakable Control Knob with Metal Ring Replacement Part Exact Fit for General Electric Dryers and Washers - Replaces - Pack of 2\n\u26a0\ufe0f IMPORTANT NOTE This knob is installed onto the D-shaped shaft of the control mechanism, 2 inches in diameter and 1-1/4 inch in depth. Please check the model number carefully before ordering. If you are unsure about the compatibility, you can send us your dryer/washer model number, we will help you confirm if it fits or not. \u2705 \ud835\udfcf\ud835\udfce\ud835\udfce% \ud835\udc0b\ud835\udc08\ud835\udc05\ud835\udc04\ud835\udc13\ud835\udc08\ud835\udc0c\ud835\udc04 \ud835\udc16\ud835\udc00\ud835\udc11\ud835\udc11\ud835\udc00\ufffd"}, {"role": "assistant", "content": "Price is $11.97"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSaramonic Lavmicro 2M Dual Lavalier Mics\nThe Saramonic LavMicro 2M is a set of two high-quality clip-on wired lavalier microphones that share one cable and connect to a single 1/8\u201c mic input. This enables you to put wired lavalier mics on two people and plug into a single mic input on a camera or an audio recorder. The microphones deliver broadcast-quality sound to DSLRs, mirrorless, cinema, and video cameras, as well as audio recorders, smartphones, tablets, and other devices. It features a (7m) cable, which gives you plenty of length to position subjects in front of a camera, around a table for a podcast recording, etc. 2 high-quality wired l"}, {"role": "assistant", "content": "Price is $47.24"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKala KA-STG, Solid Spruce Top Gloss Tenor Ukulele Bundle with Gig Bag, Tuner, DVD, and Austin Bazaar Polishing Cloth\nKala Ukulele, known for high-quality instruments, is the most recognized and sought after ukulele brand in the world. Kala ukuleles are the instrument of choice for schools - more people learn to play on a Kala than any other ukulele brand Adding value to your purchase, Austin Bazaar bundles your instrument with quality accessories, saving you time and money. A premium Gearlux gig bag is included so you can keep your instrument safe when you're on the go. The included clip-on tuner is easy to use and delivers reliable performance. Our exclusive Austin Bazaar instructional DVD provides the guidance you need"}, {"role": "assistant", "content": "Price is $223.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nConrad Gotz ZK306 Violin\nOriginal CONRAD G\u00d6TZ STRADIVARI-TYPE Chinrest for Violin (4/4 Violin Size). Model ZK306. Violin Chinrest Wood Ebony. Responsibly sourced wood // Certified Wood Origin. Best fresh and hand cut Portuguese cork padding. Quality Goetz Screws, closed style. Height of chinrest 0.94 inch Depth of chinrest 2.44 inch (6.2 cm). Width of chinrest 4.96 inch (12.6 cm). Please note Due to natural characteristics of product the dimensions of this chinrest are subject to minor variations. Violin Chinrest STRADIVARI-TYPE (4/4 Violin Size), Ebony Responsibly sourced Wood // Certified Wood Origin"}, {"role": "assistant", "content": "Price is $27.53"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n3-Pack Replacement for LG Refrigerator Water Filter - Compatible with LG LT500P Fridge Water Filter Cartridge\nThis is a Denali Pure Brand replacement part, NOT an OEM product. All mentions of brand names or model descriptions are made strictly to illustrate compatibility. All brand names and logos are registered trademarks of their respective owners. This product is not affiliated with any OEM brands and is not covered under any warranties offered by the original manufacturers. Any warranties for this product are offered solely by Denali Pure. Compatible Filter for LG Refrigerator, Quantity 3 Compatible Replacement for LT500P Fridge Water Filter Cartridge NSF 42 certified refrigerator water filter by IAPMO and WQA Reduces impurities & substances without restricting the flow rate of the water. For the highest quality water replace the filter"}, {"role": "assistant", "content": "Price is $30.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBlue Spark Shock Mount with Pop Filter, Windscreen and Shockmount to Reduce Vibration Noise Matching Mic Boom Arm for Blue Spark SL Microphone by YOUSHARES\nAre you still bothered by the obnoxious noise, shock and vibrations, like floor tapping, desk bumping, putting down a glass of liquor, adjusting the boom arm during recording, etc.? You definitely need a Blue Spark Mic Shock Mount Choose YOUSHRES\u2019s shock mount, take your recording and streaming to the Next Level. Our shock mount are designed for Blue Spark to effectively isolate the microphone from the noise and vibration. This Blue Spark shock comes with a Foam insert, which is used to hold and protect the microphone. Improved Sound Quality It reduces rumble noise in your recordings dramatically. Improve recording quality, reduce post-production"}, {"role": "assistant", "content": "Price is $15.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\ntenlamp USB Audio Interface with Mixer and Sound Board, PK KING Condenser Microphone, Studio All-in-one Podcast Equipment Bundle for Phone & PC Live Streaming Podcast Pecording Gaming\nG10 offers a one-stop solution that allows for the recording and mixing of sound sources without complicated settings, provides all audio-related operation and workflow needed for live-streaming, online podcasts, and other applications. Allows you record and mix mic inputs, change your voice, control the volume of all your audio sources in real time, trigger internal interesting sounds and music via the pads, and input external audio from your phone or PC. Designed to help streamer manage their audio mixing during their streaming sessions in real time, making live streaming easier and simpler. G10 MIXER offers a one-stop solution that allows for the recording"}, {"role": "assistant", "content": "Price is $329.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nEMG MMCS Music Man Active Bass Pickup, Black\nThe MMCS is a direct replacement pickup for the Music Man Bass. Music Man\u2019s introduction of the large profile pickup changed bass playing forever. This dual-coil pickup has wide bobbins combined with a large coil surface area that gives the MMCS a most amazing bass tone. Utilizing EMG\u2019s popular CS (ceramic and steel) design the MMCS is a great mixture of design, with ceramic magnets for a transparent high end with steel added to increase the inductance for a powerful and warm low-end. It\u2019s easy to get great clean tone, but it can also warm up for a great ballad. If you are looking for a bass pickup with a thunderous low-end, this is it. The MM-CS"}, {"role": "assistant", "content": "Price is $109.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAccutronics Reverb Tank\nDesigned for applications in which the overall sound quality is important and a compact package is required. Small in size, this three spring reverb approaches the rich textural quality of larger reverb units. Replaces Solid, sturdy construction Type Short (3 Spring) tank Decay medium decay Input 310 \u03a9 Output 2,575 \u03a9 Connectors Input insulated/output grounded Locking No lock Mounting Vertical/connectors up New production Accutronics tank. Questions about reverb tanks? See our tech articles for more information. Note Rubber grommets are not included with this tank. If you would like to purchase the grommets separately please see Replaces Solid, sturdy construction Type Short (3 Spring) tank Decay medium decay Input 310 Ω Weight"}, {"role": "assistant", "content": "Price is $31.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nEliminator LP 12 Hex 12X5W RGBWA+UV LED Par Light\nLightweight LED Par powered by twelve 5W hex LEDs. beam angle. Includes scissor yoke. Designed for portable use or permanent installation. Leds 12 x 5-watt hex LEDs Beam angle Ultra Violet Wavelength Dmx channels 4 or 8 selectable Auto, sound Active and master/Slave modes 0-100% Dimming and variable strobe 4 push button menu with LED display Scissor yoke included 3-Pin DMX In/Out Iec in/out connections to daisy chain power Weight 3 pounds, Dimensions 14 x 12 x 5 inches, model number LP 12 Hex, Rank Musical Instruments 21626, Stage Lights "}, {"role": "assistant", "content": "Price is $149.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nStove Burner Covers, Non Stick Reusable Gas Stove Top Protectors - 0.4mm Double Thickness Reusable Stovetop Range Protectors Mat - Washable Keep Stove Clean Stove Guard for Kitchen/Cooking\nDust-proof and avoid spillage The gas stove cover has high-quality high-temperature resistance and does not melt, deform, or generate any odor during frequent cooking. The gas range cover is the perfect combination for your routine cooking. You just need to make sure the gas stove top covers fit your Samsung gas stove. You can install it quickly. Easy to cut stove gas range cover Our oven gap cover has an anti-static function, so the dust that adheres to it can be easily scrubbed away. It is also very stable, so it is"}, {"role": "assistant", "content": "Price is $17.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHigh Quality Factory 5PCS Heavy Duty Burner Knob Replace for Compatible with General Electric Stove Range Replaces\nReplace Part Number Fitment Fit for General Electric Stove Range. Fits models Possible Repair Solution For Will Not Start Will not shut off Timer will not advance. Note This Heavy Duty Burner Knob is not original parts, the mention of brand names and any related model designation above is only for purposes of demonstrating compatibility. Fitment Fit for General Electric Stove Range. D shaped shaft knobs. Replacement for Note This item is a replacement part. Please make sure the images are the same with what you want. If not, please do not purchase it even your model is in the described list! Made of high quality materials, and easy to install. Every product has quality inspection before leaving"}, {"role": "assistant", "content": "Price is $32.90"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUpgrade Washer Drain Pump Motor (OEM) by Beaquicy - Replace B35-3a for SAMSUNG Washer Years Warranty\n\ud835\udc76\ud835\udc6c\ud835\udc74 \ud835\udc7e\ud835\udc68\ud835\udc7a\ud835\udc6f\ud835\udc6c\ud835\udc79 \ud835\udc77\ud835\udc7c\ud835\udc74\ud835\udc77 \ud835\udc74\ud835\udc76\ud835\udc7b\ud835\udc76\ud835\udc79 The OEM Washer Drain Pump is used to remove water from the washer in the drain part of the cycle. It has a power of 120V, 60Hz, 80W. The OEM Washer Drain Pump is composed of a motor, a pump body, an impeller, and a fan blade. \u27a4Samsung Drain Pump can solve the FOLLOWING washing machine PROBLEMS Washer"}, {"role": "assistant", "content": "Price is $23.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nRemo Medium Fingerdrum, Sunburst Design\nThis small, colorful drum is the ultimate in personal percussion from Remo - it goes anywhere and is played with just a tap of a finger. Made of the same quality materials that are used on Remo's professional percussion instruments Acousticon\u0099 shell (manufactured from recycled hardwood fibers and unaffected by climatic changes) and synthetic FiberSkyn 3\u00ae head. (Remember, since the drumhead is not tunable each instrument will have a slightly different pitch). 5 diameter x 3 high pretuned fingerdrum. The Acousticon shell features the Sunburst design finish. Weight 6.4 ounces, Dimensions 4 x 6 x 4 inches, Rank Musical Instruments Bodhrans & Frame Drums 404"}, {"role": "assistant", "content": "Price is $33.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGE Range/Stove/Oven Thermostat Knob, Black\nProduct Description The high quality GE Appliances Control Knob ) allows for control of the oven temperature. The Control Knob is approximately 2.25 inches in diameter and compatible with Kenmore gas ranges. Please be aware that it is recommended to use saftey equipment and to disconnect the appliance from all utilities prior to any service or repair. Please refer to your owners manual to confirm part numbers and for instructions as some repairs require a trained service professional to complete. From the Manufacturer This is a Genuine Replacement Part,The Model Number and Name for The Following Item General Electric Range/stove/oven Thermostat Knob The GE Appliances Control Knob is a genuine OEM (Original Equipment Manufacturer) part designed and engineered to exact specifications GE Appliances Control"}, {"role": "assistant", "content": "Price is $22.05"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSennheiser ew 100 ENG G4 Wireless Microphone Combo System A1 (470 to 516 MHz) with SKB iSeries Waterproof System Case and 4-Hour Rapid Charger (4 AA Rechargeable Batteries)\nThe Sennheiser ew 100 ENG G4 Wireless Microphone Combo System is the latest addition to Sennheiser's evolution family of wireless microphones and it is fully compatible with all previous series. This package includes the EK 100 G4 camera-mount receiver, SK 100 G4 bodypack transmitter with ME 2-II lavalier, and the SKP 100 G4 plug-on transmitter. Accessories include a CA 2 camera mount, 1/8 to 1/8 cable, and a 1/8 to X"}, {"role": "assistant", "content": "Price is $849.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSeismic Audio Speakers Dual XLR Female Connectors, Stainless Steel Wall Plate\nSeismic Audio\u2019s Dual XLR female stainless steel wall plate is sturdy and robust, made of stainless steel which gives it a classic yet modern look. The wall plates have dual XLR connectors, excellent for permanent cable installation. These audio connectors are a must have for all audio or video technicians. It fits over the standard electrical box. High quality XLR female connectors make these wall plates worry free! These XLR Wall Plates are durable and have a professional look. The XLR female wall plate connection is screwed on, making it easily serviceable. The dimensions of the wall plate are 4 \u00bd X 2 \u00be\u201d and mounting screws are included! MODEL CONTENTS Dual XLR Female Stainless Steel Wall Plate"}, {"role": "assistant", "content": "Price is $15.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWhirlpool W62780 Washer Cabinet Clip Genuine Original Equipment Manufacturer (OEM) Part\nGenuine Original Equipment Manufacturer (OEM) parts! This cabinet clip (part number is for washers. Cabinet clip locks the washer top panel to the washer side panel. Unplug the washer and shut off the water supply before installing this part. Wear work gloves to protect your hands. For Whirlpool, Kenmore, Kitchenaid, Roper, Maytag, Estate, Kenmore Elite, Inglis, Crosley, Amana, Kirkland, Admiral, & Magic Chef. This part is compatible with models including; This is a manufacturer substitution. Part may differ in appearance but is a functional equivalent to prior parts including; 62780 Genuine Original Equipment Manufacturer (OEM) part"}, {"role": "assistant", "content": "Price is $6.92"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGENUINE Whirlpool Shelf for Refrigerator\nProduct Description This is a genuine replacement part. The model number and name for the following item is Whirlpool Shelf for Refrigerator. From the Manufacturer Whirlpool Shelf for Refrigerator. Works with the following models Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Genuine Whirlpool Replacement Part. Works with the following models Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Whirlpool Genuine Whirlpool Replacement Part Manufacturer Whirlpool, Part Weight 1 Pounds, Dimensions 17 x 6 x 4 inches, model number Is Discontinued No, Quantity 1,"}, {"role": "assistant", "content": "Price is $19.31"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBuckle-Down Guitar Strap - GREEN LANTERN/Logo Collage Weathered Greens - 2 Wide - 29-54 Length\nWhen you hit the stage, you definitely want to be rockin' with a Buckle-Down guitar strap. Proudly hand-crafted in America, Buckle-Down's premium guitar straps are hand-built with hearty, durable materials and display your favorite characters or brands with the highest-quality printing in the industry. The colors pop so hard that people will notice your strap from outer space! Great for everyone from beginners to advanced players, this strap will adjust to fit children and adults. This product is Officially Licensed by DC Comics. 100% Polyester Made in the USA and Imported Proudly hand-crafted in America, Buckle-Down's premium"}, {"role": "assistant", "content": "Price is $21.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSHEHDS LED Par Lights COB 200W Linear Zoom Spotlights Wash Lights Warm & Cool Stage Lights Barn Door DMX512 Sound Activated DJ Lights for Christmas Church Wedding Theater\nSuper Bright Cool White and Warm White Effect The high-brightness large chip light beads for this party light can evenly emit the soft light, which shows the true natural colors of scenery and cast. Can generate a uniformly bright and saturated cool white and warm white color (Warm White Cool White by a 200W LED Stage Light. With Barn Door for Adjusting the Light-emitting Angle The COB par light includs adjustable barn doors, which block excess light from the stage and unwanted areas, controlling superfluous spill light from the stage or other architectural projection elements, the angle can be adjusted to obtain the"}, {"role": "assistant", "content": "Price is $258.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSilvertone 6 String Solid-Body Electric Guitar, Right, Silverburst, standard\nProduct Description Silvertone Classic SVB Electric Guitar, Silverburst From the Manufacturer Presenting the by Silvertone Guitars View larger Key Features Single Cutaway Mahogany body Single Cutaway Mahogany body Mahogany 'C shape' bolt on neck with dual action truss rod Mahogany 'C shape' bolt on neck with dual action truss rod 1 11/16 Nut width 1 11/16 Nut width Rosewood fingerboard with 12 radius Rosewood fingerboard with 12 radius Pearl dot inlay Pearl dot inlay 21 Nickel Silver frets 21 Nickel Silver frets 25 Scale 25 Scale Chrome hardware Chrome hardware Chrome vintage style tuners Chrome vintage"}, {"role": "assistant", "content": "Price is $399.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nNew - Range Oven Bake Element Compatible with Maytag Jenn Air\nNew - Range Oven Bake Element Compatible with Maytag Jenn Air Product Description Brand New - Unused Parts Top Quality, Generic Aftermarket Part - 30 Day Money Back Guarantee Includes (1) bake element as pictured Item Specifications Dimensions 20 1/2 wide x 16 3/4 from bracket to back Terminals push in Space between terminals 1 1/4 Fits many Whirlpool, Kenmore, Maytag, KitchenAid ovens & ranges Replaces part numbers New - Range Oven Bake Element Compatible with Maytag Jenn Air Brand New - Unused Parts Includes (1) bake element as pictured Dimensions 20 1/2 wide x 16 3/4 from bracket to back Replaces part numbers Manufacturer"}, {"role": "assistant", "content": "Price is $68.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHagstrom 6 String Solid-Body Electric Guitar, Right (C-51)\nMade for the Hagstrom super Swede, Swede, Ultra Swede electric guitars, This hard-shell case offers rugged and striking tweed-like covering. Hagstrom touches include gold highlights Plus a padded, plush Interior. Fits all versions of the Hagstrom Swede electric guitar. Durable vintage tan Tolex exterior with a Hagstrom logo gracefully emblazoned Reinforced seams with heavy brown stitching along with a tasteful leatherette stitched sides A rigid arched top with a form-fitting design Heavy-duty Gold Plated latches, ergonomically comfortable soft handle Deep plush protective lining to reduce interior movement Fits most super Swede, Swede, Viking and H-Series hollow body models Weight 7"}, {"role": "assistant", "content": "Price is $219.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBehringer HA-20R 20 Watt Guitar Amplifier with 2 Independent Channels, VTC Tube Modeling, Reverb and Original Bugera 8 Speaker\nPowerful solid-state guitar amplifier, ideal for practice, small gigs and home recording 2 full-featured channels offering everything you need from sparkling cleans to super-fat high-gain overdrive Revolutionary VTC (Virtual Tube Circuit) technology, reproduces real tube-like tone, touch and feel Powerful 3-band EQ with bass, middle and treble provides unbridled tone shaping for dialing in any sound you need Clean channel with independent level control ranges from pristine sparkle to fat warmth, perfect for recapturing vintage tones, modern cleans or use as a pedal platform solution Weight 14.25 pounds, Dimensions 8.27"}, {"role": "assistant", "content": "Price is $99.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDavison Guitars Left Handed Electric Bass Guitar, Black - Full Size Beginner Kit with Gig Bag and Accessories\nLearning to play rhythm will be a breeze with Davison's gorgeous, high-quality, beautifully designed electric bass guitar. Crafted for superior performance and quality, this is an excellent choice for bass players at all levels. From students and beginners to intermediates and advanced players, it provides all the necessary features and incredible sound. The Davison electric bass guitar is a 45 full-size, electric bass, and it features a solid body with a stunning high gloss finish. It is designed with a maple neck, a finely finished maple fretboard, a chrome bridge, and an adjustable truss rod. It has nickel frets and diecast turners, along with dual P-style"}, {"role": "assistant", "content": "Price is $129.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nStrymon Volante Magnetic Echo Machine\nSOUNDS FROM THE EXPANSE. Create instant retrofuture atmosphere with evocative vintage delay tones. Activate your imagination with evolving ambient echoes and warm, organic feedback with just the right amount of grit. Sculpt your soundscape in real time as Volante becomes an extension and expansion of your musical instrument. Infuse your pedalboard with stunning vintage vibes that resonate and inspire. - Multi-head magnetic media delay machine providing four playback heads with individual feedback, panning, and level controls - Processor-intense algorithms deliver meticulously nuanced recreations of vintage magnetic echo systems (drum echo, tape echo, studio reel-to-- reel echo) - Dedicated control over echo machine tone and media Low Cut, Mechanics, Wear - Input Record Level for clean reproduction to warm,"}, {"role": "assistant", "content": "Price is $429.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSOLOROCK 24 2.7 cb.ft. 26 lbs High Capacity Ventless Washer Dryer Combo White\nExtensively upgraded model, increased washing and drying capacity by 70% and 100% respectively with a bigger drum and new features! 12 Kg or 26 lbs 3.1 cb.ft. (Canadian Standard) or 2.7 cb. ft. (US Standard) 24 Ventless Washer & Dryer Combo - Front Load. Voltage/Frequency Rated Current 20A; Washing Capacity(DOE) 12 kg or 26 lbs; Drying Capacity 7 kg or 16 lbs; Energy verified for USA & Canada; Color White; Max spin speed 1200 rpm; Wash temps Hot+, Hot, Warm, Eco, Cold; Display"}, {"role": "assistant", "content": "Price is $899.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHONEY JOY Roll Up Piano, Portable 88 Key Piano Keyboard, Soft Grade Silicone, Rechargeable Educational Piano with LED Touch Screen, 128 Tones, 128 Rhythms, 15 Demos, Built-in Amplifying Speakers\n\u266a Multiple Built-in Functions The roll up piano features in Bluetooth, transpose, chord function, recording, playback and other functions, can be connected to USB, MIDI, microphone, etc. In addition, it has 128 tones, 128 rhythms, and 15 demo songs. Its powerful functions will meet various requirements and achieve more creation. \u266a Soft Keyboard with Thicken Keys Crafted with premium grade silicone, the 88 standard keys piano keyboard is soft and comfortable to play, giving a real feeling for players. Thicken keys will provide"}, {"role": "assistant", "content": "Price is $59.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nElite Core CSM2 Series Tour-Grade Microphone Cable, 15 ft\nTour-Grade Ultra Quiet and Ultra Durable mic cable with genuine Neutrik NC3XX XLR connectors and conductive PE for maximum EM and RF rejection. Elite Core CSM2 Custom Shop mic cables are hand-built by skilled technicians in the USA using only the finest available materials and most effective techniques. Every detail - the cable construction, the connector choice, the solder, the flux, the shrink tube, the testing, and the packaging, are each carefully chosen to create the finest stage and touring microphone cable available. Straight Male and Right-Angle Female Neutrik Connectors Ultra durable dual core tour-grade microphone cable and LIVE QUIET performance Dual primary bare-copper inner conductors Conductive PE outer-core"}, {"role": "assistant", "content": "Price is $58.79"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSpectrasonics Omnisphere 2 Upgrade\nOmnisphere 2 Upgrade. **This is the upgrade version and will upgrade current users of Omnisphere to the full version of Omnisphere 2.0. Omnisphere is among the elite virtual synthesizer programs for producers, composers, and sound designers; and if you think this monster power synth couldnt get any better, youve just been proven wrong. Introducing Omnisphere 2.0, the first v2.0 of any Spectrasonics instrument and it is truly gigantic! With Omnisphere 2.0 comes a massive variety of new synthesis options, a staggering audio library with over 10,000 sounds, a new interface with an enhanced sound browsing capability, a new and enhanced"}, {"role": "assistant", "content": "Price is $229.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLight Stix LED Drumsticks (Blue)\nPlay all day and night with these NEW! Color effects Light Up Drumsticks Create amazing visual effects when they move through the air! Specially selected LED's for maximum light and effect (wavelength & beam angle) to bring the spotlight to you on stage and help you play in the dark! Motion Activated Light Up Drumsticks Lights up every beat! Frosted Tips for Great Effects! Ideal for marching bands electronic & acoustic kits. Amateur and Professional drummers young & old for that extra special gig! Made from strong Poly-Carbonate! (as used in riot shields) Suitable for all drum kits and types snare drums, zildjian, mapex, yamaha, ludwig, pearl and compliment your other drum sticks, vic firth etc"}, {"role": "assistant", "content": "Price is $20.75"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nThomastik-Infeld Versum Solo Cello Single A-String - 4/4 Scale - No. VES41\nThe set VE400 is extremely well-balanced with a warm, sweet and fresh sound color. Its refined texture and easy playability make it a universal choice for many different types of cellos and musical genres. Developed and produced in Vienna, Austria since 1927 100% constant quality absolutely reliable at every performance Breathable leather lining Thomastik-Infeld offers 1,300 strings for every playing style! Weight 0.352 ounces, Dimensions 4.75 x 0.13 x 4.75 inches, model number VES41, Rank Musical Instruments 62773, Cello Strings 78, Is Discontinued No"}, {"role": "assistant", "content": "Price is $54.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKeeley Seafoam Plus Vibrato Chorus Effects Pedal, Blue\nWe are proud to announce the all new Seafoam Plus Chorus \u2013 True Chorus and ADT with Reverb. It will forever change the way you think about chorus, because we have developed a new type of chorus that until now has only been available in expensive DAWs and in studios. Not only is it tuned for guitar, but there are voices and modes created specifically for bass players including flanging and tremolo. Lastly, this tri-mode chorus pedal offers internal switching for vintage and modern tones, further doubling the amount of sounds you can get. A new type of chorus that until now has only been available in expensive DAWs and in studios Not only is it tuned for guitar, but there"}, {"role": "assistant", "content": "Price is $160.65"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJHS Pedals JHS Red Remote Footswitch\nUse with select JHS Pedals to remotely activate the on board toggle found on the pedal itself Acts as an on the fly switcher to give you more tonal options in any setting Currently compatible with these JHS Pedals Morning Glory V4, SuperBolt V2, Twin Twelve V2, Double Barrel V4 To use, plug it into the jack of the pedal labeled REMOTE; the red washer denotes the jack to plug the Red Remote into Weight 6.9 ounces, Dimensions 6 x 4 x 3 inches, model number RedR, Rank Musical Instruments 10643, Guitar Amplifier Footswitches & Controllers 28, Is Discontinued No, Available April 23, 2016, Color Name"}, {"role": "assistant", "content": "Price is $45.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nf\u00e4nde SmartMic Bluetooth Wireless Microphone Lapel Lavalier, Rechargeable Bluetooth Clip-on Lapel Mic Noise Cancellation for iPhone Android iPad Video Recording Interview Teaching Podcast Vlogging\nPowered by Sanbinetek GREAT FOR YOUR CHOICE Just connect your Smartphone with UAT Smart Mic microphone via bluetooth, Say Goodbye to Messy Cables! You can create the perfect videos and audio files on your smartphone at anywhere. Ideal for Vloggers, Youtubers, Podcasters, Interviewers, online meeting and more. \ud83c\udfa4 Powered by Sanbinetek Bluetooth Wireless Mic Professional Grade Bluetooth Lavalier Lapel Microphone, easy to connect and covers 98 foot for the Bluetooth signal. Works with any your smart phones, tables and PC device. Perfect for on line"}, {"role": "assistant", "content": "Price is $28.90"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n2 Units - 2 Foot - Canare L-4E6S Star Quad, Patch Cable terminated with Neutrik-Rean NYS \u00bc Inch Gold TRS Stereo Phone Plugs - CUSTOM MADE By WORLDS BEST CABLES.\n2 Units - Custom Made - 2 Foot Canare L-4E6S Star Quad, Patch Cable terminated with Neutrik-Rean NYS \u00bc Inch Gold TRS Stereo Phone Plugs (this sale is for 2 cables, each cable is 2 foot long). Canare L-4E6S by Canare Electric Co., LTD-Japan is a premier (21 AWG) ultra-durable Star Quad audio cable for high-end audio applications. 40 separate strands in each conductor results in improved strength &"}, {"role": "assistant", "content": "Price is $21.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTHD Electronics YJ20S Yellow Jacket for 6V6 Amps, Single, w/Tube\nThis model of Yellow Jackets converter, the YJ20, is a specialized, current-limiting/voltage-conditioning adapter for use in most amplifiers which use 6V6 output tubes, or other similar-based tubes, such as the 6F6, 6G6, 6K6, 6Y6, etc. All Yellow Jackets converters come with JJ Brand vacuum tubes. * Converts most audio amplifiers with 6V6s and similar-based tubes to EL84s without modification or rebiasing * One year limited warranty on converter. * Safe for all common amplifiers and transformers. Converts Class AB to Class A operationDrops Output Power Does"}, {"role": "assistant", "content": "Price is $99.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMOKFON Stereo Aux Cable for Power Amplifier Male to 3.5mm 1/8\u201d Male TRS Audio Adapter on iPod, Guitar,Microphone and Black)\nDESCRIPTION MOKFON TRS amplifier cable connector ideal for connecting between devices with 1/8 and 1/4 jacks.You can widely connect to your mixing console, home theater devices, stereo power amplifiers,guitar, guitar speaker,CD Players, soundbox, tablets and so on. Oxygen-free conductors combine with nylon mesh braid provide maximum's conductivity and durability. 6.35mm 1/4 male TRS amplifier cable connector connect to a mixing console, home theater devices, stereo power amplifiers,guitar, guitar speaker, etc. 3.5mm 1"}, {"role": "assistant", "content": "Price is $9.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDomini Milk Frothing Pitcher, Stainless Steel Metal 20 oz -For Milk Frothers, Espresso Cappuccino Coffee, Creamer,Steaming,chef,motta (Measurement inside)\nMaterial The frother pitcher is made of #304 stainless steel, no rust, the surface is bright and clean, smooth, environmentally friendly, durable,and easy to clean it has a small mouth design, helps you to pour liquid out(milk, coffee, etc.) easily, no overflow, when you cook cream, very suitable for modeling. Capacity\uff1a full), the capacity of moderate, available for milk machine and playing milk containers,coffee pitcher,the size Application\uff1a the coffee milk pitcher can be for liquid and solid,milk, coffee, drinking,wine and so on.6 solder joints in the handle"}, {"role": "assistant", "content": "Price is $13.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGuitar Kit Tail Nail Tool Musical Instrument Part Accessory musican lovers. for installing guitar tuners, enlarging holes in pickguards and lots of other tasks.\nYou can punch the tuning pegs with a diameter of 1cm / unique step structure can easily open various types and sizes of apertures.Help you easily drill a hole on guitar. Useful tool for guitar lovers to do DIY. Guitar Tail Nail Tool is made of qualitied material, high strength, wearable and durable.With wooden handle, comfortable for you to use.Most often used for installing guitar tuners, enlarging holes in pickguards and lots of other tasks. Features EXCELLENT TOOLS Great end pin hole reamer tool for acoustic guitar, acoustic bass, ukulele and mandolin.Good quality with"}, {"role": "assistant", "content": "Price is $19.59"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nExtra Thick Flying V Bass Guitar Gig Bag/soft case\n* Super Heavy duty, 600 denier cordoura nylon * Thick high density foam padding * Padded back pack style shoulder straps * Tear proof fabric lining with extra reinforcement at the headstock and body * Heavy metal fittings, extra large zippers and pulls * 3 Accessory pockets, strong padded carry handle Will fit Bass Flying V or similar copies. 52 x 18 x 3 inches Super Heavy duty, 600 denier cordoura nylon Thick high density foam padding Padded back pack style shoulder straps 3 Accessory pockets Weight 4 pounds, Dimensions 52 x 18 x 3 inches, model number Rank Musical Instruments 81399, Bass Guitar Bags & Cases 97, Is Discontinued No,"}, {"role": "assistant", "content": "Price is $89.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTC Electronic VORTEX MINI FLANGER Ultra-Compact Flanger Pedal with Built-In TonePrint Technology\nThe flange sound has been with music throughout the ages - used on everything from vocals to drums, but a guitarist you might have heard of (Edward Van Halen) showed us the only righteous place for flange is guitar! We've combined a classic tape flange with the awesome Tone Print technology, giving you access to everything from through-zero flanges to customized rock star sounds! Tone Print-enabled - load Vortex Mini Flanger with your favorite artist's tone Through-zero-flanger - get the authentic psychedelic flanger sound of the sixties. True-To-Tone True bypass and analog-dry-through Free Tone Print Editor to create your own custom flanger pedal Put it in front"}, {"role": "assistant", "content": "Price is $129.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAlvarez Artist Series AD60CE Dreadnought Acoustic - Electric Guitar, Natural/Gloss Finish\nNew Artist Series guitars from Alvarez look stunning and come in a huge variety of shapes, colors and wood choices. All of their components are made of natural materials such as mother of pearl and abalone inlays, real bone saddles and nuts and rosewood appointments. But the magic really starts when you pick one up and play it. Each model is designed to get the best out if its components, and for them to work together to produce a tone and player experience, rarely found in affordable instruments. The solid \u2018A\u2019 grade Sitka spruce and cedar tops are hand selected from quarter-sawn wood. This ensures consistent quality, and its no secret better guitars are made from better wood"}, {"role": "assistant", "content": "Price is $499.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nXinglong 12 x 12 x 2 24 Pack Black Acoustic Wedge Studio Soundproofing Foam Wall Tiles\nDescribe Produced by environmentally polyurethane foam.In order to improve the opening steps and specific acoustic characteristics, make it not only has the sound absorption characteristics effectively, without any harm to human body Specifications Material nvironmentally polyurethane foam Color black Size x12\\ ) Thickness 5cm / 2\\ 2 inch wedge foam is effective against standing waves and flutter echoes in most small-to-medium sized rooms like vocal booths, control rooms and studios. It also functions as a full frequency bandwidth absorber for any size room when used in conjunction with corner bass absorbers and male/female broadband absorbers good for studios, recording studios, vocal booths, control rooms."}, {"role": "assistant", "content": "Price is $35.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFLOYD ROSE NUT R-3 BLACK\nThe Floyd Rose is a Complete R3 Locking Nut Assembly for Original Floyd Rose Tremolo Systems. These locking nuts will also work with non-Floyd Rose and Licensed Floyd Rose Tremolo Systems. If you don't know the nut size you need, please consult the nut sizing chart. The first, the only, the Original double-locking tremolo system used by more professionals than any other! The Floyd Rose Original is precision-made in Germany, engineered to exacting specifications using high-quality hardened steel. Floyd Rose R3 Locking Nut for Floyd Rose Tremolo Bridge System Width 1.6875 (42.85 mm) Radius 10 (254 mm) Height @ D.278 E-E Center Width 1.4155 ("}, {"role": "assistant", "content": "Price is $49.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nZLINE 36 in. Remote Blower Wall Mount Range Hood in Stainless Steel\nZLINE 36 in. Remote Blower Wall Mounted Range Hood is part of our Professional Series and is one of our best-selling models. With a powerful, 900 CFM dual motor remotely installed in the interior of your home, this unit will quietly, yet efficiently move large amounts of air away from your cook stove area. A sleek, stainless steel surface and an updated modern design, with 4 speed fan control and dishwasher-safe baffle filters, makes this the perfect addition to your home. Comes with everything you need for easy installation. With factory-tested assurance of performance, this wall mounted range hood will be reliable for years to come. Includes a free LED light upgrade. Powerful air flow requires ducted,"}, {"role": "assistant", "content": "Price is $878.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSeymour Duncan APH/Slash Bridge Humbucker (Black)\nSEYMOUR DUNCAN APH-2B SLASH ALNICO II PRO HB BLACK - Includes FREE Fitting at our York branch workshop, alternatively please ask for our Simply Pickup price. Though he has dozens of amazing guitars, since 1986 Slash has used pretty much one very special Les Paul \u00ae for all recording. The Alnico II Pro Slash was designed to give Slash's other Les Paul guitars-what he calls his live guitars -the exact tone of this legendary instrument. Application Warm, moderate output humbucker. Recommended for jazz, blues, and classic rock. Description Like the standard APH-1 Alnico II Pro, this pickup uses an Alnico 2 magnet. However,"}, {"role": "assistant", "content": "Price is $119.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUpStart Components Replacement for General Electric Bake Element - Compatible with General Electric Oven Heating Element\nPlease note This is an UpStart Components brand replacement part, not an OEM product. This product is not affiliated with any OEM brands and is not covered under any warranties offered by the original manufacturers. Any warranties for this product are offered solely by Upstart Components. All mentions of brand names or model descriptions are made strictly to illustrate compatibility. All brand names and logos are registered trademarks of their respective owners. Replacement General Electric Oven Bake Element Replaces General Electric Oven Heating Element Quick and easy installation. Restore your old range and make it perform like brand new with this replacement heating element. Replace your heating element if you experience little or no heat, slow to heat up, uneven heat, inaccurate temperature. Manufacturer UpStart Components"}, {"role": "assistant", "content": "Price is $24.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGold Tone CB-100 Openback Banjo (Five String, Vintage Brown)\nFor 12 years Gold Tone has easily proved the best value in beginner to Pro level open backs. playability, tone and quality designs are our trademark. The CB-100 was created to meet the demands of the modern old-time player. Its lightweight minimalist design yields nothing but effortless playability. An entry level price with all the features of a high end open back, the CB-100 includes a maple neck with a scooped rosewood fingerboard, rolled brass rod Tone ring, a vintage neck design, Fiberskyn head, Planetary tuners, and a no knot tailpiece. Final assembly and Complete setup performed at the Gold Tone factory in Florida. Finish Clear Satin Neck Maple; Nut Bone High"}, {"role": "assistant", "content": "Price is $899.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWaterdrop NSF 53&42 Certified Refrigerator Water Filter, Replacement for Samsung HAF-CIN/EXP, 1 Filter\nCompatible with multiple models HAF-CIN, HAF-CIN/EXP, HDX FMS-2, Replacement for multiple models WS627, CF7, FIN-7, WF294 Authoritative Certifications This Waterdrop water filter replacement for Samsung refrigerators, trusted by American families, has been certified by NSF and IAPMO against NSF/ANSI standards 53, 42, and 372 for effective reduction of 20 substances, offering outstanding filtration and high-quality water purification and bringing healthy drinking water. Deep Filtration This filter has been strictly certified against NSF/ANSI 42 for reduction of chlorine, taste and odor and against NSF"}, {"role": "assistant", "content": "Price is $19.59"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKAISH Stainless Steel USA Thread Tremolo Trem Arm Whammy Bar Fits American/Mexican Standard or Vintage Strat Nickel with 3 Tips\nKAISH Stainless Steel USA Thread Tremolo Trem Arm Whammy Bar Fits American/Mexican Standard or Vintage Strat Nickel with 3 Tips KAISH Screw-in tremolo arm with 3 tips for most right-handed Standard/Deluxe/Vintage strats made in USA or Mexico Made of Stainless Steel, not cheap Iron; Please watch the video to screw the tremolo arm tip correctly! American 10-32 threading, Do Not fit Fender Squier or other import style Strats which needed metric 5.5mm or 6mm diameter thread trem arm Arm Thread diameter is about 4.65mm You may need a tremolo arm"}, {"role": "assistant", "content": "Price is $8.59"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMonoprice 9 x Quad LED Flat Par Stage Wash Light (RGBW) Black, DMX Option - Stage Right Series\nEnjoy bright and colorful stage lighting using this Flat PAR Stage Light from Monoprice! This light uses nine RGBW LEDs with an almost unlimited number of color variations. It can be controlled using basic DMX or using one of the built-in programs. The Strobe Follow mode allows you to have multiple fixtures strobe in sequence, rather than all at once. Strobe follow mode for up to 32 devices Smooth color blending and dimming does not look glitchy on video Wattage 10.0 Voltage 240.0 Color Black, Material Plastic, Light Source Type Led, Power Source Corded Electric, Brand Monoprice, Weight 2.6"}, {"role": "assistant", "content": "Price is $69.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGeneral Electric High Limit Thermostat\nProduct Description This is a Genuine Replacement Part, The Model Number and Name for The Following Item General Electric High Limit Thermostat. From the Manufacturer This is a Genuine Replacement Part,The Model Number and Name for The Following Item General Electric High Limit Thermostat General Electric This is a genuine replacement part Clothes-dryer-replacement-parts Brand name GE Brand Name GE, Model Info Weight 1.6 ounces, Dimensions 8 x 7.5 x 0.6 inches, model number Is Discontinued No, Part Color Silver, White, Black, Rank Tools & Home Improvement Dryer Replacement Parts 20510, Domestic Shipping can be shipped within U.S., International Shipping This item can be shipped to select countries outside of the U.S. Learn More, Available"}, {"role": "assistant", "content": "Price is $61.27"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nABS Novelties Cats with Glasses Pattern Double Cushion\nCats With Glasses pattern double cushion 3 thick foam top & bottom Made in USA Vibrant dye sublimated prints on durable poly material 14\u201d x 14\u201d x 3\u201d foam on seat and back gives comfort to your back and bottom Velcro sealed flap on the back of double cushion gives storage space and allows you to secure the cushion to the back of your chair Folds easily with carrying handles made for easy transport Fill Material Foam, Pillow Type Furniture Cushion, Color Red, Brand ABS Novelties, Shape L-Shape, Special Feature Protable, Pattern Cat, Age Range (Description) Adult, s 1, Dimensions 14\\ L x 14\\ W, Care Instructions Dry Clean Only, Style"}, {"role": "assistant", "content": "Price is $34.75"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDEFLECTO F0405B Supurr-Flex UL Listed Clothes Dryer Transition Duct-4 x 5', Silver\nSupurr-Flex UL Listed Clothes Dryer Transition Duct - 4 x 5'. Item Number Product Description 4 dia. x 5 ft. UL Listed Supurr-Flex Clothes Dryer Transition Duct. Features UL listed clothes dryer transition duct. Fire resistant and flexible. Easy to install. UL listed clothes dryer transition duct Fire resistant Flexible, easy to install Size 4 x 5' Manufacturer CORPORATION, Part Weight 0.5 Pounds, Dimensions 6 x 4.5 x 4.5 inches, model number Is Discontinued No, Size Pack of 1, Color Silver, Power Source Hand Powered, Quantity 1"}, {"role": "assistant", "content": "Price is $10.79"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTomsline AAS-3 AC Stage, Acoustic Guitar Simulator Pedal\nAcoustic Guitar Simulator Pedal. Volume, body and top control. 3 options of piezo, standard and jumbo. True bypass. Acoustic guitar simulator Volume, body and top control 3 options of piezo, standard and jumbo True bypass Power supply DC 9V adapter (not included) Weight 1 Pounds, Dimensions 4 x 2 x 2 inches, model number AAS-3, Rank Musical Instruments Steel-String Acoustic Guitars 479, Is Discontinued No, Available August 12, 2015, Color Name White, Yellow, Guitar Pickup Configuration Piezo, Signal Format Analog, Power Source Adapter, Voltage 9 Volts, Brand T"}, {"role": "assistant", "content": "Price is $45.62"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFender CD-60S Solid Top Dreadnought Acoustic Guitar, Left Handed - Natural Bundle with Gig Bag, Tuner, Strap, Strings, Picks, and Austin Bazaar Instructional DVD\nAdding value to your purchase, Austin Bazaar bundles your instrument with necessary accessories. Everything you need to start playing immediately comes in one box. Save yourself the hassle and save some money while you're at it. A gig bag is included so you can keep your instrument safely packed away when you're on the go. An easy-to-use clip-on tuner is included so you can keep your instrument in tune. A strap is included so you can practice or better yet perform while standing up. Strings are included so you have extra for later. Picks are included so you can start playing right out of"}, {"role": "assistant", "content": "Price is $279.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSelmer Alto Saxophone Mouthpiece\nSelmer alto saxophone mouthpiece hard rubber soloist. Alto Saxaphone Hard Rubber Mouthpiece Used by professionals Item Package Dimension 2.0 L x 2.0 W x 1.0 H Weight 1.76 ounces, Dimensions 1 x 1 x 1 inches, Domestic Shipping can be shipped within U.S., International Shipping This item can be shipped to select countries outside of the U.S. Learn More, Country of Origin USA, model number S432D, Rank Musical Instruments Alto Saxophones Mouthpieces 288, Is Discontinued No, Available February 6, 2009, Brand SELMER, Style Modern, Dimensions LxWxH 1 x 1 x 1 inches, Finish Type Pol"}, {"role": "assistant", "content": "Price is $148.85"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBexGears DIY 8 String Electric Guitar Kits Burl poplar veener top okoume Body maple neck & composite ebony fingerboard You Build The Guitar\nYou Build The Guitar Country of Origin CHINA Dexterity Right Handed Body Material Okoume Body Top Veneer Burl poplar top Neck Material Maple Fretboard Material composite ebony Scale 26 1/2 Frets 24 Nut Width 1 7/8 Truss Rod Adjustable Rod Nut Controls 1 Volume & 1 Tone 3 way witch Hardware Color Black Chrome Knobs Strings 8 String weight 7 lbs.If you need instructions, we will send it to you as a PDF. 8 String Electric Guitar Kits Burl poplar veener top okoume Body maple neck & composite ebony fingerboard Kit"}, {"role": "assistant", "content": "Price is $209.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSmall 10 Baby Twirling Baton/Gift/Souvenir Baton\nThis is our Wrapped Pretty Baby Baton. It is approximately 9 long. It is not weighted, like our professional batons are and is not appropriate length to twirl. This is Just for Fun. It makes a great present. It is also used by a lot of twirlers for practicing finger rolls. This would be a great tool to use for rehabilitation of finger dexterity. 9 Long, Plain Shaft, Great Gift, Award, Prize, Finger Exercise, Small Souvenir Baton Just for fun, My first baton Weight 4 Ounces, Weight 0.25 Pounds, Brand Name Sharp's Baton, Model Name Sharp Souvenir Baby Baton, Material Tempered steel, Manufacturer Sharp's Baton Corp"}, {"role": "assistant", "content": "Price is $15.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDishwasher Magnet Cover, Retro Rusty Style Decorative Magnets Refrigerator Wrap Front Door Stickers, Home Appliances Decals 23inch W x 26inch H\nAffordable way to update the looks of your dishwasher,dishwasher decorative covers affixes instantly to the front of your dishwasher giving it a custom decorator look.Bring lovely color and unique look into your kitchen. Our dishwasher magnetic LIDS are magnetically removable self-adhesive PVC and PET films, flexible magnet sheets that easily cover stains, are water resistant and heat resistant, as well as easy to clean and maintain. 23 / 23 / Features Imitation rust decorative magnetic dishwasher cover easily hides scratches, dents or other unsightly markings on your dishwasher. Waterproof, oil resistant, high temperature resistant, corrosion resistant"}, {"role": "assistant", "content": "Price is $38.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCHAUVET DJ Mini Kinta IRC 3W LED RGB DMX Light Effect + H700 Fog/Smoke Machine\nThe Chauvet Mini Kinta IRC is fitted with 3 W LEDs to punch through nearly any ambient lighting or fog. Filling a room floor to ceiling with razor sharp beams, it delivers an output that surpasses those of much larger derby effects. DMX controllable, it also features exciting built-in programs. Just over 3 pounds this light is lightweight and rugged for mobile DJs and to protect your light on the go the CHS-30 VIP gear bag is recommended (not included). Also included with the Chauvet Mini Kinta IRC is the H700 fog machine, which is perfect for any party or event. It provides the quality, performance and innovation"}, {"role": "assistant", "content": "Price is $180.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nVAlinks USB Guitar Cable, USB Guitar Cord Male to 6.35mm 1/4 Mono Male Electric Guitar Cable, Computer Audio Connector Cord Adapter for Music Instrument Recording Singing\nPlug & Play Use VAlinks USB Guitar Cable, plug the 1/4 TS plug into the guitar you love, plug the usb interface into your computer, your computer will be converted to guitar amplifier and recording system without the need for any other hardware and driver, plug and play. Great Compatibility Compatible with USB 2.0. Fit for almost all kinds of computers with USB port, such as Windows 98SE/ 2000/ XP/ VISTA/ Win7/ Win 8/ Win 10, Mac OSX(But not for PS2/ PS3/ PS4/ WII"}, {"role": "assistant", "content": "Price is $11.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKNA Pickups, 1/8 to 1/4 Instrument Cable Portable Piezo Nylon String Guitar Pickup (NG-1)\nEncased in lightweight tone wood, The NG-1 Sensor ensures Natural sounding amplification of your nylon-string guitar without modification to the instrument. Utilizing the tension of tuned strings, NG-1 installs safely and securely on the tie bar of most classical and flamenco style guitars. NG-1 comes complete with a detachable, mini-plug to 1/4 Cable. Delivers the natural sound of your nylon-string guitar Lightweight, wood-encased sensor Easy installation without modification to your instrument Passive, no-battery-required design Includes 10' foot detachable cable Detachable, or may remain installed when not in use One 9-ft. "}, {"role": "assistant", "content": "Price is $69.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDefrost Heater Assembly with Refrigerator Clip Drain Evaporator by Wadoy, Heater Metal Sheath Compatible with Samsung\n\ud83d\udd27 Compatibility Defrost heater assembly part number / replaces Refrigerator clip drain evaporator part number / replaces \ud83d\udd27 Compatible With Samsung Appliances including etc. \ud83d\udd27 Defrost heater assembly with thermostat, which can effectively ensure that the frost heater will not overheat and always work at a safe and effective temperature. \ud83d\udd27 Durable to Use Multi-layer protection for the electric wire to extend the service life. Heat generating device and wire connection part is wrapped with silicone rubber for better stability and insulation. \ud83d\udd27 Non original aftermarket part. - Defrost heater assembly kit, compatible with Samsung. This defrost heater assembly kit was not created by Samsung."}, {"role": "assistant", "content": "Price is $27.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nRock and Roll It - Studio Piano. Roll Up Flexible USB MIDI Piano Keyboard for Kids & Adults. 61 Keys Portable Controller Keyboard. Foldable Silicone Piano Pad with Built-in Speaker\nRock out, then roll it up! Multi-function, flexible, completely portable professional piano by MukikiM with 61 standard keys. Features \u266b128 Keyboard Tones \u266b128 Rhythms \u266b45 Demo Songs \u266bVibrato/Sustain \u266bRecord & Playback AND OOP recording \u266bTeaching Mode \u266bMIDI compatible \u266bDigital display \u266bTempo control \u266bDrum sound function \u266bPower saving function activates when not in use \u266bBuilt In Speaker w/auxiliary capabilities(headphones or external speaker) \u266bPowered by included rechargeable battery OR USB ("}, {"role": "assistant", "content": "Price is $82.96"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUltimate Support Ultimate Double Brace X-Style Keyboard Stand\nSet up your keyboard on a sturdy, lightweight stand, with the double-braced X-style keyboard stand. The is easily adjustable to sitting or standing height thanks to the large height-adjustment knob. The X-style keyboard stand accommodates a variety of playing situations. The unit folds flat for easy transport and storage and ships assembled.. Double-Braced For Heavier Keyboards; Five Height Positions; Easy-To-Adjust Pull-Style Knob Locks Stand In Place Country of Origin China Package weight 11.24 pounds Model number JS502D Package dimensions 104.6 cms L x 51.6 cms W x 8.2 cms H Weight 11 pounds, Dimensions 19.25 x 15.75 x "}, {"role": "assistant", "content": "Price is $47.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n460mm Guitar Truss Rod Two Way Rod Type,Pack of 2pcs\nTwo way or two course rod type A3 Steel Guitar Truss Rod For making or repairs. Total length is Rod head Outside diameter 9mm ; Inside diameter included 2 * Truss Rod ; 1 * Adjust Wrench. High quality Guitar Truss Rod For making or repairs. Two way or two course guitar truss rod type. A3 Steel Material,Total length is Truss Rod head Outside diameter 9mm ; Inside diameter 5mm Package included 2 * Truss Rod ; 1 * Adjust Wrench. Weight 11.2 ounces, Dimensions 18.1 x 1 x 1 inches, Rank Musical Instruments 48258, Electric Guitar Wood & Inlay Material "}, {"role": "assistant", "content": "Price is $16.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSeismic Audio - T12Sub - 12 Inch Steel Frame Subwoofer Driver - 300 Watts RMS Replacement Sub Woofer for PA, DJ, Band, Live Sound\n12 Inch Steel Frame Subwoofer Driver Model # T12Sub Contents 12 Inch Replacement Subwoofer Power Rating 300 Watts RMS - 600 Watts Peak Impedance 8 Ohms Frequency response 26 Hz - 500 Hz Sensitivity 94 db Magnet Size 50 oz Voice Coil 2 Inch Chassis Type Pressed Steel Cone Paper Cone/Cloth Edge Mounting Information Diameter 12 1/4, Cut Out Diameter 11, Mounting Slot Dimensions 1/4, Number of Mounting Slots 8, Overall Depth 5 1/2, Mounting Depth 5 "}, {"role": "assistant", "content": "Price is $76.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAITREASURE Tibetan Singing Bowl Set with Mallet & Cushion- Meditation Sound Bowl for Chakra Healing, Yoga, Zen\nSinging bowls are a type of bell used by many people across the world, especially the Yoga, the Meditation and Prayers. The tone is calming and very zen like. So the AITREASURE Singing Bowl is a delightful addition to your search for peace and tranquility! Specifications Material of the bowl copper Size 4 (W) x 2 (H) Weight of the bowl 250g Packing List 1 x Tibetan Singing Bowl 1 x Cushion 1 x Striker BENEFITS ENHANCES YOGA, MEDITATION AND HEART CHAKRA CLEARING - The sounds generated by this Tibertan Singing"}, {"role": "assistant", "content": "Price is $26.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGemini Sound Bluetooth Dual Active/Passive 15 Inch Woofer 2000W Watts Speaker PA System, XLR Input/Output, 1/4 Inch Mic, RCA/AUX Inputs, USB SD Card, Mixer Stands Cables Microphone Set Bundle\nCOMPLETE PROFESSIONAL PA SYSTEM This Gemini PA system is a complete package for all your event needs. It comes with a pair of 15 speakers (one active, one passive), a wired microphone, two sturdy tripod speaker stands, a Speakon cable, and a power cable. Perfect for DJs, live bands, and other professional events. VERSATILE CONNECTIVITY OPTIONS The integrated MP3 player offers multiple connectivity options including USB, SD, and Bluetooth. This allows for seamless connection with various devices, making this system"}, {"role": "assistant", "content": "Price is $399.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAll Parts PC Cream Humbucking Pickup Ring Set\nHumbucking pickup ring set - Neck and Bridge, flat bottom, slanted, Cream plastic. Outside dimensions - Inch x Inch, Inside dimensions - 2-3/4 Inch x 1-1/2 Inch. The low mounting rings are for the neck position. The height tapers from 3/16 Inch to 1/4 Inch. Cream Humbucking Pickup Ring Set Model Number PC Electric Guitar Parts Weight 0.32 ounces, Dimensions 4.5 x 0.5 x 7 inches, model number PC Rank Musical Instruments 76865, Electric Guitar Pickups & Pickup Covers 1035, Is Discontinued No, Available February 5, 2011, Material Type Plastic"}, {"role": "assistant", "content": "Price is $6.49"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nNANYI 4/4 Violin Shoulder Rest, Premium Large Arc aluminum alloy plate skeleton High strength sponge Comfortable violin shoulder pad -Black\nViolin shoulder Rest/pad lining between the violin and the shoulder, so that the position and direction of the violin on the shoulder is relatively stable, the violin is not easy to fall, the neck does not need to kneel, reduce the neck and The trend of hunchback. The large arc fits the shoulders completely, coupled with the elastic sponge, very comfortable and relaxed, and more free to play. An important advantage of this shoulder pad is that the bottom plate is made of aluminum alloy instead of wood or plastic. strong and not easy to deform. can adjust the height, adapt to the length of different necks and the thickness of"}, {"role": "assistant", "content": "Price is $57.98"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nYosa Dishwasher Cover Magnet - Santa Claus Magnetic Sticker Decals- Christmas Kitchen Refrigerator Dishwasher Panel Decor\nWant to make your dishwasher bright, stylish and beautiful? Magnetic stickers are easy to update your dishwasher panel, covering the ordinary, boring, and scratched panels, giving you a different kitchen experience. Material PET Film and Magnet. Features Heat resistant, Waterproof, Scratch, and Tear Resistant.These Stickers hide scratches, dents, or other unsightly marks.With a smooth surface that is environmentally safe, easy to remove with no sticky residue. Occasion Decor dishwasher covers and any metal device surface with magnetism. Size M for magnetic panels, stainless steel panels are not available. Tips\uff1a Before buying, you can measure the size of the dishwasher or washing machine and choose the appropriate size"}, {"role": "assistant", "content": "Price is $38.85"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nYELANGU Wireless lavalier Microphone for iPhone ipad, Plug - Play & Smart Noise Cancellation Professional Mini Lapel Cordless Mic for Video Recording, Interview and Vlog\nEasy to use YELANGU Wireless lavalier microphone for iphone is plug and play, rejecting cumbersome APP installation and messy wiring process. 1. Insert the receiver into the IOS ipad device. 2. Turn on the transmitter - the indicator light of the lapel microphone turns green and you can use it. Intelligent noise reduction & real-time synchronization 360\u00b0 omnidirectional iphone microphone for video recording is equipped with high-density anti-spray sponge and high-sensitivity sound sensor. Even in a noisy environment, it can easily identify the original sound and automatically perform noise reduction processing. The real-time synchronization"}, {"role": "assistant", "content": "Price is $19.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFrigidaire Thermostat for Dish Washer\nProduct Description This is a genuine replacement part. The number and name for the Following item is Frigidaire thermostat for dish washer From the Manufacturer Frigidaire Thermostat for Dish Washer. Works with the following models Frigidaire Frigidaire Frigidaire Frigidaire Frigidaire Genuine replacement part. Works with the following models Frigidaire Frigidaire Frigidaire Frigidaire Frigidaire Genuine replacement part Manufacturer Frigidaire, Part Weight 6.4 ounces, Dimensions 3.5 x 3.4 x 1.4 inches, model number Is Discontinued No, Quantity 1, Rank Tools & Home Improvement Dishwasher Parts & Accessories 239"}, {"role": "assistant", "content": "Price is $46.62"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJim Dunlop Lucky 13 Picks, Assorted,.60mm, Pack\nDunlop and Lucky 13 Apparel have joined forces to bring you this new line of picks. These little collectors items sport full-throttle, in-your-face images like hot rods, whiskey bottles, and tattoos and come in a variety of colors and gauges..60mm - Lucky 13B Player's Pack 6 Picks Per Player's Pack Gauges (mm).60,.73, 1.0mm Rock and roll art inspired picks by Lucky 13 Highly collectible Weight 0.004 ounces, Dimensions 3.6 x 2 x 0.4 inches, model number Rank Musical Instruments 80680, Guitar Picks & Bass Picks 2373, Is Discontinued"}, {"role": "assistant", "content": "Price is $5.79"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHercules DJControl Inpulse 500 DJ Software Controller with Polsen Monitor Headphones & Mini to 6' RCA Cable Bundle\nThe Hercules DJControl Inpulse 500 is a plug-and-play, USB DJ controller that connects in seconds and allows you to mix and scratch with ease using the included DJUCED and Serato DJ Lite software. It offers two-channel mixing with 5.5 high-precision touch-reactive platters, each with a beatmatch light guide for easy manual mixing. The two sets of eight performance pads per channel offer vinyl functions and loop-in / loop-out capabilities, as well as the default color of each cue point in Serato DJ Lite, providing a natural and intuitive control of the cue points and sampler. The Filter/FX area helps create smoother original"}, {"role": "assistant", "content": "Price is $299.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAKG P420 Condenser Microphone Bundle with Studio Stand, Pop Filter and XLR Cable (4 Items)\nThe AKG P420 Professional Microphone is engineered for clear, professional quality sound capabilities you won't find in other instrumental microphones in the same class. The one-inch dual diaphragm microphone features 3 selectable polar patterns for the perfect setting; Cardioid, Omnideirectional and Figure of Eight. The low noise electronics offers a high dynamic range, and the switchable attenuation pad is geared for high SPL applications up to 155 dB SPL. The AKG P420 Mic offers a high sensitivity and delivers a warm, transparent sound quality, perfectly suited for ensemble recording, grand piano, woodwind and brass instruments as well as drums and percussion. Bundle Includes AKG P420"}, {"role": "assistant", "content": "Price is $219.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFrigidaire Genuine OEM Control Board and Clock for Ranges\nProduct Description The high quality Frigidaire Control Board and Clock ) monitors the temperature and controls the oven heat. The Control Board and Clock has an electronic clock/timer display and compatible with Frigidaire ranges. Please be aware that it is recommended to use saftey equipment and to disconnect the appliance from all utilities prior to any service or repair. Please refer to your owners manual to confirm part numbers and for instructions as some repairs require a trained service professional to complete. From the Manufacturer This is a genuine replacement part. The model number and name for the following item is Frigidaire (FRIGB) Oven ControlBoard The Frigidaire Control Board and Clock is a genuine OEM (Original Equipment Manufacturer)"}, {"role": "assistant", "content": "Price is $209.47"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDawn Wall Mount Supply Elbow\nDawn shower products are made of solid brass and plated with chrome or brushed nickel to provide reliability and durability. They come in classic and modern styles with various functions to suit and enhance the visual landscape of a home. The showers are equipped with different spray settings and easy-to-clean spray nozzles to create extraordinary showering experience. Designed to prevent wear and tear, they are easy and durable for everyday use and nearly maintenance free. Connects Handshower Hose To Water Supply Durable And Easy To Maintain Also Comes In Round From The Brand Name Dawn Brand Dawn, Style Brass,Classic,Modern, Shape Round, Material Solid Brass Construction, Finish Type Brushed, Installation Type Wall Mounted, Color Chrome, Jets 1, Manufacturer Dawn Kitchen & Bath Products,"}, {"role": "assistant", "content": "Price is $29.13"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMotu M2 2x2 USB Audio Interface with AKG Project Studio P220 Condenser Mic, Studio Monitor Headphones & XLR Cable Bundle\nEquipped with the same ESS Ultra DAC Technology found in audio interfaces costing thousands, the M2 from Motu delivers an astonishing 120 dB Dynamic Range on its main outputs. ESS converters also drive the headphone output, which rivals dedicated headphone amplifiers costing hundreds. Ultra-clean preamp circuits produce a measured -129 dBu EIN on the mic inputs. Capture and monitor your audio with pristine clarity. The M2 provides best-in-class speed for monitoring live inputs (mic, guitar or keyboard) through your computer, thanks to MOTU's expertly engineered USB drivers, which deliver class-leading, ultra-low 2.5 ms"}, {"role": "assistant", "content": "Price is $309.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBuckle-Down Guitar Strap Candy Cane 2 Inches Wide\nWhen you hit the stage, you definitely want to be rockin' with a Buckle-Down guitar strap. Proudly hand-crafted in America, Buckle-Down's premium guitar straps are hand-built with hearty, durable materials and display your favorite characters or brands with the highest-quality printing in the industry. The colors pop so hard that people will notice your strap from outer space! Great for everyone from beginners to advanced players, this strap will adjust to fit children and adults. This product is Officially Licensed by Buckle-Down, Inc.. 100% Polyester Made in the USA and Imported Buckle-Down Guitar Strap - Candy Cane - 2 Wide - 29-54 Length Dimensions L x W x"}, {"role": "assistant", "content": "Price is $21.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJBER Hexagon Acoustic Panels Beveled Edge Sound Proof Foam Panels X 12 X 0.4 High-Density Sound Absorbing Panels Wall Tiles for Acoustic Treatment, Home Office 12 Pack - White\nHigh Density and Eco-Friendly - Made from 100% polyester fiber, better Sound Insulation than soundproofing foam! Sound proofing and flame retardant, odorless, non-toxic, non-slip, corrosion resistant, and anti-aging. Size - 14 X 12 X 0.4 inches, light weight, multiple colors for decoration; Package includes - 12 Pack Set Acoustic Absorption Panel. Multipurpose - Perfect for individuals to reduce and absorb unwanted echoes, waves, reverb and flutter echoes and wall decoration. Use to spot treat"}, {"role": "assistant", "content": "Price is $28.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nD'Addario Helicore 4/4 Size Violin Strings Set with Plain Steel E String - H310 4/4L - Full Set - Light Tension\nDesigned for optimum playability, D\u2019Addario\u2019s Helicore violin strings are one of the most versatile stranded-steel core strings available. Used by professionals and students, Helicore strings suit many playing styles, levels and instruments. They are often preferred by alternative-style and electric instrument players. D\u2019Addario leverages centuries of string-making experience and advanced computer-controlled winding technology to bring you the most durable, consistent and long-lasting strings. Helicore violin strings are crafted with a multi-stranded steel core, giving them great playability and a clear, warm tone. The smaller string diameter provides quick"}, {"role": "assistant", "content": "Price is $45.93"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCompatible Range Gas Oven Igniter with Magic Chef models\nParts Number Please note This is a generic product and not an OEM product and is not covered under any OEM manufacturer's warranty. The OEM brand names and logos are the registered trademarks of their respective owners. Any use of the OEM brand name or model designation for this product is made solely for purposes of demonstrating compatibility. Part Number Exact Replacement for numbers Two Prong Female Pin Plug Great part, direct fit and easy to install. Easy installation - your satisfaction! MONEY BACK GUARANTEE within 30 days from the date of purchase. We are confident in the quality of our part, and you can be confident in us. If you are not satisfied with our product, a refund will be made This is a generic product and not an OEM product Manufacturer"}, {"role": "assistant", "content": "Price is $38.98"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWasher Motor Coupler & 285809 Short Cam Agitator Repair Kit Replacement for Whirlpool - Compatible w/ Direct Drive Motor Coupling Kit & 285809 Agitator Repair Kit\nUpStart Components Replacement Washer Motor Coupler & 285809 Short Cam Agitator Repair Kit for Whirlpool Washing MachinePlease note This is an UpStart Components Brand replacement part, NOT an OEM product. All mentions of brand names or model descriptions are made strictly to illustrate compatibility. All brand names and logos are registered trademarks of their respective owners. This product is not affiliated with any brands and is not covered under any warranties offered by the original manufacturers. Any warranties for this product are offered solely by UpStart Components. UpStart Components Replacement Washer Motor Coupler & 285809 Short Cam Ag"}, {"role": "assistant", "content": "Price is $7.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUpgraded Refrigerator Evaporator Fan Motor, Compatible with LG, Kenmore, Replace Figure 6 Lists The Compatible Models- 15 Years Warranty\nPRODUCT FUNCTION refrigerator fan motor circulates air through the fresh food compartment for efficient cooling.Perfectly fixes a series of problems such as abnormal refrigerator temperature and abnormal noise from the fan motor. Easy to install. You can fix it yourself, enjoy the joy of DIY repair. (Take photos of your unit prior to disassembly, it will save time during the reassembly) Exact Compatible We know you are concerned about whether the Evaporator Fan Motor is compatible with your refrigerator. Figure 6 shows some compatible LG, Kenmore refrigerator models. But not all models. You can tell us your refrigerator model and we will confirm it for you. This"}, {"role": "assistant", "content": "Price is $31.44"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTaylor 114CE Grand Auditorium Acoustic Electric Guitar\nGreat for beginners and seasoned pros alike, the 100 Series instruments from Taylor give players the quality, tone, and playability you've come to expect from a Taylor guitar at a more affordable price. Available in Dreadnought or Taylor's signature Grand Auditorium body shape, the 100 Series instruments all boast solid Sitka spruce tops and beautiful layered walnut back sides while Taylor Expression System 2 electronics (ES-N on nylon-string model) make these instruments great for performing. These 100 Series guitars also come standard with a Taylor gig bag, black binding, a black pickguard (except nylon-string model), and Italian acrylic dot fingerboard inlays.Featuring layered walnut back sides, a solid Sitka spruce top, and"}, {"role": "assistant", "content": "Price is $999.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCES Wide Dispersion PIEZO Horn TWEETR 3 x 7\nPIEZO TWEETER 3 x 7 are made of high temperature black plastic, no voice coils or crossovers delivering cleaner response, high output levels, excellent transient response, high impedance, low harmonic distortion Rated at 80 Watts RMS Frequency Response 3.5kHz -30kHz SPL 97dB @ 1W/1M 3 x 7 4 hole mounting model number Is Discontinued No, Wireless Remote No, Rank Musical Instruments Monitor, Speaker & Subwoofer Parts 319, Available November 19, 2013, Brand CES, Surround Sound Channel Configuration 3.0, Color Black, Is Waterproof FALSE, Manufacturer CES"}, {"role": "assistant", "content": "Price is $4.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKONIX 49 Key Piano Keyboard, Portable Touch Sensitive Keyboard Piano for Beginners Kids, Travel Electric Piano Keyboard Slim with MIDI, Speakers and Piano Bag\nReal Portable KONIX 49 key piano keyboard has a compact body, saving space and easy to carry, it equiped high-quality speakers. Three-dimensional surrounding sound, heavy bass, and warm tone help you create the songs more professionally Ultra-Thin Standard Keyboard 49 standard keys keyboard with velocity touch response, ensure a real piano spacing and comfortable finger feel. the volume of the keyboard depends on how hard you press the keys, through different key strength can obtain the timbre exquisite change Bluetooth MIDI Function The 49 key piano keyboard built in MIDI connection. Easy to connect wirelessly with piano games apps such as Garage Band, Perfect Piano and"}, {"role": "assistant", "content": "Price is $109.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLevy's Leathers 2.5 Neoprene Padded Guitar Strap with Leather Ends; Black\n2 inch neoprene padded guitar strap with leather ends and 2 inch polypropylene webbing with tri-glide adjustment at back end. Adjustable from 46 inches to 53 inches. Also available in extra long (XL), which adds 12 inches to overall length. 2 inch neoprene padded guitar strap with leather ends and 2 inch polypropylene webbing with tri-glide adjustment at back end. Adjustable from 46 inches to 53 inches. Also available in extra long (XL), which adds 12 inches to overall length. Levy's Leathers 2 1/2 Neoprene Padded Guitar Strap,Black. Weight 8 ounces,"}, {"role": "assistant", "content": "Price is $45.62"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nTaylor Guitars Big Baby Taylor, BBT, Natural\nTaylor Guitars Big Baby Taylor The Versatile Dreadnought The Baby Taylor\u2019s big sibling, a Dreadnought with a solid Sitka spruce top and sapele-laminate back and sides, boasts a surprisingly full voice, comes with a lightweight gig bag for easy portability, and makes a trusty companion wherever you go \u2014 even if it's just to the couch. Slightly smaller than than a full-size guitar, the Big Baby looks and feels like a grownup. About Taylor Guitars Founded in 1974, Taylor Guitars has evolved into one of the world's leading manufacturers of premium acoustic and electric guitars. Renowned for blending an innovative use of modern technology with a master craftsman"}, {"role": "assistant", "content": "Price is $419.90"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nUpgraded Dryer Door Catch - Compatible GE Hotpoint - Replaces - Keeps Door Closed, Made of Durable and Tested Materials - Quick DIY Solution\nDryer Door Latch Catch- A high-quality exact equivalent for part numbers Unplug your appliance to prevent electrocution during the replacement. Compatibility with major brands - Catch for dryer door is compatible with General Electric, Hotpoint appliances. It fits hundreds of models and can be installed in a few minutes. Quick DIY repair - Clothes Dryer Door Catch Replacement will help if your appliance door doesn't close and keeps popping open. Wear work gloves to protect your hands. Attentive support - If you are uncertain about whether the catch fits your dryer, we will help you. We generally put forth a valiant effort to guarantee you are totally happy"}, {"role": "assistant", "content": "Price is $16.37"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCasio PX-770 BK Privia Digital Home Piano, Black\nThe world-renowned Privia family of digital pianos grows with the designed to provide a true grand piano experience in a slim, modern design. With authentic piano sound, natural feel and impressive features, the PX-770 is a brilliant instrument for inspiring brilliant performances. Dimensions 54.76 x 11.77 x 31.42 | Weight 69.45 lbs The Tri-Sensor Scaled Hammer Action II keyboard has an incredible feel and captures the dynamics of a performance with unparalleled speed and accuracy Includes a powerful stereo amplification system offering an optimal listening experience that is crystal-clear across the entire audio spectrum Duet Mode splits the piano into two equal pitch ranges, allowing a student and teacher to sit at the same instrument Concert"}, {"role": "assistant", "content": "Price is $899.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSeismic Audio - T10Sub - 10 Inch Steel Frame Subwoofer Driver - 200 Watts RMS Replacement Sub Woofer for PA, DJ, Band, Live Sound\n10 Inch Steel Frame Subwoofer Driver Model # T10Sub Contents 10 Inch Replacement Subwoofer Power Rating 200 Watts RMS, 400 Watts Peak each Impedance 8 Ohms Frequency response 30 Hz - 500 Hz Sensitivity 94 db Magnet Size 50 oz Voice Coil 2 Inch Cone Paper Cone/Cloth Edge Mounting Information Diameter 10 1/4, Cut Out Diameter 9 3/4, Mounting Slot Dimensions 1/4, Number of Mounting Slots 8, Overall Depth 5, Mounting Depth 4 1/2 Weight "}, {"role": "assistant", "content": "Price is $65.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nADJ Products, Startec Series Starburst, Rotating LED Sphere for DJ Light Shows STA962\nWith the Startec Series Starburst lighting fixture from ADJ Products you can project sharp beams of multi-colored LED light to transform any space. With RGBAW+Purple, the Starburst gives you access to a wide array of colors that are sound active and DMX compatible. It also features Auto Run Mode for plug-and-play operation. Easy to mount and connect to other units, the Starburst is a stunning solution for highly-function lighting for clubs, productions, DJs or anywhere you need an impressive light show. CREATE A STUNNING EFFECT The Startec Starburst from ADJ Products is a futuristic rotating mirror ball that shoots out 34 highly powerful beams of 15W LED multi-colored light"}, {"role": "assistant", "content": "Price is $319.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSeymour Duncan Mark Holcomb Signature Pickup - Black Omega Bridge\nBridge Voiced by Mark Holcomb, his signature Omega humbucker is now available once again due to popular demand! The progressive metal virtuosos of Periphery are known for their technically complex rhythms and precise tones \u2013 tones which require pickups with just the right amount of output and articulation whether standing alone or working in a dense mix. The Alpha and Omega pickups were created to match that level of precision and versatility. Working with guitarist Mark Holcomb, the Omega bridge pickup was created to provide destructive percussion and growl in the mids and low end. It\u2019s aggressive but it also has lots of clarity and brightness, which cuts through whether you\u2019re playing sophisticated chords, complex single-note lines or intense solos. SKU Barcode"}, {"role": "assistant", "content": "Price is $139.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nOEM Washer Drain Pump by AMI PARTS Replaces Fit for kenMore samSung Washing Machine\n\ud83d\udd27 PART NUMBER maytag neptune washer drain pump removes water from the washer during the drain portion of the cycle.This pump uses 60 Hz, 80 rpm and 120 volts, it includes impeller \ud83d\udd27 PREMIUM QUALITY \ud83d\udd27-This Original drain pump is made from durable high quality material and well-tested by the manufacturer,the product quality can completely satisfy customers \ud83d\udd27 COMPATIBILITY \ud83d\udd27-This washer drain pump is made exactly fit for most top name brand (samSung, mayTag, kenMore),replaces your Range is not listed above, please send us a message so we may help you obtain the correct part) \ud83d\udd27 TIRED OF"}, {"role": "assistant", "content": "Price is $23.47"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGotoh Hardtail Bridge, Black\nThe Gotoh Hardtail Bridge is for guitars such as non-tremolo Strats\u00ae that have through-body string mounting. Saddles and baseplate are brass. Saddles and baseplate are brass. Saddle intonation is individually adjustable. Saddle intonation is individually adjustable. Use a 1.5mm allen wrench (not included) for saddle height adjustment. Use a 1.5mm allen wrench (not included) for saddle height adjustment. Mounting screws (5) included. Mounting screws (5) included. Bridge specs String spread 2-1/16 String spread 2-1/16 Saddle Width 13/32 Saddle Width 13/32 Saddle Length 25/32 Saddle"}, {"role": "assistant", "content": "Price is $65.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKalimba Thumb Piano 8 Key Mini Kalimba Portable Marimba Musical Good Accessory for Kids, Adults and Beginners.\nSpecification Material Acrylic + MahoganyProduct Size / 2.9 * 2.9 * 0.7 inchesProduct Weight Size / 4.1 * 3.9 * 3.5 inches Package included 8 Keys Kalimba box*1 Our promise If you are dissatisfied with our products, we will return or refund for no reason. \u266bPerfect sound quality\uff1a The sound of 8 key mini Kalimba is fresh and natural. Just move your thumb to get wonderful music, which can relieve your work or study pressure. \u266bHigh-quality materials\uff1aThumb pianos is composed of two materials, acrylic and sape"}, {"role": "assistant", "content": "Price is $8.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFolkmaster Harmonica Key A\n1072A Key A Features -Harmonica. -Classically sculptured metal covers. -Exacting standards are used together with a molded plastic waterproof body. -10 Hole diatonic. Holes -10. Reeds -Single. Key -A/Bb/C/D/E/F/G. Generic Dimensions -4.5 H x 1.5 W x 1 D. Dimensions Overall Height - Top to Bottom -4.5 Inches. Overall Length - Side to Side -1.5 Inches. Overall Depth - Front to Back -1 Inches. Overall Product Weight -0.2 Pounds. Weight 100 Grams, Dimensions 1 x 1.5 x 4.5 inches, model number 1072A,"}, {"role": "assistant", "content": "Price is $19.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nENTERPARK (NEW) Inlet Valve for Whirlpool Refrigerator\nENTERPARK AUTHORIZED OEM REPLACEMENT PART NUMBER Refrigerator Valve Inlt Part Number replaces Safety first Wear work gloves to protect your hands. Unplug the refrigerator before installing this part. Easy to Install - Made Exactly to Fit For Most Top Brand Refrigerators Compatible With Most Whirlpool Refrigerators including G Compatible with Whirlpool Maytag KitchenAid Jenn-Air Amana Magic Chef Admiral Norge Roper and others Manufacturer by OEM factory, Part Weight 12 ounces, Dimensions 5.87 x 4.96 x 3.54 inches, model number Rank Tools & Home Improvement Dryer Replacement Parts 15332, Available January 26, 2021"}, {"role": "assistant", "content": "Price is $82.50"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPyle Upgraded Version Portable Washer - Top Loader Portable Laundry, Mini Washing Machine, Quiet Washer, Rotary Controller, 110V - for Compact Laundry, 4.5 Lbs. Capacity, Translucent Tubs -\nFeatures - Convenient Top-Loading Washing Machine - Hassle-Free Operation Simply Insert Detergent & Water - Does Not Require Any Special Parts or Plumbing - Watch it Work Translucent Tub Container - Energy & Water Efficient Design - Ideal for Small Laundry Loads - Perfect for Underwear, Socks, T-Shirts & Towels - Rotary Control Wash Timer - Compact & Portable Size Technical Specs - High-Powered Washing Motor 180 Watt - Wash-Load Capacity 4. 5 lbs. - Water Tank Capacity 19 Liters - Noise Level 57dB - Power Cable Length"}, {"role": "assistant", "content": "Price is $73.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSF Cable, 10ft XLR 3P Female to 1/4 Mono Microphone Cable\nConnectors XLR 3P Female to 1/4 Mono Male Connectors XLR 3P Female to 1/4 Mono Male Molded connector design enhances the strength of the XLR microphone cables. Molded connector design enhances the strength of the XLR microphone cables. Nickel plated connectors Nickel plated connectors Length 10ft Length 10ft Nickel plated connectors. Connectors XLR 3P Female to 1/4 Mono Male. They are used to connect a high quality microphone to a mixer or guitar amplifier, Available devices Microphones, Audio Sound Consoles, Power Amplifier, Stereo System, Wireless Microphone Receiver, etc. Molded design enhances the strength"}, {"role": "assistant", "content": "Price is $3.29"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSaramonic White 3.5mm Lavalier with 4.1\u2019 Cable for Wireless Systems, Portable Recorders, Cameras, Blink 500, Blink 500 Pro and More\nThe Saramonic SR-M1W lavalier is a White 3.5mm plug-in powered microphone with a 4.1\u2019 cable. Designed as a replacement lavalier for the Saramonic Blink 500 and Blink 500 Pro Snow White wireless systems. It also works perfectly with other wireless transmitters, recorders, as well as cameras. It is also a great addition to any other brand\u2019s wireless systems with 3.5mm inputs, when you need a white lav for weddings, worship services and when white clothing is used. Plug-in powered 3."}, {"role": "assistant", "content": "Price is $30.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCASEMATIX Hard Case Compatible with Pioneer DJ Controller DDJ FLX4 Rekordbox 400 With Room For Cables, Adapters for DJ Controllers and Mixer Accessories, Includes Shoulder Strap, Mixer Not Included\nUltimate DJ Controller Case For Mixers - This premium casematix Travel Case features a dense, hard shell EVA exterior that will protect your precious DJ board from scratches, drops, dings and impacts. Provides portable decksaver protection Internal Foam Holds Down Mixer With Side Storage For Cables - This mixer Carrying Case features top and bottom layers of convoluted, shock-absorbing foam protection. Your controller will be safely secured between those two layers of protective foam. Larger Design Fits The Mixer With Space For Accessories - Featuring a built-in carry handle, adjustable shoulder strap and external"}, {"role": "assistant", "content": "Price is $64.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWasher Suspension Kit Compatible with Some Whirlpool Maytag Kenmore Amana Washing Machines,\nPackage includes This washing machine suspension rods kit includes 4 suspension rods, 4 suspension balls and 4 bushings. Suspension rod length 23.6in Compatible with many models This suspension rod kit is compatible with most Whirlpool, Maytag, kenmore, Amana, Admiral, Crosley and Roper. It is compatible with etc. For more compatible models, please see picture 7. If you can't find your machine model, you can email us and we will help you confirm it. Replaceable suspension rod There are many types of suspension rods that can be replaced by this washer suspension kit, such as etc. Can fix your washing machine's problems When the washing machine has large"}, {"role": "assistant", "content": "Price is $37.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPRS SE Standard 24 - Vintage Cherry\nPlayability, Tone, Looks, Affordability This PRS Has It All Solidbody Electric Guitar with Mahogany Body Vibrato Bridge - Vintage Cherry Rosewood Fingerboard 2 Humbucking Pickups Maple Neck Weight 12.41 pounds, Dimensions 44.02 x 15.98 x 5.98 inches, model number ST4VC, Rank Musical Instruments 19432, Solid Body Electric Guitars 128, Is Discontinued No, Available May 3, 2021, Back Material Mahogany Wood, Body Material Rosewood, Color Name Vintage Cherry, Fretboard Material Rosewood, Guitar Pickup Configuration H, Scale Length 25 Inches, String Material Nickel, Top Material Maple Wood, Rosewood, Mahogany Wood"}, {"role": "assistant", "content": "Price is $649.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nOriGlam Piano Keyboard Cover, Keyboard Dust Cover, Anti-Dust Cover Key Cover Cloth for 88 Keys Electronic Keyboard, Digital Piano, Yamaha, Casio, Roland, Consoles\nFeatures Color Black Material Nylon + Cotton Black soft piano keyboard cover. Protect your keyboard from dust, while adding an attractive style to your piano. Dampproofing function. Suit for any 88 key piano or keyboard. Package Weight 1.55 Ounces Package Dimensions (L*W*H) Inches Package Include 1 x Piano Key Cover \u221a Ultra-Premium Protection - Introduce a breathable layer to keep your keyboard clean and safe against all the dust, dirt, or wear. And enjoy the extended lifetime of your instruments. \u221a Supreme Material - Makes your instrument more elegant and brings better durability"}, {"role": "assistant", "content": "Price is $8.08"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSeismic Audio - - Lightweight 4 Space Compact ABS Rack Case - 4U PA DJ Amp Effects Shallow Rack Case\nSeismic Audio's line of\u00e2\u0080\u009a\u00c2 lightweight ABS Rack Cases offer the perfect solution to ensure all of your Pro Audio and DJ Rack gear is protected and secure. These 4 Space Rack Cases are made of lightweight polyethylene with\u00e2\u0080\u009a\u00c2 aluminum rails and finishes, making carrying your gear easier. These racks offer excellent protection of anything that is mounted in them. The shallow design is great for smaller gear and devices like wireless mics, preamps, etc.\u00e2\u0080\u009a\u00c2 These 4U Racks are 8 inches deep,\u00e2\u0080\u009a\u00c2have standard 19 mounting rails, spring loaded handles, sturdy butterfly latches and rack screws are"}, {"role": "assistant", "content": "Price is $145.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSKB Custom Fit Waterproof Equipment Case for Zoom H4N Stereo Digital Recorder\nThis military-standard waterproof hard case was specifically designed for the Zoom H4N recorders. The interior is custom cut ELE foam that includes pockets for the recorder, power supply, wind screens, memory cards and other accessories. Anyone that uses Zoom H4N recorders will find themselves in the elements. This is the only way to protect your recorder and related accessories from rain and dust, states Steph Maffei, SKB Product Manager. Our ability to customize the interior using our water jet foam cutting machine provides precise pockets that provide maximum protection in transport. Not only does the SKB Zoom H4N case provide the ultimate protection for recorders it is backed by SKB. SKB's iSeries injection molded"}, {"role": "assistant", "content": "Price is $87.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWasher Drain Pump Motor Assembly Replacement for Whirlpool Washing Machine - Compatible with 850024 Water Pump Assembly - UpStart Components Brand\nUpStart Components Replacement Washer Drain Pump Motor Assembly for Whirlpool Washing MachinePlease note This is an UpStart Components Brand replacement part, NOT an OEM product. All mentions of brand names or model descriptions are made strictly to illustrate compatibility. All brand names and logos are registered trademarks of their respective owners. This product is not affiliated with any brands and is not covered under any warranties offered by the original manufacturers. Any warranties for this product are offered solely by UpStart Components. UpStart Components Replacement Washer Drain Pump Motor Assembly for Whirlpool Washing Machine Ultra durable, high quality material resists wear and tear over time. Easy at-home installation. An affordable way to"}, {"role": "assistant", "content": "Price is $33.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAlhambra 6 String Classical Guitar, Right, Solid Canadian Cedar,\nIberia you understand right away what\u2019s it all about the Spanish sound at your finger tips! Not only the sound is different - but as you take it you notice the top is made of high quality cedar. A lush rosewood headstock, Rosewood fingerboard, Gold plated tuners, and sericite back and sides, give this guitar a classy and elegance look. Solid Canadian Cedar top with rosewood Binding, high gloss natural finish Sericite back & sides Rosewood Fingerboard, Mahogany neck, 650mm radius Gold Plated machine heads & D 'Addario strings Gig Bag included Weight 4.2 pounds, Dimensions 47 x 6.5 x 21.25 inches"}, {"role": "assistant", "content": "Price is $899.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCoffee Filters for Cold Brew Maker - Reusable Coffee Filter Replacement for Cold Brew System\nAlocs cold brew coffee filters are designed specifically for cold brew system, traping sediment and fines and extracting all the natural and delicious flavors of coffee and tea, and leaving behind the bitter acids and oils attached to their warm brew counterparts to give you a fresh, flavorful glass of cold brew. Our coffee filters are washable and reusable kits mading of quality polypropylene. You can clean simply requires rinsing under running water to remove any residue, squeezing off any moisture, and storing in an airtight container in your refrigerator or freezer in between uses. Package Includes 10 x reusable coffee filters replacements Usage Suggestions Coffee filters are suggested to be changed after 10 to 12 uses or after three months, whichever"}, {"role": "assistant", "content": "Price is $11.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMusiclily Pro 52.5mm Style Guitar Tremolo Bridge Short Block for Squier Strat Electric Guitar, Chrome\nMusiclily Pro 52.5mm Style Guitar Tremolo Bridge Short Block for Squier Strat Electric Guitar, Chrome. Good replacement for many Squier Strat, also fits some import Asian made guitar, please check your guitar size before you buy String spacing 52.5mm ), stud spacing to ), stud outside diameter 10mm (25/64 ) 10.5mm wide modern style zinc saddles. Standard Squier style thin zinc block, 36mm tall, it will fit thin body Squier strat like Bullet and Affinity series Thread-in style tremolo arm, full metal made, just like stocked Squier one Includes full set of bridge and mounting"}, {"role": "assistant", "content": "Price is $23.29"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nRIYIN Ligature for Wooden Plastic or Rubber Soprano Saxophone Mouthpiece\nSturdy and dependable. Great protection for your mouthpiece and reed without the major cost. Fits all standard hard rubber and plastic standard Soprano sax mouthpieces, it can't fits metal mouthpieces. Screws adjust. Provide a great sound with wonderful flexibility. Great protection for your Soprano mouthpiece Sturdy and dependable. Great protection for your mouthpiece and reed without the major cost. Fits all standard hard rubber and plastic standard Soprano sax mouthpieces, it can't fits metal mouthpieces. Weight 4.2 ounces, Dimensions 5 x 2 x 2 inches, Rank Musical Instruments Soprano Saxophones Mouthpieces 56, Is Discontinued No"}, {"role": "assistant", "content": "Price is $19.77"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSaxophone Universal Saxophone Sax Neck Joint Cork Sheet Instrument Accessories\nSpecification Condition 100% Brand New Item Type Instrument Accessory Material Cork Suitable for Saxophone Size Approx. 60 * 40 * 2mm / 2.4 * 1.6 * Weight Approx. 11g Package Include 10 x Saxophone Cork Universal Great neck tenor cork Compatible with All saxophone.You can buy it with confidence. Universal Great neck tenor cork Compatible with All saxophone.You can buy it with confidence. Universal Great neck tenor cork Compatible with All saxophone.You can buy it with confidence. Universal Great neck tenor cork Compatible with All saxophone.You can buy it with confidence. Universal Great neck tenor cork Compatible with All saxophone.You can buy it with confidence. Flex"}, {"role": "assistant", "content": "Price is $11.92"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMaxblue MWF Refrigerator Water Filter, Replacement for GE\u00ae Smart Water MWF, MWFINT, MWFP, MWFA, GWF, HDX FMG-1, Kenmore 9991, 1 Filter\nMaxblue refrigerator water filter not only features prior filtration performance but also certified by authority NSF 42 and 372 for lead-free. GE is a registered trademark of General Electric Company. GE is used for reference purposes only. Brilliant filtration The filter can reduce a wide range of harmful substances in water including heavy metals, chlorine, odor, THM, VOCs, particles, cadmium, and all other major impurities, which has been tested by an independent third-party laboratory. Perfect fit Our professional research team make effort to produce perfect fit refrigerator filters with exquisite engineering"}, {"role": "assistant", "content": "Price is $16.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPyle Professional Wireless DJ Audio Mixer - Bluetooth DJ Controller Sound Mixer w/USB Audio Interface, Combo Jack Microphone/Guitar 3.5mm Stereo In, Headphone Jack -\nFeatures - Ultra-low Noise Design with High Headroom - USB Sound Card/Audio Interface, for Computer Playing & Recording - Combo Jack for MIC/LINE/GUITAR Inputs - Independent 3.5mm Stereo Input Jack - Flexible Connectivity for a Variety of External Devices - 6.35mm Jacks for Stereo Input and Output - 6.35mm Jack for Earphone Monitor Output - +48V Phantom Power - DC 5V Power Supply, or PC Power Supply - Rugged Metal Chassis Bluetooth Connectivity - Instantly Receives Wireless Music Streaming Audio - Works with All of Your Favorite Devices - ("}, {"role": "assistant", "content": "Price is $53.18"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJJ EL34 Burned In Vacuum Tube, Apex Matched Quad\nJJ Tubes are known for known for their high quality, durability, and their excellence in tone. Formerly produced by Tesla, JJ tubes are still made to exacting standards. They work well in all applications. High Quality EL34 Replacement Tube Burned In For Maximum Stability And Performance Superior JJ Quality Matched Quad Weight 9.1 ounces, Dimensions 7 x 5 x 7 inches, model number Rank Musical Instruments 36284, Guitar Amplifier Tubes 94, Is Discontinued No, Available November 18, 2010, Color Name Matched Quad, Brand JJ Electronic, Color Matched Quad, Dimensions LxWxH 7 x 5 x 7 inches"}, {"role": "assistant", "content": "Price is $146.19"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGENUINE Frigidaire Cooling Fan Range/Stove/Oven\nProduct Description This is a genuine replacement part. The model number and name for the following item is Cooling Fan Frigidaire motor. From the Manufacturer This is a genuine replacement part. The model number and name for the following item is Cooling Fan Frigidaire motor Manufacturer Model Genuine Replacement Part Frigidaire item Brand name FRIGIDAIRE Brand Name Frigidaire, Model Info Weight 1.8 pounds, Dimensions 9.63 x 5.06 x 9.56 inches, model number Is Discontinued No, Part Wattage 7.3 watts, Certification Certified frustration-free, Rank Tools & Home Improvement Oven Parts & Accessories 706, Domestic Shipping can be shipped within U.S.,"}, {"role": "assistant", "content": "Price is $98.40"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nNew Judaica Oil 13 Anointing Silver Rams Shofar From the Holy Land\nAmazing 13 Anointing Silver Rams Shofar Made of a natural Rams Horn. A sterling silver plated Rams Horn shofar specially designed for holding anointing oil with a seal on one end and strap for holding. One side of the shofar with Star of David and the other side with Menorah. The shofar is mentioned frequently in the Hebrew Bible, the Talmud and rabbinic literature. The blast of a shofar emanating from the thick cloud on Mount Sinai made the Israelites tremble in awe (Exodus 19, 20). The shofar was used in to announce holidays (Ps. lxxxi. 4),"}, {"role": "assistant", "content": "Price is $95.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJo Ral TPT-2A Aluminum Trumpet Bubble Mute\nThe bubble mute produces a distinctive sound with a louder buzz factor making it especially exciting for jazz musicians. Produces a distinctive sound with a louder buzz factor making it especially exciting for jazz musicians Create an exciting tonal quality that results in near-perfect intonation Crafted from aluminum, for a brighter tone, or from copper for a more mellow sound Designed and tested to perform evenly in all registers Unique cork pads and some feature felt caps to prevent scratching the instrument Weight 0.5 Pounds, Dimensions 5 x 5 x 9.25 inches, model number Rank Musical Instruments 15263, Trumpet Mutes 19, Is Discontinued No, Available December 19, 2006, Color Name"}, {"role": "assistant", "content": "Price is $60.06"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDrain Pump Compatible With Frigidaire Washers\nCompatible with the following brands Frigidaire brands including Frigidaire, Electrolux, Frigidaire, Gibson, Kelvinator, Westinghouse and Kenmore (Model Specific). Drain Pump. High Quality Replacement Part. 90 Day Manufacturer Warranty. Compatible with the following brands Frigidaire brands including Frigidaire, Electrolux, Frigidaire, Gibson, Kelvinator, Westinghouse and Kenmore (Model Specific). Drain Pump. High Quality Replacement Part. 90 Day Manufacturer Warranty. Manufacturer Midwest Appliance Parts, Part model number Style Drain Pump, Material Other, Power Source Ac/dc, Quantity 1, Rank Tools & Home Improvement Clothes Washer Replacement Drain Pumps 2808,"}, {"role": "assistant", "content": "Price is $59.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLilydrip coffee dripper transformer brewer filter paper inverter fit for V60 coffee brewer set\nWhen Lily is 3, she likes watching Daddy brewing coffee. One day when her Daddy was brewing coffee, Lily dropped a glass ball into the dripper, she said It will make a better coffee.. After brewed with a glass ball inside the dripper, the Daddy invented this little bullet. It was named LilyDrip. LilyDrip works with cone shape dripper. It modified the depth of grounds -50% and working filter area +100%. Therefore less duplicate extraction and less clogging, more recipe become available and the result is very consistent. Since 2017, LilyDrip provided support to hundreds of competitors all around the world, from national brewing competition to"}, {"role": "assistant", "content": "Price is $29.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nEmpava 24 Single Gas Wall Oven Bake Broil Rotisserie Functions with Digital Timer and Convection Fan in Stainless Steel\nThe Empava 24 inch 2.3 Cu. Ft. Single Gas Wall Oven with the CSA Certified is a Perfect Combination of Style and Practicality. The Exterior Features Stainless Steel Construction for Long-lasting Durability, with the Color-Matched Handle and Knobs combine together, Constructing a Fashion Sense. With Ample Cooking Capacity - 2.3 Cu. Ft., 5 Adjustable Rack Position to Accommodate a Various Size of Food Items. The 13,600 BTU Oven Includes Bake, Broil and Rotisserie Function, with a Convection Fan Takes Built-In Cooking to a New Level of Excellence. The Large Oven Window and Interior Light"}, {"role": "assistant", "content": "Price is $782.13"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPtzizi I Couldn\u2019t Pick A Better Brother, Stainless Steel Guitar Picks Jewelry for Guitar Player Musician Brother Friends Birthday Christmas Graduation Gifts\nThis guitar pick make great gifts for any occasion, surprise your love with this great lovely gift, and show how much he means to you. Perfect Gifts This guitar pick make great gifts for any occasion, surprise your love with this great lovely gift, and show how much he means to you. Size Approx 1.4'' in length; 1.12'' in width; 1.5 mm in thickness. Material Made of high quality stainless steel. Sturdy and durable. It is lead free and nickel free, No Rust, No Allergy, No Fading, No Deformation. Festival Gifts it can be give in birthday gifts, anniversary"}, {"role": "assistant", "content": "Price is $9.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nProX Cases 12 Space 10U Top Load Slant DJ Mixer - Road Gig Ready Flight Combo Rack w/Gliding Laptop Shelf\nPro X Cases 10U vertical rack, 10U slant mixer rack system has all the best features you're looking for in a world-class flight case strength, durability and reliability with flexible options and sizing for different applications. This heavy-duty professional combo rack is 19 deep and features 4U front loading and 10U top loading rails for convenient security for a wide variety of pro DJ mixers. Other design highlights include a large swinging rear door (for easy wiring) with a beveled cable hole for permanent or semi-permanent installation. It also includes two handles on either side of the case for convenient transportation. This case also includes a"}, {"role": "assistant", "content": "Price is $448.33"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWholesale Sensors Replacement for Pentair 075173 Fusible Link Thermal Cut-Off for Pool & Spa Month Warranty\nReplacement 075173 Fusible Link Thermal Cut-Off with 12 Month Warranty. This part is not made by Pentair. This is a high quality replacement. 12 Month Manufacturers Warranty Made in the USA - Creating jobs in America Replacement for Pentair 075173 Fusible Link Cut-off Fits Pentair MiniMax CH, NT STD, NT LN, NT TSI, NT TSI pool and spa heater models 150 IID, 150, 200, 250, 300, 350, 400 Also fits Pentair MiniMax Plus, PowerMax pool and spa heater models 75, 100, 150, 200, 250, "}, {"role": "assistant", "content": "Price is $12.85"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAudioblast - 3 Units - 40 Foot - HQ-1 - Ultra Flexible - Dual Shielded (100%) - Guitar Instrument Effects Pedal Patch Cable w/ Eminence Straight & Angled Gold \u00bc inch TS Plugs & Double Boots\n3 Units - 40 Foot - Audioblast HQ-1 - BRAID - Flexible - Dual Shielded (100%) - Guitar Bass Effects Instrument, Professional Patch Cable with Eminence E119 Angled and E120 Straight Gold plated 1/4 inch 2-Pole Straight TS Connectors. Staggered hand assembled Double Boot protects the cable from damage by handling stresses. The Most-Flexible, Hand-Assembled Braided Cable in the Market with Ultra-Soft, Easy to Coil, Extremely Durable Polyester Braid"}, {"role": "assistant", "content": "Price is $52.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMOTU Micro Lite USB MIDI Interface\nFrom the Manufacturer Built from the same technology found in MOTU's flagship MIDI Timepiece, the micro lite is a professional MIDI interface that provides portable, plug-and-play connectivity to any USB-equipped Macintosh or Windows computer. The micro lite provides 5 MIDI IN, 5 MIDI OUT, 80 MIDI channels and compatibility with all Macintosh and Windows software. Large front-panel LEDs illuminate to indicate MIDI activity. The micro lite takes full advantage of USB, giving you high-speed MIDI throughput, sub-millisecond timing accuracy, support for hot-swapping and plug-and-play expansion. Need to connect another sound module or synth? No problem. Just add another MOTU USB MIDI interface via any available USB port. And the micro lite is powered by the USB port"}, {"role": "assistant", "content": "Price is $135.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nEaton WD1212 50-Amp 3-Pole 4-Wire Surface Mount Range Power Receptacle, Black\nThe Eaton Wiring Device WD1212 50-Amp Surface Range Power Receptacle has a heavy duty design and construction that is ideal for any high amperage industrial and commercial power connectivity application. This surface receptacle features heavy gauged galvanized steel mounting strap and a glass reinforced nylon body. This heavy-duty non-grounding application has features and a NEMA standard of 14-50R with This surface receptacle has a patented lay-in terminal that allows it to except wire up to #4 on the American Wire Gauge (AWG). Its back features concentric knockouts and an adjustable cord clamp to allow wiring from the back and bottom to fit"}, {"role": "assistant", "content": "Price is $18.30"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nReplacement for Whirlpool Refrigerator Water Filter - Compatible with Whirlpool Fridge Water Filter Cartridge\nThis is a Denali Pure Brand replacement part, NOT an OEM product. All mentions of brand names or model descriptions are made strictly to illustrate compatibility. All brand names and logos are registered trademarks of their respective owners. This product is not affiliated with any OEM brands and is not covered under any warranties offered by the original manufacturers. Any warranties for this product are offered solely by Denali Pure. Replacement for Filter Manufacturer Denali Pure, model number Rank Tools & Home Improvement In-Refrigerator Water Filters 3106, Is Discontinued No, Available May 27, 2015, Duration 6 \\tmonths, External Testing Certification ANSI, NSF, WQA, Brand Upstart"}, {"role": "assistant", "content": "Price is $12.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSummit Appliance 24 Wide Built-In Dishwasher, Black, ADA Compliant, Quite Performance, Touch Controls, Digital Display, Top Control Panel, Stainless Steel Interior, 8 Wash Programs\nSummit Appliance 24 Wide Built-In Dishwasher, Black, ADA Compliant, Quite Performance, Touch Controls, Digital Display, Top Control Panel, Stainless Steel Interior, 8 Wash Programs Model is a 24 wide dishwasher sized at 32.25 high for an easy fit under lower ADA compliant counters. The leveling legs allow you to raise the height up to 34. We include an extra kickplate that covers the front for a cleaner look and to help prevent dirt from going under the unit. The controls are located on top of the door, making it easier to create a more seamless"}, {"role": "assistant", "content": "Price is $862.49"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPitco Control Box Assembly\nProduct Description CONTROL BOX, ASSEMBLY. Pitco Genuine OEM replacement part. Pitco has been producing industry-leading frying equipment with a track record of excellence. Use genuine OEM parts for safety reliability and performance. From the Manufacturer CONTROL BOX, ASSEMBLY. Pitco Genuine OEM replacement part. Pitco has been producing industry-leading frying equipment with a track record of excellence. Use genuine OEM parts for safety reliability and performance. Genuine OEM replacement part Pitco has been producing industry-leading frying equipment with a track record of excellence Use genuine OEM parts for safety reliability and performance Package dimensions 5.0 L x 9.0 W x 9.0 H Manufacturer Prtst, Part Weight 1.1 pounds, Dimensions 5 x 9 x "}, {"role": "assistant", "content": "Price is $780.65"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n20 to 22 Gongs on the Spirit Guide Gong Stand - 22 Atlantis Gong/Includes Gong, Mallet, & Stand/Great for Office & Home/Traditional Style\nThis listing includes the gong of your choice, gong stand, and a matching stained mallet. The Spirit Guide Wood Gong Stand is stained a rich dark brown with hints of red.A Spirit Guide is a spirit like you, who currently does not have a body. Their job is to guide you in one or more sections of your life. Let your Spirit Guide lead you to the perfect gong stand for your home or office. This stand is easily assembled and sturdy as it guides the energy of your room directly to your gong. It is great for end tables, dressers, and meditation nooks. When"}, {"role": "assistant", "content": "Price is $517.20"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nJiayouy 6 Pack Rubber Clarinet Thumb Rest Cushion Protector for Oboe Clarinet Instruments 6 Color\nDescription Easy to install, stable and comfortable, not falling. Soft and durable, helps to maintain the correct finger position. It can solve the problem of finger fatigue, discomfort. Provides extra thumb rest and protects your instrument and hands. Application Suit for most Clarinet and Oboes. Specifications Thumb Rest Size approx 2.2 x 2cm Color Yellow/ Pink/ Purple/ Blue/ Black/ White Material Rubber Quantity 6pc Package include 1 x Thumb Rest Cushion set Rubber material clarinet thumb rest cushion which is not only soft and comfortable when used, but also non-toxic, environmentally friendly. Provides extra thumb rest and helps maintain correct finger"}, {"role": "assistant", "content": "Price is $6.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGE Appliances Dishwasher Circulation Pump Assembly\nDishwasher Circulation Pump Assembly (part number is a Genuine GE replacement part. For more than 100 years, GE Appliances has been a trusted brand, synonymous with quality and reliability. To continue earning your trust, our appliances and parts are engineered to precise specifications and subjected to rigorous testing. Behind every GE Appliances product is the work of thousands of dedicated Americans committed to excellence as well as a better future for our communities and our environment. This circulation pump assembly (part number is for dishwashers Circulation pump assembly delivers water to the spray arms to clean your dishes The assembly may include multiple parts. Refer to your parts diagram for a list of parts included Unplug the dishwasher or shut off the house circuit breaker before installing this part Genuine GE replacement part"}, {"role": "assistant", "content": "Price is $132.54"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFlute Fingering Chart with Color-Coded Notes, Learn Flute Technique Suitable for All Levels, Made in the USA\nFLUTE FINGERING CHART Memorizing the notes on the flute can be daunting at first. Learn flute technique and master the flute with this fingering chart for all levels. COLOR-CODED NOTES This flute fingering chart features color-coded notes to help beginners remember the finger positions. The easy-to-follow design makes this flute fingering chart convenient, especially for visual learners. LONG-LASTING MATERIALS We laminated this flute fingering chart so that it will last you longer even after constant use. With a slightly oversized yet still portable design, this chart measures LEARN FLUTE TECHNIQUE If you want to learn how to play the flute, this fingering"}, {"role": "assistant", "content": "Price is $12.95"}]} \ No newline at end of file diff --git a/week6/community-contributions/kwabena/fine_tune_validation.jsonl b/week6/community-contributions/kwabena/fine_tune_validation.jsonl new file mode 100644 index 0000000..c209355 --- /dev/null +++ b/week6/community-contributions/kwabena/fine_tune_validation.jsonl @@ -0,0 +1,50 @@ +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSupplying Demand Electric Range Cooktop 9 Inch Dual Radiant Surface Element Replacement Model Specific Not Universal\nPlease see Model Number fitment information at the bottom of this page before placing your order for this part. Alternate part numbers include and 240V | Watts | Instructions included | Fits model specific electric ranges It is important to disconnect your appliance from the power supply before servicing. From the manufacturer Cracks in the ring are cosmetic and acceptable. The ring is made from compressed material bound with fibers, so it will perform the same. Supplying Demand replacement parts are compatible with Major Brands, but you should always verify fitment with your specific model. We have included a video in the product gallery to help you find your model number and information in the description below. SD products come in Supplying Demand packaging"}, {"role": "assistant", "content": "Price is $59.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nInnovative Percussion GT-2 General Series Timpani Mallets (Medium Soft, General)\nThe general Timpani series is the latest addition to our selection of Tim pan I mallets. After many requests from percussion educators and performers, The GT Series was designed as another quality choice from Innovative Percussion. These models feature tapered maple handles for ultimate balance and German felt parachute-style covered heads for professional grade sound quality.Features tapered maple handles wood cores high quality German felt covers woven felt liners (models 1-4). Country of Origin UNITED STATES The Package Length of the Product is 50.8 centimeters The Package Width of the Product is 0.254 centimeters The Package Height of the Product is 19.812 centimeters Weight 0.25 Pounds,"}, {"role": "assistant", "content": "Price is $43.20"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFriedman Amplification Buxom Boost Guitar Effects Pedal\nThe Friedman Buxom Boost may be the most powerful tonal solution you ever put on your pedalboard. Like its namesake amp head, this pedal pushes a pure, clean signal to conjure the absolute most from your tone. Turning the boost control is your ticket to volume increase, pushing the front of your amp for thick harmonic overdrive, or balancing between two guitars with varying output. Whether you're after a tone tailored by its active mid, treble, and bass controls or the pedal's ability to achieve total transparency - thanks to its onboard EQ Bypass switch - it's all in there. We've even added a useful tight control for reigning in your tube amp's bottom end when boosted. As expected, every"}, {"role": "assistant", "content": "Price is $169.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWhirlpool Bimetal Fuse for Dishwasher\nProduct Description This is a genuine replacement part. The model number and name for the following item is Whirlpool Bimetal Fuse for Dishwasher From the Manufacturer Whirlpool Bimetal Fuse for Dishwasher. Works with the following model Maytag Part Number Genuine Replacement Part. This product is a Factory Certified Part. These three words represent quality parts and accessories designed specifically for your appliance. Time tested engineering that meets our strict quality specifications Package contains (1) Dishwasher Thermal Fuse Kit Multi screwdriver, wire cutters, and torque 1 screwdriver needed for installation One Year Limited Part Warranty This part is a replacement for the following part number This is a GENUINE ORIGINAL Whirlpool replacement part. Don't settle for lower quality aftermarket"}, {"role": "assistant", "content": "Price is $18.74"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLovermusic 7 Tone Wood Instrument Energy Chime with Mallet & 7 Tubes Wooden Collection Percussion Accessories\nFeatures 1.The long-lasting echo is perfect for yoga, mindfulness and sound therapy, and can be coordinated with your improvisations for a better experience. 2.With a simple tap of a mallet, this handheld chime emits a powerful, constant sound that inspires, entertains and entertains people of all ages. 3.The chime makes a crisp sound when tapped, making it the perfect musical initiation tool, as a gift for a friend, in the classroom or in your daily practice. 4.Calm your mind or adjust the attention of the group, the resonant sound can not only calm and adjust the attention of individuals, but also adjust the attention of the"}, {"role": "assistant", "content": "Price is $23.58"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nShure C25B Heavy-Duty Cable XLR Connector on Microphone End, Black\nHeavy-duty, 25 foot (7.5 m), balanced cable for low-impedance operation. Features black connector on microphone end for low visibility. Heavy-duty, 25 foot (7.5 m), balanced cable for low-impedance operation. Features black connector on microphone end for low visibility The package length of the product is inches The package width of the product is inches The package height of the product is inches Brand Shure, Connector Type XLR, Cable Type XLR, Compatible Devices Microphone, Color Black, Connector Gender Male-to-Male, Shape Round, Unit Count 1.00 Count, Headphones Jack Xlr, Indoor/Outdoor Usage Outdoor, Indoor,"}, {"role": "assistant", "content": "Price is $29.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCecilio MM-CBlue Traditional Wind Up Mechanical Pyramid Shape Pendulum Metronome with Bell\nThis is a traditional wind up mechanical metronome featuring beats per minute starting from 40 bpm to 208 bpm and 0 to 6 bell beats. Color Solid clear blue with clear cover Tempo Range Grave 40 bpm to Prestissimo 208 bpm, Clockwork motor with click Downbeat bell off, 2, 3, 4, or 6 beats Wind up switch, No batteries required Dimension 5 x 5.5 x 9.5 Weight 1.25 pounds, Dimensions 9 x 5 x 5.4 inches, Domestic Shipping can be shipped within U.S., International Shipping This item can be shipped to select countries outside of the U.S"}, {"role": "assistant", "content": "Price is $39.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWhirlpool Fuse\nProduct Description This is a genuine replacement part. The model number and name for the following item is Whirlpool Fuse From the Manufacturer This is a genuine replacement part. The model number and name for the following item is Whirlpool Fuse This is an O.E.M. Authorized part Fits with various whirlpool brand models Oem part # Refer comparison chart for compatibility manufacturer model # Genuine Replacement Part H and H Manufacturing item Replaces part number Manufacturer Whirlpool, Part Weight 1.51 ounces, Dimensions 1.5 x 2.5 x 3.5 inches, model number Is Discontinued No, Quantity 1, Rank Tools & Home Improvement Parts & Accessories 79804, Available August 2, 2013"}, {"role": "assistant", "content": "Price is $18.40"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHermitshell Hard Travel Case for Numark Party Mix Starter DJ Controller\nHermitshell Hard Travel Case for Numark Party Mix Starter DJ Controller Hermitshell Hard Travel Storage Carrying Case Protect your favorite device from bumps dents and scratches Made to fit Numark Party Mix Starter DJ Controller Material EVA\uff1bColor Black; Outter Size inch For Sale is Case Only (Device and Accessories are Sold separately) Weight 1.18 pounds, Dimensions 14.06 x 10.98 x 3.43 inches, Rank Musical Instruments 11826, DJ Controllers 37, Is Discontinued No, Available January 16, 2019, Material Type Ethylene Vinyl Acetate (EVA), Brand Hermitshell, Material Ethylene Vinyl Acetate (EVA),"}, {"role": "assistant", "content": "Price is $17.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSTRETTO 1020 Humidifier for Violin, Viola and Small Instruments incl. Case, 2 humid Bags and with Hygrometer\nSTRETTO 1020 Humidifier for Violin, Viola and Small Instruments incl. Case, 2 humid bags and WITH DIGITAL HYGROMETER. The STRETTO system evenly releases humidity over time with easy to use microfiber hydration pouches. The container is being attached to the inside of the case. Including humidifier, 2 humid bags and digital hygrometer. Made in Switzerland. Includes case and 2 humidification bags & DIGITAL HYGROMETER For Violin, Viola and small instruments One STRETTO HUMID BAG humidifies for up to two weeks Fits in to"}, {"role": "assistant", "content": "Price is $52.78"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nKyser Quick-Change Guitar Capo for guitars, Black, KG12B\nWith more strings, you need more tension and a larger body than the original Kyser Quick-Change capo. This Kyser Quick-Change capo is specifically designed for your guitar and is built to last. It is reliable and does just what it is designed to do \u2014 clearly raise the pitch of the guitar so you can play in a different key without retuning or changing fingering. Seasoned professionals and beginning players alike appreciate how the Kyser Quick-Change capo helps them transpose their guitar in seconds, with only one hand. The beauty of the Kyser Quick-Change capo is in its simplicity. Kyser pioneered this design and although often imitated, a Kyser is never equaled"}, {"role": "assistant", "content": "Price is $21.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDW Drum Set Rack Tom, Gloss Lacquer\nDesigned with seamless quality for a stylistic touch to your drum setup, the DW Design Tobacco Burst Tom delivers it all. With a Suspension Tom Mount (STM), the system allows your drum to vibrate freely throughout any environment with maximum resonance. The mount works without washers and grommets to efficiently hold the drum in place, making tuning the easiest it has ever been. Take your performance to the next level with a premium-sounding drum that features defining looks and durability to stand the test of time. Introduce this stand-alone drum as a new element to your band setup, and you will not regret it! Exclusively available with chrome standard triple-flange hoops that will give your drum a versatile sound Sets a new standard for quality drums"}, {"role": "assistant", "content": "Price is $259.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDecksaver Akai Force Cover (DS-PC-FORCE)\nEngineered in the UK specifically for the Akai professional force controller, a tough but lightweight polycarbonate shell protects from dust, liquid and accidental impact. Precision molded for an exact fit whilst accommodating cables, your Akai professional force can sit ready for operation. Slides straight into a flight case or protective bag ready for transportation. Shields delicate controls and internal components from damage at home, on the road and on stage. Engineered specifically for the Akai force Accommodates cables Shields delicate controls from damage on the road, at home or in the studio Protects your investment from dust and accidental impact Designed and engineered in the UK Weight 1.25 pounds, Dimensions 15 x 13.94 x 1."}, {"role": "assistant", "content": "Price is $81.06"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDishwasher Seal kit Replacement Compatible with Frigidaire, Includes Tub Gasket, Lower Seal, Splash Shield\nDishwasher Door Gasket. This part is approximately 73 long. The door gasket seals the gap between the opening to the dishwasher tub and the outer edge of the door. The Dishwasher Bottom Door Gasket helps prevent water from leaking out of the bottom edge of your dishwasher door by creating a watertight seal. This part is attached to the bottom of your dishwasher inner door panel. The water and chemicals can wear down the gasket and compromise the integrity of the seal. If the gasket is malfunctioning, the integrity of the door seal will be affected. The splash shield is used to prevent water from spraying past the door seal. If your dishwasher is leaking"}, {"role": "assistant", "content": "Price is $25.59"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDCOLOR Wireless Lavalier Microphone for iPhone, 35H Battery Life with Charging Case, Wireless Recording Device, Clip on Lapel Microphone for Video Recording Vlog\nDesign for iPhone The wireless lavalier microphone is compatible with iPhone the receiver has a lightning to plug in iPhone, then the transmitter will pairing automatically with your iPhone, no app or bluetooth need. True Wireless Microphone Unlike the other wired microphone, Dcolor wireless microphone separates the receiver from the transmitter, just plug the receiver in your iPhone and start recording video. It is compatible with all kinds of video recording App, such as Youtube TikTok. One-Click Hear Clear The microphone has 2 modes, the natural mode is suitable for the quiet environment, the noise cancelling mode is for a noisy environment. Click the M"}, {"role": "assistant", "content": "Price is $35.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nSummit Wide 230V Coil Electric Cooktop, Stainless-Steel Surface, Easy to Clean, Four Coil Burners Total 6000 Watts, Push-to-turn Solid Knobs, with Indicator Lights\nSummit Appliance 30 Wide 230V Electric Cooktop with Four Coil Elements and Stainless Steel Finish, Removable Chrome Drip Bowls, Black Matte Finish on Knobs, Indicator Lights Summit's collection of electric cooktops offers the perfect fit and finish for a variety of kitchen spaces. Sized at a traditional 30 wide, the is a 230V cooktop with four coil elements. The convenient layout puts a large 1800W burner in the front right side and rear left side, with two standard 1200W elements ensuring the perfect setup to cook multiple dishes with"}, {"role": "assistant", "content": "Price is $422.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nStore Indya Hand Painted Metal Tibetan Singing Bowl Set - 7 Inch Musical Instrument Chakra with Wooden Stick Mallet - For Meditation, Yoga, Spiritual Healing, and Stress Relief -Spiritual Gifts\n\u2705AUTHENTIC HAND PAINTED 7\u201d TIBETAN SINGING BOWL SET This high-quality handcrafted meditation bowl set includes a wooden striker. Dimensions Size 7 Inch Diameter 3.5 Inch high.Made out of finest quality of metal and comes with a hand carved wooden mallet. 8 LUCKY TIBETAN SYMBOLS etched inside the bowl & mantra hand-painted outside of the bowl.Plays easily and long lasting great sound. Helps to reduce stress, alter consciousness and create a deep sense of peace, well-being and better health"}, {"role": "assistant", "content": "Price is $24.40"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDunlop Joe Bonamassa Signature Crybaby Wah Pedal Bundle w/4 Free Cables!\nSave with this bundle. Package includes Dunlop Joe Bonamassa Signature Crybaby Wah Pedal Bundle w/4 Free Cables! Dunlop Joe Bonamassa Signature Crybaby Wah Pedal Whether he's blazing through the blues on his own or rocking with Black Country Communion, Joe Bonamassa's playing is fiery, deep, and powerful. And when he really wants to express himself in a solo, he steps on a Cry Baby wah. That's why we at Dunlop worked with Joe to develop the Joe Bonamassa Signature Cry Baby, specially engineered to fit in perfectly with Joe's system, from the way it looks to the way it sounds. On the outside, it"}, {"role": "assistant", "content": "Price is $199.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n1set Belcat BJ-70 4 String Bass Humbucker Double Coil Pickup Black for Bass Guitar\n100% new high quality and testing is fine Item 100% like the picture shown Brand Belcat Color black magnet ferrite & Ceramic D.C.Resistance 8.5k\u03a9 inductance 6.48H package included 1 x belcat 4 String Bass Humbucker Double Coil Pickup black Belcat is an OEM manufacturer that has developed a new product line with their own name on it. Their pedals are well built and produce an extremely clean sound. They are the best I have found any where near this price point. This item is sent from China,it will take 4-14 days from China to US! Brand Belcat Color black magnet ferrite & Ceramic Weight "}, {"role": "assistant", "content": "Price is $21.45"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nProtec Explorer Series Trumpet Bag with Sheet Music Pocket\nDesigned to meet the demands of Mobile musicians needing slim lightweight instrument protection with generous storage capacity, protec\u2019s Explorer bags feature thick 20mm padding, reinforced protection, sheet music pocket, & Built-in backpack straps. Fits most trumpet makes/ models and is designed for slim lightweight horn protection with generous storage capacity for sheet music, mutes, and other accessories Durable abrasion resistant nylon exterior with thick protective 20mm padding along with reinforced puncture resistant bell protection against damage Rear side sheet music pocket, spacious mute storage pocket, and accessory organizer pocket with built-in mouthpiece pouch Comfortable carrying handles with padded handle Wrap, subway handle, includes shoulder strap, and built-in backpack straps with tuck-away pocket Weight 2.45 pounds"}, {"role": "assistant", "content": "Price is $54.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLOT OF 2 - Ernie Ball RPS Super Slinky Electric Guitar Strings, Made USA, P02239\nProduct Information Individually boxed... new... never opened or used! Gauges 2 Sets of Strings A patented winding of bronze wire is tightly wrapped around the lock twist of the ball end of the plain strings. String slippage and breakage are minimized at the ball end where these most often occur. Plain strings in RPS sets last longer and stay in tune better than conventional plain strings. Wound strings are the same used in SLINKY NICKEL WOUND. 2 Sets of strings Gauges Made in the U.S.A String slippage and breakage are minimized at the ball end where these most often occur Weight 2.01 pounds, Dimensions"}, {"role": "assistant", "content": "Price is $16.98"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nRemo 8 Pretuned Tambourine with Single Row of Jingles, Plain Head\nAn economical tambourine, great for use in your home or classroom! 8 diameter tambourine with a fixed (pretuned) Fiberskyn 3\u00ae synthetic head. Black Quadura finish rim, with a single row of 8 pairs of jingles. Weight 1 Pounds, Dimensions 14 x 11 x 2 inches, model number Rank Musical Instruments 24257, Tambourines 167, Available July 16, 2004, Color Name Black,grey,silver, Material Type Fiberskyn, Color Black,grey,silver, Brand Remo, Material Fiberskyn, Dimensions LxWxH 14 x 11 x"}, {"role": "assistant", "content": "Price is $24.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMusiclily Pro 11.5mm Natural Paua Abalone Shell Diamonds Snowflake Guitar Fretboard Inlay Dots (Set of 10)\nMusiclily Pro 11.5mm Natural Paua Abalone Shell Diamonds Snowflake Guitar Fretboard Inlay Dots (Set of 10). Good for guitar fingerboards inlay job, like Martin style guitar Diameter 11.5mm (0.45 inch) square, thickness 2mm (0.08 inch) Genuine natural paua abalone shell material made, selected part to cut Correct, consistent color and thickness, easy to work with Package inlcudes 10 pieces inlay dots Weight 0.246 ounces, Dimensions 2.56 x 1.57 x 0.59"}, {"role": "assistant", "content": "Price is $11.84"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n4-Pack Gas Range Cooktop Burner Knob Replacement for Jenn-Air - Compatible with Top Burner Control Knob\n4-Pack UpStart Components Replacement Gas Range Cooktop Burner Knob for Jenn-Air note This is an UpStart Components Brand replacement part, NOT an OEM product. All mentions of brand names or model descriptions are made strictly to illustrate compatibility. All brand names and logos are registered trademarks of their respective owners. This product is not affiliated with any brands and is not covered under any warranties offered by the original manufacturers. Any warranties for this product are offered solely by UpStart Components. UpStart Components Replacement Gas Range Cooktop Burner Knob for Jenn-Air Quantity 4 Ultra durable, high quality material resists wear and tear over time. Easy at-home installation. An"}, {"role": "assistant", "content": "Price is $19.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGator Cases 4G Series Gig Bag For Mini Acoustic Guitars With Adjustable Backpack Straps;\nThe Gator Cases 4G Series gig-bag for mini acoustic guitars combines quality with affordability and protection! The features a durable nylon exterior with Gators gflex 20mm padding to prevent scratches and dings while transporting and storing your mini acoustic guitar. The 4G Series gig-bags feature a patent pending pick-clip zipper pull that holds a spare guitar pick, padded backpack straps with the contoured back padding for added comfort while carrying, as well as a durable reinforced carry handle. The Gator Cases 4G Series gig-bags also feature a generously large front pocket for storing guitar accessories such as guitar tuners, strings, cables, capos and other items."}, {"role": "assistant", "content": "Price is $69.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nK&M Tuba Stand\nThe K&M 19492 Instrument Stand Gig Bag is designed for tuba and baritone stands 14940 and 14941. It is designed as a black waterproof nylon carrying case and features a zipper and adjustable shoulder strap. The main features of the K&M 19492 Instrument Stand Gig Bag include Dimensions 350 x 110 x 110 Fastener zip fastener Handle or carrying type shoulder strap Material nylon Weight 0.18 kg Carrying case with adjustable shoulder strap Made of nylon Zip fastener Black, waterproof Measures 350 mm length by 110 mm width by 100 mm height Weight 6.3 ounces, Dimensions 19.29 x 3.54 x 2.76 inches, model number Rank Musical Instruments 56932, Brass"}, {"role": "assistant", "content": "Price is $38.16"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nYOUSHARES NTG4+ Microphone Windscreen - Windmuff for Rode NTG4 Plus Shotgun Microphones, Windshield Up to 6.3 Long\nYou must often shot stuff in high winds or light breezes. But the windy conditions outdoors can wreak havoc on our sound recording. You will be interested in our product, use our mic windscreen on every outdoor shoot where audio matters. Not only does the winshiled look great on the mic, but it also eliminates almost all wind noise. The windmuff went on easily, fit snugly and made a tight seal around the rear of the microphone. The wind screen has an acoustically transparent foam inner layer and artificial fur outer layer, with an airtight rubber base for wind protection. You will"}, {"role": "assistant", "content": "Price is $18.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nWalker & Williams M-41 Chestnut Brown Leather Mandolin Strap For A or F Types\nTraditional Mandolin Strap in Chestnut Brown Leather Loop for headstock or scroll fastening Suitable for A and F type mandolins Double reinforced endcaps Adjustable from 41-47 3/8 Wide and 1/8 Thick Weight 1.6 ounces, Dimensions 8 x 1 x 0.5 inches, model number M-41, Rank Musical Instruments 3051, Mandolin Accessories 5, Is Discontinued No, Available December 4, 2015, Color Name Brown, Strings 8, Material Type Leather, Musical Style bluegrass, folk, country, Size regular, Brand Walker & Williams, Color Brown, Dimensions LxWxH 8 x"}, {"role": "assistant", "content": "Price is $23.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nMilisten Wood Kazoo Kazoo Musical Instrument Ukulele Guitar Partner Guitar Accompany Wood Harmonica Flutes for Music Lover\nDescription Kazoo is a special wind instrument, made of safe and durable wooden materials. It is small and portable and can be placed in a pocket. It is easy to use. When playing kazoo, you don't necessarily have to learn music theory or sheet music. It is very suitable as an enlightening instrument for children. Features - Color Wood color- Material Wood- Size About 10. 00X3. 00X1. 00cm/ 3. 93X1. 18X0. 39inch Package Including 1 x Kazoo The structure is simple, no need to learn music theory, no need to recite"}, {"role": "assistant", "content": "Price is $11.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHal Leonard The Real Book Volume 1 - C Edition Bass Clef Edition\nThe Real Books are the best-selling jazz books of all time. Since the 1970s, musicians have trusted these volumes to get them through every gig, night after night. The problem is that the books were illegally produced and distributed, without any regard to copyright law, or royalties paid to the composers who created these musical masterpieces. Hal Leonard is very proud to present the first legitimate and legal editions of these books ever produced. You won't even notice the difference, other than all the notorious errors being fixed the covers and typeface look the same, the song list is nearly identical, and the price for this edition is even cheaper than the original. Every conscientious musician will appreciate that these books are now produced"}, {"role": "assistant", "content": "Price is $32.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nDenis Wick Silver-Plated Trumpet Mouthpiece\nDenis Wick Silver-Plated Trumpet Mouthpiece Slightly wider rim for better comfort V-type back bore for increased upper register support Open throat with medium deep cup for a full, round sound Designed by Maurice Murphy, all are customized from an old Tottle model Easier to play, have a fantastic high register and excel well at pianissimo Weight 0.27 Pounds, Dimensions 1.97 x 1.97 x 4.33 inches, model number Rank Musical Instruments Trumpet Mouthpieces 740, Is Discontinued No, Available July 16, 2004, Color Name Silver, Color Silver, Brand Denis Wick, Style Modern, Dimensions LxWxH 1.97 x 1"}, {"role": "assistant", "content": "Price is $85.98"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nOn-Stage UPK300 Felt Ukulele Picks, 3 Pack,White, blue, purple,Small\nProduct Description The UPK300 picks are precisely scaled for its precise/specific application The soft felt material is tough yet flexible and they feel great in your hand and produce exceptional sound on your ukulele, bass and other stringed instruments. Pack of three felt ukulele picks in various colors. Triangle shape measures 25mm x 30mm. From the Manufacturer Pack of three felt ukulele picks in various colors. These picks are precisely scaled for its precise/specific application The soft felt material is tough yet flexible and they feel great in your hand and produce exceptional sound on your ukulele, bass and other stringed instruments. UPK300 picks are precisely"}, {"role": "assistant", "content": "Price is $5.95"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGE Appliances Dishwasher Circulation Pump Assembly\nDishwasher Circulation Pump Assembly (part number is a Genuine GE replacement part. For more than 100 years, GE Appliances has been a trusted brand, synonymous with quality and reliability. To continue earning your trust, our appliances and parts are engineered to precise specifications and subjected to rigorous testing. Behind every GE Appliances product is the work of thousands of dedicated Americans committed to excellence as well as a better future for our communities and our environment. This circulation pump assembly (part number is for dishwashers Circulation pump assembly delivers water to the spray arms to clean your dishes The assembly may include multiple parts. Refer to your parts diagram for a list of parts included Unplug the dishwasher or shut off the house circuit breaker before installing this part Genuine GE replacement part"}, {"role": "assistant", "content": "Price is $105.53"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nForeverPRO Ice Maker Assembly for Samsung Appliance\nForeverPRO Appliance Ice Maker Assembly Fits Samsung Appliance. This is not a Samsung OEM product. Use of the Manufacturers trade names and logos are the registered trademarks of their respective owners. Any use of the Manufacturers brand name, part numbers or model designation for this product is made solely for purposes of demonstrating and for identification compatibility and are displayed for descriptive purposes only. Use of them does not associated with, imply any affiliation or endorsement by any manufacturer. \u2705 Easy to Install - Made Exactly to Fit For Most Top Brand Appliances \u2705 No Questions Asked Money Back Guarantee. Proud USA Based Company. Comes with 1 Year Warranty or 90 Day Returns \u2705 PRO Grade Premium Ice Maker Assembly - Meets or Exceeds OEM Specifications Quality. Comes Brand"}, {"role": "assistant", "content": "Price is $92.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nFrigidaire Igniter\nThe high quality Frigidaire Burner Igniter ) ignites the gas to light the oven burner. The Burner Igniter includes 2 ceramic wire connectors and replaces Please be aware that it is recommended to use saftey equipment and to disconnect the appliance from all utilities prior to any service or repair. Please refer to your owners manual to confirm part numbers and for instructions as some repairs require a trained service professional to complete. The Frigidaire Burner Igniter is a genuine OEM (Original Equipment Manufacturer) part designed and engineered to exact specifications Frigidaire Burner Igniter ignites the gas to light the oven burner Frigidaire includes 2 ceramic wire connectors The high quality Frigidaire Burner Igniter replaces With Fr"}, {"role": "assistant", "content": "Price is $68.23"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nNovation Impulse 49 Keys USB bus-powered MIDI Controller Keyboard \u2013 Robust, ultra-responsive, full-size piano keyboard with aftertouch and velocity-sensitive pads \u2013 works on Mac or Windows\nProduct Description Novation's Impulse is a range of professional USB/MIDI controllers. They each have a precision keyboard and a full control surface powered by a brand new version of Novation's Automap control software - Automap 4 (which makes getting hands-on with your DAW/plug-ins fast and simple). Impulse also has 8 back-lit drum pads which can warp arpeggios, roll beats and launch clips in Ableton live. Impulse, available with 25, 49 or 61 keys, gives you instant access to your DAW's mixer, transport, and"}, {"role": "assistant", "content": "Price is $299.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n9V Power Adapter fit for Casio Keyboard AD-5 AD-5MU WK-110 WK-200 LK-43 LK-100 CT-360 CasioTone Piano Keyboard Power Supply Cord\nPower Input Center Negative; Output 9V 2A 130mA, 250mA, 500mA, 650mA, 850mA, 2000mA / 9V Power Adapter fit for Casio Charger AD-5 AD-5MU AD-5MR AD-5EL AD-5GL Compatible with Casio keyboards Compatible with Casio keyboards ToneBank Mini CasioTone CT-460 Lantisri Lifelong friendly customer service. If you have any questions, please contact us and we 24Hrs in time after-sales service. Thank"}, {"role": "assistant", "content": "Price is $9.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHoly Voice Sterling Silver-Plated Jerusalem Decoration Ram Shofar 14 -16 With Shofar Stand, Carrying Bag, Brush & Anti-Odor Spray \u2013 Made in Israel.\nDecorate and Celebrate With Your Stunning Shofar The finest everyday items, ornaments, or instruments fill your heart as well as your home. Experience your spirituality and enhance your space with your decorative shofar from Holy Voice! Your traditional horn boasts breathtaking beauty thanks to its 925 sterling silver, 9k gold plating. Discover the perfect union of faith, fashion, and function in your exquisite, kosher shofar! Enjoy Every Premium Piece of Your Set Relish a set of superior quality! Based in Israel, we draw from ancient knowledge and modern technology to handcraft pieces that honor history"}, {"role": "assistant", "content": "Price is $79.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLG LT600P Refrigerator Water Filter, 3 Count (Pack of 1), White\nLG - 6 Month / 300 Gallon Capacity Replacement Refrigerator Water Filter (NSF42 and NSF53) or Provide cleaner, fresher and better tasting water and ice for your family Have peace of mind with nsf-certified lg filters that reduce contaminants Provides high-quality drinking water by removing contaminants like pesticides, chemicals, and detergents Removes 99.99% of cysts and almost all mercury, lead, and benzene Removes some herbacides and pharmaceuticals that can be found in water Genuine lg part or Filtration certification per nsf standards nsf42 and nsf53. Included components Filter, Instructions, and Warranty Material Plastic, Carbon, Dimensions 2."}, {"role": "assistant", "content": "Price is $131.97"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLatin Percussion Big Egg Shaker, Black\nLP\u2019s Big Egg Shakers are constructed with wipe-clean plastic and are approximately 3\u201d in diameter. They are filled with non-toxic steel shot and produce big shaker sound. Available in black and red. 3 Egg Shaker Constructed of wipe clean plastic Filled with non-toxic steel shot Great for loud playing situations Weight 4.5 ounces, Dimensions 5 x 4 x 4 inches, Country of Origin Taiwan, model number Rank Musical Instruments 25348, Hand Percussion Shakers 55, Is Discontinued No, Available April 15, 2017, Body Material plastic,steel, Color Name Black, Material Type Plastic, Musical Style All, Color Black, Brand Latin Percussion, Material Plastic,"}, {"role": "assistant", "content": "Price is $11.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nEpiphone J45 Solid Top Acoustic Guitar (Natural)\nSitka spruce top and luxurious appointments in an Epiphone guitar offered at a steal. From Epiphone comes this beautiful entry-level guitar, priced for anyone to afford. Dressed in a beautiful finish, and featuring appointments you'd often find on higher-end guitars, the Epiphone guitar sounds just as good as it looks. Built on advanced jumbo body design, the depth of the body and the width of the shoulders create a large sound chamber, presenting tone that is full, deep, and loud. The mahogany back and sides paired with a solid Sitka spruce top brings out rich harmonics, lots of projection, and clarity in tone. A glued-in dovetail neck joint keeps the Epiphone acoustic guitar's neck and body"}, {"role": "assistant", "content": "Price is $299.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nBlueridge Guitars 6 String Acoustic Guitar, Right, 000 Sitka Yellow\nBlueridge 000 style guitars are fast becoming the most popular guitar in its class. From folk to fingerstyle, the BR-143 is an example of a guitar that really does it all. The solid mahogany and spruce combined with the smaller body size make for a truly enjoyable\u2013and versatile guitar to play. Solid Sitka spruce top with scalloped braces gives you clean articulation and a crisp tone Solid mahogany back and sides for robust, warm resonance Slim mahogany neck offers fast, easy action and inherently long-lasting stability Quality natural bone nut and saddle for best tone transmission Every Blueridge now comes with an exclusive sturdy, padded Blueridge logo bag Weight 4"}, {"role": "assistant", "content": "Price is $860.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nGENUINE Whirlpool Timer - Washer\nProduct Description This is a Genuine Replacement Part,The Model Number and Name for the Following Item Whirlpool (WHIRA) Timer - Washer. From the Manufacturer This is a Genuine Replacement Part,The Model Number and Name for the Following Item Whirlpool (WHIRA) Timer - Washer Whirlpool (WHIRA) Genuine Replacement Part Appliance-replacement-parts Product is plastic Manufacturer Whirlpool, Part Weight 0.32 ounces, Dimensions 4.63 x 4.38 x 6.63 inches, model number Is Discontinued No, Material Plastic, Quantity 1, Included Components 1, Rank Tools & Home Improvement Washer Parts & Accessories 456, Available November 9, 2011"}, {"role": "assistant", "content": "Price is $141.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nForeverPRO Roller Kit (4 Pak) Lower for Whirlpool Dishwasher 2959 303991\nForeverPRO Dishwasher Roller Kit (4 Pak) Lower Part Number replaces 2959 303991 675549 717509 8222 Whirlpool Dishwasher. Compatible with Whirlpool Maytag KitchenAid Jenn-Air Amana Magic Chef Admiral Norge Roper and others This is not a Whirlpool OEM product. Use of the Manufacturers trade names and logos are the registered trademarks of their respective owners. Any use of the Manufacturers brand name, part numbers or model designation for this product is made solely for purposes of demonstrating and for identification compatibility and are displayed for descriptive purposes only. Use of them does not associated with, imply any affiliation or endorsement by any manufacturer.Com"}, {"role": "assistant", "content": "Price is $25.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nPaiste Signature Cymbal Full Crash\nForged from proprietary bronze developed specifically for cymbals,handcrafted by highly skilled Swiss sound concepts,Signature Cymbals are instruments of unsurpassed quality for the discerning drummer's quest for personal creativity & musical excellence Since 1996. Alloy Proprietary Signature Bronze Soft to medium loud settings Live and recording Classic to modern Jazz Blues Swing Big Band Country Funk Reggae R&B and Soul as well as Pop and moderate Rock Weight 898 Grams, Dimensions 16 x 16 x 1 inches, model number Rank Musical Instruments 44826, Crash Cymbals 94, Is Discontinued No, Available April 4, 2007, Body Material Bronze, Material Type Bronze, Size 16 Inch, Brand Paiste, Material"}, {"role": "assistant", "content": "Price is $302.35"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nCHAUVET DJ Hurricane 1101 Fog Machine w/LED Illuminated 1.3L Tank\nCompact and lightweight fog machine emits thick bursts of water-based fog to fill a venue within minutes Advanced fluid sensor, with automatic shut-off which protects our pump from overheating Features a 1.3 l tank capacity and quick heat-up time for an output of 8,000 cfm Easily control using the manual fog button Enhance operation and safety with the LED illuminated tank Weight 8.36 pounds, Dimensions 12.4 x 10.04 x 9.84 inches, model number Hurricane 1101, Rank Musical Instruments 89831, Stage Fog Machines & Accessories 599, Stage Lighting Equipment & Accessories 2724, Music Recording Equipment 24574, Available February"}, {"role": "assistant", "content": "Price is $129.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\n10 inches Diameter Handmade singing bowl-Tibetan singing bowl from Nepal\nThis singing bowl is a special bowl, which is made of seven metals, i.e. gold, silver, copper, iron, tin, lead, and zinc. All the metal used has a specific purpose and represent the sun and the moon and other planets. This bowl can be used for meditation, music, and chakra cleansing. A leather striker is included with this singing bowl and this bowl was hand-hammered in Nepal. This bowl is truly hand made in a traditional way at singing-bowl house. Due to handmade bowl, the surface have several marked of hammered on it. The bowl have long lasting tune which create totally peaceful environment around you. who are looking for real handmade bowl from Himalaya will not"}, {"role": "assistant", "content": "Price is $230.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nAquila Oud Strings Iraqi Tuning 11 Strings Red Nylgut Model 610\nAquila oud strings IRAQI tuning. new condition. The sets have a working tension of 3.4 kg per rope. The cellars are made with a newly discovered bio-plastic with high acoustic performance, derived from sugar cane, and called by us Sugar. The coated strings are made of hypoallergenic red copper (with the exception of the fourth ones for the Iraqi Oud set, which is in a gray metal alloy) and low noise under the fingers. Diameter conversion Sugar = Nylon x 0.91. Example 0.71 mm Nylon x.91 = 0.646 mm Sugar (in practice 0.65 mm). \u25cb Red strings \u25cb IRAQ"}, {"role": "assistant", "content": "Price is $21.00"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nLronbird Steel Tongue Inch 13 Note Handpan Drums, Concert Percussion Instrument with Travel Bag Music Book Mallets for Adults Kids Meditation Yoga Chakra Healing, Unique Gifts, C Major (Blue)\n\ud83d\udd14EASY TO PLAY USEFUL FOR \u2714\ufe0f Stress & Anxiety Reduction \u2714\ufe0f Deep Relaxation \u2714\ufe0f Musicians & Teachers \u2714\ufe0f Holistic Healing & Reiki Practice \u2714\ufe0f Spiritual Healing \u2714\ufe0f Self-Hypnosis \u2714\ufe0f Home Decor \u2714\ufe0f Gift Lronbird Steel Tongue Drum The steel tongue drum is made of steel-titanium alloy and precision-cut by professional craftsmen to make 13 notes pronounce accurately to get an ideal ethereal tone, gentle and long, which helps to eliminate worries, relax the mind and relieve anxiety, come with music score which is"}, {"role": "assistant", "content": "Price is $59.99"}]} +{"messages": [{"role": "system", "content": "You estimate prices of items. Reply only with the price, no explanation"}, {"role": "user", "content": "How much does this cost?\n\nHosa 1/4 TS to Neutrik speakON Speaker Adaptor Cable, 16 AWG x 2 OFC\nThe Hosa GSK116 cable is designed to adapt a speaker cable with a phone plug to a speaker with a SpeakON input. It is ideal for use in touring and other live-sound applications. This cable is designed to adapt a speaker cable with a phone plug to a speaker with a Speakon input. It is ideal for use in touring and other live-sound applications A genuine Neutrik Speakon connector for a safe and secure connection every time Oxygen-free copper (OFC) Conductors for lower resistance and increased signal flow Intended for high-current applications only, not line level signals Conductor) 16 AWG x 2 OFC"}, {"role": "assistant", "content": "Price is $23.95"}]} \ No newline at end of file diff --git a/week6/community-contributions/kwabena/items.py b/week6/community-contributions/kwabena/items.py new file mode 100644 index 0000000..89aecc4 --- /dev/null +++ b/week6/community-contributions/kwabena/items.py @@ -0,0 +1,103 @@ +from typing import Optional +from transformers import AutoTokenizer +import re + +BASE_MODEL = "meta-llama/Meta-Llama-3.1-8B" + +MIN_TOKENS = 150 # Any less than this, and we don't have enough useful content +MAX_TOKENS = 160 # Truncate after this many tokens. Then after adding in prompt text, we will get to around 180 tokens + +MIN_CHARS = 300 +CEILING_CHARS = MAX_TOKENS * 7 + +class Item: + """ + An Item is a cleaned, curated datapoint of a Product with a Price + """ + + tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL, trust_remote_code=True) + PREFIX = "Price is $" + QUESTION = "How much does this cost to the nearest dollar?" + REMOVALS = ['"Batteries Included?": "No"', '"Batteries Included?": "Yes"', '"Batteries Required?": "No"', '"Batteries Required?": "Yes"', "By Manufacturer", "Item", "Date First", "Package", ":", "Number of", "Best Sellers", "Number", "Product "] + + title: str + price: float + category: str + token_count: int = 0 + details: Optional[str] + prompt: Optional[str] = None + include = False + + def __init__(self, data, price): + self.title = data['title'] + self.price = price + self.parse(data) + + def scrub_details(self): + """ + Clean up the details string by removing common text that doesn't add value + """ + details = self.details + for remove in self.REMOVALS: + details = details.replace(remove, "") + return details + + def scrub(self, stuff): + """ + Clean up the provided text by removing unnecessary characters and whitespace + Also remove words that are 7+ chars and contain numbers, as these are likely irrelevant product numbers + """ + stuff = re.sub(r'[:\[\]"{}【】\s]+', ' ', stuff).strip() + stuff = stuff.replace(" ,", ",").replace(",,,",",").replace(",,",",") + words = stuff.split(' ') + select = [word for word in words if len(word)<7 or not any(char.isdigit() for char in word)] + return " ".join(select) + + def parse(self, data): + """ + Parse this datapoint and if it fits within the allowed Token range, + then set include to True + """ + contents = '\n'.join(data['description']) + if contents: + contents += '\n' + features = '\n'.join(data['features']) + if features: + contents += features + '\n' + self.details = data['details'] + if self.details: + contents += self.scrub_details() + '\n' + if len(contents) > MIN_CHARS: + contents = contents[:CEILING_CHARS] + text = f"{self.scrub(self.title)}\n{self.scrub(contents)}" + tokens = self.tokenizer.encode(text, add_special_tokens=False) + if len(tokens) > MIN_TOKENS: + tokens = tokens[:MAX_TOKENS] + text = self.tokenizer.decode(tokens) + self.make_prompt(text) + self.include = True + + def make_prompt(self, text): + """ + Set the prompt instance variable to be a prompt appropriate for training + """ + self.prompt = f"{self.QUESTION}\n\n{text}\n\n" + self.prompt += f"{self.PREFIX}{str(round(self.price))}.00" + self.token_count = len(self.tokenizer.encode(self.prompt, add_special_tokens=False)) + + def test_prompt(self): + """ + Return a prompt suitable for testing, with the actual price removed + """ + return self.prompt.split(self.PREFIX)[0] + self.PREFIX + + def __repr__(self): + """ + Return a String version of this Item + """ + return f"<{self.title} = ${self.price}>" + + + + + \ No newline at end of file diff --git a/week6/community-contributions/kwabena/loaders.py b/week6/community-contributions/kwabena/loaders.py new file mode 100644 index 0000000..c3472e2 --- /dev/null +++ b/week6/community-contributions/kwabena/loaders.py @@ -0,0 +1,81 @@ +from datetime import datetime +from tqdm import tqdm +from datasets import load_dataset +from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor +from items import Item + +CHUNK_SIZE = 1000 +MIN_PRICE = 0.5 +MAX_PRICE = 999.49 + +class ItemLoader: + + + def __init__(self, name): + self.name = name + self.dataset = None + + def from_datapoint(self, datapoint): + """ + Try to create an Item from this datapoint + Return the Item if successful, or None if it shouldn't be included + """ + try: + price_str = datapoint['price'] + if price_str: + price = float(price_str) + if MIN_PRICE <= price <= MAX_PRICE: + item = Item(datapoint, price) + return item if item.include else None + except ValueError: + return None + + def from_chunk(self, chunk): + """ + Create a list of Items from this chunk of elements from the Dataset + """ + batch = [] + for datapoint in chunk: + result = self.from_datapoint(datapoint) + if result: + batch.append(result) + return batch + + def chunk_generator(self): + """ + Iterate over the Dataset, yielding chunks of datapoints at a time + """ + size = len(self.dataset) + for i in range(0, size, CHUNK_SIZE): + yield self.dataset.select(range(i, min(i + CHUNK_SIZE, size))) + + def load_in_parallel(self, workers): + """ + Use concurrent.futures to farm out the work to process chunks of datapoints - + This speeds up processing significantly, but will tie up your computer while it's doing so! + """ + results = [] + chunk_count = (len(self.dataset) // CHUNK_SIZE) + 1 + with ProcessPoolExecutor(max_workers=workers) as pool: + for batch in tqdm(pool.map(self.from_chunk, self.chunk_generator()), total=chunk_count): + results.extend(batch) + for result in results: + result.category = self.name + return results + + def load(self, workers=8): + """ + Load in this dataset; the workers parameter specifies how many processes + should work on loading and scrubbing the data + """ + start = datetime.now() + print(f"Loading dataset {self.name}", flush=True) + self.dataset = load_dataset("McAuley-Lab/Amazon-Reviews-2023", f"raw_meta_{self.name}", split="full", trust_remote_code=True) + results = self.load_in_parallel(workers) + finish = datetime.now() + print(f"Completed {self.name} with {len(results):,} datapoints in {(finish-start).total_seconds()/60:.1f} mins", flush=True) + return results + + + + \ No newline at end of file diff --git a/week6/community-contributions/kwabena/product pricer flavoured.ipynb b/week6/community-contributions/kwabena/product pricer flavoured.ipynb new file mode 100644 index 0000000..e3f7918 --- /dev/null +++ b/week6/community-contributions/kwabena/product pricer flavoured.ipynb @@ -0,0 +1,567 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "db8736a7-ed94-441c-9556-831fa57b5a10", + "metadata": {}, + "source": [ + "# The Product Pricer Continued\n", + "\n", + "A model that can estimate how much something costs, from its description.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "681c717b-4c24-4ac3-a5f3-3c5881d6e70a", + "metadata": {}, + "outputs": [], + "source": [ + "# imports\n", + "\n", + "import os\n", + "import re\n", + "import math\n", + "import json\n", + "import random\n", + "from dotenv import load_dotenv\n", + "from huggingface_hub import login\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pickle\n", + "from collections import Counter\n", + "from openai import OpenAI\n", + "from anthropic import Anthropic" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36d05bdc-0155-4c72-a7ee-aa4e614ffd3c", + "metadata": {}, + "outputs": [], + "source": [ + "# environment\n", + "\n", + "load_dotenv(override=True)\n", + "os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY', 'your-key-if-not-using-env')\n", + "os.environ['ANTHROPIC_API_KEY'] = os.getenv('ANTHROPIC_API_KEY', 'your-key-if-not-using-env')\n", + "os.environ['HF_TOKEN'] = os.getenv('HF_TOKEN', 'your-key-if-not-using-env')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4dd3aad2-6f99-433c-8792-e461d2f06622", + "metadata": {}, + "outputs": [], + "source": [ + "# Log in to HuggingFace\n", + "\n", + "hf_token = os.environ['HF_TOKEN']\n", + "login(hf_token, add_to_git_credential=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "884a50bd-8cae-425e-8e56-f079fc3e65ce", + "metadata": {}, + "outputs": [], + "source": [ + "# moved our Tester into a separate package\n", + "# call it with Tester.test(function_name, test_dataset)\n", + "\n", + "from items import Item\n", + "from testing import Tester" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b0a6fb86-74a4-403c-ab25-6db2d74e9d2b", + "metadata": {}, + "outputs": [], + "source": [ + "openai = OpenAI()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c830ed3e-24ee-4af6-a07b-a1bfdcd39278", + "metadata": {}, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c9b05f4-c9eb-462c-8d86-de9140a2d985", + "metadata": {}, + "outputs": [], + "source": [ + "# Let's avoid curating all our data again! Load in the pickle files:\n", + "\n", + "with open('train.pkl', 'rb') as file:\n", + " train = pickle.load(file)\n", + "\n", + "with open('test.pkl', 'rb') as file:\n", + " test = pickle.load(file)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8367135-f40e-43e1-8f3c-09e990ab1194", + "metadata": {}, + "outputs": [], + "source": [ + "# OpenAI recommends fine-tuning with populations of 50-100 examples\n", + "# But as our examples are very small, I'm suggesting we go with 200 examples (and 1 epoch)\n", + "\n", + "fine_tune_train = train[:200]\n", + "fine_tune_validation = train[200:250]" + ] + }, + { + "cell_type": "markdown", + "id": "8be4a889-81c3-42b1-a2fc-034cdc7321a6", + "metadata": {}, + "source": [ + "# Step 1\n", + "\n", + "Prepare our data for fine-tuning in JSONL (JSON Lines) format and upload to OpenAI" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8ae2fb3c-1cff-4ce3-911e-627c970edd7b", + "metadata": {}, + "outputs": [], + "source": [ + "# First let's work on a good prompt for a Frontier model\n", + "# Notice that I'm removing the \" to the nearest dollar\"\n", + "# When we train our own models, we'll need to make the problem as easy as possible,\n", + "# but a Frontier model needs no such simplification.\n", + "\n", + "def messages_for(item):\n", + " system_message = \"You estimate prices of items. Reply only with the price, no explanation\"\n", + " user_prompt = item.test_prompt().replace(\" to the nearest dollar\",\"\").replace(\"\\n\\nPrice is $\",\"\")\n", + " return [\n", + " {\"role\": \"system\", \"content\": system_message},\n", + " {\"role\": \"user\", \"content\": user_prompt},\n", + " {\"role\": \"assistant\", \"content\": f\"Price is ${item.price:.2f}\"}\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1aa280f6-1227-426a-a2e2-1ce985feba1e", + "metadata": {}, + "outputs": [], + "source": [ + "messages_for(train[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0e5b56c-8a0b-4d8e-a112-ce87efb4e152", + "metadata": {}, + "outputs": [], + "source": [ + "# Convert the items into a list of json objects - a \"jsonl\" string\n", + "# Each row represents a message in the form:\n", + "# {\"messages\" : [{\"role\": \"system\", \"content\": \"You estimate prices...\n", + "\n", + "\n", + "def make_jsonl(items):\n", + " result = \"\"\n", + " for item in items:\n", + " messages = messages_for(item)\n", + " messages_str = json.dumps(messages)\n", + " result += '{\"messages\": ' + messages_str +'}\\n'\n", + " return result.strip()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5e72de93-a6a6-4b35-855e-15786b97bf5f", + "metadata": {}, + "outputs": [], + "source": [ + "print(make_jsonl(train[:3]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7734bff0-95c4-4e67-a87e-7e2254e2c67d", + "metadata": {}, + "outputs": [], + "source": [ + "# Convert the items into jsonl and write them to a file\n", + "\n", + "def write_jsonl(items, filename):\n", + " with open(filename, \"w\") as f:\n", + " jsonl = make_jsonl(items)\n", + " f.write(jsonl)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "393d3ad8-999a-4f99-8c04-339d9166d604", + "metadata": {}, + "outputs": [], + "source": [ + "write_jsonl(fine_tune_train, \"fine_tune_train.jsonl\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8e23927f-d73e-4668-ac20-abe6f14a56cb", + "metadata": {}, + "outputs": [], + "source": [ + "write_jsonl(fine_tune_validation, \"fine_tune_validation.jsonl\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d59ad8d2-c61a-448e-b7ed-232f1606970f", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"fine_tune_train.jsonl\", \"rb\") as f:\n", + " train_file = openai.files.create(file=f, purpose=\"fine-tune\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "083fefba-fd54-47ce-9ff3-aabbc200846f", + "metadata": {}, + "outputs": [], + "source": [ + "train_file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97df3360-0760-4422-a556-5f26d23de6dc", + "metadata": {}, + "outputs": [], + "source": [ + "with open(\"fine_tune_validation.jsonl\", \"rb\") as f:\n", + " validation_file = openai.files.create(file=f, purpose=\"fine-tune\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a1abb8f3-9e52-4061-970c-fcf399d8ffa3", + "metadata": {}, + "outputs": [], + "source": [ + "validation_file" + ] + }, + { + "cell_type": "markdown", + "id": "466052b9-9fb9-48f6-8cf9-c74e6ddc1394", + "metadata": {}, + "source": [ + "# Step 2\n", + "\n", + "I love Weights and Biases - a beautiful, free platform for monitoring training runs. \n", + "Weights and Biases is integrated with OpenAI for fine-tuning.\n", + "\n", + "First set up your weights & biases free account at:\n", + "\n", + "https://wandb.ai\n", + "\n", + "From the Avatar >> Settings menu, near the bottom, you can create an API key.\n", + "\n", + "Then visit the OpenAI dashboard at:\n", + "\n", + "https://platform.openai.com/account/organization\n", + "\n", + "In the integrations section, you can add your Weights & Biases key.\n", + "\n", + "## And now time to Fine-tune!" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c7add1a7-a746-4d6e-a5f8-e25629b8b527", + "metadata": {}, + "outputs": [], + "source": [ + "wandb_integration = {\"type\": \"wandb\", \"wandb\": {\"project\": \"gpt-pricer\"}}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "49801e69-9277-4deb-9f33-99efb6b45ac2", + "metadata": {}, + "outputs": [], + "source": [ + "train_file.id" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "45421b86-5531-4e42-ab19-d6abbb8f4c13", + "metadata": {}, + "outputs": [], + "source": [ + "openai.fine_tuning.jobs.create(\n", + " training_file=train_file.id,\n", + " validation_file=validation_file.id,\n", + " model=\"gpt-4o-mini-2024-07-18\",\n", + " seed=42,\n", + " hyperparameters={\"n_epochs\": 1},\n", + " integrations = [wandb_integration],\n", + " suffix=\"pricer\"\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aeb9de2e-542c-4e83-81c7-b6745133e48b", + "metadata": {}, + "outputs": [], + "source": [ + "openai.fine_tuning.jobs.list(limit=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "40d24873-8ff5-413f-b0d4-8f77c28f18e1", + "metadata": {}, + "outputs": [], + "source": [ + "job_id = openai.fine_tuning.jobs.list(limit=1).data[0].id" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a32aef35-4b38-436c-ad00-d082f758efa7", + "metadata": {}, + "outputs": [], + "source": [ + "job_id" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7e01247-c133-48e1-93d3-c79c399e6178", + "metadata": {}, + "outputs": [], + "source": [ + "openai.fine_tuning.jobs.retrieve(job_id)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f5150e1-b8de-485f-8eba-cf1e5b00c117", + "metadata": {}, + "outputs": [], + "source": [ + "openai.fine_tuning.jobs.list_events(fine_tuning_job_id=job_id, limit=10).data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b19ea9e9", + "metadata": {}, + "outputs": [], + "source": [ + "import wandb\n", + "from wandb.integration.openai.fine_tuning import WandbLogger\n", + "\n", + "# Log in to Weights & Biases.\n", + "wandb.login()\n", + "# Sync the fine-tuning job with Weights & Biases.\n", + "WandbLogger.sync(fine_tune_job_id=job_id, project=\"gpt-pricer\")" + ] + }, + { + "cell_type": "markdown", + "id": "066fef03-8338-4526-9df3-89b649ad4f0a", + "metadata": {}, + "source": [ + "# Step 3\n", + "\n", + "Test our fine tuned model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fa4488cb-3c17-4eda-abd1-53c1c68a491b", + "metadata": {}, + "outputs": [], + "source": [ + "fine_tuned_model_name = openai.fine_tuning.jobs.retrieve(job_id).fine_tuned_model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e9370937-5a6f-4724-8265-b208663b4450", + "metadata": {}, + "outputs": [], + "source": [ + "fine_tuned_model_name" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66ea68e8-ab1b-4f0d-aba4-a59574d8f85e", + "metadata": {}, + "outputs": [], + "source": [ + "# The prompt\n", + "\n", + "def messages_for(item):\n", + " system_message = \"You estimate prices of items. Reply only with the price, no explanation\"\n", + " user_prompt = item.test_prompt().replace(\" to the nearest dollar\",\"\").replace(\"\\n\\nPrice is $\",\"\")\n", + " return [\n", + " {\"role\": \"system\", \"content\": system_message},\n", + " {\"role\": \"user\", \"content\": user_prompt},\n", + " {\"role\": \"assistant\", \"content\": \"Price is $\"}\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ff92d61-0d27-4b0d-8b32-c9891016509b", + "metadata": {}, + "outputs": [], + "source": [ + "# Try this out\n", + "\n", + "messages_for(test[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b1af1888-f94a-4106-b0d8-8a70939eec4e", + "metadata": {}, + "outputs": [], + "source": [ + "# A utility function to extract the price from a string\n", + "\n", + "def get_price(s):\n", + " s = s.replace('$','').replace(',','')\n", + " match = re.search(r\"[-+]?\\d*\\.\\d+|\\d+\", s)\n", + " return float(match.group()) if match else 0" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f138c5b7-bcc1-4085-aced-68dad1bf36b4", + "metadata": {}, + "outputs": [], + "source": [ + "get_price(\"The price is roughly $99.99 because blah blah\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "501a2a7a-69c8-451b-bbc0-398bcb9e1612", + "metadata": {}, + "outputs": [], + "source": [ + "# The function for gpt-4o-mini\n", + "\n", + "def gpt_fine_tuned(item):\n", + " response = openai.chat.completions.create(\n", + " model=\"ft:gpt-4o-mini-2024-07-18:gpt-pricer:pricer:CVwNdjUi\",\n", + " messages=messages_for(item),\n", + " seed=42,\n", + " max_tokens=7\n", + " )\n", + " reply = response.choices[0].message.content\n", + " return get_price(reply)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "843d88b4-364a-431b-b48b-8a7c1f68b786", + "metadata": {}, + "outputs": [], + "source": [ + "print(test[0].price)\n", + "print(gpt_fine_tuned(test[0]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "edd7ada0-15b7-42ec-bbbb-1250e0eb9af1", + "metadata": {}, + "outputs": [], + "source": [ + "print(test[0].test_prompt())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36bdd2c9-1859-4f99-a09f-3ec83b845b30", + "metadata": {}, + "outputs": [], + "source": [ + "Tester.test(gpt_fine_tuned, test)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/week6/community-contributions/kwabena/testing.py b/week6/community-contributions/kwabena/testing.py new file mode 100644 index 0000000..cd43924 --- /dev/null +++ b/week6/community-contributions/kwabena/testing.py @@ -0,0 +1,75 @@ +import math +import matplotlib.pyplot as plt + +GREEN = "\033[92m" +YELLOW = "\033[93m" +RED = "\033[91m" +RESET = "\033[0m" +COLOR_MAP = {"red":RED, "orange": YELLOW, "green": GREEN} + +class Tester: + + def __init__(self, predictor, data, title=None, size=250): + self.predictor = predictor + self.data = data + self.title = title or predictor.__name__.replace("_", " ").title() + self.size = size + self.guesses = [] + self.truths = [] + self.errors = [] + self.sles = [] + self.colors = [] + + def color_for(self, error, truth): + if error<40 or error/truth < 0.2: + return "green" + elif error<80 or error/truth < 0.4: + return "orange" + else: + return "red" + + def run_datapoint(self, i): + datapoint = self.data[i] + guess = self.predictor(datapoint) + truth = datapoint.price + error = abs(guess - truth) + log_error = math.log(truth+1) - math.log(guess+1) + sle = log_error ** 2 + color = self.color_for(error, truth) + title = datapoint.title if len(datapoint.title) <= 40 else datapoint.title[:40]+"..." + self.guesses.append(guess) + self.truths.append(truth) + self.errors.append(error) + self.sles.append(sle) + self.colors.append(color) + print(f"{COLOR_MAP[color]}{i+1}: Guess: ${guess:,.2f} Truth: ${truth:,.2f} Error: ${error:,.2f} SLE: {sle:,.2f} Item: {title}{RESET}") + + def chart(self, title): + max_error = max(self.errors) + plt.figure(figsize=(12, 8)) + max_val = max(max(self.truths), max(self.guesses)) + plt.plot([0, max_val], [0, max_val], color='deepskyblue', lw=2, alpha=0.6) + plt.scatter(self.truths, self.guesses, s=3, c=self.colors) + plt.xlabel('Ground Truth') + plt.ylabel('Model Estimate') + plt.xlim(0, max_val) + plt.ylim(0, max_val) + plt.title(title) + plt.show() + + def report(self): + average_error = sum(self.errors) / self.size + rmsle = math.sqrt(sum(self.sles) / self.size) + hits = sum(1 for color in self.colors if color=="green") + title = f"{self.title} Error=${average_error:,.2f} RMSLE={rmsle:,.2f} Hits={hits/self.size*100:.1f}%" + self.chart(title) + + def run(self): + self.error = 0 + for i in range(self.size): + self.run_datapoint(i) + self.report() + + @classmethod + def test(cls, function, data): + cls(function, data).run() \ No newline at end of file diff --git a/week7/community_contributions/muthama/week7_exercise_Testing_Colab.md b/week7/community_contributions/muthama/week7_exercise_Testing_Colab.md new file mode 100644 index 0000000..663e7d2 --- /dev/null +++ b/week7/community_contributions/muthama/week7_exercise_Testing_Colab.md @@ -0,0 +1,3 @@ +### Link + +https://colab.research.google.com/drive/1CAF3VcNvZs3Eex71TMX3A5exw2Bw4HUF?usp=sharing \ No newline at end of file diff --git a/week7/community_contributions/muthama/week7_exercise_Training_Colab.md b/week7/community_contributions/muthama/week7_exercise_Training_Colab.md new file mode 100644 index 0000000..663e7d2 --- /dev/null +++ b/week7/community_contributions/muthama/week7_exercise_Training_Colab.md @@ -0,0 +1,3 @@ +### Link + +https://colab.research.google.com/drive/1CAF3VcNvZs3Eex71TMX3A5exw2Bw4HUF?usp=sharing \ No newline at end of file diff --git a/week7/community_contributions/week7_exercise (10).py b/week7/community_contributions/week7_exercise (10).py new file mode 100644 index 0000000..985ad93 --- /dev/null +++ b/week7/community_contributions/week7_exercise (10).py @@ -0,0 +1,445 @@ +# -*- coding: utf-8 -*- +"""Week7_Exercise.ipynb + +Automatically generated by Colab. + +Original file is located at + https://colab.research.google.com/drive/1wxcBNWbsDDC_SwXnQZP2dmo7ddOxkJmU +""" + +#my pip installtions (some of them were not used in the project but i initally planned to use them (and we're left here so that I after the project i revisit the notebook and update when i have time and more sources.)) +!pip install -q --upgrade pip +!pip install -q transformers accelerate peft bitsandbytes trl sentencepiece safetensors +!pip install -q wandb +!pip install -q git+https://github.com/huggingface/peft.git@main +!pip install datasets==3.0.1 +!pip install evaluate -q +!pip install --upgrade scikit-learn + +#All imports +import os, random, json, re +import pandas as pd +import numpy as np +import torch +import matplotlib.pyplot as plt +from tqdm import tqdm +from sklearn.model_selection import train_test_split +from sklearn.model_selection import train_test_split +from datasets import Dataset, DatasetDict +from IPython.display import Markdown as md +from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score +from transformers import ( + AutoTokenizer, + AutoModelForCausalLM, + TrainingArguments, + Trainer, + DataCollatorForLanguageModeling +) + +#I tried a lot of models and every time my colab ran out of RAM, i did a lot of tweakings including replacing models with smaller ones +#I also used try and error to come up with samples size, eval size etc that would fit in my limited T4 Ram (had started from sample size of 15k down to 200) +MODEL_NAME = "facebook/opt-125m" +SAMPLE_SIZE = 200 +EVAL_SIZE = 50 +MAX_LENGTH = 128 +RANDOM_SEED = 42 + +#Seeting LoRa hyper parameters +LORA_R = 4 +LORA_ALPHA = 8 +LORA_DROPOUT = 0.05 +#Target modules to apply LoRA. I kept these to just "q_proj" and "v_proj" to lower memory usage on a T4 GPU. +TARGET_MODULES = ["q_proj", "v_proj"] + +#to make sure thes expriment is reproducible +random.seed(RANDOM_SEED) +np.random.seed(RANDOM_SEED) +torch.manual_seed(RANDOM_SEED) + +#Hf data +DATASET_NAME = "McAuley-Lab/Amazon-Reviews-2023" +SUBSET = "raw_meta_Appliances" + +#loading the data +dataset = load_dataset(DATASET_NAME, SUBSET, split="full") +df = dataset.to_pandas() + +# somecleaning on prices +df["price_clean"] = pd.to_numeric(df["price"], errors="coerce") + +# Bringing the text fields togeter +def combine_text(row): + title = row["title"] or "" + features = " ".join(row["features"]) if isinstance(row["features"], list) else "" + description = " ".join(row["description"]) if isinstance(row["description"], list) else "" + return f"TITLE: {title}\n\nFEATURES: {features}\n\nDESCRIPTION: {description}" + +df["text"] = df.apply(combine_text, axis=1) + +df_clean = df.dropna(subset=["price_clean"]).reset_index(drop=True) + +# Example: sample the cleaned data for faster experimentation +df_sample = df_clean.sample(n=5000, random_state=42) # adjust n as needed + +train_df, eval_df = train_test_split(df_sample, test_size=0.2, random_state=42) + +print(f"Train size: {len(train_df)}, Eval size: {len(eval_df)}") + +train_df.head(2) + +hf_train = Dataset.from_pandas(train_df.reset_index(drop=True)) +hf_eval = Dataset.from_pandas(eval_df.reset_index(drop=True)) +dataset = DatasetDict({"train": hf_train, "eval": hf_eval}) + +# Add instruction + numeric target (log-transformed) +import numpy as np + +def add_instruction_and_target(ex): + ex["instruction"] = "Estimate the fair market price of this product in USD. Return only a single number." + price = float(ex["price_clean"]) + ex["target_log"] = np.log1p(price) # log1p makes training easier + ex["target_str"] = f"{ex['target_log']:.6f}" # as string for LM + return ex + +dataset = dataset.map(add_instruction_and_target) + +print(dataset) +print(dataset["train"][0]) + +print(df_clean[["title", "price", "price_clean"]].head(10)) +print(f"\nNumber of valid price entries: {df_clean['price_clean'].notna().sum()}") + +# trying to downsamble for RAM purposes-hoping the punshment to results wasn't much +if len(df_clean) > SAMPLE_SIZE + EVAL_SIZE: + df_sample = df_clean.sample(SAMPLE_SIZE + EVAL_SIZE, random_state=RANDOM_SEED).reset_index(drop=True) +else: + df_sample = df_clean.copy() + +train_df, eval_df = train_test_split(df_sample, test_size=EVAL_SIZE, random_state=RANDOM_SEED) + +# FHow to format the examples +def make_example(row): + instruction = "Estimate the fair market price of this product in USD. Return only a single number." + input_text = row["text"] + output = f"{float(row['price_clean']):.2f}" + return {"instruction": instruction, "input": input_text, "output": output} + +train_examples = [make_example(r) for _, r in train_df.iterrows()] +eval_examples = [make_example(r) for _, r in eval_df.iterrows()] + +# Saving into JSONL +with open("pricing_train.jsonl", "w") as f: + for ex in train_examples: + f.write(json.dumps(ex) + "\n") + +with open("pricing_eval.jsonl", "w") as f: + for ex in eval_examples: + f.write(json.dumps(ex) + "\n") + +#A good formating for the llm +def format_for_model(ex): + return f"### Instruction:\n{ex['instruction']}\n\n### Input:\n{ex['input']}\n\n### Response:\n{ex['output']}" + +#seeing the examples +print("Example formatted prompts (3):") + +#iterating over the egs +for ex in train_examples[:3]: + print(format_for_model(ex)) + print("-"*80) + +#tokenization now +tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME) +tokenizer.pad_token = tokenizer.eos_token + +model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, device_map="auto") + +#check ifthe model successful +print(f"{MODEL_NAME} succceeded") + +# ===== Tokenization & dataset preprocessing ===== +MAX_LENGTH = 128 + +def preprocess_for_training(examples): + input_ids, attention_masks, labels = [], [], [] + + for instr, inp, tgt in zip(examples["instruction"], examples["text"], examples["target_str"]): + prompt = f"### Instruction:\n{instr}\n\n### Input:\n{inp}\n\n### Response:\n" + full = prompt + tgt + + tok_full = tokenizer(full, truncation=True, max_length=MAX_LENGTH, padding="max_length") + tok_prompt = tokenizer(prompt, truncation=True, max_length=MAX_LENGTH, padding="max_length") + + inp_ids = tok_full["input_ids"] + attn_mask = tok_full["attention_mask"] + + prompt_len = sum(1 for t in tok_prompt["input_ids"] if t != tokenizer.pad_token_id) + label_ids = [-100] * prompt_len + inp_ids[prompt_len:] + label_ids = label_ids[:MAX_LENGTH] + + input_ids.append(inp_ids) + attention_masks.append(attn_mask) + labels.append(label_ids) + + return { + "input_ids": input_ids, + "attention_mask": attention_masks, + "labels": labels + } + +# Map this to dataset +tokenized_datasets = dataset.map( + preprocess_for_training, + batched=True, + remove_columns=dataset["train"].column_names +) + +print(" Tokenization complete:", tokenized_datasets) + +# Sample random evaluation +sample_eval = random.sample(eval_examples, 10) + +baseline_preds, baseline_truths = [], [] + +baseline_preds = [] +baseline_truths = [] + +for ex in tqdm(sample_eval, desc="Evaluating"): + true_price = float(ex["output"]) + + prompt = ( + f"### Instruction:\nEstimate the fair market price of this product in USD. " + f"Return only a number — no text, no currency symbols.\n\n" + f"### Input:\n{ex['input']}\n\n### Response:" + ) + + inputs = tokenizer(prompt, return_tensors="pt").to(model.device) + + with torch.no_grad(): + output = model.generate( + **inputs, + max_new_tokens=20, + temperature=0.0, + do_sample=False + ) + + generated_tokens = output[0][inputs["input_ids"].shape[-1]:] + text_output = tokenizer.decode(generated_tokens, skip_special_tokens=True).strip() + + # Extract number from output + match = re.search(r"[-+]?\d*\.?\d+", text_output) + pred_price = float(match.group()) if match else None + + # Apply inverse log if model outputs logs + if pred_price is not None: + if pred_price < 20: # log range, assuming trained on log(price) + pred_price = np.expm1(pred_price) + else: + print(f" Skipping log transform, raw pred {pred_price}") + + # Only keep realistic prices + if 0 < pred_price < 1e4: + baseline_preds.append(pred_price) + baseline_truths.append(true_price) + else: + print(f" Skipping unreasonable pred {pred_price}") + else: + print(f" No number extracted from: {text_output}") + + print(f" Predicted: {pred_price}, True: {true_price}, Raw: {text_output}") + +print(f"\nNumber of baseline predictions: {len(baseline_preds)}") +print(f"Number of baseline truths: {len(baseline_truths)}") + +# Manual computation of metrics +if baseline_preds: + mae = mean_absolute_error(baseline_truths, baseline_preds) + mse = mean_squared_error(baseline_truths, baseline_preds) + rmse = mse ** 0.5 # take square root manually + print(f"\nBaseline MAE: ${mae:.2f}") + print(f"Baseline RMSE: ${rmse:.2f}") + +print(f"Number of baseline predictions: {len(baseline_preds)}") +print(f"Number of baseline truths: {len(baseline_truths)}") + +#inspectthe data a little +print(dataset) +print(dataset["train"].column_names) +print(dataset["train"][0]) # show one sample + +# create TrainingArguments and Trainer, compatible with older transformers === +import transformers +print("transformers version:", transformers.__version__) + +# decide whether evaluation_strategy is supported +supports_eval_strategy = False +try: + import inspect + sig = inspect.signature(transformers.TrainingArguments.__init__) + if 'evaluation_strategy' in sig.parameters: + supports_eval_strategy = True +except Exception: + # fallback: assume older version + supports_eval_strategy = False + +from transformers import TrainingArguments, Trainer + +# common args +common_args = dict( + output_dir="./price-predictor-checkpoints", + num_train_epochs=3, + per_device_train_batch_size=2, + gradient_accumulation_steps=4, + learning_rate=2e-5, + fp16=True, # if you see fp16 errors, set this to False + save_total_limit=1, + logging_steps=10, + report_to="none", +) + +if supports_eval_strategy: + print("Using evaluation_strategy in TrainingArguments (newer transformers).") + training_args = TrainingArguments( + **common_args, + evaluation_strategy="steps", + eval_steps=100, + save_strategy="steps", + save_steps=200, + ) +else: + print("evaluation_strategy not supported in this transformers version. Using minimal TrainingArguments and running trainer.evaluate() after training.") + # remove args unknown to old versions + # older versions may also not accept fp16 or report_to; if errors appear, set fp16=False and remove report_to + training_args = TrainingArguments(**common_args) + +# Build the Trainer +trainer = Trainer( + model=model, + args=training_args, + train_dataset=tokenized_datasets["train"], + eval_dataset=tokenized_datasets["eval"], + tokenizer=tokenizer +) + +# Train +train_result = trainer.train() + +# If evaluation_strategy wasn't available, run a manual evaluate here +if not supports_eval_strategy: + print("Running manual evaluation because evaluation_strategy was not available...") + eval_metrics = trainer.evaluate(eval_dataset=tokenized_datasets["eval"]) + print("Trainer.evaluate metrics:", eval_metrics) + +# Save model and tokenizer +trainer.save_model("./price-predictor-finetuned") +try: + tokenizer.save_pretrained("./price-predictor-finetuned") +except Exception as e: + print("Could not save tokenizer:", e) + +#outcomes +#train_result = trainer.train() +trainer.save_model("./price-predictor-finetuned") + +# Loading fine-tuned model +model = AutoModelForCausalLM.from_pretrained("./price-predictor-finetuned", device_map="auto") +tokenizer = AutoTokenizer.from_pretrained("./price-predictor-finetuned") + +#small evaluation subset +eval_dataset_small = dataset["eval"].shuffle(seed=42).select(range(min(50, len(dataset["eval"])))) +pred_prices, true_prices = [], [] + +pred_prices = [] +true_prices = [] + +for ex in tqdm(eval_dataset_small, desc="Evaluating"): + # check which column exists + if "target_str" in ex: + true_price_log = float(ex["target_str"]) + true_price = np.expm1(true_price_log) # convert back from log1p + elif "output" in ex: + true_price = float(ex["output"]) + elif "price_clean" in ex: + true_price = float(ex["price_clean"]) + else: + raise KeyError("No valid price column found in eval example.") + + # Skip invalid prices + if np.isnan(true_price): + continue + + prompt = f"### Instruction:\nEstimate the fair market price of this product in USD. Return only a single number.\n\n### Input:\n{ex.get('text', ex.get('input', ''))}\n\n### Response:" + inputs = tokenizer(prompt, return_tensors="pt").to(model.device) + + with torch.no_grad(): + output = model.generate(**inputs, max_new_tokens=20, temperature=0.2, do_sample=False) + + text = tokenizer.decode(output[0], skip_special_tokens=True) + + # Extract numeric prediction + numbers = re.findall(r"[-+]?\d*\.\d+|\d+", text) + if not numbers: + continue + + pred = float(numbers[-1]) + + # If you trained on log prices, exponentiate to get back to USD + if "target_str" in ex: + pred = np.expm1(pred) + + pred_prices.append(pred) + true_prices.append(true_price) + +# -- Compute metrics -- +pred_prices = np.array(pred_prices) +true_prices = np.array(true_prices) + +mae = mean_absolute_error(true_prices, pred_prices) +rmse = np.sqrt(mean_squared_error(true_prices, pred_prices)) +r2 = r2_score(true_prices, pred_prices) + +print(f"\nFine-Tuned Evaluation:\nMAE: ${mae:.2f}, RMSE: ${rmse:.2f}, R²: {r2:.4f}") + +# #iteration Over the tqdm +# for ex in tqdm(eval_dataset_small, desc="Evaluating"): +# prompt = f"### Instruction:\nEstimate the fair market price of this product in USD. Return only a single number.\n\n### Input:\n{ex['input']}\n\n### Response:" +# inputs = tokenizer(prompt, return_tensors="pt").to(model.device) +# with torch.no_grad(): +# output = model.generate(**inputs, max_new_tokens=20) +# text = tokenizer.decode(output[0], skip_special_tokens=True) + +# # Extract numeric prediction +# numbers = re.findall(r"[-+]?\d*\.\d+|\d+", text) +# pred = float(numbers[-1]) if numbers else np.nan + +# pred_prices.append(pred) +# true_prices.append(float(ex["output"])) + +# Filter out invalid predictions +mask = ~np.isnan(pred_prices) + +pred_prices = np.array(pred_prices)[mask] + +true_prices = np.array(true_prices)[mask] + +# Compute metrics manually again +mae = mean_absolute_error(true_prices, pred_prices) + +mse = mean_squared_error(true_prices, pred_prices) + +rmse = np.sqrt(mse) + +r2 = r2_score(true_prices, pred_prices) + +print(f"Fine-Tuned Evaluation:\nMAE: ${mae:.2f}, RMSE: ${rmse:.2f}, R²: {r2:.4f}") + +#see what was predicted +plt.figure(figsize=(6,6)) +plt.scatter(true_prices, pred_prices, alpha=0.5) +plt.plot([0, max(true_prices)], [0, max(true_prices)], 'r--', label="Perfect Prediction") +plt.xlabel("Actual Price (USD)") +plt.ylabel("Predicted Price (USD)") +plt.title("Predicted vs Actual Prices") +plt.legend() +plt.grid(True) +plt.show() \ No newline at end of file diff --git a/week8/community_contributions/muthama/price_is_right_final.py b/week8/community_contributions/muthama/price_is_right_final.py new file mode 100644 index 0000000..eb32e6b --- /dev/null +++ b/week8/community_contributions/muthama/price_is_right_final.py @@ -0,0 +1,164 @@ +import logging +import queue +import threading +import time +import gradio as gr +import plotly.graph_objects as go + +from deal_agent_framework import DealAgentFramework +# from agents.deals import Opportunity, Deal +from log_utils import reformat + + + +class QueueHandler(logging.Handler): + def __init__(self, log_queue): + super().__init__() + self.log_queue = log_queue + + def emit(self, record): + self.log_queue.put(self.format(record)) + +def html_for(log_data): + output = '
'.join(log_data[-18:]) + return f""" +
+ {output} +
+ """ + +def setup_logging(log_queue): + handler = QueueHandler(log_queue) + formatter = logging.Formatter( + "[%(asctime)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S %z", + ) + handler.setFormatter(formatter) + logger = logging.getLogger() + logger.addHandler(handler) + logger.setLevel(logging.INFO) + + +class App: + + def __init__(self): + self.agent_framework = None + + def get_agent_framework(self): + if not self.agent_framework: + self.agent_framework = DealAgentFramework() + self.agent_framework.init_agents_as_needed() + return self.agent_framework + + def run(self): + with gr.Blocks(title="The Price is Right", fill_width=True) as ui: + + log_data = gr.State([]) + + def table_for(opps): + return [[opp.deal.product_description, f"${opp.deal.price:.2f}", f"${opp.estimate:.2f}", f"${opp.discount:.2f}", opp.deal.url] for opp in opps] + + def update_output(log_data, log_queue, result_queue): + def live_table(): + return table_for(self.get_agent_framework().memory) + + final_result = None + while True: + try: + message = log_queue.get_nowait() + log_data.append(reformat(message)) + yield log_data, html_for(log_data), live_table() + continue + except queue.Empty: + pass + + try: + final_result = result_queue.get_nowait() + yield log_data, html_for(log_data), (final_result or live_table()) + break + except queue.Empty: + time.sleep(0.05) + + def get_plot(): + documents, vectors, colors = DealAgentFramework.get_plot_data(max_datapoints=1000) + # Create the 3D scatter plot + fig = go.Figure(data=[go.Scatter3d( + x=vectors[:, 0], + y=vectors[:, 1], + z=vectors[:, 2], + mode='markers', + marker=dict(size=2, color=colors, opacity=0.7), + )]) + + fig.update_layout( + scene=dict(xaxis_title='x', + yaxis_title='y', + zaxis_title='z', + aspectmode='manual', + aspectratio=dict(x=2.2, y=2.2, z=1), # Make x-axis twice as long + camera=dict( + eye=dict(x=1.6, y=1.6, z=0.8) # Adjust camera position + )), + height=400, + margin=dict(r=5, b=1, l=5, t=2) + ) + + return fig + + def do_run(): + new_opportunities = self.get_agent_framework().run() + table = table_for(new_opportunities) + return table + + def run_with_logging(initial_log_data): + log_queue = queue.Queue() + result_queue = queue.Queue() + setup_logging(log_queue) + + def worker(): + result = do_run() # this updates memory during execution + result_queue.put(result) + + thread = threading.Thread(target=worker, daemon=True) + thread.start() + + for log_data, output_html, table in update_output(initial_log_data, log_queue, result_queue): + yield log_data, output_html, table + + def do_select(selected_index: gr.SelectData): + opportunities = self.get_agent_framework().memory + row = selected_index.index[0] + opportunity = opportunities[row] + self.get_agent_framework().planner.messenger.alert(opportunity) + + with gr.Row(): + gr.Markdown('
The Price is Right - Autonomous Agent Framework that hunts for deals
') + with gr.Row(): + gr.Markdown('
A proprietary fine-tuned LLM deployed on Modal and a RAG pipeline with a frontier model collaborate to send push notifications with great online deals.
') + with gr.Row(): + opportunities_dataframe = gr.Dataframe( + headers=["Deals found so far", "Price", "Estimate", "Discount", "URL"], + wrap=True, + column_widths=[6, 1, 1, 1, 3], + row_count=10, + col_count=5, + max_height=400, + ) + with gr.Row(): + with gr.Column(scale=1): + logs = gr.HTML() + with gr.Column(scale=1): + plot = gr.Plot(value=get_plot(), show_label=False) + + ui.load(run_with_logging, inputs=[log_data], outputs=[log_data, logs, opportunities_dataframe]) + + timer = gr.Timer(value=300, active=True) + timer.tick(run_with_logging, inputs=[log_data], outputs=[log_data, logs, opportunities_dataframe]) + + opportunities_dataframe.select(do_select) + + ui.launch(share=False, inbrowser=True) + +if __name__=="__main__": + App().run() + \ No newline at end of file diff --git a/week8/community_contributions/muthama/week8_exercise_solution-Stephen.ipynb b/week8/community_contributions/muthama/week8_exercise_solution-Stephen.ipynb new file mode 100644 index 0000000..75da0cf --- /dev/null +++ b/week8/community_contributions/muthama/week8_exercise_solution-Stephen.ipynb @@ -0,0 +1,88 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "a71ed017-e1b0-4299-88b3-f0eb05adc4df", + "metadata": {}, + "source": [ + "# The Price is Right\n", + "\n", + "The final step is to build a User Interface\n", + "\n", + "We will use more advanced aspects of Gradio - building piece by piece." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b77940b8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "133.0\n" + ] + } + ], + "source": [ + "import modal" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6449363f", + "metadata": {}, + "outputs": [], + "source": [ + "!modal deploy -m pricer_service2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c67160e", + "metadata": {}, + "outputs": [], + "source": [ + "Pricer = modal.Cls.from_name(\"pricer-service\", \"Pricer\")\n", + "pricer = Pricer()\n", + "reply = pricer.price.remote(\"Quadcast HyperX condenser mic, connects via usb-c to your computer for crystal clear audio\")\n", + "print(reply)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "48506465-1c7a-433f-a665-b277a8b4665c", + "metadata": {}, + "outputs": [], + "source": [ + "!python price_is_right_final.py" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/week8/community_contributions/w8d5/agents/__init__.py b/week8/community_contributions/w8d5/agents/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/week8/community_contributions/w8d5/agents/agent.py b/week8/community_contributions/w8d5/agents/agent.py new file mode 100644 index 0000000..fe09e18 --- /dev/null +++ b/week8/community_contributions/w8d5/agents/agent.py @@ -0,0 +1,33 @@ +import logging + +class Agent: + """ + An abstract superclass for Agents + Used to log messages in a way that can identify each Agent + """ + + # Foreground colors + RED = '\033[31m' + GREEN = '\033[32m' + YELLOW = '\033[33m' + BLUE = '\033[34m' + MAGENTA = '\033[35m' + CYAN = '\033[36m' + WHITE = '\033[37m' + + # Background color + BG_BLACK = '\033[40m' + + # Reset code to return to default color + RESET = '\033[0m' + + name: str = "" + color: str = '\033[37m' + + def log(self, message): + """ + Log this as an info message, identifying the agent + """ + color_code = self.BG_BLACK + self.color + message = f"[{self.name}] {message}" + logging.info(color_code + message + self.RESET) \ No newline at end of file diff --git a/week8/community_contributions/w8d5/agents/travel_estimator_agent.py b/week8/community_contributions/w8d5/agents/travel_estimator_agent.py new file mode 100644 index 0000000..c809a79 --- /dev/null +++ b/week8/community_contributions/w8d5/agents/travel_estimator_agent.py @@ -0,0 +1,75 @@ +import os +import re +import sys +from typing import List, Dict +from openai import OpenAI +from sentence_transformers import SentenceTransformer + +w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) + +from agents.agent import Agent + + +class TravelEstimatorAgent(Agent): + + name = "Travel Estimator" + color = Agent.BLUE + + MODEL = "gpt-4o-mini" + + def __init__(self, collection): + self.log("Travel Estimator initializing") + self.client = OpenAI() + self.MODEL = "gpt-4o-mini" + self.log("Travel Estimator using OpenAI") + self.collection = collection + self.model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') + self.log("Travel Estimator ready") + + def make_context(self, similars: List[str], prices: List[float]) -> str: + message = "Here are similar travel deals for context:\n\n" + for similar, price in zip(similars, prices): + message += f"Similar deal:\n{similar}\nPrice: ${price:.2f}\n\n" + return message + + def messages_for(self, description: str, similars: List[str], prices: List[float]) -> List[Dict[str, str]]: + system_message = "You estimate fair market prices for travel deals. Reply only with the price estimate, no explanation" + user_prompt = self.make_context(similars, prices) + user_prompt += "Now estimate the fair market price for:\n\n" + user_prompt += description + return [ + {"role": "system", "content": system_message}, + {"role": "user", "content": user_prompt}, + {"role": "assistant", "content": "Fair price estimate: $"} + ] + + def find_similars(self, description: str): + self.log("Travel Estimator searching for similar deals") + vector = self.model.encode([description]) + results = self.collection.query(query_embeddings=vector.astype(float).tolist(), n_results=5) + documents = results['documents'][0][:] + prices = [m['price'] for m in results['metadatas'][0][:]] + self.log("Travel Estimator found similar deals") + return documents, prices + + def get_price(self, s) -> float: + s = s.replace('$','').replace(',','') + match = re.search(r"[-+]?\d*\.\d+|\d+", s) + return float(match.group()) if match else 0.0 + + def estimate(self, description: str) -> float: + documents, prices = self.find_similars(description) + self.log(f"Travel Estimator calling {self.MODEL}") + response = self.client.chat.completions.create( + model=self.MODEL, + messages=self.messages_for(description, documents, prices), + seed=42, + max_tokens=10 + ) + reply = response.choices[0].message.content + result = self.get_price(reply) + self.log(f"Travel Estimator complete - ${result:.2f}") + return result + diff --git a/week8/community_contributions/w8d5/agents/travel_messaging_agent.py b/week8/community_contributions/w8d5/agents/travel_messaging_agent.py new file mode 100644 index 0000000..541ad71 --- /dev/null +++ b/week8/community_contributions/w8d5/agents/travel_messaging_agent.py @@ -0,0 +1,48 @@ +import os +import sys +import http.client +import urllib + +w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) + +from agents.agent import Agent +from helpers.travel_deals import TravelOpportunity + +DO_PUSH = True + +class TravelMessagingAgent(Agent): + + name = "Travel Messenger" + color = Agent.WHITE + + def __init__(self): + self.log("Travel Messenger initializing") + if DO_PUSH: + self.pushover_user = os.getenv('PUSHOVER_USER', 'your-pushover-user-if-not-using-env') + self.pushover_token = os.getenv('PUSHOVER_TOKEN', 'your-pushover-token-if-not-using-env') + self.log("Travel Messenger has initialized Pushover") + + def push(self, text): + self.log("Travel Messenger sending push notification") + conn = http.client.HTTPSConnection("api.pushover.net:443") + conn.request("POST", "/1/messages.json", + urllib.parse.urlencode({ + "token": self.pushover_token, + "user": self.pushover_user, + "message": text, + "sound": "cashregister" + }), { "Content-type": "application/x-www-form-urlencoded" }) + conn.getresponse() + + def alert(self, opportunity: TravelOpportunity): + text = f"Travel Deal! {opportunity.deal.destination} - " + text += f"Price=${opportunity.deal.price:.2f}, " + text += f"Est=${opportunity.estimate:.2f}, " + text += f"Save ${opportunity.discount:.2f}! " + text += opportunity.deal.url + if DO_PUSH: + self.push(text) + self.log("Travel Messenger completed") + diff --git a/week8/community_contributions/w8d5/agents/travel_planning_agent.py b/week8/community_contributions/w8d5/agents/travel_planning_agent.py new file mode 100644 index 0000000..75f4132 --- /dev/null +++ b/week8/community_contributions/w8d5/agents/travel_planning_agent.py @@ -0,0 +1,57 @@ +import os +import sys +from typing import Optional, List + +w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) + +from agents.agent import Agent +from helpers.travel_deals import TravelDeal, TravelOpportunity +from agents.travel_scanner_agent import TravelScannerAgent +from agents.travel_estimator_agent import TravelEstimatorAgent +from agents.travel_messaging_agent import TravelMessagingAgent + + +class TravelPlanningAgent(Agent): + + name = "Travel Planner" + color = Agent.GREEN + DEAL_THRESHOLD = 50 + + def __init__(self, collection): + self.log("Travel Planner initializing") + self.scanner = TravelScannerAgent() + self.estimator = TravelEstimatorAgent(collection) + self.messenger = TravelMessagingAgent() + self.log("Travel Planner ready") + + def evaluate(self, deal: TravelDeal) -> TravelOpportunity: + self.log(f"Travel Planner evaluating {deal.destination}") + estimate = self.estimator.estimate(deal.description) + discount = estimate - deal.price + self.log(f"Travel Planner found discount ${discount:.2f}") + return TravelOpportunity(deal=deal, estimate=estimate, discount=discount) + + def plan(self, memory: List[str] = []) -> Optional[List[TravelOpportunity]]: + self.log("Travel Planner starting run") + selection = self.scanner.scan(memory=memory) + if selection and selection.deals: + opportunities = [self.evaluate(deal) for deal in selection.deals[:5]] + if not opportunities: + self.log("Travel Planner found no valid opportunities") + return None + opportunities.sort(key=lambda opp: opp.discount, reverse=True) + good_deals = [opp for opp in opportunities if opp.discount > self.DEAL_THRESHOLD] + if good_deals: + best = good_deals[0] + self.log(f"Travel Planner found {len(good_deals)} deals above threshold, best: ${best.discount:.2f} off") + self.messenger.alert(best) + self.log("Travel Planner completed") + return good_deals + else: + self.log(f"Travel Planner completed - no deals above ${self.DEAL_THRESHOLD} threshold") + return None + self.log("Travel Planner found no deals to evaluate") + return None + diff --git a/week8/community_contributions/w8d5/agents/travel_scanner_agent.py b/week8/community_contributions/w8d5/agents/travel_scanner_agent.py new file mode 100644 index 0000000..0d0b504 --- /dev/null +++ b/week8/community_contributions/w8d5/agents/travel_scanner_agent.py @@ -0,0 +1,87 @@ +import os +import sys +from typing import Optional, List +from openai import OpenAI + +w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) + +from agents.agent import Agent +from helpers.travel_deals import ScrapedTravelDeal, TravelDealSelection + + +class TravelScannerAgent(Agent): + + MODEL = "gpt-4o-mini" + + SYSTEM_PROMPT = """You identify and summarize the 5 most promising travel deals from a list. + Focus on deals with destinations, deal types (flight/hotel/package), and detailed descriptions. + If price is mentioned, extract it. If no specific price is given but there's a discount mentioned (e.g. "30% off"), estimate a reasonable price. + If absolutely no pricing information exists, use a placeholder price of 500. + Respond strictly in JSON with no explanation. + + {"deals": [ + { + "destination": "City or Country name", + "deal_type": "Flight, Hotel, or Package", + "description": "4-5 sentences describing the travel deal, dates, what's included, and key highlights", + "price": 499.99, + "url": "the url as provided" + }, + ... + ]}""" + + USER_PROMPT_PREFIX = """Respond with the 5 most promising travel deals with destinations, types, and descriptions. + Respond strictly in JSON. Provide detailed descriptions focusing on what travelers get. + Extract the destination and deal type (Flight/Hotel/Package) from the title and description. + For pricing: extract exact prices if available, estimate from percentage discounts, or use 500 as placeholder. + + Travel Deals: + + """ + + USER_PROMPT_SUFFIX = "\n\nStrictly respond in JSON with exactly 5 deals." + + name = "Travel Scanner" + color = Agent.CYAN + + def __init__(self): + self.log("Travel Scanner is initializing") + self.openai = OpenAI() + self.log("Travel Scanner is ready") + + def fetch_deals(self, memory) -> List[ScrapedTravelDeal]: + self.log("Travel Scanner fetching deals from RSS feeds") + urls = [opp.deal.url for opp in memory] + scraped = ScrapedTravelDeal.fetch() + result = [scrape for scrape in scraped if scrape.url not in urls] + self.log(f"Travel Scanner found {len(result)} new deals") + return result + + def make_user_prompt(self, scraped) -> str: + user_prompt = self.USER_PROMPT_PREFIX + user_prompt += '\n\n'.join([scrape.describe() for scrape in scraped]) + user_prompt += self.USER_PROMPT_SUFFIX + return user_prompt + + def scan(self, memory: List[str]=[]) -> Optional[TravelDealSelection]: + scraped = self.fetch_deals(memory) + if scraped: + user_prompt = self.make_user_prompt(scraped) + self.log("Travel Scanner calling OpenAI") + result = self.openai.beta.chat.completions.parse( + model=self.MODEL, + messages=[ + {"role": "system", "content": self.SYSTEM_PROMPT}, + {"role": "user", "content": user_prompt} + ], + response_format=TravelDealSelection + ) + result = result.choices[0].message.parsed + valid_deals = [deal for deal in result.deals if deal.price > 0] + result.deals = valid_deals + self.log(f"Travel Scanner received {len(result.deals)} valid deals") + return result if result.deals else None + return None + diff --git a/week8/community_contributions/w8d5/agents/travel_xgboost_agent.py b/week8/community_contributions/w8d5/agents/travel_xgboost_agent.py new file mode 100644 index 0000000..09c9a45 --- /dev/null +++ b/week8/community_contributions/w8d5/agents/travel_xgboost_agent.py @@ -0,0 +1,73 @@ +import os +import sys +import numpy as np +import joblib +from sentence_transformers import SentenceTransformer +import xgboost as xgb + +w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) + +from agents.agent import Agent + + +class TravelXGBoostAgent(Agent): + + name = "XGBoost Estimator" + color = Agent.GREEN + + def __init__(self, collection): + self.log("XGBoost Estimator initializing") + self.collection = collection + self.model_path = os.path.join(w8d5_path, 'helpers', 'travel_xgboost_model.pkl') + self.embedder = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') + + if os.path.exists(self.model_path): + self.log("Loading existing XGBoost model") + self.model = joblib.load(self.model_path) + else: + self.log("Training new XGBoost model") + self.model = self._train_model() + joblib.dump(self.model, self.model_path) + self.log(f"XGBoost model saved to {self.model_path}") + + self.log("XGBoost Estimator ready") + + def _train_model(self): + self.log("Fetching training data from ChromaDB") + result = self.collection.get(include=['embeddings', 'metadatas']) + + X = np.array(result['embeddings']) + y = np.array([m['price'] for m in result['metadatas']]) + + self.log(f"Training on {len(X)} samples") + + model = xgb.XGBRegressor( + n_estimators=100, + max_depth=6, + learning_rate=0.1, + subsample=0.8, + colsample_bytree=0.8, + random_state=42, + n_jobs=-1 + ) + + model.fit(X, y) + self.log("XGBoost training complete") + + return model + + def estimate(self, description: str) -> float: + self.log(f"XGBoost estimating price for: {description[:50]}...") + + embedding = self.embedder.encode([description])[0] + embedding_2d = embedding.reshape(1, -1) + + prediction = self.model.predict(embedding_2d)[0] + + prediction = max(0, prediction) + + self.log(f"XGBoost estimate: ${prediction:.2f}") + return float(prediction) + diff --git a/week8/community_contributions/w8d5/helpers/__init__.py b/week8/community_contributions/w8d5/helpers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/week8/community_contributions/w8d5/helpers/create_travel_vectorstore.py b/week8/community_contributions/w8d5/helpers/create_travel_vectorstore.py new file mode 100644 index 0000000..87bf87a --- /dev/null +++ b/week8/community_contributions/w8d5/helpers/create_travel_vectorstore.py @@ -0,0 +1,230 @@ +import os +import random +from dotenv import load_dotenv +from huggingface_hub import login +from sentence_transformers import SentenceTransformer +import chromadb +from tqdm import tqdm + +load_dotenv(override=True) +os.environ['HF_TOKEN'] = os.getenv('HF_TOKEN', 'your-key-if-not-using-env') + +hf_token = os.environ['HF_TOKEN'] +login(hf_token, add_to_git_credential=True) + +DB = "travel_vectorstore" +CATEGORIES = ['Flights', 'Hotels', 'Car_Rentals', 'Vacation_Packages', 'Cruises', 'Activities'] + +AIRLINES = ['American Airlines', 'Delta', 'United', 'Southwest', 'JetBlue', 'Spirit', 'Frontier', 'Alaska Airlines', 'Emirates', 'British Airways', 'Air France', 'Lufthansa', 'Qatar Airways'] +CITIES = ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Miami', 'San Francisco', 'Boston', 'Seattle', 'Denver', 'Atlanta', 'Las Vegas', 'Orlando', 'Phoenix', 'London', 'Paris', 'Tokyo', 'Dubai', 'Singapore', 'Sydney', 'Rome'] +HOTELS = ['Hilton', 'Marriott', 'Hyatt', 'Holiday Inn', 'Best Western', 'Sheraton', 'Ritz-Carlton', 'Four Seasons', 'Westin', 'Radisson'] +CLASSES = ['Economy', 'Premium Economy', 'Business', 'First Class'] +CAR_COMPANIES = ['Hertz', 'Enterprise', 'Avis', 'Budget', 'National', 'Alamo'] +CAR_TYPES = ['Compact', 'Sedan', 'SUV', 'Luxury', 'Van'] + +def generate_flight_description(): + airline = random.choice(AIRLINES) + source = random.choice(CITIES) + dest = random.choice([c for c in CITIES if c != source]) + flight_class = random.choice(CLASSES) + stops = random.choice(['non-stop', 'one-stop', 'two-stops']) + duration = f"{random.randint(1, 15)} hours {random.randint(0, 59)} minutes" + + description = f"{airline} {flight_class} {stops} flight from {source} to {dest}. " + description += f"Flight duration approximately {duration}. " + + if random.random() > 0.5: + description += f"Includes {random.randint(1, 2)} checked bag" + if random.random() > 0.5: + description += "s" + description += ". " + + if flight_class in ['Business', 'First Class']: + description += random.choice(['Priority boarding included. ', 'Lounge access available. ', 'Lie-flat seats. ']) + + price = random.randint(150, 2500) if flight_class == 'Economy' else random.randint(800, 8000) + return description, price + +def generate_hotel_description(): + hotel = random.choice(HOTELS) + city = random.choice(CITIES) + stars = random.randint(2, 5) + room_type = random.choice(['Standard Room', 'Deluxe Room', 'Suite', 'Executive Suite']) + nights = random.randint(1, 7) + + description = f"{hotel} {stars}-star hotel in {city}. {room_type} for {nights} night" + if nights > 1: + description += "s" + description += ". " + + amenities = [] + if random.random() > 0.3: + amenities.append('Free WiFi') + if random.random() > 0.5: + amenities.append('Breakfast included') + if random.random() > 0.6: + amenities.append('Pool access') + if random.random() > 0.7: + amenities.append('Gym') + if random.random() > 0.8: + amenities.append('Spa services') + + if amenities: + description += f"Amenities: {', '.join(amenities)}. " + + price_per_night = random.randint(80, 500) if stars <= 3 else random.randint(200, 1200) + total_price = price_per_night * nights + + return description, total_price + +def generate_car_rental_description(): + company = random.choice(CAR_COMPANIES) + car_type = random.choice(CAR_TYPES) + city = random.choice(CITIES) + days = random.randint(1, 14) + + description = f"{company} car rental in {city}. {car_type} class vehicle for {days} day" + if days > 1: + description += "s" + description += ". " + + if random.random() > 0.6: + description += "Unlimited mileage included. " + if random.random() > 0.5: + description += "Airport pickup available. " + if random.random() > 0.7: + description += "GPS navigation included. " + + daily_rate = {'Compact': random.randint(25, 45), 'Sedan': random.randint(35, 65), 'SUV': random.randint(50, 90), 'Luxury': random.randint(80, 200), 'Van': random.randint(60, 100)} + total_price = daily_rate[car_type] * days + + return description, total_price + +def generate_vacation_package_description(): + city = random.choice(CITIES) + nights = random.randint(3, 10) + + description = f"All-inclusive vacation package to {city} for {nights} nights. " + description += f"Includes round-trip {random.choice(CLASSES)} flights, {random.choice(HOTELS)} hotel accommodation, " + + extras = [] + if random.random() > 0.3: + extras.append('daily breakfast') + if random.random() > 0.5: + extras.append('airport transfers') + if random.random() > 0.6: + extras.append('city tour') + if random.random() > 0.7: + extras.append('travel insurance') + + if extras: + description += f"and {', '.join(extras)}. " + + base_price = random.randint(800, 4000) + return description, base_price + +def generate_cruise_description(): + destinations = [', '.join(random.sample(['Caribbean', 'Mediterranean', 'Alaska', 'Hawaii', 'Baltic Sea', 'South Pacific'], k=random.randint(2, 4)))] + nights = random.choice([3, 5, 7, 10, 14]) + + description = f"{nights}-night cruise visiting {destinations[0]}. " + description += f"All meals and entertainment included. " + + cabin_type = random.choice(['Interior cabin', 'Ocean view cabin', 'Balcony cabin', 'Suite']) + description += f"{cabin_type}. " + + if random.random() > 0.5: + description += "Unlimited beverage package available. " + if random.random() > 0.6: + description += "Shore excursions at each port. " + + base_price = random.randint(500, 5000) + return description, base_price + +def generate_activity_description(): + city = random.choice(CITIES) + activities = ['City sightseeing tour', 'Museum pass', 'Adventure sports package', 'Wine tasting tour', 'Cooking class', 'Hot air balloon ride', 'Snorkeling excursion', 'Helicopter tour', 'Spa day package', 'Theme park tickets'] + activity = random.choice(activities) + + description = f"{activity} in {city}. " + + if 'tour' in activity.lower(): + description += f"Duration: {random.randint(2, 8)} hours. " + if random.random() > 0.5: + description += "Hotel pickup included. " + if random.random() > 0.6: + description += "Small group experience. " + + price = random.randint(30, 500) + return description, price + +GENERATORS = { + 'Flights': generate_flight_description, + 'Hotels': generate_hotel_description, + 'Car_Rentals': generate_car_rental_description, + 'Vacation_Packages': generate_vacation_package_description, + 'Cruises': generate_cruise_description, + 'Activities': generate_activity_description +} + +print("Generating synthetic travel dataset...") +travel_data = [] + +items_per_category = 3334 +for category in CATEGORIES: + print(f"Generating {category}...") + generator = GENERATORS[category] + for _ in range(items_per_category): + description, price = generator() + travel_data.append((description, float(price), category)) + +random.shuffle(travel_data) +print(f"Generated {len(travel_data)} travel deals") + +print("\nInitializing SentenceTransformer model...") +model = SentenceTransformer('sentence-transformers/all-MiniLM-L6-v2') + +print(f"Connecting to ChromaDB at {DB}...") +client = chromadb.PersistentClient(path=DB) + +collection_name = "travel_deals" +existing_collections = [col.name for col in client.list_collections()] +if collection_name in existing_collections: + client.delete_collection(collection_name) + print(f"Deleted existing collection: {collection_name}") + +collection = client.create_collection(collection_name) +print(f"Created new collection: {collection_name}") + +print("\nCreating embeddings and adding to ChromaDB...") +for i in tqdm(range(0, len(travel_data), 1000)): + batch = travel_data[i:i+1000] + documents = [desc for desc, _, _ in batch] + vectors = model.encode(documents).astype(float).tolist() + metadatas = [{"category": cat, "price": price} for _, price, cat in batch] + ids = [f"travel_{j}" for j in range(i, i+len(batch))] + + collection.add( + ids=ids, + documents=documents, + embeddings=vectors, + metadatas=metadatas + ) + +total_items = collection.count() +print(f"\nVectorstore created successfully with {total_items} travel deals") + +result = collection.get(include=['metadatas'], limit=total_items) +categories = [m['category'] for m in result['metadatas']] +prices = [m['price'] for m in result['metadatas']] +category_counts = {} +for cat in categories: + category_counts[cat] = category_counts.get(cat, 0) + 1 + +print("\nCategory distribution:") +for category, count in sorted(category_counts.items()): + print(f" {category}: {count}") + +avg_price = sum(prices) / len(prices) if prices else 0 +print(f"\nAverage price: ${avg_price:.2f}") +print(f"Price range: ${min(prices):.2f} - ${max(prices):.2f}") diff --git a/week8/community_contributions/w8d5/helpers/travel_deal_framework.py b/week8/community_contributions/w8d5/helpers/travel_deal_framework.py new file mode 100644 index 0000000..9f4296c --- /dev/null +++ b/week8/community_contributions/w8d5/helpers/travel_deal_framework.py @@ -0,0 +1,99 @@ +import os +import sys +import logging +import json +from typing import List, Optional +from dotenv import load_dotenv +import chromadb +import numpy as np +from sklearn.manifold import TSNE + +w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) + +from agents.travel_planning_agent import TravelPlanningAgent +from helpers.travel_deals import TravelOpportunity + +BG_BLUE = '\033[44m' +WHITE = '\033[37m' +RESET = '\033[0m' + +CATEGORIES = ['Flights', 'Hotels', 'Car_Rentals', 'Vacation_Packages', 'Cruises', 'Activities'] +COLORS = ['red', 'blue', 'green', 'orange', 'purple', 'cyan'] + +def init_logging(): + root = logging.getLogger() + root.setLevel(logging.INFO) + + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.INFO) + formatter = logging.Formatter( + "[%(asctime)s] [Travel Agents] [%(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S %z", + ) + handler.setFormatter(formatter) + root.addHandler(handler) + +class TravelDealFramework: + + DB = "travel_vectorstore" + MEMORY_FILENAME = "travel_memory.json" + + def __init__(self): + init_logging() + load_dotenv() + client = chromadb.PersistentClient(path=self.DB) + self.memory = self.read_memory() + self.collection = client.get_or_create_collection('travel_deals') + self.planner = None + + def init_agents_as_needed(self): + if not self.planner: + self.log("Initializing Travel Agent Framework") + self.planner = TravelPlanningAgent(self.collection) + self.log("Travel Agent Framework ready") + + def read_memory(self) -> List[TravelOpportunity]: + if os.path.exists(self.MEMORY_FILENAME): + with open(self.MEMORY_FILENAME, "r") as file: + data = json.load(file) + opportunities = [TravelOpportunity(**item) for item in data] + return opportunities + return [] + + def write_memory(self) -> None: + data = [opportunity.dict() for opportunity in self.memory] + with open(self.MEMORY_FILENAME, "w") as file: + json.dump(data, file, indent=2) + + def log(self, message: str): + text = BG_BLUE + WHITE + "[Travel Framework] " + message + RESET + logging.info(text) + + def run(self) -> List[TravelOpportunity]: + self.init_agents_as_needed() + logging.info("Starting Travel Planning Agent") + results = self.planner.plan(memory=self.memory) + logging.info(f"Travel Planning Agent completed with {len(results) if results else 0} results") + if results: + self.memory.extend(results) + self.write_memory() + return self.memory + + @classmethod + def get_plot_data(cls, max_datapoints=10000): + client = chromadb.PersistentClient(path=cls.DB) + collection = client.get_or_create_collection('travel_deals') + result = collection.get(include=['embeddings', 'documents', 'metadatas'], limit=max_datapoints) + vectors = np.array(result['embeddings']) + documents = result['documents'] + categories = [metadata['category'] for metadata in result['metadatas']] + colors = [COLORS[CATEGORIES.index(c)] for c in categories] + tsne = TSNE(n_components=3, random_state=42, n_jobs=-1) + reduced_vectors = tsne.fit_transform(vectors) + return documents, reduced_vectors, colors + +if __name__=="__main__": + TravelDealFramework().run() + diff --git a/week8/community_contributions/w8d5/helpers/travel_deals.py b/week8/community_contributions/w8d5/helpers/travel_deals.py new file mode 100644 index 0000000..7f05300 --- /dev/null +++ b/week8/community_contributions/w8d5/helpers/travel_deals.py @@ -0,0 +1,67 @@ +from pydantic import BaseModel +from typing import List, Dict, Self +from bs4 import BeautifulSoup +import re +import feedparser +from tqdm import tqdm +import requests +import time + +feeds = [ + "https://thepointsguy.com/feed/", +] + +def extract(html_snippet: str) -> str: + soup = BeautifulSoup(html_snippet, 'html.parser') + text = soup.get_text(strip=True) + text = re.sub('<[^<]+?>', '', text) + return text.replace('\n', ' ').strip() + +class ScrapedTravelDeal: + title: str + summary: str + url: str + details: str + + def __init__(self, entry: Dict[str, str]): + self.title = entry.get('title', '') + summary_text = entry.get('summary', entry.get('description', '')) + self.summary = extract(summary_text) + self.url = entry.get('link', '') + self.details = self.summary + + def __repr__(self): + return f"<{self.title}>" + + def describe(self): + return f"Title: {self.title}\nDetails: {self.details.strip()}\nURL: {self.url}" + + @classmethod + def fetch(cls, show_progress: bool = False) -> List[Self]: + deals = [] + feed_iter = tqdm(feeds) if show_progress else feeds + for feed_url in feed_iter: + try: + feed = feedparser.parse(feed_url) + for entry in feed.entries[:10]: + deals.append(cls(entry)) + time.sleep(0.3) + except Exception as e: + print(f"Error fetching {feed_url}: {e}") + return deals + +class TravelDeal(BaseModel): + destination: str + deal_type: str + description: str + price: float + url: str + +class TravelDealSelection(BaseModel): + deals: List[TravelDeal] + +class TravelOpportunity(BaseModel): + deal: TravelDeal + estimate: float + discount: float + diff --git a/week8/community_contributions/w8d5/helpers/travel_dual_framework.py b/week8/community_contributions/w8d5/helpers/travel_dual_framework.py new file mode 100644 index 0000000..ad8344e --- /dev/null +++ b/week8/community_contributions/w8d5/helpers/travel_dual_framework.py @@ -0,0 +1,161 @@ +import os +import sys +import logging +import json +from typing import List, Tuple +from dotenv import load_dotenv +import chromadb +import numpy as np +from sklearn.manifold import TSNE + +w8d5_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) + +from agents.travel_scanner_agent import TravelScannerAgent +from agents.travel_estimator_agent import TravelEstimatorAgent +from agents.travel_xgboost_agent import TravelXGBoostAgent +from agents.travel_messaging_agent import TravelMessagingAgent +from helpers.travel_deals import TravelOpportunity, TravelDeal + +BG_BLUE = '\033[44m' +WHITE = '\033[37m' +RESET = '\033[0m' + +CATEGORIES = ['Flights', 'Hotels', 'Car_Rentals', 'Vacation_Packages', 'Cruises', 'Activities'] +COLORS = ['red', 'blue', 'green', 'orange', 'purple', 'cyan'] + +def init_logging(): + root = logging.getLogger() + root.setLevel(logging.INFO) + + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.INFO) + formatter = logging.Formatter( + "[%(asctime)s] [Travel Agents] [%(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S %z", + ) + handler.setFormatter(formatter) + root.addHandler(handler) + + +class TravelDualFramework: + + DB = "travel_vectorstore" + LLM_MEMORY_FILE = "travel_memory_llm.json" + XGB_MEMORY_FILE = "travel_memory_xgb.json" + DEAL_THRESHOLD = 200.0 + + def __init__(self): + init_logging() + load_dotenv() + client = chromadb.PersistentClient(path=self.DB) + self.collection = client.get_or_create_collection('travel_deals') + + self.llm_memory = self.read_memory(self.LLM_MEMORY_FILE) + self.xgb_memory = self.read_memory(self.XGB_MEMORY_FILE) + + self.scanner = None + self.llm_estimator = None + self.xgb_estimator = None + self.messenger = None + + def init_agents_as_needed(self): + if not self.scanner: + self.log("Initializing Travel Dual Estimation Framework") + self.scanner = TravelScannerAgent() + self.llm_estimator = TravelEstimatorAgent(self.collection) + self.xgb_estimator = TravelXGBoostAgent(self.collection) + self.messenger = TravelMessagingAgent() + self.log("Travel Dual Framework ready") + + def read_memory(self, filename: str) -> List[TravelOpportunity]: + if os.path.exists(filename): + with open(filename, "r") as file: + data = json.load(file) + opportunities = [TravelOpportunity(**item) for item in data] + return opportunities + return [] + + def write_memory(self, opportunities: List[TravelOpportunity], filename: str) -> None: + data = [opportunity.dict() for opportunity in opportunities] + with open(filename, "w") as file: + json.dump(data, file, indent=2) + + def log(self, message: str): + text = BG_BLUE + WHITE + "[Dual Framework] " + message + RESET + logging.info(text) + + def run(self) -> Tuple[List[TravelOpportunity], List[TravelOpportunity]]: + self.init_agents_as_needed() + + self.log("Starting dual estimation scan") + deal_selection = self.scanner.scan() + + if not deal_selection or not deal_selection.deals: + self.log("No deals found") + return self.llm_memory, self.xgb_memory + + deals = deal_selection.deals + self.log(f"Processing {len(deals)} deals with both estimators") + + llm_opportunities = [] + xgb_opportunities = [] + + for deal in deals: + llm_estimate = self.llm_estimator.estimate(deal.description) + llm_discount = llm_estimate - deal.price + + if llm_discount >= self.DEAL_THRESHOLD: + llm_opp = TravelOpportunity( + deal=deal, + estimate=llm_estimate, + discount=llm_discount + ) + llm_opportunities.append(llm_opp) + self.log(f"LLM found opportunity: {deal.destination} - ${llm_discount:.0f} savings") + self.messenger.alert(llm_opp) + + xgb_estimate = self.xgb_estimator.estimate(deal.description) + xgb_discount = xgb_estimate - deal.price + + if xgb_discount >= self.DEAL_THRESHOLD: + xgb_opp = TravelOpportunity( + deal=deal, + estimate=xgb_estimate, + discount=xgb_discount + ) + xgb_opportunities.append(xgb_opp) + self.log(f"XGBoost found opportunity: {deal.destination} - ${xgb_discount:.0f} savings") + self.messenger.alert(xgb_opp) + + if llm_opportunities: + self.llm_memory.extend(llm_opportunities) + self.write_memory(self.llm_memory, self.LLM_MEMORY_FILE) + + if xgb_opportunities: + self.xgb_memory.extend(xgb_opportunities) + self.write_memory(self.xgb_memory, self.XGB_MEMORY_FILE) + + self.log(f"Scan complete: {len(llm_opportunities)} LLM, {len(xgb_opportunities)} XGBoost opportunities") + + return self.llm_memory, self.xgb_memory + + @classmethod + def get_plot_data(cls, max_datapoints=10000): + client = chromadb.PersistentClient(path=cls.DB) + collection = client.get_or_create_collection('travel_deals') + result = collection.get(include=['embeddings', 'documents', 'metadatas'], limit=max_datapoints) + vectors = np.array(result['embeddings']) + documents = result['documents'] + categories = [metadata['category'] for metadata in result['metadatas']] + colors = [COLORS[CATEGORIES.index(c)] for c in categories] + tsne = TSNE(n_components=3, random_state=42, n_jobs=-1) + reduced_vectors = tsne.fit_transform(vectors) + return documents, reduced_vectors, colors, categories + + +if __name__=="__main__": + framework = TravelDualFramework() + framework.run() + diff --git a/week8/community_contributions/w8d5/tests/__init__.py b/week8/community_contributions/w8d5/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/week8/community_contributions/w8d5/tests/test_components.py b/week8/community_contributions/w8d5/tests/test_components.py new file mode 100644 index 0000000..5c0699c --- /dev/null +++ b/week8/community_contributions/w8d5/tests/test_components.py @@ -0,0 +1,66 @@ +import os +import sys +from dotenv import load_dotenv + +project_root = os.path.join(os.path.dirname(__file__), '..') +sys.path.insert(0, project_root) +sys.path.insert(0, os.path.join(project_root, '..', '..')) + +from helpers.travel_deals import ScrapedTravelDeal +from agents.travel_scanner_agent import TravelScannerAgent +from agents.travel_estimator_agent import TravelEstimatorAgent + +load_dotenv() + +print("\nTesting Travel Deal Hunter Components\n") + +print("1. RSS Feed Scraping") +deals = ScrapedTravelDeal.fetch(show_progress=False) +print(f"Fetched {len(deals)} deals from RSS feeds") +if deals: + print(f"Sample: {deals[0].title[:60]}...") + + +print("\n2. OpenAI Connection") +if os.getenv("OPENAI_API_KEY"): + print("OPENAI_API_KEY found") +else: + print("OPENAI_API_KEY not found - set in .env file") + +print("\n3. Scanner Agent") +scanner = TravelScannerAgent() +print("Scanner agent initialized") + +print("\n4. Deal Scanning") +try: + selection = scanner.scan(memory=[]) + if selection and selection.deals: + print(f"Scanner found {len(selection.deals)} processed deals") + print(f"Sample: {selection.deals[0].destination} - ${selection.deals[0].price}") + else: + print("No deals returned") +except Exception as e: + print(f"Error: {e}") + +print("\n5. ChromaDB Access") +import chromadb +try: + db_path = "travel_vectorstore" + client = chromadb.PersistentClient(path=db_path) + collection = client.get_or_create_collection('travel_deals') + count = collection.count() + print(f"ChromaDB connected - {count} travel items in collection") +except Exception as e: + print(f"Error: {e}") + +print("\n6. Estimator Check using travel vectorstore") +try: + estimator = TravelEstimatorAgent(collection) + sample = "Non-stop economy flight from New York to London, duration 7 hours" + estimate = estimator.estimate(sample) + print(f"Estimate: ${estimate:.2f}") +except Exception as e: + print(f"Error: {e}") + +print("\nComponent tests complete") + diff --git a/week8/community_contributions/w8d5/tests/test_dual_estimation.py b/week8/community_contributions/w8d5/tests/test_dual_estimation.py new file mode 100644 index 0000000..3b1ba2c --- /dev/null +++ b/week8/community_contributions/w8d5/tests/test_dual_estimation.py @@ -0,0 +1,49 @@ +import os +import sys +from dotenv import load_dotenv + +project_root = os.path.join(os.path.dirname(__file__), '..') +sys.path.insert(0, project_root) +sys.path.insert(0, os.path.join(project_root, '..', '..')) + +from agents.travel_estimator_agent import TravelEstimatorAgent +from agents.travel_xgboost_agent import TravelXGBoostAgent +import chromadb + +load_dotenv() + +print("\nTesting Dual Estimation (LLM vs XGBoost)\n") + +client = chromadb.PersistentClient(path='travel_vectorstore') +collection = client.get_collection('travel_deals') + +print("Initializing agents...") +llm_agent = TravelEstimatorAgent(collection) +xgb_agent = TravelXGBoostAgent(collection) + +test_cases = [ + "Round trip flight from New York to London, Economy class, non-stop", + "5-star Marriott hotel in Paris, 3 nights, Suite with breakfast included", + "7-night Caribbean cruise, Balcony cabin, all meals included", + "Hertz SUV rental in Los Angeles for 5 days with unlimited mileage", + "All-inclusive vacation package to Dubai for 7 nights with Business class flights" +] + +print("\n" + "="*80) +print(f"{'Travel Deal Description':<60} {'LLM Est.':<12} {'XGB Est.':<12}") +print("="*80) + +for desc in test_cases: + llm_est = llm_agent.estimate(desc) + xgb_est = xgb_agent.estimate(desc) + + short_desc = desc[:57] + "..." if len(desc) > 60 else desc + print(f"{short_desc:<60} ${llm_est:>9.2f} ${xgb_est:>9.2f}") + +print("="*80) +print("\nDual estimation test complete!") +print("\nKey Observations:") +print("- LLM: Uses semantic understanding + RAG context") +print("- XGBoost: Uses pattern recognition from embeddings") +print("- Both trained on same 20K travel deals dataset") + diff --git a/week8/community_contributions/w8d5/tests/test_pipeline.py b/week8/community_contributions/w8d5/tests/test_pipeline.py new file mode 100644 index 0000000..1592437 --- /dev/null +++ b/week8/community_contributions/w8d5/tests/test_pipeline.py @@ -0,0 +1,38 @@ +import os +import sys +from dotenv import load_dotenv + +project_root = os.path.join(os.path.dirname(__file__), '..') +sys.path.insert(0, project_root) +sys.path.insert(0, os.path.join(project_root, '..', '..')) + +from helpers.travel_deal_framework import TravelDealFramework + +load_dotenv() + +print("\nTesting Full Travel Deal Pipeline\n") + +print("Initializing framework...") +framework = TravelDealFramework() +framework.init_agents_as_needed() + +print("\nRunning one iteration...") +try: + result = framework.run() + print(f"\nPipeline completed") + print(f"Memory now has {len(result)} opportunities") + if result: + latest = result[-1] + print(f"\nLatest opportunity:") + print(f" Destination: {latest.deal.destination}") + print(f" Type: {latest.deal.deal_type}") + print(f" Price: ${latest.deal.price:.2f}") + print(f" Estimate: ${latest.estimate:.2f}") + print(f" Discount: ${latest.discount:.2f}") +except Exception as e: + print(f"\nError during pipeline: {e}") + import traceback + traceback.print_exc() + +print("\n") + diff --git a/week8/community_contributions/w8d5/w8d5_dual.py b/week8/community_contributions/w8d5/w8d5_dual.py new file mode 100644 index 0000000..7ffc4e5 --- /dev/null +++ b/week8/community_contributions/w8d5/w8d5_dual.py @@ -0,0 +1,306 @@ +import os +import sys +import logging +import queue +import threading +import time +import gradio as gr +import plotly.graph_objects as go + +w8d5_path = os.path.abspath(os.path.dirname(__file__)) +week8_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +if w8d5_path not in sys.path: + sys.path.insert(0, w8d5_path) +if week8_path not in sys.path: + sys.path.insert(0, week8_path) + +from log_utils import reformat +from helpers.travel_dual_framework import TravelDualFramework +from helpers.travel_deals import TravelOpportunity, TravelDeal + + +class QueueHandler(logging.Handler): + def __init__(self, log_queue): + super().__init__() + self.log_queue = log_queue + + def emit(self, record): + self.log_queue.put(self.format(record)) + + +log_queue = queue.Queue() +queue_handler = QueueHandler(log_queue) +queue_handler.setFormatter( + logging.Formatter( + "[%(asctime)s] [%(levelname)s] %(message)s", + datefmt="%Y-%m-%d %H:%M:%S" + ) +) +logging.getLogger().addHandler(queue_handler) +logging.getLogger().setLevel(logging.INFO) + +agent_framework = TravelDualFramework() +agent_framework.init_agents_as_needed() + +CHECK_INTERVAL = 300 + + +def run_agent_framework(): + while True: + try: + agent_framework.run() + except Exception as e: + logging.error(f"Error in agent framework: {e}") + time.sleep(CHECK_INTERVAL) + + +framework_thread = threading.Thread(target=run_agent_framework, daemon=True) +framework_thread.start() + + +def get_llm_table(llm_opps): + return [[ + opp.deal.destination, + opp.deal.deal_type, + f"${opp.deal.price:.2f}", + f"${opp.estimate:.2f}", + f"${opp.discount:.2f}", + opp.deal.url[:50] + "..." if len(opp.deal.url) > 50 else opp.deal.url + ] for opp in llm_opps] + + +def get_xgb_table(xgb_opps): + return [[ + opp.deal.destination, + opp.deal.deal_type, + f"${opp.deal.price:.2f}", + f"${opp.estimate:.2f}", + f"${opp.discount:.2f}", + opp.deal.url[:50] + "..." if len(opp.deal.url) > 50 else opp.deal.url + ] for opp in xgb_opps] + + +log_data = [] + +def update_ui(): + global log_data + llm_data = get_llm_table(agent_framework.llm_memory) + xgb_data = get_xgb_table(agent_framework.xgb_memory) + + while not log_queue.empty(): + try: + message = log_queue.get_nowait() + log_data.append(reformat(message)) + except: + break + + logs_html = '
' + logs_html += '
'.join(log_data[-50:]) + logs_html += '
' + + llm_count = len(agent_framework.llm_memory) + xgb_count = len(agent_framework.xgb_memory) + + stats = f"LLM Opportunities: {llm_count} | XGBoost Opportunities: {xgb_count}" + + return llm_data, xgb_data, logs_html, stats + + +def create_3d_plot(): + try: + documents, vectors, colors, categories = TravelDualFramework.get_plot_data(max_datapoints=5000) + + if len(vectors) == 0: + fig = go.Figure() + fig.add_annotation( + text="No data available yet. Vectorstore will load after initialization.", + xref="paper", yref="paper", + x=0.5, y=0.5, showarrow=False, + font=dict(size=16) + ) + return fig + + fig = go.Figure() + + unique_categories = list(set(categories)) + category_colors = {cat: colors[categories.index(cat)] for cat in unique_categories} + + for category in unique_categories: + mask = [cat == category for cat in categories] + cat_vectors = vectors[mask] + + fig.add_trace(go.Scatter3d( + x=cat_vectors[:, 0], + y=cat_vectors[:, 1], + z=cat_vectors[:, 2], + mode='markers', + marker=dict( + size=3, + color=category_colors[category], + opacity=0.6 + ), + name=category.replace('_', ' '), + hovertemplate='%{text}', + text=[category] * len(cat_vectors) + )) + + fig.update_layout( + title={ + 'text': f'3D Travel Vectorstore Visualization ({len(vectors):,} deals)', + 'x': 0.5, + 'xanchor': 'center' + }, + scene=dict( + xaxis_title='Dimension 1', + yaxis_title='Dimension 2', + zaxis_title='Dimension 3', + camera=dict( + eye=dict(x=1.5, y=1.5, z=1.5) + ) + ), + width=1200, + height=600, + margin=dict(r=0, b=0, l=0, t=40), + showlegend=True, + legend=dict( + yanchor="top", + y=0.99, + xanchor="left", + x=0.01 + ) + ) + + return fig + except Exception as e: + logging.error(f"Error creating 3D plot: {e}") + fig = go.Figure() + fig.add_annotation( + text=f"Error loading plot: {str(e)}", + xref="paper", yref="paper", + x=0.5, y=0.5, showarrow=False, + font=dict(size=14, color="red") + ) + return fig + + +with gr.Blocks(title="Travel Deal Hunter - Dual Estimation", fill_width=True, theme=gr.themes.Soft()) as ui: + + gr.Markdown( + """ +
+

Travel Deal Hunter - Dual Estimation System

+

+ Comparing LLM-based Semantic Estimation vs XGBoost Machine Learning +

+

+ System scans RSS feeds every 5 minutes. Use the button below to trigger a manual scan. +

+
+ """ + ) + + with gr.Row(): + with gr.Column(scale=3): + stats_display = gr.Textbox( + label="", + value="LLM Opportunities: 0 | XGBoost Opportunities: 0", + interactive=False, + show_label=False, + container=False + ) + with gr.Column(scale=1): + scan_button = gr.Button("Scan Now", variant="primary") + + with gr.Row(): + with gr.Column(scale=1): + gr.Markdown("### LLM Estimates") + llm_dataframe = gr.Dataframe( + headers=["Destination", "Type", "Price", "LLM Est.", "Savings", "URL"], + datatype=["str", "str", "str", "str", "str", "str"], + wrap=True, + column_widths=[2, 1, 1, 1, 1, 2], + row_count=5, + col_count=6, + interactive=False + ) + + with gr.Column(scale=1): + gr.Markdown("### XGBoost Estimates") + xgb_dataframe = gr.Dataframe( + headers=["Destination", "Type", "Price", "XGB Est.", "Savings", "URL"], + datatype=["str", "str", "str", "str", "str", "str"], + wrap=True, + column_widths=[2, 1, 1, 1, 1, 2], + row_count=5, + col_count=6, + interactive=False + ) + + with gr.Row(): + with gr.Column(scale=2): + plot_output = gr.Plot(label="3D Travel Vectorstore Visualization") + + with gr.Column(scale=1): + gr.Markdown("### Agent Activity Logs") + log_output = gr.HTML( + value='
' + ) + + ui.load( + fn=lambda: ( + get_llm_table(agent_framework.llm_memory), + get_xgb_table(agent_framework.xgb_memory), + "", + f"LLM Opportunities: {len(agent_framework.llm_memory)} | XGBoost Opportunities: {len(agent_framework.xgb_memory)}", + create_3d_plot() + ), + outputs=[llm_dataframe, xgb_dataframe, log_output, stats_display, plot_output] + ) + + # Manual scan button + def manual_scan(): + try: + agent_framework.run() + return update_ui() + except Exception as e: + logging.error(f"Manual scan error: {e}") + return update_ui() + + scan_button.click( + fn=manual_scan, + outputs=[llm_dataframe, xgb_dataframe, log_output, stats_display] + ) + + # Click handlers for notifications + def llm_click_handler(selected_index: gr.SelectData): + try: + row = selected_index.index[0] + if row < len(agent_framework.llm_memory): + opportunity = agent_framework.llm_memory[row] + agent_framework.messenger.alert(opportunity) + logging.info(f"Manual alert sent for LLM opportunity: {opportunity.deal.destination}") + except Exception as e: + logging.error(f"Error sending LLM notification: {e}") + + def xgb_click_handler(selected_index: gr.SelectData): + try: + row = selected_index.index[0] + if row < len(agent_framework.xgb_memory): + opportunity = agent_framework.xgb_memory[row] + agent_framework.messenger.alert(opportunity) + logging.info(f"Manual alert sent for XGBoost opportunity: {opportunity.deal.destination}") + except Exception as e: + logging.error(f"Error sending XGBoost notification: {e}") + + llm_dataframe.select(fn=llm_click_handler) + xgb_dataframe.select(fn=xgb_click_handler) + + gr.Timer(5).tick( + fn=update_ui, + outputs=[llm_dataframe, xgb_dataframe, log_output, stats_display] + ) + + +if __name__ == "__main__": + ui.launch(inbrowser=True, share=False) +