Skip to content

AI & Machine Learning

PyTorch

The deep-learning framework that won research and now trains almost every open model — used by engineers who know it is a tool for building models, not a substitute for one.

Overview

PyTorch is a deep-learning framework: at its core, a tensor library with GPU acceleration, an automatic differentiation engine, and the building blocks for defining and training neural networks. A tensor is a multi-dimensional array — the currency of every model — and PyTorch moves those tensors onto a CUDA-capable GPU and runs the heavy linear algebra there, which is what makes training a large network in hours rather than weeks possible at all. Around that core sits autograd, which records the operations you perform and computes gradients automatically, so you write the forward pass of a model and get backpropagation for free.

What set PyTorch apart, and won it the research community, is that it is define-by-run. The computation graph is built dynamically as your Python code executes, rather than compiled ahead of time into a static graph you then feed data through. In practice that means a model is just Python: you can use ordinary control flow, print a tensor mid-forward-pass, set a breakpoint, and inspect exactly what is happening. Debugging a model feels like debugging any other program, which is a genuinely different experience from the earlier generation of frameworks. That Pythonic, immediate feel is why the field moved, and why nearly every new architecture now appears in PyTorch first.

We use PyTorch where a problem genuinely calls for a trained model — a classifier, a fine-tuned language model, a computer-vision system, an embedding model for search — rather than something a rule or a database query would solve more cheaply. That distinction is the whole job. PyTorch is the tool we build models with; it does not decide whether you need one, and it does not run itself in production. We are direct about both the capability and the surrounding engineering — data pipelines, evaluation, serving, monitoring — that turns a promising notebook into a system you can depend on.

Best for — Teams that genuinely need a custom or fine-tuned model — an LLM adapted to their domain, a vision or NLP system, a bespoke architecture — and want senior engineers who can both train it and stand up the MLOps to run it.

Why teams choose PyTorch

  • The framework the field standardised on

    New architectures, open models and research appear in PyTorch first. Building in it means you inherit that momentum — reference implementations, pretrained weights, and a community that has already hit and solved most problems you will face.

  • Models you can actually debug

    Because a PyTorch model is just executing Python, we can step through a forward pass, inspect intermediate tensors, and find why a model misbehaves. That shortens the training-and-debugging loop that dominates the cost of any serious ML project.

  • A route to owning your own model

    Fine-tuning an open model in PyTorch gives you a system that runs on your infrastructure, on your data, without a per-token bill to a third party. For the right workload that is cheaper, more private, and more controllable than an external API.

Why businesses choose PyTorch

  • You have a problem that genuinely warrants a trained model, and you want it built by engineers who will also tell you when it does not.
  • You want to fine-tune or self-host an open model rather than depend entirely on a closed API, and you value the control, privacy and unit economics that brings.
  • You need the flexibility to build something the standard toolkits do not cover — a custom architecture, loss, or training regime — and want it done in the framework the whole field builds in.
  • You want the model and the engineering around it from one senior team, so the thing that works in a notebook actually survives contact with production traffic.

What we build with PyTorch

The capabilities this technology is genuinely strong at — and what we most often build with it.

  • Tensors and CUDA acceleration

    The GPU-accelerated tensor library is the foundation: everything is a tensor moved onto CUDA hardware where the linear algebra runs in parallel. We are deliberate about device placement, mixed-precision training, and memory — the difference between a job that fits on the GPU you have and one that constantly runs out.

  • Autograd and define-by-run graphs

    Autograd records operations as they run and differentiates them automatically, so we write the forward pass and get correct gradients back. The dynamic graph means models are ordinary Python — inspectable, breakpoint-able, and free to use real control flow — which is what makes hard training bugs tractable.

  • The Hugging Face and torchvision ecosystem

    We rarely start from a blank model. Hugging Face Transformers — built on PyTorch — gives us pretrained language models to fine-tune, and torchvision gives vision backbones and datasets. Standing on these is the difference between weeks of work and months, and we choose which to build on with care.

  • PyTorch Lightning for training structure

    For non-trivial training we use Lightning to separate the research code from the engineering boilerplate — distributed training, mixed precision, checkpointing, logging — so the training loop stays readable and reproducible rather than a sprawl of manual device and gradient handling.

  • torch.compile for speed

    torch.compile traces and optimises a model into fused, faster kernels without abandoning the Pythonic authoring model — often a material speed-up on both training and inference for a one-line change. We apply it where it measurably helps and verify it has not changed the numerics.

  • Production export: TorchServe, ONNX, TorchScript

    To leave the notebook, a model is packaged for serving — TorchServe for a PyTorch-native endpoint, ONNX export for a portable, runtime-agnostic graph, or TorchScript to serialise a model away from Python. We pick the path that fits your latency, hardware and operational constraints rather than a default.

Use cases

  • Fine-tuning a domain LLM

    Adapting an open language model to your terminology, documents and tasks — often with parameter-efficient methods like LoRA — to get a private, self-hosted model that outperforms a generic API on your specific work.

  • Computer vision systems

    Image and document classification, object detection, and quality inspection built on torchvision backbones and fine-tuned on your data — the workloads where a trained vision model earns its keep over hand-written rules.

  • Semantic search and embeddings

    Training or fine-tuning embedding models that turn text or images into vectors, so search and retrieval match on meaning rather than keywords — the backbone of retrieval-augmented systems and recommendation.

  • Custom models on structured data

    Forecasting, anomaly detection and classification where the problem is genuinely non-linear and a bespoke network, built and trained in PyTorch, beats the off-the-shelf option — provided the data justifies it.

When PyTorch is the right choice

  • Right when the task genuinely needs a trained model — fine-tuning a language model on your domain, image or document classification, semantic search embeddings, forecasting, anomaly detection — and no rule, query or off-the-shelf API answers it well enough.
  • Right when you want to fine-tune or adapt an open model: nearly all modern LLMs and open-weight models are trained and released in PyTorch, and the Hugging Face ecosystem that hosts them is built on it, so this is the path of least resistance for owning your own model.
  • Right when you need research-grade flexibility — a custom architecture, a bespoke loss, a training loop that does something unusual — because define-by-run lets you write and debug that as ordinary Python rather than fighting a static graph.
  • Wrong for a problem a simpler method solves. If logistic regression, gradient-boosted trees, or a plain SQL query gets you there, deep learning adds cost, latency and opacity for no gain. We will say so before you spend on GPUs.
  • Wrong as a shortcut past having the data and the expertise. PyTorch is a framework for people who can build models; it will not conjure one from insufficient, unlabelled or biased data, and pointing it at a vague problem produces a confident, wrong model rather than an answer.

PyTorch: pros and cons

Strengths

  • Define-by-run dynamic graphs make models natural to write and, crucially, to debug — the single biggest reason the research community adopted it and stayed.
  • It is the de facto standard for training and fine-tuning modern models: the ecosystem — torchvision, Hugging Face Transformers, PyTorch Lightning — is deep, current and built around it.
  • First-class GPU/CUDA acceleration and, with torch.compile, ahead-of-time-style speed-ups without giving up the Pythonic authoring model.
  • Flexible enough for cutting-edge research and mature enough for production, so a prototype and the system it becomes can share one framework rather than a risky rewrite.

Trade-offs

  • Production and deployment tooling has historically been less turnkey than TensorFlow’s serving story — it is improving fast (TorchServe, ONNX, torch.compile), but standing up robust serving is still real work, not a checkbox.
  • Mobile and edge deployment is weaker than TensorFlow Lite. If a model must run on-device on a phone or embedded hardware, TF Lite is usually the more mature path, and we will tell you so.
  • It demands genuine ML expertise. PyTorch is a tool for building and fine-tuning models, not a substitute for knowing how — a team without ML depth will produce models that look plausible and fail quietly.
  • A trained model in a notebook is not a product. Running PyTorch in production needs real MLOps — data pipelines, versioning, evaluation, monitoring for drift — that the framework itself does not provide and that many projects underestimate.

Architecture

A PyTorch project is more architecture than model. The model definition — the nn.Module and its layers — is usually the smallest and most stable part. Around it we build the data pipeline that feeds it (Datasets and DataLoaders, augmentation, batching, and the often-underestimated work of cleaning and labelling), the training loop or Lightning module that orchestrates optimisation, and the evaluation harness that tells us honestly whether the thing is any good. We settle these boundaries early, because a tangled training script is where reproducibility and trust go to die.

The other decision we make up front is where the model runs. Training happens on GPU hardware — your cloud, a managed platform, or on-premise — and inference has its own home, which may be entirely different: a served endpoint, a batch job, or an exported graph embedded in another service. We design the boundary between the training world and the serving world deliberately, exporting via TorchServe, ONNX or TorchScript, so the model that ships is a versioned, tested artefact and not a copy of a researcher’s notebook.

Performance

Performance in PyTorch splits into two questions: how fast you train, and how fast and cheap you serve. On training, the wins come from keeping the GPU fed and busy — an efficient data pipeline that does not starve the device, mixed-precision to roughly halve memory and speed up the maths, gradient accumulation to fit larger effective batches, and distributed training across multiple GPUs when scale demands it. torch.compile often adds a further speed-up for a one-line change. We profile before optimising, because the bottleneck is frequently the data loader, not the model.

On inference, the priorities invert to latency, throughput and cost per prediction. Here we reach for quantisation to shrink a model, batching to amortise overhead, ONNX or TorchScript export to a leaner runtime, and honest measurement of whether a smaller model meets the requirement rather than the largest one that fits. Running a large model in production is a recurring GPU bill, and the cheapest inference is often a distilled or quantised model that is good enough — a trade-off we make explicit rather than defaulting to the biggest network.

Security

The security surface of a machine-learning system is broader than the code. Models are trained on data, and that data is often the most sensitive thing an organisation owns — so we treat training data as a controlled asset, keep it inside your boundary, and are careful that a model does not memorise and leak the very records it learned from. For teams choosing to fine-tune and self-host rather than send data to an external API, keeping sensitive data in-house is frequently the entire point, and we architect for that.

There are ML-specific hazards too. Model weights loaded from an untrusted source can carry executable code — Python’s pickle format is a known vector — so we load only from trusted origins and prefer safe serialisation formats. Beyond that, the ordinary discipline applies: serving endpoints are authenticated and rate-limited, inputs are validated, dependencies are kept current given the size of the ML stack, and we think about adversarial inputs and prompt injection where a model is exposed to untrusted users.

Scalability

Scaling a PyTorch system means two different things at two different times. Training scales with data and model size: from a single GPU, to several via distributed data-parallel training, to sharded approaches when a model no longer fits on one device. We choose the smallest rung of that ladder that meets the need, because multi-GPU training adds real complexity and cost that a great many projects simply do not require.

Serving scales with traffic, and that is a more ordinary engineering problem: stateless inference services behind a load balancer, containerised and orchestrated so instances scale with demand, with batching and autoscaling tuned to keep expensive GPU capacity busy without over-provisioning it. Because inference is often the larger long-run cost, we design serving to scale down as readily as up — the goal is capacity that tracks real demand, not a fleet of idle GPUs.

PyTorch integrations & ecosystem

The technologies we most often pair with it — each links to how we work with it.

How we work

We start before the model, with the problem and the data. The first question is always whether a trained model is the right tool at all, and if it is, whether the data to train it honestly exists. From there we set up evaluation early — the metric and the held-out test that will tell us whether a model is genuinely good — because a project without an honest measure of success will happily convince itself it has succeeded. Only then do we train, iterating from a simple baseline upward rather than reaching for the largest model first.

The engineers who train the model are the ones who deploy and run it. That is what we mean by operating what we build: the person who chose the architecture also lives with its latency, its GPU bill, and its behaviour on real traffic, so we favour models we can actually serve and maintain over impressive numbers on a slide. You get a model with an honest evaluation behind it, the MLOps to run it, and straight answers about what it can and cannot do.

The service behind it

Delivered throughAI Development

What we build with PyTorch

The disciplines this technology most often shows up in — from a first build to taking over and stabilising an existing one.

How we deliver

  1. 01

    Discover

    We map the system, the constraints and the business it serves — including the parts nobody documented.

    Architecture brief

  2. 02

    Architect

    Decisions get made, written down and defended before a line of production code exists.

    Decision records

  3. 03

    Build

    Short cycles against working software. You see progress in the product, not in a status deck.

    Shipping increments

  4. 04

    Operate

    Monitoring, incident response and iteration. The system is alive, so the engagement is too.

    Runbooks & SLOs

Industries we use PyTorch in

Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.

Also in AI & Machine Learning

Why teams choose us for PyTorch

  • Senior ML engineers, not notebook demos

    The people building your model have trained, deployed and operated models before. They know the difference between a metric that looks good and one that holds up on real data, and there are no juniors experimenting on your problem.

  • We operate what we build

    We run the models we ship, so we design for the production reality — latency, GPU cost, drift over time — from the start, not as an afterthought once the notebook works. That shapes which model we build in the first place.

  • Honest about when not to use deep learning

    If a simpler method, an off-the-shelf API, or a plain query would serve you better than a trained model, we will tell you before you spend on GPUs. We would rather lose the work than build you a model you did not need.

  • The model and the engineering from one team

    Training and MLOps are not separate jobs here. The same team that fine-tunes the model builds the pipeline, evaluation and serving around it, so nothing is lost in the handoff that usually kills ML projects.

Typical timeline

  1. 01

    Data and feasibility

    One to two weeks assessing the data, defining the evaluation metric, and confirming a trained model is the right approach before any training spend — the cheapest place to catch a bad idea.

  2. 02

    Baseline model

    A simple, honestly-evaluated model early, to establish what is achievable and give a real number to beat, rather than months of work before anyone knows if it can work at all.

  3. 03

    Iteration and tuning

    Improving the model against the held-out set — architecture, fine-tuning, data quality — in short cycles, stopping when it is good enough for the requirement rather than chasing diminishing returns.

  4. 04

    Serving and handover

    Packaging the model for production via TorchServe, ONNX or TorchScript, standing up monitoring for drift and performance, and documenting it so your team can retrain and operate it.

How pricing works

  • Fixed-scope model builds for a well-defined problem — a classifier, a fine-tuned model, a vision system — quoted once we have seen the data and agreed how success is measured.
  • A discovery and feasibility engagement for teams unsure whether deep learning is the right tool: a short, honest assessment of the data, the approach, and whether to proceed at all.
  • Monthly senior engagement for ongoing ML work, where models need retraining, evaluation and iteration, and you want continuity rather than a single deliverable.
  • Focused work on serving and MLOps for teams with a working model but no production path — packaging, deployment, and monitoring priced by the assessment.

Hire PyTorch engineers

Need PyTorch capacity on your own team? We embed named senior engineers into your existing team — reporting to your leads, working in your rituals — so you add capacity without a hiring cycle.

Hire PyTorch engineers

Common questions

PyTorch or TensorFlow — which should we use?

For most new work today, PyTorch. It won the research community and much of production, nearly every modern LLM and open model is trained in it, and its define-by-run model makes development and debugging genuinely easier. TensorFlow retains real strengths in some established pipelines and, via TensorFlow Lite, in mobile and edge deployment — if your model must run on-device on a phone or embedded hardware, TF is often the more mature path. We choose on your constraints, not fashion.

Can we fine-tune our own version of an open model like Llama?

Yes, and PyTorch is the natural place to do it — the open-weight models and the Hugging Face ecosystem that hosts them are built on it. With parameter-efficient methods like LoRA, fine-tuning is far cheaper than training from scratch, and the result is a private, self-hosted model adapted to your domain that runs on your infrastructure without a per-token bill. Whether it beats simply using a hosted API depends on your data, volume and privacy needs, which is a conversation we have honestly up front.

Do we even need deep learning, or would something simpler work?

Often something simpler works, and we will say so. Deep learning earns its cost — GPUs, data, opacity — only when the problem is genuinely complex and the data supports it. For plenty of tasks, gradient-boosted trees, a classical model, or a well-written query is faster to build, cheaper to run, and easier to trust. Our first job is to work out which side of that line your problem falls on before you commit to the expensive path.

What does it actually take to run a PyTorch model in production?

More than the model. A trained model in a notebook is a long way from a dependable system — production needs a data pipeline to feed it, versioning so you know exactly what is deployed, a serving path (TorchServe, ONNX or TorchScript) with sensible latency and cost, and monitoring to catch drift when the world changes and the model quietly stops being right. This MLOps work is where many ML projects stall, and we treat it as part of the build rather than an optional extra.

How do we know the model is any good, and will stay good?

We define the evaluation before we train — the metric and a held-out test set the model never sees during training — so success is measured honestly rather than by how confident the model sounds. In production we monitor for drift: real-world data shifts over time, and a model that was accurate at launch degrades silently unless someone is watching. We build that monitoring in and plan for retraining, because a model is a system to maintain, not a deliverable to hand over and forget.

Building on PyTorch?

A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.

Two fields required. We reply to real enquiries — no list, no sequence.