Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 
 

464 řádky
12 KiB

  1. package model
  2. import (
  3. "fmt"
  4. "sort"
  5. "strings"
  6. "sync"
  7. "time"
  8. "github.com/QuantumNous/new-api/common"
  9. "github.com/QuantumNous/new-api/constant"
  10. "github.com/QuantumNous/new-api/setting/ratio_setting"
  11. "github.com/QuantumNous/new-api/types"
  12. )
  13. type Pricing struct {
  14. ModelName string `json:"model_name"`
  15. Description string `json:"description,omitempty"`
  16. Icon string `json:"icon,omitempty"`
  17. Tags string `json:"tags,omitempty"`
  18. VendorID int `json:"vendor_id,omitempty"`
  19. QuotaType int `json:"quota_type"`
  20. ModelRatio float64 `json:"model_ratio"`
  21. ModelPrice float64 `json:"model_price"`
  22. OwnerBy string `json:"owner_by"`
  23. CompletionRatio float64 `json:"completion_ratio"`
  24. CacheRatio float64 `json:"cache_ratio"`
  25. CacheCreationRatio float64 `json:"cache_creation_ratio"`
  26. EnableGroup []string `json:"enable_groups"`
  27. SupportedEndpointTypes []constant.EndpointType `json:"supported_endpoint_types"`
  28. PricingVersion string `json:"pricing_version,omitempty"`
  29. Type int `json:"type"`
  30. PricingConfig *types.PricingConfig `json:"pricing_config,omitempty"`
  31. }
  32. type PricingVendor struct {
  33. ID int `json:"id"`
  34. Name string `json:"name"`
  35. Description string `json:"description,omitempty"`
  36. Icon string `json:"icon,omitempty"`
  37. }
  38. const (
  39. QuotaTypeByTokens = 0
  40. QuotaTypeByCall = 1
  41. )
  42. var (
  43. pricingMap []Pricing
  44. pricingByModel map[string]*Pricing
  45. vendorsList []PricingVendor
  46. supportedEndpointMap map[string]common.EndpointInfo
  47. lastGetPricingTime time.Time
  48. updatePricingLock sync.Mutex
  49. modelEnableGroups = make(map[string][]string)
  50. modelQuotaTypeMap = make(map[string]int)
  51. modelEnableGroupsLock = sync.RWMutex{}
  52. )
  53. var (
  54. modelSupportEndpointTypes = make(map[string][]constant.EndpointType)
  55. modelSupportEndpointsLock = sync.RWMutex{}
  56. )
  57. func SetTestPricing(pricing []Pricing) {
  58. updatePricingLock.Lock()
  59. defer updatePricingLock.Unlock()
  60. pricingMap = pricing
  61. idx := make(map[string]*Pricing, len(pricing))
  62. for i := range pricing {
  63. idx[pricing[i].ModelName] = &pricingMap[i]
  64. }
  65. pricingByModel = idx
  66. lastGetPricingTime = time.Now()
  67. }
  68. func GetPricing() []Pricing {
  69. if time.Since(lastGetPricingTime) > time.Minute || len(pricingMap) == 0 {
  70. updatePricingLock.Lock()
  71. defer updatePricingLock.Unlock()
  72. if time.Since(lastGetPricingTime) > time.Minute || len(pricingMap) == 0 {
  73. modelSupportEndpointsLock.Lock()
  74. defer modelSupportEndpointsLock.Unlock()
  75. updatePricing()
  76. }
  77. }
  78. return pricingMap
  79. }
  80. func GetPricingByModel(modelName string) *Pricing {
  81. GetPricing()
  82. modelEnableGroupsLock.RLock()
  83. p := pricingByModel[modelName]
  84. modelEnableGroupsLock.RUnlock()
  85. return p
  86. }
  87. func GetVendors() []PricingVendor {
  88. if time.Since(lastGetPricingTime) > time.Minute || len(pricingMap) == 0 {
  89. GetPricing()
  90. }
  91. return vendorsList
  92. }
  93. func GetModelSupportEndpointTypes(model string) []constant.EndpointType {
  94. if model == "" {
  95. return make([]constant.EndpointType, 0)
  96. }
  97. modelSupportEndpointsLock.RLock()
  98. defer modelSupportEndpointsLock.RUnlock()
  99. if endpoints, ok := modelSupportEndpointTypes[model]; ok {
  100. return endpoints
  101. }
  102. return make([]constant.EndpointType, 0)
  103. }
  104. func parseModelEndpointTypes(rawValue string) []string {
  105. trimmed := strings.TrimSpace(rawValue)
  106. if trimmed == "" {
  107. return nil
  108. }
  109. var rawObject map[string]interface{}
  110. if err := common.Unmarshal([]byte(trimmed), &rawObject); err == nil {
  111. endpoints := make([]string, 0, len(rawObject))
  112. for k, v := range rawObject {
  113. switch v.(type) {
  114. case string, map[string]interface{}:
  115. if !common.StringsContains(endpoints, k) {
  116. endpoints = append(endpoints, k)
  117. }
  118. }
  119. }
  120. if len(endpoints) == 0 {
  121. return nil
  122. }
  123. return endpoints
  124. }
  125. var rawList []string
  126. if err := common.Unmarshal([]byte(trimmed), &rawList); err == nil {
  127. endpoints := make([]string, 0, len(rawList))
  128. for _, endpoint := range rawList {
  129. endpoint = strings.TrimSpace(endpoint)
  130. if endpoint == "" || common.StringsContains(endpoints, endpoint) {
  131. continue
  132. }
  133. endpoints = append(endpoints, endpoint)
  134. }
  135. if len(endpoints) == 0 {
  136. return nil
  137. }
  138. return endpoints
  139. }
  140. return nil
  141. }
  142. func updatePricing() {
  143. enableAbilities, err := GetAllEnableAbilityWithChannels()
  144. if err != nil {
  145. common.SysLog(fmt.Sprintf("GetAllEnableAbilityWithChannels error: %v", err))
  146. return
  147. }
  148. var allMeta []Model
  149. _ = DB.Find(&allMeta).Error
  150. metaMap := make(map[string]*Model)
  151. prefixList := make([]*Model, 0)
  152. suffixList := make([]*Model, 0)
  153. containsList := make([]*Model, 0)
  154. for i := range allMeta {
  155. m := &allMeta[i]
  156. if m.NameRule == NameRuleExact {
  157. metaMap[m.ModelName] = m
  158. continue
  159. }
  160. switch m.NameRule {
  161. case NameRulePrefix:
  162. prefixList = append(prefixList, m)
  163. case NameRuleSuffix:
  164. suffixList = append(suffixList, m)
  165. case NameRuleContains:
  166. containsList = append(containsList, m)
  167. }
  168. }
  169. for _, m := range prefixList {
  170. for _, ability := range enableAbilities {
  171. if strings.HasPrefix(ability.Model, m.ModelName) {
  172. if _, exists := metaMap[ability.Model]; !exists {
  173. metaMap[ability.Model] = m
  174. }
  175. }
  176. }
  177. }
  178. for _, m := range suffixList {
  179. for _, ability := range enableAbilities {
  180. if strings.HasSuffix(ability.Model, m.ModelName) {
  181. if _, exists := metaMap[ability.Model]; !exists {
  182. metaMap[ability.Model] = m
  183. }
  184. }
  185. }
  186. }
  187. for _, m := range containsList {
  188. for _, ability := range enableAbilities {
  189. if strings.Contains(ability.Model, m.ModelName) {
  190. if _, exists := metaMap[ability.Model]; !exists {
  191. metaMap[ability.Model] = m
  192. }
  193. }
  194. }
  195. }
  196. var vendors []Vendor
  197. _ = DB.Find(&vendors).Error
  198. vendorMap := make(map[int]*Vendor, len(vendors))
  199. for i := range vendors {
  200. vendorMap[vendors[i].Id] = &vendors[i]
  201. }
  202. initDefaultVendorMapping(metaMap, vendorMap, enableAbilities)
  203. vendorOrderMap := make(map[int]int, len(vendorMap))
  204. for _, v := range vendorMap {
  205. vendorOrderMap[v.Id] = v.SortOrder
  206. }
  207. vendorsList = make([]PricingVendor, 0, len(vendorMap))
  208. for _, v := range vendorMap {
  209. vendorsList = append(vendorsList, PricingVendor{
  210. ID: v.Id,
  211. Name: v.Name,
  212. Description: v.Description,
  213. Icon: v.Icon,
  214. })
  215. }
  216. sort.Slice(vendorsList, func(i, j int) bool {
  217. oi := vendorOrderMap[vendorsList[i].ID]
  218. oj := vendorOrderMap[vendorsList[j].ID]
  219. if oi != oj {
  220. return oi < oj
  221. }
  222. return vendorsList[i].ID < vendorsList[j].ID
  223. })
  224. modelGroupsMap := make(map[string]*types.Set[string])
  225. for _, ability := range enableAbilities {
  226. groups, ok := modelGroupsMap[ability.Model]
  227. if !ok {
  228. groups = types.NewSet[string]()
  229. modelGroupsMap[ability.Model] = groups
  230. }
  231. groups.Add(ability.Group)
  232. }
  233. modelSupportEndpointsStr := make(map[string][]string)
  234. for _, ability := range enableAbilities {
  235. endpoints := modelSupportEndpointsStr[ability.Model]
  236. channelTypes := common.GetEndpointTypesByChannelType(ability.ChannelType, ability.Model)
  237. for _, channelType := range channelTypes {
  238. if !common.StringsContains(endpoints, string(channelType)) {
  239. endpoints = append(endpoints, string(channelType))
  240. }
  241. }
  242. modelSupportEndpointsStr[ability.Model] = endpoints
  243. }
  244. for modelName, meta := range metaMap {
  245. if strings.TrimSpace(meta.Endpoints) == "" {
  246. continue
  247. }
  248. if endpoints := parseModelEndpointTypes(meta.Endpoints); len(endpoints) > 0 {
  249. modelSupportEndpointsStr[modelName] = endpoints
  250. }
  251. }
  252. modelSupportEndpointTypes = make(map[string][]constant.EndpointType)
  253. for model, endpoints := range modelSupportEndpointsStr {
  254. supportedEndpoints := make([]constant.EndpointType, 0, len(endpoints))
  255. for _, endpointStr := range endpoints {
  256. supportedEndpoints = append(supportedEndpoints, constant.EndpointType(endpointStr))
  257. }
  258. modelSupportEndpointTypes[model] = supportedEndpoints
  259. }
  260. supportedEndpointMap = make(map[string]common.EndpointInfo)
  261. for _, endpoints := range modelSupportEndpointTypes {
  262. for _, et := range endpoints {
  263. if info, ok := common.GetDefaultEndpointInfo(et); ok {
  264. if _, exists := supportedEndpointMap[string(et)]; !exists {
  265. supportedEndpointMap[string(et)] = info
  266. }
  267. }
  268. }
  269. }
  270. for _, meta := range metaMap {
  271. if strings.TrimSpace(meta.Endpoints) == "" {
  272. continue
  273. }
  274. var raw map[string]interface{}
  275. if err := common.Unmarshal([]byte(meta.Endpoints), &raw); err == nil {
  276. for k, v := range raw {
  277. switch val := v.(type) {
  278. case string:
  279. supportedEndpointMap[k] = common.EndpointInfo{Path: val, Method: "POST"}
  280. case map[string]interface{}:
  281. ep := common.EndpointInfo{Method: "POST"}
  282. if p, ok := val["path"].(string); ok {
  283. ep.Path = p
  284. }
  285. if m, ok := val["method"].(string); ok {
  286. ep.Method = strings.ToUpper(m)
  287. }
  288. supportedEndpointMap[k] = ep
  289. }
  290. }
  291. }
  292. }
  293. pricingMap = make([]Pricing, 0, len(modelGroupsMap))
  294. for model, groups := range modelGroupsMap {
  295. pricing := Pricing{
  296. ModelName: model,
  297. EnableGroup: groups.Items(),
  298. SupportedEndpointTypes: modelSupportEndpointTypes[model],
  299. }
  300. if meta, ok := metaMap[model]; ok {
  301. if meta.Status == 0 {
  302. continue
  303. }
  304. pricing.Description = meta.Description
  305. pricing.Icon = meta.Icon
  306. pricing.Tags = meta.Tags
  307. pricing.VendorID = meta.VendorID
  308. pricing.Type = meta.Type
  309. }
  310. applyGlobalDefault(&pricing, model)
  311. pricingMap = append(pricingMap, pricing)
  312. }
  313. sort.Slice(pricingMap, func(i, j int) bool {
  314. mi, okI := metaMap[pricingMap[i].ModelName]
  315. mj, okJ := metaMap[pricingMap[j].ModelName]
  316. si := 999999
  317. sj := 999999
  318. if okI {
  319. si = mi.SortOrder
  320. }
  321. if okJ {
  322. sj = mj.SortOrder
  323. }
  324. if si != sj {
  325. return si < sj
  326. }
  327. return pricingMap[i].ModelName < pricingMap[j].ModelName
  328. })
  329. if len(pricingMap) > 0 {
  330. pricingMap[0].PricingVersion = "82c4a357505fff6fee8462c3f7ec8a645bb95532669cb73b2cabee6a416ec24f"
  331. }
  332. modelEnableGroupsLock.Lock()
  333. modelEnableGroups = make(map[string][]string)
  334. modelQuotaTypeMap = make(map[string]int)
  335. byModel := make(map[string]*Pricing, len(pricingMap))
  336. for i := range pricingMap {
  337. p := &pricingMap[i]
  338. modelEnableGroups[p.ModelName] = p.EnableGroup
  339. modelQuotaTypeMap[p.ModelName] = p.QuotaType
  340. byModel[p.ModelName] = p
  341. }
  342. pricingByModel = byModel
  343. modelEnableGroupsLock.Unlock()
  344. lastGetPricingTime = time.Now()
  345. }
  346. func GetSupportedEndpointMap() map[string]common.EndpointInfo {
  347. return supportedEndpointMap
  348. }
  349. func applyGlobalDefault(pricing *Pricing, model string) {
  350. if applyMatrixPricingConfig(pricing, model) {
  351. return
  352. }
  353. modelPrice, findPrice := ratio_setting.GetModelPrice(model, false)
  354. if findPrice {
  355. pricing.ModelPrice = modelPrice
  356. pricing.ModelRatio = 0
  357. pricing.CompletionRatio = 0
  358. pricing.QuotaType = QuotaTypeByCall
  359. } else {
  360. modelRatio, _, _ := ratio_setting.GetModelRatio(model)
  361. pricing.ModelPrice = 0
  362. pricing.ModelRatio = modelRatio
  363. pricing.CompletionRatio = ratio_setting.GetCompletionRatio(model)
  364. pricing.QuotaType = QuotaTypeByTokens
  365. }
  366. pricing.CacheRatio, _ = ratio_setting.GetCacheRatio(model)
  367. pricing.CacheCreationRatio, _ = ratio_setting.GetCreateCacheRatio(model)
  368. }
  369. func applyMatrixPricingConfig(pricing *Pricing, model string) bool {
  370. cfg := ratio_setting.GetPricingConfig(model)
  371. if cfg == nil {
  372. return false
  373. }
  374. pricing.PricingConfig = cfg
  375. minPrice := minPricingConfigPrice(cfg)
  376. if cfg.BillingUnit == types.BillingUnitPer1MTokens {
  377. pricing.ModelPrice = minPrice
  378. pricing.ModelRatio = 0
  379. pricing.CompletionRatio = 0
  380. pricing.QuotaType = QuotaTypeByTokens
  381. return true
  382. }
  383. pricing.ModelPrice = minPrice
  384. pricing.ModelRatio = 0
  385. pricing.CompletionRatio = 0
  386. pricing.QuotaType = QuotaTypeByCall
  387. return true
  388. }
  389. func minPricingConfigPrice(cfg *types.PricingConfig) float64 {
  390. if cfg == nil || len(cfg.Table) == 0 {
  391. return 0
  392. }
  393. var min float64
  394. found := false
  395. for _, row := range cfg.Table {
  396. price, ok := pricingRowNumber(row["price"])
  397. if !ok {
  398. continue
  399. }
  400. if !found || price < min {
  401. min = price
  402. found = true
  403. }
  404. }
  405. return min
  406. }
  407. func pricingRowNumber(v any) (float64, bool) {
  408. switch n := v.(type) {
  409. case float64:
  410. return n, true
  411. case float32:
  412. return float64(n), true
  413. case int:
  414. return float64(n), true
  415. case int64:
  416. return float64(n), true
  417. case int32:
  418. return float64(n), true
  419. default:
  420. return 0, false
  421. }
  422. }