Unlocking the Power of LLM for Text Analysis
We are going to build a batch feedback analyzer that reads raw customer support tickets, scores sentiment, extracts topics, and flags urgent issues. It helps support teams prioritize their queue without reading every mes
We are going to build a batch feedback analyzer that reads raw customer support tickets, scores sentiment, extracts topics, and flags urgent issues. It helps support teams prioritize their queue without reading every message manually. I will use Oxlo.ai and the OpenAI SDK so the code is fully runnable against a flat per-request endpoint.
What you'll need
You need Python 3.10 or newer, the OpenAI SDK, and an Oxlo.ai API key. Grab the key from https://portal.oxlo.ai. Install the dependencies with pip.
pip install openai pandas
Step 1: Set up the client
I initialize the OpenAI client pointing at Oxlo.ai. Because Oxlo.ai is fully OpenAI SDK compatible, this is the only change needed from a standard setup.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.environ.get("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)
Step 2: Define the schema and system prompt
I want structured JSON back so I can feed results directly into a dataframe. The system prompt forces exactly three fields: sentiment, topics, and urgent.
SYSTEM_PROMPT = """You are a support ticket analyst. Read the ticket and return ONLY a JSON object with this exact shape:
{
"sentiment": "positive" | "neutral" | "negative",
"topics": ["topic_one", "topic_two"],
"urgent": true | false
}
Rules:
- urgent is true only if the customer mentions a security breach, data loss, payment failure, or service outage.
- topics must be lowercase, one or two words each.
- Do not include markdown or explanation outside the JSON."""
Step 3: Build the analysis function
This function wraps the Oxlo.ai call. I use Llama 3.3 70B because it handles instruction following reliably, and I set the response format to JSON to lock output structure.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
SYSTEM_PROMPT = """You are a support ticket analyst. Read the ticket and return ONLY a JSON object with this exact shape:
{
"sentiment": "positive" | "neutral" | "negative",
"topics": ["topic_one", "topic_two"],
"urgent": true | false
}
Rules:
- urgent is true only if the customer mentions a security breach, data loss, payment failure, or service outage.
- topics must be lowercase, one or two words each.
- Do not include markdown or explanation outside the JSON."""
def analyze_ticket(text: str) -> dict:
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
],
response_format={"type": "json_object"},
temperature=0.1,
)
return json.loads(response.choices[0].message.content)
Step 4: Process a batch
I will create a small inline dataset so the script is runnable without external files. In production you would swap this for a CSV read with pandas.
import pandas as pd
tickets = [
{"id": 101, "body": "I love the new dashboard, but my export failed twice today."},
{"id": 102, "body": "URGENT: customer credit cards are being double charged since the 2 AM deploy."},
{"id": 103, "body": "How do I change my notification settings? Thanks."},
]
df = pd.DataFrame(tickets)
df["analysis"] = df["body"].apply(analyze_ticket)
# Flatten the JSON into columns
df = pd.concat([df.drop(columns=["analysis"]), df["analysis"].apply(pd.Series)], axis=1)
print(df[["id", "sentiment", "topics", "urgent"]])
Step 5: Surface urgent issues
Finally, I filter for anything marked urgent and negative sentiment, then print a priority list. This is the exact view I send to the on-call lead each morning.
flagged = df[(df["urgent"] == True) & (df["sentiment"] == "negative")]
if flagged.empty:
print("No urgent negative tickets.")
else:
for _, row in flagged.iterrows():
print(f"Ticket {row['id']}: {row['body']}")
print(f" Topics: {', '.join(row['topics'])}")
print()
Run it
Here is the complete script. Save it as feedback_analyzer.py, export your key, and run it.
import json
import os
import pandas as pd
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.environ.get("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)
SYSTEM_PROMPT = """You are a support ticket analyst. Read the ticket and return ONLY a JSON object with this exact shape:
{
"sentiment": "positive" | "neutral" | "negative",
"topics": ["topic_one", "topic_two"],
"urgent": true | false
}
Rules:
- urgent is true only if the customer mentions a security breach, data loss, payment failure, or service outage.
- topics must be lowercase, one or two words each.
- Do not include markdown or explanation outside the JSON."""
def analyze_ticket(text: str) -> dict:
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": text},
],
response_format={"type": "json_object"},
temperature=0.1,
)
return json.loads(response.choices[0].message.content)
tickets = [
{"id": 101, "body": "I love the new dashboard, but my export failed twice today."},
{"id": 102, "body": "URGENT: customer credit cards are being double charged since the 2 AM deploy."},
{"id": 103, "body": "How do I change my notification settings? Thanks."},
]
df = pd.DataFrame(tickets)
df["analysis"] = df["body"].apply(analyze_ticket)
df = pd.concat([df.drop(columns=["analysis"]), df["analysis"].apply(pd.Series)], axis=1)
print(df[["id", "sentiment", "topics", "urgent"]])
print()
flagged = df[(df["urgent"] == True) & (df["sentiment"] == "negative")]
if flagged.empty:
print("No urgent negative tickets.")
else:
for _, row in flagged.iterrows():
print(f"Ticket {row['id']}: {row['body']}")
print(f" Topics: {', '.join(row['topics'])}")
print()
Execute it from your terminal:
export OXLO_API_KEY="sk-oxlo.ai-..."
python feedback_analyzer.py
When I ran this against Oxlo.ai, the output looked like this:
id sentiment topics urgent
0 101 negative [export, dashboard] False
1 102 negative [payment, billing] True
2 103 neutral [notifications] False
Ticket 102: URGENT: customer credit cards are being double charged since the 2 AM deploy.
Topics: payment, billing
Wrap up
This pipeline gives you a working text analysis layer in under fifty lines of code. Two concrete ways to extend it: first, schedule the script as a nightly cron job and POST flagged tickets to a Slack webhook so the team sees them first thing. Second, swap in DeepSeek V3.2 or Kimi K2.6 if you want heavier reasoning for multi-step classification tasks. Because Oxlo.ai uses flat per-request pricing, you can process large backlogs without the cost scaling on ticket length. See the details at https://oxlo.ai/pricing.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.