We are building a lightweight sentiment analysis CLI that classifies customer feedback into structured labels with confidence scores and short explanations. It is useful for support teams and product managers who need to triage text at scale without maintaining a custom NLP pipeline. I will walk through the exact code I run in production, wired to Oxlo.ai.
What you'll need
- Python 3.10 or higher
- An Oxlo.ai API key from https://portal.oxlo.ai
- The OpenAI SDK:
pip install openai
Step 1: Initialize the Oxlo.ai client
I configure the OpenAI SDK to point to Oxlo.ai. I keep the client at module level so the rest of the script can reuse the same connection pool.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
Step 2: Define the system prompt
The system prompt locks the model into a strict JSON schema. I ask for a label, a confidence score from 0.0 to 1.0, and a one sentence rationale. Keeping the output machine readable removes regex hacks.
SYSTEM_PROMPT = """You are a sentiment analysis engine. Analyze the user-provided text and respond with a single JSON object containing exactly these keys:
- "sentiment": one of "positive", "negative", "neutral", or "mixed"
- "confidence": a float between 0.0 and 1.0
- "rationale": one sentence explaining why
Rules:
- Return only the JSON object, with no markdown formatting and no extra text.
- If the text contains conflicting signals, choose "mixed".
- Base confidence on how explicit the emotional signals are."""
Step 3: Build the analysis function
This function takes a raw string, injects it into the user message, and parses the JSON response. I use Llama 3.3 70B here again, and I set temperature low to keep the output deterministic.
import json
def analyze_sentiment(text: str):
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
],
temperature=0.1,
)
raw = response.choices[0].message.content.strip()
# some models return markdown code fences; strip them if present
if raw.startswith("
```"):
raw = raw.split("```
")[1].replace("json", "").strip()
return json.loads(raw)
Step 4: Add batch processing
Real data comes in lists, not single strings. This helper iterates over a collection, calls analyze_sentiment for each entry, and returns a list of dicts that you can dump to CSV or a database.
from typing import List, Dict
def analyze_batch(texts: List[str]) -> List[Dict]:
results = []
for t in texts:
try:
result = analyze_sentiment(t)
result["input"] = t
results.append(result)
except Exception as e:
results.append({
"input": t,
"sentiment": "error",
"confidence": 0.0,
"rationale": str(e),
})
return results
Step 5: Run it
Here is the full script with three sample reviews. Because Oxlo.ai uses per request pricing, you can stuff an entire support thread into the prompt without the cost scaling with input length.
if __name__ == "__main__":
reviews = [
"The onboarding wizard was smooth and I was productive in ten minutes.",
"I waited three days for a reply and the fix still did not work. Frustrating.",
"The feature works as described, though the UI feels a bit dated.",
]
for r in analyze_batch(reviews):
print(f"Review: {r['input']}")
print(f"Sentiment: {r['sentiment']} ({r['confidence']:.2f})")
print(f"Rationale: {r['rationale']}")
print()
Example output:
Review: The onboarding wizard was smooth and I was productive in ten minutes.
Sentiment: positive (0.92)
Rationale: The text contains explicit positive language about ease of use and quick productivity.
Review: I waited three days for a reply and the fix still did not work. Frustrating.
Sentiment: negative (0.89)
Rationale: The text explicitly mentions a long wait time and unresolved issue, indicating clear dissatisfaction.
Review: The feature works as described, though the UI feels a bit dated.
Sentiment: mixed (0.78)
Rationale: The text contains a positive functional signal balanced with a mild negative aesthetic signal.
Next steps
Wire this into a FastAPI endpoint so your support stack can classify tickets in real time. If you are processing long conversation threads, try swapping the model to Kimi K2.6 on Oxlo.ai. Its 131K context window and advanced reasoning handle multi-turn transcripts well, and the flat per-request pricing keeps costs predictable even when the prompt grows. You can compare plans at https://oxlo.ai/pricing.
Top comments (0)