DEV Community

shashank ms
shashank ms

Posted on

Building Chatbots with LLM and Intent Recognition

Modern chatbots rarely rely on pure generative freedom. While large language models handle open-ended dialogue well, production systems need guardrails. Intent recognition provides those guardrails by mapping user utterances to predefined actions, reducing hallucinations, and keeping backend integrations predictable. The most reliable approach is a hybrid pipeline: a fast classification step to decide what the user wants, followed by a language model turn to craft the response. This separation of concerns improves accuracy, cuts latency, and makes costs easier to control.

Why Intent Recognition Still Matters

LLMs are generalists. In a customer support scenario, a user might ask to check an order, request a refund, or troubleshoot a product. Without explicit intent detection, the model must infer the correct workflow from prompt context alone. That inference grows harder as conversations lengthen and edge cases multiply. A dedicated intent layer removes ambiguity, enforces business rules, and triggers the right backend handlers before any creative text is generated.

A Practical Architecture

A production chatbot usually splits work across three layers. First, an intent classifier routes the incoming message to a known action. Second, a state manager tracks slots, user context, and conversation history. Third, a response generator produces natural language, often conditioned on the intent and any retrieved data. Each layer can use a different model or service, so you can optimize for speed, cost, and capability independently.

The Intent Recognition Layer

You have two practical options for intent detection. The first is an embedding or classifier model. You encode user utterances with an embedding model such as BGE-Large, compare against labeled examples with cosine similarity, and pick the nearest intent. This is fast and runs entirely inside your infrastructure.

The second option is to use a chat model with structured output. You prompt an LLM to pick an intent from a closed list and return JSON. Oxlo.ai supports JSON mode and function calling, which lets you constrain the model to a rigid schema. For this step, a model like Qwen 3 32B or DeepSeek V4 Flash works well, especially when you need multilingual understanding or very long context to disambiguate intent.

Implementation with Python

Because Oxlo.ai is fully OpenAI SDK compatible, you can point the official client to Oxlo.ai and run the same code you would anywhere else. Below is a minimal two-stage example: classify, then generate.

import os
from openai import OpenAI

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

INTENTS = ["check_order", "return_item", "talk_to_human"]

def classify_intent(user_message: str) -> dict:
    # Use a fast, general-purpose model from Oxlo.ai, such as Llama 3.3 70B.
    response = client.chat.completions.create(
        model="<your-oxlo.ai-model-id>",
        messages=[
            {"role": "system", "content": f"Classify intent into one of {INTENTS}. Respond with JSON."},
            {"role": "user", "content": user_message}
        ],
        response_format={"type": "json_object"},
        max_tokens=256
    )
    import json
    return json.loads(response.choices[0].message.content)

def generate_reply(intent: str, history: list) -> str:
    # Use a model suited for dialogue, such as Qwen 3 32B or DeepSeek V3.2.
    messages = [{"role": "system", "content": f"Intent: {intent}. Answer helpfully."}] + history
    stream = client.chat.completions.create(
        model="<your-oxlo.ai-model-id>",
        messages=messages,
        stream=True
    )
    parts = []
    for chunk in stream:
        if chunk.choices[0].delta.content:
            parts.append(chunk.choices[0].delta.content)
    return "".join(parts)

Context Memory and Multi-Turn Handling

Conversations accumulate history, and naive implementations send the full transcript every turn. A better pattern is to keep recent turns verbatim and summarize older ones. Oxlo.ai hosts models with extended context windows, including DeepSeek V4 Flash with 1M context and Kimi K2.6 with 131K context, so you can maintain longer verbatim histories before compressing. Because Oxlo.ai has no cold starts on popular models, multi-turn responses remain snappy even under load.

Tool Use and Function Calling

Once intent is locked, the bot must act. Oxlo.ai supports function calling, so you can register schemas for order lookups, calendar bookings, or ticket creation. The model returns a structured tool call, your backend executes the logic, and you feed the result back into the chat history. This keeps the LLM focused on language while your code handles state and side effects. For complex tool chains or agentic coding tasks, models like Kimi K2.6, GLM 5, or Minimax M2.5 provide advanced reasoning and tool-use capabilities.

Cost Predictability with Oxlo.ai

Most inference providers bill by the token. That means long system prompts, retrieved documents, and multi-turn history all inflate costs before the model generates a single character. Oxlo.ai uses request-based pricing: one flat cost per API request regardless of prompt length. For chatbots, where each turn can carry a growing conversation history plus retrieval context, this model can be 10-100x cheaper than token-based billing for long-context workloads. You can explore plans and request allowances on the Oxlo.ai pricing page.

Conclusion

Building a chatbot that blends intent recognition with LLM generation gives you the structure of classical dialogue systems and the fluency of modern models. Oxlo.ai supports this architecture with OpenAI SDK compatibility, models ranging from fast classifiers to deep reasoning generators, and flat per-request pricing that removes the billing volatility common with token-based providers. Set your base URL to https://api.oxlo.ai/v1, choose the right model for each pipeline stage, and deploy a chatbot that stays responsive as conversations grow.

Top comments (0)