TSAIChatVM.swift 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //
  2. // TSAIChatVM.swift
  3. // AIEmoji
  4. //
  5. // Created by 100Years on 2025/2/9.
  6. //
  7. let kAIErrorString = "Server is busy, please try again later".localized
  8. class TSAIChatVM {
  9. enum UIStype {
  10. case chat
  11. case history
  12. }
  13. lazy var dbAIChatList: TSDBAIChatList = {
  14. let dbAIChatList = TSDBAIChatList.getOneDB()
  15. return dbAIChatList
  16. }()
  17. var uiStyle:UIStype = UIStype.chat
  18. var streamRequest:StreamPostRequest?
  19. let kAIUser = TSChatUser(senderId: "000", displayName: "AI")
  20. let kUserSender = TSChatUser(senderId: "001", displayName: "001")
  21. //ai markDown 回答的string
  22. var AiMDString:String = ""
  23. }
  24. //MARK: AI 聊天请求
  25. extension TSAIChatVM {
  26. func sendChatMessage(
  27. message:String,
  28. streamHandler:@escaping (String) -> Void,
  29. completion: @escaping (Any?, Error?) -> Void
  30. ) {
  31. let parameters: [String: String] = [
  32. "sessionId": dbAIChatList.sessionId,
  33. "message": message
  34. ]
  35. // AiMDString = ""
  36. // streamRequest = TSNetworkShared.postStream(urlType: .chat,parameters: parameters) {[weak self] string in
  37. // guard let self = self else { return }
  38. // AiMDString = AiMDString + string
  39. // streamHandler(string)
  40. // } completion: { result in
  41. // switch result {
  42. // case .success(let data):
  43. // completion(data,nil)
  44. // case .failure(let error):
  45. // completion(nil,error)
  46. // }
  47. // }
  48. AiMDString = ""
  49. _ = TSNetworkShared.postStream(urlType: .chat,parameters: parameters) {[weak self] string in
  50. guard let self = self else { return }
  51. if AiMDString.count == 0 {
  52. //{"code":500,"message":"Server Error"}
  53. //如果错误,基本都是第一条就返回结果了,这里需要做下 code 判断,来确定接口
  54. if let dataDict = string.jsonDict() , let code = dataDict["code"] {
  55. completion(nil,NSError(domain: dataDict.safeString(forKey: "message"), code: 0))
  56. return
  57. }
  58. }
  59. AiMDString = AiMDString + string
  60. streamHandler(string)
  61. } completion: { result in
  62. switch result {
  63. case .success(let data):
  64. completion(data,nil)
  65. case .failure(let error):
  66. completion(nil,error)
  67. }
  68. }
  69. }
  70. func stopAiGenerate () {
  71. streamRequest?.stopRequest()
  72. }
  73. }
  74. //MARK: 数据存储
  75. extension TSAIChatVM {
  76. func getHistoryChatMessage() -> [TSChatMessage] {
  77. if uiStyle == .history {
  78. return self.dbAIChatList.getMessageList()
  79. }else {
  80. let aiString = "I can tackle your questions, my skillset includes, but is not limited to:\n\n📧 Composing high-quality emails\n\n🇺🇸 Facilitating language learning\n\n📑 Assisting in your studies\n\n💡Brainstorming ideas\n\nand much more!"
  81. let msg = TSChatMessage(kind: .attributedText(kMDAttributedString(text: aiString)), user: kAIUser, messageId: "", date: Date())
  82. return [msg]
  83. }
  84. }
  85. func updateMessages(msgModels:[TSChatMessage]){
  86. kExecuteOnMainThread {
  87. //保存数据库
  88. self.dbAIChatList.updateMessages(msgModels: msgModels)
  89. //保存服务器
  90. }
  91. }
  92. }
  93. import SwiftyMarkdown
  94. private var md: SwiftyMarkdown = {
  95. let md = SwiftyMarkdown(string: "")
  96. md.setFontColorForAllStyles(with: .white)
  97. md.code.color = .red
  98. return md
  99. }()
  100. //字符串转成 markdown NSAttributedString
  101. func kMDAttributedString(text:String) -> NSAttributedString{
  102. return md.attributedString(from: text)
  103. }