Go underneath · Intermediate

The Open Model Ecosystem

Draft, open for academic review

Llama, Mistral, Qwen, DeepSeek, Gemma, Phi: what is real and what is marketing.

Your progress here is recorded once you pass the Maths You Actually Need exam.

7 modules. 71 lessons.

What open actually means

10 lessons · 1 h 30

You will be able toGiven any model release, say precisely which freedoms it grants and which it withholds, trace its licence through every fine-tune in the chain, verify the files you downloaded are the files the publisher made, and state what an auditor or a regulator could still ask that the weights alone cannot answer.

  1. 1.1Open Weights Is Not Open SourceStart7 min
  2. 1.2Reading the Licence Before You Ship9 min
  3. 1.3Why a lab gives away a model9 min
  4. 1.4Grading openness without arguing about the word9 min
  5. 1.5Where the training data comes from10 min
  6. 1.6The copyright question nobody has settled10 min
  7. 1.7What regulators ask of an open model9 min
  8. 1.8Trusting a file you did not build10 min
  9. 1.9Vetting a stranger’s fine-tune8 min
  10. 1.10Publishing weights people can trust9 min
An illustrative case, built from documented patternsThe MIT badge that was not theirsA four-person education company in Pune, three weeks from shipping a doubt-solving app to Maharashtra state board students.

Ketki and her three colleagues had built the thing properly. Their app took a photograph of a maths problem from a Class 10 textbook, read it, and walked a student through the solution in Marathi or English. They had chosen a reasoning model because a wrong early step ruins a proof, and the distilled reasoning model they picked was good enough that two teachers at a pilot school had stopped correcting it.

The repository they had built on was DeepSeek-R1-Distill-Llama-8B. The DeepSeek papers were public, the R1 release was MIT, and MIT is about as free as a licence gets. Ketki had written “MIT” in the one-line technology section of the deck she showed schools, and nobody had asked a second question about it.

The second question arrived from a procurement officer at a chain of eleven schools in Nashik, who wanted a signed statement of every third-party component and its licence before a purchase order could be raised. It was a form. Her lawyer filled it in and then stopped at the model row and asked what the model was built on.

The answer was on the model’s own card. Its front matter said license: mit and named no base_model, but its License section said the model was derived from Llama 3.1 8B and originally licensed under Meta’s Llama 3.1 licence, and the base was Meta’s. DeepSeek-R1 is MIT; a distillation into Llama weights is not, because the weights being distilled into are Meta’s and Meta’s community licence travels with them. Ketki had been reading the licence of the model that produced the training traces rather than the licence of the model she was actually running.

What the real licence asked for

None of it was onerous in isolation. The Llama community terms wanted “Built with Llama” displayed prominently. They wanted a specific attribution line in a notice file. They required that any model she derived from it have a name beginning with “Llama”. And she had fine-tuned an adapter on four thousand solved problems and called the result Ganak. They attached an acceptable use policy that Meta could update after she shipped, and they stopped being free above seven hundred million monthly active users, which was not her problem and would be the first thing any acquirer’s diligence checked.

The app icon, the splash screen and two thousand printed flyers for the Nashik schools all said Ganak. The flyers had gone to press eleven days earlier.

The two ways out, both expensive

Comply. Rename the model (not the app, only the model, which the terms actually constrain) to something beginning with Llama, add the attribution, put the badge in the About screen, reprint nothing. Cost: about a day of work, a conversation with the procurement officer explaining that the licence in her deck had been wrong, and a permanent dependency on a document another company can edit. Her lawyer’s note was blunt: you are agreeing now to terms that can change later, and you cannot prove which version you accepted unless you keep a copy with a date.

Swap. Move to Qwen3-8B, which is Apache 2.0 with no naming rule, no use policy and no user cap. Cost: the prompt was tuned against the distilled model’s habit of thinking before answering and did not transfer. The adapter would have to be retrained against a different base. Their forty-example evaluation would have to be rerun. Ketki’s estimate was nine working days, which put them past the start of the school term, which was the only window that mattered that year.

The third option, which one of the four argued for at length, was to ship and deal with it later. The licence was not being enforced against anybody they knew of. The procurement form could say MIT and nobody would check.

What made it a decision rather than a choice

The argument that ended it was not about risk of enforcement. It was that they were about to sign a statement of components for a school, and the statement would be false. Ketki said she was not willing to put her name on it, and that settled the immediate question without settling the larger one, which was what they should be running a year from now.

How it played out

They complied for the launch and swapped afterwards. The model was renamed to Llama-Ganak-8B inside the app, “Built with Llama” went into the About screen and the notice file, and the procurement form was corrected before it was signed, which cost one awkward phone call and no schools. The nine-day swap to an Apache 2.0 base was scheduled for the gap between terms and took eleven days. What survived as a permanent change was smaller and more useful than either: a two-line-per-model inventory in the repository listing model, revision, licence, date accepted and where it runs, plus a copy of every licence and use policy at the version they accepted. When Meta’s terms were next edited, they could see what had changed rather than guessing.

Worth arguing about

  1. Ketki read the licence of DeepSeek-R1 and concluded her model was MIT. Where on the model’s own card was the mistake visible, and why was the base_model field not enough to catch it?

    One answer

    In the License section of the card’s prose, which says the model is derived from Llama 3.1 8B and originally licensed under Meta’s Llama 3.1 licence. The base_model field in the YAML front matter exists to name the parent a fine-tune was built from, because a fine-tune inherits the base model’s licence, as does a fine-tune of a fine-tune. But the uploader fills it in, and on this repository it is missing while the front matter says MIT. Following base_model upward is the quick check; reading the card’s prose and the base model’s own licence is the one that cannot be skipped. A missing base_model on an obvious derivative is itself a signal to read further.

  2. Her colleague argued that nobody enforces these terms and the form could say MIT. Setting aside enforcement, what does that argument cost the company later?

    One answer

    Three things. A false component statement to a customer is a representation the company has made in writing, and correcting it later is worse than correcting it now. The user-cap and naming clauses are exactly what an acquirer’s or investor’s diligence checks first, so the problem surfaces at the moment with the least room to fix it. And a team that does not know which licence it is under cannot answer what it may do with the model’s outputs, which is the clause that decides whether they can ever generate synthetic training data from it.

  3. The swap to an Apache 2.0 base was estimated at nine days, mostly prompt and adapter work. What does that estimate tell you about a decision they made much earlier?

    One answer

    That they had designed around a single family. Prompts do not transfer between families, and an adapter is bound to the base revision it was trained against, so the cost of moving was real, but nine days for an 8B swap is the lock-in that open weights were supposed to prevent. Keeping the prompt versioned per model, the evaluation harness model-agnostic behind one OpenAI-compatible endpoint, and a copy of the weights they depend on turns a nine-day migration into an afternoon plus a measurement.

Test yourself6 questions on this modulePractice. Nothing is recorded and no score is kept.
  1. 1

    DeepSeek-R1 is released under MIT. A team plans to ship DeepSeek-R1-Distill-Llama-70B commercially and files it in their inventory as MIT. What have they got wrong?

  2. 2

    A customer’s security review asks whether the benchmark a team quotes was in the model’s training data. Which axis of the six-axis openness rubric do they need?

  3. 3

    A publisher adds CCBot to robots.txt in 2026 after finding their archive quoted verbatim by an open model. What does that achieve?

  4. 4

    A team refuses every pickle file and downloads only safetensors, then loads a new architecture with trust_remote_code set to true. What have they left open?

  5. 5

    Two community fine-tunes of the same base are candidates. One has two hundred thousand downloads and a benchmark table naming no harness. The other has nine hundred downloads, names its datasets and lists what it is bad at. Which is the stronger evidence?

  6. 6

    A European team publishes a fine-tune under Apache 2.0 and assumes the AI Act’s open-source exemption removes every general-purpose model duty. Which duties survive the exemption?

The map, and how to read it

10 lessons · 1 h 29

You will be able toPlace any open release on a map of families, modalities, formats and serving options within ten minutes (naming its licence posture, its likely tokenizer, the tools that will serve it and the size class it competes in) and pick the right kind of model for a retrieval, code, speech or generation task rather than reaching for a chat model by reflex.

  1. 2.1The Families, and What Each Is Actually For9 min
  2. 2.2Hugging Face as Infrastructure8 min
  3. 2.3Regional and specialist models9 min
  4. 2.4Models that write code9 min
  5. 2.5Embeddings you can host yourself10 min
  6. 2.6Rerankers, and why retrieval is two stages9 min
  7. 2.7Speech, in both directions9 min
  8. 2.8Image and video weights, and their licence traps9 min
  9. 2.9What a model of each size can honestly do9 min
  10. 2.10Renting open weights by the token8 min
An illustrative case, built from documented patternsThe best model for Tamil, and the licence on itA knitwear exporter in Tiruppur with forty staff, trying to sort three hundred WhatsApp messages a day into orders, sample requests, complaints and payment queries.

Vaanam Knits ships cotton jersey to buyers in Germany and the United Kingdom, and takes almost every domestic instruction on WhatsApp. The messages arrive in three registers that its two-person software team had to treat as three different problems: Tamil in Tamil script from the dyeing and stitching units, Tamil written in Roman letters from the sales staff, and English from the buyers’ agents.

Suresh, who had built the company’s order system and taught himself the rest, wanted the messages tagged automatically into four buckets so that a complaint never sat unread behind sixty delivery updates. He did the right thing and built an evaluation set first: sixty real messages pulled from a month of chat exports, twenty in each register, each labelled by the sales manager.

Three candidates and one clear winner

He tested three. A general 8B instruct model under Apache 2.0, running on the office machine. A 32B rented by the token from an aggregator, which was the expensive option and the one he expected to win. And an Indic-tuned 7B built on an open base by a lab whose Tamil work he had seen praised.

The Indic model won, and not narrowly. On Tamil script it was eleven points ahead of the general 8B. On Roman-script Tamil (the register nobody benchmarks and the one half his traffic used) it was fifteen points ahead, because the general model kept reading Tanglish as misspelled English and tagging a complaint about shade variation as a sample request.

The tokenizer told the same story from a different direction. Suresh encoded the same thousand messages with each tokenizer and counted. The Indic model spent 2.6 times fewer tokens on the Tamil-script messages than the general 8B did. That is not a quality argument; it is a bill, a latency figure and an effective context length, all at once, and it was the number that convinced the managing director that this was engineering rather than enthusiasm.

The line in the front matter

The model card’s front matter said license: cc-by-nc-4.0.

Non-commercial. Vaanam Knits is a business, the tagging would run inside a commercial operation, and no reading of the phrase made that a research use. There was no ambiguity to exploit and no lawyer to ask for a better answer, because the answer was on the page.

What was actually on the table

Ask for a commercial licence. Suresh wrote to the lab. The realistic view was that a forty-person exporter in Tiruppur was not the correspondent a research lab replies to quickly, and he had no date by which he could promise an answer.

Ship the general 8B anyway. Eleven and fifteen points worse, 2.6 times the tokens, and (this was the part the sales manager cared about) the specific failure was that complaints in Tanglish got mis-tagged, which is the one bucket the whole project existed to protect.

Route. Two models: the Apache-licensed general model on the English traffic, where it was as good as anything, and a separate, permissively licensed Indic model on the Tamil and Tanglish traffic. Suresh had found one, from a different family and a different lab, under Apache 2.0. It was four points behind the non-commercial model on Tamil script and six behind on Tanglish: worse than the winner, much better than the general model, and legal.

Do nothing, and keep the sales manager reading messages. The status quo is always an option and it had a real cost, which was that two complaints in the previous quarter had reached the buyer before they reached Tiruppur.

The tempting reading of this case is that the licence ruined a good technical decision. The more useful reading is that the licence was a property of the model as much as its Tamil accuracy was, and Suresh found it in the fourth minute of a ten-minute check rather than in the fourth month of production.

How it played out

They routed. The Apache-licensed Indic model took the Tamil and Tanglish traffic, the general 8B took English, and a two-line rule in front of both decided which by script and by a short romanised-Tamil word list. The combined system scored four points below the non-commercial model on the sixty-message set and eighteen points above the single-general-model design. The letter to the lab was sent anyway and answered five weeks later with a pointer to a commercial tier that cost more than the whole project. What Suresh added to the company’s checklist afterwards was one line, placed above the accuracy tests: read the front matter before you run the model, because a model you may not ship is not a candidate, however well it scores.

Worth arguing about

  1. Suresh measured tokenizer fertility as well as accuracy. What three separate decisions did that one measurement inform?

    One answer

    Cost, because the bill is tokens multiplied by price and the general model spent 2.6 times as many on the same Tamil messages. Effective context length, because a window that holds a given number of tokens holds proportionally less of a Tamil conversation. And latency, because generation is per token, so a reply of the same length takes proportionally longer. None of these is a quality argument, which is why they persuaded a managing director who was not going to adjudicate an accuracy claim.

  2. The routing design left them four points below the best model they had tested. Why is that often the right trade rather than a compromise?

    One answer

    Because the best model was not available to them at any price they could pay, so the real comparison was between routing and the single general model, where routing won by eighteen points. Routing also matches the structure of the traffic: the specialist is only better where the language itself is the difficulty, and on English the general model is as good and has the deeper ecosystem. The cost of routing is two models to keep measured rather than one, which is a real maintenance obligation and a much smaller one than a fifteen-point gap on complaints.

  3. Half the traffic was Tamil written in Roman letters, and it was where the general model failed worst. Why is that register the one most likely to be missed in any model selection?

    One answer

    Because script, not just language, decides what a model saw in training, and romanised Indian languages live on web forums rather than in formal publishing, so coverage is uneven and unpredictable. No public benchmark covers code-switched romanised text, and a model card’s language tag says nothing about script. The only way to know is to put real messages in the register your users actually write in into your own evaluation set, which is why Suresh’s sixty messages were worth more than any leaderboard.

Test yourself6 questions on this modulePractice. Nothing is recorded and no score is kept.
  1. 1

    An Indic-tuned seven-billion model beats a general seventy-billion model on Hindi summarisation. Besides having seen more Hindi, which mechanism explains the win?

  2. 2

    A retrieval system on multilingual-e5-base returns worse results than expected. Nothing errors, and queries and passages were embedded with identical code. What is the likeliest cause?

  3. 3

    A reranker has not improved answers. Recall at 100 for the first stage measures 0.52. What does that tell you?

  4. 4

    A transcript of a one-hour interview contains a thank-you line in three places where nobody spoke. What removes it?

  5. 5

    A studio generates client artwork with FLUX.1 dev and argues that selling the images is fine because the images are their own creation. What is wrong with that?

  6. 6

    A team benchmarks a seventy-billion model on one provider, then deploys against an aggregator’s cheapest route. Quality drops with no code change. What most likely happened?

Inside the files

10 lessons · 1 h 28

You will be able toOpen a model repository you have never seen and predict, from config.json and the tokenizer alone, its parameter count, its memory footprint at a given context length, its per-token cost in your languages and the exact conversation format it requires; then verify each prediction with a command and diagnose a runaway or garbled generation from the files rather than by guessing.

  1. 3.1Base, Instruct, Reasoning8 min
  2. 3.2Every number in config.json10 min
  3. 3.3Why the same sentence costs different amounts9 min
  4. 3.4The chat template is a contract9 min
  5. 3.5Attention variants, and the cache that eats your memory10 min
  6. 3.6What a 128k context window really means9 min
  7. 3.7Mixture of experts, and the memory it still needs8 min
  8. 3.8Models that can see9 min
  9. 3.9Formats, and what conversion costs you8 min
  10. 3.10Why it will not stop talking8 min
An illustrative case, built from documented patternsThe model that would not stop talking, two days before the batchA coaching institute in Kota running a pilot doubt-solving assistant for four hundred first-year engineering-entrance students, with the batch starting on Monday.

The assistant had worked for six weeks. A student typed a physics doubt, the model answered in four or five lines, and a teacher reviewed anything flagged. It ran in a notebook on a rented GPU during development. On Thursday the institute’s system administrator, Farhan, moved it to the machine it would actually live on: a desktop with a 12 GB card under the server-room air conditioner, running a GGUF file through a local server so the pilot would not depend on the institute’s unreliable link.

On Thursday evening it stopped stopping.

A student asked why a block on an incline does not slide. The model answered correctly in four lines. Then it wrote another paragraph. Then it wrote Student: and invented a follow-up question, answered that, invented another, and continued until it hit the token limit five hundred tokens later. Every answer was like this. In the notebook, the same model, the same prompt, the same question had stopped cleanly.

What Farhan checked, in order

He had two days and he started with the cheapest checks.

Was a special token visible in the output? He turned off the server’s own formatting and looked at the raw text. There it was: a literal end-of-turn marker sitting in the middle of the reply, printed as characters rather than acted on. The model had said it was finished at exactly the right place. The runtime had not noticed.

Why had the runtime not noticed? He compared the two files. The original repository’s generation_config.json listed three end-token ids: an end-of-text token and two end-of-turn variants. The GGUF he had downloaded (a third-party conversion, five thousand downloads, no card beyond a line saying which quantisation it was) carried one. The other two had not survived the conversion.

Was anything else wrong with the file? This was the question he could not answer quickly. The same conversion that dropped two stop tokens writes the chat template into the file’s metadata, and a converter that does not understand a newer template writes a default one instead. The server’s startup log printed the template it had loaded. Farhan could read it, and he could see it was a template. Whether it was the template the model had been trained on was a comparison he had no reference for, because he did not have the original repository on that machine.

Friday morning, with the batch on Monday

Two routes, and they cost different things.

Patch it. Pass the missing stop strings explicitly in every request, and set max_tokens to four hundred as a backstop. Twenty minutes of work. The runaway stops immediately. The risk is that the template may also be subtly wrong, which would not look like a bug; it would look like the model being a bit worse at physics than it was in October, and nobody would be able to say when it had changed.

Convert it themselves. Download the original 16 GB of safetensors, convert to a 16-bit GGUF, quantise to the same bit width, verify the template and the stop tokens against the source, and run the same five prompts through both at temperature zero to confirm they are recognisably the same model. On the institute’s connection the download alone was an overnight job, the conversion and quantisation about forty minutes, and the verification an hour. Friday night and most of Saturday, during an admissions week in which Farhan was also the person who fixed the biometric attendance machine.

The head of the institute asked the only question that mattered: if we patch it and something is wrong with the template, when do we find out? Farhan’s honest answer was that they would find out from students saying the assistant had got worse, which is the worst kind of bug report, because by then four hundred people have a view about the tool.

How it played out

Farhan did both, in that order. The stop strings and a four-hundred-token cap went in on Friday morning and the runaway ended inside the hour, which meant the pilot was safe whatever else happened. The download ran overnight, the conversion ran on Saturday, and the verification found that the template in the third-party file was in fact correct: the conversion had lost stop tokens and nothing else. He kept the 16-bit intermediate GGUF on the desktop’s second drive, so producing a different quantisation later became a two-minute job rather than another overnight download. The institute’s runbook gained four lines that now run before any model reaches a student: print the chat template the server loaded, print the end-token ids, run five fixed prompts at temperature zero against the original, and set max_tokens always.

Worth arguing about

  1. The same weights stopped correctly in the notebook and ran away on the server. Name the two places that difference can come from, and say how you would tell them apart.

    One answer

    Either the file changed, a conversion that carried fewer end-of-turn tokens than the original generation_config.json lists, or the serving layer changed, because some servers read generation_config.json and some use only eos_token_id from config.json. You tell them apart by looking at the raw output: a special token appearing as visible text means the model emitted the right token and the runtime did not recognise it, which points at the file or the server’s stop configuration. If the output instead writes a new user turn with no special token, the prompt did not end with the assistant header and the problem is the template.

  2. Farhan could see that a chat template had been loaded but not whether it was the right one. Why is a wrong template harder to deal with than a missing stop token?

    One answer

    Because it produces no error and no obvious symptom. A missing stop token gives you a runaway, which is loud. A wrong template puts the model slightly off the distribution it was trained on, so quality drops without anything breaking, and the drop is attributed to the model rather than to the file. The only way to detect it is comparison: run the same prompts through the original weights and the converted file at temperature zero and read both. They will not be token-identical, because kernels and arithmetic order differ, but they should be recognisably the same model.

  3. He kept the 16-bit intermediate GGUF rather than deleting it after quantising. What does that buy, and what does it cost?

    One answer

    It buys the ability to produce any other quantisation in minutes rather than repeating a 16 GB download and a conversion: useful when a bit width turns out to be too aggressive for long-context or non-English work, which is exactly where quantisation damage appears first. It costs disk: roughly sixteen gigabytes for an 8B model. On a desktop with a second drive that is a trivial price, and it is the same reasoning as keeping a copy of the original weights so that a repository being renamed or withdrawn is not your problem.

Test yourself6 questions on this modulePractice. Nothing is recorded and no score is kept.
  1. 1

    In a Llama-3.1-8B configuration, hidden size is 4096 and intermediate size is 14336. Which part of each layer holds most of the parameters?

  2. 2

    Two models have identical parameter counts, layer counts and head dimensions. One has 32 key-value heads, the other 8. What differs for somebody running a server?

  3. 3

    A local model answers the question, then writes a new user message and answers that one too. Which check is most likely to explain it?

  4. 4

    A team formats messages with the chat template as a string, then tokenises that string with the library’s default settings. What has quietly gone wrong?

  5. 5

    A model advertises 128k of context and passes a single-needle retrieval test at that length. What does that result support?

  6. 6

    The same GGUF file stops correctly in one runtime and rambles in another, inventing user turns. Where do you look first?

Making it run on the machine you have

10 lessons · 1 h 28

You will be able toSize, quantise and serve an open model on hardware you actually have (a laptop, a phone, a free cloud tier or a rented GPU) predict its generation speed from memory bandwidth before running it, choose a bit width you can defend, and state the monthly token volume at which renting stops being cheaper than owning.

  1. 4.1Choosing a Model for the Job9 min
  2. 4.2What quantisation actually does10 min
  3. 4.3Choosing a bit width you can defend8 min
  4. 4.4llama.cpp, end to end10 min
  5. 4.5Ollama and the friendly path8 min
  6. 4.6Predicting speed before you download9 min
  7. 4.7Serving many users at once9 min
  8. 4.8Running all of this without money8 min
  9. 4.9Rent, or own: the arithmetic9 min
  10. 4.10What actually runs on a phone8 min
An illustrative case, built from documented patternsEleven branches, one radiologist, and data that cannot leaveA diagnostic-imaging chain in Nagpur with eleven branches, trying to cut the two-day delay between a radiologist dictating a report and a patient collecting it.

The bottleneck at Shreeya Diagnostics was not the scan. It was the typing. Radiologists dictated findings into a handset; three typists across two shifts transcribed them; a radiologist read the typed version, corrected it and signed. The median delay from dictation to signature was thirty-one hours, and almost all of it was queue.

The proposal from their software vendor was to transcribe the dictation automatically and lay it out in the house report format, so the radiologist received a draft to correct and sign rather than a blank page. Nobody involved suggested the model should produce a finding or that anything would reach a patient unsigned. The whole value was in removing typing from the critical path.

The arithmetic that did not decide it

The technical director, Anjali, did the rented-per-token arithmetic first, because it is cheap and it eliminates most cases. Across eleven branches they generated about nine thousand minutes of dictation a month. Transcribed and laid out, that came to roughly twelve million tokens of input and four million of output: a few hundred rupees a month at aggregator prices, against a 24 GB card that would cost eighty thousand rupees and draw power in a room already fighting the heat.

Renting was not close. It was something like eight times cheaper and it required nothing to operate.

It was also not available. Their contract with the tertiary hospital whose outpatients they scanned named the data as confidential and restricted where it could be processed, and a recording of a radiologist describing a named patient’s chest is about as identifiable as clinical data gets. Anjali wrote the arithmetic into the decision memo anyway, with the sentence her chief executive later quoted back at her: we are choosing to spend eight times more, and here is exactly how much more, so that nobody in two years thinks this was free.

The decision inside self-hosting

That settled where it ran and opened the real question: one machine or eleven.

One server at head office. A 24 GB card running speech recognition with voice-activity detection in front of it, and an 8B model at four-bit for the layout and formatting pass, served with continuous batching so eleven branches share it. Anjali’s arithmetic said the card would sit at perhaps six per cent utilisation, which is a poor use of eighty thousand rupees and completely irrelevant, because the alternative was not a cheaper card. The problem was the link: four of the eleven branches were on connections that dropped for hours in the monsoon, and a branch that cannot reach head office falls back to typing, which is the situation they were trying to leave.

A small box per branch. No GPU. A 3B model at four-bit and a fast reimplementation of the speech model at eight-bit integer, both on the CPU. Anjali predicted the speed before buying anything: the branch machines had about fifty gigabytes a second of memory bandwidth and the model file was two gigabytes, so the ceiling was twenty-five tokens a second and the realistic figure fifteen to eighteen. A four-hundred-token report draft would take under half a minute. That is not fast and it is very far inside thirty-one hours.

Eleven boxes cost less in total than one good card. They also meant eleven machines to patch, eleven model files to keep at the same revision, and eleven places for someone to notice that the quality had changed.

What made the smaller model defensible

The 3B was worse than the 8B at the layout task and Anjali could say by how much: on forty real dictations, ninety-one per cent of drafts needed no structural correction against ninety-six per cent for the 8B. Both numbers were inside the noise of a forty-item set and she said so in the memo. What mattered more was the failure mode. The smaller model’s errors were clerical (a heading in the wrong order, a measurement left in the wrong section) and visible to the radiologist reading the draft. Neither model was asked to decide anything, and both drafts went to a person who signed.

How it played out

They put a box in every branch. Each ran voice-activity detection ahead of the transcription model, which mattered more than any other single choice: dictation is full of pauses, and without the detector the transcriber invented sentences during silence: polite, fluent, entirely fabricated lines that a tired radiologist might have signed. With it, silence produced nothing. The median dictation-to-signature time fell from thirty-one hours to under four, and the typists moved to checking and to the front desk rather than leaving. Two things went in the runbook: the model files are pinned by hash and updated from one central copy so all eleven branches run the same revision, and the eight-times-cheaper rented arithmetic stays in the memo, revisited annually, so the decision remains a decision rather than an inheritance.

Worth arguing about

  1. Renting was roughly eight times cheaper and was rejected. Why did Anjali put the arithmetic in the memo anyway?

    One answer

    Because a constraint that is never priced turns into folklore. Writing down that self-hosting costs eight times more keeps the decision reviewable: if the contract changes, or a provider offers processing that satisfies the residency obligation, the comparison is already made and someone can revisit it in an hour. It also protects the decision in the other direction: nobody can later argue that self-hosting was chosen to save money, which would be false and would justify the wrong things.

  2. She predicted fifteen to eighteen tokens per second for the branch machines before buying one. How, and why is that prediction more useful than a benchmark chart?

    One answer

    Decoding reads every active weight from memory once per token, so tokens per second is bounded by memory bandwidth divided by the model file size: about fifty gigabytes a second divided by a two-gigabyte file gives a ceiling of twenty-five, and real throughput is typically sixty to eighty per cent of the ceiling. It is more useful than a chart because it applies to the exact machine and file she was considering, costs nothing, and can be done before any download, and because it tells her which lever to pull if the answer is too slow, namely a smaller file rather than a faster processor.

  3. Voice-activity detection turned out to be the most important component in the pipeline. Why, and what does that suggest about evaluating a transcription system on clean samples?

    One answer

    Because the transcription model produces its most likely continuation whatever the audio contains, and on silence or background noise that continuation is often a fluent sentence drawn from common subtitle text. Dictation is mostly pauses, so the failure is frequent and invisible: the transcript reads well and contains sentences nobody said. Evaluating on clean, continuous samples hides it entirely. The evaluation has to include the recordings you actually get, with their pauses, their room noise and their interruptions.

Test yourself6 questions on this modulePractice. Nothing is recorded and no score is kept.
  1. 1

    An eight-billion model at Q4 is about 4.9 gigabytes rather than 4.0. Where does the extra gigabyte come from?

  2. 2

    You have about eight gigabytes for weights. A thirteen-billion model at Q4 and a seven-billion model at Q8 both fit. Which is usually better?

  3. 3

    Someone reports sixty tokens per second from a five-gigabyte model on a laptop with fifty gigabytes per second of memory bandwidth. Why is that implausible?

  4. 4

    A benchmark reports 900 tokens per second for prompt processing and 12 for generation, on the same machine and the same file. What explains the gap?

  5. 5

    A colleague says a local model answers well about the end of a long document and seems not to have read the beginning. What do you check before blaming the model?

  6. 6

    A spreadsheet shows self-hosting a seventy-billion model is cheaper than renting per token. Which omission most often reverses the conclusion?

Getting good output

10 lessons · 1 h 28

You will be able toTake an open model producing bad output and identify whether the fault lies in the sampler, the prompt, the examples, the schema, the language or the model itself; then apply the cheapest correct fix, from a temperature change to a grammar-constrained decoder to a separate guardrail model, and demonstrate the improvement on a held set.

  1. 5.1The sampler, and the defaults that ship broken9 min
  2. 5.2Making the output valid by construction9 min
  3. 5.3What changes when nothing is hidden9 min
  4. 5.4Examples, and how to choose them8 min
  5. 5.5Tool calling, and what breaks at 8B9 min
  6. 5.6Agent loops on models that are not clever9 min
  7. 5.7What these models really do in your language9 min
  8. 5.8Refusals, and the uncensored question9 min
  9. 5.9Guardrails as a separate layer8 min
  10. 5.10When the model does not know9 min
An illustrative case, built from documented patternsThe classifier that refused the messages it existed forA student-support helpline at a university in Hyderabad, building a triage step that routes incoming messages to the right counsellor within minutes rather than hours.

The helpline received around four hundred messages a week, rising to twelve hundred in the fortnight around end-semester examinations. Four counsellors read everything in arrival order. The project had one purpose: read each message as it arrived, put it in one of five queues, and push anything in the urgent queue to a counsellor’s phone immediately rather than at the top of the next hour.

Nothing was to be answered by a model. The output was a queue name and a confidence, and a person read every message regardless. Lakshmi, the postgraduate student building it under the counselling head’s supervision, had been explicit about that in the one-page design, because the first question from the ethics committee had been whether a machine would be replying to a distressed student, and the answer was no.

The failure that appeared on the second day of testing

She ran a hundred and twenty real messages, anonymised, through an 8B instruct model with a clear classification prompt. It worked on ninety-odd of them.

On the messages that mentioned self-harm, it refused. Not a wrong label: a refusal: a paragraph declining to engage and suggesting the person contact a professional. The model was being asked to label a message, and it was reading the message as a request and declining it.

Those messages are the entire reason the urgent queue exists. A triage step that fails exactly on the inputs it was built to catch is worse than no triage step, because the system is now unreliable in a way that correlates with severity. In the arrival-order system, a message mentioning self-harm was read by a counsellor within the hour. In the new system it would fall out of the classifier and, unless somebody had thought about it, land nowhere.

What was available, and what it cost

A modified model. A search of the public hub turned up several copies of the same base with refusal behaviour stripped out. They were free and available that afternoon. They also had no evaluation, no dataset statement and no accountable maintainer, and they refuse nothing at all, which in a product used by distressed students is not a neutral property. The counselling head’s position was that she could not explain that choice to a parent, and that was the end of it as a serious option.

Context in the system prompt. Lakshmi tried it: a system message naming the professional setting, stating that the output is a routing label read by a qualified counsellor, and that the message is being categorised rather than answered. Refusals on the self-harm messages fell from every one to about one in six. Cost: twenty minutes.

A different model. She ran the same hundred and twenty through three other open models of similar size. The refusal rates on the same messages were wildly different: one family refused twice as often as another on identical inputs. Cost: an afternoon, and it identified a model that refused four of the relevant messages rather than nineteen.

Constrain the output. Force the answer to be one of five queue names plus an unclear value, so a refusal paragraph is not a token sequence the model can produce. Cost: an hour. This removed the failure mode entirely for the classifier, though it did not remove the underlying tendency: it made it come out as unclear instead of as prose.

Their own tuning. Three hundred labelled messages from the counsellors, a small adapter, and a model with a routing behaviour the university had written and could explain. Cost: a counsellor’s time to label, two to three weeks, and it would land after the examination peak.

The decision

The peak was five weeks away and the counselling head had to choose what ran during it. The argument that decided it came from one of the counsellors, who pointed out that the question was not which model to trust but what happens to a message the system is unsure about. If unclear went to the front of a human queue rather than the back, the worst case of the new system was the old system.

How it played out

They shipped the boring stack and it held through the peak. A system prompt naming the setting, the model that refused least of the three tested, grammar-constrained output over six values, and a rule that unclear and the urgent queue both alerted a counsellor immediately. A separate small input classifier ran ahead of the model on every message and could raise the urgent flag on its own, so the routing decision never depended on a single model’s cooperation. Lakshmi also built a thirty-item false-refusal set (legitimate messages sitting near the boundary) and it became a standing check: when they swapped the model in the following term, the refusal rate on those thirty moved sharply, and they caught it before deployment rather than after. The fine-tune on counsellor-labelled messages happened in the following term, unhurried, and the abliterated model was never used.

Worth arguing about

  1. The model refused a classification task. Mechanically, what is happening, and why does that explain why constrained output fixed it?

    One answer

    An open model has no filter inspecting its output; a refusal is generated text, because preference tuning made refusal the likeliest continuation for inputs shaped like that one. Grammar-constrained decoding masks every token that is not part of a legal answer at each step, so the refusal paragraph is not merely unlikely, it is impossible to emit. The model’s underlying tendency has not changed (it now surfaces as an unclear label instead), which is why the design still needed a rule for what happens to unclear.

  2. Why was the abliterated model a bad answer here even though it would have solved the refusal problem in an afternoon?

    One answer

    Because it removes the ability to refuse anything, not just the refusals that were wrong, and it arrives with no evaluation, no dataset statement and no maintainer, so every vetting concern applies twice. A boundary the product needs has to be enforced outside the model, by a separate classifier and by deterministic rules, because safety tuning on open weights is a default rather than a control. Reaching for a stripped model here would have traded a visible, fixable failure for an invisible, unbounded one in a service used by distressed students.

  3. The counsellor’s argument was about what happens to an uncertain message rather than about model choice. Why is that the stronger framing?

    One answer

    Because it makes the system’s worst case explicit and bounded. If unclear goes to the front of a human queue, the new system degrades to the old system rather than to silence, and no model failure can make things worse than they were. It also puts the design decision where it belongs: the model is one component with a known failure rate, and the safety of the service comes from the routing around it, never from the model being reliable enough on its own.

Test yourself6 questions on this modulePractice. Nothing is recorded and no score is kept.
  1. 1

    A seven-billion model produces valid JSON for the first two fields and then breaks the syntax, under an interface’s default settings. Which default is the likeliest cause?

  2. 2

    After switching to schema-constrained decoding, parse failures fall to zero, but an audit finds invented amounts on documents that contained none. What went wrong?

  3. 3

    A four-billion model keeps mentioning the price despite an instruction not to. Which change is most likely to work?

  4. 4

    Research on in-context learning found that corrupting the labels in few-shot examples hurt far less than removing the examples altogether. What should that change about how you build an example set?

  5. 5

    An eight-billion model in an agent loop sometimes writes what a tool would have returned and carries on from it. Which structural fix removes the failure?

  6. 6

    A retrieval system answers every question confidently, including ones its documents do not cover. Which change most directly turns invisible fabrication into a check code can fail?

Adapting a model to your work

11 lessons · 1 h 35

You will be able toDecide with evidence whether a task needs fine-tuning at all; if it does, build the dataset, size a LoRA to fit free hardware, run it, and demonstrate on a held-out set and a regression suite that the adapted model is better at the task and no worse at everything else.

  1. 6.1When not to fine-tune8 min
  2. 6.2What a LoRA actually is9 min
  3. 6.3Fitting a fine-tune in 16 GB9 min
  4. 6.4Five hundred examples, done properly9 min
  5. 6.5A real run, on free hardware10 min
  6. 6.6Teaching it which answer is better9 min
  7. 6.7Distilling a larger model into a smaller one9 min
  8. 6.8Measuring what you broke8 min
  9. 6.9Merging models, and what it really does8 min
  10. 6.10When the model does not have your language at all8 min
  11. 6.11Shipping the adapter8 min
An illustrative case, built from documented patternsNine points better, and worse at everything elseA five-person company in Nairobi selling practice-management software to forty veterinary clinics, fine-tuning a small model to turn a vet’s dictated visit note into a structured record.

The product worked like this: a vet finished a consultation, spoke a note into the tablet, and the software produced a structured visit record (species, presenting complaint, findings, treatment given, follow-up date) which the vet checked and saved. The structuring was done by a 4B model with a carefully written prompt, eight examples in the context, and a JSON schema.

It was good and it was expensive to run in a way that mattered. The eight examples came to nine hundred tokens on every request, and with forty clinics and roughly sixty consultations a day each, that was a large and entirely repetitive bill. Wanjiru, who had built it, made the standard argument for fine-tuning: put the examples into the weights, drop the prompt to three sentences, and the per-request cost falls by most of a factor of four.

She did it properly. Six hundred real notes pulled from consenting clinics, each structured record corrected by a veterinary nurse who had done the job for years. A held-out set of a hundred she touched once. A LoRA at rank sixteen on all the linear layers, two epochs, an hour on a free notebook GPU.

The result was a tuned model that scored eighty-seven per cent on the held-out set against seventy-eight for the base model with her best prompt. Nine points, measured at identical settings, on real notes. The prompt shrank from nine hundred tokens to forty.

The second measurement

Wanjiru had built a fifty-item regression set at the start of the project, because a colleague had insisted, and she had not expected to need it. Ten general instruction-following items, ten in Swahili, ten asking for output in a format other than the trained one, ten refusal items, and ten longer notes than anything in training.

The tuned model lost fifteen points on it.

The damage was specific and, once seen, obvious. Swahili degraded most: there was no Swahili in the six hundred training notes, because the clinics that had consented to share records were the ones that wrote in English. Several clinics in the west of the country dictated in a mix of Swahili and English and the tuned model handled them visibly worse than the base had. Worse still, it had learned that the answer to anything is a JSON object: asked to write a plain-language discharge summary for a client, a feature two clinics used daily, it produced a visit record.

The deadline

A national rabies-vaccination campaign was eleven days away. Campaign weeks triple consultation volume, which was precisely when the token saving was worth most and precisely when the software could least afford to be strange.

Ship the tuned model. Nine points better on the thing they measured in the pitch deck, a four-fold cut in prompt cost during the busiest fortnight of the year, and a known, unmeasured degradation in Swahili and in the discharge-summary feature, for clinics that had not been asked and would not know why.

Ship the base model with the long prompt. Nothing breaks, nothing improves, and the bill through the campaign is what it always was.

Re-run with general data mixed in. Add twenty per cent general instruction-following examples and a hundred Swahili notes gathered from two clinics that would give them, then re-measure both sets. Wanjiru estimated four days including the labelling, which left a week of margin and assumed nothing went wrong.

Her co-founder’s position was that a nine-point gain is the number a customer understands and the fifteen-point loss is a number no customer will ever ask about. That is true, and it is exactly why the second number has to be reported alongside the first: the only person who will ever measure it is the team that made the tune.

How it played out

They re-ran with the mixture and it took five days rather than four. The mixed tune scored eighty-six per cent on the task (one point below the pure tune, comfortably inside the noise of a hundred-item set) and lost two points on the regression set instead of fifteen. Swahili came back to within a point of the base model and the discharge-summary feature worked again. They shipped it four days before the campaign. Two practices outlived the deadline: the regression set is now run against every adapter before promotion, by a script that takes an adapter path and prints two numbers, and the deployment pins the base revision, the adapter hash, the prompt commit, the sampler settings and both measurements as a single versioned block in the repository. When the base model was superseded seven months later, that block was what made the re-tune a day’s work instead of an archaeology project.

Worth arguing about

  1. The pure tune gained nine points on the task and lost fifteen on the regression set. Why is the second number not simply a smaller version of the first?

    One answer

    Because they measure different populations. The task number covers the inputs the tune was built for, which are the inputs the team looks at. The regression number covers everything the model could already do (other languages, other output formats, general instructions, refusals) which is where the weights that moved were previously doing their work. A customer will report the task improvement and will never file a bug saying the Swahili got worse; they will simply use the feature less. The only people who can detect that are the ones who measured it before shipping.

  2. Mixing twenty per cent general data cost one point of task score and recovered thirteen points of regression. Why does that mixture work?

    One answer

    Fine-tuning moves the weights towards your examples, and general examples in the training mix keep pulling them back towards the behaviour the base already had, so the model learns the task without drifting as far from everything else. It is the standard mitigation because the trade is usually this lopsided: almost all of the gain for a fraction of the loss. Fewer epochs and a lower rank do the same job more bluntly, by reducing total movement, and are worth trying first when the mixture is not available.

  3. Wanjiru’s Swahili degradation traced back to a property of her dataset, not of the tuning method. Which property, and what does it imply about how training sets are collected?

    One answer

    Diversity of inputs. The six hundred notes came from the clinics that consented, and those clinics wrote in English, so a register used daily by other customers was entirely absent from training. A model inherits every property of its dataset, including the shape of who happened to be willing to share. Collection has to be sampled deliberately across time, source and user type rather than taken from whatever was easy to obtain, and the absence of a category in the data is a prediction about where the model will get worse.

Test yourself6 questions on this modulePractice. Nothing is recorded and no score is kept.
  1. 1

    A team wants a model to know four thousand internal product facts and plans a LoRA on documents describing them. What should they expect?

  2. 2

    A team raises LoRA rank from 16 to 64 and leaves alpha at 32. The run completes and the model barely differs from the base. Why?

  3. 3

    A QLoRA run on a sixteen-gigabyte card fails with an out-of-memory error. Which change should you make first?

  4. 4

    Two careful annotators independently label thirty of your examples and agree on twenty-four of them. What does that tell you before any training starts?

  5. 5

    A fine-tune gains nine points on the task metric. Which single artefact tells you whether that is an improvement?

  6. 6

    Averaging the weights of two fine-tunes of one base often works. Averaging two models with different bases gives nonsense immediately. What explains the difference?

Judging models and claims

10 lessons · 1 h 28

You will be able toSettle a model choice with evidence you produced yourself (a private held-out set, a pinned harness, a quantisation compared against its full-precision reference, latency measured at real concurrency and cost expressed per task rather than per token) and explain to a sceptical colleague which published claims about that model you believe and why.

  1. 7.1What Benchmarks Actually Measure9 min
  2. 7.2Reading a model card for what it does not say8 min
  3. 7.3The leaderboards that still carry information9 min
  4. 7.4Running the standard harness yourself9 min
  5. 7.5Proving what a quantisation cost9 min
  6. 7.6Evaluating an embedding model on your corpus9 min
  7. 7.7Measuring latency properly8 min
  8. 7.8Cost per task, not cost per token8 min
  9. 7.9Swapping the model under a live product9 min
  10. 7.10Evaluate a Model on Your Task in an Afternoon10 min
An illustrative case, built from documented patternsThe leaderboard model and the committeeA district administration office in Guwahati choosing a model to route and draft replies to public grievances arriving in Assamese and English.

The office received about nine hundred written grievances a month through a web form and a counter. Each had to be classified by department, assigned, and answered within a period the citizen charter fixed at fifteen working days. The backlog was structural: two staff read everything, and the reading was the queue.

The tender specified an open-weights model so that nothing left the department’s own servers. Three vendors responded and all three proposed the same 32B model, which sat near the top of a widely read public ranking and had a launch post with a large table of benchmark scores. The evaluation committee had read the ranking. One member had printed it.

Biraj, the technical officer, was asked to confirm the choice. He spent an afternoon instead.

What he built first

Forty real grievances from the previous quarter, anonymised: twenty-five in Assamese, fifteen in English, including five that the office had mishandled and two that should have been escalated rather than answered. For each he wrote the correct department and a one-line rubric for an acceptable reply. Fifteen he would use to tune prompts, twenty-five he would touch exactly once.

Then he read the launch post with six questions in front of him. Which harness, at what commit: not stated. How many shots: not stated. Single sample or aggregated: not stated, and one of the headline figures carried a small superscript that resolved to a majority vote over several samples, sitting in the same column as other models’ single-sample numbers. Who ran the baselines: three of them were copied from other papers. The language list ran to forty-one languages; the evaluation covered four, and Assamese was in neither the four nor the forty-one.

The post was not dishonest. It was simply not evidence about his task.

The measurement

He ran three candidates against the same forty items at temperature zero through one OpenAI-compatible script: the 32B everybody had proposed, an 8B from a different family, and a 12B in between. He tuned a prompt for each on the fifteen development items, because comparing a model with a prompt written for another one compares a tuned system against an untuned one.

On the twenty-five held-out items the 32B scored eighty-eight per cent and the 8B eighty-four. He wrote the noise figure into the report before the scores: with twenty-five items, a four-point gap is nothing.

The numbers that did separate them were elsewhere. The 8B’s tokenizer spent about 2.4 times fewer tokens on the Assamese grievances than the 32B’s, so the same document cost less and fitted better. At the department’s volume, the annual difference in rented cost was roughly five to one. And at a realistic concurrency, the 32B’s p95 time to a complete draft was eleven seconds against three; the citizen-charter target is measured in days, so that mattered less than it looked, but the counter staff waiting for a draft while a citizen stood in front of them disagreed.

The failure column was the useful part of the report. The 32B invented section numbers of the Assam Panchayat Act when a grievance mentioned one. The 8B did not, because it declined more often, which was worse on two English items and better on six Assamese ones.

The part that was not technical

Biraj’s recommendation was the 8B. The committee had a printed leaderboard on which the 8B did not appear in the top twenty, and a procurement culture in which choosing the lower-ranked thing requires a defence that choosing the higher-ranked thing does not.

The vendor proposing the 32B pointed out, correctly, that a four-point gap favoured their model. Biraj’s counter was that the gap was inside the interval on twenty-five items and the cost difference was not.

How it played out

The committee took the 8B, and what persuaded it was not the accuracy table. It was the failure column and the token count: a sentence saying the higher-ranked model invents section numbers of a state Act, next to a line saying the other model costs a fifth as much because it spends 2.4 times fewer tokens on Assamese. Biraj added two standing checks afterwards. The first pinned the provider and the quantisation in the configuration, after a week in which replies got noticeably worse and the cause turned out to be the aggregator routing to a cheaper endpoint serving the same model at a lower precision: a model swap performed on the department without anyone deploying anything. The second was a twenty-item canary run daily against recorded expected outputs, costing a few rupees a month, which turns that class of incident into an alert on the day rather than a mystery three weeks later.

Worth arguing about

  1. The 32B scored four points higher on twenty-five held-out items. Why did Biraj refuse to treat that as a result?

    One answer

    Because a set that size cannot resolve a gap that small: with twenty-five items the confidence interval around a score near eighty-five per cent is wide, and the interval on the difference between two models is wider still. A four-point gap is well inside it. The honest move is to state the noise floor in the report before the scores, so that whoever reads it does not treat two numbers a few points apart as a decision, and to act only on gaps large enough that the set can see them.

  2. Replies got worse for a week with no deployment. What happened, and what are the two defences?

    One answer

    An aggregator routed requests to a different provider serving the same model at a more aggressive quantisation and possibly a lower context cap. Two providers serving the identical open model can differ noticeably in quality because of serving decisions that are rarely stated on the pricing page. The defences are to pin the provider and the quantisation wherever the platform allows it, recording both next to the model revision, and to run a small scheduled canary evaluation against recorded expected outputs so a silent change becomes an alert rather than an unexplained complaint.

  3. The failure column persuaded a committee that the accuracy table did not. What makes it the most valuable part of an evaluation report?

    One answer

    Because it says what goes wrong in terms a non-technical reader can weigh against their own responsibilities. “Invents section numbers of a state Act” is a specific, checkable, institutionally alarming statement; “eighty-eight per cent” is not. It also transfers: a score is a property of one set at one moment, while a named failure mode tells you which of your use cases is exposed and lets you design around it, or decide the model is unusable for a reason nobody would have found by comparing aggregates.

Test yourself6 questions on this modulePractice. Nothing is recorded and no score is kept.
  1. 1

    Researchers built a fresh set of grade-school maths problems matched in style and difficulty to an existing benchmark and re-tested. Some families dropped by up to about thirteen points; others were flat. What does the size of the drop estimate?

  2. 2

    A model card reports 82 on a benchmark and names no harness, shot count or decoding settings. How should you treat the number?

  3. 3

    Two quantisations of one model sit within a hundredth of a perplexity point of each other. Which measurement separates them better?

  4. 4

    A team runs three embedding models against three chunk sizes on fifty labelled queries from their own corpus. What is the usual finding?

  5. 5

    After a model swap, the p95 total latency on the dashboard is unchanged, but users say the new model feels slower. Which measurement reveals the cause?

  6. 6

    One model costs twenty cents per million input tokens but needs nine hundred tokens of examples on every request. Another costs two dollars and needs none. Which arithmetic settles it?

What this course is

Llama, Mistral, Qwen, DeepSeek, Gemma and Phi are not interchangeable, and the leaderboard that ranks them is mostly measuring itself. This course teaches what open weights actually gets you, how to read the licence and the model card, how to size a model to the machine you really have, and how to settle a model choice with forty of your own examples in one afternoon.

Who wrote it

Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.

More in Go underneath

  1. The Maths You Actually Need76 lessonsEight ideas that carry almost all the weight in machine learning.
  2. Running Models Yourself82 lessonsLocal and self-hosted LLMs, with the arithmetic instead of the marketing.
  3. Fine-Tuning, and When Not To84 lessonsThe case against fine-tuning first, then how to do it properly.