AI Engineer World's Fair 2026
Your Fine-Tuned Model Is Tech Debt: A 50x ROI House of Cards
Read the talk
When a successful fine-tuned model becomes expensive to change
Lease End’s SMS application delivered strong commercial results, but repairing its intent classifier exposed costs that cheaper inference could not offset.
From a talk by Dan Bjornn
A message decides when the phone rings
Should a customer get a call tomorrow or right now? At Lease End, which helps customers finance the purchase of their leased cars, that decision became part of an LLM application built in late 2024. Customers could text questions, schedule calls and receive reminders. Dan Bjornn, the company’s senior data scientist, describes an initial workflow built on retrieval-augmented generation: search a vector database of previously seen messages labeled with customer intent, then use that classification to route the conversation.
The straightforward examples made the approach look manageable. “Call me tomorrow” meant the customer wanted to talk later; “I've got time now” meant they wanted to talk immediately. But real conversations contained nuance that the retrieval approach did not reliably capture. The system worked, yet its most consequential decision—what the customer wanted to happen next—remained fragile.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
A textbook case for supervised fine-tuning
Bjornn’s next move was supervised fine-tuning. Accuracy came first because every downstream action depended on intent: call now, schedule a call or honor an opt-out. Smaller models also promised cheaper inference and lower latency for thousands of messages answered in real time each day. The task was narrow and structured, with conversations assigned to one of six categories.
There was a portability argument, too. Lease End owned its training data. In principle, the team could pass those examples to another model, repeat the fine-tuning process and recover similar behavior. Owning the dataset appeared to offer control over the choice of model provider.
The training pipeline followed a familiar sequence:
- Collect conversation examples.
- Use LLM-as-judge classification to label them.
- Manually review the labels.
- Create holdout sets.
- Fine-tune and check the resulting metrics.
This gave the team both a way to train the classifier and a separate set of examples against which to evaluate it.
Bjornn reports that within a year, the application helped bring in $12 million in revenue at 50× ROI. Those are application-level results; he does not provide the accounting denominator or isolate fine-tuning’s contribution. The commercial success was real in the team’s experience, but it did not reveal how difficult the system would become to maintain.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
When acknowledgment becomes permission to call
The first failure, which Bjornn calls the confused confirmer, began with an appointment already arranged. Lease End told Tracy that her advisor would call on Thursday at 2 PM. Tracy replied, “Sounds good.” The application answered, “Great. I'm calling you right now.” An acknowledgment of a future appointment had become an immediate-call action. The result was frustrated customers and missed opportunities.
The second failure, the overeager puppy, needed even less encouragement. Alex from Lease End contacted James about his upcoming lease maturity. James replied, “Hi, good morning.” The application responded, “Good morning, I'm giving you a call.” Bjornn confirms that this happened in production. A greeting had been treated as a request to speak immediately.
Both examples expose the same operational problem: a conversational response is not necessarily authorization for the next action. Positive language can confirm an existing plan or simply acknowledge another person. The application could produce strong revenue results while still making conspicuous mistakes at that boundary.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
An hour of training inside a week of repair
The difficult question was how to make repairs manageable. Each newly observed failure started another data preparation cycle:
- Gather examples of the problem.
- Decide whether there are enough examples to retrain.
- If necessary, generate additional examples with an LLM.
- Manually validate the generated conversations.
- Label the examples with the classification categories and manually review those labels.
The manual work protected training-data quality, but it also meant that correcting a seemingly small behavioral mistake required much more than launching a training job.
Bjornn reports that fine-tuning itself normally took about an hour, depending on dataset size. It was the shortest part of the process. Evaluation then exposed a second problem: fixing the latest failure could introduce regressions elsewhere. The team would repair one behavior only to see an older issue return, forcing another iteration.
The complete repair process—from gathering data through labeling, training iterations and deployment—took about a week, according to Bjornn. That cost changed which bugs the team could afford to address.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
How much customer pain can wait?
Before retraining, the team asked how often an issue occurred. An everyday failure had a different priority from a one-off. Severity could override frequency, however: a customer repeatedly stating a preferred call time while the model ignored it deserved urgent attention. Another serious failure occurred when the application told a customer that an appointment was scheduled but returned a malformed payload. The promised appointment never existed, so the follow-up never happened.
The final question was whether a workaround could avoid retraining. Could a temporary fix let the issue wait until the next run, rather than trigger a week of work for one or two problems? Together, frequency, customer harm and the possibility of postponement became the gate before anyone acted.
This was the practical cost of the repair loop: the team ranked bugs by how much customer pain it could tolerate in the meantime. Maintenance expense had become part of the customer experience.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
The calcification tax
Bjornn calls the growing rigidity the calcification tax. The first form was model lock-in—the opposite of the portability he had expected. Even versions from the same provider differed in what training data they needed. Across providers, the differences extended to data formats, the volume of examples required and the interfaces used to run training.
Owning the examples did not make those differences disappear. Switching was too costly, so the team kept the same model for consistency. Routine retraining already consumed the capacity that might otherwise have gone toward evaluating and adopting a better model.
The second form was architectural lock-in. Bjornn describes predefined workflows as the production gold standard when the application was built in late 2024. As newer approaches became available, keeping the existing system running left little room to adopt them. The accumulated cost constrained both the model and the architecture around it.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Moving behavior into context
The alternative became apparent through the team’s use of Claude Code. Different coding tasks did not require a different model each time. The team changed the skills, resources and context supplied to it. Better context changed the resulting behavior. Bjornn began asking whether the messaging application could work the same way.
Reconsidering fine-tuning meant reversing an approach Bjornn had championed, but an existing project gave the team a route forward. They migrated the workflow into skills, tools and resources that the skills could load for context. The messaging application became one of the first production tests of an agentic framework already under development. This was Lease End’s own rebuild; the Claude Code inspiration does not establish that it adopted Claude Code’s particular skill format or loader.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Repairing instructions, then validating behavior
Previously, the team waited for a critical mass of problems before entering the training cycle. After the rebuild, a discovered problem could lead directly to an edit of the affected system prompt or skill. The unit of repair had changed from a training dataset and model update to an instruction change.
For the earlier Tracy failure, a proposed instruction could make the distinction explicit in Markdown:
markdown
# Appointment acknowledgments
When the customer acknowledges an already scheduled call,
preserve the scheduled time. Do not treat agreement as a request
to call immediately.
Example:
- Existing appointment: Thursday at 2 PM.
- Customer reply: "Sounds good."
- Required behavior: Keep the Thursday appointment;
do not initiate an immediate call.
The edit expresses the intended behavior; validation still has to establish whether the model follows it. Lease End checked changes against a curated set collected during production, iterated a few times, then deployed by uploading Markdown files to an S3 bucket.
Bjornn reports that after the rebuild, the complete process from discovering a problem to deploying its fix took less than an hour. This measures the team’s repair turnaround, including validation and iteration, rather than training speed or inference latency.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
More expensive messages, a cheaper system
The rebuild increased API cost per message because the team used better models. Bjornn reports substantially better accuracy than the fine-tuned system, but supplies no numerical accuracy results or evaluation-set size. Faster repairs also let the team respond to problems without waiting for another batch of failures to justify retraining.
The new framework also restored the model choice the training dataset had failed to provide. Bjornn describes it as model-agnostic, supporting OpenAI, Anthropic and other providers, with task behavior supplied through context. He reports that total cost fell despite higher per-message API charges, because the team spent much less time maintaining and retraining the system. Inference cost was only one part of the operating cost.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
What still justifies fine-tuning?
The original reasons for fine-tuning look different when tested against the operating history:
| Original reason | Lease End’s reported outcome |
|---|---|
| Better accuracy | The rebuild outperformed the fine-tuned model. |
| Lower cost at volume | Higher message costs, lower total cost. |
| Lower latency | Smaller models delivered marginal gains with no practical difference. |
| Narrow, structured task | A textbook fit still accumulated technical debt. |
| Vendor control | Reusing data alone did not make switching easy. |
The comparison changes the decision from whether a model can learn the task to whether the team can afford to keep that learned behavior correct as requirements and models change.
Privacy, data control and offline operation remain possible reasons to fine-tune. Bjornn treats them cautiously: other solutions may exist, and the long-term consequences still need to be assessed. His closing rule is deliberately demanding: fine-tune only when calling a frontier model is not an option—and even then, the decision must justify the continuing cost of changing, validating and maintaining the system.
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
Practical documentation for creating Claude Code skills with Markdown instructions and supporting resources.
Further reading
Anthropic explains how skills package procedural knowledge and load instructions and resources only when needed.
- Building effective agentsArticle
Architectural guidance covering routing workflows, tool-using agents, evaluation and complexity tradeoffs.
Read the complete timestamped transcript
- 0:00
[outro jingle] All right. Hello, everybody.
- 0:16
Thank you for coming. I'm Dan Bjornn. I'm a senior data scientist at Lease End. Lease End, we connect people who are coming to the end of their auto lease with financing, uh, options so that they can buy out their lease and keep their car.
- 0:33
Now, as part of this, uh, we, uh, built a, an LLM-based application in late twenty-twenty-four to help our customers connect with, uh, with our sales team. This application allowed them to send messages through text.
- 0:51
Uh, they could ask questions about the sales process. They could schedule calls. Uh, they could get reminders, all of this stuff. Our first solution used a workflow-based approach, uh, built on top of, uh, a RAG system, where we searched a vector database of messages that we had already seen and classified with the customer's intent.
- 1:15
So, for example, uh, a message saying, "Call me tomorrow," would be classified as the customer wants to, uh, wants to talk later. A message saying, "I've got time now," would be classified as, uh, the customer wants to talk right now.
- 1:33
Uh, this has worked, but not super amazing. There's a lot of nuance in, in messages and, and conversation, and this RAGs approach just couldn't quite pick up on that nuance.
- 1:46
And so we started to look for, uh, for new options to improve this. And naturally, being a data scientist, my first thought was, "Hey, let's start fine-tuning." This seemed like a fun thing to do, and I was sure that this was the right call.
- 2:01
Um, there's a few reasons for that. First of all, uh, we need a better accuracy. Uh, our entire system, uh, was built upon us getting the user's intent correct.
- 2:14
Did they want to talk now? Did they wanna schedule a call? Do they want to opt out? All of this hinged on that decision, and so we needed to make sure that we got that first and foremost.
- 2:25
Next, uh, we could use smaller models with fine-tuning, and so this would lower the cost and also lower latency. So this was really important for us because we were, uh, responding to thousands of messages a day in real time, and so it, it, uh, would help us scale a lot.
- 2:46
Then next, like I said, we were classifying the intent of the user, and so this was a very narrow, structured task that we were trying to do, and so it lent itself very nicely to supervised fine-tuning.
- 2:58
Uh, we would bucket, uh, that conversation in one of six different categories, and the model would learn the differences between those. Uh, so seemed like a great option there.
- 3:10
Lastly, uh, I believe that this would help us have a little bit more control over our destiny with the, the model providers. Uh, the idea was that we had the data, and all we would need to do is pass that into a new model, go through the fine-tuning process, and we could get similar results no matter, uh,
- 3:33
what we decided to use, so we could be model agnostic.
- 3:38
So this was the approach that we took. Um, and I built a pipeline to collect examples, run LLM-as-judge, uh, classifications to label our data. I'd, uh, manually review that, create holdout sets, go through the fine-tuning process, check my metrics.
- 3:58
This was a data scientist's dream. And, uh, the numbers sure helped. Within a year, this application had helped us bring in twelve million dollars of revenue at a fifty X ROI.
- 4:11
Um, it was pretty awesome. But, uh, the whole time, it was quietly accumulating debt underneath that we didn't see. So I wanna show a couple examples of how this application could get things wrong.
- 4:27
Uh, first of all, uh, the confused confirmer is a situation where, um, when customers set up an appointment with a sales rep, we send them a confirmation message to let them know that it's been scheduled and give them the details of that.
- 4:44
Uh, so a conversation may look like this.
- 4:48
We reach out and say, "Hi, Tracy, just confirming your Lease End call with your advisor is set for Thursday at two PM. We'll call you then." Tracy then sends us a message back saying, "Sounds good."
- 5:01
And then our LLM responds with, "Great. I'm calling you right now." Uh, it's not what we want. We just confirmed a me- an appointment for a following day, and then all of a sudden we start calling them.
- 5:14
This led to frustrated customers and some missed opportunities. Uh, the next one, um, I've come to lovingly call the overeager puppy. Um, the, the conversation looks like this. So first, "Hi, James.
- 5:30
This is Alex with Lease End reaching out about your upcoming lease maturity." James then says, "Hi, good morning." And,
- 5:40
"Good morning, I'm giving you a call." Um, just like a puppy that gets so excited that somebody's giving it attention, our model decided to, to give a call right there.
- 5:53
Um, obviously, this is not what James wanted. This actually did happen in production. Um, very embarrassing there.
- 6:01
Uh, but this is a-- these are a couple examples of, of where it went wrong. And, and don't get me wrong, the, the app did well. The revenue numbers show that, that it was working, but it could also mess up pretty spectacularly.
- 6:17
Um, the big issue wasn't how to fix it, but how to make it, the fix manageable. The, the fine-tuning process was pretty complex. Uh, first, we needed to gather examples of the problems that we started to see.
- 6:34
Um, then we needed to ask ourselves, uh, do we have enough examples for, uh, to go through fine-tuning? If not, we synthesized those examples. Uh, we passed it through an LLM.
- 6:48
We created some, some possible examples there. We'd have to validate those, which was a very manual process, uh, because we wanted to make sure it had the best training data possible.
- 6:59
And then once we had enough, uh, we labeled those with, uh, the categorization bins, and we validate- validated those through a manual review. Surprisingly, the fine-tuning process was the shortest part of all of this.
- 7:14
Uh, it normally took about an hour, depending on the size of the data that we had. But, uh, we never got it on the first iteration. Uh, normally what happened was we would, uh, we would fine-tune, and we'd evaluate this, and, uh, we fixed the problem that we were just trying to solve, but then we caused regressions
- 7:36
in other things. And so, this turned into kind of a whack-a-mole process where we would solve something new, but then other old issues kept popping up that we had to, to whack down.
- 7:47
Um, this whole process took about a week to gather the data, label everything, go through the fine-tuning process and iterate, and then deploy. So, it was costly. Um, therefore, we needed to triage all of these issues that we ran into.
- 8:04
We asked ourselves three questions before a- we did any, any retraining. How frequent is the issue?
- 8:12
Is it something that customers are seeing every day? Is it one-off? Um, one big exception to this was if it was hurting the customer experience too much. So, for example of this would be, uh, somebody repeatedly stating what their, uh, their preference for a call time is, and then the, um, the model ignoring that.
- 8:36
Another one would be a customer scheduling a call. We tell them that we've scheduled it for them, but we don't return the payload in, in the proper way. And so, the, this call never gets scheduled, and so we don't follow up with them.
- 8:51
So, these kinds of things needed to be fixed right away. But before we did that, uh, we asked the last question. Is there anything that we can do in order to prevent a retrain?
- 9:02
Can we have some kind of a band-aid fix to get out there so we don't have to go through a whole week-long process, uh, for one or two issues?
- 9:11
And so, we, we ranked our own bugs, um, based on how much customer pain we could tolerate at the moment. Um, so not a great situation to be in with a production system.
- 9:23
This led to what I've come to call the calcification tax. Uh, the more we used the model, the more rigid everything became. This manifested in a couple different ways.
- 9:35
First, we were locked into our model. You remember when I said that, uh, fine-tuning would give us, uh, more freedom in what model we did? That was not the case.
- 9:47
Um, within providers, there's nuance between one model version to another, and so that changes the, the training data that you need to provide it. Um, across model providers, uh, it's extremely different.
- 10:02
The structure of the data you need to pass to it could be different, the amount of the training data to get good results, the way to interact with the training interface.
- 10:13
All of this caused a lot of complexity, and so it was just too costly for us to switch. And so, um, to-- we kept it the same model for consistency because we already had a lot to do with, uh, with each retraining process, and we couldn't afford to s- uh, upgrade the model.
- 10:34
So, uh, the other way that this locked in was architecture. Uh, we built this app in, uh, late 2024, uh, when workflows were kind of the, um, gold standard if you wanted good, uh, production results.
- 10:52
And, uh, the AI world moves very fast, and we couldn't adapt to that because we were so locked into this, just trying to keep it running, and we couldn't take advantage of the new architectures, um, and, and improve performance that way.
- 11:11
So earlier this year, I had an aha moment. Um, we started using Claude Code for our coding tasks, and I noticed that we never needed to change the model depending on what task we were using.
- 11:27
Um, we just changed the skill, the resources that we passed it, the context. Um, you drop in the better, better context, you get better results. And I thought, "Why can't we do this with our messaging app?"
- 11:43
Um, this was obviously difficult for me to admit because I was the champion for fine-tuning. And, uh, luckily, we were able to piggyback on a project that was already happening.
- 11:55
Um, and so we migrated our workflow approach to a series of skills, tools, and resources that the skills could, could load into or load up, um, and get that context.
- 12:09
And so we pushed this as one of our first production tests of our, our new agentic framework that, that was being built already.
- 12:18
Now, uh, I want to compare the process before and after our rebuild. Uh, before, we already went through the, kind of the training cycle, but there was this triage cycle beforehand where we needed to make sure that we had reached a critical mass of problems before we would even s- attempt to, uh, fine-tune again to improve everything.
- 12:43
Like I said, this took about a week, so it was a long process, costly. Uh, after the rebuild, um, it was a simple process of you find a problem, you adjust the sym- system prompt or the skill that was affected.
- 13:00
We validated performance on a curated set that we had been collecting over the time that this was in production. We iterate a few times, and then we deploy that simply by uploading MD files to an S3 bucket.
- 13:14
Um, this whole process from discovering a problem to deploying the fix, we reduced down to less than an hour. So it extremely improved all of this, and we could be far more reactive, give our, our customers way better performance or better experience there.
- 13:34
Now, I'll be honest, it did cost us a little bit more per message. We were using better models, um, so the API costs were a little higher. But
- 13:46
accuracy went way up. I said before that accuracy was the key to, to getting all of this right, um, and we did that. Accuracy, uh, was far better with this than it ever was with fine-tuning.
- 14:00
Um, next, like I said, we reduced our, uh, our fix process from days down to minutes.
- 14:09
Next, we were able to unfreeze our model and finally get that freedom from a vendor that we never had with fine-tuning. Um, the-- Our agentic framework was built, uh, model-agnostic, so we could use OpenAI, we can use, uh, Anthropic, we can use any other model that we want.
- 14:27
The important part is the context that we're providing to that model. And then lastly, while it cost us a little more per message, the total cost went down because we were spending far less time trying to keep it up and running and fine-tuning to, uh, to keep it working properly.
- 14:49
So before you fine-tune, I'd ask you, can you cross your reason off of this list? So I thought we would get better accuracy. Uh, the rebuild beat the fine-tune model.
- 15:03
Um, I thought we would get lower cost at the volume we were doing. Um, I was looking at the wrong costs. We, we paid more per message, but the total cost ended up going down with our rebuild.
- 15:15
Lower latency, we, we did see marginal gains on the- these smaller models, but they were so small that in practice it really didn't make any difference.
- 15:26
And then maybe you've got a narrow or structured task. Our textbook case still became tech debt. Uh, and lastly, vendor control. It's not as simple as just plugging the data in.
- 15:40
The other two situations where you, you might have privacy and data control, or you need some offsign- offline solution, I would say this, these are the situations where a fine-tuned model may be useful, but you need to be cautious.
- 15:57
There are other solutions out there, um, but, um, you need to make sure that it's not, uh, not causing issues in the long run. So finally, fine-tune only when you literally cannot call a frontier model, and even then, your decision still has to beat the, the tax.
- 16:18
Thank you. [audience applauding] [outro music]