tempest-react-sdk 0.32.0 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.cjs","names":[],"sources":["../../src/tabular/manifest.ts"],"sourcesContent":["/**\n * Reading an edge package published by `tempest-fastapi-sdk`.\n *\n * `edge_pipeline` writes a directory — the graph, a gzipped copy, a drift\n * baseline and a `manifest.json` — and the browser is one of its two\n * intended consumers. The manifest is what turns a `.onnx` URL into\n * something a UI can use: the **column order** the model was trained on,\n * the class names behind `probabilities[2]`, and a version to compare\n * against what is already cached.\n *\n * That column order is the field worth loading a manifest for. A model fed\n * the right features in the wrong order answers confidently and wrongly,\n * and no runtime check catches it.\n *\n * The contract is pinned by `schema_version`. Unknown fields are ignored\n * rather than rejected, so a package written by a newer SDK still loads.\n */\n\nimport { fetchModelBytes, type ModelCacheOptions } from \"./cache\";\nimport { ModelFetchError } from \"./exceptions\";\nimport { TabularPredictor } from \"./predictor\";\nimport type { TabularPredictorOptions } from \"./types\";\n\n/** Manifest schema version this reader was written against. */\nexport const SUPPORTED_MANIFEST_SCHEMA = 1;\n\n/** Fixed filename inside a package directory. */\nexport const MANIFEST_FILENAME = \"manifest.json\";\n\n/** The graph file and how to check you got it whole. */\nexport interface ManifestModelFile {\n readonly file: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly gzip_file: string | null;\n readonly gzip_bytes: number | null;\n readonly opset: number;\n readonly dtype: string;\n}\n\n/** What the graph expects per row. */\nexport interface ManifestInput {\n readonly name: string;\n readonly features: number;\n /** Column order used at training time. */\n readonly feature_names: readonly string[];\n}\n\n/** What the graph answers. */\nexport interface ManifestOutput {\n readonly is_classifier: boolean;\n readonly label_output: string;\n readonly probability_output: string | null;\n /** Class labels in score-column order. */\n readonly classes: readonly string[];\n}\n\n/** The package manifest, as written by `edge_pipeline`. */\nexport interface EdgeManifest {\n readonly schema_version: number;\n readonly name: string;\n readonly version: string;\n readonly created_at: string;\n readonly sdk_version: string;\n readonly estimator: string;\n readonly model: ManifestModelFile;\n readonly input: ManifestInput;\n readonly output: ManifestOutput;\n readonly verified: boolean | null;\n readonly baseline_file: string | null;\n readonly baseline_samples: number;\n}\n\n/** A package loaded and ready to answer. */\nexport interface LoadedEdgePackage {\n /** What was published. */\n readonly manifest: EdgeManifest;\n /** The running model. */\n readonly predictor: TabularPredictor;\n /** Column order the rows must follow. */\n readonly featureNames: readonly string[];\n /** Class names behind each probability column. */\n readonly classes: readonly string[];\n /**\n * Map a prediction's scores onto class names.\n *\n * @param probabilities One row of scores.\n * @returns Name/score pairs, highest first.\n */\n readonly explain: (probabilities: readonly number[]) => { name: string; score: number }[];\n}\n\n/** Options for {@link loadEdgePackage}. */\nexport interface LoadEdgePackageOptions extends TabularPredictorOptions {\n /** Cache the model bytes for offline use. `true` by default. */\n readonly cache?: boolean | ModelCacheOptions;\n}\n\n/**\n * Read a package's manifest.\n *\n * Cheap: it is a few hundred bytes, so an app can check for a new version\n * without downloading a model it may already have.\n *\n * @example\n * ```ts\n * const manifest = await fetchEdgeManifest(\"/models/risk/\");\n * if (manifest.version !== localStorage.getItem(\"risk-version\")) {\n * // a new model was published\n * }\n * ```\n *\n * @param directoryUrl URL of the package directory, with or without a\n * trailing slash. A full URL to the manifest file also works.\n * @param requestInit `fetch` options.\n * @returns The parsed manifest.\n * @throws {@link ModelFetchError} when the manifest cannot be read, or when\n * its `schema_version` is newer than this reader understands — loading it\n * anyway would risk misreading the field that defines column order.\n */\nexport async function fetchEdgeManifest(\n directoryUrl: string,\n requestInit?: RequestInit,\n): Promise<EdgeManifest> {\n const url = manifestUrl(directoryUrl);\n let response: Response;\n try {\n response = await fetch(url, requestInit);\n } catch (error) {\n throw new ModelFetchError(`Could not read the manifest at ${url}`, {\n cause: error,\n });\n }\n if (!response.ok) {\n throw new ModelFetchError(\n `Could not read the manifest at ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n const manifest = (await response.json()) as EdgeManifest;\n if (typeof manifest?.schema_version !== \"number\") {\n throw new ModelFetchError(`${url} is not an edge package manifest (no schema_version).`);\n }\n if (manifest.schema_version > SUPPORTED_MANIFEST_SCHEMA) {\n throw new ModelFetchError(\n `The manifest at ${url} uses schema_version ${manifest.schema_version}, ` +\n `and this SDK understands ${SUPPORTED_MANIFEST_SCHEMA}. Upgrade ` +\n \"tempest-react-sdk before serving this package.\",\n );\n }\n return manifest;\n}\n\n/**\n * Load a whole edge package: manifest, model, and the names to read it by.\n *\n * @example\n * ```ts\n * const pkg = await loadEdgePackage(\"/models/risk/\");\n *\n * console.log(pkg.featureNames); // [\"age\", \"income\", \"tenure\", \"score\", \"visits\"]\n *\n * const { probabilities } = await pkg.predictor.predict([[41, 5200, 3, 0.82, 12]]);\n * console.log(pkg.explain(probabilities[0]!)); // [{ name: \"approved\", score: 0.91 }, ...]\n * ```\n *\n * @param directoryUrl URL of the package directory.\n * @param options Predictor options plus caching.\n * @returns The loaded package.\n * @throws {@link ModelFetchError} when the manifest or model cannot be read.\n */\nexport async function loadEdgePackage(\n directoryUrl: string,\n options: LoadEdgePackageOptions = {},\n): Promise<LoadedEdgePackage> {\n const manifest = await fetchEdgeManifest(directoryUrl);\n const base = directoryUrl.endsWith(\"/\") ? directoryUrl : `${directoryUrl}/`;\n const modelUrl = `${base}${manifest.model.file}`;\n\n const cache = options.cache ?? true;\n const source =\n cache === false\n ? modelUrl\n : await fetchModelBytes(modelUrl, typeof cache === \"object\" ? cache : {});\n\n const predictor = await TabularPredictor.create(source, {\n providers: options.providers,\n warmup: options.warmup,\n sessionOptions: options.sessionOptions,\n });\n\n const classes = manifest.output.classes;\n return {\n manifest,\n predictor,\n featureNames: manifest.input.feature_names,\n classes,\n explain: (probabilities: readonly number[]) =>\n probabilities\n .map((score, index) => ({\n name: classes[index] ?? String(index),\n score,\n }))\n .sort((a, b) => b.score - a.score),\n };\n}\n\n/**\n * Resolve a directory URL to its manifest file.\n *\n * @param directoryUrl The package directory, or the manifest itself.\n * @returns The manifest URL.\n */\nfunction manifestUrl(directoryUrl: string): string {\n if (directoryUrl.endsWith(\".json\")) return directoryUrl;\n return directoryUrl.endsWith(\"/\")\n ? `${directoryUrl}${MANIFEST_FILENAME}`\n : `${directoryUrl}/${MANIFEST_FILENAME}`;\n}\n"],"mappings":"0FAwBA,IAAa,EAA4B,EAG5B,EAAoB,
|
|
1
|
+
{"version":3,"file":"manifest.cjs","names":[],"sources":["../../src/tabular/manifest.ts"],"sourcesContent":["/**\n * Reading an edge package published by `tempest-fastapi-sdk`.\n *\n * `edge_pipeline` writes a directory — the graph, a gzipped copy, a drift\n * baseline and a `manifest.json` — and the browser is one of its two\n * intended consumers. The manifest is what turns a `.onnx` URL into\n * something a UI can use: the **column order** the model was trained on,\n * the class names behind `probabilities[2]`, and a version to compare\n * against what is already cached.\n *\n * That column order is the field worth loading a manifest for. A model fed\n * the right features in the wrong order answers confidently and wrongly,\n * and no runtime check catches it.\n *\n * The contract is pinned by `schema_version`. Unknown fields are ignored\n * rather than rejected, so a package written by a newer SDK still loads.\n */\n\nimport { fetchModelBytes, type ModelCacheOptions } from \"./cache\";\nimport { ModelFetchError } from \"./exceptions\";\nimport { TabularPredictor } from \"./predictor\";\nimport type { TabularPredictorOptions } from \"./types\";\n\n/** Manifest schema version this reader was written against. */\nexport const SUPPORTED_MANIFEST_SCHEMA = 1;\n\n/** Fixed filename inside a package directory. */\nexport const MANIFEST_FILENAME = \"manifest.json\";\n\n/** The graph file and how to check you got it whole. */\nexport interface ManifestModelFile {\n readonly file: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly gzip_file: string | null;\n readonly gzip_bytes: number | null;\n readonly opset: number;\n readonly dtype: string;\n}\n\n/** What the graph expects per row. */\nexport interface ManifestInput {\n readonly name: string;\n readonly features: number;\n /** Column order used at training time. */\n readonly feature_names: readonly string[];\n}\n\n/** What the graph answers. */\nexport interface ManifestOutput {\n readonly is_classifier: boolean;\n readonly label_output: string;\n readonly probability_output: string | null;\n /** Class labels in score-column order. */\n readonly classes: readonly string[];\n}\n\n/**\n * Where the packaged model came from, when it came from an existing\n * artifact.\n *\n * Present when the package was built with `edge_pipeline_from_pickle`: the\n * `.pkl` never reaches the browser (a pickle is a Python program, not\n * data), but its name and digest travel in the manifest, so a model\n * answering in a tab can be traced back to the file that produced it.\n */\nexport interface ManifestSource {\n readonly file: string;\n readonly kind: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly sklearn_version: string;\n readonly warnings: readonly string[];\n}\n\n/** The package manifest, as written by `edge_pipeline`. */\nexport interface EdgeManifest {\n readonly schema_version: number;\n readonly name: string;\n readonly version: string;\n readonly created_at: string;\n readonly sdk_version: string;\n readonly estimator: string;\n readonly model: ManifestModelFile;\n readonly input: ManifestInput;\n readonly output: ManifestOutput;\n readonly verified: boolean | null;\n /** Absent on packages built straight from a fitted estimator. */\n readonly source?: ManifestSource;\n readonly baseline_file: string | null;\n readonly baseline_samples: number;\n}\n\n/** A package loaded and ready to answer. */\nexport interface LoadedEdgePackage {\n /** What was published. */\n readonly manifest: EdgeManifest;\n /** The running model. */\n readonly predictor: TabularPredictor;\n /** Column order the rows must follow. */\n readonly featureNames: readonly string[];\n /** Class names behind each probability column. */\n readonly classes: readonly string[];\n /**\n * Map a prediction's scores onto class names.\n *\n * @param probabilities One row of scores.\n * @returns Name/score pairs, highest first.\n */\n readonly explain: (probabilities: readonly number[]) => { name: string; score: number }[];\n}\n\n/** Options for {@link loadEdgePackage}. */\nexport interface LoadEdgePackageOptions extends TabularPredictorOptions {\n /** Cache the model bytes for offline use. `true` by default. */\n readonly cache?: boolean | ModelCacheOptions;\n}\n\n/**\n * Read a package's manifest.\n *\n * Cheap: it is a few hundred bytes, so an app can check for a new version\n * without downloading a model it may already have.\n *\n * @example\n * ```ts\n * const manifest = await fetchEdgeManifest(\"/models/risk/\");\n * if (manifest.version !== localStorage.getItem(\"risk-version\")) {\n * // a new model was published\n * }\n * ```\n *\n * @param directoryUrl URL of the package directory, with or without a\n * trailing slash. A full URL to the manifest file also works.\n * @param requestInit `fetch` options.\n * @returns The parsed manifest.\n * @throws {@link ModelFetchError} when the manifest cannot be read, or when\n * its `schema_version` is newer than this reader understands — loading it\n * anyway would risk misreading the field that defines column order.\n */\nexport async function fetchEdgeManifest(\n directoryUrl: string,\n requestInit?: RequestInit,\n): Promise<EdgeManifest> {\n const url = manifestUrl(directoryUrl);\n let response: Response;\n try {\n response = await fetch(url, requestInit);\n } catch (error) {\n throw new ModelFetchError(`Could not read the manifest at ${url}`, {\n cause: error,\n });\n }\n if (!response.ok) {\n throw new ModelFetchError(\n `Could not read the manifest at ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n const manifest = (await response.json()) as EdgeManifest;\n if (typeof manifest?.schema_version !== \"number\") {\n throw new ModelFetchError(`${url} is not an edge package manifest (no schema_version).`);\n }\n if (manifest.schema_version > SUPPORTED_MANIFEST_SCHEMA) {\n throw new ModelFetchError(\n `The manifest at ${url} uses schema_version ${manifest.schema_version}, ` +\n `and this SDK understands ${SUPPORTED_MANIFEST_SCHEMA}. Upgrade ` +\n \"tempest-react-sdk before serving this package.\",\n );\n }\n return manifest;\n}\n\n/**\n * Load a whole edge package: manifest, model, and the names to read it by.\n *\n * @example\n * ```ts\n * const pkg = await loadEdgePackage(\"/models/risk/\");\n *\n * console.log(pkg.featureNames); // [\"age\", \"income\", \"tenure\", \"score\", \"visits\"]\n *\n * const { probabilities } = await pkg.predictor.predict([[41, 5200, 3, 0.82, 12]]);\n * console.log(pkg.explain(probabilities[0]!)); // [{ name: \"approved\", score: 0.91 }, ...]\n * ```\n *\n * @param directoryUrl URL of the package directory.\n * @param options Predictor options plus caching.\n * @returns The loaded package.\n * @throws {@link ModelFetchError} when the manifest or model cannot be read.\n */\nexport async function loadEdgePackage(\n directoryUrl: string,\n options: LoadEdgePackageOptions = {},\n): Promise<LoadedEdgePackage> {\n const manifest = await fetchEdgeManifest(directoryUrl);\n const base = directoryUrl.endsWith(\"/\") ? directoryUrl : `${directoryUrl}/`;\n const modelUrl = `${base}${manifest.model.file}`;\n\n const cache = options.cache ?? true;\n const source =\n cache === false\n ? modelUrl\n : await fetchModelBytes(modelUrl, typeof cache === \"object\" ? cache : {});\n\n const predictor = await TabularPredictor.create(source, {\n providers: options.providers,\n warmup: options.warmup,\n sessionOptions: options.sessionOptions,\n });\n\n const classes = manifest.output.classes;\n return {\n manifest,\n predictor,\n featureNames: manifest.input.feature_names,\n classes,\n explain: (probabilities: readonly number[]) =>\n probabilities\n .map((score, index) => ({\n name: classes[index] ?? String(index),\n score,\n }))\n .sort((a, b) => b.score - a.score),\n };\n}\n\n/**\n * Resolve a directory URL to its manifest file.\n *\n * @param directoryUrl The package directory, or the manifest itself.\n * @returns The manifest URL.\n */\nfunction manifestUrl(directoryUrl: string): string {\n if (directoryUrl.endsWith(\".json\")) return directoryUrl;\n return directoryUrl.endsWith(\"/\")\n ? `${directoryUrl}${MANIFEST_FILENAME}`\n : `${directoryUrl}/${MANIFEST_FILENAME}`;\n}\n"],"mappings":"0FAwBA,IAAa,EAA4B,EAG5B,EAAoB,gBAiHjC,eAAsB,EAClB,EACA,EACqB,CACrB,IAAM,EAAM,EAAY,CAAY,EAChC,EACJ,GAAI,CACA,EAAW,MAAM,MAAM,EAAK,CAAW,CAC3C,OAAS,EAAO,CACZ,MAAM,IAAI,EAAA,gBAAgB,kCAAkC,IAAO,CAC/D,MAAO,CACX,CAAC,CACL,CACA,GAAI,CAAC,EAAS,GACV,MAAM,IAAI,EAAA,gBACN,kCAAkC,EAAI,IAAI,EAAS,OAAO,GAAG,EAAS,YAC1E,EAGJ,IAAM,EAAY,MAAM,EAAS,KAAK,EACtC,GAAI,OAAO,GAAU,gBAAmB,SACpC,MAAM,IAAI,EAAA,gBAAgB,GAAG,EAAI,sDAAsD,EAE3F,GAAI,EAAS,eAAA,EACT,MAAM,IAAI,EAAA,gBACN,mBAAmB,EAAI,uBAAuB,EAAS,eAAe,qFAG1E,EAEJ,OAAO,CACX,CAoBA,eAAsB,EAClB,EACA,EAAkC,CAAC,EACT,CAC1B,IAAM,EAAW,MAAM,EAAkB,CAAY,EAE/C,EAAW,GADJ,EAAa,SAAS,GAAG,EAAI,EAAe,GAAG,EAAa,KAC9C,EAAS,MAAM,OAEpC,EAAQ,EAAQ,OAAS,GACzB,EACF,IAAU,GACJ,EACA,MAAM,EAAA,gBAAgB,EAAU,OAAO,GAAU,SAAW,EAAQ,CAAC,CAAC,EAE1E,EAAY,MAAM,EAAA,iBAAiB,OAAO,EAAQ,CACpD,UAAW,EAAQ,UACnB,OAAQ,EAAQ,OAChB,eAAgB,EAAQ,cAC5B,CAAC,EAEK,EAAU,EAAS,OAAO,QAChC,MAAO,CACH,WACA,YACA,aAAc,EAAS,MAAM,cAC7B,UACA,QAAU,GACN,EACK,KAAK,EAAO,KAAW,CACpB,KAAM,EAAQ,IAAU,OAAO,CAAK,EACpC,OACJ,EAAE,CAAC,CACF,MAAM,EAAG,IAAM,EAAE,MAAQ,EAAE,KAAK,CAC7C,CACJ,CAQA,SAAS,EAAY,EAA8B,CAE/C,OADI,EAAa,SAAS,OAAO,EAAU,EACpC,EAAa,SAAS,GAAG,EAC1B,GAAG,IAAe,IAClB,GAAG,EAAa,GAAG,GAC7B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.js","names":[],"sources":["../../src/tabular/manifest.ts"],"sourcesContent":["/**\n * Reading an edge package published by `tempest-fastapi-sdk`.\n *\n * `edge_pipeline` writes a directory — the graph, a gzipped copy, a drift\n * baseline and a `manifest.json` — and the browser is one of its two\n * intended consumers. The manifest is what turns a `.onnx` URL into\n * something a UI can use: the **column order** the model was trained on,\n * the class names behind `probabilities[2]`, and a version to compare\n * against what is already cached.\n *\n * That column order is the field worth loading a manifest for. A model fed\n * the right features in the wrong order answers confidently and wrongly,\n * and no runtime check catches it.\n *\n * The contract is pinned by `schema_version`. Unknown fields are ignored\n * rather than rejected, so a package written by a newer SDK still loads.\n */\n\nimport { fetchModelBytes, type ModelCacheOptions } from \"./cache\";\nimport { ModelFetchError } from \"./exceptions\";\nimport { TabularPredictor } from \"./predictor\";\nimport type { TabularPredictorOptions } from \"./types\";\n\n/** Manifest schema version this reader was written against. */\nexport const SUPPORTED_MANIFEST_SCHEMA = 1;\n\n/** Fixed filename inside a package directory. */\nexport const MANIFEST_FILENAME = \"manifest.json\";\n\n/** The graph file and how to check you got it whole. */\nexport interface ManifestModelFile {\n readonly file: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly gzip_file: string | null;\n readonly gzip_bytes: number | null;\n readonly opset: number;\n readonly dtype: string;\n}\n\n/** What the graph expects per row. */\nexport interface ManifestInput {\n readonly name: string;\n readonly features: number;\n /** Column order used at training time. */\n readonly feature_names: readonly string[];\n}\n\n/** What the graph answers. */\nexport interface ManifestOutput {\n readonly is_classifier: boolean;\n readonly label_output: string;\n readonly probability_output: string | null;\n /** Class labels in score-column order. */\n readonly classes: readonly string[];\n}\n\n/** The package manifest, as written by `edge_pipeline`. */\nexport interface EdgeManifest {\n readonly schema_version: number;\n readonly name: string;\n readonly version: string;\n readonly created_at: string;\n readonly sdk_version: string;\n readonly estimator: string;\n readonly model: ManifestModelFile;\n readonly input: ManifestInput;\n readonly output: ManifestOutput;\n readonly verified: boolean | null;\n readonly baseline_file: string | null;\n readonly baseline_samples: number;\n}\n\n/** A package loaded and ready to answer. */\nexport interface LoadedEdgePackage {\n /** What was published. */\n readonly manifest: EdgeManifest;\n /** The running model. */\n readonly predictor: TabularPredictor;\n /** Column order the rows must follow. */\n readonly featureNames: readonly string[];\n /** Class names behind each probability column. */\n readonly classes: readonly string[];\n /**\n * Map a prediction's scores onto class names.\n *\n * @param probabilities One row of scores.\n * @returns Name/score pairs, highest first.\n */\n readonly explain: (probabilities: readonly number[]) => { name: string; score: number }[];\n}\n\n/** Options for {@link loadEdgePackage}. */\nexport interface LoadEdgePackageOptions extends TabularPredictorOptions {\n /** Cache the model bytes for offline use. `true` by default. */\n readonly cache?: boolean | ModelCacheOptions;\n}\n\n/**\n * Read a package's manifest.\n *\n * Cheap: it is a few hundred bytes, so an app can check for a new version\n * without downloading a model it may already have.\n *\n * @example\n * ```ts\n * const manifest = await fetchEdgeManifest(\"/models/risk/\");\n * if (manifest.version !== localStorage.getItem(\"risk-version\")) {\n * // a new model was published\n * }\n * ```\n *\n * @param directoryUrl URL of the package directory, with or without a\n * trailing slash. A full URL to the manifest file also works.\n * @param requestInit `fetch` options.\n * @returns The parsed manifest.\n * @throws {@link ModelFetchError} when the manifest cannot be read, or when\n * its `schema_version` is newer than this reader understands — loading it\n * anyway would risk misreading the field that defines column order.\n */\nexport async function fetchEdgeManifest(\n directoryUrl: string,\n requestInit?: RequestInit,\n): Promise<EdgeManifest> {\n const url = manifestUrl(directoryUrl);\n let response: Response;\n try {\n response = await fetch(url, requestInit);\n } catch (error) {\n throw new ModelFetchError(`Could not read the manifest at ${url}`, {\n cause: error,\n });\n }\n if (!response.ok) {\n throw new ModelFetchError(\n `Could not read the manifest at ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n const manifest = (await response.json()) as EdgeManifest;\n if (typeof manifest?.schema_version !== \"number\") {\n throw new ModelFetchError(`${url} is not an edge package manifest (no schema_version).`);\n }\n if (manifest.schema_version > SUPPORTED_MANIFEST_SCHEMA) {\n throw new ModelFetchError(\n `The manifest at ${url} uses schema_version ${manifest.schema_version}, ` +\n `and this SDK understands ${SUPPORTED_MANIFEST_SCHEMA}. Upgrade ` +\n \"tempest-react-sdk before serving this package.\",\n );\n }\n return manifest;\n}\n\n/**\n * Load a whole edge package: manifest, model, and the names to read it by.\n *\n * @example\n * ```ts\n * const pkg = await loadEdgePackage(\"/models/risk/\");\n *\n * console.log(pkg.featureNames); // [\"age\", \"income\", \"tenure\", \"score\", \"visits\"]\n *\n * const { probabilities } = await pkg.predictor.predict([[41, 5200, 3, 0.82, 12]]);\n * console.log(pkg.explain(probabilities[0]!)); // [{ name: \"approved\", score: 0.91 }, ...]\n * ```\n *\n * @param directoryUrl URL of the package directory.\n * @param options Predictor options plus caching.\n * @returns The loaded package.\n * @throws {@link ModelFetchError} when the manifest or model cannot be read.\n */\nexport async function loadEdgePackage(\n directoryUrl: string,\n options: LoadEdgePackageOptions = {},\n): Promise<LoadedEdgePackage> {\n const manifest = await fetchEdgeManifest(directoryUrl);\n const base = directoryUrl.endsWith(\"/\") ? directoryUrl : `${directoryUrl}/`;\n const modelUrl = `${base}${manifest.model.file}`;\n\n const cache = options.cache ?? true;\n const source =\n cache === false\n ? modelUrl\n : await fetchModelBytes(modelUrl, typeof cache === \"object\" ? cache : {});\n\n const predictor = await TabularPredictor.create(source, {\n providers: options.providers,\n warmup: options.warmup,\n sessionOptions: options.sessionOptions,\n });\n\n const classes = manifest.output.classes;\n return {\n manifest,\n predictor,\n featureNames: manifest.input.feature_names,\n classes,\n explain: (probabilities: readonly number[]) =>\n probabilities\n .map((score, index) => ({\n name: classes[index] ?? String(index),\n score,\n }))\n .sort((a, b) => b.score - a.score),\n };\n}\n\n/**\n * Resolve a directory URL to its manifest file.\n *\n * @param directoryUrl The package directory, or the manifest itself.\n * @returns The manifest URL.\n */\nfunction manifestUrl(directoryUrl: string): string {\n if (directoryUrl.endsWith(\".json\")) return directoryUrl;\n return directoryUrl.endsWith(\"/\")\n ? `${directoryUrl}${MANIFEST_FILENAME}`\n : `${directoryUrl}/${MANIFEST_FILENAME}`;\n}\n"],"mappings":";;;;AAwBA,IAAa,IAA4B,GAG5B,IAAoB;
|
|
1
|
+
{"version":3,"file":"manifest.js","names":[],"sources":["../../src/tabular/manifest.ts"],"sourcesContent":["/**\n * Reading an edge package published by `tempest-fastapi-sdk`.\n *\n * `edge_pipeline` writes a directory — the graph, a gzipped copy, a drift\n * baseline and a `manifest.json` — and the browser is one of its two\n * intended consumers. The manifest is what turns a `.onnx` URL into\n * something a UI can use: the **column order** the model was trained on,\n * the class names behind `probabilities[2]`, and a version to compare\n * against what is already cached.\n *\n * That column order is the field worth loading a manifest for. A model fed\n * the right features in the wrong order answers confidently and wrongly,\n * and no runtime check catches it.\n *\n * The contract is pinned by `schema_version`. Unknown fields are ignored\n * rather than rejected, so a package written by a newer SDK still loads.\n */\n\nimport { fetchModelBytes, type ModelCacheOptions } from \"./cache\";\nimport { ModelFetchError } from \"./exceptions\";\nimport { TabularPredictor } from \"./predictor\";\nimport type { TabularPredictorOptions } from \"./types\";\n\n/** Manifest schema version this reader was written against. */\nexport const SUPPORTED_MANIFEST_SCHEMA = 1;\n\n/** Fixed filename inside a package directory. */\nexport const MANIFEST_FILENAME = \"manifest.json\";\n\n/** The graph file and how to check you got it whole. */\nexport interface ManifestModelFile {\n readonly file: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly gzip_file: string | null;\n readonly gzip_bytes: number | null;\n readonly opset: number;\n readonly dtype: string;\n}\n\n/** What the graph expects per row. */\nexport interface ManifestInput {\n readonly name: string;\n readonly features: number;\n /** Column order used at training time. */\n readonly feature_names: readonly string[];\n}\n\n/** What the graph answers. */\nexport interface ManifestOutput {\n readonly is_classifier: boolean;\n readonly label_output: string;\n readonly probability_output: string | null;\n /** Class labels in score-column order. */\n readonly classes: readonly string[];\n}\n\n/**\n * Where the packaged model came from, when it came from an existing\n * artifact.\n *\n * Present when the package was built with `edge_pipeline_from_pickle`: the\n * `.pkl` never reaches the browser (a pickle is a Python program, not\n * data), but its name and digest travel in the manifest, so a model\n * answering in a tab can be traced back to the file that produced it.\n */\nexport interface ManifestSource {\n readonly file: string;\n readonly kind: string;\n readonly sha256: string;\n readonly bytes: number;\n readonly sklearn_version: string;\n readonly warnings: readonly string[];\n}\n\n/** The package manifest, as written by `edge_pipeline`. */\nexport interface EdgeManifest {\n readonly schema_version: number;\n readonly name: string;\n readonly version: string;\n readonly created_at: string;\n readonly sdk_version: string;\n readonly estimator: string;\n readonly model: ManifestModelFile;\n readonly input: ManifestInput;\n readonly output: ManifestOutput;\n readonly verified: boolean | null;\n /** Absent on packages built straight from a fitted estimator. */\n readonly source?: ManifestSource;\n readonly baseline_file: string | null;\n readonly baseline_samples: number;\n}\n\n/** A package loaded and ready to answer. */\nexport interface LoadedEdgePackage {\n /** What was published. */\n readonly manifest: EdgeManifest;\n /** The running model. */\n readonly predictor: TabularPredictor;\n /** Column order the rows must follow. */\n readonly featureNames: readonly string[];\n /** Class names behind each probability column. */\n readonly classes: readonly string[];\n /**\n * Map a prediction's scores onto class names.\n *\n * @param probabilities One row of scores.\n * @returns Name/score pairs, highest first.\n */\n readonly explain: (probabilities: readonly number[]) => { name: string; score: number }[];\n}\n\n/** Options for {@link loadEdgePackage}. */\nexport interface LoadEdgePackageOptions extends TabularPredictorOptions {\n /** Cache the model bytes for offline use. `true` by default. */\n readonly cache?: boolean | ModelCacheOptions;\n}\n\n/**\n * Read a package's manifest.\n *\n * Cheap: it is a few hundred bytes, so an app can check for a new version\n * without downloading a model it may already have.\n *\n * @example\n * ```ts\n * const manifest = await fetchEdgeManifest(\"/models/risk/\");\n * if (manifest.version !== localStorage.getItem(\"risk-version\")) {\n * // a new model was published\n * }\n * ```\n *\n * @param directoryUrl URL of the package directory, with or without a\n * trailing slash. A full URL to the manifest file also works.\n * @param requestInit `fetch` options.\n * @returns The parsed manifest.\n * @throws {@link ModelFetchError} when the manifest cannot be read, or when\n * its `schema_version` is newer than this reader understands — loading it\n * anyway would risk misreading the field that defines column order.\n */\nexport async function fetchEdgeManifest(\n directoryUrl: string,\n requestInit?: RequestInit,\n): Promise<EdgeManifest> {\n const url = manifestUrl(directoryUrl);\n let response: Response;\n try {\n response = await fetch(url, requestInit);\n } catch (error) {\n throw new ModelFetchError(`Could not read the manifest at ${url}`, {\n cause: error,\n });\n }\n if (!response.ok) {\n throw new ModelFetchError(\n `Could not read the manifest at ${url}: ${response.status} ${response.statusText}`,\n );\n }\n\n const manifest = (await response.json()) as EdgeManifest;\n if (typeof manifest?.schema_version !== \"number\") {\n throw new ModelFetchError(`${url} is not an edge package manifest (no schema_version).`);\n }\n if (manifest.schema_version > SUPPORTED_MANIFEST_SCHEMA) {\n throw new ModelFetchError(\n `The manifest at ${url} uses schema_version ${manifest.schema_version}, ` +\n `and this SDK understands ${SUPPORTED_MANIFEST_SCHEMA}. Upgrade ` +\n \"tempest-react-sdk before serving this package.\",\n );\n }\n return manifest;\n}\n\n/**\n * Load a whole edge package: manifest, model, and the names to read it by.\n *\n * @example\n * ```ts\n * const pkg = await loadEdgePackage(\"/models/risk/\");\n *\n * console.log(pkg.featureNames); // [\"age\", \"income\", \"tenure\", \"score\", \"visits\"]\n *\n * const { probabilities } = await pkg.predictor.predict([[41, 5200, 3, 0.82, 12]]);\n * console.log(pkg.explain(probabilities[0]!)); // [{ name: \"approved\", score: 0.91 }, ...]\n * ```\n *\n * @param directoryUrl URL of the package directory.\n * @param options Predictor options plus caching.\n * @returns The loaded package.\n * @throws {@link ModelFetchError} when the manifest or model cannot be read.\n */\nexport async function loadEdgePackage(\n directoryUrl: string,\n options: LoadEdgePackageOptions = {},\n): Promise<LoadedEdgePackage> {\n const manifest = await fetchEdgeManifest(directoryUrl);\n const base = directoryUrl.endsWith(\"/\") ? directoryUrl : `${directoryUrl}/`;\n const modelUrl = `${base}${manifest.model.file}`;\n\n const cache = options.cache ?? true;\n const source =\n cache === false\n ? modelUrl\n : await fetchModelBytes(modelUrl, typeof cache === \"object\" ? cache : {});\n\n const predictor = await TabularPredictor.create(source, {\n providers: options.providers,\n warmup: options.warmup,\n sessionOptions: options.sessionOptions,\n });\n\n const classes = manifest.output.classes;\n return {\n manifest,\n predictor,\n featureNames: manifest.input.feature_names,\n classes,\n explain: (probabilities: readonly number[]) =>\n probabilities\n .map((score, index) => ({\n name: classes[index] ?? String(index),\n score,\n }))\n .sort((a, b) => b.score - a.score),\n };\n}\n\n/**\n * Resolve a directory URL to its manifest file.\n *\n * @param directoryUrl The package directory, or the manifest itself.\n * @returns The manifest URL.\n */\nfunction manifestUrl(directoryUrl: string): string {\n if (directoryUrl.endsWith(\".json\")) return directoryUrl;\n return directoryUrl.endsWith(\"/\")\n ? `${directoryUrl}${MANIFEST_FILENAME}`\n : `${directoryUrl}/${MANIFEST_FILENAME}`;\n}\n"],"mappings":";;;;AAwBA,IAAa,IAA4B,GAG5B,IAAoB;AAiHjC,eAAsB,EAClB,GACA,GACqB;CACrB,IAAM,IAAM,EAAY,CAAY,GAChC;CACJ,IAAI;EACA,IAAW,MAAM,MAAM,GAAK,CAAW;CAC3C,SAAS,GAAO;EACZ,MAAM,IAAI,EAAgB,kCAAkC,KAAO,EAC/D,OAAO,EACX,CAAC;CACL;CACA,IAAI,CAAC,EAAS,IACV,MAAM,IAAI,EACN,kCAAkC,EAAI,IAAI,EAAS,OAAO,GAAG,EAAS,YAC1E;CAGJ,IAAM,IAAY,MAAM,EAAS,KAAK;CACtC,IAAI,OAAO,GAAU,kBAAmB,UACpC,MAAM,IAAI,EAAgB,GAAG,EAAI,sDAAsD;CAE3F,IAAI,EAAS,iBAAA,GACT,MAAM,IAAI,EACN,mBAAmB,EAAI,uBAAuB,EAAS,eAAe,qFAG1E;CAEJ,OAAO;AACX;AAoBA,eAAsB,EAClB,GACA,IAAkC,CAAC,GACT;CAC1B,IAAM,IAAW,MAAM,EAAkB,CAAY,GAE/C,IAAW,GADJ,EAAa,SAAS,GAAG,IAAI,IAAe,GAAG,EAAa,KAC9C,EAAS,MAAM,QAEpC,IAAQ,EAAQ,SAAS,IACzB,IACF,MAAU,KACJ,IACA,MAAM,EAAgB,GAAU,OAAO,KAAU,WAAW,IAAQ,CAAC,CAAC,GAE1E,IAAY,MAAM,EAAiB,OAAO,GAAQ;EACpD,WAAW,EAAQ;EACnB,QAAQ,EAAQ;EAChB,gBAAgB,EAAQ;CAC5B,CAAC,GAEK,IAAU,EAAS,OAAO;CAChC,OAAO;EACH;EACA;EACA,cAAc,EAAS,MAAM;EAC7B;EACA,UAAU,MACN,EACK,KAAK,GAAO,OAAW;GACpB,MAAM,EAAQ,MAAU,OAAO,CAAK;GACpC;EACJ,EAAE,CAAC,CACF,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;CAC7C;AACJ;AAQA,SAAS,EAAY,GAA8B;CAE/C,OADI,EAAa,SAAS,OAAO,IAAU,IACpC,EAAa,SAAS,GAAG,IAC1B,GAAG,IAAe,MAClB,GAAG,EAAa,GAAG;AAC7B"}
|
package/dist/tabular.d.ts
CHANGED
|
@@ -62,6 +62,8 @@ export declare interface EdgeManifest {
|
|
|
62
62
|
readonly input: ManifestInput;
|
|
63
63
|
readonly output: ManifestOutput;
|
|
64
64
|
readonly verified: boolean | null;
|
|
65
|
+
/** Absent on packages built straight from a fitted estimator. */
|
|
66
|
+
readonly source?: ManifestSource;
|
|
65
67
|
readonly baseline_file: string | null;
|
|
66
68
|
readonly baseline_samples: number;
|
|
67
69
|
}
|
|
@@ -212,6 +214,24 @@ export declare class FeatureShapeError extends TabularError {
|
|
|
212
214
|
readonly classes: readonly string[];
|
|
213
215
|
}
|
|
214
216
|
|
|
217
|
+
/**
|
|
218
|
+
* Where the packaged model came from, when it came from an existing
|
|
219
|
+
* artifact.
|
|
220
|
+
*
|
|
221
|
+
* Present when the package was built with `edge_pipeline_from_pickle`: the
|
|
222
|
+
* `.pkl` never reaches the browser (a pickle is a Python program, not
|
|
223
|
+
* data), but its name and digest travel in the manifest, so a model
|
|
224
|
+
* answering in a tab can be traced back to the file that produced it.
|
|
225
|
+
*/
|
|
226
|
+
export declare interface ManifestSource {
|
|
227
|
+
readonly file: string;
|
|
228
|
+
readonly kind: string;
|
|
229
|
+
readonly sha256: string;
|
|
230
|
+
readonly bytes: number;
|
|
231
|
+
readonly sklearn_version: string;
|
|
232
|
+
readonly warnings: readonly string[];
|
|
233
|
+
}
|
|
234
|
+
|
|
215
235
|
/** Options for {@link fetchModelBytes}. */
|
|
216
236
|
export declare interface ModelCacheOptions {
|
|
217
237
|
/** Cache Storage bucket name. */
|