The model proposes; the code disposes.
How deterministic code turns five years of messy filings into one traceable, verifiable knowledge graph.Compiling five years of filings into one knowledge graph that can’t lie about its sourcesOne of Caterpillar’s three operating segments is called “Energy & Transportation.” When I first compiled…
How deterministic code turns five years of messy filings into one traceable, verifiable knowledge graph.Compiling five years of filings into one knowledge graph that can’t lie about its sourcesOne of Caterpillar’s three operating segments is called “Energy & Transportation.” When I first compiled five years of the company’s filings into a knowledge graph, that single real-world segment came out as thirteen separate entities, scattered across thirteen different types: a Segment here, a Metric there, a Product, a Charge, a Driver. Same name, thirteen ghosts.That is the whole problem with turning documents into structured knowledge, in one example. The same thing shows up in a 10-K paragraph, a slide bullet, a spreadsheet cell, and a spoken sentence on an earnings call, each phrased a little differently, and a naive pipeline treats every phrasing as a new thing. You end up with a graph that looks detailed and is actually just confused.This is a post about the release where I made that stop happening, and the principle underneath it: the model proposes, the code disposes.What the thing isSmoothie is an open-source compiler for documents. You point it at a folder of mixed files plus a short brief of what you care about, and it produces a single typed, grounded, versioned knowledge graph: entities and typed relationships, where every element traces back to the exact span in the exact source it came from.The word “compiler” is doing real work there. The output is not a database you mutate. It is a declared artifact, committed to git on every build, diffable, rollback-able, and independently validated. Same inputs produce the same bytes.The governing rule is a division of labor between the model and the code:The model reads documents and proposes content: it says “this looks like an entity, of roughly this type, related to that one.” Everything that has to be *true* is owned by code. Identity, provenance, types, and the validation gates are all code-owned, and nothing scenario-specific (no company, no corpus, no demo logic) is allowed to live in the code. The model is creative and occasionally wrong. The code is boring and does not negotiate.To prove that boundary actually holds, I ran it on something genuinely hard.The test: five years of Caterpillar, four modalities82 documents. 10-Ks and 10-Qs, investor decks, earnings-call transcripts, and financial spreadsheets, spanning fiscal 2020 through 2025. The extraction stage pulled 5,901 facts out of them.I picked Caterpillar precisely because it is boring and hard: a large industrial company with multiple operating segments, a segment structure that gets reorganized mid-period, and the same numbers restated four different ways across four different kinds of documents. If identity and provenance survive that, they survive most things.The result is one graph where a single real-world thing has a single identity no matter where it was mentioned, and every claim on it points back to a real source:That is what “grounded” means here, concretely. “Energy & Transportation” is not an assertion the graph makes. It is a node backed by 251 facts, and each of those facts carries a receipt to a specific line in a specific filing, cell in a specific spreadsheet, or sentence in a specific transcript. If a fact cannot point to a source, it does not exist in the graph.The identity collapseBack to the thirteen ghosts.The root cause was subtle and worth stating plainly, because it is a trap anyone building this will hit. An entity’s identity was derived from its type plus its name. That is reasonable. But the model, reading the corpus in batches, typed “Energy & Transportation” as a Segment in one batch, a Metric in another, a Driver in a third. Because type was part of the identity key, each inconsistent guess minted a brand new entity. Thirteen batches, thirteen types, thirteen entities for one segment.The fix is a deterministic reconciliation pass that runs before identity is assigned. For each name, it tallies every candidate type the model proposed and the evidence behind each, and elects a single winner: most fact evidence first, then most occurrences, then alphabetical as a final tie-break so the result is fully deterministic. No model call. Every mention of that name then resolves to one entity under the winning type.For “Energy & Transportation,” the Segment reading had 111 facts of evidence against 31, 13, 10, and 1 for the pretenders. It collapses to one entity, correctly typed as a Segment, carrying 32 aliases from 32 different sources across the full five years. And the collapse is reversible: the merged members are kept, not deleted, so any merge can be undone. Across the whole corpus, the count of names split across multiple types went from 20 to zero.The rest of the disciplineThe identity fix was the headline, but the same “code owns the contract” line runs through everything that shipped:Grounding is enforced. The model occasionally emits a fact ID it made up. Every ID it gives is filtered against the real fact set before it is used. Invented references are dropped, and an entity with no surviving grounding fact is dropped entirely rather than emitted ungrounded.Vocabulary gets consolidated. Left alone, the model coins a sprawling near-duplicate vocabulary: 302 relation types on this corpus, 55% of them used exactly once, with families like `affects` / `affected` / `affected_by` / `affected_margin`. A deterministic fold handles the inflectional duplicates, and a gated, cached model pass maps the rest onto a smaller canonical set drawn only from the corpus’s own names (the model cannot invent a new name; if it tries, that mapping is discarded). 302 relation types became 127, 68 entity types became 44, with no loss of meaning.An independent reader re-checks everything. The producer is not trusted. A separate Rust binary re-validates the finished artifact against ten gates, fail-closed: grounding, typing, reference integrity, identity, resolution, and more. The first full-scale run failed with 215 violations. After the fixes, it passes clean, and that pass is checked by code that never saw the producer’s intentions.Non-determinism is pinned down. The only non-deterministic input is the model, so every model call is cached by a hash of its exact inputs. This started as a crash-resilience fix (a laptop went to sleep mid-run and threw away 15 minutes of paid model calls), but the payoff is bigger: after any downstream code change, re-running served all 18 model batches from cache at zero incremental cost, and the artifact is bit-for-bit reproducible.Why this shapeThe reason to build it this way is trust. An LLM reading your documents is genuinely useful and genuinely unreliable, and most tools resolve that tension by asking you to trust the model. This one resolves it by not trusting the model with anything that has to be correct. The model proposes; code assigns every ID, verifies every citation, elects every identity, and an independent validator re-checks the whole thing before it is allowed to be called valid.What you get out the other side is an artifact where the same real-world thing has one identity regardless of which of your documents mentioned it, every claim carries a receipt to its source, and the whole thing is versioned and independently verifiable. Point an agent at it over MCP, and it answers from the graph and shows you the source line, instead of paraphrasing from a pile of chunks and hoping.It is open source and still rough in places. There is a real long tail of rare types the model only ever reads once; it is built from source right now, and I would not call the linking precision solved. But the core claim holds on real data: 82 messy documents in, one validated graph out, and nothing in it that cannot point to where it came from.Repo: github.com/4tyone/smoothieThis story is published on Generative AI. Connect with us on LinkedIn and follow Zeniteq to stay in the loop with the latest AI stories.Subscribe to our newsletter and YouTube channel to stay updated with the latest news and updates on generative AI. Let’s shape the future of AI together!The model proposes; the code disposes. was originally published in Generative AI on Medium, where people are continuing the conversation by highlighting and responding to this story.Source: Generative AI Pub — Published — Category: Image AI