DEV Community

shashank ms
shashank ms

Posted on

Building a Chatbot with LLM: A Comprehensive Tutorial

We are going to build a customer support chatbot that handles order status questions and basic troubleshooting. This tutorial is for developers who need to ship a working agent without managing infrastructure or unpredictable token costs. By the end, you will have a CLI tool that maintains conversation history, calls a mock order API, and runs entirely on Oxlo.ai.

What you'll need

  • Python 3.10 or newer
  • The OpenAI SDK: pip install openai
  • An Oxlo.ai API key from https://portal.oxlo.ai
  • A virtual environment (optional but recommended)

Step 1: Configure the Oxlo.ai client

Create a file named support_bot.py and initialize the client. I use llama-3.3-70b here because it is a strong general-purpose model, but you can swap in kimi-k2.6 or deepseek-v3.2 later if you need deeper reasoning or coding capabilities.

import os
from openai import OpenAI

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

Step 2: Write the system prompt

The system prompt is the only fine-tuning we need for now. It sets boundaries, tone, and instructs the model to use our tool for order lookups.

SYSTEM_PROMPT = """You are a customer support agent for an electronics store.
You help users with order status, returns, and basic troubleshooting.
Be concise and friendly. If a user asks about an order, you must use the lookup_order tool.
If you do not know something, say so. Do not make up order details."""

Step 3: Manage conversation history

A chatbot without memory is useless. We will keep a simple list of turns and format them into the message array that the Oxlo.ai API expects. Because Oxlo.ai uses request-based pricing, sending the full conversation history every turn does not inflate your cost per call.

history = []

def build_messages(user_input):
    messages = [{"role": "system", "content": SYSTEM_PROMPT}]
    for turn in history:
        messages.append({"role": "user", "content": turn["user"]})
        messages.append({"role": "assistant", "content": turn["assistant"]})
    messages.append({"role": "user", "content": user_input})
    return messages

Step 4: Define a tool for order lookups

We give the model access to a lookup_order function. The function definition is passed in the tools parameter so the LLM knows when to call it. For this tutorial we use a hardcoded dictionary, but in production this would query your ERP or database.

import json

TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "lookup_order",
            "description": "Get order status by order ID",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {
                        "type": "string",
                        "description": "The order ID, e.g. ORD-12345"
                    }
                },
                "required": ["order_id"]
            }
        }
    }
]

def lookup_order(order_id):
    db = {
        "ORD-12345": {"status": "shipped", "item": "USB-C Cable", "eta": "2 days"},
        "ORD-67890": {"status": "processing", "item": "Webcam Pro", "eta": "5 days"}
    }
    return db.get(order_id, {"status": "not_found", "message": "Order not found."})

Step 5: Handle tool calls and generate the final response

When the model requests a tool call, we execute the function, append the result, and send everything back to Oxlo.ai for a final answer.

def chat(user_input):
    messages = build_messages(user_input)

    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=messages,
        tools=TOOLS,
        tool_choice="auto"
    )

    assistant_message = response.choices[0].message

    # Check if the model wants to call a tool
    if assistant_message.tool_calls:
        tool_calls_payload = []
        for tc in assistant_message.tool_calls:
            tool_calls_payload.append({
                "id": tc.id,
                "type": "function",
                "function": {
                    "name": tc.function.name,
                    "arguments": tc.function.arguments
                }
            })

        messages.append({
            "role": "assistant",
            "content": assistant_message.content or "",
            "tool_calls": tool_calls_payload
        })

        for tc in assistant_message.tool_calls:
            if tc.function.name == "lookup_order":
                args = json.loads(tc.function.arguments)
                result = lookup_order(args["order_id"])
                messages.append({
                    "role": "tool",
                    "tool_call_id": tc.id,
                    "content": json.dumps(result)
                })

        # Send the tool results back to get the final response
        final = client.chat.completions.create(
            model="llama-3.3-70b",
            messages=messages
        )
        reply = final.choices[0].message.content
    else:
        reply = assistant_message.content

    # Save to history
    history.append({"user": user_input, "assistant": reply})
    return reply

Step 6: Build the CLI loop

Wire everything into a simple loop that accepts user input, prints the assistant reply, and tracks history.

if __name__ == "__main__":
    print("Support Bot: Hi! How can I help you today? (type 'exit' to quit)")
    while True:
        user_input = input("You: ").strip()
        if user_input.lower() in ("exit", "quit"):
            break
        if not user_input:
            continue
        reply = chat(user_input)
        print(f"Support Bot: {reply}")

Run it

Export your key and run the script. Here is a sample session showing the bot retrieving an order and then answering a follow-up.

$ export OXLO_API_KEY="sk-oxlo.ai-..."
$ python support_bot.py

Support Bot: Hi! How can I help you today? (type 'exit' to quit)
You: Where is my order ORD-12345?
Support Bot: Your order ORD-12345 for USB-C Cable has shipped and should arrive in 2 days.
You: Can I return it?
Support Bot: Yes, you can return items within 30 days of delivery. I can help you start a return request if you would like.
You: exit

Next steps

Replace the mock lookup_order dictionary with a real database query or REST call to your order management system. If you want the bot to answer questions from your help center, add a retrieval step using Oxlo.ai embedding models such as bge-large to pull relevant articles into the system prompt before each turn.

Top comments (0)