Skip to content

Commit 52fcf68

Browse files
committed
feat: Add ImageGenerations API
1 parent d58093b commit 52fcf68

File tree

15 files changed

+217
-1
lines changed

15 files changed

+217
-1
lines changed

sample/android/src/main/java/co/yml/ychat/android/MainViewModel.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package co.yml.ychat.android
22

3+
import android.util.Log
34
import androidx.compose.runtime.mutableStateListOf
45
import androidx.compose.runtime.mutableStateOf
56
import androidx.lifecycle.MutableLiveData
67
import androidx.lifecycle.ViewModel
78
import androidx.lifecycle.viewModelScope
89
import co.yml.ychat.YChat
10+
import co.yml.ychat.YChat.Callback
911
import kotlinx.coroutines.delay
1012
import kotlinx.coroutines.launch
1113

@@ -20,6 +22,11 @@ class MainViewModel(private val chatGpt: YChat) : ViewModel() {
2022
)
2123
}
2224

25+
private val imageGenerations by lazy {
26+
chatGpt.imageGenerations()
27+
.setResults(2)
28+
}
29+
2330
private val _items = mutableStateListOf<MessageItem>()
2431
val items = _items
2532

@@ -41,6 +48,20 @@ class MainViewModel(private val chatGpt: YChat) : ViewModel() {
4148
}
4249
}
4350

51+
fun onImageRequest(prompt: String) {
52+
viewModelScope.launch {
53+
imageGenerations.execute(prompt, object: Callback<List<String>> {
54+
override fun onSuccess(result: List<String>) {
55+
Log.d("callback", "onSuccess: $result")
56+
}
57+
58+
override fun onError(throwable: Throwable) {
59+
Log.d("callback", "onError: $throwable")
60+
}
61+
})
62+
}
63+
}
64+
4465
private suspend fun showTypingAnimation(message: String) {
4566
items.add(MessageItem(message = message, isOut = true))
4667
delay((1000..2000).random().toLong())

sample/android/src/main/java/co/yml/ychat/android/ui/SendMessageLayout.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ fun SendMessageLayout() {
9191
.background(if (textFieldState.isNotEmpty() && isLoading.not()) colorResource(id = R.color.softBlue) else colorResource(id = R.color.opaqueWhite)),
9292
onClick = {
9393
scope.launch {
94-
viewModel.onSendMessage(textFieldState, typingString)
94+
//viewModel.onSendMessage(textFieldState, typingString)
95+
viewModel.onImageRequest(textFieldState)
9596
textFieldState = ""
9697
}
9798
},

ychat/src/commonMain/kotlin/co/yml/ychat/YChat.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package co.yml.ychat
22

33
import co.yml.ychat.entrypoint.features.ChatCompletions
44
import co.yml.ychat.entrypoint.features.Completion
5+
import co.yml.ychat.entrypoint.features.ImageGenerations
56
import co.yml.ychat.entrypoint.impl.YChatImpl
67
import kotlin.jvm.JvmStatic
78
import kotlin.jvm.Volatile
@@ -77,6 +78,8 @@ interface YChat {
7778
*/
7879
fun chatCompletions(): ChatCompletions
7980

81+
fun imageGenerations(): ImageGenerations
82+
8083
/**
8184
* Callback is an interface used for handling the results of an operation.
8285
* It provides two methods, `onSuccess` and `onError`, for handling the success

ychat/src/commonMain/kotlin/co/yml/ychat/data/api/ChatGptApi.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ import co.yml.ychat.data.dto.ChatCompletionParamsDto
44
import co.yml.ychat.data.dto.ChatCompletionsDto
55
import co.yml.ychat.data.dto.CompletionDto
66
import co.yml.ychat.data.dto.CompletionParamsDto
7+
import co.yml.ychat.data.dto.ImageGenerationsDto
8+
import co.yml.ychat.data.dto.ImageGenerationsParamsDto
79
import co.yml.ychat.data.infrastructure.ApiResult
810

911
internal interface ChatGptApi {
1012

1113
suspend fun completion(paramsDto: CompletionParamsDto): ApiResult<CompletionDto>
1214

1315
suspend fun chatCompletions(paramsDto: ChatCompletionParamsDto): ApiResult<ChatCompletionsDto>
16+
17+
suspend fun imageGenerations(paramsDto: ImageGenerationsParamsDto): ApiResult<ImageGenerationsDto>
1418
}

ychat/src/commonMain/kotlin/co/yml/ychat/data/api/impl/ChatGptApiImpl.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import co.yml.ychat.data.dto.ChatCompletionParamsDto
55
import co.yml.ychat.data.dto.ChatCompletionsDto
66
import co.yml.ychat.data.dto.CompletionDto
77
import co.yml.ychat.data.dto.CompletionParamsDto
8+
import co.yml.ychat.data.dto.ImageGenerationsDto
9+
import co.yml.ychat.data.dto.ImageGenerationsParamsDto
810
import co.yml.ychat.data.infrastructure.ApiExecutor
911
import co.yml.ychat.data.infrastructure.ApiResult
1012
import io.ktor.http.HttpMethod
@@ -26,4 +28,12 @@ internal class ChatGptApiImpl(private val apiExecutor: ApiExecutor) : ChatGptApi
2628
.setBody(paramsDto)
2729
.execute()
2830
}
31+
32+
override suspend fun imageGenerations(paramsDto: ImageGenerationsParamsDto): ApiResult<ImageGenerationsDto> {
33+
return apiExecutor
34+
.setEndpoint("v1/images/generations")
35+
.setHttpMethod(HttpMethod.Post)
36+
.setBody(paramsDto)
37+
.execute()
38+
}
2939
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package co.yml.ychat.data.dto
2+
3+
import co.yml.ychat.domain.model.ImageGenerated
4+
import kotlinx.serialization.SerialName
5+
import kotlinx.serialization.Serializable
6+
7+
@Serializable
8+
internal data class ImageGenerationsDto(
9+
@SerialName("created")
10+
val created: Long,
11+
@SerialName("data")
12+
val data: List<ImageGenerated>,
13+
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package co.yml.ychat.data.dto
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
@Serializable
7+
internal data class ImageGenerationsParamsDto(
8+
@SerialName("prompt")
9+
val prompt: String,
10+
@SerialName("n")
11+
val results: Int,
12+
@SerialName("size")
13+
val size: String,
14+
@SerialName("response_format")
15+
val responseFormat: String,
16+
@SerialName("user")
17+
val user: String,
18+
)

ychat/src/commonMain/kotlin/co/yml/ychat/di/module/LibraryModule.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import co.yml.ychat.data.storage.ChatLogStorage
77
import co.yml.ychat.di.provider.NetworkProvider
88
import co.yml.ychat.domain.usecases.ChatCompletionsUseCase
99
import co.yml.ychat.domain.usecases.CompletionUseCase
10+
import co.yml.ychat.domain.usecases.ImageGenerationsUseCase
1011
import co.yml.ychat.entrypoint.features.ChatCompletions
1112
import co.yml.ychat.entrypoint.features.Completion
13+
import co.yml.ychat.entrypoint.features.ImageGenerations
1214
import co.yml.ychat.entrypoint.impl.ChatCompletionsImpl
1315
import co.yml.ychat.entrypoint.impl.CompletionImpl
16+
import co.yml.ychat.entrypoint.impl.ImageGenerationsImpl
1417
import kotlinx.coroutines.Dispatchers
1518
import org.koin.core.module.Module
1619
import org.koin.dsl.module
@@ -23,11 +26,13 @@ internal class LibraryModule(private val apiKey: String) {
2326
private val entrypointModule = module {
2427
factory<Completion> { CompletionImpl(Dispatchers.Default, get()) }
2528
factory<ChatCompletions> { ChatCompletionsImpl(Dispatchers.Default, get()) }
29+
factory<ImageGenerations> { ImageGenerationsImpl(Dispatchers.Default, get()) }
2630
}
2731

2832
private val domainModule = module {
2933
factory { CompletionUseCase(get(), get()) }
3034
factory { ChatCompletionsUseCase(get()) }
35+
factory { ImageGenerationsUseCase(get()) }
3136
}
3237

3338
private val dataModule = module {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package co.yml.ychat.domain.mapper
2+
3+
import co.yml.ychat.data.dto.ImageGenerationsDto
4+
import co.yml.ychat.data.dto.ImageGenerationsParamsDto
5+
import co.yml.ychat.domain.model.ImageGenerated
6+
import co.yml.ychat.domain.model.ImageGenerationsParams
7+
8+
internal fun ImageGenerationsDto.toImageGenerated(): List<ImageGenerated> {
9+
return this.data.map {
10+
ImageGenerated(it.url)
11+
}
12+
}
13+
14+
15+
internal fun ImageGenerationsParams.toImageGenerationsParamsDto(): ImageGenerationsParamsDto {
16+
return ImageGenerationsParamsDto(
17+
prompt = this.prompt,
18+
results = this.results,
19+
size = this.size,
20+
responseFormat = this.responseFormat,
21+
user = this.user
22+
)
23+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package co.yml.ychat.domain.model
2+
3+
import kotlinx.serialization.SerialName
4+
import kotlinx.serialization.Serializable
5+
6+
/**
7+
* Represents a message in a conversation, consisting of a [role] indicating the speaker
8+
* (e.g., “system”, “user” or “assistant”), and the [content] of the message sent by the speaker.
9+
* @property role The role of the speaker who sends the message.
10+
* @property content The content of the message sent by the speaker.
11+
*/
12+
@Serializable
13+
data class ImageGenerated(
14+
@SerialName("url")
15+
val url: String,
16+
)

0 commit comments

Comments
 (0)