This video shows very quick steps to create your own AI based chatbot based on Google’s Gemini in less than 10 minutes.
It refers to the below page for the steps:
https://developer.android.com/studio/preview/gemini-template
It uses – Android Studio Jellyfish | 2023.3.1 Canary 11 version for demo.
I hope you like this video. For any questions, suggestions or appreciation please contact us at: https://programmerworld.co/contact/ or email at: programmerworld1990@gmail.com
Complete source code and other details:
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.ai.sample.feature.chat
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Send
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.google.ai.sample.GenerativeViewModelFactory
import com.google.ai.sample.R
import com.google.ai.sample.ui.theme.GenerativeAISample
import kotlinx.coroutines.launch
@Composable
internal fun ChatRoute(
chatViewModel: ChatViewModel = viewModel(factory = GenerativeViewModelFactory)
) {
val chatUiState by chatViewModel.uiState.collectAsState()
val listState = rememberLazyListState()
val coroutineScope = rememberCoroutineScope()
Scaffold(
bottomBar = {
MessageInput(
onSendMessage = { inputText ->
chatViewModel.sendMessage(inputText)
},
resetScroll = {
coroutineScope.launch {
listState.scrollToItem(0)
}
}
)
}
) { paddingValues ->
Column(
modifier = Modifier
.padding(paddingValues)
.fillMaxSize()
) {
// Messages List
ChatList(chatUiState.messages, listState)
}
}
}
@Composable
fun ChatList(
chatMessages: List<ChatMessage>,
listState: LazyListState
) {
LazyColumn(
reverseLayout = true,
state = listState
) {
items(chatMessages.reversed()) { message ->
ChatBubbleItem(message)
}
}
}
@Composable
fun ChatBubbleItem(
chatMessage: ChatMessage
) {
val isModelMessage = chatMessage.participant == Participant.MODEL ||
chatMessage.participant == Participant.ERROR
val backgroundColor = when (chatMessage.participant) {
Participant.MODEL -> MaterialTheme.colorScheme.primaryContainer
Participant.USER -> MaterialTheme.colorScheme.tertiaryContainer
Participant.ERROR -> MaterialTheme.colorScheme.errorContainer
}
val bubbleShape = if (isModelMessage) {
RoundedCornerShape(4.dp, 20.dp, 20.dp, 20.dp)
} else {
RoundedCornerShape(20.dp, 4.dp, 20.dp, 20.dp)
}
val horizontalAlignment = if (isModelMessage) {
Alignment.Start
} else {
Alignment.End
}
Column(
horizontalAlignment = horizontalAlignment,
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 4.dp)
.fillMaxWidth()
) {
Text(
text = chatMessage.participant.name,
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.padding(bottom = 4.dp)
)
Row {
if (chatMessage.isPending) {
CircularProgressIndicator(
modifier = Modifier
.align(Alignment.CenterVertically)
.padding(all = 8.dp)
)
}
BoxWithConstraints {
Card(
colors = CardDefaults.cardColors(containerColor = backgroundColor),
shape = bubbleShape,
modifier = Modifier.widthIn(0.dp, maxWidth * 0.9f)
) {
Text(
text = chatMessage.text,
modifier = Modifier.padding(16.dp)
)
}
}
}
}
}
@Composable
fun MessageInput(
onSendMessage: (String) -> Unit,
resetScroll: () -> Unit = {}
) {
var userMessage by rememberSaveable { mutableStateOf("") }
ElevatedCard(
modifier = Modifier
.fillMaxWidth()
) {
Row(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
) {
OutlinedTextField(
value = userMessage,
label = { Text(stringResource(R.string.chat_label)) },
onValueChange = { userMessage = it },
keyboardOptions = KeyboardOptions(
capitalization = KeyboardCapitalization.Sentences,
),
modifier = Modifier
.align(Alignment.CenterVertically)
.fillMaxWidth()
.weight(0.85f)
)
IconButton(
onClick = {
if (userMessage.isNotBlank()) {
onSendMessage(userMessage)
userMessage = ""
resetScroll()
}
},
modifier = Modifier
.padding(start = 16.dp)
.align(Alignment.CenterVertically)
.fillMaxWidth()
.weight(0.15f)
) {
Icon(
Icons.Default.Send,
contentDescription = stringResource(R.string.action_send),
modifier = Modifier
)
}
}
}
}
/*
* Copyright 2023 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.ai.sample.feature.chat
import java.util.UUID
enum class Participant {
USER, MODEL, ERROR
}
data class ChatMessage(
val id: String = UUID.randomUUID().toString(),
var text: String = "",
val participant: Participant = Participant.USER,
var isPending: Boolean = false
)
Screenshots:
Complete Project Folder is available in the below path Link:
https://drive.google.com/file/d/1peDcaxgAzsVIowW2awicZaMoTn8hfYzm/view?usp=drive_link
Excerpt:
This video tutorial demonstrates the swift creation of an AI-based chatbot using Google’s Gemini in under 10 minutes. It utilizes the Android Studio Jellyfish | 2023.3.1 Canary 11 version for the demonstration. The complete source code and additional details are accessible at the provided link. For inquiries, suggestions, or appreciation, contact via the given website or email address. Additionally, the project folder is available for download through the provided link.