DEV Community

shashank ms
shashank ms

Posted on

Zero-Shot Learning with LLM: Applications and Best Practices

We are going to build a support ticket triage agent that classifies incoming messages, assigns severity, and routes them to the correct team without a single training example. This is zero-shot learning: the LLM infers the task from a detailed system prompt and a raw ticket body. I will walk through the exact code I run on Oxlo.ai, where flat per-request pricing makes long system prompts economical.

What you'll need

Step 1: Connect to Oxlo.ai and verify the client

I always start by confirming the client can authenticate and reach the API. This avoids debugging network issues later.

from openai import OpenAI

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

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Say 'Connection OK' and nothing else."},
    ],
)

print(response.choices[0].message.content)

Step 2: Design the zero-shot system prompt

Zero-shot means zero examples. The model must learn the output schema and classification rules from instructions alone. I treat the system prompt as a config file that defines categories, severity levels, and the exact JSON schema the agent must return.

SYSTEM_PROMPT = '''
You are a support ticket triage agent. Your job is to read a raw customer message and return a single JSON object with no markdown formatting.

Classification rules:
- category must be one of: Billing, Technical, Account, General.
- severity must be one of: Low, Medium, High, Critical.
- team must be one of: Finance, Engineering, Customer Success.
- reasoning must be one sentence explaining your choice.

Severity guidance:
- Critical: service down, data loss, security breach.
- High: feature broken, cannot complete core workflow.
- Medium: partial issue, workaround exists.
- Low: general question, feature request, typo.

JSON schema:
{
  "category": "string",
  "severity": "string",
  "team": "string",
  "reasoning": "string"
}

Return only the JSON object. Do not include backticks or explanation outside the JSON.
'''

Step 3: Build the triage function

Now I wrap the API call into a reusable function. I use JSON mode to constrain the model to valid JSON, then parse the result with the standard library. I run this on llama-3.3-70b because it follows structured instructions reliably.

import json

def triage_ticket(ticket_body: str) -> dict:
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": ticket_body},
        ],
        response_format={"type": "json_object"},
        temperature=0.2,
    )

    raw = response.choices[0].message.content
    return json.loads(raw)

Step 4: Process a batch of tickets

In production, tickets arrive as a list. I loop over them, classify each, and print a routing report. Because Oxlo.ai bills per request, not per token, adding a long system prompt or a verbose ticket history does not inflate the cost per classification.

tickets = [
    "I was double charged for my subscription this month. Please refund the extra payment.",
    "The API returns a 500 error every time I try to create a webhook. This is blocking our deploy.",
    "How do I reset my password? I cannot find the link.",
    "We need SAML SSO support for our enterprise account. Is this on the roadmap?",
]

for ticket in tickets:
    result = triage_ticket(ticket)
    print(f"Ticket: {ticket[:50]}...")
    print(f"  Route to: {result['team']} | Severity: {result['severity']}")
    print(f"  Reason: {result['reasoning']}")
    print()

Run it

Here is the complete script and the output it produces when I execute it against Oxlo.ai.

from openai import OpenAI
import json

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

SYSTEM_PROMPT = '''
You are a support ticket triage agent. Your job is to read a raw customer message and return a single JSON object with no markdown formatting.

Classification rules:
- category must be one of: Billing, Technical, Account, General.
- severity must be one of: Low, Medium, High, Critical.
- team must be one of: Finance, Engineering, Customer Success.
- reasoning must be one sentence explaining your choice.

Severity guidance:
- Critical: service down, data loss, security breach.
- High: feature broken, cannot complete core workflow.
- Medium: partial issue, workaround exists.
- Low: general question, feature request, typo.

JSON schema:
{
  "category": "string",
  "severity": "string",
  "team": "string",
  "reasoning": "string"
}

Return only the JSON object. Do not include backticks or explanation outside the JSON.
'''

def triage_ticket(ticket_body: str) -> dict:
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": ticket_body},
        ],
        response_format={"type": "json_object"},
        temperature=0.2,
    )
    raw = response.choices[0].message.content
    return json.loads(raw)

tickets = [
    "I was double charged for my subscription this month. Please refund the extra payment.",
    "The API returns a 500 error every time I try to create a webhook. This is blocking our deploy.",
    "How do I reset my password? I cannot find the link.",
    "We need SAML SSO support for our enterprise account. Is this on the roadmap?",
]

for ticket in tickets:
    result = triage_ticket(ticket)
    print(f"Ticket: {ticket[:50]}...")
    print(f"  Route to: {result['team']} | Severity: {result['severity']}")
    print(f"  Reason: {result['reasoning']}")
    print()

Example output:

Ticket: I was double charged for my subscription this month...
  Route to: Finance | Severity: High
  Reason: Double charging is a billing error that requires immediate refund processing.

Ticket: The API returns a 500 error every time I try to create...
  Route to: Engineering | Severity: Critical
  Reason: A recurring 500 error blocking deployment indicates a service outage.

Ticket: How do I reset my password? I cannot find the link...
  Route to: Customer Success | Severity: Low
  Reason: Password reset is a standard account support question with no urgency.

Ticket: We need SAML SSO support for our enterprise account. Is...
  Route to: Engineering | Severity: Low
  Reason: Feature requests for roadmap items are not urgent incidents.

Next steps

Swap in kimi-k2.6 or deepseek-v3.2 on Oxlo.ai if you need deeper reasoning for ambiguous edge cases, or add function calling so the agent can open a Jira ticket or Slack channel automatically after classification. If volume grows, the flat per-request pricing on Oxlo.ai keeps long-context triage predictable.

Top comments (0)