ChatVM.kt 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package com.nova.brain.glass.viewmodel
  2. import android.os.Handler
  3. import android.os.Looper
  4. import androidx.lifecycle.MutableLiveData
  5. import com.nova.brain.glass.model.ChatItem
  6. import com.nova.brain.glass.model.ChatModel
  7. import com.nova.brain.glass.model.ChatModel1
  8. import com.nova.brain.glass.model.data.ChatData
  9. import com.nova.brain.glass.repository.Service
  10. import com.xuqm.base.common.GsonImplHelp
  11. import com.xuqm.base.common.LogHelper
  12. import com.xuqm.base.di.manager.HttpManager
  13. import com.xuqm.base.viewmodel.BaseListViewModel
  14. import com.xuqm.base.viewmodel.callback.Response
  15. import io.reactivex.disposables.Disposable
  16. import io.reactivex.schedulers.Schedulers
  17. class ChatVM : BaseListViewModel<ChatItem>() {
  18. val result = MutableLiveData<String>()
  19. val loading = MutableLiveData<Boolean>()
  20. val chatItems: MutableList<ChatItem> = mutableListOf()
  21. private var currentTask: Disposable? = null
  22. private var itemIdCounter = 0
  23. private var dataSourceReady = false
  24. private val mainHandler = Handler(Looper.getMainLooper())
  25. override fun loadData(page: Int, onResponse: Response<ChatItem>) {
  26. dataSourceReady = true
  27. if (page == 0) {
  28. onResponse.onResponse(ArrayList(chatItems))
  29. } else {
  30. onResponse.onResponse(ArrayList())
  31. }
  32. }
  33. fun demoPostSse(question: String) {
  34. currentTask?.dispose()
  35. currentTask = null
  36. val itemId = itemIdCounter++
  37. chatItems.add(ChatItem(itemId, question, ""))
  38. if (dataSourceReady) invalidate()
  39. loading.postValue(true)
  40. currentTask = HttpManager.getApi(Service::class.java).chat(ChatData(question))
  41. .subscribeOn(Schedulers.io())
  42. .subscribe({ body ->
  43. var content = ""
  44. body.charStream().buffered().use { reader ->
  45. try {
  46. var line: String?
  47. while (reader.readLine().also { line = it } != null) {
  48. val l = line!!
  49. if (l.isNotEmpty()) {
  50. if (l.trimStart().startsWith("<")) {
  51. // HTML 响应(隧道断开),移除占位项并在主线程用相同问题重试
  52. mainHandler.post {
  53. if (chatItems.isNotEmpty()) chatItems.removeAt(chatItems.size - 1)
  54. demoPostSse(question)
  55. }
  56. loading.postValue(false)
  57. return@use
  58. }
  59. val json = if (l.startsWith("data:")) l.removePrefix("data:").trim() else l
  60. val model = GsonImplHelp.get().toObject(json, ChatModel::class.java)
  61. if (model.type == null) {
  62. loading.postValue(false)
  63. val msg = model.msg ?: json
  64. val lastIndex = chatItems.size - 1
  65. if (lastIndex >= 0) {
  66. chatItems[lastIndex].content = msg
  67. notifyItem(lastIndex)
  68. }
  69. result.postValue(msg)
  70. return@use
  71. }
  72. if (model.role != "assistant" || model.type != "string") continue
  73. val model1 = GsonImplHelp.get().toObject(json, ChatModel1::class.java)
  74. content += model1.data
  75. val lastIndex = chatItems.size - 1
  76. if (lastIndex >= 0) {
  77. chatItems[lastIndex].content = content
  78. notifyItem(lastIndex)
  79. }
  80. result.postValue(content)
  81. }
  82. }
  83. } catch (e: Exception) {
  84. LogHelper.e(">>>>11", e)
  85. loading.postValue(false)
  86. val errMsg = "AI反馈异常: ${e.message}"
  87. val lastIndex = chatItems.size - 1
  88. if (lastIndex >= 0) {
  89. chatItems[lastIndex].content = errMsg
  90. notifyItem(lastIndex)
  91. }
  92. result.postValue(errMsg)
  93. }
  94. }
  95. loading.postValue(false)
  96. }, { e ->
  97. LogHelper.e(">>>>22", e)
  98. loading.postValue(false)
  99. result.postValue("AI反馈异常: ${e.message}")
  100. })
  101. currentTask?.also { add(it) }
  102. }
  103. }