relay_info.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. package common
  2. import (
  3. "one-api/common"
  4. "one-api/constant"
  5. "one-api/dto"
  6. relayconstant "one-api/relay/constant"
  7. "strings"
  8. "sync"
  9. "time"
  10. "github.com/gin-gonic/gin"
  11. "github.com/gorilla/websocket"
  12. )
  13. type ThinkingContentInfo struct {
  14. IsFirstThinkingContent bool
  15. SendLastThinkingContent bool
  16. HasSentThinkingContent bool
  17. }
  18. const (
  19. LastMessageTypeNone = "none"
  20. LastMessageTypeText = "text"
  21. LastMessageTypeTools = "tools"
  22. LastMessageTypeThinking = "thinking"
  23. )
  24. type ClaudeConvertInfo struct {
  25. LastMessagesType string
  26. Index int
  27. Usage *dto.Usage
  28. FinishReason string
  29. Done bool
  30. }
  31. const (
  32. RelayFormatOpenAI = "openai"
  33. RelayFormatClaude = "claude"
  34. )
  35. type RerankerInfo struct {
  36. Documents []any
  37. ReturnDocuments bool
  38. }
  39. type RelayInfo struct {
  40. ChannelType int
  41. ChannelId int
  42. TokenId int
  43. TokenKey string
  44. UserId int
  45. Group string
  46. TokenUnlimited bool
  47. StartTime time.Time
  48. FirstResponseTime time.Time
  49. isFirstResponse bool
  50. responseMutex sync.Mutex // Add mutex for protecting concurrent access
  51. //SendLastReasoningResponse bool
  52. ApiType int
  53. IsStream bool
  54. IsPlayground bool
  55. UsePrice bool
  56. RelayMode int
  57. UpstreamModelName string
  58. OriginModelName string
  59. //RecodeModelName string
  60. RequestURLPath string
  61. ApiVersion string
  62. PromptTokens int
  63. ApiKey string
  64. Organization string
  65. BaseUrl string
  66. SupportStreamOptions bool
  67. ShouldIncludeUsage bool
  68. IsModelMapped bool
  69. ClientWs *websocket.Conn
  70. TargetWs *websocket.Conn
  71. InputAudioFormat string
  72. OutputAudioFormat string
  73. RealtimeTools []dto.RealTimeTool
  74. IsFirstRequest bool
  75. AudioUsage bool
  76. ReasoningEffort string
  77. ChannelSetting map[string]interface{}
  78. ParamOverride map[string]interface{}
  79. UserSetting map[string]interface{}
  80. UserEmail string
  81. UserQuota int
  82. RelayFormat string
  83. SendResponseCount int
  84. ThinkingContentInfo
  85. *ClaudeConvertInfo
  86. *RerankerInfo
  87. }
  88. // 定义支持流式选项的通道类型
  89. var streamSupportedChannels = map[int]bool{
  90. common.ChannelTypeOpenAI: true,
  91. common.ChannelTypeAnthropic: true,
  92. common.ChannelTypeAws: true,
  93. common.ChannelTypeGemini: true,
  94. common.ChannelCloudflare: true,
  95. common.ChannelTypeAzure: true,
  96. common.ChannelTypeVolcEngine: true,
  97. common.ChannelTypeOllama: true,
  98. common.ChannelTypeXai: true,
  99. }
  100. func GenRelayInfoWs(c *gin.Context, ws *websocket.Conn) *RelayInfo {
  101. info := GenRelayInfo(c)
  102. info.ClientWs = ws
  103. info.InputAudioFormat = "pcm16"
  104. info.OutputAudioFormat = "pcm16"
  105. info.IsFirstRequest = true
  106. return info
  107. }
  108. func GenRelayInfoClaude(c *gin.Context) *RelayInfo {
  109. info := GenRelayInfo(c)
  110. info.RelayFormat = RelayFormatClaude
  111. info.ShouldIncludeUsage = false
  112. info.ClaudeConvertInfo = &ClaudeConvertInfo{
  113. LastMessagesType: LastMessageTypeNone,
  114. }
  115. return info
  116. }
  117. func GenRelayInfoRerank(c *gin.Context, req *dto.RerankRequest) *RelayInfo {
  118. info := GenRelayInfo(c)
  119. info.RelayMode = relayconstant.RelayModeRerank
  120. info.RerankerInfo = &RerankerInfo{
  121. Documents: req.Documents,
  122. ReturnDocuments: req.GetReturnDocuments(),
  123. }
  124. return info
  125. }
  126. func GenRelayInfo(c *gin.Context) *RelayInfo {
  127. channelType := c.GetInt("channel_type")
  128. channelId := c.GetInt("channel_id")
  129. channelSetting := c.GetStringMap("channel_setting")
  130. paramOverride := c.GetStringMap("param_override")
  131. tokenId := c.GetInt("token_id")
  132. tokenKey := c.GetString("token_key")
  133. userId := c.GetInt("id")
  134. group := c.GetString("group")
  135. tokenUnlimited := c.GetBool("token_unlimited_quota")
  136. startTime := c.GetTime(constant.ContextKeyRequestStartTime)
  137. // firstResponseTime = time.Now() - 1 second
  138. apiType, _ := relayconstant.ChannelType2APIType(channelType)
  139. info := &RelayInfo{
  140. UserQuota: c.GetInt(constant.ContextKeyUserQuota),
  141. UserSetting: c.GetStringMap(constant.ContextKeyUserSetting),
  142. UserEmail: c.GetString(constant.ContextKeyUserEmail),
  143. isFirstResponse: true,
  144. RelayMode: relayconstant.Path2RelayMode(c.Request.URL.Path),
  145. BaseUrl: c.GetString("base_url"),
  146. RequestURLPath: c.Request.URL.String(),
  147. ChannelType: channelType,
  148. ChannelId: channelId,
  149. TokenId: tokenId,
  150. TokenKey: tokenKey,
  151. UserId: userId,
  152. Group: group,
  153. TokenUnlimited: tokenUnlimited,
  154. StartTime: startTime,
  155. FirstResponseTime: startTime.Add(-time.Second),
  156. OriginModelName: c.GetString("original_model"),
  157. UpstreamModelName: c.GetString("original_model"),
  158. //RecodeModelName: c.GetString("original_model"),
  159. IsModelMapped: false,
  160. ApiType: apiType,
  161. ApiVersion: c.GetString("api_version"),
  162. ApiKey: strings.TrimPrefix(c.Request.Header.Get("Authorization"), "Bearer "),
  163. Organization: c.GetString("channel_organization"),
  164. ChannelSetting: channelSetting,
  165. ParamOverride: paramOverride,
  166. RelayFormat: RelayFormatOpenAI,
  167. ThinkingContentInfo: ThinkingContentInfo{
  168. IsFirstThinkingContent: true,
  169. SendLastThinkingContent: false,
  170. },
  171. }
  172. if strings.HasPrefix(c.Request.URL.Path, "/pg") {
  173. info.IsPlayground = true
  174. info.RequestURLPath = strings.TrimPrefix(info.RequestURLPath, "/pg")
  175. info.RequestURLPath = "/v1" + info.RequestURLPath
  176. }
  177. if info.BaseUrl == "" {
  178. info.BaseUrl = common.ChannelBaseURLs[channelType]
  179. }
  180. if info.ChannelType == common.ChannelTypeAzure {
  181. info.ApiVersion = GetAPIVersion(c)
  182. }
  183. if info.ChannelType == common.ChannelTypeVertexAi {
  184. info.ApiVersion = c.GetString("region")
  185. }
  186. if streamSupportedChannels[info.ChannelType] {
  187. info.SupportStreamOptions = true
  188. }
  189. return info
  190. }
  191. func (info *RelayInfo) SetPromptTokens(promptTokens int) {
  192. info.PromptTokens = promptTokens
  193. }
  194. func (info *RelayInfo) SetIsStream(isStream bool) {
  195. info.IsStream = isStream
  196. }
  197. func (info *RelayInfo) SetFirstResponseTime() {
  198. info.responseMutex.Lock()
  199. defer info.responseMutex.Unlock()
  200. if info.isFirstResponse {
  201. info.FirstResponseTime = time.Now()
  202. info.isFirstResponse = false
  203. }
  204. }
  205. func (info *RelayInfo) HasSendResponse() bool {
  206. return info.FirstResponseTime.After(info.StartTime)
  207. }
  208. type TaskRelayInfo struct {
  209. *RelayInfo
  210. Action string
  211. OriginTaskID string
  212. ConsumeQuota bool
  213. }
  214. func GenTaskRelayInfo(c *gin.Context) *TaskRelayInfo {
  215. info := &TaskRelayInfo{
  216. RelayInfo: GenRelayInfo(c),
  217. }
  218. return info
  219. }