DEV Community

shashank ms
shashank ms

Posted on

LLM for Sentiment Analysis in Social Media

We are building a batch sentiment analyzer for social media comments that classifies tone, extracts emotions, and flags urgent posts. It is designed for community managers and product teams who need structured signal from noisy, unstructured feedback streams.

What you'll need

Before starting, grab an Oxlo.ai API key from https://portal.oxlo.ai. You will also need Python 3.10 or newer and the OpenAI SDK.

pip install openai

Step 1: Configure the Oxlo.ai client

I keep secrets out of code by reading the API key from the environment. Then I point the OpenAI SDK at Oxlo.ai.

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key=os.getenv("OXLO_API_KEY")
)

Step 2: Write the system prompt

The system prompt forces the model to return strict JSON and defines the dimensions we care about: sentiment label, confidence, emotions, and urgency.

SYSTEM_PROMPT = """You are a social media sentiment analyzer.
Analyze the user provided post and return ONLY a JSON object with no markdown formatting.
Use this exact schema:
{
  "sentiment": "positive" | "negative" | "neutral" | "mixed",
  "confidence": 0.0 to 1.0,
  "emotions": ["joy", "anger", "sadness", "fear", "surprise", "disgust"] (pick up to two),
  "urgency": true | false,
  "summary": "one sentence explaining the verdict"
}
Be concise and accurate."""

Step 3: Create the analysis function

This helper calls Oxlo.ai and parses the JSON response. I use Llama 3.3 70B because it handles instruction tuning reliably and keeps latency low.

import json

def analyze_post(text: str) -> dict:
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": text},
        ],
    )
    raw = response.choices[0].message.content.strip()
    # Remove accidental markdown fences if the model emits them
    if raw.startswith("

```"):
        raw = raw.split("\n", 1)[1].rsplit("```

", 1)[0].strip()
    return json.loads(raw)

Step 4: Batch process posts

Social data never arrives one at a time. I loop over a list of posts, analyze each one, and store the results. Because Oxlo.ai uses flat per-request pricing, the cost is predictable even when individual posts are long.

posts = [
    "Just spent 20 minutes on hold and the app still crashed. Worst experience ever.",
    "Love the new dark mode. The team really listens!",
    "Is anyone else seeing a 500 error on checkout? Need this fixed ASAP.",
    "It's fine I guess. Does what it says.",
    "Your latest update deleted all my saved projects. I am furious.",
]

results = []
for post in posts:
    try:
        result = analyze_post(post)
        result["original_text"] = post
        results.append(result)
    except Exception as e:
        results.append({
            "original_text": post,
            "error": str(e),
            "sentiment": "unknown"
        })

Step 5: Format and export results

Raw JSON is hard to scan in standups. I print a simple table and write the output to a CSV for downstream dashboards.

import csv

# Print a quick table
print(f"{'Sentiment':<10} {'Urgency':<8} {'Summary'}")
print("-" * 60)
for r in results:
    if "error" in r:
        continue
    print(f"{r['sentiment']:<10} {str(r['urgency']):<8} {r['summary']}")

# Save to CSV
with open("sentiment_report.csv", "w", newline="") as f:
    writer = csv.DictWriter(
        f,
        fieldnames=["sentiment", "confidence", "emotions", "urgency", "summary", "original_text"]
    )
    writer.writeheader()
    writer.writerows(results)

Run it

Here is the complete entry point. Execute the script and you will see structured sentiment output for every post.

if __name__ == "__main__":
    for r in results:
        if "error" in r:
            print(f"FAILED: {r['original_text'][:50]}... -> {r['error']}")
        else:
            print(f"{r['sentiment'].upper()} | urgency={r['urgency']} | {r['summary']}")

Example output:

NEGATIVE | urgency=False | The user is frustrated due to a poor app experience and long hold time.
POSITIVE | urgency=False | The user is happy with the new dark mode and feels heard.
NEGATIVE | urgency=True | The user is reporting a critical checkout error that needs immediate attention.
NEUTRAL  | urgency=False | The user has a neutral opinion, stating the product is adequate.
NEGATIVE | urgency=True | The user is extremely angry because an update deleted their saved projects.

Next steps

Wire this analyzer into a webhook that listens to your Twitter or Reddit firehose and writes results into a real-time database. Alternatively, extend the prompt to perform aspect-based sentiment so you can track scores for specific product features like checkout, onboarding, or dark mode.

Top comments (0)