DEV Community

shashank ms
shashank ms

Posted on

Sentiment Analysis with LLM and Transformers

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)