Datadog’s free guide shows how to connect AI spend, infrastructure, and model performance into a single view, so you can correlate cost increases to the architecture changes that caused them before they show up on your cloud bill.

Break down AI costs by token, model, provider, and team

Get alerted the instant inference volume spikes or API spend exceeds budget

Correlate cost increases directly to architecture changes so root-cause analysis takes minutes

Get the guide :https://go.bytebytego.com/Datadog_090126

A model with 70 billion parameters can take up to 140 GB of space. A good graphics card has 24 GB. A very good one might have 48 GB.

As you can see, the gap is quite significant. Disk space is pretty cheap, but fast memory is scarce and costly. Moreover, the models have grown roughly 100-fold in a few years, while consumer graphics memory has roughly doubled. It’s not just a matter of tightening things up to make them fit.

The simplest option is to purchase the hardware that is capable of running the model. But it is costly, and doesn’t work well with consumer hardware.

The other option is to shrink the model. But we don’t want to do so at the expense of the model’s intelligence. This is where certain techniques can help us make the model smaller in principle without a dip in the quality of its output.

What makes a language model intelligent?

Three techniques to shrink the model

How to shrink the model by packing fewer details?

How to shrink the model by trimming unused pathways?

How to shrink the model by mimicking behaviour?

Does shrinking damage the model’s intelligence?

Disclaimer: This post is based on publicly shared details from various sources. References at the end. Please comment if you notice any inaccuracies.

Large language models like ChatGPT are quite different from normal software programs. They don’t depend on typical if-else statements to decide what should happen next.

A large language model is essentially a very big pile of numbers called parameters or weights. These weights are the foundation of a language model’s intelligence. For reference, a model with 70 billion parameters means 70 billion numbers or weights. Each weight is normally stored in 16 bits, which is two bytes. Two bytes multiplied by 70 billion comes to 140 GB, which is basically considered the size of the model.

The weights are arranged into matrices. A single weight matrix is a grid, often something like 4096 by 4096. This comes to roughly 16.7 million numbers in a matrix. A 70 billion parameter model has hundreds of these matrices stacked across 80 or so layers.

Of course, weights in themselves aren’t the whole story behind a model’s capability. Multiple components work together to make a model intelligent. For example, the model needs an architecture like the Transformer to route data and perform attention. It also needs a context window that holds the prompt and everything generated during the conversation.

However, the architecture is made up of a few hundred lines of code. The prompt may be a few kilobytes. In contrast, the weights form the bulk of the language model. Without the proper weights, a language model cannot work as intended. The weights perform a bunch of tasks:

They store patterns such as grammar, facts, and reasoning shortcuts.

Once the training is finished, the weights freeze into an immutable network of numerical values.

The weights decide how strongly one simulated neuron influences the next.

Running the model means pushing the input through these weight matrices until the next word comes out of the other end.

One thing to keep in mind over here is that no single weight means anything on its own. If you opened a model file and looked at weight number N, you might see something like 0.0293. On either side of this number may be other numbers such as -0.0117, 0.004, -0.0862. On their own, each of these numbers hardly makes sense. The ability of the model is hidden in the relationships between the various weights. Think of it like a photograph where every pixel comes together to show something recognizable. Even if we modify every pixel’s brightness slightly, we can still make out the things in the picture. This is because the information isn’t sitting in one single place.

Following on from all this information, it is quite easy to figure out that to shrink a model, we’ve to somehow deal with these weights. And this is exactly where the techniques come into the picture. However, a couple of points can help us make better sense of the techniques to shrink a model:

Firstly, not all weights matter equally. Most of the weight values are close to zero and barely impact the final output. However, a small handful are large and produce a bigger impact.

Second, we can only judge a model based on its behaviour, not its internals.

Shipping agents to production is the easy part. Keeping them reliable, governable, and improving over time is where most enterprise AI programs stall.

How do top teams do it? They use an Agentic Operating Model (AOM), a step-by-step framework for aligning people, process, and technology so enterprise agents improve as they scale.

In LangChain’s latest guide, you’ll learn:

Why AI agents don’t break like traditional software

The engineering stack that covers the entire agent lifecycle

Shifting from “build and deploy” to “operate and continuously improve”

Learn more :https://go.bytebytego.com/LangChain_090126

The techniques to shrink a model revolve around using fewer bits to store a weight or using fewer weights. There are three main techniques:

Storing Each Weight in Less Detail (Quantization): In this approach, we keep all the weights, but describe each one in a less precise manner. For example, two bytes become half a byte.

Removing Irrelevant Weights (Pruning): This approach involves finding the weights that contribute nothing and deleting them.

Building a Smaller Model to Mimic the Larger One (Knowledge Distillation): In this approach, we don’t touch the original model, but train a new, smaller model to behave in a similar way.

Going back to our photograph example, we can think of quantization as taking a picture with a cheaper camera that has a slightly lower resolution. Pruning is more like cutting away the blank edges of the photograph that might not be adding any value to the picture. Distillation can be thought of as paying a skilled painter to reproduce the picture at a quarter of the size.

The great part about all these techniques is that they can be stacked. For example, a model can be distilled by the lab that made it. It can be pruned by a research team. Lastly, it can be quantized by the user before it is loaded on a specific machine. In other words, stacking can make it possible to run a high-end large language model on normal consumer hardware.

Let us now look at each of these techniques in more detail.

The first technique to shrink a model is to pack fewer details for every weight. This technique is known as quantization.

Let’s say a particular weight might be stored as 0.02934517. This takes a lot of space, but in a 70 billion parameter model, it just happens to be one single weight. Whether it is stored as 0.02934517 or 0.029 makes almost no difference to the model’s output. In other words, a lot of storage is spent on precision that might not even be important.

Quantization is a technique that takes away this precision.

The first bit of quantization happens even before the model is shipped. During training, model weights are normally stored as 32-bit (4 bytes) floating-point numbers. This is also known as the FP32 format. Since training involves making millions of tiny adjustments to each weight, high precision is needed. But when the model is distributed, the precision is usually brought down to 16-bit float format, which is also known as FP16 or BF16.

However, we can bring the precision down even further. To understand how, we need to first be clear about how a float value is actually built.

A floating-point number splits the bits into three parts: a sign, an exponent, and a mantissa. FP32 gives 1 bit to the sign, 8 bits to the exponent, and 23 bits to the mantissa. BF16, on the other hand, keeps all exponent bits and cuts the mantissa down to seven. This is basically the same range as FP32, but with less detail. For clarity, BF16 is slightly different from FP16, which gives the exponent only 5 bits and keeps more bits for the mantissa. BF16 has largely replaced FP16 in practice.

An integer has an even greater difference. An 8-bit integer is a whole number from -128 to 127. A 4-bit integer is a whole number from -8 to 7. There is no exponent and no scale. In other words, converting a float into an integer not only causes a loss of precision, but also removes each weight’s scale.

Let us now look at the complete process of quantization:

In the first step, we find out the minimum and maximum values of a data set and divide the total span into a fixed number of steps.

To be clear, “the data set” is not the entire model. It’s just a small group of neighbouring weights. We can call it a block, and it should ideally be pretty small.

For example, consider these eight weights: 0.021, -0.017, 0.004, -0.048, 0.011, 0.033, -0.006, 0.070. They span from -0.048 to 0.070. The largest value in either direction is 0.070. With 4 bits as our target precision, we can write whole numbers from -7 to 7. In other words, seven steps in each direction. Therefore, one step can be calculated as 0.070/7, which comes to 0.010.

Instead of keeping a long decimal, each original number is rounded to the closest available step. To do so, we divide each weight by the step size and round it to the nearest whole number.

The table below shows the new weights:

As you can see in the table, the right-hand column values are the ones that go into the model weights file eventually. Every entry here is a whole number between -7 and 7.

The original weights were floating-point numbers. Since a float carries its own scale, rounding off to engineers removes the precision as well as the scale of every weight. This scale has to be stored somewhere.

We need to keep track of the scale factor so that the compressed numbers can roughly reconstruct the original values when the model needs to read them.

In our example, the scale factor is the step size (0.010). It is stored once for the entire block. To recover a weight, we can multiply the stored integer by the scale factor.