chat.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. package llm
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "eta/eta_api/utils"
  6. "eta/eta_api/utils/llm/eta_llm"
  7. "eta/eta_api/utils/llm/eta_llm/eta_llm_http"
  8. "fmt"
  9. "io"
  10. "mime/multipart"
  11. "net/http"
  12. "os"
  13. )
  14. var (
  15. llmService = eta_llm.GetInstance()
  16. )
  17. type UploadTempDocsResp struct {
  18. Code int `json:"code"`
  19. Msg string `json:"msg"`
  20. Data UploadTempDocDataResp `json:"data"`
  21. }
  22. type UploadTempDocDataResp struct {
  23. Id string `json:"id"`
  24. FailedFiles []interface{} `json:"failed_files"`
  25. }
  26. // UploadTempDocs
  27. // @Description: 上传到临时知识库
  28. // @author: Roc
  29. // @datetime 2025-03-10 14:42:18
  30. // @param filePath string
  31. // @return resp UploadDocsResp
  32. // @return err error
  33. func UploadTempDocs(filePath string) (resp UploadTempDocsResp, err error) {
  34. postUrl := utils.LLM_SERVER + "/knowledge_base/upload_temp_docs"
  35. params := make(map[string]string)
  36. //params[`prev_id`] = ``
  37. params[`chunk_size`] = `750`
  38. params[`chunk_overlap`] = `150`
  39. params[`zh_title_enhance`] = `true`
  40. files := make(map[string]string)
  41. files[`files`] = filePath
  42. result, err := PostFormData(postUrl, params, files)
  43. if err != nil {
  44. return
  45. }
  46. str := string(result)
  47. fmt.Println(str)
  48. err = json.Unmarshal(result, &resp)
  49. if err != nil {
  50. return
  51. }
  52. return
  53. }
  54. type UploadDocsResp struct {
  55. Code int `json:"code"`
  56. Msg string `json:"msg"`
  57. Data UploadDocDataResp `json:"data"`
  58. }
  59. type UploadDocDataResp struct {
  60. Id string `json:"id"`
  61. FailedFiles map[string]string `json:"failed_files"`
  62. }
  63. // UploadDocsToKnowledge
  64. // @Description: 上传文章到知识库
  65. // @author: Roc
  66. // @datetime 2025-03-10 14:40:44
  67. // @param filePath string
  68. // @param knowledgeName string
  69. // @return resp UploadTempDocsResp
  70. // @return err error
  71. func UploadDocsToKnowledge(filePath, knowledgeName string) (updateResp UploadDocDataResp, err error) {
  72. postUrl := utils.LLM_SERVER + "/knowledge_base/upload_docs"
  73. params := make(map[string]string)
  74. params[`knowledge_base_name`] = knowledgeName
  75. params[`override`] = `true` // 覆盖已有文件
  76. params[`to_vector_store`] = `true` // 上传文件后是否进行向量化
  77. params[`chunk_size`] = `750` // 知识库中单段文本最大长度
  78. params[`chunk_overlap`] = `150` // 知识库中相邻文本重合长度
  79. params[`zh_title_enhance`] = `true` // 是否开启中文标题加强
  80. params[`docs`] = `` // 自定义的docs,需要转为json字符串
  81. params[`not_refresh_vs_cache`] = `false` // 暂不保存向量库(用于FAISS)
  82. files := make(map[string]string)
  83. files[`files`] = filePath
  84. result, err := PostFormData(postUrl, params, files)
  85. if err != nil {
  86. return
  87. }
  88. str := string(result)
  89. fmt.Println(str)
  90. var resp UploadDocsResp
  91. err = json.Unmarshal(result, &resp)
  92. if err != nil {
  93. return
  94. }
  95. if resp.Code != 200 {
  96. err = fmt.Errorf(`上传文件失败: %s`, resp.Msg)
  97. return
  98. }
  99. updateResp = resp.Data
  100. return
  101. }
  102. // ChatResp 问答响应
  103. type ChatResp struct {
  104. Answer string `json:"answer"`
  105. Docs []string `json:"docs"`
  106. }
  107. type HistoryContent struct {
  108. Content string `json:"content"`
  109. Role string `json:"role"`
  110. }
  111. func ChatByFile(knowledgeId, question string, historyList []eta_llm_http.HistoryContent) (answerStr string, answer ChatResp, err error) {
  112. // 没有问题那就直接返回
  113. if question == `` {
  114. return
  115. }
  116. history := make([]json.RawMessage, 0)
  117. for _, v := range historyList {
  118. tmpHistory, tmpErr := json.Marshal(v)
  119. if tmpErr != nil {
  120. return
  121. }
  122. history = append(history, json.RawMessage(string(tmpHistory)))
  123. }
  124. resp, err := llmService.DocumentChat(question, knowledgeId, history, false)
  125. if err != nil {
  126. return
  127. }
  128. defer func() {
  129. if resp != nil && resp.Body != nil {
  130. _ = resp.Body.Close()
  131. }
  132. }()
  133. if resp == nil {
  134. err = fmt.Errorf(`知识库问答失败: 无应答`)
  135. return
  136. }
  137. result, err := io.ReadAll(resp.Body)
  138. if err != nil {
  139. err = fmt.Errorf(`知识库问答数据解析失败: %s`, err.Error())
  140. return
  141. }
  142. answerStr = string(result)
  143. // 找到"data:"关键字的位置
  144. dataIndex := bytes.Index([]byte(answerStr), []byte("data: "))
  145. if dataIndex == -1 {
  146. err = fmt.Errorf(`未找到"data:"关键字`)
  147. return
  148. }
  149. // 提取"data:"关键字之后的部分
  150. answerStr = answerStr[dataIndex+len("data: "):]
  151. // 解析JSON数据
  152. err = json.Unmarshal([]byte(answerStr), &answer)
  153. if err != nil {
  154. err = fmt.Errorf(`解析JSON数据失败: %s`, err.Error())
  155. return
  156. }
  157. return
  158. }
  159. // PostFormData sends a POST request with form-data
  160. func PostFormData(url string, params map[string]string, files map[string]string) ([]byte, error) {
  161. body := &bytes.Buffer{}
  162. writer := multipart.NewWriter(body)
  163. for key, val := range params {
  164. if err := writer.WriteField(key, val); err != nil {
  165. return nil, err
  166. }
  167. }
  168. for fieldName, filePath := range files {
  169. file, err := os.Open(filePath)
  170. if err != nil {
  171. return nil, err
  172. }
  173. defer file.Close()
  174. part, err := writer.CreateFormFile(fieldName, filePath)
  175. if err != nil {
  176. return nil, err
  177. }
  178. _, err = io.Copy(part, file)
  179. if err != nil {
  180. return nil, err
  181. }
  182. }
  183. err := writer.Close()
  184. if err != nil {
  185. return nil, err
  186. }
  187. req, err := http.NewRequest("POST", url, body)
  188. if err != nil {
  189. return nil, err
  190. }
  191. //req.Header.Set("accept", `application/json`)
  192. req.Header.Set("Content-Type", writer.FormDataContentType())
  193. client := &http.Client{}
  194. resp, err := client.Do(req)
  195. if err != nil {
  196. return nil, err
  197. }
  198. defer resp.Body.Close()
  199. result, err := io.ReadAll(resp.Body)
  200. return result, nil
  201. }