Skip to content
This repository was archived by the owner on Jan 24, 2026. It is now read-only.

Commit f778ac6

Browse files
committed
feat: merge message by role to generate correctly with deepseek
1 parent ba65ac7 commit f778ac6

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.github.stream29.proxy.client
2+
3+
fun <T> List<T>.mergeBy(
4+
selector: (T) -> String,
5+
merger: (T, T) -> T,
6+
): List<T> {
7+
val result = mutableListOf<T>()
8+
var lastItem: T? = null
9+
for (item in this) {
10+
result.add(
11+
if (lastItem != null && selector(lastItem) == selector(item)) {
12+
merger(lastItem, item).also { lastItem = it }
13+
} else {
14+
lastItem = item
15+
item
16+
}
17+
)
18+
}
19+
return result
20+
}

src/main/kotlin/io/github/stream29/proxy/client/OpenAiBased.kt

Lines changed: 44 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.github.stream29.proxy.client
22

3+
import io.github.stream29.proxy.server.*
4+
import kotlinx.coroutines.flow.Flow
35
import kotlinx.serialization.SerialName
46
import kotlinx.serialization.Serializable
57

@@ -9,7 +11,7 @@ import kotlinx.serialization.Serializable
911
data class DashScopeConfig(
1012
val apiKey: String,
1113
val modelList: List<String> = listOf("qwen-max", "qwen-plus", "qwen-turbo", "qwen-long"),
12-
): ApiProvider by OpenAiConfig(
14+
) : ApiProvider by OpenAiConfig(
1315
baseUrl = "https://dashscope.aliyuncs.com/compatible-mode/v1/",
1416
apiKey = apiKey,
1517
modelList = modelList
@@ -21,19 +23,50 @@ data class DashScopeConfig(
2123
data class DeepSeekConfig(
2224
val apiKey: String,
2325
val modelList: List<String> = listOf("deepseek-chat", "deepseek-reasoner"),
24-
): ApiProvider by OpenAiConfig(
25-
baseUrl = "https://api.deepseek.com/",
26-
apiKey = apiKey,
27-
modelList = modelList
28-
)
26+
) : ApiProvider {
27+
val delegate = OpenAiConfig(
28+
baseUrl = "https://api.deepseek.com/",
29+
apiKey = apiKey,
30+
modelList = modelList
31+
)
32+
33+
override suspend fun getModelNameList(): List<String> = modelList
34+
35+
override suspend fun generateLStream(request: LChatCompletionRequest): Flow<LChatCompletionResponseChunk> {
36+
return delegate.generateLStream(
37+
request.copy(
38+
messages = request.messages.mergeBy(
39+
selector = { it.role },
40+
merger = { a, b -> a.copy(content = a.content + b.content) }
41+
)
42+
)
43+
)
44+
}
45+
46+
override suspend fun generateOStream(request: OChatRequest): Flow<OChatResponseChunk> {
47+
return delegate.generateOStream(
48+
request.copy(
49+
messages = request.messages.mergeBy(
50+
selector = { it.role },
51+
merger = { a, b -> a.copy(content = a.content + b.content) }
52+
)
53+
)
54+
)
55+
}
56+
57+
override fun close() {
58+
delegate.close()
59+
}
60+
61+
}
2962

3063
@Suppress("unused")
3164
@Serializable
3265
@SerialName("Mistral")
3366
data class MistralConfig(
3467
val apiKey: String,
3568
val modelList: List<String> = listOf("codestral", "mistral-large"),
36-
): ApiProvider by OpenAiConfig(
69+
) : ApiProvider by OpenAiConfig(
3770
baseUrl = "https://api.mistral.ai/v1/",
3871
apiKey = apiKey,
3972
modelList = modelList
@@ -45,7 +78,7 @@ data class MistralConfig(
4578
data class SiliconFlowConfig(
4679
val apiKey: String,
4780
val modelList: List<String>,
48-
): ApiProvider by OpenAiConfig(
81+
) : ApiProvider by OpenAiConfig(
4982
baseUrl = "https://api.siliconflow.cn/v1/",
5083
apiKey = apiKey,
5184
modelList = modelList
@@ -57,7 +90,7 @@ data class SiliconFlowConfig(
5790
data class GeminiConfig(
5891
val apiKey: String,
5992
val modelList: List<String>,
60-
): ApiProvider by OpenAiConfig(
93+
) : ApiProvider by OpenAiConfig(
6194
baseUrl = "https://generativelanguage.googleapis.com/v1beta/openai",
6295
apiKey = apiKey,
6396
modelList = modelList
@@ -69,7 +102,7 @@ data class GeminiConfig(
69102
data class ClaudeConfig(
70103
val apiKey: String,
71104
val modelList: List<String>,
72-
): ApiProvider by OpenAiConfig(
105+
) : ApiProvider by OpenAiConfig(
73106
baseUrl = "https://api.anthropic.com/v1/",
74107
apiKey = apiKey,
75108
modelList = modelList
@@ -81,7 +114,7 @@ data class ClaudeConfig(
81114
data class OpenRouterConfig(
82115
val apiKey: String,
83116
val modelList: List<String>,
84-
): ApiProvider by OpenAiConfig(
117+
) : ApiProvider by OpenAiConfig(
85118
baseUrl = "https://openrouter.ai/api/v1",
86119
apiKey = apiKey,
87120
modelList = modelList

0 commit comments

Comments
 (0)