OpenBI Docs Buy

Versions and results

What a notebook saves for a person to approve: model versions (Models) and the results of a plan, a valuation or a network (Results), how their scores are written, their history and checks, and models brought from elsewhere, read and never run.

Models

public static class Models

Model versions for notebooks: save the model a notebook learned (the output of a notebook), import one a data scientist brings, load one to score.

Properties

static string ProjectFolder { get; }
The project folder: the kernel's, or OPENBI_PROJECT.

Methods

static VersionStore Store(string name, string? project = null)
A notebook's versions (a prediction's, or another kind's), in the given project (the studio's) or the notebook's.
static Booster Load(string name, int? version = null)
A version's model: the version given, or else the one in use, or else the newest.
static ModelVersion Save(string name, Booster booster, DaxQuery? features = null, string? key = null, Output? output = null, IEnumerable<object?>? evidence = null, bool keepTrainingData = true, string? note = null, string? scoreAt = null, HeldOut? heldOut = null, Calibrator? calibrator = null, string? label = null)

Saves the model as a new version (a draft): the model, its inputs (the OAX that computes them, when given), how it scores, the evidence, the training rows, the notebook as it ran, and the environment. It never changes after; someone other than its author approves it before use.

  • name: The prediction's name (its folder, PREDICT("name")).
  • booster: The model, as LightGbm.Train made it.
  • features: The OAX step that computes its inputs (with a date parameter for a history): kept, and run when the model scores.
  • key: The column that names each row (the entity's key): its scores' first column.
  • label: The column that names who is scored for a reader, kept with the version: PREDICT gives it right after the key. A column of the features query ("Varenavn"), or a column of the key's table in the model ('Customer'[Name], read by the key when the version scores). Not given: the prediction's definition's entityLabel as it is now, when it is one of those; "" none. A version keeps what it was saved with: one saved without a label never gets one.
  • output: How it scores: a probability with bands and reasons, or a value. From the objective when not given.
  • evidence: What shows it is good: metrics, charts, tables (kept, and shown to whoever approves it).
  • keepTrainingData: Keep the rows it learned from (Parquet, out of git), so it can be retrained bit for bit.
  • note: Why this version (kept with it).
  • scoreAt: OAX for the date the model scores at, in the model (its feature query's date parameter): TODAY() unless given, such as "MAX ( Orders[OrderDate] )" for the latest data. On data that arrives later than today - a monthly snapshot published weeks after the month - TODAY() finds no rows, and PREDICT then fails with that date ("no rows at 2026-10-27 (scoreAt TODAY())"): give the data's latest date. The Versions tab tries the scoring date and shows how many rows it scores before anyone approves the version.
  • heldOut: The model that was checked and the held-out test its metrics were measured on: kept with the version (split train/validation/test), so the Versions tab and model_versions say "metrics on held-out rows". Without it the version says no test was kept apart, and its metrics are as the notebook measured them.
  • calibrator: A calibration of this booster's probabilities (Calibration.Platt or Calibration.Isotonic, learned on its scores of rows it did not learn from): kept with the version, so PREDICT gives each row's calibrated probability - exactly what calibrator.Apply gives here - and bands that. Without it the version scores the model's own probabilities, uncalibrated, and its bands say so.
static ModelVersion SaveForecast(string name, Booster p50, Booster p10, Booster p90, ForecastHistory history, int horizon, Table span, DaxQuery period, string? series = null, string value = "value", IEnumerable<object?>? evidence = null, bool keepTrainingData = true, string? note = null, IReadOnlyDictionary<string, DaxQuery>? regressors = null)

Saves a forecast as a new version (a draft): its three models (the median, model.txt; the 10th and 90th percentiles, model.p10.txt and model.p90.txt), the OAX that gives the span of the data and a period's value per series, the evidence and the rows it learned from. The engine forecasts with it as with its own recipe (Forecast): every complete period read with the period query, the recipe's inputs computed from them, so the models must learn from those inputs, in their order.

  • name: The prediction's name (its folder, PREDICT("name")).
  • p50: The median's model (its rows are kept with the version).
  • p10: The 10th percentile's model: the low end of the likely range.
  • p90: The 90th percentile's model: the high end.
  • history: The history it learned from (its grain and its series).
  • horizon: How many periods ahead it forecasts.
  • span: The OAX step that gives the first and last dates with data (columns "first" and "last").
  • period: The OAX step that gives a period's value per series, from @from up to (not including) @until.
  • series: The period query's column that names each series; none when the forecast is a total.
  • value: The period query's column with the value.
  • evidence: What shows it is good: how far off on the held-back periods, the simple rule's, how often its range held (kept, and shown to whoever approves it).
  • keepTrainingData: Keep the rows it learned from (Parquet, out of git), so it can be retrained bit for bit.
  • note: Why this version (kept with it).
static ModelVersion Import(string name, string file, string? note = null, IReadOnlyList<Feature>? features = null, Output? output = null, string? project = null, string? author = null, bool byAgent = false)
Imports a LightGBM model from a file (model.txt, a pickle or joblib file) as a new version (a draft). The original file is kept with it, as it came. Features with their categories can be given when the file does not say which columns are text.
static (bool Same, string Detail) Reproduce(string name, int version, string? project = null)
Retrains a version from what it kept (its training rows, features, dataset and model parameters, its number of trees) and compares the new model's text with the saved one.

Also: static IReadOnlyList<ModelVersion> Versions(string name), static void WriteParquet(string path, Table t), static Table ReadParquet(string path).

ModelVersion

public sealed class ModelVersion

A saved model version: serialized (LightGBM's text format), with what made it and what it showed. It never changes after it is saved: its manifest holds every file's fingerprint and the previous version's, and the version's fingerprint is its manifest's.

Fields

const string HeldOutSince = "0.3.53"
The OpenBI release from which a version keeps how its metrics were measured (the patterns test on held-out rows).

Properties

string Fingerprint { get; }
The SHA-256 of manifest.json.
string AuthorAccount { get; }
The computer account it was saved from.
bool ByAgent { get; }
Saved by the agent, on its author's behalf.
DateTimeOffset? Created { get; }
When it was saved (its manifest's "created"); null when the manifest doesn't say or says it unreadably - a version written by hand or by another tool still shows, its date said unknown (ModelVersion.CreatedText).
string Status { get; }
draft, approved, not approved, in use, retired.
string? MetricsOn { get; }
What its metrics were measured on, in words: "metrics on held-out rows" - a test neither learning nor early stopping saw (any Models.Save with heldOut:, a forecast's held-back periods) -, "metrics on the early-stopping rows (an older pattern's version)" for a version saved before that (versions keep no record of how they were measured then), whose pattern stopped early and measured on the same rows (a little optimistic), or as its notebook measured them. Null for a version without a model's metrics (results, an imported model). Never changes the version: it reads what it kept.
string? MetricsKind { get; }
MetricsOn in a word or two, for a list: held-out, early-stopping rows, as measured; null as MetricsOn.

Also: string Name { get; }, int Number { get; }, string Folder { get; }, JsonObject Manifest { get; }, string Author { get; }, string Origin { get; }, JsonObject Schema { get; }.

Methods

string CreatedText(bool utc = false)
Its date as shown ("yyyy-MM-dd HH:mm", local time unless utc), or "date unknown".
Booster Load()
The model, ready to score.

Also: string PathOf(string file), string ToString().

Output

public sealed record Output(string Kind, string Outcome)

How a model version's scores are written: a probability (with bands and reasons), a value, or a survival model's risk with each row's survival to a horizon (Outcome its duration column, Event its event column, in the features query).

Properties

string? Event { get; init; }
A survival model's event column (1 when it happened, 0 while still going), in the features query.
double? Horizon { get; init; }
A survival model's horizon, in its durations' units: each row's survival to it, and from now.
double? High { get; init; }
Bands by rank: the share of rows, highest scores first, in the High band (and next in Medium). The bands are then ranks, not levels of likelihood: a row in Low can still be likely, when most rows are.
double? HighAt { get; init; }
Bands by the chance itself (a probability's): High from this chance up, Medium from Output.MediumAt up to it, Low below - what a reader takes High, Medium and Low to mean.
int ReasonCount { get; init; }
How many reasons (the features that raised the score most) each row gets.
string? LabelCulture { get; init; }
The culture its bands and reasons are said in (Labels), or null: no words beside them.
IReadOnlyList<string>? BandLabels { get; init; }
The bands' names in that culture: High, Medium, Low (Høy, Middels, Lav).
string? NoneLabel { get; init; }
What a reason says of a missing value (none, ingen).
IReadOnlyDictionary<string, (string Label, string? Format)>? FeatureLabels { get; init; }
Each feature in words, by its name, and its value's format ("omsetning_180": ("Omsetning siste 180 dager", "#,0")).

Also: string Kind { get; init; }, string Outcome { get; init; }, double? Medium { get; init; }, double? MediumAt { get; init; }.

Methods

static Output Survival(string duration, string evt, double horizon)
A survival model (LightGbm.TrainSurvival): each row's risk (against the average row's), band and reasons, its survival to the horizon, its median time, and, for a row still going, its chance of lasting the horizon more from its own duration. duration and evt: the features query's columns.
Output Bands(double top = 0.1, double next = 0.2)
Bands by rank: the top share of the rows High (of the held-out test's rows, when the version is saved with one; else the validation or training rows'), the next share Medium, the rest Low. Ranks, not levels of likelihood.
Output Cuts(double high = 0.5, double medium = 0.2)
Bands by the chance itself (a probability's): High from high up (0.5: more likely than not), Medium from medium up to it, Low below. The version keeps them, so a band is the same chance whoever else is scored.
Output Labels(string culture, Dictionary<string, (string Label, string? Format)>? features = null, string[]? bands = null, string? none = null)

Words beside the version's bands and reasons, in a culture (the model's): PREDICT then adds Band label and Band order (a slicer sorts by it) beside Band, and Reason 1 label, 2, … beside Reason 1, 2, … - "Omsetning siste 180 dager: 6 399", the feature in words and its value in its format, formatted in the culture. Band and Reason N themselves do not change, since keys filter on them, and a version saved without labels scores exactly as it did. features: each feature's words and format, by its name (one not named: its name, #,0.##); bands: High, Medium and Low's names (Norwegian's: Høy, Middels, Lav; else the English); none: a missing value's word (ingen; none).

Output.Probability("stopped").Cuts().Reasons(3).Labels("nb-NO", new() { ["omsetning_180"] = ("Omsetning siste 180 dager", "#,0"), ["days_since_last"] = ("Dager siden siste aktivitet", "#,0"), }) 

Also: static Output Probability(string outcome), static Output Value(string outcome), Output Reasons(int count = 3), JsonObject ToJson().

HeldOut

public sealed record HeldOut(
    Booster Model,
    Table Test,
    string? How = null)

How a version's metrics were measured, kept with it (Models.Save heldOut:): the model that was checked - learned from the training rows, its trees chosen by early stopping on the validation rows - and the held-out test it was measured on, rows neither learning nor early stopping saw (for a history, the latest as-of dates, whose outcome came after all the others'). The version's own model is that one, or one learned again from every row with the trees early stopping chose (as the engine and the forecast recipe do). How: the rule that picked the test, in words, so a reviewer can pick the same rows again.

Properties

string Split { get; }
The split it says: train/validation/test, or train/test when the checked model had no validation rows.

Also: Booster Model { get; init; }, Table Test { get; init; }, string? How { get; init; }.

HistoryEntry

public sealed record HistoryEntry(
    DateTimeOffset At,
    int Version,
    string Action,
    string By,
    string? Note,
    string Hash)

A step in a version's life, as the history keeps it: who (their name), from which account, why.

Properties

string? Account { get; init; }
The computer account it was done from (DOMAIN\\user).

Also: DateTimeOffset At { get; init; }, int Version { get; init; }, string Action { get; init; }, string By { get; init; }, string? Note { get; init; }, string Hash { get; init; }.

VersionStore

public sealed class VersionStore

A prediction's model versions (predictions/<name>/versions/<n>/) and their history: saved, approved (by someone other than the author), not approved, in use, retired. The history is a file of entries each holding the previous entry's fingerprint, so a changed or removed entry shows.

Constructors

Its constructors: VersionStore(string predictionFolder).

Properties

static string ProcessAccount { get; }
The computer account decisions are taken from: OPENBI_ACCOUNT when the process started with it (a service account), else Windows' DOMAIN\\user. Read once, before any step's code runs.
string Account { get; }
The account this store's decisions are recorded with (tests set another).
bool SelfApproval { get; }
Whether the project lets an author approve their own versions (predictions/settings.json: "selfApproval": true).
ModelVersion? InUse { get; }
The version in use (the one the model scores with), or null.

Also: string Name { get; }, string Folder { get; }, string HistoryFile { get; }.

Methods

void SetSelfApproval(bool allow)
Lets authors approve their own versions, or requires another person again (predictions/settings.json) - a person's decision, never the agent's; each approval it allows says so in the history.
ModelVersion Create(Action<string> write, string author, string origin, string? note, JsonObject? extra = null)
Saves a new version: write writes its files into a folder; then the manifest (every file's fingerprint, the previous version's) is written, the files made read-only, and the history says who saved it.
void Approve(int version, string by, string? note = null)
Approves a draft. Someone other than its author approves, unless the project allows authors to.
void Reject(int version, string by, string reason)
Records that a draft is not approved, and why. It stays, with its reason.
void PutInUse(int version, string by, string? note = null)
Puts an approved version in use (the model scores with it); the one in use before is retired.
StoreCheck Check()
Checks every version's files against its manifest, the chain of manifests, and the chain of the history.
void Export(int version, string zipPath)
One file for a review: the version's files as they were saved, its history, the manifests of the versions before it (the chain), and a page on how to check the fingerprints.

Also: IReadOnlyList<ModelVersion> List(), ModelVersion Get(int number), void Retire(int version, string by, string? note = null), IReadOnlyList<HistoryEntry> History().

StoreCheck

public sealed record StoreCheck(
    int Versions,
    int Files,
    IReadOnlyList<string> Problems)

What checking a model store found: nothing changed, or what did.

Properties

Its properties: int Versions { get; init; }, int Files { get; init; }, IReadOnlyList<string> Problems { get; init; }, bool Unchanged { get; }.

Results

public static class Results

What an operations research, a valuation or a network notebook found - a plan, positions valued, a network's nodes - saved as a version of its own: the rows (result.parquet, kept in git: they are the version's output), what they are (schema.json), the evidence, the notebook as it ran and where it ran. Like a model version it never changes, and someone other than its author approves it; in use, its rows are a table of the model.

Methods

static ModelVersion Save(string name, Table rows, string? key = null, IEnumerable<object?>? evidence = null, string? note = null, JsonObject? details = null)

Saves the rows a notebook found as a new version (a draft) of its work. Someone other than its author approves it before it is used; in use, the rows are a table of the model (the notebook's Versions: Use in the model).

  • name: The notebook's name (its operations research model, valuation or network).
  • rows: What it found: the plan, the positions valued, the nodes measured.
  • key: The column that names each row (a product, a position, a customer): the table relates on it.
  • evidence: What shows it is right: metrics, charts, tables, notes (kept, and shown to whoever approves it).
  • note: Why this version (kept with it).
  • details: What the kind keeps besides (a solver's status, a valuation's date, a network's size).
static ModelVersion Save(string name, Network network, IEnumerable<object?>? evidence = null, string? note = null)
Saves a network as a new version (a draft): its nodes are the rows (the key Node), its edges are kept beside them (edges.parquet) for the Graph and the network visual. Without evidence, its communities, modularity and drawing are the evidence.
static ModelVersion Save(string name, Solution plan, IEnumerable<object?>? evidence = null, string? note = null, ScenarioSet? scenarios = null)

Saves a plan as a new version (a draft): its rows are the plan (the decisions' rows with their values), and the model is kept beside them (formulation.json), so the engine solves it again for a what-if (OPTIMIZE). Without evidence, the objective, what limits the plan and every constraint's use and shadow price are the evidence. How the plan stands is kept too (sensitivity.json): every limit's use, slack and shadow price, and an LP's ranging by the solver - what its review page (the Versions tab's Review as a page) shows, as saved.

  • name: The notebook's name (its operations research model).
  • plan: The solution whose plan is saved (it must have one).
  • evidence: What shows it is right (by default: the objective, what limits the plan, every constraint).
  • note: Why this version.
  • scenarios: Scenarios against this plan (solution.Scenarios(…)), kept with it for the Scenarios tab.
static ModelVersion Save(string name, Routes routes, IEnumerable<object?>? evidence = null, string? note = null)
Saves routes as a new version (a draft): its rows are every stop (Vehicle, Order, Place, Load, Time, Lat and Lon with coordinates), and the distances, loads and times are its evidence; the routes as shown are kept beside them (routes.json, the Routes tab's). Approved and in use, the stops are a table of the model.
static ModelVersion Save(string name, Valued valuation, IEnumerable<object?>? evidence = null, string? note = null)
Saves a valuation as a new version (a draft): its rows are the positions valued, and its market (curves' pillars, quotes, FX rates) is kept beside them (market.json), frozen: the version is the official numbers once risk control (someone other than its author) approves it, and runs again on the same market.
static Market Market(string name, int? version = null)
A saved valuation's market (its market.json): the version given, else the one in use, else the latest.
static Network Network(string name, int? version = null)
A saved network: the version given, else the one in use, else the latest.
static Table Load(string name, int? version = null)
A version's rows: the version given, or else the one in use, or else the newest.

Also: static IReadOnlyList<ModelVersion> Versions(string name).

ImportedModel

public sealed record ImportedModel(
    string ModelText,
    string Format,
    string? PythonClass,
    IReadOnlyList<string>? Classes,
    string? SklearnVersion,
    IReadOnlyList<string> Notes,
    string SourceSha256)

A LightGBM model brought from outside OpenBI: its text, and what the file said about it.

Properties

Its properties: string ModelText { get; init; }, string Format { get; init; }, string? PythonClass { get; init; }, IReadOnlyList<string>? Classes { get; init; }, string? SklearnVersion { get; init; }, IReadOnlyList<string> Notes { get; init; }, string SourceSha256 { get; init; }.

ModelImport

public static class ModelImport

Reads a LightGBM model a data scientist sends: LightGBM's text format (model.txt), or a Python pickle or joblib file of a Booster, an LGBMClassifier/LGBMRegressor, or a scikit-learn pipeline ending in one. Pickles are read as data, never run (PickleReader).

Methods

Its methods: static ImportedModel Read(string path), static ImportedModel Read(byte[] file, string fileName = "").

PickleReader

public sealed class PickleReader

Reads a Python pickle (protocols 0 to 5) as data, never as code: classes are names, calls are recorded, nothing is imported or executed. Unpickling a file runs any code it names, so OpenBI never unpickles; it walks the opcodes. joblib files (their arrays written between the opcodes, zlib or gzip compressed) are read too.

Methods

static object? Read(byte[] file)
The object a pickle (or joblib) file describes.

PyObject

public sealed class PyObject

A Python object a pickle describes: its class, the arguments it is made from, and its state. Nothing is run.

Constructors

PyObject(object? cls, object? args)
A Python object a pickle describes: its class, the arguments it is made from, and its state. Nothing is run.

Properties

byte[]? RawData { get; }
A joblib array's data, written after the pickle's object (kept when small).

Also: object? Class { get; }, object? Args { get; }, object? State { get; }, string ClassName { get; }.

Methods

Its methods: string ToString().

PyGlobal

public sealed record PyGlobal(string Module, string Name)

A Python class or function a pickle names (module and name). It is only a name here: nothing is imported or run.

Properties

Its properties: string Module { get; init; }, string Name { get; init; }, string FullName { get; }.

PyDict

public sealed class PyDict

A Python dict, in its order.

Constructors

Its constructors: PyDict().

Properties

Its properties: List<KeyValuePair<object?, object?>> Items { get; }.

Indexers

Its indexers: object? this[string key] { get; }.

Methods

Its methods: bool Has(string key).

PyTuple

public sealed class PyTuple

A Python tuple.

Constructors

PyTuple(object?[] items)
A Python tuple.

Properties

Its properties: object?[] Items { get; }.

PyNone

public sealed class PyNone

Python's None.

Constructors

Its constructors: PyNone().

Fields

Its fields: static readonly PyNone Value.

Methods

Its methods: string ToString().

Last updated · OpenBI Studio 0.3.78