Automated Product Classification & Data Cleaning
01 Challenge
Assigning product data to categories by hand and rewriting descriptions one by one takes a lot of time for larger catalogs.
02 Approach
A Python script loads the products with Pandas and has a local LLM (gemma3:4b via Ollama) classify each product and rewrite its description with SEO in mind.
03 Result
An enriched dataset with the new columns PredictedCategory and new_descriptions, exported as CSV – in just a few lines of code and without a cloud API.
I developed a small but useful Python script that reads product data from a CSV file, automatically assigns it to a suitable category, and optimizes the description. The idea was to test how well Large Language Models (LLMs) like gemma3:4b perform for such tasks.
The script is not a complex AI system – but it shows how manual work steps can be automated with just a few lines of code, especially in e-commerce and for larger product catalogs.
- Sample products
- 20
- CSV with 6 columns
- Target categories
- 4
- Electronics · Household · Clothing · Garden
- LLM tasks
- 2
- Classify + rewrite per product
- Inference
- local
- Ollama · gemma3:4b
The Technical Approach
- 01LoadCSV string becomes a DataFrameload_data
- 02ClassifyLLM assigns each product to a categoryclassify_product_llm
- 03RewriteLLM rewrites the description for SEOrewrite_description
- 04EnrichNew columns in the DataFrameenrich_data_…
- 05ExportResult saved as a CSV fileto_csv
1. Loading the Data
Everything starts with the function that reads the CSV data. Using Pandas and StringIO, I turn a simple CSV string into a DataFrame – the basis for processing the product data in a structured way.
2. LLM-Based Product Classification
For classification, I use the ollama package to access the gemma3:4b model. In classify_product_llm, a system prompt gives the model clear instructions: take the product name and description and assign them to a predefined category schema – Electronics, Household Goods, Clothing, or Garden Items.
3. Optimizing Product Descriptions
In parallel, rewrite_description optimizes the product description. A second system prompt ensures the text is SEO-optimized and more engaging at the same time: short sentences, relevant keywords without keyword stuffing, bullet points when there are many benefits.
It was important to me to strike a balance between technical precision and natural, sales-promoting language – and above all, that no new details are invented. The prompt explicitly forbids it: the text should only be improved, not extended.
4. Data Enrichment
enrich_data_with_classification iterates over all products in the DataFrame, applies classification and text optimization, and extends the dataset with two new columns. In the final step, the result is saved as classified_products.csv.
Input (CSV)
- ArticleID, Name, Description
- Manufacturer, Price, Stock
- No category
- Description in raw form
Output (enriched)
- All original columns are kept
- + PredictedCategory
- + new_descriptions (SEO-optimized)
- Exported as classified_products.csv
Learnings
- Two tasks, two prompts: Classification and copywriting have completely different output requirements – separate system prompts keep both tasks clean.
- Guardrails belong in the prompt: Explicitly forbidding invented product details is essential for generated shop copy.
- Local is enough for testing: A 4B model via Ollama is enough to try out the workflow without a cloud API.
The Code
In the main part of the program, I define example CSV data, load it, and run it through the entire processing chain. Here is the complete Python script:
import pandas as pd
from io import StringIO
from ollama import chat
def load_data(csv_data: str) -> pd.DataFrame:
"""
Reads CSV data from a string.
"""
df = pd.read_csv(StringIO(csv_data))
return df
def classify_product_llm(name: str, description: str) -> str:
"""
Uses the ollama package to access the model "gemma3:4b" and
determine a category based on a system prompt and the product
(name and description).
"""
system_prompt = (
"""
Du bist ein Experte für Produktklassifizierung. Ordne das Produkt in eine der folgenden Kategorien ein:
Elektronik: Computer, Smartphones, Fernseher, Audio-Geräte, Kameras, Wearables.
Haushaltswaren: Küchengeräte, Staubsauger, Bügeleisen, Waschmaschinen, Toaster, Lampen.
Kleidung: Schuhe, Jacken, T-Shirts, Hosen, Pullover.
Gartenartikel: Gartengeräte, Pflanzenzubehör, Rasenmäher, Heckenscheren.
Antworte ausschließlich mit dem Kategorienamen.
"""
)
user_prompt = f"Produktname: {name}\nBeschreibung: {description}"
# Send the messages to the model
response = chat(
model="gemma3:4b", # gemma3 references gemma3:4b by default
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
)
# Extract and clean the response
category = response.message.content.strip()
return category if category else "Unbekannt"
def rewrite_description(name: str, description: str) -> str:
"""
Uses the ollama package to access the model "gemma3:4b" and
rewrite the product description to be SEO-optimized and more engaging.
"""
system_prompt = (
"""
Du bist ein Experte für E-Commerce und SEO-optimierte Produktbeschreibungen.
Deine Aufgabe ist es, die gegebene Produktbeschreibung zu verbessern, indem du sie:
Leserfreundlich formulierst.
Relevante Keywords einbaust (ohne Keyword-Stuffing).
Eine emotionale und verkaufsstarke Sprache nutzt.
Erfinde keine Produktdetails – Es dürfen nur die vorhandenen Artikelinformationen angegeben werden, um zu verhindern, dass ausgedachte Details hinzugefügt werden.
Die Beschreibung leicht verständlich und ansprechend hälst.
Verwende eine natürliche, aber verkaufsstarke Tonalität, als würde ein professioneller Online-Shop sie schreiben.
Schreibe in kurzen Sätzen, verwende Bulletpoints bei vielen Vorteilen und formuliere den Text so, dass er die Kaufentscheidung positiv beeinflusst.
Gib nur die optimierte Beschreibung zurück, ohne weitere Erklärungen.
"""
)
user_prompt = f"Produktname: {name}\nBeschreibung: {description}"
# Send the messages to the model
response = chat(
model="gemma3:4b", # gemma3 references gemma3:4b by default
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_prompt},
],
)
# Extract and clean the response
new_description = response.message.content.strip()
return new_description if new_description else "Unbekannt"
def enrich_data_with_classification(df: pd.DataFrame) -> pd.DataFrame:
"""
Iterates over the product list and calls the LLM-based classification for each item.
The result is stored in the new column 'PredictedCategory'.
"""
predicted_categories_list = []
new_descriptions_list = []
for idx, row in df.iterrows():
name = row.get("Name", "")
description = row.get("Description", "")
category = classify_product_llm(name, description)
new_description = rewrite_description(name, description)
print(f"Product '{name}' -> Predicted category: {category}")
predicted_categories_list.append(category)
new_descriptions_list.append(new_description)
df["PredictedCategory"] = predicted_categories_list
df["new_descriptions"] = new_descriptions_list
return df
def main():
# Example CSV data as string
csv_data = """
ArticleID,Name,Description,Manufacturer,Price,Stock
1,Smartphone,"Modernes Smartphone mit 6.5 Zoll Display und 128GB Speicher",TechCorp,699.99,50
2,T-Shirt,"Bequemes Baumwoll-T-Shirt in verschiedenen Farben",FashionCo,19.99,200
3,Kaffeemaschine,"Automatische Kaffeemaschine mit 12 Tassen Kapazität",HomeBrew,129.99,80
4,Gartenschere,"Hochwertige Gartenschere für präzises Schneiden",GardenPro,24.99,150
5,LED-Fernseher,"50 Zoll LED-Fernseher mit 4K Auflösung und Smart TV Funktionen",ElectroMax,499.99,30
6,Notebook,"Leistungsstarkes Notebook mit Intel i7 und 16GB RAM",CompuWorld,1299.99,20
7,Lederjacke,"Hochwertige Lederjacke aus echtem Leder",FashionCo,199.99,35
8,Toaster,"2-Schlitz-Toaster mit einstellbarer Bräunung",HomeBrew,34.99,100
9,Rasenmäher,"Elektrischer Rasenmäher mit 40cm Schnittbreite",GardenPro,299.99,40
10,Smartwatch,"Wasserdichte Smartwatch mit Fitness-Tracking",TechCorp,199.99,60
11,Hoodie,"Kapuzenpullover aus weichem Fleece-Material",FashionCo,39.99,120
12,Mikrowelle,"800W Mikrowelle mit Auftaufunktion",HomeBrew,89.99,75
13,Heckenschere,"Akku-Heckenschere für präzises Schneiden",GardenPro,179.99,50
14,Kopfhörer,"Kabellose Over-Ear-Kopfhörer mit Noise Cancelling",TechCorp,149.99,90
15,Winterjacke,"Gefütterte Winterjacke mit wasserabweisendem Material",FashionCo,129.99,45
16,Staubsauger,"Leistungsstarker Staubsauger mit HEPA-Filter",HomeBrew,199.99,55
17,Gartenlampe,"Solarbetriebene Gartenlampe mit Bewegungssensor",GardenPro,39.99,100
18,Bluetooth-Lautsprecher,"Wasserdichter Bluetooth-Lautsprecher mit 360° Sound",ElectroMax,79.99,85
19,Sneaker,"Bequeme Laufschuhe mit atmungsaktivem Material",FashionCo,89.99,150
20,Espressomaschine,"Hochwertige Espressomaschine mit Milchaufschäumer",HomeBrew,249.99,30
"""
# Load data
df = load_data(csv_data)
print("Original data:")
print(df, "\n")
# Run LLM-based classification
df = enrich_data_with_classification(df)
print("\nData with predicted categories:")
print(df)
# Optionally save result to CSV
output_file = "classified_products.csv"
df.to_csv(output_file, index=False)
print(f"\nResult saved to '{output_file}'.")
if __name__ == "__main__":
main()