@@ -13,6 +13,7 @@ import com.aallam.openai.api.core.Parameters
1313import com.aallam.openai.api.model.ModelId
1414import com.aallam.openai.client.OpenAI
1515import com.aallam.openai.client.OpenAIHost
16+ import com.aallam.openai.client.RetryStrategy
1617import com.penumbraos.mabl.sdk.BinderConversationMessage
1718import com.penumbraos.mabl.sdk.DeviceUtils
1819import com.penumbraos.mabl.sdk.ILlmCallback
@@ -27,6 +28,7 @@ import com.penumbraos.sdk.http.ktor.HttpClientPlugin
2728import io.ktor.client.*
2829import kotlinx.coroutines.CoroutineScope
2930import kotlinx.coroutines.Dispatchers
31+ import kotlinx.coroutines.flow.catch
3032import kotlinx.coroutines.flow.collect
3133import kotlinx.coroutines.flow.onEach
3234import kotlinx.coroutines.launch
@@ -36,6 +38,7 @@ import java.io.ByteArrayOutputStream
3638import java.io.FileInputStream
3739import kotlin.io.encoding.Base64
3840import kotlin.io.encoding.ExperimentalEncodingApi
41+ import kotlin.time.Duration.Companion.milliseconds
3942
4043private 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