AI Engineer Summit 2023
Harnessing the Power of LLMs Locally
Read the talk
Harnessing Local LLMs with Rust
Local inference puts model selection, session state, sampling, and deployment inside your application. Mithun Hunsur’s llm.rs examples show what that control enables—and what it costs.
From a talk by Mithun Hunsur
Before you start: Basic familiarity with language-model prompts and Rust functions, closures, and threads will help with the implementation examples.
What changes when the model runs on your computer?
What changes when an application runs its own language model instead of sending prompts to a hosted service? With ChatGPT, Claude, or Bard, the provider operates the model. With local inference, the model runs on your computer, giving your application control over the hardware, inference process, and data it sends into that process. Mithun Hunsur, known online as philpax, introduces this approach through llm.rs, the Rust inference library he maintains alongside his work building a game engine at Ambient. The recording describes the historical library; its repository is now archived and unmaintained.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Model capacity meets available hardware
The first constraint is model size. Hunsur uses parameter count as a rough proxy for capacity: the hosted models in his comparison—GPT-3, GPT-4, Gopher, and PaLM 2—occupy the large end of the chart, while Llama and Falcon represent the growing local-model ecosystem. Size is not a task-quality guarantee, however. A smaller model focused on one problem may solve it better than a larger general model. The chart’s GPT-4 size is explicitly speculative; Hunsur says its actual size is unknown outside OpenAI.
Hardware introduces a separate limit. Hosted inference uses specialized infrastructure, while local inference uses whatever equipment you can obtain, including rented machines. More capable infrastructure can improve generation speed, support more simultaneous inference, or both. Hunsur’s illustrative hardware-cost axis runs from a few hundred dollars to a few hundred million dollars. This is a comparison of infrastructure scale, not a measured price-performance benchmark.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Latency, cost, customization, and privacy
Latency is not just the speed at which a model generates tokens. In the hosted request pattern Hunsur describes, the application submits a completed prompt and waits for the network exchange. A local application can feed input into the model incrementally as it arrives. For conversation, that means processing what someone is saying while they are still saying it. Removing the network trip and overlapping prompt processing with input can reduce waiting, although inference itself still takes time.
The economic comparison is similarly workload-dependent:
| Question | Hosted inference | Local inference |
|---|---|---|
| What determines the bill? | Provider’s per-token price | Cost of operating the machine |
| Who supplies the hardware? | Provider | You, or a hardware rental service |
| When can local be cheaper? | Compare the workload’s API bill | When local operating cost is lower |
An existing computer reduces additional acquisition cost; it does not make electricity, machine time, or operation literally free. The relevant comparison is the cost of serving your workload, not simply whether you already own a laptop.
Model choice adds another reason to run locally. Hosted applications select from a provider’s catalog, and fine-tuning may introduce both training fees and higher usage charges. Local applications can choose custom models for retrieval, storytelling, conversation, or tool use, then fine-tune further when necessary. Hunsur recommends Axolotl for that training work. Finally, local inference can keep private prompts on the machine instead of submitting them to a cloud model—a practical benefit even when the question is merely embarrassing.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Fitting billions of parameters into memory
Owning the inference process only helps if the model fits the available hardware. Billions of parameters mean billions of stored numerical values, and consumer machines have limited memory. Quantization addresses this by representing parameters at lower precision: a lossy compression that reduces the model’s memory requirement while preserving much of its useful capability.
The benefit extends beyond storing a smaller file. A smaller representation can let the computer process more of the model at a time, potentially improving inference speed. The trade-off is information loss, so reduced size and retained quality have to be considered together. Hunsur presents the mechanism rather than a particular compression ratio or speed benchmark.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
From a Rust rewrite to a reusable library
The project began with Hunsur encountering llama.cpp in March. The repository snapshots he presents contrast 98 stars early on with roughly 42,000 at presentation time. His response was to rewrite it in Rust, partly for the familiar programming joke and partly because he wanted to reuse inference in other applications. Another developer, setzer22, finished a parallel implementation first. They merged their projects, and Hunsur became maintainer of the resulting llm library.
Why build another implementation? Hunsur describes the March version of llama.cpp as an application rather than a reusable library. His design starts with embedding inference in other software and develops six requirements:
- Library first: expose inference as functionality an application can call.
- Customizable behavior: avoid coupling the library to one application or assuming how it will be used.
- Multiple architectures: support more than one model family.
- Idiomatic Rust: make the interface feel native to Rust, rather than like foreign-language bindings.
- Multiple backends: allow CPU, GPU, and future compute implementations.
- Portable deployment: keep application behavior consistent across Windows, Linux, macOS, and other platforms.
Together, these requirements make inference a component whose behavior the application can shape.
The supported architectures, including Llama and Falcon, share an interface. Switching architectures therefore does not require rewriting the application’s integration around a completely different API. Hunsur credits Lucas, Dan, and the wider contributor community for making that breadth possible.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Load a model, then keep state in sessions
The demonstrated API separates the loaded model from an inference session, which tracks one ongoing use of that model. This is the historical rustformers API, not the provider interface now documented under the latest llm crate. Its application flow is straightforward:
- Load the model.
- Create a session for an ongoing interaction.
- Pass a prompt into that session and run inference.
- Receive generated tokens through a callback.
You can create multiple sessions, but each carries a memory cost. Keeping a session alive lets a conversation continue without feeding its previous context back into the model on every turn. Session lifetime therefore affects both memory consumption and conversational behavior.
The inference function is a convenience helper: it repeatedly calls the model until its boundary conditions say to stop. An application that needs different control flow can replace that loop. Likewise, the sample’s repeated Default values are customization points for model loading, inference, and sampling. The defaults provide a short path to inference without making the default behavior mandatory.
Hunsur then demonstrates Llama 7B running on his MacBook CPU before showing GPU acceleration. The GPU version makes the interaction visibly more usable in his presentation; he also reports faster performance on NVIDIA GPUs. These are qualitative comparisons, with no tokens-per-second result or complete benchmark configuration. AMD and Intel support is described as pending at the time of the demonstration.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Three ways to package local inference
The community projects show how the same inference engine fits different kinds of software:
- local.ai: louisgv’s desktop application makes local inference available through a downloadable app, without requiring the user to build an integration.
- llm-chain: a Rust workflow library that Hunsur describes as LangChain for Rust, with llm.rs as an inference option.
- Floneum: a flowchart-based application in which users connect nodes into workflows, using the library as an inference engine.
The reusable part is model execution; the surrounding product can be a simple app, a programmatic workflow, or a visual editor.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Separating generation from response delivery
Hunsur’s first proof of concept, llmcord, puts the library behind a Discord bot. A user sends a prompt and receives generated text. Hunsur attributes the visible hitches in the demonstration to Discord’s limits rather than inference. Underneath the chat interface, a generation thread and a channel connect the request to a response task responsible for sending output to the user.
The separation can be expressed directly in Rust. This adapter accepts a generation function that emits text chunks and a response function that delivers them. The channel carries output between the generation thread and the response side:
rust
use std::sync::mpsc::{self, Sender};
use std::thread;
pub fn stream_response<G, R>(generate: G, mut respond: R)
where
G: FnOnce(Sender<String>) + Send + 'static,
R: FnMut(String),
{
let (output, incoming) = mpsc::channel::<String>();
let generation = thread::spawn(move || generate(output));
for chunk in incoming {
respond(chunk);
}
generation.join().expect("generation thread panicked");
}
An inference callback supplies chunks to output; respond handles delivery. Once generation finishes and its sender is dropped, the receiver loop ends. Keeping those responsibilities separate lets the response side accommodate a transport’s delivery behavior without putting that behavior inside model generation.
The bot creates and discards a session for each query. Retaining a session instead would let later requests continue the conversation. The transport is another replaceable part: remove Discord, put HTTP at the boundary, and the core flow remains request, generation, response. The session policy and the transport policy are independent application decisions.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Autocomplete beyond the code editor
Alpa, Hunsur’s second proof of concept, starts with a limitation he encounters using GitHub Copilot: completion is tied to his editor and requires an internet connection. Alpa takes text to the left of the cursor and uses a local model to continue it elsewhere in the operating system. Model selection remains open, including a model fine-tuned on the user’s own writing.
The application loop is small:
- Listen for input.
- Copy the relevant text into a prompt.
- Generate a continuation with the model.
- Type the response into the application.
The inference engine supplies text; the operating-system integration decides where that text comes from and where the completion goes.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Turning Wikipedia dates into structured data
The third application moves from proofs of concept to a data-extraction workload. Hunsur wants to build a world-history timeline from dates scattered across Wikipedia. The scale is millions of pages, but the harder problem is interpretation: date expressions are unstructured, and finding a date-like substring does not recover the context needed to understand it. Regular expressions can locate patterns without resolving what those patterns mean.
He first tries GPT-3 and GPT-4. Even after prompt engineering, the results remain imperfect, and processing millions of dates is too slow and expensive for his workload. That leads to a specialized model and a data preparation loop:
- Generate a representative dataset with GPT-3.
- Inspect examples in a custom tool.
- Correct erroneous data points and assemble the corrected dataset.
- Fine-tune a model with Axolotl.
The correction step matters: generated examples are material to review and repair before training.
The resulting model accepts a date expression and returns a structured representation that Rust can parse. Hunsur describes it as small, fast, and consistent, without giving measured accuracy or throughput. Once the inference and output parsing are wrapped behind an fn parse-style interface, the rest of the ingestion pipeline can treat the model as a component: pass dates in, receive structured dates back. Specialization turns a broad language-model capability into a narrow application interface.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Shipping inference and controlling its behavior
Embedding inference in Rust also changes distribution. Hunsur contrasts managing Python environments through conda, pip, and Pipenv with using Rust’s build system and platform support to ship self-contained application binaries. Users need not install Torch to run these applications, making local models easier to incorporate into desktop software.
The surrounding ecosystem matters as much as the model interface. Rust libraries let Hunsur build Discord integration, operating-system autocomplete, a data-ingestion pipeline, and tools for exploring and correcting datasets in the same language. Inference becomes another library in that application, rather than a separate service around which the entire program must be organized.
Control also extends to token sampling. Hunsur contrasts direct access to local generation with hosted interfaces that expose limited probability information and require repeated network exchanges to influence the process. Owning the inference loop lets application code decide how to sample at the point where the next token is selected.
That access creates room to experiment with new research before a hosted provider offers equivalent functionality. A developer can implement a technique, try it against the application’s problem, and decide whether it is an improvement. The opportunity is earlier experimentation—not an assurance that every new paper will help.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Hardware, compatibility, and licensing still constrain the application
Local inference does not remove hardware requirements. Hunsur explicitly qualifies the earlier suggestion that models can run on almost anything: an old computer, smartphone, or Raspberry Pi has limits that smaller models and better inference implementations can ease but not erase. The application still has to choose among speed, cost, and quality. A larger model may improve results while making the interaction slower; whether that is acceptable depends on the task.
Rapid innovation also creates compatibility churn. A new model can break a previously working workflow. Hunsur points to his work on GGUF standardization as one way to reduce that friction, not eliminate it. Format standardization should not be confused with support in this particular library: the archived repository’s main branch lacks GGUF support, while its experimental GGUF branch has limited Llama support and lacks quantization.
Licensing is a separate constraint. Downloadable weights and permission for personal use do not establish unrestricted rights; model licenses can contain consequential clauses and exceptions. Hunsur points to Mistral 7B and StableLM as encouraging developments in smaller models, compared with the larger Llama and Falcon models in his discussion. Their licenses still need to be distinguished: Mistral 7B was released under Apache 2.0, while StableLM terms vary by checkpoint, including attribution/share-alike and noncommercial terms. The model family’s name alone is not enough to determine whether a release fits an application.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
More accessible models, application-specific choices
Smaller, more capable models make local inference easier to adopt, and a reusable library makes that capability easier to embed. Neither development produces one obvious answer for every problem. The practical choice remains tied to the application: what it needs the model to do, how quickly it must respond, and which constraints its deployment can accept.
Hunsur closes by directing viewers to llm.rs and inviting contributions from people interested in Rust or language models. Sponsorship would help test additional hardware—a concrete requirement for a project aiming to support diverse machines. He offers email, Mastodon, and conversation at the conference as ways to get involved.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
Archived source for the library in the talk, including CLI examples, session persistence and model-format limitations.
Desktop application built around llm, with model downloads, notes and a streaming inference server.
Archived Rust Discord bot demonstrating integration with the llm inference library.
Hunsur's Rust proof of concept for LLM-powered autocomplete across the operating system.
Fine-tuning framework with dataset preparation, configuration examples and training instructions. The repository documents its current capabilities.
The September 2023 announcement describes the 7.3B model, Apache 2.0 licensing and the team's benchmark methodology.
Model-family documentation distinguishing base-model, tuned-model and source-code licenses.
Read the complete timestamped transcript
- 0:00
[upbeat music] Right. Good day, everyone.
- 0:15
Good to see you all. Today, I'm here to tell you to har- how to harness the power of local LLMs using our Rust library. Quick intro. I'm Mithun, as you just heard, but I go by [REDACTED:username] online.
- 0:27
I hail from Australia, hence the accent, but I live in Sweden. I do a lot of things with computers, but my day job is at Ambient, where I build a game engine of the future.
- 0:36
Today though, I'm here to talk to you about llm.rs, a Rust library that I maintain.
- 0:42
So llm.rs or LLM between friends. I realized that I have to disambiguate when I started, when I signed this Simon's newsletter. [laughs] It's an all-in-one solution for local inference of LLMs, but what does that actually mean?
- 0:55
Well, most of the models we've discussed at this conference have been cloud models. You have ChatGPTs, your Claudes, your Bards. Local models offer another way, where you own the model and it runs on your computer.
- 1:07
So let's quickly go over what that actually means.
- 1:11
First up, size. Model size can be used as a rough proxy for the intelligence of the model. Most hosting models are really, really big. You can see that it's dominating the right-hand side of the chart there.
- 1:24
You have your GPT-3, your GPT-4, we'll get back to that. Your Gopher, your PaLM 2. These are all insanely big in comparison to the open source models we have.
- 1:34
We're gonna, we're beginning to see some, uh, bigger models thanks to, uh, Llama and Falcon, but even they pale in comparison to what the bigger players can do. This means the local models don't have the same capacity for intelligence.
- 1:45
However, a smaller, more focused model may be able to solve problems l- uh, better than a large general model. By the way, we don't actually know what size GPT-4 is.
- 1:55
That's rumors. Uh, only OpenAI knows. Next, let's talk about speed and capacity. Cloud models run specialized hardware with special configuration. Local models run on whatever hardware you can scrounge up, including rented hardware.
- 2:11
The further up the axis you go, the more speed and/or parallel inference you can do, but the more inaccessible it becomes. This end, a few hundred dollars. That end, a few hundred million dollars.
- 2:24
Next up, latency. Cloud models need the full prompt before they can start inference, and you have to wait for the message back, uh, back and forth. Local models can give you a response immediately.
- 2:35
You can feed the prompt as you go along. This is very important for conversations where you want the model to be able to process what you're saying as you say it.
- 2:44
And of course, you can't escape talking about cost. The cloud vendors will charge you a per token price. When running locally, it's entirely up to you how much it costs you to run the machine.
- 2:55
If the running cost of your, uh, model is less than the cost of running your workload through the cloud, you're going to make a profit, and if you're running on a machine you already own, well, that's basically free, right?
- 3:06
With the cloud, you have to offer, you have to use the models they offer you. Some vendors offer fine-tuning, but they often charge more than, uh, just using the regular model, and they often charge you for the pro- process of actually fine-tuning.
- 3:18
This means that it's not often cost-effective to, to actually do that. With local models, the sky's the limit. There are hundreds, potentially thousands of custom models that can suit any need you have.
- 3:30
Knowledge retrieval, storytelling, conversation, tool use. You name it, someone's probably already done it, and if they haven't, fine-tuning an existing model for your own use is easy enough. Special shout-out to Axolotl over there, which makes it easy to fine-tune, uh, models of any architecture.
- 3:47
And of course, privacy. [laughs] There are some questions you don't want to ask the internet. Local models let you privately embarrass yourself. [laughs]
- 3:58
Now, you might be wondering how it's actually possible to run these models locally. That, my friends, is possible with the power of quantization. If each model is billions of parameters, and those parameters are, are like individual numbers, how could you, how could you possibly run them on consumer hardware when there's only so much memory given for, uh,
- 4:15
available for a given, uh, performance level? Well, we can use quantization. Quantization lets you lossily compress a model while maintaining the majority of its maths. We can take the original model, here in blue, and squish it down to something much smaller using one of these green formats.
- 4:30
This is a secret sauce that makes it, uh, viable to run models locally. Smaller models aren't easier to store, aren't just easier to store. They can also run faster as your process, uh, uh, as your computer can process more of the model at any given moment.
- 4:44
But that's enough about local models. You've probably already h-heard much, uh, much that already. Let's talk about the actual library.
- 4:52
It all started with this man who built something you may have heard of. Of course, I'm referring to Llama CPP, and that's what it looked like on day one.
- 4:59
Look at the mere 98 stars. How pedestrian compared to today, where it's forty-two thousand stars. Uh, but let's go back to March when I first saw it. When I saw it, I had but one idea.
- 5:11
It's time to rewrite it in Rust. [laughs] For both the meme and because I wanted to do use it for other things. Well, I wanted to say I... Well, I said I wanted to do it, and I did.
- 5:21
But to the right here, [REDACTED:username] was also working on the same problem, and well, there was just one catch. He beat me at... He beat me to it, completely beat me to it.
- 5:30
I'm not afraid to admit it. Luckily, we came together, merged our projects, and I ended up as the maintainer of the resulting project, and that's how LLM was born.
- 5:41
So you might be wondering, why? If Llama CPP exists, why use La- uh, llm.rs? Well, with llm.rs, I had six principles in mind. It must be a library. When I first started in March, Llama CPP was not a library.
- 5:56
It was an application, and that made it impossible to reuse. It must not be coupled to, to an application. You must be able to customize its behavior. You must be able to go in and change every little bit of it to make it work for your application, and we sh- we shouldn't make any assumptions about how it's,
- 6:11
it's going to be used.
- 6:12
Uh, it should support a multitude of model architectures. Of course, llama.cpp supports Llama and now Falcon, but clearly there are more out there. Next up, it should be Rust native.
- 6:23
It should feel like using a Rust library. It shouldn't feel like using a, a library with bindings, and it should feel, work how you expect a Rust library to work.
- 6:30
Next up, backends. It should support all other, uh, all possible kinds of backends, so you can run it on your CPU, your GPU, or of course, your ML-powered toaster.
- 6:38
I'm sure that's gonna be a thing. But we have, we've s- we're gonna see it coming, I'm s- I swear. And finally, platforms. It should work the same whether it's on Windows, Linux, macOS, or something else.
- 6:49
It shouldn't have... You shouldn't have to change it significantly to make it work, because deployment has always been an issue.
- 6:56
Today, I'm proud to say we support a myriad of architectures, including the, uh, the darlings of the movement, Llama and Falcon. These architectures all use the same interface, so you don't have to worry about changing your code to use a different model.
- 7:08
This is made possible by the coordint- coordi- [laughs] concerted efforts of my co-contributors Lucas and Dan, who couldn't have done this without, as well, as well as many others.
- 7:18
Here's some sample code for the library. I won't go too much into it because it's quite dense, but the idea is that you load a model right there at the top.
- 7:26
You can see it's actually quite small. And with that model you create sessions which track an ongoing use of the model. You can have as many of these as you would like, but they do have a memory cost, so you want to be careful.
- 7:35
Once you have a session, you could pass, you can pass a prompt in and infer with the model to determine what comes next. You can k- keep reusing the same session, which is very useful for conversation.
- 7:44
You don't need to keep re-feeding the context. The last argument of the call, uh, of the function is the callback. That's where you actually get the tokens out. Um, it's worth noting that the function itself is actually a helper.
- 7:57
All it does is call the model in a loop with some boundary conditions. So if you wanna change the logic in some, uh, significant way, you can. We're not gonna stop you from doing that.
- 8:06
One last thing about this though. You see all the calls to default there? Those are all customization points. You can change pretty much anything about this. You can change how the model is loaded.
- 8:15
You can change how it'll do the inference. You can change how it'll sample. The entire point is you have the control you need to make the thing y- uh, you need to work.
- 8:24
Here's a quick demo of, uh, the library working with Llama 7, uh, billion on my MacBook CPU. It's reasonably fast, but it could be faster, right? Well, thanks to the power of
- 8:40
GPU acceleration, we have something that's much more usable. And believe me, it's even faster on NVIDIA GPUs. AMD and Intel, uh, support, uh, pending.
- 8:51
Now let's talk about what you can actually do with the library.
- 8:54
Let's start with three community projects to begin with. First, we've got Local AI. Local AI is a simple app that you can install to do inference locally. There's nothing magical about it.
- 9:04
It's just exactly what it says. I think that's really wonderful because it, it means anyone can download this app and get ready... Uh, get, be able to use local models without having to think about it.
- 9:14
Next up, LLMchain. It's, uh, LangChain but for Rust, and of course it supports inference with our library. And finally, we have Flowonium, which is a flowchart-based application where you can build your own workflows.
- 9:24
I think we've seen a few of that, few of those at this con- uh, this conference. And you can combine and, uh, create vi- uh, nodes to, uh, build the workflow you need.
- 9:32
And of course, it supports the library as an inference engine.
- 9:36
Now, I wouldn't be a very good library author if I didn't actually test my own library. So I'm gonna go through three applications. The first two are proofs of concept.
- 9:45
The first is llmcord. It's a Discord bot. [laughs]
- 9:49
You can see it's exactly what you'd expect. You send, uh, give it a prompt, it'll give you a response. Any hitches you see come from Discord limits, not from the actual, uh, inferencing itself.
- 9:58
You can see, bam, all there. When an issue, when a user, uh, issues a request for generation, it goes through this process here where the request goes through a generation thread, uh, with a channel.
- 10:12
That channel is then used, uh, to create a response task, and then that response task is r- responsible for sending the responses to the, uh, user. Now, the interesting thing is these sessions are created and thrown away immediately with each query.
- 10:28
But you don't need to do that. If you keep them around, you can actually use them for conversation.
- 10:33
And just to illustrate, this is just like the request response w- workflow you would use for anything. If I just take what I had there and drop the Discord bit and add in HTTP, you can see request, generation, response.
- 10:45
Easy. Next up, Alpa. I love using GitHub Copilot, but it's only available in my code editor, and it requires internet connection. Alpa is my attempt to solve this. It is autocomplete anywhere on your system just by taking what's left of your cursor and, uh, having, passing it to a model to type in.
- 11:04
And of course, you can use any model, including a model fine-tuned in your own writing. Ask me how I know. [laughs]
- 11:11
Alpa is also quite simple. In fact, it's so simple I don't really need to cover it. Listen for input, copy the, uh, the input, um, into a prompt, start generating, type out response.
- 11:20
Easy. Now, the first two examples were pretty simple. They're proofs of concept. But now I want to talk about an actual use case. This is a real world data extraction task.
- 11:31
Over the last few years, I've been working on a project to make a timeline from dates on Wikipedia because there are millions of pages and they all have dates, and you can build a world history from it.
- 11:40
However, these dates are often unstructured and more or less impossible to parse using traditional means. Like, yes, you can try using regex to extract the dates, but you can't get the context out in any meaningful sense, and there are some dates here that just don't make any sense at all.
- 11:53
So that's why, as is the theme of this conference, I threw a large language model at it. However, GPT-3 and 4 aren't perfect, even after rounds of prompt engineering.
- 12:02
You can see I tried here. And handling millions of dates is just too expensive and slow. So I decided I'd fine-tune my own model. I generated a representative data set using GPT-3, built a tool, uh, tool to go through the data set.
- 12:15
So pick out any data point, fix it up, and then correct the errors, build a new data set, and train a new model.
- 12:22
So we did that using Axolotl, which I mentioned earlier. Again, check out Axolotl for all your fine-tuning needs. Highly recommended. And now I have a small, fast, consistent model that can pass any data to, uh, sorry, any date to, and get back a structured, uh, representation, which I can then of course immediately parse using Rust.
- 12:38
And I can treat that as a black box. So I have a function there, fn parse, pass some dates, get some dates back. Simple. Now, let's quickly talk about the benefits of using local models and the library.
- 12:50
First off, deployments. Show of hands, who's had to deal with Python deployment hell?
- 12:55
Dependency hell even. Yeah, yeah, I know. It's, it's awful. You spend hours just trying to sort out your, your Conda, your PIP, your PIPenv. It's awful. With the library, you inherit Rust's excellent cross-platform support and build system, making it easy to ship self-enclosed support, uh, binaries to your platform.
- 13:14
No more making your users install Torch. As you might imagine, this unlocks use of desktop applications with models.
- 13:21
Next up, the ecosystem. Rust has one of the strongest ecosystems of, uh, of any native language. You can combine these libraries with LLMs to build all kinds of things.
- 13:31
It's what let me build a Discord bot, a system auto-completion utility, a data ingestion pipeline with a data set, a utility explorer, all in the same language. And I think if you use llm-rs, you can do the same thing with your, uh, task as well.
- 13:45
Of course, you also have control over how, uh, the model generates. I alluded to this earlier, but you can choose exactly how it samples tokens. Normally, when you use a cloud model, you have to get back the, uh, logits, the l- uh, probabilities.
- 13:56
But those probabilities are limited. Like, you have to keep going back and forth, and that's slow and expensive. With this, you can directly control what you are sampling.
- 14:07
Finally, let's talk about the innovation in the space. If you're here, you probably know there's a paper almost every single day. It's impossible to keep up with. Trust me, I've tried.
- 14:16
But it mean, but the use of local models means you can try this out before anyone else can. You can go through. You can try out some of these papers and be like, "Oh, wow, that's actually a worthwhile improvement."
- 14:24
And eventually, the cloud providers will provide them, but in the meantime, the control remains with you.
- 14:29
However, it's time to talk about the problems. There ain't no such thing as a free lunch, except if you're at a conference, of course. [laughs]
- 14:37
Let's talk about hardware again. I mentioned earlier that you can pretty much run any, uh, these things on almost any hardware, but that's kind of a lie. You still need some kind of power.
- 14:48
You c- you can only get so much out of your 10-year-old computer, your smartphone, or your Raspberry Pi. We're finding clever ways to improve this, like smaller models and better inferencing, but it's still something to be aware of.
- 15:00
Next, as with all things, the fast, cheap, good triad applies. You can, uh, make all kinds of trade-offs here, and you can see I've listed a couple of them here.
- 15:08
But fundamentally, you have to choose what are you willing to sacrifice in or- in order to serve your a- application. Are you willing to go for a bigger model to get better quality results at the cost of speed?
- 15:18
These are all decisions you have to make, and they're not always obvious. It's something you have to think about.
- 15:26
Next, there's no other way of putting this. The ecosystem churns. Innovation is a double-edged sword. When those changes come in, they can often break your existing workflows. I've helped alleviate this w- to some extent using the GGUF, uh, file format which helps standardize, but it's still a problem.
- 15:41
Some days you will just wake up, try your application with a new model, and it just won't work. There's nothing you can do except deal with it. Finally, a lot of the models in this space are open source.
- 15:53
They're free for you to use personally, but they have very strange clauses and exceptions. For most of us, this doesn't matter. You can just use the model personally. But it's a reminder that even though that these models are free, they're not capital F Free.
- 16:06
Luckily, there's been some recent change in this space with Mistral and StableLM giving you strong performance for small level, uh, sorry, a small size and being completely unburdened. But it's still a problem, and they're still, uh, much smaller than the big ones like Llama and Falcon.
- 16:20
Unfortunately, I've got to wrap things up here. There's only so much you can talk about in 18 minutes, I'm afraid. Local models are great, and I like, I'd like to think our library is too.
- 16:30
They're getting easier to run day by day with smaller, more powerful models. However, the situation isn't perfect, and there isn't always one obvious solution for your problem.
- 16:38
Thanks for listening. You can contact me by email or via Mastodon. The library can be found at, you guessed it, llm.rs or by scanning the QR code. Finally, we're always looking for contributors.
- 16:49
If you're interested in LLMs or Rust, feel free to reach out. Sponsorships are also very welcome because they help me try out new hardware, which is always necessary. And if you want to chat in person, I'll be hanging around the conference.
- 16:59
See you later. [audience cheering] [upbeat music]