We are going to build a batch product description generator that turns a CSV of sparse product specs into polished, ready-to-publish marketing copy. This is for e-commerce ops teams who are tired of writing the same blurbs over and over. I will use Oxlo.ai because its request-based pricing means I can feed it long, messy supplier spec sheets without watching the meter spin on every extra token.
What you'll need
- Python 3.10 or newer
- An Oxlo.ai API key from https://portal.oxlo.ai
- The OpenAI SDK:
pip install openai - Pandas for CSV handling:
pip install pandas
Step 1: Configure the Oxlo.ai client
I start by importing the OpenAI SDK and pointing it at Oxlo.ai. Because Oxlo.ai is fully OpenAI API compatible, this is a drop-in replacement. No custom adapters needed.
from openai import OpenAI
import os
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.environ.get("OXLO_API_KEY")
)
I keep the key in an environment variable so I do not accidentally commit it.
Step 2: Craft the system prompt
The system prompt is the only part of the agent I will tune heavily. It defines voice, length, and what to avoid. I treat it as a config file and keep it in a constant so I can iterate without touching the logic.
SYSTEM_PROMPT = """You are a senior e-commerce copywriter. Your job is to turn raw product specifications into compelling product descriptions.
Rules:
- Write exactly one paragraph of 40 to 60 words.
- Highlight the single most important benefit first.
- Use active voice and concrete nouns.
- Do not use exclamation points or all-caps.
- If technical specs are provided, translate one key spec into a customer benefit.
Output only the description text. No markdown, no preamble."""
Step 3: Build the generation function
Next I wrap the API call in a small function that accepts a raw spec string and returns the generated copy. I use Llama 3.3 70B because it is Oxlo.ai's general-purpose flagship and handles marketing voice reliably. I also add a short sleep to be polite if I scale this up later.
import time
def generate_description(product_specs: str, model: str = "llama-3.3-70b") -> str:
response = client.chat.completions.create(
model=model,
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": product_specs},
],
temperature=0.7,
max_tokens=256,
)
time.sleep(0.5)
return response.choices[0].message.content.strip()
Step 4: Load data and run the batch
For this project I assume a CSV with two columns: sku and raw_specs. I read it with Pandas, apply the generator row by row, and append the result to a new column. This pattern works for hundreds of SKUs. If I needed thousands I would add a simple retry loop around the API call.
import pandas as pd
df = pd.read_csv("products.csv")
descriptions = []
for _, row in df.iterrows():
desc = generate_description(row["raw_specs"])
descriptions.append(desc)
df["generated_description"] = descriptions
df.to_csv("products_with_copy.csv", index=False)
print(f"Generated {len(descriptions)} descriptions.")
I keep the loop explicit instead of using apply so I can add logging or error handling later without refactoring.
Step 5: Inspect the output
After the run I always spot-check a few rows. Here is a quick script to pretty-print a sample so I can scan for tone drift or hallucinated claims before the copy goes live.
for i in range(min(3, len(df))):
print(f"SKU: {df.loc[i, 'sku']}")
print(f"Specs: {df.loc[i, 'raw_specs']}")
print(f"Copy: {df.loc[i, 'generated_description']}")
print("-" * 40)
Run it
To test the whole flow without a CSV, I can call the generator directly with a raw string. This is the same call the batch loop makes under the hood.
test_specs = """
SKU: BK-2024-009
Name: Terra Hiking Backpack
Material: 420D recycled nylon
Capacity: 28L
Features: Hydration sleeve, rain cover, ventilated back panel
"""
print(generate_description(test_specs))
Example output:
The Terra Hiking Backpack keeps you moving with a ventilated back panel that cuts heat on steep ascents. Built from 420D recycled nylon, it offers a 28-liter capacity with a dedicated hydration sleeve and integrated rain cover so you are ready when weather turns. Lightweight, durable, and designed for the trail.
Next steps
This agent works, but it is just a starting point. Two concrete upgrades I would ship next:
- Add structured output by switching to JSON mode and returning
description,bullet_points, andseo_titlein one request. Oxlo.ai supports this on all chat models. - Pipe the output directly into your storefront or PIM API so the copy moves from generated to published without a manual CSV handoff.
If your product specs are long or your agent needs multi-turn reasoning, Oxlo.ai's request-based pricing stays flat no matter how much context you stuff into the prompt. You can explore plans and model options at https://oxlo.ai/pricing.
Top comments (0)