Skip to content

Commit b957d7a

Browse files
#updating proguard rules, serilaization, crashanalystic for ai catelog parsing.
1 parent 311ca1c commit b957d7a

4 files changed

Lines changed: 85 additions & 45 deletions

File tree

core/ai/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ android {
2929
buildConfigField("String", "HUGGING_FACE_AUTH_TOKEN", getSecret("HUGGING_FACE_AUTH_TOKEN"))
3030
buildConfigField("String", "GIST_ACCESS_TOKEN", getSecret("GIST_ACCESS_TOKEN"))
3131
buildConfigField("String", "AI_CATELOG_GIST_URL", getSecret("AI_CATELOG_GIST_URL"))
32+
33+
consumerProguardFiles "proguard-rules.pro"
3234
}
3335

3436
compileOptions {

core/ai/proguard-rules.pro

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# kotlinx-serialization specific rules
2+
-keepattributes Annotation, Signature, InnerClasses, EnclosingMethod
3+
4+
# Keep serializable classes and their members
5+
-keepclassmembers class * {
6+
@kotlinx.serialization.Serializable *;
7+
}
8+
9+
# Keep the serializer for all serializable classes
10+
-keep class *$$serializer { *; }
11+
12+
# Keep specific Gist classes just in case
13+
-keep class com.mintanable.notethepad.feature_ai.data.repository.GistWrapper { *; }
14+
-keep class com.mintanable.notethepad.feature_ai.data.repository.GistFile { *; }

core/ai/src/main/java/com/mintanable/notethepad/feature_ai/data/repository/AiModelRepositoryImpl.kt

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import com.mintanable.notethepad.core.common.DispatcherProvider
66
import com.mintanable.notethepad.core.model.ai.AiModel
77
import com.mintanable.notethepad.core.model.ai.AiModelCatalog
88
import com.mintanable.notethepad.feature_ai.BuildConfig
9+
import com.google.firebase.crashlytics.FirebaseCrashlytics
10+
import kotlinx.serialization.SerialName
911
import kotlinx.serialization.Serializable
1012
import kotlinx.serialization.json.Json
1113
import com.mintanable.notethepad.feature_ai.domain.repository.AiModelRepository
@@ -78,6 +80,7 @@ class AiModelRepositoryImpl @Inject constructor(
7880
}
7981
} catch (e: Exception) {
8082
Log.e("kptest", "Error processing remote AI catalog", e)
83+
FirebaseCrashlytics.getInstance().recordException(e)
8184
}
8285
}.flowOn(dispatcherProvider.io)
8386

@@ -125,19 +128,34 @@ class AiModelRepositoryImpl @Inject constructor(
125128
val gistResponse = response.body.string()
126129

127130
if (!gistResponse.isNullOrEmpty()) {
128-
val wrapper = json.decodeFromString<GistWrapper>(gistResponse)
129-
val content = wrapper.files?.get(MODEL_CATALOG_FILENAME)?.content
130-
131-
if (content != null) {
132-
val internalFile = File(context.filesDir, MODEL_CATALOG_FILENAME)
133-
internalFile.writeText(content)
134-
Log.d("kptest", "Catalog updated from Gist")
131+
try {
132+
val wrapper = json.decodeFromString<GistWrapper>(gistResponse)
133+
val content = wrapper.files?.get(MODEL_CATALOG_FILENAME)?.content
134+
135+
if (content != null) {
136+
val internalFile = File(context.filesDir, MODEL_CATALOG_FILENAME)
137+
internalFile.writeText(content)
138+
Log.d("kptest", "Catalog updated from Gist")
139+
} else {
140+
Log.w("kptest", "Catalog content is null for $MODEL_CATALOG_FILENAME")
141+
FirebaseCrashlytics.getInstance().log("Gist catalog content is null for $MODEL_CATALOG_FILENAME")
142+
}
143+
} catch (e: Exception) {
144+
Log.e("kptest", "Failed to parse Gist response", e)
145+
FirebaseCrashlytics.getInstance().apply {
146+
log("Failed to parse Gist response: $gistResponse")
147+
recordException(e)
148+
}
135149
}
136150
}
151+
} else {
152+
Log.e("kptest", "Gist fetch unsuccessful: ${response.code}")
153+
FirebaseCrashlytics.getInstance().log("Gist fetch unsuccessful: ${response.code}")
137154
}
138155
}
139156
} catch (e: Exception) {
140157
Log.e("kptest", "Failed to fetch catalog from Gist $e")
158+
FirebaseCrashlytics.getInstance().recordException(e)
141159
}
142160
}
143161

@@ -149,6 +167,7 @@ class AiModelRepositoryImpl @Inject constructor(
149167
} else null
150168
} catch (e: Exception) {
151169
Log.e("kptest", "Failed to parse internal catalog", e)
170+
FirebaseCrashlytics.getInstance().recordException(e)
152171
null
153172
}
154173
}
@@ -161,17 +180,18 @@ class AiModelRepositoryImpl @Inject constructor(
161180
.let { json.decodeFromString<AiModelCatalog>(it) }
162181
} catch (e: Exception) {
163182
Log.e("kptest", "Failed to parse assets catalog", e)
183+
FirebaseCrashlytics.getInstance().recordException(e)
164184
null
165185
}
166186
}
167187
}
168188

169189
@Serializable
170190
data class GistWrapper(
171-
val files: Map<String, GistFile>? = null
191+
@SerialName("files") val files: Map<String, GistFile>? = null
172192
)
173193

174194
@Serializable
175195
data class GistFile(
176-
val content: String? = null
196+
@SerialName("content") val content: String? = null
177197
)

core/model/src/main/java/com/mintanable/notethepad/core/model/ai/AiModel.kt

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,31 @@ import kotlinx.serialization.SerialName
44
import kotlinx.serialization.Serializable
55

66
@Serializable
7-
data class PromptTemplate(val title: String, val description: String, val prompt: String)
7+
data class PromptTemplate(
8+
@SerialName("title") val title: String,
9+
@SerialName("description") val description: String,
10+
@SerialName("prompt") val prompt: String
11+
)
812

913
@Serializable
1014
data class AiModel(
11-
val name: String,
12-
val displayName: String = "",
13-
val info: String = "",
14-
val bestForTaskIds: List<String> = emptyList(),
15-
val minDeviceMemoryInGb: Int? = null,
16-
val url: String = "",
17-
val sizeInBytes: Long = 0L,
18-
val downloadFileName: String = "_",
19-
val version: String = "_",
20-
val isLlm: Boolean = false,
21-
val llmPromptTemplates: List<PromptTemplate> = emptyList(),
22-
val llmSupportImage: Boolean = false,
23-
val llmSupportAudio: Boolean = false,
24-
val llmMaxToken: Int = 0,
25-
val accelerators: List<Accelerator> = emptyList(),
26-
val imported: Boolean = false,
27-
val isDownloaded: Boolean = false,
15+
@SerialName("name") val name: String,
16+
@SerialName("displayName") val displayName: String = "",
17+
@SerialName("info") val info: String = "",
18+
@SerialName("bestForTaskIds") val bestForTaskIds: List<String> = emptyList(),
19+
@SerialName("minDeviceMemoryInGb") val minDeviceMemoryInGb: Int? = null,
20+
@SerialName("url") val url: String = "",
21+
@SerialName("sizeInBytes") val sizeInBytes: Long = 0L,
22+
@SerialName("downloadFileName") val downloadFileName: String = "_",
23+
@SerialName("version") val version: String = "_",
24+
@SerialName("isLlm") val isLlm: Boolean = false,
25+
@SerialName("llmPromptTemplates") val llmPromptTemplates: List<PromptTemplate> = emptyList(),
26+
@SerialName("llmSupportImage") val llmSupportImage: Boolean = false,
27+
@SerialName("llmSupportAudio") val llmSupportAudio: Boolean = false,
28+
@SerialName("llmMaxToken") val llmMaxToken: Int = 0,
29+
@SerialName("accelerators") val accelerators: List<Accelerator> = emptyList(),
30+
@SerialName("imported") val imported: Boolean = false,
31+
@SerialName("isDownloaded") val isDownloaded: Boolean = false,
2832
)
2933

3034
@Serializable
@@ -36,32 +40,32 @@ enum class Accelerator(val label: String) {
3640

3741
@Serializable
3842
data class AiModelCatalog(
39-
val models: List<AiModelEntry>? = emptyList()
43+
@SerialName("models") val models: List<AiModelEntry>? = emptyList()
4044
)
4145

4246
@Serializable
4347
data class ModelDefaultConfig(
44-
val topK: Int? = 0,
45-
val topP: Float? = 0f,
46-
val temperature: Float? = 0f,
47-
val maxTokens: Int? = 1024,
48-
val accelerators: String? = ""
48+
@SerialName("topK") val topK: Int? = 0,
49+
@SerialName("topP") val topP: Float? = 0f,
50+
@SerialName("temperature") val temperature: Float? = 0f,
51+
@SerialName("maxTokens") val maxTokens: Int? = 1024,
52+
@SerialName("accelerators") val accelerators: String? = ""
4953
)
5054

5155
@Serializable
5256
data class AiModelEntry(
53-
val name: String? = "",
54-
val modelId: String? = "",
55-
val modelFile: String? = "",
56-
val description: String? = "",
57-
val sizeInBytes: Long? = 0L,
58-
val minDeviceMemoryInGb: Int? = 0,
59-
val commitHash: String? = "",
60-
val llmSupportImage: Boolean? = false,
61-
val llmSupportAudio: Boolean? = false,
62-
val defaultConfig: ModelDefaultConfig? = null,
63-
val taskTypes: List<String>? = emptyList(),
64-
val bestForTaskTypes: List<String>? = emptyList()
57+
@SerialName("name") val name: String? = "",
58+
@SerialName("modelId") val modelId: String? = "",
59+
@SerialName("modelFile") val modelFile: String? = "",
60+
@SerialName("description") val description: String? = "",
61+
@SerialName("sizeInBytes") val sizeInBytes: Long? = 0L,
62+
@SerialName("minDeviceMemoryInGb") val minDeviceMemoryInGb: Int? = 0,
63+
@SerialName("commitHash") val commitHash: String? = "",
64+
@SerialName("llmSupportImage") val llmSupportImage: Boolean? = false,
65+
@SerialName("llmSupportAudio") val llmSupportAudio: Boolean? = false,
66+
@SerialName("defaultConfig") val defaultConfig: ModelDefaultConfig? = null,
67+
@SerialName("taskTypes") val taskTypes: List<String>? = emptyList(),
68+
@SerialName("bestForTaskTypes") val bestForTaskTypes: List<String>? = emptyList()
6569
) {
6670
fun toAiModel(): AiModel {
6771
val downloadUrl = "https://huggingface.co/${modelId ?: ""}/resolve/${commitHash ?: "main"}/${modelFile ?: ""}?download=true"

0 commit comments

Comments
 (0)