I am working on the Gemini API Chat app. In debug APR app is running fine but in release build it gives an exception generativeai.type.InvalidStateException.
I can't find any documentation for that. Please try to help me out. Here is the code with HiltModule and ViewModel.
Also, I won't get any pro-guard rules fot that.
GeminiModule.kt
@Module
@InstallIn(SingletonComponent::class)
object GeminiModule {
@Provides
@Singleton
fun provideGemini(): GenerativeModel {
val harassmentSafety =
SafetySetting(HarmCategory.HARASSMENT, BlockThreshold.ONLY_HIGH)
val hateSpeechSafety =
SafetySetting(HarmCategory.HATE_SPEECH, BlockThreshold.MEDIUM_AND_ABOVE)
val config = generationConfig {
stopSequences = listOf(
"fuck",
"sex",
)
temperature = 0.9f
topK = 16
topP = 0.1f
}
return GenerativeModel(
modelName = "gemini-pro",
apiKey = BuildConfig.apiKey,
generationConfig = config,
safetySettings = listOf(
harassmentSafety, hateSpeechSafety
)
)
}
}
And ViewModel
@HiltViewModel
class ChatViewModel @Inject constructor(
private val generativeModel: GenerativeModel,
private val case: ChatUseCases,
private val mapper: ChatMessageToModelMapper
) : ViewModel() {
private var chat: Chat? = null
private val _uiState: MutableState<ChatUiState> =
mutableStateOf(ChatUiState())
val uiState: State<ChatUiState> = _uiState
private val _isLoading = mutableStateOf<Boolean>(false)
val isLoading: State<Boolean> get() = _isLoading
private var job: Job? = null
init {
getChat()
}
private fun getChat() = viewModelScope.launch {
val history = mapper.mapFromEntityList(case.getAllChat.invoke()).toContent()
chat = generativeModel.startChat(history)
_uiState.value = ChatUiState(
chat?.history?.map { content ->
// Map the initial messages
ChatMessage(
text = content.parts.first().asTextOrNull() ?: "",
participant = if (content.role == "user") Participant.USER else
Participant.MODEL,
)
} ?: emptyList()
)
}
fun cancelJob() {
try {
_isLoading.value = false
job?.cancel()
} catch (e: Exception) {
Log.e(TAGS.BIT_ERROR.name, "cancelJob: ${e.localizedMessage}")
}
}
fun sendMessage(userMessage: String) {
// Add a pending message
val userInput = ChatMessage(
text = userMessage, participant = Participant.USER,
)
_isLoading.value = true
_uiState.value.addMessage(
userInput
)
job = viewModelScope.launch {
try {
val response = chat!!.sendMessage(userMessage)
_isLoading.value = false
response.text?.let { modelResponse ->
val modelRes = ChatMessage(
text = modelResponse, participant = Participant.MODEL
)
mapper.mapToEntityList(
listOf(
_uiState.value.getLastMessage()!!
.copy(
linkedId = modelRes.id
),
modelRes.copy(
linkedId = _uiState.value.getLastMessage()!!.id
)
)
).forEach {
case.insertChat.invoke(it)
}
_uiState.value.addMessage(
modelRes
)
}
} catch (e: Exception) {
Log.d("AAA", "sendMessage: $e")
if (e is PromptBlockedException) {
_uiState.value.addMessage(
ChatMessage(
text = "The input you provided contains offensive language, which goes against our community guidelines " +
"and standards. Please refrain from using inappropriate language and ensure that your input is " +
"respectful and adheres to our guidelines. If you have any questions or concerns, feel free " +
"to contact our support team.",
participant = Participant.ERROR
)
)
return@launch
}
_uiState.value.addMessage(
ChatMessage(
text = e.localizedMessage ?: "Unknown error",
participant = Participant.ERROR
)
)
} finally {
_isLoading.value = false
job = null
}
}
}
}