DEV Community

Mattias chaw
Mattias chaw

Posted on

Building a Cost-Aware LLM Router with DeepSeek V4 Flash and GLM-5

Building a Cost-Aware LLM Router with DeepSeek V4 Flash and GLM-5

Production AI systems rarely need the same model for every request. A short classification task, a code review, and a long reasoning workflow have different latency and quality requirements. Sending all three to one premium model is easy to operate, but it makes cost and failure behaviour harder to control.

This tutorial builds a small model router on top of an OpenAI-compatible endpoint. The example uses two models that were visible in AIWave's public pricing catalog on 2026-08-03:

  • deepseek-v4-flash: $0.206 input and $0.412 output per 1M tokens.
  • glm-5: $1.55 input and $4.96 output per 1M tokens.

The prices above are the live AIWave rates at the time of writing, calculated from the catalog's model and completion ratios. Pricing changes, so production code should treat the AIWave pricing page as the source of truth rather than hard-coding a permanent rate.

Why route instead of using one model?

Routing is useful when workloads have an observable difference in complexity. A flash model can handle short answers, extraction, and routine transformations with lower spend. A stronger reasoning model can be reserved for ambiguous requirements, multi-step planning, and code reviews where an incorrect answer costs more than a few extra tokens.

The important design goal is not “always choose the cheapest model.” It is to make the trade-off explicit and measurable:

Workload Suggested model Input / output per 1M tokens Reason
Classification, extraction, short rewrite deepseek-v4-flash $0.206 / $0.412 Low cost and fast first response
Architecture review, debugging, complex planning glm-5 $1.55 / $4.96 More budget for difficult reasoning

For example, a request with 2,000 input tokens and 800 output tokens costs approximately $0.00074 on DeepSeek V4 Flash and $0.00708 on GLM-5 at the rates above. The calculation is (input_tokens / 1,000,000 × input_price) + (output_tokens / 1,000,000 × output_price). Your actual bill depends on the tokens returned and any retries.

Keep the integration OpenAI-compatible

AIWave exposes the standard Chat Completions shape. Existing OpenAI SDK code only needs a different base URL and a key created in the AIWave dashboard. Keep the placeholder below in source control; never commit a real API key.

from openai import OpenAI

client = OpenAI(
    base_url="https://aiwave.live/v1",
    api_key="YOUR_API_KEY_HERE",  # Create a key at https://aiwave.live/
)

response = client.chat.completions.create(
    model="deepseek-v4-flash",
    messages=[
        {"role": "system", "content": "Return concise, structured answers."},
        {"role": "user", "content": "Extract the three action items from this text."},
    ],
    max_tokens=400,
)

print(response.choices[0].message.content)
Enter fullscreen mode Exit fullscreen mode

The model name is the catalog identifier, not a marketing alias. Before deployment, compare the identifier in your configuration with the current model catalog.

A small deterministic router

The first version can be deliberately boring. Route based on a caller-supplied task type and keep a safe default. This is easier to test than a router that asks another model to classify every request.

from openai import OpenAI

client = OpenAI(base_url="https://aiwave.live/v1", api_key="YOUR_API_KEY_HERE")

MODEL_BY_TASK = {
    "routine": "deepseek-v4-flash",
    "reasoning": "glm-5",
}


def complete(prompt: str, task: str = "routine") -> str:
    model = MODEL_BY_TASK.get(task, MODEL_BY_TASK["routine"])
    result = client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        temperature=0.2 if task == "reasoning" else 0.0,
    )
    return result.choices[0].message.content or ""


print(complete("Turn this support ticket into JSON fields: priority, owner, next_step."))
print(complete("Review this migration plan and list hidden failure modes.", "reasoning"))
Enter fullscreen mode Exit fullscreen mode

In a real service, put the routing decision in a small module and log the selected model, latency, status code, and token usage. Do not log prompts that contain customer secrets. A request ID lets you join application metrics with provider responses without storing sensitive content.

Add budget and failure guardrails

Three guardrails are usually enough to make a first router production-friendly:

  1. Set a maximum output token budget per task class. A short extraction should not be allowed to generate a long essay.
  2. Retry transient 429 and 5xx responses with exponential backoff, but cap retries so an outage cannot multiply spend.
  3. Keep a fallback policy. If GLM-5 is unavailable, fail closed for high-risk workflows or route to DeepSeek V4 Flash only when the caller accepts a quality downgrade.

The fallback must be visible to operators. Return the selected model and a fallback_used flag in internal telemetry; otherwise a silent quality change can look like a prompt regression.

Measure cost instead of guessing

At minimum, collect request count, input tokens, output tokens, latency percentiles, error rate, and estimated USD cost by model. The following helper calculates an estimate from usage returned by the SDK:

PRICE_PER_MILLION = {
    "deepseek-v4-flash": (0.206, 0.412),
    "glm-5": (1.55, 4.96),
}


def estimate_usd(model: str, prompt_tokens: int, completion_tokens: int) -> float:
    input_price, output_price = PRICE_PER_MILLION[model]
    return (prompt_tokens * input_price + completion_tokens * output_price) / 1_000_000
Enter fullscreen mode Exit fullscreen mode

Treat this table as a dated snapshot, not a permanent configuration. Refresh it from AIWave pricing before a billing review, and keep the effective date beside the snapshot. If your organization requires approval for pricing changes, make the refresh a reviewed configuration change.

When routing is the wrong abstraction

Do not route solely on a user-visible keyword, and do not send private data to a classifier that does not need it. A single model may be preferable when strict reproducibility, one vendor's safety controls, or a single latency SLO matters more than cost. Likewise, if you do not have enough traffic to measure quality and spend, start with one model and instrument it before adding routing logic.

For teams already using the OpenAI SDK, the migration path is intentionally small: create an AIWave key, change the base URL, select a catalog model, and add the router behind your existing service boundary. The Chat Completions documentation covers request parameters and streaming details.

Practical rollout checklist

  • Verify model IDs and current USD input/output rates on the pricing page.
  • Run a fixed evaluation set through both routes before changing traffic.
  • Start with a small percentage of routine requests and compare quality, latency, and cost.
  • Alert on error rate, fallback rate, and daily spend—not only request count.
  • Keep YOUR_API_KEY_HERE in examples and store real keys in your secret manager.

A cost-aware router is a measurement system first and a model-selection rule second. Once the telemetry is trustworthy, you can add caching, batch processing, or a third model without losing visibility into why a request was routed or what it cost.

Top comments (0)