Here is a practical pipeline that turns raw text into structured intelligence. We will build a single Python module that runs sentiment analysis, topic classification, and named entity recognition through one call to an LLM. If you process support tickets, survey responses, or news feeds, this removes the need to manage three separate services.
What you'll need
- An Oxlo.ai API key from https://portal.oxlo.ai
- Python 3.10 or newer
- The OpenAI SDK:
pip install openai
Step 1: Set up the Oxlo.ai client
I keep the API key in an environment variable in production, but for this tutorial you can paste it directly. Oxlo.ai exposes a fully OpenAI-compatible endpoint, so the official SDK works without adapters. The snippet below verifies that you can reach the API and that your key is active.
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key="YOUR_OXLO_API_KEY"
)
# Quick connectivity check
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[{"role": "user", "content": "ping"}],
max_tokens=5
)
print(response.choices[0].message.content)
Step 2: Design the system prompt
The trick to reliable structured output is being explicit about the schema in the system prompt. I treat the model as a strict JSON formatter. This prompt is the only part you need to edit if you want to add custom categories or entity types later.
SYSTEM_PROMPT = """You are a structured text analysis engine.
Analyze the user text and return a single JSON object with exactly these keys:
- sentiment: one of "positive", "neutral", or "negative"
- category: one of "support", "billing", "feedback", or "other"
- entities: an array of objects, each with "text", "type", and "start" keys.
Supported types are "PERSON", "ORG", "PRODUCT", and "MONEY".
Rules:
1. Do not include markdown, explanations, or code fences.
2. Return only the raw JSON object.
3. The "start" value is the zero-based character index where the entity text begins.
4. If no entities are found, return an empty array for entities."""
Step 3: Build the analysis function
This function wraps the API call, strips accidental markdown fences, and parses the JSON. I use llama-3.3-70b because it follows instructions reliably and runs with no cold starts on Oxlo.ai. Because Oxlo.ai uses request-based pricing instead of token-based pricing, you can throw long support transcripts or chat histories at this without the cost scaling with input length. Details are at https://oxlo.ai/pricing.
import json
def analyze_text(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,
max_tokens=512
)
raw = response.choices[0].message.content.strip()
# Guard against markdown fences
if raw.startswith("
```"):
raw = raw.split("\n", 1)[1].rsplit("```
", 1)[0].strip()
return json.loads(raw)
Step 4: Process a batch of texts
Real data is never clean, so I loop over a list of strings and collect results in a list of dictionaries. This stays simple so you can swap in queue-based processing later.
texts = [
"Sarah from Acme Corp said the ProWidget is fantastic, but she wants a $50 refund.",
"I hate the new dashboard. It crashes every time I try to export.",
"The invoice for March was correct. No action needed.",
]
results = []
for t in texts:
try:
result = analyze_text(t)
results.append({"input": t, "analysis": result})
except Exception as e:
results.append({"input": t, "error": str(e)})
print(json.dumps(results, indent=2))
Run it
Save the full script as analyzer.py, export your key, and run python analyzer.py. You should see structured JSON for every input. Here is the output I get on my end.
[
{
"input": "Sarah from Acme Corp said the ProWidget is fantastic, but she wants a $50 refund.",
"analysis": {
"sentiment": "positive",
"category": "support",
"entities": [
{"text": "Sarah", "type": "PERSON", "start": 0},
{"text": "Acme Corp", "type": "ORG", "start": 12},
{"text": "ProWidget", "type": "PRODUCT", "start": 31},
{"text": "$50", "type": "MONEY", "start": 72}
]
}
},
{
"input": "I hate the new dashboard. It crashes every time I try to export.",
"analysis": {
"sentiment": "negative",
"category": "feedback",
"entities": []
}
},
{
"input": "The invoice for March was correct. No action needed.",
"analysis": {
"sentiment": "neutral",
"category": "billing",
"entities": []
}
}
]
Wrap-up
You now have a single-pass analyzer that runs on Oxlo.ai. Two concrete next steps: wire this into a FastAPI endpoint so other services can POST text and receive JSON back, or swap in qwen-3-32b or kimi-k2.6 if you need stronger multilingual entity recognition or vision support for scanned documents.
Top comments (0)