{"id":41737,"date":"2026-07-13T14:27:04","date_gmt":"2026-07-13T12:27:04","guid":{"rendered":"https:\/\/www.graviton.at\/letterswaplibrary\/i-built-a-gated-dataset-pipeline-for-fine-tuning-small-local-models-heres-how-the-checks-work\/"},"modified":"2026-07-13T14:27:04","modified_gmt":"2026-07-13T12:27:04","slug":"i-built-a-gated-dataset-pipeline-for-fine-tuning-small-local-models-heres-how-the-checks-work","status":"publish","type":"post","link":"https:\/\/www.graviton.at\/letterswaplibrary\/i-built-a-gated-dataset-pipeline-for-fine-tuning-small-local-models-heres-how-the-checks-work\/","title":{"rendered":"I Built A Gated Dataset Pipeline For Fine-tuning Small Local Models, Here&#8217;s How The Checks Work"},"content":{"rendered":"<p><!-- SC_OFF --><\/p>\n<div class=\"md\">\n<p>I&#8217;ve been deep-fine-tuning small local models (BitNet 1.58, Qwen 1.7B\/4B, Gemma-4) into a real on-device assistant with actual tool-calling. The hard part was never the training loop, it&#8217;s the <strong>data<\/strong>. Scraped<\/p>\n<p> ShareGPT dumps collapse small models into formulaic slop and teach tool syntax that doesn&#8217;t match your runtime. And for <strong>full\/deep fine-tuning<\/strong> (not LoRA), bad data is fatal: a small model trained on redundant, single-voice data <em>monocultures<\/em> hard.<\/p>\n<p> So I built a pipeline where <strong>every example has to survive a set of hard gates<\/strong> before it&#8217;s allowed in.<\/p>\n<p>Sharing how it works, because I rarely see people talk about the <em>controls<\/em>, only the volume.<\/p>\n<p> <strong>The core: hand-written &#8220;gold seed&#8221; \u2192 multi-teacher expansion<\/strong><\/p>\n<p> &#8211; The seed is <strong>hand-written<\/strong>, one example at a time, in a <strong>neutral model-agnostic format<\/strong> ({messages, tools}).<\/p>\n<p> &#8211; It&#8217;s rendered <strong>per dialect<\/strong>: ChatML for Qwen\/BitNet, native Gemma tool-call format for Gemma. Same data, correct syntax for each target.<\/p>\n<p> &#8211; From a curated seed it <strong>expands to hundreds of thousands of examples on demand<\/strong> \u2014 volume comes from <strong>multiple teacher models of different families<\/strong> (anti style-collapse), each example tagged with the teacher that produced it. You scale to the size you actually need.<\/p>\n<p> <strong>The gates (this is the value)<\/strong><\/p>\n<p> &#8211; <strong>Anti-formula<\/strong>: blocks over-used openers\/closers at ingest + global frequency caps; any phrase repeated too often <em>anywhere<\/em> gets flagged. This is what stops a full fine-tune from collapsing into one voice.<\/p>\n<p>&#8211; <strong>Semantic dedup (BGE-M3)<\/strong>: near-duplicate detection, not byte-match. On one 9k combinatorial corpus it found <strong>43% near-duplicates<\/strong>, paraphrases expansion would&#8217;ve amplified. Keeps 1 per cluster, with a <strong>coverage<\/strong> <strong>guard<\/strong> that never drops the sole example teaching a capability.<\/p>\n<p>&#8211; <strong>Flow gate<\/strong>: multi-turn tool-call integrity: every assistant tool_call is followed by <em>exactly<\/em> its results, no orphans, no pending calls, ends with a real answer. <\/p>\n<p>&#8211; <strong>Dialect gate<\/strong>: every tool-call is round-tripped through each target model&#8217;s syntax and <strong>rejected if it<\/strong> <strong>doesn&#8217;t parse back identical<\/strong>. train == runtime, guaranteed.<\/p>\n<p> &#8211; <strong>Coverage<\/strong>: every tool taught above threshold; catalog-sync rejects phantom (hallucinated) and untaught tools.<\/p>\n<p>&#8211; <strong>Vision routing<\/strong>: vision examples go <em>only<\/em> to vision-capable models; text-only models never see image context they can&#8217;t use at inference.<\/p>\n<p> &#8211; <strong>Judge routing<\/strong> \u2014 teacher outputs that pass go to SFT; the ones that fail become <strong>KTO negatives<\/strong> (preference signal, not trash).<\/p>\n<p> <strong>Built for deep fine-tuning, at scale<\/strong><\/p>\n<p> The whole point of the gates is that you can <strong>full-fine-tune a small model<\/strong> on this without it collapsing and expand a small hand-verified seed to <strong>100k+ examples<\/strong> while keeping every one of those checks green. <\/p>\n<p>Tool-calling, multi-turn, charts\/tables\/HTML, per-model vision, reasoning, all gate-verified, neutral format so you render to your own dialect.<\/p>\n<p><strong>What it trains<\/strong><\/p>\n<p> <strong>Liara<\/strong> \u2014 a local personal AI with <strong>24 real tools<\/strong> (email, calendar, files, notes, web, weather, charts), english and italian-first + multilingual, that resists prompt-injection while still handling legitimate reasoning-test \/ structured-output prompts (the distinction most classifiers get wrong).<\/p>\n<p> &#8211; Liara app: <a href=\"https:\/\/nothumanallowed.com\/local\"><strong>https:\/\/nothumanallowed.com\/local<\/strong><\/a><\/p>\n<p> &#8211; Tooling \/ code: <a href=\"https:\/\/github.com\/adoslabsproject-gif\/Liara-toolkit\"><strong>https:\/\/github.com\/adoslabsproject-gif\/Liara-toolkit<\/strong><\/a><\/p>\n<\/div>\n<p><!-- SC_ON -->   submitted by   <a href=\"https:\/\/www.reddit.com\/user\/Key-Outcome-2927\"> \/u\/Key-Outcome-2927 <\/a> <br \/> <span><a href=\"https:\/\/www.reddit.com\/r\/datasets\/comments\/1uv8xd6\/i_built_a_gated_dataset_pipeline_for_finetuning\/\">[link]<\/a><\/span>   <span><a href=\"https:\/\/www.reddit.com\/r\/datasets\/comments\/1uv8xd6\/i_built_a_gated_dataset_pipeline_for_finetuning\/\">[comments]<\/a><\/span><\/p><div class='watch-action'><div class='watch-position align-right'><div class='action-like'><a class='lbg-style1 like-41737 jlk' href='javascript:void(0)' data-task='like' data-post_id='41737' data-nonce='9de69db8d5' rel='nofollow'><img class='wti-pixel' src='https:\/\/www.graviton.at\/letterswaplibrary\/wp-content\/plugins\/wti-like-post\/images\/pixel.gif' title='Like' \/><span class='lc-41737 lc'>0<\/span><\/a><\/div><\/div> <div class='status-41737 status align-right'><\/div><\/div><div class='wti-clear'><\/div>","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been deep-fine-tuning small local models (BitNet 1.58, Qwen 1.7B\/4B, Gemma-4) into a real on-device assistant with&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[85],"tags":[],"class_list":["post-41737","post","type-post","status-publish","format-standard","hentry","category-datatards","wpcat-85-id"],"_links":{"self":[{"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/posts\/41737","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/comments?post=41737"}],"version-history":[{"count":0,"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/posts\/41737\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/media?parent=41737"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/categories?post=41737"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.graviton.at\/letterswaplibrary\/wp-json\/wp\/v2\/tags?post=41737"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}