Merge branches 'main' and 'main' of github.com:danding5/new-api

# Conflicts:
#	common/api_type.go
#	constant/api_type.go
#	constant/channel.go
#	relay/relay_adaptor.go
#	web/src/constants/channel.constants.js
This commit is contained in:
DD
2025-09-10 18:33:42 +08:00
597 changed files with 61068 additions and 26580 deletions

View File

@@ -25,6 +25,16 @@ var defaultCacheRatio = map[string]float64{
"gpt-4o-mini-realtime-preview": 0.5,
"gpt-4.5-preview": 0.5,
"gpt-4.5-preview-2025-02-27": 0.5,
"gpt-4.1": 0.25,
"gpt-4.1-mini": 0.25,
"gpt-4.1-nano": 0.25,
"gpt-5": 0.1,
"gpt-5-2025-08-07": 0.1,
"gpt-5-chat-latest": 0.1,
"gpt-5-mini": 0.1,
"gpt-5-mini-2025-08-07": 0.1,
"gpt-5-nano": 0.1,
"gpt-5-nano-2025-08-07": 0.1,
"deepseek-chat": 0.25,
"deepseek-reasoner": 0.25,
"deepseek-coder": 0.25,
@@ -40,6 +50,8 @@ var defaultCacheRatio = map[string]float64{
"claude-sonnet-4-20250514-thinking": 0.1,
"claude-opus-4-20250514": 0.1,
"claude-opus-4-20250514-thinking": 0.1,
"claude-opus-4-1-20250805": 0.1,
"claude-opus-4-1-20250805-thinking": 0.1,
}
var defaultCreateCacheRatio = map[string]float64{
@@ -55,6 +67,8 @@ var defaultCreateCacheRatio = map[string]float64{
"claude-sonnet-4-20250514-thinking": 1.25,
"claude-opus-4-20250514": 1.25,
"claude-opus-4-20250514-thinking": 1.25,
"claude-opus-4-1-20250805": 1.25,
"claude-opus-4-1-20250805-thinking": 1.25,
}
//var defaultCreateCacheRatio = map[string]float64{}
@@ -75,7 +89,7 @@ func CacheRatio2JSONString() string {
defer cacheRatioMapMutex.RUnlock()
jsonBytes, err := json.Marshal(cacheRatioMap)
if err != nil {
common.SysError("error marshalling cache ratio: " + err.Error())
common.SysLog("error marshalling cache ratio: " + err.Error())
}
return string(jsonBytes)
}

View File

@@ -5,13 +5,13 @@ import "sync/atomic"
var exposeRatioEnabled atomic.Bool
func init() {
exposeRatioEnabled.Store(false)
exposeRatioEnabled.Store(false)
}
func SetExposeRatioEnabled(enabled bool) {
exposeRatioEnabled.Store(enabled)
exposeRatioEnabled.Store(enabled)
}
func IsExposeRatioEnabled() bool {
return exposeRatioEnabled.Load()
}
return exposeRatioEnabled.Load()
}

View File

@@ -1,55 +1,55 @@
package ratio_setting
import (
"sync"
"sync/atomic"
"time"
"sync"
"sync/atomic"
"time"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin"
)
const exposedDataTTL = 30 * time.Second
type exposedCache struct {
data gin.H
expiresAt time.Time
data gin.H
expiresAt time.Time
}
var (
exposedData atomic.Value
rebuildMu sync.Mutex
exposedData atomic.Value
rebuildMu sync.Mutex
)
func InvalidateExposedDataCache() {
exposedData.Store((*exposedCache)(nil))
exposedData.Store((*exposedCache)(nil))
}
func cloneGinH(src gin.H) gin.H {
dst := make(gin.H, len(src))
for k, v := range src {
dst[k] = v
}
return dst
dst := make(gin.H, len(src))
for k, v := range src {
dst[k] = v
}
return dst
}
func GetExposedData() gin.H {
if c, ok := exposedData.Load().(*exposedCache); ok && c != nil && time.Now().Before(c.expiresAt) {
return cloneGinH(c.data)
}
rebuildMu.Lock()
defer rebuildMu.Unlock()
if c, ok := exposedData.Load().(*exposedCache); ok && c != nil && time.Now().Before(c.expiresAt) {
return cloneGinH(c.data)
}
newData := gin.H{
"model_ratio": GetModelRatioCopy(),
"completion_ratio": GetCompletionRatioCopy(),
"cache_ratio": GetCacheRatioCopy(),
"model_price": GetModelPriceCopy(),
}
exposedData.Store(&exposedCache{
data: newData,
expiresAt: time.Now().Add(exposedDataTTL),
})
return cloneGinH(newData)
}
if c, ok := exposedData.Load().(*exposedCache); ok && c != nil && time.Now().Before(c.expiresAt) {
return cloneGinH(c.data)
}
rebuildMu.Lock()
defer rebuildMu.Unlock()
if c, ok := exposedData.Load().(*exposedCache); ok && c != nil && time.Now().Before(c.expiresAt) {
return cloneGinH(c.data)
}
newData := gin.H{
"model_ratio": GetModelRatioCopy(),
"completion_ratio": GetCompletionRatioCopy(),
"cache_ratio": GetCacheRatioCopy(),
"model_price": GetModelPriceCopy(),
}
exposedData.Store(&exposedCache{
data: newData,
expiresAt: time.Now().Add(exposedDataTTL),
})
return cloneGinH(newData)
}

View File

@@ -48,7 +48,7 @@ func GroupRatio2JSONString() string {
jsonBytes, err := json.Marshal(groupRatio)
if err != nil {
common.SysError("error marshalling model ratio: " + err.Error())
common.SysLog("error marshalling model ratio: " + err.Error())
}
return string(jsonBytes)
}
@@ -67,7 +67,7 @@ func GetGroupRatio(name string) float64 {
ratio, ok := groupRatio[name]
if !ok {
common.SysError("group ratio not found: " + name)
common.SysLog("group ratio not found: " + name)
return 1
}
return ratio
@@ -94,7 +94,7 @@ func GroupGroupRatio2JSONString() string {
jsonBytes, err := json.Marshal(GroupGroupRatio)
if err != nil {
common.SysError("error marshalling group-group ratio: " + err.Error())
common.SysLog("error marshalling group-group ratio: " + err.Error())
}
return string(jsonBytes)
}

View File

@@ -52,27 +52,52 @@ var defaultModelRatio = map[string]float64{
"gpt-4o-realtime-preview-2024-12-17": 2.5,
"gpt-4o-mini-realtime-preview": 0.3,
"gpt-4o-mini-realtime-preview-2024-12-17": 0.3,
"gpt-image-1": 2.5,
"o1": 7.5,
"o1-2024-12-17": 7.5,
"o1-preview": 7.5,
"o1-preview-2024-09-12": 7.5,
"o1-mini": 0.55,
"o1-mini-2024-09-12": 0.55,
"o3-mini": 0.55,
"o3-mini-2025-01-31": 0.55,
"o3-mini-high": 0.55,
"o3-mini-2025-01-31-high": 0.55,
"o3-mini-low": 0.55,
"o3-mini-2025-01-31-low": 0.55,
"o3-mini-medium": 0.55,
"o3-mini-2025-01-31-medium": 0.55,
"gpt-4o-mini": 0.075,
"gpt-4o-mini-2024-07-18": 0.075,
"gpt-4-turbo": 5, // $0.01 / 1K tokens
"gpt-4-turbo-2024-04-09": 5, // $0.01 / 1K tokens
"gpt-4.5-preview": 37.5,
"gpt-4.5-preview-2025-02-27": 37.5,
"gpt-4.1": 1.0, // $2 / 1M tokens
"gpt-4.1-2025-04-14": 1.0, // $2 / 1M tokens
"gpt-4.1-mini": 0.2, // $0.4 / 1M tokens
"gpt-4.1-mini-2025-04-14": 0.2, // $0.4 / 1M tokens
"gpt-4.1-nano": 0.05, // $0.1 / 1M tokens
"gpt-4.1-nano-2025-04-14": 0.05, // $0.1 / 1M tokens
"gpt-image-1": 2.5, // $5 / 1M tokens
"o1": 7.5, // $15 / 1M tokens
"o1-2024-12-17": 7.5, // $15 / 1M tokens
"o1-preview": 7.5, // $15 / 1M tokens
"o1-preview-2024-09-12": 7.5, // $15 / 1M tokens
"o1-mini": 0.55, // $1.1 / 1M tokens
"o1-mini-2024-09-12": 0.55, // $1.1 / 1M tokens
"o1-pro": 75.0, // $150 / 1M tokens
"o1-pro-2025-03-19": 75.0, // $150 / 1M tokens
"o3-mini": 0.55,
"o3-mini-2025-01-31": 0.55,
"o3-mini-high": 0.55,
"o3-mini-2025-01-31-high": 0.55,
"o3-mini-low": 0.55,
"o3-mini-2025-01-31-low": 0.55,
"o3-mini-medium": 0.55,
"o3-mini-2025-01-31-medium": 0.55,
"o3": 1.0, // $2 / 1M tokens
"o3-2025-04-16": 1.0, // $2 / 1M tokens
"o3-pro": 10.0, // $20 / 1M tokens
"o3-pro-2025-06-10": 10.0, // $20 / 1M tokens
"o3-deep-research": 5.0, // $10 / 1M tokens
"o3-deep-research-2025-06-26": 5.0, // $10 / 1M tokens
"o4-mini": 0.55, // $1.1 / 1M tokens
"o4-mini-2025-04-16": 0.55, // $1.1 / 1M tokens
"o4-mini-deep-research": 1.0, // $2 / 1M tokens
"o4-mini-deep-research-2025-06-26": 1.0, // $2 / 1M tokens
"gpt-4o-mini": 0.075,
"gpt-4o-mini-2024-07-18": 0.075,
"gpt-4-turbo": 5, // $0.01 / 1K tokens
"gpt-4-turbo-2024-04-09": 5, // $0.01 / 1K tokens
"gpt-4.5-preview": 37.5,
"gpt-4.5-preview-2025-02-27": 37.5,
"gpt-5": 0.625,
"gpt-5-2025-08-07": 0.625,
"gpt-5-chat-latest": 0.625,
"gpt-5-mini": 0.125,
"gpt-5-mini-2025-08-07": 0.125,
"gpt-5-nano": 0.025,
"gpt-5-nano-2025-08-07": 0.025,
//"gpt-3.5-turbo-0301": 0.75, //deprecated
"gpt-3.5-turbo": 0.25,
"gpt-3.5-turbo-0613": 0.75,
@@ -118,6 +143,7 @@ var defaultModelRatio = map[string]float64{
"claude-sonnet-4-20250514": 1.5,
"claude-3-opus-20240229": 7.5, // $15 / 1M tokens
"claude-opus-4-20250514": 7.5,
"claude-opus-4-1-20250805": 7.5,
"ERNIE-4.0-8K": 0.120 * RMB,
"ERNIE-3.5-8K": 0.012 * RMB,
"ERNIE-3.5-8K-0205": 0.024 * RMB,
@@ -149,8 +175,10 @@ var defaultModelRatio = map[string]float64{
"gemini-2.5-flash-preview-05-20-nothinking": 0.075,
"gemini-2.5-flash-thinking-*": 0.075, // 用于为后续所有2.5 flash thinking budget 模型设置默认倍率
"gemini-2.5-pro-thinking-*": 0.625, // 用于为后续所有2.5 pro thinking budget 模型设置默认倍率
"gemini-2.5-flash-lite-preview-thinking-*": 0.05,
"gemini-2.5-flash-lite-preview-06-17": 0.05,
"gemini-2.5-flash": 0.15,
"gemini-2.5-flash-image-preview": 0.15, // $0.30text/image) / 1M tokens
"text-embedding-004": 0.001,
"chatglm_turbo": 0.3572, // ¥0.005 / 1k tokens
"chatglm_pro": 0.7143, // ¥0.01 / 1k tokens
@@ -279,10 +307,11 @@ var (
)
var defaultCompletionRatio = map[string]float64{
"gpt-4-gizmo-*": 2,
"gpt-4o-gizmo-*": 3,
"gpt-4-all": 2,
"gpt-image-1": 8,
"gpt-4-gizmo-*": 2,
"gpt-4o-gizmo-*": 3,
"gpt-4-all": 2,
"gpt-image-1": 8,
"gemini-2.5-flash-image-preview": 8.3333333333,
}
// InitRatioSettings initializes all model related settings maps
@@ -324,7 +353,7 @@ func ModelPrice2JSONString() string {
modelPriceMapMutex.RLock()
defer modelPriceMapMutex.RUnlock()
jsonBytes, err := json.Marshal(modelPriceMap)
jsonBytes, err := common.Marshal(modelPriceMap)
if err != nil {
common.SysError("error marshalling model price: " + err.Error())
}
@@ -347,12 +376,8 @@ func GetModelPrice(name string, printErr bool) (float64, bool) {
modelPriceMapMutex.RLock()
defer modelPriceMapMutex.RUnlock()
if strings.HasPrefix(name, "gpt-4-gizmo") {
name = "gpt-4-gizmo-*"
}
if strings.HasPrefix(name, "gpt-4o-gizmo") {
name = "gpt-4o-gizmo-*"
}
name = FormatMatchingModelName(name)
price, ok := modelPriceMap[name]
if !ok {
if printErr {
@@ -367,7 +392,7 @@ func UpdateModelRatioByJSONString(jsonStr string) error {
modelRatioMapMutex.Lock()
defer modelRatioMapMutex.Unlock()
modelRatioMap = make(map[string]float64)
err := json.Unmarshal([]byte(jsonStr), &modelRatioMap)
err := common.Unmarshal([]byte(jsonStr), &modelRatioMap)
if err == nil {
InvalidateExposedDataCache()
}
@@ -386,11 +411,8 @@ func GetModelRatio(name string) (float64, bool, string) {
modelRatioMapMutex.RLock()
defer modelRatioMapMutex.RUnlock()
name = handleThinkingBudgetModel(name, "gemini-2.5-flash", "gemini-2.5-flash-thinking-*")
name = handleThinkingBudgetModel(name, "gemini-2.5-pro", "gemini-2.5-pro-thinking-*")
if strings.HasPrefix(name, "gpt-4-gizmo") {
name = "gpt-4-gizmo-*"
}
name = FormatMatchingModelName(name)
ratio, ok := modelRatioMap[name]
if !ok {
return 37.5, operation_setting.SelfUseModeEnabled, name
@@ -399,7 +421,7 @@ func GetModelRatio(name string) (float64, bool, string) {
}
func DefaultModelRatio2JSONString() string {
jsonBytes, err := json.Marshal(defaultModelRatio)
jsonBytes, err := common.Marshal(defaultModelRatio)
if err != nil {
common.SysError("error marshalling model ratio: " + err.Error())
}
@@ -431,7 +453,7 @@ func UpdateCompletionRatioByJSONString(jsonStr string) error {
CompletionRatioMutex.Lock()
defer CompletionRatioMutex.Unlock()
CompletionRatio = make(map[string]float64)
err := json.Unmarshal([]byte(jsonStr), &CompletionRatio)
err := common.Unmarshal([]byte(jsonStr), &CompletionRatio)
if err == nil {
InvalidateExposedDataCache()
}
@@ -441,12 +463,9 @@ func UpdateCompletionRatioByJSONString(jsonStr string) error {
func GetCompletionRatio(name string) float64 {
CompletionRatioMutex.RLock()
defer CompletionRatioMutex.RUnlock()
if strings.HasPrefix(name, "gpt-4-gizmo") {
name = "gpt-4-gizmo-*"
}
if strings.HasPrefix(name, "gpt-4o-gizmo") {
name = "gpt-4o-gizmo-*"
}
name = FormatMatchingModelName(name)
if strings.Contains(name, "/") {
if ratio, ok := CompletionRatio[name]; ok {
return ratio
@@ -464,13 +483,23 @@ func GetCompletionRatio(name string) float64 {
func getHardcodedCompletionModelRatio(name string) (float64, bool) {
lowercaseName := strings.ToLower(name)
if strings.HasPrefix(name, "gpt-4") && !strings.HasSuffix(name, "-all") && !strings.HasSuffix(name, "-gizmo-*") {
isReservedModel := strings.HasSuffix(name, "-all") || strings.HasSuffix(name, "-gizmo-*")
if isReservedModel {
return 2, false
}
if strings.HasPrefix(name, "gpt-") {
if strings.HasPrefix(name, "gpt-4o") {
if name == "gpt-4o-2024-05-13" {
return 3, true
}
return 4, true
}
// gpt-5 匹配
if strings.HasPrefix(name, "gpt-5") {
return 8, true
}
// gpt-4.5-preview匹配
if strings.HasPrefix(name, "gpt-4.5-preview") {
return 2, true
@@ -525,12 +554,9 @@ func getHardcodedCompletionModelRatio(name string) (float64, bool) {
return 3.5 / 0.15, false
}
if strings.HasPrefix(name, "gemini-2.5-flash-lite") {
if strings.HasPrefix(name, "gemini-2.5-flash-lite-preview") {
return 4, false
}
return 4, false
}
return 2.5 / 0.3, true
return 2.5 / 0.3, false
}
return 4, false
}
@@ -607,7 +633,7 @@ func ModelRatio2JSONString() string {
modelRatioMapMutex.RLock()
defer modelRatioMapMutex.RUnlock()
jsonBytes, err := json.Marshal(modelRatioMap)
jsonBytes, err := common.Marshal(modelRatioMap)
if err != nil {
common.SysError("error marshalling model ratio: " + err.Error())
}
@@ -623,7 +649,7 @@ var imageRatioMapMutex sync.RWMutex
func ImageRatio2JSONString() string {
imageRatioMapMutex.RLock()
defer imageRatioMapMutex.RUnlock()
jsonBytes, err := json.Marshal(imageRatioMap)
jsonBytes, err := common.Marshal(imageRatioMap)
if err != nil {
common.SysError("error marshalling cache ratio: " + err.Error())
}
@@ -634,7 +660,7 @@ func UpdateImageRatioByJSONString(jsonStr string) error {
imageRatioMapMutex.Lock()
defer imageRatioMapMutex.Unlock()
imageRatioMap = make(map[string]float64)
return json.Unmarshal([]byte(jsonStr), &imageRatioMap)
return common.Unmarshal([]byte(jsonStr), &imageRatioMap)
}
func GetImageRatio(name string) (float64, bool) {
@@ -676,3 +702,23 @@ func GetCompletionRatioCopy() map[string]float64 {
}
return copyMap
}
// 转换模型名,减少渠道必须配置各种带参数模型
func FormatMatchingModelName(name string) string {
if strings.HasPrefix(name, "gemini-2.5-flash-lite") {
name = handleThinkingBudgetModel(name, "gemini-2.5-flash-lite", "gemini-2.5-flash-lite-thinking-*")
} else if strings.HasPrefix(name, "gemini-2.5-flash") {
name = handleThinkingBudgetModel(name, "gemini-2.5-flash", "gemini-2.5-flash-thinking-*")
} else if strings.HasPrefix(name, "gemini-2.5-pro") {
name = handleThinkingBudgetModel(name, "gemini-2.5-pro", "gemini-2.5-pro-thinking-*")
}
if strings.HasPrefix(name, "gpt-4-gizmo") {
name = "gpt-4-gizmo-*"
}
if strings.HasPrefix(name, "gpt-4o-gizmo") {
name = "gpt-4o-gizmo-*"
}
return name
}