Skip to content

Commit 02ebfb8

Browse files
Merge pull request #14 from SKaiNET-developers/feature/MNIST-rework-0.3.0
Feature/mnist rework 0.3.0
2 parents f602c44 + 6cac26a commit 02ebfb8

191 files changed

Lines changed: 9011 additions & 5 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

MNISTDemo/.gitignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
*.iml
2+
.kotlin
3+
.gradle
4+
**/build/
5+
xcuserdata
6+
!src/**/build/
7+
local.properties
8+
.idea
9+
.DS_Store
10+
captures
11+
.externalNativeBuild
12+
.cxx
13+
*.xcodeproj/*
14+
!*.xcodeproj/project.pbxproj
15+
!*.xcodeproj/xcshareddata/
16+
!*.xcodeproj/project.xcworkspace/
17+
!*.xcworkspace/contents.xcworkspacedata
18+
**/xcshareddata/WorkspaceSettings.xcsettings

MNISTDemo/README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
This is a Kotlin Multiplatform project targeting Android, iOS, Web, Desktop, Server.
2+
3+
Clean architecture overview (MNIST demo)
4+
- Presentation (UI/ViewModel): Compose screens and view models. UI talks only to use cases, not to model types or storage.
5+
- Domain (Entities + Use Cases + Ports):
6+
- Entities: image and model identifiers used by the demo (for example, ModelId).
7+
- Use cases: LoadModel and ClassifyDigit orchestrate model loading and classification.
8+
- Ports (interfaces): DigitClassifier, ModelWeightsRepository.
9+
- Data (Repositories + Data Sources): ModelWeightsRepositoryImpl composes cache and local resource readers to provide model weights.
10+
- Framework/DI (Platform Adapters): expect/actual ResourceReader and a lightweight ServiceLocator for wiring dependencies.
11+
12+
Simple class diagram (Mermaid)
13+
14+
```mermaid
15+
classDiagram
16+
class ServiceLocator
17+
class ModelId
18+
19+
class DigitClassifierFactory {
20+
+create(modelId: ModelId): DigitClassifier
21+
}
22+
23+
class DigitClassifier {
24+
+suspend loadModel(modelId: ModelId)
25+
+classify(image): Int
26+
}
27+
28+
class ModelWeightsRepository {
29+
+suspend getWeights(modelId: ModelId): ByteArray
30+
}
31+
32+
class ModelWeightsRepositoryImpl
33+
class ModelWeightsCacheDataSource
34+
class ModelWeightsLocalDataSource
35+
class ResourceReader {
36+
+suspend read(path: String): ByteArray?
37+
}
38+
39+
class LoadModel
40+
class ClassifyDigit
41+
42+
ServiceLocator --> DigitClassifierFactory : provides
43+
ServiceLocator --> ModelWeightsRepository : provides
44+
DigitClassifierFactory --> DigitClassifier : creates
45+
46+
LoadModel --> ModelWeightsRepository : getWeights()
47+
LoadModel --> DigitClassifier : loadModel()
48+
ClassifyDigit --> DigitClassifier : classify()
49+
50+
ModelWeightsRepository <|.. ModelWeightsRepositoryImpl
51+
ModelWeightsRepositoryImpl --> ModelWeightsCacheDataSource
52+
ModelWeightsRepositoryImpl --> ModelWeightsLocalDataSource
53+
ModelWeightsLocalDataSource --> ResourceReader
54+
```
55+
56+
Entry points for developers
57+
- ServiceLocator: central place to wire platform resources and obtain a classifier.
58+
- Configure once at app startup: ServiceLocator.configure(resourceReader, digitClassifierFactory)
59+
- Get a classifier by model id: ServiceLocator.provideDigitClassifier(modelId)
60+
- Use cases:
61+
- LoadModel(modelWeightsRepository, digitClassifier).invoke(modelId)
62+
- ClassifyDigit(digitClassifier).invoke(image)
63+
64+
See also
65+
- PRD-clean.md describes the architecture in detail, design goals, and boundaries between layers.
66+
- clean-task.md tracks the implementation checklist and testing/migration items.
67+
68+
* `/composeApp` is for code that will be shared across your Compose Multiplatform applications.
69+
It contains several subfolders:
70+
- `commonMain` is for code that’s common for all targets.
71+
- Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name.
72+
For example, if you want to use Apple’s CoreCrypto for the iOS part of your Kotlin app,
73+
`iosMain` would be the right folder for such calls.
74+
75+
* `/iosApp` contains iOS applications. Even if you’re sharing your UI with Compose Multiplatform,
76+
you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.
77+
78+
* `/server` is for the Ktor server application.
79+
80+
* `/shared` is for the code that will be shared between all targets in the project.
81+
The most important subfolder is `commonMain`. If preferred, you can add code to the platform-specific folders here too.
82+
83+
84+
Learn more about [Kotlin Multiplatform](https://www.jetbrains.com/help/kotlin-multiplatform-dev/get-started.html),
85+
[Compose Multiplatform](https://github.com/JetBrains/compose-multiplatform/#compose-multiplatform),
86+
[Kotlin/Wasm](https://kotl.in/wasm/)
87+
88+
We would appreciate your feedback on Compose/Web and Kotlin/Wasm in the public Slack channel [#compose-web](https://slack-chats.kotlinlang.org/c/compose-web).
89+
If you face any issues, please report them on [GitHub](https://github.com/JetBrains/compose-multiplatform/issues).
90+
91+
You can open the web application by running the `:composeApp:wasmJsBrowserDevelopmentRun` Gradle task.

MNISTDemo/build.gradle.kts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
plugins {
2+
// this is necessary to avoid the plugins to be loaded multiple times
3+
// in each subproject's classloader
4+
alias(libs.plugins.androidApplication) apply false
5+
alias(libs.plugins.androidLibrary) apply false
6+
alias(libs.plugins.composeMultiplatform) apply false
7+
alias(libs.plugins.composeCompiler) apply false
8+
alias(libs.plugins.kotlinJvm) apply false
9+
alias(libs.plugins.kotlinMultiplatform) apply false
10+
}
11+
12+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>().configureEach {
13+
compilerOptions {
14+
freeCompilerArgs = listOf("-Xdownload-sources=true")
15+
}
16+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
2+
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
3+
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
4+
5+
plugins {
6+
alias(libs.plugins.kotlinMultiplatform)
7+
alias(libs.plugins.androidApplication)
8+
alias(libs.plugins.composeMultiplatform)
9+
alias(libs.plugins.composeCompiler)
10+
}
11+
12+
kotlin {
13+
jvmToolchain(21)
14+
15+
androidTarget()
16+
17+
jvm("desktop")
18+
19+
@OptIn(ExperimentalWasmDsl::class)
20+
wasmJs {
21+
browser {
22+
val rootDirPath = project.rootDir.path
23+
val projectDirPath = project.projectDir.path
24+
commonWebpackConfig {
25+
outputFileName = "composeApp.js"
26+
devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply {
27+
static = (static ?: mutableListOf()).apply {
28+
// Serve sources to debug inside browser
29+
add(rootDirPath)
30+
add(projectDirPath)
31+
}
32+
}
33+
}
34+
}
35+
binaries.executable()
36+
}
37+
38+
sourceSets {
39+
val desktopMain by getting
40+
41+
androidMain.dependencies {
42+
implementation(compose.preview)
43+
implementation(libs.androidx.activity.compose)
44+
}
45+
commonMain.dependencies {
46+
47+
implementation(compose.runtime)
48+
implementation(compose.foundation)
49+
// Material Design 3
50+
implementation(compose.material3)
51+
// Keep Material Design 2 for backward compatibility during migration
52+
implementation(compose.material)
53+
implementation(compose.ui)
54+
implementation(compose.components.resources)
55+
implementation(compose.components.uiToolingPreview)
56+
implementation(libs.androidx.lifecycle.viewmodel)
57+
implementation(libs.androidx.lifecycle.runtimeCompose)
58+
implementation(projects.shared)
59+
60+
implementation(libs.kotlinx.io.core)
61+
62+
}
63+
desktopMain.dependencies {
64+
implementation(compose.desktop.currentOs)
65+
implementation(libs.kotlinx.coroutinesSwing)
66+
// JVM-optimized SKaiNET backend
67+
implementation(libs.skainet.backend.cpu.jvm)
68+
}
69+
}
70+
}
71+
72+
android {
73+
namespace = "sk.ainet.app.sample.mnist"
74+
compileSdk = libs.versions.android.compileSdk.get().toInt()
75+
76+
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
77+
sourceSets["main"].res.srcDirs("src/androidMain/res")
78+
sourceSets["main"].resources.srcDirs("src/commonMain/resources")
79+
80+
defaultConfig {
81+
applicationId = "sk.ai.net.samples.kmp.mnist.demo"
82+
minSdk = libs.versions.android.minSdk.get().toInt()
83+
targetSdk = libs.versions.android.targetSdk.get().toInt()
84+
versionCode = 1
85+
versionName = "1.0"
86+
}
87+
packaging {
88+
resources {
89+
excludes += "/META-INF/{AL2.0,LGPL2.1}"
90+
}
91+
}
92+
buildTypes {
93+
getByName("release") {
94+
isMinifyEnabled = false
95+
}
96+
}
97+
compileOptions {
98+
sourceCompatibility = JavaVersion.VERSION_21
99+
targetCompatibility = JavaVersion.VERSION_21
100+
}
101+
buildFeatures {
102+
compose = true
103+
}
104+
dependencies {
105+
debugImplementation(compose.uiTooling)
106+
}
107+
}
108+
109+
dependencies {
110+
//testImplementation(libs.junit.jupiter)
111+
//testImplementation(libs.junit)
112+
}
113+
114+
compose.desktop {
115+
application {
116+
mainClass = "sk.ai.net.samples.kmp.mnist.demo.MainKt"
117+
118+
nativeDistributions {
119+
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
120+
packageName = "sk.ai.net.samples.kmp.mnist.demo"
121+
packageVersion = "1.0.0"
122+
}
123+
}
124+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<application
5+
android:allowBackup="true"
6+
android:icon="@mipmap/ic_launcher"
7+
android:label="@string/app_name"
8+
android:roundIcon="@mipmap/ic_launcher_round"
9+
android:supportsRtl="true"
10+
android:theme="@android:style/Theme.Material.Light.NoActionBar">
11+
<activity
12+
android:exported="true"
13+
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden|mnc|colorMode|density|fontScale|fontWeightAdjustment|keyboard|layoutDirection|locale|mcc|navigation|smallestScreenSize|touchscreen|uiMode"
14+
android:name="com.kkon.kmp.ai.mnist.demo.MainActivity">
15+
<intent-filter>
16+
<action android:name="android.intent.action.MAIN" />
17+
18+
<category android:name="android.intent.category.LAUNCHER" />
19+
</intent-filter>
20+
</activity>
21+
</application>
22+
23+
</manifest>

0 commit comments

Comments
 (0)