Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,34 @@

## [Unreleased]

### Added
- **Composite emission behind `OpGranularityPolicy`** (#1342 part 2): a `LoweringSpec` per fused-able op (`skainet.gelu`, `skainet.erf`) and `ConversionContext.emitComposite` emit `stablehlo.composite "<name>" {composite_attributes, decomposition = @fn, version}` plus one private decomposition function per (op, attributes, type) when a target's policy keeps the op fused; otherwise the same builder emits the decomposition inline. Helper functions go to a module trailer after the entry function so existing text tooling keeps finding `@main` first. First consumer of `OpGranularityPolicy.keepFused`.
- **`GeluApproximationLegalizationPass`** (`skainet-compile-opt`): targets without any erf lowering rewrite `gelu(approximate = false)` to the tanh form explicitly, recording `legalizedFrom` and `maxAbsError = 4.8e-4` on the node and a `GELU_APPROX_LEGALIZED` diagnostic, instead of a silent default. Registered per target through `TargetOptimizers.registerDagPasses`.
- **`@Lowering` annotation** and a *Lowering* column in the generated operator coverage matrix (`composite · decompose · native`); `operators.json` carries the field.
## [0.59.0] - 2026-10-14

Headline: **exact GELU and lowering metadata (#1342).** `erf` becomes a first-class op and `gelu`
carries its form (`approximate: Boolean = true`) as op metadata, so DIRECT execution, the compiled
graph and the StableHLO export make the same numeric choice. On the export side a `LoweringSpec` per
fused-able op emits a `stablehlo.composite` when a target keeps the op fused and the inline
decomposition otherwise, an explicit legalization pass replaces the silent exact→tanh substitution,
and `@Lowering` records each op's lowering in the operator matrix.

Version note: SKaiNET-transformers follows on this release; its Laya adapter replaces the host-side
exact GELU with `gelu(approximate = false)`. The io-core deprecation aliases introduced in 0.58 stay
at WARNING in this release; their schedule moves by one minor (ERROR in 0.60, removed in 0.61) to
match the SKaiNET-transformers schedule.

### Added

- **`TensorOps.erf` and exact GELU** (#1342): `gelu(tensor, approximate: Boolean = true)` keeps the tanh form as the default and selects the exact `0.5·x·(1 + erf(x/√2))` with `approximate = false`, the form BERT-class encoders and the Laya decision models were trained with (the two differ by up to 4.7e-4 near |x| ≈ 2.7). CPU: Abramowitz–Stegun 7.1.26 erf evaluated in double (|err| < 1.5e-7) with a JVM Vector API lane kernel; `GELU(approximate)` module, `network {}` `gelu(approximate)`, Java `TensorJavaOps.gelu(a, approximate)` / `erf(a)` and `SequentialModelBuilder.gelu(approximate)`; exact backward rule and `erfBackward`.
- **GELU carries its form as op metadata**: the flag is recorded as `parameters["approximate"]` on the graph node (`GeluOperation`, `ErfOperation`), read by `ComputeGraphExecutor`, the backward rule and the StableHLO converter, so the compiled path cannot silently diverge from eager execution. StableHLO lowers `erf` to `chlo.erf` and exact GELU to `0.5·x·(1 + chlo.erf(x·√½))`; one `GeluLowering` builder emits both forms.
- **Composite emission behind `OpGranularityPolicy`** (#1342 part 2): a `LoweringSpec` per fused-able op (`skainet.gelu`, `skainet.erf`) and `ConversionContext.emitComposite` emit `stablehlo.composite "<name>" {composite_attributes, decomposition = @fn, version}` plus one private decomposition function per (op, attributes, type) when a target's policy keeps the op fused; otherwise the same builder emits the decomposition inline. Helper functions go to a module trailer after the entry function so existing text tooling keeps finding `@main` first. First consumer of `OpGranularityPolicy.keepFused`.
- **`GeluApproximationLegalizationPass`** (`skainet-compile-opt`): targets without any erf lowering rewrite `gelu(approximate = false)` to the tanh form explicitly, recording `legalizedFrom` and `maxAbsError = 4.8e-4` on the node and a `GELU_APPROX_LEGALIZED` diagnostic, instead of a silent default. Registered per target through `TargetOptimizers.registerDagPasses`.
- **`@Lowering` annotation** and a *Lowering* column in the generated operator coverage matrix (`composite · decompose · native`); `operators.json` carries the field.

### Changed

- `TensorOps.gelu` gained the `approximate` parameter: implementors of the interface must update the override (callers are source-compatible through the default). The legacy recording decorator now records `gelu`/`erf` as graph operations instead of delegating them unrecorded.

### Fixed

- `DefaultCpuOps.gelu` printed a literal `${tensor.dtype}` in its unsupported-dtype message.

## [0.58.0] - 2026-10-12
Expand Down
4 changes: 2 additions & 2 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ authors:
orcid: https://orcid.org/0009-0006-7981-4075
- name: SKaiNET-developers contributors
website: https://github.com/SKaiNET-developers
version: "0.58.0"
date-released: "2026-10-12"
version: "0.59.0"
date-released: "2026-10-14"
license: MIT
repository-code: https://github.com/SKaiNET-developers/SKaiNET
url: https://skainet-developers.github.io/SKaiNET/
Expand Down
43 changes: 26 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Add the core dependencies (Gradle Kotlin DSL):
```kotlin
dependencies {
// Recommended: import the umbrella BOM and drop versions on the engine modules.
implementation(platform("sk.ainet:skainet-bom:0.58.0"))
implementation(platform("sk.ainet:skainet-bom:0.59.0"))

implementation("sk.ainet.core:skainet-lang-core")
implementation("sk.ainet.core:skainet-backend-cpu")
Expand Down Expand Up @@ -308,21 +308,24 @@ val withoutLabel = dataPipeline<RawDataset>()

---

## What's New in 0.58.0

Input front ends and model identity land as SKEEP-006:

- **One front-end contract for every input modality** — `skainet-frontend-core` defines
`FrontEnd`, `FrontEndSpec` and the text, audio, image and multimodal contracts; a resolver turns a
checkpoint view into the front ends a model needs. The text lane ships in `skainet-frontend-text`.
- **Tokenizers move out of io-core and cover more files** — Metaspace BPE with byte fallback,
Viterbi Unigram and WordPiece join byte-level BPE, SentencePiece and Tekken. A golden corpus
recorded with the Hugging Face `tokenizers` library guards exact id parity for GPT-2, Qwen2.5,
TinyLlama, T5, BERT, Gemma 4 and the two public Laya tokenizers.
- **Families are identities** — `skainet-model-identity` carries `ModelIdentity`, `CheckpointView`
and an immutable `ModelFamilyRegistry`; the old enum-style detection is deprecated.
- Everything that compiled against 0.57 still compiles: the io-core names are deprecated aliases
that forward to the new homes.
## What's New in 0.59.0

Exact GELU and lowering metadata (#1342):

- **`erf` and the exact GELU** — `gelu(approximate = false)` computes `0.5·x·(1 + erf(x/√2))`, the
form BERT-class encoders and the Laya decision models were trained with, on the CPU scalar kernel
and the JVM Vector API lanes. The default stays the tanh form, byte for byte; the exact backward
rule and `erfBackward` come with it.
- **The form travels as op metadata** — `parameters["approximate"]` sits on the graph node, so the
graph executor, the backward rule and the StableHLO export read the same flag instead of each
picking a default. StableHLO lowers `erf` to `chlo.erf`.
- **Fused ops as `stablehlo.composite`** — a `LoweringSpec` per op (`skainet.gelu`, `skainet.erf`)
emits a composite with a private decomposition function when a target's `OpGranularityPolicy`
keeps the op fused, and the inline decomposition otherwise, both from one builder. An explicit
`GeluApproximationLegalizationPass` records an exact→tanh rewrite on the node instead of
substituting silently, and `@Lowering` adds a *Lowering* column to the operator matrix.
- `TensorOps.gelu` gained a parameter: implementors update the override, callers are
source-compatible. The 0.58 io-core deprecation aliases stay at WARNING (ERROR in 0.60).

See [CHANGELOG.md](CHANGELOG.md) for full release notes, including every prior release.

Expand All @@ -348,6 +351,12 @@ We love contributions! Whether it's a new operator, documentation, or a bug fix:

Browse the full codebase documentation on [DeepWiki](https://deepwiki.com/SKaiNET-developers/SKaiNET).

### Contributors (0.59.0)

- **Michal Harakal** ([@michalharakal](https://github.com/michalharakal)) — exact GELU and `erf`
across the CPU kernels, graph executor and backward rules, the lowering-metadata path with
composite emission and the legalization pass, and the release

### Contributors (0.58.0)

- **Michal Harakal** ([@michalharakal](https://github.com/michalharakal)) — SKEEP-006: the
Expand Down Expand Up @@ -437,7 +446,7 @@ from it). Ready-to-paste BibTeX:
author = {Harakal, Michal and {SKaiNET-developers contributors}},
title = {{SKaiNET}: A {Kotlin} Multiplatform {AI} Framework},
year = {2026},
note = {Version 0.58.0. MIT License},
note = {Version 0.59.0. MIT License},
howpublished = {\url{https://github.com/SKaiNET-developers/SKaiNET}}
}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ asciidoc:
framework_name: SKaiNET
# Current SKaiNET release — bump once per release; referenced as
# {skainet_version} in dependency snippets (blocks need subs="attributes+").
skainet_version: 0.58.0
skainet_version: 0.59.0
ksp_version: 2.2.21-2.0.5
dokka_version: 2.1.0
asciidoctorj_version: 3.0.0
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= Kernel × platform support matrix
:description: Which compute-kernel provider serves each weight format on each KMP target.

Generated from `kernel-support.json` (version `0.58.0`) by `KernelSupportMatrixTest` — registry introspection of the registered `KernelProvider` implementations. Do not edit by hand; run `./gradlew generateKernelMatrix` to refresh.
Generated from `kernel-support.json` (version `0.59.0`) by `KernelSupportMatrixTest` — registry introspection of the registered `KernelProvider` implementations. Do not edit by hand; run `./gradlew generateKernelMatrix` to refresh.

Each cell is the best (highest-priority) provider that serves `Float32 × format` `matmul` on that platform: *native-ffm* (100) → *panama-vector* (50) → *scalar* (0). An empty cell (`—`) means no provider carries a kernel there (the format is dequant-to-FP32 only).

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= AI-NET Operators Reference

Generated from version `0.58.0` on 2026-10-14
Generated from version `0.59.0` on 2026-10-14

== Operators by Modality

Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/reference/ops-status-matrix.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= Operator Coverage Matrix
:description: Cross-backend status for every operator function in SKaiNET.

Generated from `operators.json` version `0.58.0` on 2026-10-14.
Generated from `operators.json` version `0.59.0` on 2026-10-14.

Rows are `Operator.function` pairs. The `Validated` column shows whether the function's documentation has been DARC-validated by a reviewer (see xref:contributing/darc-workflow.adoc[DARC workflow]). The `Lowering` column lists the compile-path forms the function declares with `@Lowering` (`composite` = a `stablehlo.composite` when a target keeps it fused, `decompose` = StableHLO/CHLO primitives, `native` = a 1:1 target op); `—` means undeclared. Remaining columns are backends that appear in any function's `statusByBackend` map — a missing entry means the backend makes no claim about the function (treat it as "unknown", not "not supported").

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ An Android project with Kotlin. Add the SKaiNET modules:
[source,kotlin]
----
dependencies {
implementation("sk.ainet.core:skainet-lang-core:0.58.0") // tensors, DSL, training
implementation("sk.ainet.core:skainet-backend-cpu:0.58.0") // CPU ops
implementation("sk.ainet.core:skainet-compile-dag:0.58.0") // autograd (training context)
implementation("sk.ainet.core:skainet-data-api:0.58.0") // Dataset / DataBatch
implementation("sk.ainet.core:skainet-data-simple:0.58.0") // embedded Iris
runtimeOnly("sk.ainet.core:skainet-backend-jni-cpu:0.58.0") // NEON kernels (see below)
implementation("sk.ainet.core:skainet-lang-core:0.59.0") // tensors, DSL, training
implementation("sk.ainet.core:skainet-backend-cpu:0.59.0") // CPU ops
implementation("sk.ainet.core:skainet-compile-dag:0.59.0") // autograd (training context)
implementation("sk.ainet.core:skainet-data-api:0.59.0") // Dataset / DataBatch
implementation("sk.ainet.core:skainet-data-simple:0.59.0") // embedded Iris
runtimeOnly("sk.ainet.core:skainet-backend-jni-cpu:0.59.0") // NEON kernels (see below)
}
----

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
GROUP=sk.ainet.core
VERSION_NAME=0.58.0
VERSION_NAME=0.59.0
POM_DESCRIPTION=SKaiNET

POM_URL=https://github.com/SKaiNET-developers/skainet/
Expand Down
Loading