feat(chat): implement AiChatRepository for SSE streaming
This commit is contained in:
parent
f93c7c3e43
commit
fcf63c6175
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.stand.standapp.ui.chat.repo
|
||||||
|
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import okhttp3.MediaType.Companion.toMediaType
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import okhttp3.Response
|
||||||
|
import okhttp3.sse.EventSource
|
||||||
|
import okhttp3.sse.EventSourceListener
|
||||||
|
import okhttp3.sse.EventSources
|
||||||
|
import timber.log.Timber
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class AiChatRepository {
|
||||||
|
// 根据后端实际情况修改,模拟器访问本地后端用 10.0.2.2
|
||||||
|
private val backendUrl = "http://10.0.2.2:8080/api/chat/stream"
|
||||||
|
|
||||||
|
private val client = OkHttpClient.Builder()
|
||||||
|
.readTimeout(0, TimeUnit.MILLISECONDS) // SSE 需要关闭读取超时
|
||||||
|
.build()
|
||||||
|
|
||||||
|
fun streamChat(message: String): Flow<String> = callbackFlow {
|
||||||
|
val json = """{"message": "$message"}"""
|
||||||
|
val request = Request.Builder()
|
||||||
|
.url(backendUrl)
|
||||||
|
.post(json.toRequestBody("application/json".toMediaType()))
|
||||||
|
.header("Accept", "text/event-stream")
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val listener = object : EventSourceListener() {
|
||||||
|
override fun onEvent(eventSource: EventSource, id: String?, type: String?, data: String) {
|
||||||
|
// 收到后端推送的数据块
|
||||||
|
trySend(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(eventSource: EventSource, t: Throwable?, response: Response?) {
|
||||||
|
Timber.e(t, "SSE Connection failed")
|
||||||
|
close(t) // 结束流
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClosed(eventSource: EventSource) {
|
||||||
|
close() // 正常结束
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val eventSource = EventSources.createFactory(client).newEventSource(request, listener)
|
||||||
|
|
||||||
|
awaitClose {
|
||||||
|
eventSource.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue