Spaces:
Runtime error
Runtime error
File size: 10,018 Bytes
8273ecf | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | """
generate_data.py
-----------------
Generates a synthetic e-commerce product catalog with 2000+ unique entries
and saves it as products.csv. This CSV is the "custom database" the RAG
chatbot retrieves from.
Run:
python generate_data.py
"""
import csv
import random
random.seed(42)
# ---------------------------------------------------------------------------
# Catalog taxonomy: category -> subcategories -> base product name templates
# ---------------------------------------------------------------------------
CATALOG = {
"Electronics": {
"subcats": ["Smartphones", "Laptops", "Headphones", "Smartwatches", "Cameras",
"Tablets", "Speakers", "Gaming Consoles", "Monitors", "Power Banks"],
"price_range": (25, 2200),
"brands": ["Voltek", "Nimbus", "Zentro", "Quantex", "Pulsar", "Orbitron",
"Skyline", "Nexura", "Vantek", "Corevolt"],
},
"Clothing": {
"subcats": ["T-Shirts", "Jeans", "Jackets", "Dresses", "Sweaters",
"Activewear", "Shorts", "Formal Shirts", "Hoodies", "Coats"],
"price_range": (8, 250),
"brands": ["Urban Thread", "Loomcraft", "Northgate", "Willow & Ash",
"StrideWear", "Fablink", "Merino Co.", "CasualEdge", "DrapeLine", "Threadfox"],
},
"Home & Kitchen": {
"subcats": ["Cookware", "Blenders", "Coffee Makers", "Bedding", "Vacuum Cleaners",
"Storage Bins", "Cutlery Sets", "Lamps", "Air Purifiers", "Dinnerware"],
"price_range": (10, 600),
"brands": ["HearthPro", "Domesta", "Kitchcraft", "CozyNest", "PureAir",
"Lumina Home", "ChefMate", "TidyBox", "SilverEdge", "WarmHearth"],
},
"Beauty & Personal Care": {
"subcats": ["Moisturizers", "Shampoos", "Perfumes", "Makeup Kits", "Electric Razors",
"Hair Dryers", "Skincare Serums", "Sunscreens", "Lip Balms", "Face Masks"],
"price_range": (5, 150),
"brands": ["Glowvia", "PureSkin", "Belle Aura", "Dermalux", "Velvetone",
"NatureGlow", "SilkRoute", "LumiCare", "EssenceLab", "RadiantHue"],
},
"Sports & Outdoors": {
"subcats": ["Yoga Mats", "Dumbbells", "Tents", "Bicycles", "Running Shoes",
"Backpacks", "Water Bottles", "Fitness Trackers", "Camping Stoves", "Skateboards"],
"price_range": (10, 900),
"brands": ["TrailBlaze", "PeakForm", "IronGrit", "SummitGear", "Velocore",
"RidgeLine", "ActivFit", "TerraTrek", "FlexCore", "AltitudePro"],
},
"Books": {
"subcats": ["Fiction", "Non-Fiction", "Science Fiction", "Biography", "Self-Help",
"Children's Books", "Mystery & Thriller", "Cookbooks", "History", "Poetry"],
"price_range": (4, 45),
"brands": ["Penfield Press", "Storyhouse", "Chapter & Verse", "Inkwell Editions",
"Lanternlight Books", "Northpage", "Quillmark", "Bright Leaf Publishing",
"Cobblestone Press", "Willow Bind"],
},
"Toys & Games": {
"subcats": ["Building Blocks", "Board Games", "Action Figures", "Puzzles", "Dolls",
"Remote Control Cars", "Educational Toys", "Card Games", "Plush Toys", "Outdoor Play Sets"],
"price_range": (5, 180),
"brands": ["Funkidoo", "Brightblox", "PlayNest", "Wonderrific", "Tinker Toys Co.",
"GigglePatch", "Kudo Kids", "Puzzlewise", "Playscape", "JoyForge"],
},
"Grocery & Gourmet": {
"subcats": ["Coffee & Tea", "Snacks", "Spices", "Cereal", "Olive Oils",
"Pasta & Grains", "Chocolates", "Honey & Preserves", "Nuts & Seeds", "Sauces"],
"price_range": (3, 60),
"brands": ["Harvest Table", "Golden Pantry", "Rustic Roots", "PureField",
"Meadowbrook", "SpiceHaven", "Orchard Gold", "GrainWorks", "Savory Bay", "Farmstead Co."],
},
"Office & Stationery": {
"subcats": ["Notebooks", "Pens", "Desk Organizers", "Backpacks", "Printers",
"Office Chairs", "Whiteboards", "Planners", "Sticky Notes", "Desk Lamps"],
"price_range": (2, 400),
"brands": ["Deskly", "Penmark", "Officia", "Craftline", "NotaBene",
"GridWorks", "ClearDesk", "InkPoint", "OrganizeIt", "Brightfold"],
},
"Pet Supplies": {
"subcats": ["Dog Food", "Cat Toys", "Pet Beds", "Leashes & Collars", "Aquarium Kits",
"Grooming Kits", "Bird Cages", "Pet Carriers", "Litter Boxes", "Chew Toys"],
"price_range": (4, 220),
"brands": ["Pawsome", "Furry Friend Co.", "WhiskerWorks", "TailWag", "NestleNook",
"Barkline", "PetHaven", "ScratchCraft", "Critter Corner", "Loyal Paws"],
},
}
ADJECTIVES = ["Premium", "Classic", "Compact", "Deluxe", "Ergonomic", "Portable",
"Wireless", "Eco-Friendly", "Heavy-Duty", "Ultra-Light", "All-Season",
"Professional", "Everyday", "Signature", "Modern", "Vintage-Style",
"Advanced", "Essential", "Rugged", "Smart"]
COLORS = ["Black", "White", "Navy Blue", "Charcoal Grey", "Forest Green", "Sunset Orange",
"Crimson Red", "Sand Beige", "Slate Blue", "Blush Pink", "Graphite", "Ivory"]
MATERIALS = ["stainless steel", "brushed aluminum", "organic cotton", "recycled polyester",
"genuine leather", "BPA-free plastic", "tempered glass", "bamboo",
"high-density foam", "merino wool", "silicone", "anodized alloy"]
FEATURES = [
"long battery life", "a sleek minimalist design", "industry-leading durability",
"fast and reliable performance", "an intuitive user experience", "excellent value for money",
"top-rated customer reviews", "easy maintenance", "a comfortable fit for all-day use",
"energy-efficient operation", "quick setup with no tools required", "a lightweight build",
"water-resistant construction", "adjustable settings for personalized use",
"a timeless design that fits any space", "reinforced stitching for extra durability",
"noise isolation for an immersive experience", "a non-slip grip for added safety",
]
TAG_POOL = ["bestseller", "new arrival", "eco-friendly", "limited edition", "on sale",
"top rated", "staff pick", "gift idea", "trending", "budget friendly",
"premium choice", "family favorite"]
def make_description(name, category, subcat, brand, color, material, adj):
feat1, feat2 = random.sample(FEATURES, 2)
templates = [
f"The {name} from {brand} combines {material} construction with {feat1}. "
f"Designed for fans of {subcat.lower()}, this {adj.lower()} pick offers {feat2}, "
f"making it a standout choice in our {category} collection.",
f"Meet the {name} — a {adj.lower()} {subcat.lower()[:-1] if subcat.endswith('s') else subcat.lower()} "
f"built from {material}. It delivers {feat1} and {feat2}, "
f"perfect for anyone shopping our {category} lineup.",
f"{brand} presents the {name}, finished in {color.lower()} with premium {material}. "
f"Customers love its {feat1}, and it also offers {feat2}.",
]
return random.choice(templates)
def generate_products(min_count=2000):
rows = []
product_id = 1
for category, meta in CATALOG.items():
subcats = meta["subcats"]
brands = meta["brands"]
low, high = meta["price_range"]
# ~ enough combos per category to comfortably exceed 2000 total across 10 categories
per_category_target = 210
for _ in range(per_category_target):
subcat = random.choice(subcats)
brand = random.choice(brands)
adj = random.choice(ADJECTIVES)
color = random.choice(COLORS)
material = random.choice(MATERIALS)
# Singular-ish name from subcat
base_noun = subcat[:-1] if subcat.endswith("s") and not subcat.endswith("ss") else subcat
name = f"{brand} {adj} {base_noun}"
price = round(random.uniform(low, high), 2)
rating = round(random.uniform(3.3, 5.0), 1)
num_reviews = random.randint(3, 4800)
stock = random.choice(["In Stock"] * 8 + ["Low Stock"] * 2 + ["Out of Stock"])
tags = ", ".join(random.sample(TAG_POOL, k=random.randint(1, 3)))
description = make_description(name, category, subcat, brand, color, material, adj)
rows.append({
"product_id": f"P{product_id:05d}",
"name": name,
"category": category,
"subcategory": subcat,
"brand": brand,
"price_usd": price,
"rating": rating,
"num_reviews": num_reviews,
"stock_status": stock,
"color": color,
"material": material,
"tags": tags,
"description": description,
})
product_id += 1
random.shuffle(rows)
# De-duplicate exact name collisions by appending a variant suffix
seen = {}
for r in rows:
key = r["name"]
if key in seen:
seen[key] += 1
r["name"] = f'{r["name"]} (Style {seen[key]})'
else:
seen[key] = 1
if len(rows) < min_count:
raise RuntimeError(f"Only generated {len(rows)} rows, need {min_count}+")
return rows
def main():
rows = generate_products(2000)
fieldnames = ["product_id", "name", "category", "subcategory", "brand", "price_usd",
"rating", "num_reviews", "stock_status", "color", "material", "tags",
"description"]
with open("products.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(rows)
print(f"Generated {len(rows)} products -> products.csv")
if __name__ == "__main__":
main()
|