relay_info.go 7.4 KB

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