We are building a batch sentiment analysis pipeline that reads raw customer reviews, scores them with structured labels, and extracts the emotional drivers behind each rating. The pipeline pairs an LLM hosted on Oxlo.ai with a local Hugging Face transformer baseline so you can compare zero-shot LLM reasoning against a classical model without managing GPU clusters. It is meant for support teams and data engineers who need production-grade feedback processing without training custom classifiers.
What you will need
- Python 3.10 or newer.
- The OpenAI SDK:
pip install openai - The Transformers library and PyTorch:
pip install transformers torch - An Oxlo.ai API key from https://portal.oxlo.ai
- A working internet connection for the first run to download the DistilBERT weights.
Step 1: Configure the Oxlo.ai client
I initialize the OpenAI-compatible client pointing at Oxlo.ai and load my API key from the environment.
import json
import os
from openai import OpenAI
OXLO_API_KEY = os.getenv("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=OXLO_API_KEY,
)
Step 2: Define the system prompt
I treat the prompt as a strict contract. It tells the model exactly which JSON keys to return and what each value should look like.
SYSTEM_PROMPT = """You are a sentiment analysis engine.
Read the customer review and return a single JSON object with exactly these keys:
- sentiment: string, one of positive, negative, or neutral
- confidence: integer from 0 to 100
- key_phrases: list of strings, maximum 3 emotional drivers from the text
Return only raw JSON. Do not wrap it in markdown."""
Step 3: Build the LLM analyzer
This function sends a review to Oxlo.ai and parses the JSON response. I keep the temperature low so the model stays consistent.
def analyze_sentiment_llm(review):
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": review},
],
response_format={"type": "json_object"},
temperature=0.2,
)
raw = response.choices[0].message.content
return json.loads(raw)
Step 4: Add a local transformer baseline
To sanity-check the LLM, I load DistilBERT. It runs locally on CPU and gives us a standard sentiment label and confidence score.
from transformers import pipeline
bert_classifier = pipeline(
"sentiment-analysis",
model="distilbert-base-uncased-finetuned-sst-2-english",
device=-1,
)
def analyze_sentiment_baseline(review):
result = bert_classifier(review, truncation=True, max_length=512)[0]
return {
"sentiment": result["label"].lower(),
"confidence": round(result["score"] * 100, 1),
}
Step 5: Batch process and merge
I iterate over a hardcoded list of reviews, call both analyzers, and assemble the results into a DataFrame.
import pandas as pd
reviews = [
"The battery life on this laptop is incredible, easily lasts 12 hours.",
"I waited two weeks for delivery and the box arrived completely crushed.",
"It is okay for the price, but the screen could be brighter.",
"Customer service ignored my emails for days. Never again.",
"Absolutely love the new design, it feels premium and the colors pop.",
]
records = []
for r in reviews:
llm_out = analyze_sentiment_llm(r)
base_out = analyze_sentiment_baseline(r)
records.append({
"review": r,
"llm_sentiment": llm_out.get("sentiment"),
"llm_confidence": llm_out.get("confidence"),
"llm_key_phrases": llm_out.get("key_phrases"),
"bert_sentiment": base_out.get("sentiment"),
"bert_confidence": base_out.get("confidence"),
})
df = pd.DataFrame(records)
print(df.to_string(index=False))
Run it
Save everything into sentiment_pipeline.py and run it from your terminal.
python sentiment_pipeline.py
You should see structured LLM output side by side with the DistilBERT baseline. Example output looks like this:
review llm_sentiment llm_confidence llm_key_phrases bert_sentiment bert_confidence
The battery life on this laptop is incredible... positive 95 [battery life, incredible] positive 99.9
I waited two weeks for delivery and the box a... negative 92 [waited two weeks, crushed] negative 99.8
It is okay for the price, but the screen could... neutral 60 [okay for the price] negative 53.2
Customer service ignored my emails for days. N... negative 96 [ignored my emails, never] negative 99.9
Absolutely love the new design, it feels premi... positive 98 [love, premium, colors pop] positive 99.9
Wrap-up
From here you can wire the analyzer into a FastAPI endpoint to score support tickets as they arrive, or swap in a reasoning model like deepseek-r1-671b when you need explicit chain-of-thought for compliance reviews. Because Oxlo.ai charges one flat cost per request, you can throw long reviews or multi-turn prompts at the pipeline without watching token meters spin up. See the details at https://oxlo.ai/pricing.
Top comments (0)