relay_info.go 7.6 KB

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