DEV Community

shashank ms
shashank ms

Posted on

Using LLM for Question Answering, Text Summarization, and Sentiment Analysis: Best Practices and Examples

We are building a single-file Python agent that performs question answering, text summarization, and sentiment analysis through Oxlo.ai's API. It is useful for any pipeline that needs to extract meaning from unstructured text without running three separate services.

What you'll need

  • Python 3.10 or newer installed locally.
  • The OpenAI SDK. Install it with pip install openai.
  • An Oxlo.ai API key from https://portal.oxlo.ai. Oxlo.ai uses request-based pricing, so feeding long documents into the summarizer costs the same flat rate as a short prompt. See https://oxlo.ai/pricing for plan details.

Step 1: Initialize the Oxlo.ai client

Create a file named text_tools.py and instantiate the client. I always run a quick connectivity check to confirm the key and base URL are correct before adding logic.

from openai import OpenAI

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

SYSTEM_PROMPT = "You are a helpful assistant."
user_message = "Say 'Connection OK' and nothing else."

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user", "content": user_message},
    ],
)
print(response.choices[0].message.content.strip())

Step 2: Define the agent's system prompt and build question answering

The system prompt is the contract. It locks the model into the three tasks and constrains output formats. After defining it, I add the first function that answers questions over a provided context.

from openai import OpenAI

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

SYSTEM_PROMPT = """You are a precise text analysis engine. You support three tasks:
1. Question Answering: Answer using ONLY the provided context. If the answer is not in the context, reply "I don't know".
2. Summarization: Reduce the text to the requested number of sentences while keeping key facts.
3. Sentiment Analysis: Classify the text as Positive, Negative, or Neutral. Output exactly one word."""

def answer_question(context: str, question: str) -> str:
    user_message = f"Task: Question Answering\nContext:\n{context}\n\nQuestion: {question}"
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

Step 3: Add text summarization

For summarization I switch to kimi-k2.6 because its 131K context window can ingest entire reports in one shot. On Oxlo.ai, a ten-page document costs the same flat per-request rate as a single sentence, which makes long-article summarization practical at scale.

from openai import OpenAI

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

SYSTEM_PROMPT = """You are a precise text analysis engine. You support three tasks:
1. Question Answering: Answer using ONLY the provided context. If the answer is not in the context, reply "I don't know".
2. Summarization: Reduce the text to the requested number of sentences while keeping key facts.
3. Sentiment Analysis: Classify the text as Positive, Negative, or Neutral. Output exactly one word."""

def summarize(text: str, sentences: int = 3) -> str:
    user_message = f"Task: Summarization\nTarget length: {sentences} sentences\nText:\n{text}"
    response = client.chat.completions.create(
        model="kimi-k2.6",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

Step 4: Add sentiment analysis

I use deepseek-v3.2 for sentiment classification. It is fast and available on the Oxlo.ai free tier, so you can label large batches of user feedback without touching your paid quota.

from openai import OpenAI

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

SYSTEM_PROMPT = """You are a precise text analysis engine. You support three tasks:
1. Question Answering: Answer using ONLY the provided context. If the answer is not in the context, reply "I don't know".
2. Summarization: Reduce the text to the requested number of sentences while keeping key facts.
3. Sentiment Analysis: Classify the text as Positive, Negative, or Neutral. Output exactly one word."""

def analyze_sentiment(text: str) -> str:
    user_message = f"Task: Sentiment Analysis\nText:\n{text}"
    response = client.chat.completions.create(
        model="deepseek-v3.2",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

Step 5: Assemble the complete script

Here is the full utility with all three functions and a small test harness that exercises each capability against the same sample text.

from openai import OpenAI

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

SYSTEM_PROMPT = """You are a precise text analysis engine. You support three tasks:
1. Question Answering: Answer using ONLY the provided context. If the answer is not in the context, reply "I don't know".
2. Summarization: Reduce the text to the requested number of sentences while keeping key facts.
3. Sentiment Analysis: Classify the text as Positive, Negative, or Neutral. Output exactly one word."""

def answer_question(context: str, question: str) -> str:
    user_message = f"Task: Question Answering\nContext:\n{context}\n\nQuestion: {question}"
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

def summarize(text: str, sentences: int = 3) -> str:
    user_message = f"Task: Summarization\nTarget length: {sentences} sentences\nText:\n{text}"
    response = client.chat.completions.create(
        model="kimi-k2.6",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

def analyze_sentiment(text: str) -> str:
    user_message = f"Task: Sentiment Analysis\nText:\n{text}"
    response = client.chat.completions.create(
        model="deepseek-v3.2",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )
    return response.choices[0].message.content.strip()

if __name__ == "__main__":
    article = (
        "Oxlo.ai launched a new inference platform for open-source LLMs. "
        "Unlike token-based providers, it offers flat per-request pricing. "
        "Developers are praising the cost savings on long-context workloads."
    )

    print("Summary:", summarize(article, sentences=2))
    print("Sentiment:", analyze_sentiment(article))
    print("QA:", answer_question(article, "What pricing model does Oxlo.ai use?"))

Run it

Save the file as text_tools.py, replace YOUR_OXLO_API_KEY with your key from https://portal.oxlo.ai, then execute:

python text_tools.py

You should see output similar to this:

Summary: Oxlo.ai introduced a flat per-request pricing model for open-source LLM inference. Developers are reporting significant cost savings, particularly on long-context workloads.
Sentiment: Positive
QA: Flat per-request pricing.

Next steps

Wrap these functions in a FastAPI endpoint so other services can call them over HTTP. You can also switch the sentiment function to JSON mode by adding response_format={"type": "json_object"} to the completion call and asking for a structured object with label and confidence fields, which makes downstream filtering much easier.

Top comments (0)