Skip to content

Commit 61b1dfd

Browse files
committed
Fix OpenAI not providing proper error messages
1 parent 1218669 commit 61b1dfd

File tree

2 files changed

+38
-20
lines changed

2 files changed

+38
-20
lines changed

gradle/libs.versions.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ composeBom = "2025.08.00"
1212
appcompat = "1.7.1"
1313
fragment = "1.8.9"
1414
material = "1.12.0"
15-
penumbraos-sdk = "783df84"
15+
penumbraos-sdk = "e1a344b"
1616
penumbraos-sdk-local = "0.1.0"
1717
moonlight-ui = "6ae1d5e"
1818
moonlight-ui-local = "0.1.0"
1919
openai-client = "dedfa47"
20+
#openai-client-local = "debugging-SNAPSHOT"
2021
ktor-client = "3.0.0"
2122
kotlinx-serialization = "1.7.1"
2223
kotlinx-coroutines = "1.8.1"
@@ -61,6 +62,7 @@ penumbraos-sdk = { group = "com.github.PenumbraOS", name = "sdk", version.ref =
6162
moonlight-ui = { group = "com.github.agg23", name = "moonlight", version.ref = "moonlight-ui" }
6263
#moonlight-ui = { group = "com.open.pin", name = "ui", version.ref = "moonlight-ui-local" }
6364
openai-client = { group = "com.github.agg23.openai-kotlin", name = "openai-client", version.ref = "openai-client" }
65+
#openai-client = { group = "com.github.agg23.openai-kotlin", name = "openai-client", version.ref = "openai-client-local" }
6466
ktor-client-android = { group = "io.ktor", name = "ktor-client-android", version.ref = "ktor-client" }
6567
ktor-content-negociation = { group = "io.ktor", name = "ktor-client-content-negotiation", version.ref = "ktor-client" }
6668
ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json", version.ref = "ktor-client" }

plugins/openai/src/main/java/com/penumbraos/plugins/openai/OpenAiLlmService.kt

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.aallam.openai.api.core.Parameters
1313
import com.aallam.openai.api.model.ModelId
1414
import com.aallam.openai.client.OpenAI
1515
import com.aallam.openai.client.OpenAIHost
16+
import com.aallam.openai.client.RetryStrategy
1617
import com.penumbraos.mabl.sdk.BinderConversationMessage
1718
import com.penumbraos.mabl.sdk.DeviceUtils
1819
import com.penumbraos.mabl.sdk.ILlmCallback
@@ -27,6 +28,7 @@ import com.penumbraos.sdk.http.ktor.HttpClientPlugin
2728
import io.ktor.client.*
2829
import kotlinx.coroutines.CoroutineScope
2930
import kotlinx.coroutines.Dispatchers
31+
import kotlinx.coroutines.flow.catch
3032
import kotlinx.coroutines.flow.collect
3133
import kotlinx.coroutines.flow.onEach
3234
import kotlinx.coroutines.launch
@@ -36,6 +38,7 @@ import java.io.ByteArrayOutputStream
3638
import java.io.FileInputStream
3739
import kotlin.io.encoding.Base64
3840
import kotlin.io.encoding.ExperimentalEncodingApi
41+
import kotlin.time.Duration.Companion.milliseconds
3942

4043
private const val TAG = "OpenAiLlmService"
4144

@@ -103,6 +106,11 @@ class OpenAiLlmService : MablService("OpenAiLlmService") {
103106
OpenAI(
104107
token = apiKey,
105108
host = OpenAIHost(baseUrl),
109+
retry = RetryStrategy(
110+
maxRetries = 1,
111+
base = 0.2,
112+
maxDelay = 200.milliseconds
113+
),
106114
httpClientConfig = {
107115
if (DeviceUtils.isAiPin()) {
108116
install(HttpClientPlugin) {
@@ -235,33 +243,41 @@ class OpenAiLlmService : MablService("OpenAiLlmService") {
235243

236244
val responseBuilder = StringBuilder()
237245
val toolCalls = mutableListOf<ToolCall>()
238-
var messageCount = 0
239246

240247
val completions = openAI!!.chatCompletions(chatCompletionRequest)
241-
completions.onEach { chunk: ChatCompletionChunk ->
242-
Log.d(TAG, "Received chunk: $chunk")
243-
messageCount += 1
244-
chunk.choices.forEach { choice ->
245-
choice.delta?.let { delta ->
246-
delta.content?.let { content ->
247-
responseBuilder.append(content)
248-
callback.onPartialResponse(content)
249-
}
248+
completions
249+
.catch { exception ->
250+
Log.e(TAG, "Error making request", exception)
251+
val content =
252+
"OpenAI error: ${exception.message?.removePrefix("Stream error: ")}"
253+
responseBuilder.append(content)
254+
// TODO: This should be onError
255+
callback.onPartialResponse(content)
256+
}
257+
.onEach { chunk: ChatCompletionChunk ->
258+
Log.d(TAG, "Received chunk: $chunk")
259+
chunk.choices.forEach { choice ->
260+
choice.delta?.let { delta ->
261+
delta.content?.let { content ->
262+
responseBuilder.append(content)
263+
callback.onPartialResponse(content)
264+
}
250265

251-
delta.toolCalls?.forEach { toolCall ->
252-
if (toolCall.function != null) {
253-
val convertedToolCall = ToolCall().apply {
254-
id = toolCall.id!!.id
255-
name = toolCall.function!!.name
256-
parameters = toolCall.function!!.arguments
257-
isLLM = true
266+
delta.toolCalls?.forEach { toolCall ->
267+
if (toolCall.function != null) {
268+
val convertedToolCall = ToolCall().apply {
269+
id = toolCall.id!!.id
270+
name = toolCall.function!!.name
271+
parameters = toolCall.function!!.arguments
272+
isLLM = true
273+
}
274+
toolCalls.add(convertedToolCall)
258275
}
259-
toolCalls.add(convertedToolCall)
260276
}
261277
}
262278
}
263279
}
264-
}.collect()
280+
.collect()
265281

266282
// Send final response
267283
val response = LlmResponse().apply {

0 commit comments

Comments
 (0)