adaptor.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package coze
  2. import (
  3. "bytes"
  4. "errors"
  5. "net/http"
  6. "net/url"
  7. "strconv"
  8. "strings"
  9. "github.com/bytedance/sonic"
  10. "github.com/gin-gonic/gin"
  11. "github.com/labring/aiproxy/core/model"
  12. "github.com/labring/aiproxy/core/relay/adaptor"
  13. "github.com/labring/aiproxy/core/relay/meta"
  14. "github.com/labring/aiproxy/core/relay/mode"
  15. "github.com/labring/aiproxy/core/relay/utils"
  16. )
  17. type Adaptor struct{}
  18. const baseURL = "https://api.coze.com"
  19. func (a *Adaptor) DefaultBaseURL() string {
  20. return baseURL
  21. }
  22. func (a *Adaptor) SupportMode(m mode.Mode) bool {
  23. return m == mode.ChatCompletions
  24. }
  25. func (a *Adaptor) GetRequestURL(
  26. meta *meta.Meta,
  27. _ adaptor.Store,
  28. _ *gin.Context,
  29. ) (adaptor.RequestURL, error) {
  30. url, err := url.JoinPath(meta.Channel.BaseURL, "/open_api/v2/chat")
  31. if err != nil {
  32. return adaptor.RequestURL{}, err
  33. }
  34. return adaptor.RequestURL{
  35. Method: http.MethodPost,
  36. URL: url,
  37. }, nil
  38. }
  39. func (a *Adaptor) SetupRequestHeader(
  40. meta *meta.Meta,
  41. _ adaptor.Store,
  42. _ *gin.Context,
  43. req *http.Request,
  44. ) error {
  45. token, _, err := getTokenAndUserID(meta.Channel.Key)
  46. if err != nil {
  47. return err
  48. }
  49. req.Header.Set("Authorization", "Bearer "+token)
  50. return nil
  51. }
  52. func (a *Adaptor) ConvertRequest(
  53. meta *meta.Meta,
  54. _ adaptor.Store,
  55. req *http.Request,
  56. ) (adaptor.ConvertResult, error) {
  57. if meta.Mode != mode.ChatCompletions {
  58. return adaptor.ConvertResult{}, errors.New("coze only support chat completions")
  59. }
  60. request, err := utils.UnmarshalGeneralOpenAIRequest(req)
  61. if err != nil {
  62. return adaptor.ConvertResult{}, err
  63. }
  64. _, userID, err := getTokenAndUserID(meta.Channel.Key)
  65. if err != nil {
  66. return adaptor.ConvertResult{}, err
  67. }
  68. request.User = userID
  69. request.Model = meta.ActualModel
  70. cozeRequest := Request{
  71. Stream: request.Stream,
  72. User: request.User,
  73. BotID: strings.TrimPrefix(meta.ActualModel, "bot-"),
  74. }
  75. for i, message := range request.Messages {
  76. if i == len(request.Messages)-1 {
  77. cozeRequest.Query = message.StringContent()
  78. continue
  79. }
  80. cozeMessage := Message{
  81. Role: message.Role,
  82. Content: message.StringContent(),
  83. }
  84. cozeRequest.ChatHistory = append(cozeRequest.ChatHistory, cozeMessage)
  85. }
  86. data, err := sonic.Marshal(cozeRequest)
  87. if err != nil {
  88. return adaptor.ConvertResult{}, err
  89. }
  90. return adaptor.ConvertResult{
  91. Header: http.Header{
  92. "Content-Type": {"application/json"},
  93. "Content-Length": {strconv.Itoa(len(data))},
  94. },
  95. Body: bytes.NewReader(data),
  96. }, nil
  97. }
  98. func (a *Adaptor) DoRequest(
  99. meta *meta.Meta,
  100. _ adaptor.Store,
  101. _ *gin.Context,
  102. req *http.Request,
  103. ) (*http.Response, error) {
  104. return utils.DoRequest(req, meta.RequestTimeout)
  105. }
  106. func (a *Adaptor) DoResponse(
  107. meta *meta.Meta,
  108. _ adaptor.Store,
  109. c *gin.Context,
  110. resp *http.Response,
  111. ) (usage model.Usage, err adaptor.Error) {
  112. if utils.IsStreamResponse(resp) {
  113. usage, err = StreamHandler(meta, c, resp)
  114. } else {
  115. usage, err = Handler(meta, c, resp)
  116. }
  117. return usage, err
  118. }
  119. func (a *Adaptor) Metadata() adaptor.Metadata {
  120. return adaptor.Metadata{
  121. KeyHelp: "token|user_id",
  122. Models: ModelList,
  123. }
  124. }