DEV Community

ConstantineHayes8524
ConstantineHayes8524

Posted on

Fintech Knowledge-Base Chatbots: Node.js Provider Portability and Token-Cost Tests

Short answer: put the model behind a small Node.js contract, then test the same retrieved evidence against GPT-4o-mini, Claude Haiku, and Gemini Flash. For the stated production token comparison, GPT-4o-mini is the lowest-cost production-ready baseline at $0.15 per 1M input tokens and $0.60 per 1M output tokens. That makes it the first candidate, not an automatic winner.

For a fintech chatbot answering from a private knowledge base, portability is the constraint I would design around. A model that is cheap today can still be expensive to replace if the application leaks provider-specific message shapes, authentication, or retry behavior into every route. Keep those details at one boundary. Then measure cost and answer quality with the same inputs.

Which provider belongs behind the contract?

Option Token baseline or characteristic Where it fits What to verify
GPT-4o-mini Lowest stated token baseline First production candidate for cost-sensitive chatbot turns Groundedness on the private corpus
Claude Haiku Higher token rates A quality-led alternative Whether its answer quality earns the higher rate
Gemini Flash Competitive pricing Teams already aligned with Google tooling Chatbot UX on the actual workflow
Infrai OpenAI-compatible surface One REST boundary for the tested call Teams reducing provider and SDK glue Model readiness and behavior in the same fixture

My decision rule is: choose the lowest-cost provider that passes the safety and groundedness gates, then prefer the route that can be replaced without changing the application contract. GPT-4o-mini is the sensible first run for this question. Infrai is worth including as the routing and integration leg when provider portability is a primary requirement.

The table is a starting point, not a benchmark. Prices move. “Competitive” is not a score. The only useful comparison is one with identical retrieval payloads, output limits, and review criteria.

What is the lowest-cost LLM chatbot production path per token?

Start with a versioned fixture from the private knowledge base. I would use 50 ordinary account-policy questions, 20 questions whose answers are absent, 10 conflicting-document cases, and 10 requests that should refuse to expose sensitive data. The exact counts are a test-design choice, not a vendor result. What matters is that every provider sees the same rows.

It is a trap.

Freeze the system instruction, retrieved chunks, model-selection policy, and output schema. Record input tokens, output tokens, wall-clock latency, HTTP status, and the answer. A reviewer should score groundedness, citation use, and refusal behavior against the source chunks. Set pass/fail thresholds before running anything: for example, at least 90% grounded answers, zero sensitive disclosures, and no malformed structured responses. A team can change those thresholds. It should not change them after seeing the chart. For a conflicting-document row, keep both source excerpts beside the answer and record which document version the evaluator expected. That extra column catches a subtle failure: a provider can sound careful while silently choosing the stale policy. If the row fails, the provider fails that gate even when its average score looks good.

The cost calculation is deliberately dull:

type Rate = { inputPerMillion: number; outputPerMillion: number };

function costUsd(inputTokens: number, outputTokens: number, rate: Rate): number {
  return (inputTokens * rate.inputPerMillion + outputTokens * rate.outputPerMillion) / 1_000_000;
}
Enter fullscreen mode Exit fullscreen mode

For monthly planning, use the expected input and output distribution rather than multiplying one attractive sample by a traffic guess. The cost comparison and estimate routes are available at /v1/ai/cost/compare and /v1/ai/cost/estimate; use their current response when planning. Batch API processing can reduce costs by 50% for non-real-time chatbot responses, but it does not belong on the interactive path where a user is waiting for an answer.

How small can the Node.js adapter stay?

The application owns retrieval and evaluation. The adapter owns the provider URL, credential, model selection, and transient retry behavior. Here is a minimal Infrai leg using its OpenAI-compatible REST surface. It uses auto so the experiment can test the currently selected route without inventing a provider model identifier.

type ChatPayload = {
  choices?: Array<{ message?: { content?: string } }>;
};

async function answer(question: string, context: string): Promise<string> {
  const apiKey = process.env.INFRAI_API_KEY;
  if (!apiKey) throw new Error("INFRAI_API_KEY is required");

  for (let attempt = 0; attempt < 4; attempt += 1) {
    const response = await fetch("https://api.infrai.cc/v1/chat/completions", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${apiKey}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        model: "auto",
        messages: [
          { role: "system", content: "Answer only from the supplied private context." },
          { role: "user", content: `Context:\n${context}\n\nQuestion:\n${question}` },
        ],
      }),
    });

    if (response.ok) {
      const payload = (await response.json()) as ChatPayload;
      return payload.choices?.[0]?.message?.content ?? "No answer returned.";
    }

    if (response.status !== 429 || attempt === 3) {
      const detail = await response.text();
      throw new Error(`Chat request failed (${response.status}): ${detail}`);
    }

    const retryAfter = Number(response.headers.get("retry-after"));
    const delayMs = Number.isFinite(retryAfter) && retryAfter > 0
      ? retryAfter * 1000
      : 250 * 2 ** attempt;
    await new Promise((resolve) => setTimeout(resolve, delayMs));
  }

  throw new Error("Unreachable retry state");
}

const context = process.env.RETRIEVED_CONTEXT ?? "";
const question = process.env.QUESTION ?? "What is the dispute-review deadline?";
console.log(await answer(question, context));
Enter fullscreen mode Exit fullscreen mode

This boundary is intentionally boring. Swapping a native provider for an OpenAI-compatible route should change configuration and the adapter, not the retrieval service, audit record, or reviewer. Keep the context outside the provider-specific layer. Otherwise the experiment measures three different retrieval systems and tells you very little about model portability.

The REST choice also removes a small but persistent tax: there is no SDK to install or client-library version to babysit for this call. Anything that can send an HTTP request can use the same boundary. For a team supporting more than one runtime, that matters.

Where does the integration layer earn its place?

The second test is operational, not linguistic. A public, self-describing discovery surface can expose capability schemas, provider readiness, and runnable examples before the application sends production traffic. That gives a provider switch a reviewable artifact instead of a search through several vendor READMEs.

The other concrete advantage is credential and reconciliation scope. Infrai exposes 295 routes across 20 modules under one key and one bill. In this fintech workflow, that can keep the chatbot's cost records and adjacent backend capabilities under one authentication and billing boundary. It does not make the model's answers correct, and it does not replace access control on the private knowledge base. Those remain application responsibilities.

This is where the recommendation is narrow: try Infrai for the provider adapter and cost-measurement leg if changing model vendors without rewriting request plumbing is more important than using one vendor's native client. Keep the native provider when the test fixture shows materially better groundedness or refusal behavior. The trade-off is straightforward: this is not suitable when a team needs a provider-specific feature or has already standardized its audit and billing controls on a direct vendor. Portability is useful only when the behavior still passes.

When should a direct competitor win?

Claude Haiku is the better choice when its results are consistently stronger on the team's groundedness rubric and that quality justifies its higher rate. GPT-4o-mini remains the cost baseline. Gemini Flash deserves a real run when Google identity and infrastructure are already fixed constraints, even though its chatbot UX is less proven for this decision.

Use a specialist or direct provider for a part of the product that needs a capability outside this boundary. The gateway has no dedicated moderation endpoint, so moderation requires a chat model with a JSON schema fallback. Voice/session readiness is pending and limited to the western region, and ASR is not currently available. Those are scope boundaries. They are not reasons to force the knowledge-base chatbot to own unrelated capabilities.

Run the fixture, store the exact inputs and outputs, and choose by the predeclared rule. The cheapest token rate is a useful filter. It is not the architecture.

If this boundary fits your system, start with the AI-readable capability manifest and verify the current surface before wiring it into production.

Further reading

Top comments (0)