DEV Community

shashank ms
shashank ms

Posted on

LLM for Question Answering in FAQs

Frequently Asked Questions pages are high-traffic support surfaces, but traditional keyword search often fails on paraphrased or ambiguous user queries. Large language models close this gap by matching intent rather than exact lexical overlap, turning static FAQ documents into conversational, self-service interfaces. With modern embedding and chat models available through a single API, you can build a pipeline that retrieves relevant answers and generates precise responses without maintaining brittle synonym lists or manual intent classifiers.

Why LLMs transform FAQ QA

Keyword-based FAQ search relies on TF-IDF or BM25, which break when users ask "How do I change my login credentials?" instead of "How do I reset my password?" LLMs understand semantic equivalence, handle typos, and can synthesize an answer even when the exact phrasing does not appear in your knowledge base. For organizations with expanding support documentation, this reduces ticket volume and keeps answers consistent across channels.

Retrieval augmented generation vs direct context

If your FAQ fits inside the context window, you can inject the entire document into the prompt and ask the model to answer based strictly on that text. This works well for small product manuals or early-stage knowledge bases. Once your content grows beyond a few thousand lines, retrieval augmented generation becomes the practical choice. You chunk the documentation, embed each section using an embeddings model, and retrieve only the top-k relevant passages to feed into the generator. Oxlo.ai offers both embeddings, such as BGE-Large and E5-Large, and general-purpose chat models, so the retrieval and generation stages run against the same API with identical authentication and base URL.

Building a minimal FAQ pipeline

The following Python example shows a minimal RAG loop against Oxlo.ai. It embeds FAQ chunks with BGE-Large, retrieves the closest matches via cosine similarity, and generates a grounded answer with Llama 3.3 70B. Because Oxlo.ai is fully OpenAI SDK compatible, the client setup requires only a base URL change.

import os
import numpy as np
from openai import OpenAI

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

faq_chunks = [
    {"question": "How do I reset my password?",
     "answer": "Click 'Forgot password' on the login screen and follow the email link."},
    {"question": "Which payment methods do you accept?",
     "answer": "We accept Visa, Mastercard, and ACH bank transfers."},
    # Append additional chunks here.
]

def embed(text: str):
    resp = client.embeddings.create(model="BGE-Large", input=text)
    return np.array(resp.data[0].embedding)

faq_embeddings = [embed(c["question"] + " " + c["answer"]) for c in faq_chunks]

def retrieve(query: str, k: int = 2):
    q_emb = embed(query)
    scores = [np.dot(q_emb, c_emb) for c_emb in faq_embeddings]
    top_indices = np.argsort(scores)[-k:][::-1]
    return [faq_chunks[i] for i in top_indices]

def answer_question(query: str) -> str:
    context = retrieve(query)
    context_block = "\n".join(
        f"Q: {c['question']}\nA: {c['answer']}" for c in context
    )
    messages = [
        {"role": "system", "content": "You are a concise support assistant. Answer using only the provided FAQ context. If the answer is not in the context, say you do not know."},
        {"role": "user", "content": f"FAQ Context:\n{context_block}\n\nUser question: {query}"}
    ]
    resp = client.chat.completions.create(
        model="Llama-3.3-70B",
        messages=messages,
        temperature=0.1
    )
    return resp.choices[0].message.content

if __name__ == "__main__":
    print(answer_question("I forgot my password, what now?"))

Note the low temperature. FAQ answers should be deterministic and faithful to the source text, not creative.

Controlling output with JSON mode

If your frontend needs structured data, you can enforce JSON output instead of parsing free text. This is useful when you want to return both the answer and a confidence flag or a reference to the source FAQ entry. Oxlo.ai supports JSON mode through the standard OpenAI SDK parameter.

import json

def answer_structured(query: str):
context = retrieve(query)
context_block = "\n".join(
f"Q: {c['question']}\nA: {c['answer']}" for c in context
)
messages = [
{"role": "system", "content": "You are a support assistant. Respond in JSON with keys: answer, source_question, confident (boolean)."},
{"role": "user", "content": f"Context:\n

Top comments (0)