I had Gemini train its own replacement for $9
Recorded: Sept. 17, 2026, 2:08 p.m.
| Original | Summarized |
I had Gemini train its own replacement for $9 — Peter Vijeh← petervijeh.comI had Gemini train its own replacement for $9This article was written with the assistance of AI. If that bothers you, stop reading here. The numbers are real: every score comes from the ten training runs described below, and the full run log is in the linked knife.day write-up.The knife.day write-up, with the full run logI like to cook, and somewhere along the way that turned into an obsession with high-end chef's knives. So I scrape the Reddit threads where people argue about them and pull out every brand, model and steel they mention, to see what is getting bought and argued about.Picking product names out of text is a job called named-entity recognition, and small models have done it for a decade. I was doing it with Gemini 3.1 Pro, one paid API call per comment. Overkill, but it worked: from "picked up a Mazaki in white #2, way better than my old Fibrox" it returned Mazaki as a brand, Fibrox as a model and white #2 as a steel, and nothing else. But the scraper pulls every new comment, so the bill grew with how much people posted, and the only way to cap it was to skip comments.The obvious replacement, an open NER model called GLiNER run zero-shot, cut the cost to nothing and the accuracy to about 0.65 F1 against Gemini's answers. That gap is what the rest of this is about: could Gemini label 4,290 comments once and teach GLiNER to close it?What: Fine-tuned GLiNER large v2.5 (459M) to tag brands, models and materials in Reddit comments, on labels Gemini 3.1 Pro wrote once.Why: Zero-shot GLiNER scored about 0.65 F1 (est.). Gemini scored well and billed every comment for as long as the scraper ran.Approach: Ask Gemini for strings, not offsets. Compute offsets in code. Add comments with no products in them as negatives. Lock a 225-comment validation set before the second run.Problems: Five of ten runs produced no usable model. Three failed on configuration. Two failed on a tensor called words_mask that I filled the way you fill an attention mask.Result: 0.83 F1 against Gemini's labels after 24 minutes on a Tesla T4. $9 of labels, about $2.50 of GPU time, and days of debugging.What I set out to doThe plan had three steps. Have Gemini label a few thousand Reddit comments once, marking every brand, model and steel. Train GLiNER on those labels. Then run GLiNER on my own machine for every comment after that, and stop calling Gemini.Gemini labeled 4,290 comments for $9, or $0.0021 a comment. That means the trained model pays for itself at roughly comment 4,291, as long as later comments are about the same length and it runs on a GPU I already own. The test of success was simple: on 225 comments the model had never seen, how often does it tag the same words Gemini tagged? One catch to keep in mind for every score in this article. Nobody checked Gemini's labels by hand, so the model is graded against Gemini, not against the truth. Where Gemini was wrong, the model gets marked right for copying the mistake and wrong for fixing it.The approachGemini labeled the comments through OpenRouter at temperature 0 in 25 minutes. The prompt decision that mattered most was to never ask the model for character offsets. It counts characters badly and returns spans off by two or three positions. The prompt asks for the exact substring and a label, and TypeScript finds the offsets. If the string is not in the comment, the entity is dropped and logged.// The model returns strings. Code computes the offsets. 1,575 positive (69.6%) 2,029 train 1,720 1,345 842 0.0 0.2 0.4 0.6 0.8 1.0 failed scored best F1 in production ✕ ✕ ✕ ✕ ✕ not 0.800 0.879 0.799 0.832 Runs 1–5 failed outright. The dashed line tracks overall F1 after the word-mask fix. Zero-shot (est.) Fine-tuned 209M Fine-tuned 459M 0.0 0.2 0.4 0.6 0.8 1.0 ~0.65 0.800 0.879 n/a 0.858 0.904 n/a 0.775 0.877 n/a 0.712 0.829 Bigger encoder helps most where the vocabulary is purely domain-specific. |
The work details an approach to automate the extraction of brand, model, and material names from Reddit comments by leveraging a large language model for initial labeling and fine-tuning a smaller Named Entity Recognition model. The initial motivation stemmed from the high cost associated with using an LLM like Gemini for per-comment extraction, leading to a strategy to delegate this task and reduce operational costs. The core methodology involved having Gemini label a large set of comments, effectively costing nine dollars for the labels, which served as the ground truth for training. This labeled dataset was then used to fine-tune an open NER model named GLiNER, which was intended to perform entity tagging on new, unseen comments locally. A critical aspect of the process involved careful prompt design; the author determined that asking the model for exact substrings rather than character offsets was necessary because the latter was prone to errors due to tokenization issues. Technical challenges arose during the training process, particularly concerning the internal structure of GLiNER. The author discovered that a tensor called words_mask, which was often misinterpreted as a standard attention mask, actually functioned as a word index, which necessitated a modification to the training loop to ensure the model correctly utilized positional information. The training phase was fraught with difficulties, as five out of ten experimental runs yielded no usable models due to configuration errors or failures in tensor handling. Debugging revealed that the failure modes were often rooted in the implementation details of the training framework rather than the quality of the labels or the data itself. The author learned that performance was sensitive to data partitioning; locking a validation set before the first run was essential, and simply observing the results on random splits could be misleading. Furthermore, the author found that adjustments to the loss calculation, such as applying a threshold per entity class instead of a global cutoff, significantly improved material recall, demonstrated by boosting the confidence in identifying complex material names. Ultimately, the fine-tuned model demonstrated a strong performance, achieving an F1 score of 0.83 against Gemini's labels on a validation set it had never seen. The performance metrics broke down by entity class, with the model showing a high recall for material specifications. The author concluded that while the process involved significant time spent debugging technical plumbing—specifically managing the input tensors and training configurations—the focus should remain on ensuring the integrity of the code connecting the data and the model. The project successfully developed a system capable of identifying complex product information from unstructured text, validated by its performance on a curated set, and resulting in a system that powers a tracking mechanism for consumer discussions on platforms like Reddit. |