relay.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package controller
  2. import (
  3. "fmt"
  4. "net/http"
  5. "one-api/common"
  6. "strings"
  7. "github.com/gin-gonic/gin"
  8. )
  9. type Message struct {
  10. Role string `json:"role"`
  11. Content string `json:"content"`
  12. Name *string `json:"name,omitempty"`
  13. }
  14. const (
  15. RelayModeUnknown = iota
  16. RelayModeChatCompletions
  17. RelayModeCompletions
  18. RelayModeEmbeddings
  19. RelayModeModerations
  20. RelayModeImagesGenerations
  21. RelayModeEdits
  22. )
  23. // https://platform.openai.com/docs/api-reference/chat
  24. type GeneralOpenAIRequest struct {
  25. Model string `json:"model,omitempty"`
  26. Messages []Message `json:"messages,omitempty"`
  27. Prompt any `json:"prompt,omitempty"`
  28. Stream bool `json:"stream,omitempty"`
  29. MaxTokens int `json:"max_tokens,omitempty"`
  30. Temperature float64 `json:"temperature,omitempty"`
  31. TopP float64 `json:"top_p,omitempty"`
  32. N int `json:"n,omitempty"`
  33. Input any `json:"input,omitempty"`
  34. Instruction string `json:"instruction,omitempty"`
  35. Size string `json:"size,omitempty"`
  36. }
  37. type ChatRequest struct {
  38. Model string `json:"model"`
  39. Messages []Message `json:"messages"`
  40. MaxTokens int `json:"max_tokens"`
  41. }
  42. type TextRequest struct {
  43. Model string `json:"model"`
  44. Messages []Message `json:"messages"`
  45. Prompt string `json:"prompt"`
  46. MaxTokens int `json:"max_tokens"`
  47. //Stream bool `json:"stream"`
  48. }
  49. type ImageRequest struct {
  50. Prompt string `json:"prompt"`
  51. N int `json:"n"`
  52. Size string `json:"size"`
  53. }
  54. type Usage struct {
  55. PromptTokens int `json:"prompt_tokens"`
  56. CompletionTokens int `json:"completion_tokens"`
  57. TotalTokens int `json:"total_tokens"`
  58. }
  59. type OpenAIError struct {
  60. Message string `json:"message"`
  61. Type string `json:"type"`
  62. Param string `json:"param"`
  63. Code any `json:"code"`
  64. }
  65. type OpenAIErrorWithStatusCode struct {
  66. OpenAIError
  67. StatusCode int `json:"status_code"`
  68. }
  69. type TextResponse struct {
  70. Usage `json:"usage"`
  71. Error OpenAIError `json:"error"`
  72. }
  73. type ImageResponse struct {
  74. Created int `json:"created"`
  75. Data []struct {
  76. Url string `json:"url"`
  77. }
  78. }
  79. type ChatCompletionsStreamResponse struct {
  80. Choices []struct {
  81. Delta struct {
  82. Content string `json:"content"`
  83. } `json:"delta"`
  84. FinishReason string `json:"finish_reason"`
  85. } `json:"choices"`
  86. }
  87. type CompletionsStreamResponse struct {
  88. Choices []struct {
  89. Text string `json:"text"`
  90. FinishReason string `json:"finish_reason"`
  91. } `json:"choices"`
  92. }
  93. func Relay(c *gin.Context) {
  94. relayMode := RelayModeUnknown
  95. if strings.HasPrefix(c.Request.URL.Path, "/v1/chat/completions") {
  96. relayMode = RelayModeChatCompletions
  97. } else if strings.HasPrefix(c.Request.URL.Path, "/v1/completions") {
  98. relayMode = RelayModeCompletions
  99. } else if strings.HasPrefix(c.Request.URL.Path, "/v1/embeddings") {
  100. relayMode = RelayModeEmbeddings
  101. } else if strings.HasSuffix(c.Request.URL.Path, "embeddings") {
  102. relayMode = RelayModeEmbeddings
  103. } else if strings.HasPrefix(c.Request.URL.Path, "/v1/moderations") {
  104. relayMode = RelayModeModerations
  105. } else if strings.HasPrefix(c.Request.URL.Path, "/v1/images/generations") {
  106. relayMode = RelayModeImagesGenerations
  107. } else if strings.HasPrefix(c.Request.URL.Path, "/v1/edits") {
  108. relayMode = RelayModeEdits
  109. }
  110. var err *OpenAIErrorWithStatusCode
  111. switch relayMode {
  112. case RelayModeImagesGenerations:
  113. err = relayImageHelper(c, relayMode)
  114. default:
  115. err = relayTextHelper(c, relayMode)
  116. }
  117. if err != nil {
  118. if err.StatusCode == http.StatusTooManyRequests {
  119. err.OpenAIError.Message = "当前分组负载已饱和,请稍后再试,或升级账户以提升服务质量。"
  120. }
  121. c.JSON(err.StatusCode, gin.H{
  122. "error": err.OpenAIError,
  123. })
  124. channelId := c.GetInt("channel_id")
  125. common.SysError(fmt.Sprintf("relay error (channel #%d): %s", channelId, err.Message))
  126. // https://platform.openai.com/docs/guides/error-codes/api-errors
  127. if common.AutomaticDisableChannelEnabled && (err.Type == "insufficient_quota" || err.Code == "invalid_api_key" || err.Code == "account_deactivated") {
  128. channelId := c.GetInt("channel_id")
  129. channelName := c.GetString("channel_name")
  130. disableChannel(channelId, channelName, err.Message)
  131. }
  132. }
  133. }
  134. func RelayNotImplemented(c *gin.Context) {
  135. err := OpenAIError{
  136. Message: "API not implemented",
  137. Type: "one_api_error",
  138. Param: "",
  139. Code: "api_not_implemented",
  140. }
  141. c.JSON(http.StatusNotImplemented, gin.H{
  142. "error": err,
  143. })
  144. }
  145. func RelayNotFound(c *gin.Context) {
  146. err := OpenAIError{
  147. Message: fmt.Sprintf("API not found: %s:%s", c.Request.Method, c.Request.URL.Path),
  148. Type: "one_api_error",
  149. Param: "",
  150. Code: "api_not_found",
  151. }
  152. c.JSON(http.StatusNotFound, gin.H{
  153. "error": err,
  154. })
  155. }