mirror of
				https://github.com/linux-do/new-api.git
				synced 2025-11-04 21:33:41 +08:00 
			
		
		
		
	add gpt-4o tokenizer
Signed-off-by: wozulong <>
This commit is contained in:
		@@ -50,14 +50,14 @@
 | 
			
		||||
 | 
			
		||||
## 模型支持
 | 
			
		||||
此版本额外支持以下模型:
 | 
			
		||||
1. 第三方模型 **gps** (gpt-4-gizmo-*)
 | 
			
		||||
1. 第三方模型 **gps** (gpt-4-gizmo-*, g-*)
 | 
			
		||||
2. 智谱glm-4v,glm-4v识图
 | 
			
		||||
3. Anthropic Claude 3 (claude-3-opus-20240229, claude-3-sonnet-20240229)
 | 
			
		||||
4. [Ollama](https://github.com/ollama/ollama?tab=readme-ov-file),添加渠道时,密钥可以随便填写,默认的请求地址是[http://localhost:11434](http://localhost:11434),如果需要修改请在渠道中修改
 | 
			
		||||
5. [Midjourney-Proxy(Plus)](https://github.com/novicezk/midjourney-proxy)接口,[对接文档](Midjourney.md)
 | 
			
		||||
6. [零一万物](https://platform.lingyiwanwu.com/)
 | 
			
		||||
 | 
			
		||||
您可以在渠道中添加自定义模型gpt-4-gizmo-*,此模型并非OpenAI官方模型,而是第三方模型,使用官方key无法调用。
 | 
			
		||||
您可以在渠道中添加自定义模型gpt-4-gizmo-*或g-*,此模型并非OpenAI官方模型,而是第三方模型,使用官方key无法调用。
 | 
			
		||||
 | 
			
		||||
## 渠道重试
 | 
			
		||||
渠道重试功能已经实现,可以在`设置->运营设置->通用设置`设置重试次数,建议开启缓存功能。  
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ import (
 | 
			
		||||
var DefaultModelRatio = map[string]float64{
 | 
			
		||||
	//"midjourney":                50,
 | 
			
		||||
	"gpt-4-gizmo-*":                15,
 | 
			
		||||
	"g-*":                          15,
 | 
			
		||||
	"gpt-4":                        15,
 | 
			
		||||
	"gpt-4-0314":                   15,
 | 
			
		||||
	"gpt-4-0613":                   15,
 | 
			
		||||
@@ -120,6 +121,7 @@ var DefaultModelRatio = map[string]float64{
 | 
			
		||||
 | 
			
		||||
var DefaultModelPrice = map[string]float64{
 | 
			
		||||
	"gpt-4-gizmo-*":     0.1,
 | 
			
		||||
	"g-*":               0.1,
 | 
			
		||||
	"mj_imagine":        0.1,
 | 
			
		||||
	"mj_variation":      0.1,
 | 
			
		||||
	"mj_reroll":         0.1,
 | 
			
		||||
@@ -162,6 +164,8 @@ func GetModelPrice(name string, printErr bool) float64 {
 | 
			
		||||
	}
 | 
			
		||||
	if strings.HasPrefix(name, "gpt-4-gizmo") {
 | 
			
		||||
		name = "gpt-4-gizmo-*"
 | 
			
		||||
	} else if strings.HasPrefix(name, "g-") {
 | 
			
		||||
		name = "g-*"
 | 
			
		||||
	}
 | 
			
		||||
	price, ok := modelPrice[name]
 | 
			
		||||
	if !ok {
 | 
			
		||||
@@ -195,6 +199,8 @@ func GetModelRatio(name string) float64 {
 | 
			
		||||
	}
 | 
			
		||||
	if strings.HasPrefix(name, "gpt-4-gizmo") {
 | 
			
		||||
		name = "gpt-4-gizmo-*"
 | 
			
		||||
	} else if strings.HasPrefix(name, "g-") {
 | 
			
		||||
		name = "g-*"
 | 
			
		||||
	}
 | 
			
		||||
	ratio, ok := modelRatio[name]
 | 
			
		||||
	if !ok {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.mod
									
									
									
									
									
								
							@@ -16,11 +16,11 @@ require (
 | 
			
		||||
	github.com/go-playground/validator/v10 v10.19.0
 | 
			
		||||
	github.com/go-redis/redis/v8 v8.11.5
 | 
			
		||||
	github.com/golang-jwt/jwt v3.2.2+incompatible
 | 
			
		||||
	github.com/google/uuid v1.3.0
 | 
			
		||||
	github.com/google/uuid v1.6.0
 | 
			
		||||
	github.com/gorilla/websocket v1.5.0
 | 
			
		||||
	github.com/jinzhu/copier v0.4.0
 | 
			
		||||
	github.com/linux-do/tiktoken-go v0.7.0
 | 
			
		||||
	github.com/pkg/errors v0.9.1
 | 
			
		||||
	github.com/pkoukk/tiktoken-go v0.1.6
 | 
			
		||||
	github.com/samber/lo v1.39.0
 | 
			
		||||
	github.com/shirou/gopsutil v3.21.11+incompatible
 | 
			
		||||
	github.com/stripe/stripe-go/v76 v76.21.0
 | 
			
		||||
@@ -42,7 +42,7 @@ require (
 | 
			
		||||
	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 | 
			
		||||
	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
 | 
			
		||||
	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 | 
			
		||||
	github.com/dlclark/regexp2 v1.10.0 // indirect
 | 
			
		||||
	github.com/dlclark/regexp2 v1.11.0 // indirect
 | 
			
		||||
	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
 | 
			
		||||
	github.com/gin-contrib/sse v0.1.0 // indirect
 | 
			
		||||
	github.com/go-ole/go-ole v1.2.6 // indirect
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.sum
									
									
									
									
									
								
							@@ -32,6 +32,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
 | 
			
		||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
 | 
			
		||||
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
 | 
			
		||||
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
 | 
			
		||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
 | 
			
		||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
 | 
			
		||||
@@ -81,6 +83,8 @@ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
 | 
			
		||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
			
		||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
 | 
			
		||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 | 
			
		||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
 | 
			
		||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 | 
			
		||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
 | 
			
		||||
@@ -122,6 +126,8 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx
 | 
			
		||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
 | 
			
		||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
 | 
			
		||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
 | 
			
		||||
github.com/linux-do/tiktoken-go v0.7.0 h1:Kcm/miJ5gp77srtF8GQWnfq7W9kTaXEuHZg/g9IVEu8=
 | 
			
		||||
github.com/linux-do/tiktoken-go v0.7.0/go.mod h1:9Vkdtp0ngi4USmrdSx984iuIQ5IMr0hnUdz4jZZTJb8=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
 | 
			
		||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 | 
			
		||||
 
 | 
			
		||||
@@ -293,6 +293,8 @@ func SyncChannelCache(frequency int) {
 | 
			
		||||
func CacheGetRandomSatisfiedChannel(group string, model string, retry int) (*Channel, error) {
 | 
			
		||||
	if strings.HasPrefix(model, "gpt-4-gizmo") {
 | 
			
		||||
		model = "gpt-4-gizmo-*"
 | 
			
		||||
	} else if strings.HasPrefix(model, "g-") {
 | 
			
		||||
		model = "g-*"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if memory cache is disabled, get channel directly from database
 | 
			
		||||
 
 | 
			
		||||
@@ -314,6 +314,9 @@ func postConsumeQuota(ctx *gin.Context, relayInfo *relaycommon.RelayInfo, textRe
 | 
			
		||||
	if strings.HasPrefix(logModel, "gpt-4-gizmo") {
 | 
			
		||||
		logModel = "gpt-4-gizmo-*"
 | 
			
		||||
		logContent += fmt.Sprintf(",模型 %s", textRequest.Model)
 | 
			
		||||
	} else if strings.HasPrefix(logModel, "g-") {
 | 
			
		||||
		logModel = "g-*"
 | 
			
		||||
		logContent += fmt.Sprintf(",模型 %s", textRequest.Model)
 | 
			
		||||
	}
 | 
			
		||||
	model.RecordConsumeLog(ctx, relayInfo.UserId, relayInfo.ChannelId, promptTokens, completionTokens, logModel, tokenName, quota, logContent, relayInfo.TokenId, userQuota, int(useTimeSeconds), relayInfo.IsStream)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import (
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/pkoukk/tiktoken-go"
 | 
			
		||||
	"github.com/linux-do/tiktoken-go"
 | 
			
		||||
	"image"
 | 
			
		||||
	"log"
 | 
			
		||||
	"math"
 | 
			
		||||
@@ -29,9 +29,16 @@ func InitTokenEncoders() {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		common.FatalLog(fmt.Sprintf("failed to get gpt-4 token encoder: %s", err.Error()))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gpt4oTokenEncoder, err := tiktoken.EncodingForModel("gpt-4o")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		common.FatalLog(fmt.Sprintf("failed to get gpt-4o token encoder: %s", err.Error()))
 | 
			
		||||
	}
 | 
			
		||||
	for model, _ := range common.DefaultModelRatio {
 | 
			
		||||
		if strings.HasPrefix(model, "gpt-3.5") {
 | 
			
		||||
			tokenEncoderMap[model] = gpt35TokenEncoder
 | 
			
		||||
		} else if strings.HasPrefix(model, "gpt-4o") {
 | 
			
		||||
			tokenEncoderMap[model] = gpt4oTokenEncoder
 | 
			
		||||
		} else if strings.HasPrefix(model, "gpt-4") {
 | 
			
		||||
			tokenEncoderMap[model] = gpt4TokenEncoder
 | 
			
		||||
		} else {
 | 
			
		||||
 
 | 
			
		||||
@@ -579,7 +579,7 @@ const OperationSetting = () => {
 | 
			
		||||
              style={{ minHeight: 250, fontFamily: 'JetBrains Mono, Consolas' }}
 | 
			
		||||
              autoComplete='new-password'
 | 
			
		||||
              value={inputs.ModelPrice}
 | 
			
		||||
              placeholder='为一个 JSON 文本,键为模型名称,值为一次调用消耗多少刀,比如 "gpt-4-gizmo-*": 0.1,一次消耗0.1刀'
 | 
			
		||||
              placeholder='为一个 JSON 文本,键为模型名称,值为一次调用消耗多少刀,比如 "gpt-4-gizmo-*": 0.1(或 "g-*": 0.1),一次消耗0.1刀'
 | 
			
		||||
            />
 | 
			
		||||
          </Form.Group>
 | 
			
		||||
          <Form.Group widths='equal'>
 | 
			
		||||
 
 | 
			
		||||
@@ -186,6 +186,7 @@ export const modelColorMap = {
 | 
			
		||||
  'gpt-4-32k-0613': 'rgb(61,71,139)', // 暗蓝灰色
 | 
			
		||||
  'gpt-4-all': 'rgb(65,105,225)', // 皇家蓝
 | 
			
		||||
  'gpt-4-gizmo-*': 'rgb(0,0,255)', // 纯蓝色
 | 
			
		||||
  'g-*': 'rgb(0,0,255)', // 纯蓝色
 | 
			
		||||
  'gpt-4-vision-preview': 'rgb(25,25,112)', // 午夜蓝
 | 
			
		||||
  'text-ada-001': 'rgb(255,192,203)', // 粉红色
 | 
			
		||||
  'text-babbage-001': 'rgb(255,160,122)', // 浅珊瑚色
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user