Skip to content

Architecture

KD's packages form a layered structure in which each layer imports only the layers below it. The order is a contract checked by import-linter on every push, so a new module that is not placed in a layer, or an import that crosses the order without being declared, fails the build. The figure below shows the layers, the algorithm packages, the three conventions that cross several layers, and the order in which one call to Model.fit passes through them.

Open the full-size architecture diagram

The preview below shows the full diagram. Open the SVG to zoom in on package names, declarations and execution steps.

Layered component view of KD: the import layers from the leaf packages to the batch harness, the algorithm plugin packages, three cross-cutting conventions, and the execution order of one fit
Bands are import layers, upper layers import lower ones, with a small number of declared exceptions. Numbers give the execution order of one fit. A dot marks a layer that takes part in the convention named above the column. Open the figure in a new tab for full size.

Layers

Algorithm packages are independent of one another. Import-linter checks both the package layers and the registered algorithm packages; a newly added module must be assigned to the appropriate layer. Algorithms import visualization descriptors to declare their diagnostic panels, so the figure layer sits below the algorithm packages. Declared exceptions are shown on the diagram.

From the bottom up:

  • Leaf packages. kd.models holds the neural field model and its trainer. kd.llm holds the provider protocol, an OpenAI-compatible client, budget accounting and a request tape for replay. Neither imports any other part of KD.
  • kd.data. The dataset types, PDEDataset for fields on axes and TabularDataset for a feature matrix with a target, together with the file loaders, the dataset catalog, the derivative providers, synthetic generators, noise and subsampling. Derivatives are computed on request and never stored in a dataset.
  • kd.core. The term notation and its operator registry, the executor that turns a term string into a column of numbers, the evaluator that assembles the design matrix and calls a linear solver, the scores, the numerical guards, the equation types with their signatures and sketches, and the platform builder that resolves the left-hand side and assembles the components an algorithm declared it needs.
  • kd.viz. The figure engine, the individual plots and the HTML report. The engine reads the score metadata carried by a result and the figure descriptors each algorithm publishes through the VizExtension protocol.
  • kd.search. The framework half holds the SearchAlgorithm contract, the runner that drives prepare and then propose, evaluate and update per iteration, the per-iteration recorder, checkpoint writing with its manifest, and the result assembly. The plugin half holds one package per algorithm. Each package owns its search procedure, its scoring and its final fit, and carries its own figure extension; SGA-PDE and PySINDy also carry a sketch backend.
  • kd.api, kd.evaluate, kd.inspect. The Model facade, term evaluation without a search, equation verification, cross-algorithm comparison, dataset inspection and preview.
  • kd.harness. Batch execution: a plan of runs executed serially, an evidence store with hashed records, merging of stores written by separate batches, and consensus across runs.

Conventions that cross layers

Three conventions apply in several layers at once and are drawn as columns beside the bands.

  • Expression bus. An equation that crosses a package boundary is written as term strings such as mul(u, u_x). Each algorithm keeps its own representation inside its package, the expression tree of SGA-PDE, the token sequence of DISCOVER, the vocabulary of EqGPT, the SymPy expression of PySR, and converts on the way out. Checkpoints are the exception: a plugin's saved state keeps its native form, since it is read back only by the same plugin. See Equation representation.
  • Capability declarations. Each algorithm declares, as data on its class, the equation forms and data layouts of each mode, the source of its derivatives, the name and direction of its score, whether it answers in one shot, which parameters survive a resume, and how far each mode honours a sketch. The facade, the runner, the batch harness, the website generator and the agent controller read the same declaration; the figure engine reads its projection in the result. See Platform and plugins.
  • Checkpoint and manifest. The runner writes the plugin's own state atomically during a run and keeps a manifest of what it wrote. A resume selects an entry from that manifest and validates the stored parameters against the new configuration. See Parameter tiers and resuming.

Execution order of one fit

  1. A dataset is built from a file, a catalog entry or arrays, optionally with noise or subsampling applied.
  2. PlatformBuilder resolves the left-hand side, builds the derivative source the algorithm declared, and assembles the components. A mode that declares no platform derivatives receives neither a derivative provider nor an evaluator; the term executor is still available.
  3. ExperimentRunner calls prepare, then repeats propose, evaluate and update until the iteration budget or the algorithm's own stop condition ends the run, recording each iteration, calling callbacks and writing checkpoints at the configured interval when a directory was given. The algorithm owns the work within each iteration step.
  4. The algorithm builds its final evaluation and the target it was fitted against. The platform does not re-score the winning candidate.
  5. The runner assembles the Equation, when the final evaluation yields one, and the run record.
  6. model.result_ holds the ExperimentResult; model.best_expr_ and model.best_score_ expose the algorithm's expression and objective value.
  7. Reports, verification, comparison, batch aggregation and agent use are separate calls on that result. A fit with a sketch also verifies the sketch before returning.

The algorithms use different parts of the setup and evaluation services. The platform and plugin responsibilities describe their native search, fitting and surrogate components.

Components outside the layer order

  • Agent controller. kd-agent drives a search through a fixed set of verbs, keeps a tree of checkpoints that can be resumed, branched or pruned, and uses only the public API of KD. KD never imports the controller.
  • Website. The parameter tables and specification strips on this site are generated from the capability declarations.
  • External dependencies. PySR runs in a Python worker process that starts its Julia runtime; PySINDy contributes its STLSQ optimizer; LLM4ED reaches a language-model endpoint through kd.llm; the agent controller reaches an OpenAI-compatible or Anthropic endpoint directly; remote datasets and model weights are fetched from the Hugging Face Hub.

Conceptual view

The second figure keeps the same components but groups them by role rather than by import layer. It is the view used when introducing KD.

Conceptual view of KD: inputs, data, algorithm and result in one row, platform services below, the calls made after a fit, and the contracts shared by all algorithms
Inputs flow into a dataset, an algorithm searches it, and a result carries the equation, the score and the run record. Platform services are used as each algorithm's declaration states; reports, verification, batch runs and the agent are separate calls on the result. Open the figure in a new tab for full size.