The inference process in machine learning is the production stage where a trained model takes new inputs and produces predictions.

Takeaways
Machine learning inference is the step where a trained model is applied to new input to produce an output. The time it takes is spent in three places: the forward pass, the inference engine, and the network path to the user.
Machine learning inference is the phase where a trained model receives new, unseen input and produces an output, such as a label, a score, a token, or an embedding. Two artifacts make it happen: the trained weights, which hold everything the model learned, and the inference engine, which runs those weights against each new input.
IBM defines AI inference as a trained model's ability to recognize patterns and draw conclusions from information it hasn't seen before. In practice, that plays out in four steps:
It helps to separate "the model" from "inference." The model is a file: an architecture plus billions (or thousands) of learned numbers. Inference is the act of running that file against real data. You'll also see the process called model inference, ML inferencing, or inference in ML. They all mean the same thing.
Definition: Machine learning inference is the act of running new input through a trained model to get an output. Training is over; the weights do not change; every call is the same computation on different data.
Consider a spam classifier sitting behind an email inbox. Here's what happens when a new message lands:
A large language model (LLM) follows the same pattern with a different output. Instead of a probability, each forward pass returns the next token in a sentence. That small difference has big consequences for speed, covered in the generative AI section below.
An inference engine is the software runtime that loads a model's trained weights and executes the forward pass efficiently on a specific hardware target, like a GPU or CPU. It's the part of the stack that actually does the work every time a request comes in.
Engines exist because training frameworks carry a lot of machinery that inference doesn't need. During training, a framework tracks gradients, stores optimizer state, and builds autograd graphs so it can adjust weights after every batch. None of that is useful once the weights are frozen. PyTorch's torch.inference_mode context manager is a simple example of this idea: it switches off gradient tracking so the model runs forward only.
A dedicated engine goes further. It takes a model exported from a training framework and applies graph optimizations: fusing operators into fewer steps, quantizing weights to smaller number formats, and selecting kernels tuned for the target chip. Then it exposes a call interface your application can hit. ONNX Runtime, NVIDIA TensorRT, vLLM, and llama.cpp are all widely used examples.
These three terms get used interchangeably, but they describe different things:
| Component | What it is | Job at inference time |
|---|---|---|
| Model (e.g., Llama, a fine-tuned BERT) | Learned weights plus architecture | Provides the computation |
| Framework (e.g., PyTorch, TensorFlow) | Training and export toolkit | Exports the model; not used to serve it |
| Inference engine (e.g., ONNX Runtime, TensorRT, vLLM) | Optimized runtime | Loads weights, runs the forward pass, and serves calls |
The mechanical difference is simple. Training runs a forward pass and a backward pass, then updates the weights based on the error. Inference runs the forward pass only, and the weights stay frozen.
The operational difference follows from that. Training is scheduled and batched: you run it once, or on a regular cadence when you retrain. Inference is on demand and often handles one request at a time, because a user is waiting on the other end. Training is judged on throughput. Inference is judged on latency and cost per call.
The cost difference is where the business impact shows up. Training spend is a one-off or periodic bill, closer to a capital cost. Inference spend recurs with every user interaction, closer to an operating cost that scales with usage. That's why a model that's cheap to train can still be expensive to run at volume.
Hardware follows the same split. Training typically runs on large GPU clusters, while inference runs on a GPU, CPU, or specialized accelerator sized to the request.
Prediction is the label people use for a classifier's or regressor's output. Inference is the broader process, and it covers every output type a model can produce. Plenty of inference outputs aren't predictions at all:
Put simply, every prediction is an inference, but not every inference is a prediction.
Here's what happens after the user sends input:
During the forward pass, input tensors are multiplied through each layer's frozen weights in sequence. Activations from one layer become inputs to the next, and no gradients are computed along the way.
In a transformer, the architecture behind most modern LLMs, attention layers compare every token in the input with every other token to work out which ones matter to each other. That mechanism comes from the 2017 paper Attention Is All You Need, and it's why longer inputs cost more compute.
Nearly every optimization an inference engine offers acts on this stage. Fused kernels cut the number of memory trips, quantized weights shrink the data the chip has to read, and batching lets one pass serve several requests at once.
Inference time is the end-to-end, wall-clock time from the moment a request is sent to the moment the response arrives. It splits into two parts:
Most benchmark numbers only measure compute time. Queueing, preprocessing, and the network round trip are also on the clock, and your users feel all of it.
Remember: Inference time is measured from request to response. The forward pass is usually the largest slice, but it is never the whole clock.
"Type" can mean three different things here, and you need to make a choice on each axis: serving mode, deployment location, and hardware target.
Which inference engine fits your model?
Pick the case that matches what you are serving and where it runs.
Stay in PyTorch with torch.inference_mode.
You do not need a separate engine yet. Wrapping your forward pass in torch.inference_mode switches off gradient tracking, so the model runs forward only and skips the autograd graph that training builds.
Move to a dedicated engine once request volume grows. Inference runs on every request, so it is the cost that scales with usage, and a training framework still carries machinery you are not using.
Before: model(batch) inside a normal training script, tracking gradients. After: with torch.inference_mode(): model(batch), forward pass only.
Export to ONNX and run ONNX Runtime.
Classifiers and embedding models return one output per forward pass, so the win comes from graph optimizations rather than token scheduling. ONNX Runtime takes a model exported from your training framework, fuses operators into fewer steps, and runs on CPU or GPU.
This is the spam classifier case. One email in, one forward pass, one probability out.
Before: PyTorch model loaded in a web handler. After: ONNX Runtime session returns 0.97 spam probability, and the app applies its threshold.
Use NVIDIA TensorRT.
TensorRT is built for one hardware target. It fuses operators, quantizes weights to smaller number formats, and selects kernels tuned for the specific NVIDIA chip you deploy on.
The tradeoff is portability. An engine built for one GPU is tuned for that GPU, so plan a build step per hardware target.
Before: generic kernels running full precision weights. After: fused operators and quantized weights on kernels tuned for your exact GPU.
Use vLLM on GPU servers.
LLM inference is autoregressive. The model produces one token per forward pass, so a long reply is many passes in a row, and serving many users means juggling many of those sequences at once. vLLM is designed for that workload.
Measure latency at the user, not at the GPU. A fast engine benchmark does not account for the network path between your server and the person waiting on the reply.
Before: one request at a time through a plain framework, each reply generated token by token. After: vLLM serving many token streams side by side on the same GPU.
Use llama.cpp with quantized weights.
llama.cpp runs LLMs without a datacenter GPU by leaning on quantized weights, which shrink the model so it fits in local memory. That makes it the practical choice for local and on-device inference.
Expect fewer tokens per second than a GPU server. Every token is still a full forward pass, so long replies take noticeably longer on modest hardware.
Before: a full precision model too large to load on a laptop. After: a quantized copy running locally through llama.cpp.
Serving mode shapes everything downstream, and it matters more than which vendor you pick. There are three options:
Where the engine runs determines how far data has to travel:
GPUs are the default for deep learning inference because they run thousands of operations in parallel. TPUs are Google's custom accelerators, built for the same matrix math. CPUs work well for small models and batch jobs where latency isn't critical. Newer LPU-style chips target one job specifically: LLM token generation.
Deep learning and generative AI use the same basic mechanism covered above, but model size and output format change where the bottlenecks sit.
Deep learning inference is the general case: a forward pass through many stacked layers. The practical consequence is about memory, not math. A model with billions of parameters has to read its weights from memory on every pass, so memory bandwidth and batch size govern speed more than raw compute power does. That's why accelerator choice and quantization have such a large effect on deep learning inference.
Generative AI inference is autoregressive. The model produces one token per forward pass, then feeds that token back in to produce the next one. A 200-token reply means 200 forward passes, in order. Here's the loop:
Two metrics describe this loop. Time to first token measures how long a user waits before anything appears. Tokens per second measures how fast the rest of the reply arrives. Streaming exists because of this loop: instead of waiting for all 200 passes, users see words as they're generated.
Those metrics only tell part of the story, though.
“
"We often obsess over LLM inference speeds, but in Voice AI, the network is often the silent killer."
In a voice or messaging product, a model with excellent tokens per second can still feel sluggish if the request crosses several networks to reach it.
Every application uses the same mechanism: frozen weights, a forward pass, and an output. What differs is how latency-sensitive the surrounding product is.
A language-learning flashcard app shows how this works in practice: text-to-speech (TTS) speaks a phrase, the learner repeats it, speech-to-text (STT) transcribes the audio, and inference scores the transcript against the target phrase. That's three AI steps inside one live phone call, and every one of them sits on the critical path.
The example below is a trimmed version of the Telnyx language-learning flashcards app. A learner dials one of the Telnyx phone numbers assigned to the app, hears a phrase in Spanish, repeats it, and gets a score with one tip for improvement.
Before you run it, you'll need:
TELNYX_API_KEY environment variableHow the flow works: your server responds to call events in order.
call.answered), speak_phrase() reads the target phrase to the learner.call.speak.ended), start_listening() begins transcribing the learner's reply.call.transcription), score_attempt() sends the transcript and the target phrase to the model.speak_phrase(), then moves on to the next card.import os import requests TELNYX_API = "https://api.telnyx.com/v2" HEADERS = {"Authorization": f"Bearer {os.environ['TELNYX_API_KEY']}"} def speak_phrase(phrase, voice, language_boost="Spanish"): # TTS: render the target phrase as audio (the app plays it to the learner) response = requests.post( f"{TELNYX_API}/text-to-speech/speech", headers=HEADERS, json={"text": phrase, "voice": voice, "output_type": "binary_output"}, timeout=60, ) response.raise_for_status() return response.content def transcribe_attempt(audio_bytes, filename="audio.webm"): # STT: transcribe the learner's recorded reply response = requests.post( f"{TELNYX_API}/ai/audio/transcriptions", headers=HEADERS, files={"file": (filename, audio_bytes, "application/octet-stream")}, data={"model": "openai/whisper-large-v3-turbo"}, timeout=180, ) response.raise_for_status() return response.json()["text"] def score_attempt(target, transcript): # Inference: compare the transcript with the target phrase response = requests.post( f"{TELNYX_API}/ai/chat/completions", headers=HEADERS, json={ "model": "moonshotai/Kimi-K2.6", "messages": [ { "role": "system", "content": "You are a pronunciation coach. Score the attempt from 1 to 10 and give one tip.", }, {"role": "user", "content": f"Target: {target}\nLearner said: {transcript}"}, ], }, timeout=60, ) response.raise_for_status() return response.json()["choices"][0]["message"]["content"]
The first call plays the phrase, the second transcribes the learner's answer, and the third is the inference call: it sends the target and transcript to an open-source model and gets back a score with a tip. All three run on one platform, inside one phone call.
Classic supervised uses follow the same mechanism with a different place in the request path:
In these cases, the inference call is often a small share of the total request path. In voice, it sits directly on the critical path of a live conversation, and that changes how you have to think about latency.
Once a model serves real traffic, the question isn't how fast it runs on a benchmark. It's how long the user waits.
An inference call is an HTTP request to an endpoint. It names a model, carries an input payload and parameters like maximum tokens, and returns the model's output in the response.
The multi-model inference switcher example below shows a production pattern. The model name isn't hardcoded. It's read from a KV feature flag at request time:
async function chat(env, messages) { const model = (await env.FLAGS.get("inference_model")) ?? "moonshotai/Kimi-K2.6"; const res = await fetch("https://api.telnyx.com/v2/ai/chat/completions", { method: "POST", headers: { Authorization: `Bearer ${env.TELNYX_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ model, messages, max_tokens: 256 }), signal: AbortSignal.timeout(30000), }); if (!res.ok) { throw new Error(`Inference request failed: ${res.status}`); } const data = await res.json(); return { model, reply: data.choices[0].message.content }; }
Swapping models becomes a config change, not a deploy. The engine and the model are decoupled from your application, so you can test, compare, and roll back models without touching the service that calls them.
Production inference latency falls into three buckets:
Only the first bucket shows up in most benchmark results. If your product feels slow despite strong tokens-per-second numbers, measure the third bucket first. A voice agent built with Telnyx Voice AI shows why: the audio, the transcription, the model, and the synthesized reply all have to move between systems, and every hop between vendors adds time the benchmark never saw.
Telnyx Inference serves open-source models through an OpenAI-compatible API, running on Telnyx-owned GPUs. Those GPUs sit on the same private network that carries Telnyx voice and messaging traffic, so the network leg of a voice or SMS inference call doesn't cross the public internet to reach the model.
Because the API is OpenAI-compatible, existing client code usually needs only a new base URL and model name. You can browse the available models in the developer docs, and teams already running voice agents can connect Telnyx Voice AI Assistants to any OpenAI-compatible LLM. For background on why we built it this way, read how Telnyx started building its AI Inference tools.
“
"Most 'end-to-end Voice AI' claims fall apart when you measure what actually matters: the end customer experience in real time. Turn latency, jitter, interruption handling. Not benchmarks on a slide, but behavior on a live call. That only happens when you control the full stack. Network, media plane, orchestration, and inference paths, not a fragile chain of third-party services over the public internet. This is the bar Voice AI should be held to."
Frequently asked questions
Know where your latency lives. Then fix it.
You can now look at any slow inference call and ask the right question: is the delay in the forward pass, the engine, or the network? For voice and messaging AI, the network is often the answer. Run inference where the network isn't the bottleneck, on GPUs that share a network with your calls and messages.
Try Telnyx InferenceRelated articles
How to scan AGENTS.md and CLAUDE.md for indirect prompt injection

vLLM inference: how it works and when to stop self-hosting

AI DLP Test: Six Data Types, Six Blocks, $0 Charged

Finding the Right Indian Text-to-Speech Voice for Your Application
%20(1).png?width=96&format=webp)
Model serving: how to run open-weight LLMs close to your users

The 11 best conversational AI platforms in 2026