relay_info.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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. RelayFormatOpenAIResponses = "openai_responses"
  35. RelayFormatOpenAIAudio = "openai_audio"
  36. RelayFormatOpenAIImage = "openai_image"
  37. RelayFormatRerank = "rerank"
  38. RelayFormatEmbedding = "embedding"
  39. )
  40. type RerankerInfo struct {
  41. Documents []any
  42. ReturnDocuments bool
  43. }
  44. type BuildInToolInfo struct {
  45. ToolName string
  46. CallCount int
  47. SearchContextSize string
  48. }
  49. type ResponsesUsageInfo struct {
  50. BuiltInTools map[string]*BuildInToolInfo
  51. }
  52. type RelayInfo struct {
  53. ChannelType int
  54. ChannelId int
  55. TokenId int
  56. TokenKey string
  57. UserId int
  58. UsingGroup string // 使用的分组
  59. UserGroup string // 用户所在分组
  60. TokenUnlimited bool
  61. StartTime time.Time
  62. FirstResponseTime time.Time
  63. isFirstResponse bool
  64. //SendLastReasoningResponse bool
  65. ApiType int
  66. IsStream bool
  67. IsPlayground bool
  68. UsePrice bool
  69. RelayMode int
  70. UpstreamModelName string
  71. OriginModelName string
  72. //RecodeModelName string
  73. RequestURLPath string
  74. ApiVersion string
  75. PromptTokens int
  76. ApiKey string
  77. Organization string
  78. BaseUrl string
  79. SupportStreamOptions bool
  80. ShouldIncludeUsage bool
  81. IsModelMapped bool
  82. ClientWs *websocket.Conn
  83. TargetWs *websocket.Conn
  84. InputAudioFormat string
  85. OutputAudioFormat string
  86. RealtimeTools []dto.RealTimeTool
  87. IsFirstRequest bool
  88. AudioUsage bool
  89. ReasoningEffort string
  90. ChannelSetting map[string]interface{}
  91. ParamOverride map[string]interface{}
  92. UserSetting map[string]interface{}
  93. UserEmail string
  94. UserQuota int
  95. RelayFormat string
  96. SendResponseCount int
  97. ChannelCreateTime int64
  98. ThinkingContentInfo
  99. *ClaudeConvertInfo
  100. *RerankerInfo
  101. *ResponsesUsageInfo
  102. }
  103. // 定义支持流式选项的通道类型
  104. var streamSupportedChannels = map[int]bool{
  105. constant.ChannelTypeOpenAI: true,
  106. constant.ChannelTypeAnthropic: true,
  107. constant.ChannelTypeAws: true,
  108. constant.ChannelTypeGemini: true,
  109. constant.ChannelCloudflare: true,
  110. constant.ChannelTypeAzure: true,
  111. constant.ChannelTypeVolcEngine: true,
  112. constant.ChannelTypeOllama: true,
  113. constant.ChannelTypeXai: true,
  114. constant.ChannelTypeDeepSeek: true,
  115. constant.ChannelTypeBaiduV2: true,
  116. }
  117. func GenRelayInfoWs(c *gin.Context, ws *websocket.Conn) *RelayInfo {
  118. info := GenRelayInfo(c)
  119. info.ClientWs = ws
  120. info.InputAudioFormat = "pcm16"
  121. info.OutputAudioFormat = "pcm16"
  122. info.IsFirstRequest = true
  123. return info
  124. }
  125. func GenRelayInfoClaude(c *gin.Context) *RelayInfo {
  126. info := GenRelayInfo(c)
  127. info.RelayFormat = RelayFormatClaude
  128. info.ShouldIncludeUsage = false
  129. info.ClaudeConvertInfo = &ClaudeConvertInfo{
  130. LastMessagesType: LastMessageTypeNone,
  131. }
  132. return info
  133. }
  134. func GenRelayInfoRerank(c *gin.Context, req *dto.RerankRequest) *RelayInfo {
  135. info := GenRelayInfo(c)
  136. info.RelayMode = relayconstant.RelayModeRerank
  137. info.RelayFormat = RelayFormatRerank
  138. info.RerankerInfo = &RerankerInfo{
  139. Documents: req.Documents,
  140. ReturnDocuments: req.GetReturnDocuments(),
  141. }
  142. return info
  143. }
  144. func GenRelayInfoOpenAIAudio(c *gin.Context) *RelayInfo {
  145. info := GenRelayInfo(c)
  146. info.RelayFormat = RelayFormatOpenAIAudio
  147. return info
  148. }
  149. func GenRelayInfoEmbedding(c *gin.Context) *RelayInfo {
  150. info := GenRelayInfo(c)
  151. info.RelayFormat = RelayFormatEmbedding
  152. return info
  153. }
  154. func GenRelayInfoResponses(c *gin.Context, req *dto.OpenAIResponsesRequest) *RelayInfo {
  155. info := GenRelayInfo(c)
  156. info.RelayMode = relayconstant.RelayModeResponses
  157. info.RelayFormat = RelayFormatOpenAIResponses
  158. info.SupportStreamOptions = false
  159. info.ResponsesUsageInfo = &ResponsesUsageInfo{
  160. BuiltInTools: make(map[string]*BuildInToolInfo),
  161. }
  162. if len(req.Tools) > 0 {
  163. for _, tool := range req.Tools {
  164. info.ResponsesUsageInfo.BuiltInTools[tool.Type] = &BuildInToolInfo{
  165. ToolName: tool.Type,
  166. CallCount: 0,
  167. }
  168. switch tool.Type {
  169. case dto.BuildInToolWebSearchPreview:
  170. if tool.SearchContextSize == "" {
  171. tool.SearchContextSize = "medium"
  172. }
  173. info.ResponsesUsageInfo.BuiltInTools[tool.Type].SearchContextSize = tool.SearchContextSize
  174. }
  175. }
  176. }
  177. info.IsStream = req.Stream
  178. return info
  179. }
  180. func GenRelayInfoGemini(c *gin.Context) *RelayInfo {
  181. info := GenRelayInfo(c)
  182. info.RelayFormat = RelayFormatGemini
  183. info.ShouldIncludeUsage = false
  184. return info
  185. }
  186. func GenRelayInfoImage(c *gin.Context) *RelayInfo {
  187. info := GenRelayInfo(c)
  188. info.RelayFormat = RelayFormatOpenAIImage
  189. return info
  190. }
  191. func GenRelayInfo(c *gin.Context) *RelayInfo {
  192. channelType := common.GetContextKeyInt(c, constant.ContextKeyChannelType)
  193. channelId := common.GetContextKeyInt(c, constant.ContextKeyChannelId)
  194. channelSetting := common.GetContextKeyStringMap(c, constant.ContextKeyChannelSetting)
  195. paramOverride := common.GetContextKeyStringMap(c, constant.ContextKeyParamOverride)
  196. tokenId := common.GetContextKeyInt(c, constant.ContextKeyTokenId)
  197. tokenKey := common.GetContextKeyString(c, constant.ContextKeyTokenKey)
  198. userId := common.GetContextKeyInt(c, constant.ContextKeyUserId)
  199. tokenUnlimited := common.GetContextKeyBool(c, constant.ContextKeyTokenUnlimited)
  200. startTime := common.GetContextKeyTime(c, constant.ContextKeyRequestStartTime)
  201. // firstResponseTime = time.Now() - 1 second
  202. apiType, _ := common.ChannelType2APIType(channelType)
  203. info := &RelayInfo{
  204. UserQuota: common.GetContextKeyInt(c, constant.ContextKeyUserQuota),
  205. UserSetting: common.GetContextKeyStringMap(c, constant.ContextKeyUserSetting),
  206. UserEmail: common.GetContextKeyString(c, constant.ContextKeyUserEmail),
  207. isFirstResponse: true,
  208. RelayMode: relayconstant.Path2RelayMode(c.Request.URL.Path),
  209. BaseUrl: common.GetContextKeyString(c, constant.ContextKeyBaseUrl),
  210. RequestURLPath: c.Request.URL.String(),
  211. ChannelType: channelType,
  212. ChannelId: channelId,
  213. TokenId: tokenId,
  214. TokenKey: tokenKey,
  215. UserId: userId,
  216. UsingGroup: common.GetContextKeyString(c, constant.ContextKeyUsingGroup),
  217. UserGroup: common.GetContextKeyString(c, constant.ContextKeyUserGroup),
  218. TokenUnlimited: tokenUnlimited,
  219. StartTime: startTime,
  220. FirstResponseTime: startTime.Add(-time.Second),
  221. OriginModelName: common.GetContextKeyString(c, constant.ContextKeyOriginalModel),
  222. UpstreamModelName: common.GetContextKeyString(c, constant.ContextKeyOriginalModel),
  223. //RecodeModelName: c.GetString("original_model"),
  224. IsModelMapped: false,
  225. ApiType: apiType,
  226. ApiVersion: c.GetString("api_version"),
  227. ApiKey: strings.TrimPrefix(c.Request.Header.Get("Authorization"), "Bearer "),
  228. Organization: c.GetString("channel_organization"),
  229. ChannelSetting: channelSetting,
  230. ChannelCreateTime: c.GetInt64("channel_create_time"),
  231. ParamOverride: paramOverride,
  232. RelayFormat: RelayFormatOpenAI,
  233. ThinkingContentInfo: ThinkingContentInfo{
  234. IsFirstThinkingContent: true,
  235. SendLastThinkingContent: false,
  236. },
  237. }
  238. if strings.HasPrefix(c.Request.URL.Path, "/pg") {
  239. info.IsPlayground = true
  240. info.RequestURLPath = strings.TrimPrefix(info.RequestURLPath, "/pg")
  241. info.RequestURLPath = "/v1" + info.RequestURLPath
  242. }
  243. if info.BaseUrl == "" {
  244. info.BaseUrl = constant.ChannelBaseURLs[channelType]
  245. }
  246. if info.ChannelType == constant.ChannelTypeAzure {
  247. info.ApiVersion = GetAPIVersion(c)
  248. }
  249. if info.ChannelType == constant.ChannelTypeVertexAi {
  250. info.ApiVersion = c.GetString("region")
  251. }
  252. if streamSupportedChannels[info.ChannelType] {
  253. info.SupportStreamOptions = true
  254. }
  255. return info
  256. }
  257. func (info *RelayInfo) SetPromptTokens(promptTokens int) {
  258. info.PromptTokens = promptTokens
  259. }
  260. func (info *RelayInfo) SetIsStream(isStream bool) {
  261. info.IsStream = isStream
  262. }
  263. func (info *RelayInfo) SetFirstResponseTime() {
  264. if info.isFirstResponse {
  265. info.FirstResponseTime = time.Now()
  266. info.isFirstResponse = false
  267. }
  268. }
  269. func (info *RelayInfo) HasSendResponse() bool {
  270. return info.FirstResponseTime.After(info.StartTime)
  271. }
  272. type TaskRelayInfo struct {
  273. *RelayInfo
  274. Action string
  275. OriginTaskID string
  276. ConsumeQuota bool
  277. }
  278. func GenTaskRelayInfo(c *gin.Context) *TaskRelayInfo {
  279. info := &TaskRelayInfo{
  280. RelayInfo: GenRelayInfo(c),
  281. }
  282. return info
  283. }
  284. type TaskSubmitReq struct {
  285. Prompt string `json:"prompt"`
  286. Model string `json:"model,omitempty"`
  287. Mode string `json:"mode,omitempty"`
  288. Image string `json:"image,omitempty"`
  289. Size string `json:"size,omitempty"`
  290. Duration int `json:"duration,omitempty"`
  291. Metadata map[string]interface{} `json:"metadata,omitempty"`
  292. }
  293. type TaskInfo struct {
  294. Code int `json:"code"`
  295. TaskID string `json:"task_id"`
  296. Status string `json:"status"`
  297. Reason string `json:"reason,omitempty"`
  298. Url string `json:"url,omitempty"`
  299. Progress string `json:"progress,omitempty"`
  300. }