#4966: Local vs Cloud: Running Hugging Face Models

Hugging Face's compatibility tracker, cache management, and the real difference between Inference Endpoints and the direct API.

Featuring
Listen
0:00
0:00
Episode Details
Episode ID
MWP-5145
Published
Duration
26:44
Audio
Direct link
Pipeline
V5.1
TTS Engine
chatterbox-regular
Script Writing Agent
deepseek-v4-pro

AI-Generated Content: This podcast is created using AI personas. Please verify any important information independently.

Hugging Face solved discovery before it solved delivery. With over half a million models on the Hub, finding one is easy — but running it is a decision tree nobody walks you through. This episode covers the two main pathways: local inference and cloud deployment, focusing on mechanics rather than marketing.

On the local side, the compatibility tracker is often misunderstood as a simple VRAM check. In reality, it calculates TOPS (trillion operations per second) and considers memory bandwidth, not just available memory. The tracker gives a compatibility score with estimated tokens-per-second, but it doesn't automatically account for quantization — that math is left to the user. Once a model fits, downloading weights involves Hugging Face's content-addressable cache, which uses symlink-based deduplication so shared base layers across fine-tuned variants are stored only once. The cache structure stores blobs by SHA-256 hash under ~/.cache/huggingface/hub, with refs mapping branches to commits. Managing cache bloat requires tools like scan_cache() and clean_cache(), which safely remove orphaned revisions.

For cloud inference, there are two distinct routes that look identical through the Python InferenceClient but route completely differently underneath. Inference Endpoints act as a gateway — Hugging Face routes requests to a backing provider like AWS or Azure, adding an extra hop but supporting any model on the Hub. The direct hosted Inference API runs models on Hugging Face's own infrastructure, reducing latency but limiting users to a curated selection of pre-deployed models. Both use the same API surface, but the cost structure, latency, and model availability differ significantly.

Downloads

Episode Audio

Download the full episode as an MP3 file

Download MP3
Transcript (TXT)

Plain text transcript file

Transcript (PDF)

Formatted PDF with styling

#4966: Local vs Cloud: Running Hugging Face Models

Herman
The thing about Hugging Face is, it solved discovery before it solved delivery. You can find a model for anything — text-to-SQL, protein folding, detecting whether a photo contains a hot dog — but the moment you click that model card, you're staring at a decision tree that nobody really walks you through.
Corn
Daniel's been poking at the two main pathways for actually running models from the Hub — local inference versus cloud — and he wants to get into the mechanics, not the marketing. On the local side, there's the compatibility tracker that checks your hardware, calculates TOPS, and tells you whether a model will run. If it will, then what? Downloading the weights, where they end up on your disk, how the cache is structured, and how you clean it up when you've accumulated forty-seven variants of Llama. On the cloud side, he's asking about two distinct routes — Hugging Face as a gateway that routes your request to a backing provider, versus calling the API directly where Hugging Face hosts the model themselves. Both use the same Python package, but the routing underneath is completely different. And he specifically doesn't want us to get bogged down in subscription tiers.
Herman
Smart. The tiers change every six months anyway.
Corn
So where do we start?
Herman
Let's start where most people start — staring at a model card wondering if your laptop can even run it.
Corn
The moment of truth. You've found the perfect model, the benchmark numbers look great, and then you scroll down and see "requirements: unspecified."
Herman
And that's exactly what the compatibility tracker is supposed to solve. Hugging Face has over half a million models now, and the model card is really just the storefront. It tells you what the model does, what it was trained on, maybe some evaluation scores. But the actual question — "can my machine run this?" — that's a hardware compatibility problem, and it's a lot more nuanced than just checking how much VRAM you have.
Corn
Most people think it's a VRAM check. You've got twelve gigs, the model needs fourteen, answer's no. Done.
Herman
And that's the first misconception worth busting. The compatibility tracker doesn't just look at VRAM. It's calculating TOPS — trillion operations per second — which is a measure of your hardware's raw compute throughput. The model has a TOPS requirement based on its architecture, parameter count, and expected precision. Your GPU has a TOPS rating. The tracker maps those against each other. But it's also looking at memory bandwidth — how fast can you shuttle those weights between VRAM and the compute units? A model might technically fit in your twelve gigs, but if your memory bandwidth is too low, inference will be painfully slow.
Corn
So it's not a binary "will it run." It's more like "will it run at a speed that doesn't make you want to throw your computer out a window."
Herman
And the tracker surfaces that. You input your hardware specs — GPU model, VRAM, system RAM, CPU if you're doing CPU inference — and it gives you a compatibility score, not just a yes or no. It'll say something like "this model will run with 4-bit quantization at approximately fifteen tokens per second on your RTX 3060." That's actionable.
Corn
And if the answer is yes — or yes with caveats — the next step is actually getting the weights onto your machine.
Herman
Right. There are two main ways to download weights from the Hub programmatically, both through the huggingface_hub Python library. The first is from_pretrained() — you call it in your code, point it at a model repo, and it handles the download automatically. It's lazy, meaning it only pulls down what it needs when it needs it. The second is snapshot_download(), which downloads the entire model snapshot at a specific revision.
Corn
And where do those files actually land?
Herman
This trips people up because it's not obvious. The default cache directory on Linux and macOS is ~/.cache/huggingface/hub. On Windows, it's %USERPROFILE%\.cache\huggingface\hub. And the structure inside is clever. Each model gets a folder named by its repo ID, with slashes replaced by double dashes. So meta-llama/Llama-2-7b-hf becomes models---llama--Llama-2-7b-hf.
Corn
That's... a choice.
Herman
It is, but it keeps things flat and predictable. Inside that folder, you've got two things. There's a blobs directory — stored at the hub level, not per-model — and a refs directory. The blobs are the actual file contents, stored by their SHA-256 hash. The refs folder maps branch names and tags to specific commits, which are essentially pointers to sets of blobs.
Corn
So it's content-addressable storage. You don't store the same file twice even if two different models share it.
Herman
And that's huge. If you've got five different fine-tuned variants of Llama 2, they all share the same base layers. Those blobs get downloaded once. The refs just point to them from different model folders. This is symlink-based deduplication — it's not copying files, it's creating references.
Corn
Which means your disk usage is a lot lower than the sum of all the model cards would suggest.
Herman
In theory. In practice, people end up with bloated caches anyway because they never clean up old revisions. Every time you pull a model at a different commit, you get a new snapshot. The old one doesn't go anywhere unless you explicitly remove it.
Corn
So how do you actually manage this? If I've been downloading models for six months and my cache is sixty gigs, what do I do?
Herman
The huggingface_hub library has a whole cache management API. The entry point is scan_cache(). It returns a list of CachedRepoInfo objects — one per repo you've ever downloaded. Each tells you the total size on disk, last access time, and how many revisions are stored. From there, you've got delete_cache() which lets you remove models by repo ID, age, or strategy — "delete the oldest ones first," that kind of thing. And then there's clean_cache(), which is the one everyone should be running and nobody does. It removes revisions that aren't pointed to by any ref anymore — stale branches, deleted tags, orphaned data.
Corn
So clean_cache() is the garbage collector.
Herman
And it's safe. It won't touch anything still referenced. You can run it whenever and it just sweeps up the cruft.
Corn
But here's the catch — deleting a model doesn't always free as much space as you'd expect.
Herman
Right, and this is the second big misconception. When you delete a model from the cache, the blobs unique to that model get removed. But any blobs shared with other models stay. So you delete a Llama fine-tune and expect to get back, say, thirteen gigs. But if you've still got the base Llama model in your cache, most of those blobs are shared. You might only free up a few hundred megabytes of the adapter weights.
Corn
The scan_cache() output actually breaks this down — it shows "shared" versus "unique" size.
Herman
It does. And that's the number you should be looking at, not the total. The total size is misleading because a chunk of it is probably being used by three other models.
Corn
Alright, let's make this concrete. I've got an RTX 3060 with twelve gigs of VRAM. I want to run Llama 2 7B. I punch my specs into the compatibility tracker. What does it tell me?
Herman
At full FP16 precision, Llama 2 7B needs about thirteen gigs just for the weights — before the key-value cache overhead during inference. The tracker would tell you it doesn't fit at FP16. But you're not going to run it at FP16. You're going to quantize it to 4-bit.
Corn
And quantization is a separate optimization step. The tracker doesn't automatically account for it.
Herman
It doesn't, and this is worth flagging because it's a gap in the workflow. The tracker checks the model's published requirements, which assume standard precision. If you're planning to quantize, you have to do that math yourself. A 7B model at 4-bit drops from roughly thirteen gigs to somewhere around four to five gigs. That fits comfortably in twelve gigs of VRAM with room for context.
Corn
So the tracker says no, but the real answer is yes if you know what you're doing.
Herman
And that's the friction. The tracker is a first-pass filter, not a definitive answer. It's useful for catching obviously impossible combinations — trying to run a 70B model on a laptop with eight gigs of RAM. But for the edge cases, you need to understand what quantization buys you and how to apply it.
Corn
Let's say I've done that. I've quantized, I've downloaded, I'm running inference locally. What does that actually mean in terms of the pipeline?
Herman
Your inference framework — usually Transformers or something built on top of it — loads the model into GPU memory, tokenizes your input, and runs it through the layers. Each layer is a series of matrix multiplications. The weights stay in VRAM the whole time. Your input tokens flow through, the attention mechanism does its thing, and you get output tokens one at a time. The key thing about local inference is that once the model is loaded, there's no network round trip. Your latency is purely compute-bound.
Corn
No network round trip, and no per-token billing.
Herman
You paid for the hardware upfront, and the marginal cost of each token is electricity. Local inference is capital expenditure heavy and operational expenditure light. Cloud inference is the reverse.
Corn
Which brings us to the other half of Daniel's question. If you don't want to manage hardware, don't want to think about quantization, don't want to clean up cache directories — you go cloud. But there are two different cloud routes, and they're not the same thing.
Herman
They're not, and conflating them is the third big misconception. The Hugging Face Inference API and Inference Endpoints sound like the same product. They both use the InferenceClient in Python. But the routing underneath is completely different.
Corn
Walk me through route one — Hugging Face as a gateway.
Herman
Route one is the Inference Endpoints product. You create an endpoint, pick a model, choose a backing provider — AWS, Azure, a dedicated GPU cloud provider — and Hugging Face deploys the model on that provider's infrastructure. When you send a request, it goes to Hugging Face first, then Hugging Face routes it to the provider, the provider runs inference, sends the result back to Hugging Face, and Hugging Face sends it to you. There's an extra hop in there.
Corn
So Hugging Face is acting as a load balancer and API gateway, but the actual compute is happening on someone else's metal.
Herman
Right. The advantage is model coverage. Because Hugging Face isn't hosting the model directly, they can support any model on the Hub as long as a provider is willing to run it. You're not limited to a curated list. The downside is that extra hop adds latency, and you're paying both Hugging Face and the provider — it's bundled into one price, but the cost structure reflects the middleman.
Corn
And route two — the direct API.
Herman
Route two is the hosted Inference API. Hugging Face runs the model on their own infrastructure. No third-party provider. Your request goes from your code to Hugging Face's servers, inference happens, the result comes straight back. It's simpler, there's less latency, and the free tier covers a decent amount of usage for smaller models.
Corn
But you're limited to models Hugging Face has chosen to host.
Herman
Correct. They pre-deploy a selection of popular models. If the model you want isn't on that list, you can't use the direct API — you'd have to go the Endpoints route or run it locally. The direct API is curated; Endpoints are open.
Corn
And both of these use the exact same Python interface.
Herman
Same InferenceClient. Same method calls. text_generation(), image_classification(), automatic_speech_recognition() — the API surface is identical. The difference is what happens after you hit "send." With the direct API, your call goes to a fixed endpoint that HF maintains. With Endpoints, your call hits a load balancer that picks a provider based on availability and latency, then forwards the request.
Corn
So from a code perspective, switching between them is basically changing a URL or an endpoint name.
Herman
It's changing one parameter when you instantiate the client. The library abstracts the routing completely. And that's both a strength and a trap — it's easy to use, but it's also easy to not understand what you're actually paying for or where your data is going.
Corn
What about the practical differences? If I'm calling InferenceClient().text_generation('-llama/Llama-2-7b-chat-hf') through the direct API versus setting up an Inference Endpoint for the same model, what am I actually experiencing differently?
Herman
Latency first. The direct API is generally faster because there's no intermediary hop. With Endpoints, you've got that routing layer — it's usually tens of milliseconds, but it's there. And if you're doing streaming, those tens of milliseconds per token add up. Cost is the bigger difference, though. The direct API has a free tier for smaller models and then usage-based pricing for PRO subscribers. Endpoints are billed by the hour that the endpoint is running, regardless of how many requests you send. If you need a model available twenty-four seven with guaranteed capacity, Endpoints is the way to go. If you're just prototyping or sending occasional requests, the direct API is dramatically cheaper.
Corn
And model availability — the direct API has maybe a few hundred models pre-deployed. Endpoints can run anything.
Herman
Anything with a compatible architecture that a provider is willing to host. In practice, that's most of the popular model families. But there's another layer worth mentioning — the free Inference API for small models is rate-limited and runs on shared infrastructure. You might get queued if demand is high. Endpoints give you dedicated resources.
Corn
So the decision tree is: if your model is on the curated list and your usage is low to moderate, direct API. If your model isn't on the list or you need guaranteed throughput, Endpoints. If you want zero per-token cost and you've already got the hardware, local.
Herman
That's the framework. And you can mix and match. Prototype on the direct API, deploy to an Endpoint when you need production reliability, and keep a quantized local copy for development and testing. The InferenceClient doesn't care which backend it's talking to.
Corn
The portability between these pathways is underrated. You write the same code, you point it at different infrastructure. That's the promise of the Hub model — the model is the interface, and where it runs is an implementation detail.
Herman
Until it isn't. There are edge cases. Some models use custom inference code that only works in specific environments. Some providers don't support certain model architectures. The abstraction leaks. But for the vast majority of models on the Hub — the Transformers-compatible ones — it really is that portable.
Corn
Let's talk about what happens when the abstraction leaks in the other direction — locally. You've downloaded a model, it's in your cache, you're running inference. Three months later, you've got forty models and your disk is full. What does the cleanup workflow actually look like?
Herman
You start with scan_cache(). That gives you a report — every repo, its size, when you last touched it, how many revisions. From there, you make decisions. Maybe you delete anything you haven't accessed in sixty days. Maybe you delete specific models you know you're done with. The delete_cache() function takes a strategy parameter — you can pass it a repo ID, a list of repo IDs, or a pattern.
Corn
If you just want to be aggressive about it, clean_cache() handles the orphaned revisions.
Herman
That's the low-hanging fruit. Run clean_cache() first, because it's safe and it'll probably free up a surprising amount of space. Then run scan_cache() again to see what's left, and make decisions from there.
Corn
I'm imagining someone running scan_cache() for the first time and discovering they've got eighty gigs of models they forgot they downloaded.
Herman
That's basically every machine learning engineer's laptop. The cache is invisible until it's a problem. It's in a dot-directory, it doesn't show up in your normal file browsing, and the files have hash names so you can't even tell what they are by looking at them. The cache management API is the only sane way to deal with it.
Corn
Unless you're the kind of person who just nukes the whole directory and starts over.
Herman
Which works, but then you have to re-download everything you actually wanted to keep. And if you're on a metered connection or you've got bandwidth caps, that's painful.
Corn
Alright, so we've covered the local pathway — compatibility tracker, downloading, cache structure, cleanup. We've covered the two cloud routes — direct API versus Endpoints, same interface, different routing. What's the thing most people get wrong about all of this?
Herman
I think the biggest thing is assuming there's one right answer. The pathways aren't competitors — they're different points on a spectrum of control versus convenience. Local gives you total control and zero per-token cost, but you manage everything. Direct API gives you zero infrastructure overhead but limited model selection. Endpoints give you any model with guaranteed capacity, but you're paying by the hour. The right choice depends on where you are in your project's lifecycle.
Corn
The lifecycle thing matters. I've watched people spin up an Endpoint for a model they're just evaluating, burn through a hundred dollars in a week, and then realize they could have done the same evaluation on the direct API for free.
Herman
Or locally. If you've got a GPU that can handle a quantized version, your evaluation cost is literally zero beyond the electricity. The compatibility tracker should be the first thing you check, not the last.
Corn
There's also a psychological dimension to this. When you're running locally, the model feels like a tool. It's on your machine, it's yours, you can modify it, you can break it, you can poke at its internals. When you're calling an API, the model feels like a service. It's someone else's thing that you're renting access to. Those are different relationships to the technology, and they shape how you use it.
Herman
That's... actually not something I'd considered, but you're right. The local pathway invites experimentation in a way that metered API access doesn't. If every request costs money, you think twice before sending a weird prompt just to see what happens. If it's running on your own GPU, the weird prompts are free.
Corn
Weird prompts are kind of our whole thing.
Herman
They really are.
Corn
To Daniel's core question — the two pathways, how the mechanics differ — I think the answer is: they differ at every level except the code you write. The interface is the same. Everything underneath is different. Where the model lives, who owns the hardware, how you pay, how you clean up, what happens when something goes wrong.
Herman
The compatibility tracker is the fork in the road. It's the thing that tells you whether the local pathway is even an option. If it is, you've got a decision to make. If it isn't, cloud is your answer, and then the question becomes direct API versus Endpoints.
Corn
One thing we haven't touched on — and this is where I think things are heading — is the blurring of these lines. Split inference, where part of the model runs locally and part runs in the cloud. Or speculative decoding where a small local model generates candidate tokens and a large cloud model verifies them. The pathways are starting to merge.
Herman
That's the open question, isn't it? As models get larger and quantization gets better, does local become more viable for more people? Or does the convenience of cloud — no downloads, no cache management, no GPU driver headaches — win out for everyone except the enthusiasts?
Corn
I think it depends on whether the hardware keeps up. Right now, a 7B model at 4-bit runs on a consumer GPU. A 70B model at 4-bit needs something closer to a workstation. If quantization techniques keep improving and hardware keeps getting cheaper, the crossover point moves. More models become locally runnable for more people.
Herman
But at the same time, the cloud providers aren't standing still. Latency keeps dropping. The free tiers keep getting more generous. The curated model lists keep growing. The gap between "it runs locally" and "it runs conveniently in the cloud" might actually be narrowing from both sides.
Corn
Which means the right answer today might not be the right answer in eighteen months. And that's fine. The point is understanding the mechanics well enough to make the call for yourself.

Hilbert: You know what nobody ever talks about with that cache system? The symlinks.
Herman
The symlinks?

Hilbert: The way the blobs are stored by hash. I managed a GPU cluster at a university lab — this was around twenty nineteen, eight A100s, a queue system that made everyone furious — and we had a ten-terabyte NAS that the grad students kept filling up. They'd download every variant of every model. Bert base, Bert large, Bert base uncased, Bert base cased, and then five different fine-tunes of each. The NAS would hit ninety-five percent and the jobs would start failing.
Corn
The symlinks were the problem?

Hilbert: They were the thing that made the problem invisible. You'd look at a model folder, it says thirteen gigs. You delete it. You get back maybe two gigs. Because the other eleven gigs of blobs are still being referenced by three other models. The scan_cache() output shows it — the shared versus unique breakdown — but nobody ever ran scan_cache(). They'd just delete folders in the file browser and then wonder why their disk was still full.
Herman
What did you do?

Hilbert: Wrote a cron job. Every Sunday at 3 a.m., it ran scan_cache(), calculated how much space each user's models were taking, and if a user was over eighty percent of their quota — we gave everyone five hundred gigs — it emailed them a report. Listed every model, when they last accessed it, how much was unique versus shared. Told them to run clean_cache() and then delete_cache() on anything older than thirty days.
Corn
Did they actually do it?

Hilbert: About half of them. The other half ignored the emails until their jobs started failing, and then they'd file a ticket saying the cluster was broken.
Herman
You were basically running tech support for a cache management API that already had all the tools built in.

Hilbert: The tools were there. The knowledge wasn't. Everyone knew how to download a model. Nobody knew where it went or how to get rid of it. We eventually added a script to the cluster login banner that just ran clean_cache() automatically on login. Saved about four terabytes a month.
Corn
Four terabytes of orphaned revisions.

Hilbert: Orphaned revisions, stale branches, models people had downloaded once to test and never touched again. The cache is designed to be efficient — the content-addressable storage is good engineering — but it assumes someone's going to maintain it. Nobody does.
Herman
The clean_cache() function is safe, though. It only removes things that aren't referenced.

Hilbert: Yeah, I know. That's why we automated it. The problem wasn't safety. It was awareness. People didn't know the cache existed, didn't know it was growing, didn't know there was a garbage collector. The whole system is invisible until you run out of disk.
Corn
That's the thing about local inference in general. The tools are good. The documentation exists. But the gap between "I found a model" and "I'm running it sustainably" is full of these invisible friction points — the cache, the quantization step, the compatibility tracker's blind spots.

Hilbert: The tracker's fine for what it is. It's a first check. The problem is when people treat it as the final answer. It says no, they give up, when the real answer was "yes, if you quantize." Or it says yes, they download, and six months later their disk is full and they don't know why.
Herman
What's the fix? Better tooling? Better defaults?

Hilbert: Default to running clean_cache() after every delete_cache() call. And show a disk usage warning when the cache crosses some threshold — fifty gigs, a hundred gigs, whatever makes sense for the machine. The information is all there. It just needs to be surfaced.
Corn
The cache as a product problem, not a technical one.

Hilbert: Most things are.
Corn
Alright, let's land this. We've traced the two pathways — local and cloud — and the cloud fork between direct API and Endpoints. The mechanics are different at every level except the code you write. The compatibility tracker is your first decision point, the cache management API is your ongoing maintenance burden, and the cloud routing is an abstraction that works until it doesn't.
Herman
The thing I keep thinking about is how much of this is going to change. Split inference — running part of a model locally and part in the cloud — is already happening in research. Apple's doing on-device inference with cloud fallback. The line between "local" and "cloud" is getting blurrier, not sharper.
Corn
Which means understanding both pathways isn't just about making a choice today. It's about understanding the pieces well enough to reassemble them when the pathways start merging.
Herman
That's a good place to leave it. Thanks to Hilbert Flumingtop for producing, and for the four terabytes of orphaned model revisions.
Corn
This has been My Weird Prompts. If you've got a weird prompt of your own, email us at show at my weird prompts dot com. We'll be back soon.

This episode was generated with AI assistance. Hosts Herman and Corn are AI personalities.