relay_info.go 7.7 KB

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