Skip to content

Commit 67a810b

Browse files
committed
feat: Add ChatCompletions API
1 parent 91a1cea commit 67a810b

File tree

15 files changed

+342
-0
lines changed

15 files changed

+342
-0
lines changed

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

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

3+
import co.yml.ychat.entrypoint.features.ChatCompletions
34
import co.yml.ychat.entrypoint.features.Completion
45
import co.yml.ychat.entrypoint.impl.YChatImpl
56
import kotlin.jvm.JvmStatic
@@ -32,6 +33,50 @@ interface YChat {
3233
*/
3334
fun completion(): Completion
3435

36+
/**
37+
* The chatCompletions api generates a list of chat completions for the given input message.
38+
* It uses machine learning algorithms to generate responses that match the context or pattern
39+
* provided in the input message.
40+
*
41+
* You can configure various parameters to customize the chat completions, such as the model to use,
42+
* the number of results to generate, and the maximum number of tokens allowed for the generated answer.
43+
*
44+
* Example usage:
45+
* ```
46+
* val result = YChat.create(apiKey).chatCompletions()
47+
* .setModel("gpt-3.5-turbo")
48+
* .setResults(3)
49+
* .setMaxTokens(1024)
50+
* .execute("Hello, how are you?")
51+
* ```
52+
* This would generate three chat completion strings based on the input message "Hello, how are you?"
53+
* using the "gpt-3.5-turbo" model, with a maximum of 1024 tokens allowed for each generated answer.
54+
*
55+
* You can also use the `addMessage` method to provide additional context or information to the API,
56+
* which can be used to restrict the generated responses to a certain topic or context.
57+
*
58+
* Example usage:
59+
* ```
60+
* val result = YChat.create(apiKey).chatCompletions()
61+
* .setModel("gpt-3.5-turbo")
62+
* .setResults(3)
63+
* .setMaxTokens(1024)
64+
* .addMessage(
65+
* role = "assistant",
66+
* content = "You are a helpful assistant that only answers questions related to fitness"
67+
* )
68+
* .execute("What is the best exercise for building muscle?")
69+
* ```
70+
* This would generate three chat completion strings based on the input message "What is the
71+
* best exercise for building muscle?", using the "gpt-3.5-turbo" model, with a maximum of 1024
72+
* tokens allowed for each generated answer. The `addMessage` method is used to provide context
73+
* to the API, restricting the generated responses to questions related to fitness, since the
74+
* assistant is set to only answer questions related to that topic.
75+
*
76+
* @return A new instance of the `ChatCompletions` class.
77+
*/
78+
fun chatCompletions(): ChatCompletions
79+
3580
/**
3681
* Callback is an interface used for handling the results of an operation.
3782
* It provides two methods, `onSuccess` and `onError`, for handling the success
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package co.yml.ychat.data.api
22

3+
import co.yml.ychat.data.dto.ChatCompletionParamsDto
4+
import co.yml.ychat.data.dto.ChatCompletionsDto
35
import co.yml.ychat.data.dto.CompletionDto
46
import co.yml.ychat.data.dto.CompletionParamsDto
57
import co.yml.ychat.data.infrastructure.ApiResult
68

79
internal interface ChatGptApi {
810

911
suspend fun completion(paramsDto: CompletionParamsDto): ApiResult<CompletionDto>
12+
13+
suspend fun chatCompletions(paramsDto: ChatCompletionParamsDto): ApiResult<ChatCompletionsDto>
1014
}

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
@@ -1,6 +1,8 @@
11
package co.yml.ychat.data.api.impl
22

33
import co.yml.ychat.data.api.ChatGptApi
4+
import co.yml.ychat.data.dto.ChatCompletionParamsDto
5+
import co.yml.ychat.data.dto.ChatCompletionsDto
46
import co.yml.ychat.data.dto.CompletionDto
57
import co.yml.ychat.data.dto.CompletionParamsDto
68
import co.yml.ychat.data.infrastructure.ApiExecutor
@@ -16,4 +18,12 @@ internal class ChatGptApiImpl(private val apiExecutor: ApiExecutor) : ChatGptApi
1618
.setBody(paramsDto)
1719
.execute()
1820
}
21+
22+
override suspend fun chatCompletions(paramsDto: ChatCompletionParamsDto): ApiResult<ChatCompletionsDto> {
23+
return apiExecutor
24+
.setEndpoint("v1/chat/completions")
25+
.setHttpMethod(HttpMethod.Post)
26+
.setBody(paramsDto)
27+
.execute()
28+
}
1929
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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 ChatCompletionParamsDto(
8+
@SerialName("model")
9+
val model: String,
10+
@SerialName("messages")
11+
val messages: List<ChatMessageDto>,
12+
@SerialName("max_tokens")
13+
val maxTokens: Int,
14+
@SerialName("temperature")
15+
val temperature: Double,
16+
@SerialName("top_p")
17+
val topP: Double,
18+
@SerialName("n")
19+
val maxResults: Int = 1,
20+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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 ChatCompletionsChoiceDto(
8+
@SerialName("index")
9+
val index: Int,
10+
@SerialName("message")
11+
val message: ChatMessageDto,
12+
@SerialName("finish_reason")
13+
val finishReason: String,
14+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 ChatCompletionsDto(
8+
@SerialName("id")
9+
val id: String,
10+
@SerialName("model")
11+
val model: String,
12+
@SerialName("choices")
13+
val choices: List<ChatCompletionsChoiceDto>,
14+
@SerialName("usage")
15+
val usage: UsageDto,
16+
)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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 ChatMessageDto(
8+
@SerialName("role")
9+
val role: String,
10+
@SerialName("content")
11+
val content: String,
12+
)

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
@@ -5,8 +5,11 @@ import co.yml.ychat.data.api.impl.ChatGptApiImpl
55
import co.yml.ychat.data.infrastructure.ApiExecutor
66
import co.yml.ychat.data.storage.ChatLogStorage
77
import co.yml.ychat.di.provider.NetworkProvider
8+
import co.yml.ychat.domain.usecases.ChatCompletionsUseCase
89
import co.yml.ychat.domain.usecases.CompletionUseCase
10+
import co.yml.ychat.entrypoint.features.ChatCompletions
911
import co.yml.ychat.entrypoint.features.Completion
12+
import co.yml.ychat.entrypoint.impl.ChatCompletionsImpl
1013
import co.yml.ychat.entrypoint.impl.CompletionImpl
1114
import kotlinx.coroutines.Dispatchers
1215
import org.koin.core.module.Module
@@ -19,10 +22,12 @@ internal class LibraryModule(private val apiKey: String) {
1922

2023
private val entrypointModule = module {
2124
factory<Completion> { CompletionImpl(Dispatchers.Default, get()) }
25+
factory<ChatCompletions> { ChatCompletionsImpl(Dispatchers.Default, get()) }
2226
}
2327

2428
private val domainModule = module {
2529
factory { CompletionUseCase(get(), get()) }
30+
factory { ChatCompletionsUseCase(get()) }
2631
}
2732

2833
private val dataModule = module {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package co.yml.ychat.domain.mapper
2+
3+
import co.yml.ychat.data.dto.ChatCompletionParamsDto
4+
import co.yml.ychat.data.dto.ChatCompletionsDto
5+
import co.yml.ychat.data.dto.ChatMessageDto
6+
import co.yml.ychat.domain.model.ChatCompletionsParams
7+
import co.yml.ychat.domain.model.ChatMessage
8+
9+
internal fun ChatCompletionsDto.toChatMessages(): List<ChatMessage> {
10+
return this.choices.map {
11+
ChatMessage(it.message.role, it.message.content)
12+
}
13+
}
14+
15+
internal fun ChatCompletionsParams.toChatCompletionParamsDto(): ChatCompletionParamsDto {
16+
return ChatCompletionParamsDto(
17+
model = this.model,
18+
messages = this.messages.map { ChatMessageDto(it.role, it.content) },
19+
maxTokens = this.maxTokens,
20+
temperature = this.temperature,
21+
topP = this.topP,
22+
maxResults = this.maxResults,
23+
)
24+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package co.yml.ychat.domain.model
2+
3+
internal data class ChatCompletionsParams(
4+
var messages: ArrayList<ChatMessage> = arrayListOf(),
5+
var model: String = "gpt-3.5-turbo",
6+
var maxResults: Int = 1,
7+
var maxTokens: Int = 4096,
8+
var temperature: Double = 1.0,
9+
var topP: Double = 1.0,
10+
)

0 commit comments

Comments
 (0)