mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-11-06 08:05:22 +00:00
feat: add some translate (#12904)
This commit is contained in:
@@ -589,7 +589,12 @@ func (a *AppInstallService) GetUpdateVersions(req request.AppUpdateVersion) ([]d
|
||||
if common.IsCrossVersion(install.Version, detail.Version) && !app.CrossVersionUpdate {
|
||||
continue
|
||||
}
|
||||
if common.CompareVersion(detail.Version, install.Version) {
|
||||
canUpgrade := common.CompareVersion(detail.Version, install.Version)
|
||||
if app.Key == vllmAppKeyForUpgrade {
|
||||
currentImage := loadVllmImageFromEnv(install.Env)
|
||||
canUpgrade = isVllmUpgradeCandidate(install.Version, detail.Version, currentImage)
|
||||
}
|
||||
if canUpgrade {
|
||||
var newCompose string
|
||||
if req.UpdateVersion != "" && req.UpdateVersion == detail.Version && detail.DockerCompose == "" && !app.IsLocalApp() {
|
||||
filename := filepath.Base(detail.DownloadUrl)
|
||||
|
||||
@@ -682,6 +682,9 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if install.App.Key == vllmAppKeyForUpgrade && !isVllmUpgradeVersionAllowed(install.Version, detail.Version, loadVllmImageFromEnv(install.Env)) {
|
||||
return errors.New("vLLM can only upgrade within the same image type")
|
||||
}
|
||||
if install.Version == detail.Version {
|
||||
return errors.New("two version is same")
|
||||
}
|
||||
@@ -748,8 +751,25 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if install.App.Key == vllmAppKeyForUpgrade {
|
||||
envs := make(map[string]interface{})
|
||||
if err = json.Unmarshal([]byte(install.Env), &envs); err != nil {
|
||||
return err
|
||||
}
|
||||
image := buildVllmUpgradeImage(loadVllmImageFromEnv(install.Env), oldVersion, detail.Version)
|
||||
envs[vllmImageEnvKey] = image
|
||||
paramByte, err := json.Marshal(envs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
install.Env = string(paramByte)
|
||||
content = setVllmImageInEnvContent(content, image)
|
||||
}
|
||||
if req.PullImage {
|
||||
composeContent := []byte(detail.DockerCompose)
|
||||
if install.App.Key == vllmAppKeyForUpgrade {
|
||||
composeContent = []byte(install.DockerCompose)
|
||||
}
|
||||
if req.DockerCompose != "" {
|
||||
composeContent = []byte(req.DockerCompose)
|
||||
}
|
||||
@@ -811,9 +831,13 @@ func upgradeInstall(req request.AppInstallUpgrade) error {
|
||||
return err
|
||||
}
|
||||
if req.DockerCompose == "" {
|
||||
newCompose, err = getUpgradeCompose(install, detail)
|
||||
if err != nil {
|
||||
return err
|
||||
if install.App.Key == vllmAppKeyForUpgrade {
|
||||
newCompose = install.DockerCompose
|
||||
} else {
|
||||
newCompose, err = getUpgradeCompose(install, detail)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newCompose = req.DockerCompose
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/common"
|
||||
)
|
||||
|
||||
const (
|
||||
vllmAppKeyForUpgrade = "vllm"
|
||||
vllmImageEnvKey = "IMAGE"
|
||||
vllmImageTypeNvidia = "nvidia"
|
||||
vllmImageTypeIntel = "intel"
|
||||
)
|
||||
|
||||
func resolveVllmVersionFamily(version, image string) string {
|
||||
normalizedVersion := strings.ToLower(strings.TrimSpace(version))
|
||||
if strings.HasPrefix(normalizedVersion, vllmImageTypeIntel+"-") {
|
||||
return vllmImageTypeIntel
|
||||
}
|
||||
if strings.HasPrefix(normalizedVersion, vllmImageTypeNvidia+"-") {
|
||||
return vllmImageTypeNvidia
|
||||
}
|
||||
normalizedImage := strings.ToLower(strings.TrimSpace(image))
|
||||
if strings.Contains(normalizedImage, "intel/") || strings.Contains(normalizedImage, "llm-scaler-vllm") {
|
||||
return vllmImageTypeIntel
|
||||
}
|
||||
return vllmImageTypeNvidia
|
||||
}
|
||||
|
||||
func trimVllmVersionFamily(version string) string {
|
||||
trimmed := strings.TrimSpace(version)
|
||||
normalized := strings.ToLower(trimmed)
|
||||
for _, family := range []string{vllmImageTypeNvidia, vllmImageTypeIntel} {
|
||||
prefix := family + "-"
|
||||
if strings.HasPrefix(normalized, prefix) {
|
||||
return strings.TrimSpace(trimmed[len(prefix):])
|
||||
}
|
||||
}
|
||||
return trimmed
|
||||
}
|
||||
|
||||
func buildDefaultVllmImageByVersion(version string) string {
|
||||
tag := trimVllmVersionFamily(version)
|
||||
if resolveVllmVersionFamily(version, "") == vllmImageTypeIntel {
|
||||
return "intel/llm-scaler-vllm:" + tag
|
||||
}
|
||||
if tag != "" && !strings.HasPrefix(strings.ToLower(tag), "v") {
|
||||
tag = "v" + tag
|
||||
}
|
||||
return "vllm/vllm-openai:" + tag
|
||||
}
|
||||
|
||||
func isVllmUpgradeVersionAllowed(currentVersion, targetVersion, currentImage string) bool {
|
||||
currentFamily := resolveVllmVersionFamily(currentVersion, currentImage)
|
||||
targetFamily := resolveVllmVersionFamily(targetVersion, "")
|
||||
return currentFamily == targetFamily
|
||||
}
|
||||
|
||||
func hasVllmVersionFamilyPrefix(version string) bool {
|
||||
normalized := strings.ToLower(strings.TrimSpace(version))
|
||||
return strings.HasPrefix(normalized, vllmImageTypeNvidia+"-") || strings.HasPrefix(normalized, vllmImageTypeIntel+"-")
|
||||
}
|
||||
|
||||
func isVllmUpgradeCandidate(currentVersion, targetVersion, currentImage string) bool {
|
||||
if strings.TrimSpace(currentVersion) == strings.TrimSpace(targetVersion) {
|
||||
return false
|
||||
}
|
||||
if !isVllmUpgradeVersionAllowed(currentVersion, targetVersion, currentImage) {
|
||||
return false
|
||||
}
|
||||
if common.CompareVersion(targetVersion, currentVersion) {
|
||||
return true
|
||||
}
|
||||
return !hasVllmVersionFamilyPrefix(currentVersion) &&
|
||||
resolveVllmVersionFamily(targetVersion, "") == vllmImageTypeNvidia &&
|
||||
trimVllmVersionFamily(currentVersion) == trimVllmVersionFamily(targetVersion)
|
||||
}
|
||||
|
||||
func buildVllmUpgradeImage(currentImage, currentVersion, targetVersion string) string {
|
||||
trimmedImage := strings.TrimSpace(currentImage)
|
||||
if trimmedImage == "" || trimmedImage == buildDefaultVllmImageByVersion(currentVersion) {
|
||||
return buildDefaultVllmImageByVersion(targetVersion)
|
||||
}
|
||||
return trimmedImage
|
||||
}
|
||||
|
||||
func loadVllmImageFromEnv(raw string) string {
|
||||
envs := make(map[string]interface{})
|
||||
if strings.TrimSpace(raw) == "" {
|
||||
return ""
|
||||
}
|
||||
if err := json.Unmarshal([]byte(raw), &envs); err != nil {
|
||||
return ""
|
||||
}
|
||||
if image, ok := envs[vllmImageEnvKey].(string); ok {
|
||||
return strings.TrimSpace(image)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func setVllmImageInEnvContent(content []byte, image string) []byte {
|
||||
normalizedImage := strings.TrimSpace(image)
|
||||
if normalizedImage == "" {
|
||||
return content
|
||||
}
|
||||
lines := strings.Split(string(content), "\n")
|
||||
replaced := false
|
||||
for index, line := range lines {
|
||||
if strings.HasPrefix(line, vllmImageEnvKey+"=") {
|
||||
lines[index] = vllmImageEnvKey + "=" + normalizedImage
|
||||
replaced = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !replaced {
|
||||
if len(lines) > 0 && lines[len(lines)-1] == "" {
|
||||
lines[len(lines)-1] = vllmImageEnvKey + "=" + normalizedImage
|
||||
lines = append(lines, "")
|
||||
} else {
|
||||
lines = append(lines, vllmImageEnvKey+"="+normalizedImage)
|
||||
}
|
||||
}
|
||||
return []byte(strings.Join(lines, "\n"))
|
||||
}
|
||||
@@ -4,7 +4,7 @@ base:
|
||||
is_demo: false
|
||||
is_offline: false
|
||||
is_fxplay: false
|
||||
is_enterprise: false
|
||||
is_enterprise: true
|
||||
|
||||
log:
|
||||
level: debug
|
||||
|
||||
@@ -16,18 +16,38 @@ import (
|
||||
)
|
||||
|
||||
func Init() {
|
||||
global.LOG.Info("agent hook: init global data start")
|
||||
initGlobalData()
|
||||
global.LOG.Info("agent hook: init global data done")
|
||||
global.LOG.Info("agent hook: handle cronjob status start")
|
||||
handleCronjobStatus()
|
||||
global.LOG.Info("agent hook: handle cronjob status done")
|
||||
global.LOG.Info("agent hook: handle clam status start")
|
||||
handleClamStatus()
|
||||
global.LOG.Info("agent hook: handle clam status done")
|
||||
global.LOG.Info("agent hook: handle record status start")
|
||||
handleRecordStatus()
|
||||
global.LOG.Info("agent hook: handle record status done")
|
||||
global.LOG.Info("agent hook: handle snapshot status start")
|
||||
handleSnapStatus()
|
||||
global.LOG.Info("agent hook: handle snapshot status done")
|
||||
global.LOG.Info("agent hook: handle ollama model status start")
|
||||
handleOllamaModelStatus()
|
||||
global.LOG.Info("agent hook: handle ollama model status done")
|
||||
|
||||
global.LOG.Info("agent hook: load local dir start")
|
||||
loadLocalDir()
|
||||
global.LOG.Info("agent hook: load local dir done")
|
||||
|
||||
global.LOG.Info("agent hook: init docker config start")
|
||||
initDockerConf()
|
||||
global.LOG.Info("agent hook: init docker config done")
|
||||
global.LOG.Info("agent hook: init alert task start")
|
||||
initAlertTask()
|
||||
global.LOG.Info("agent hook: init alert task done")
|
||||
global.LOG.Info("agent hook: init monitor db start")
|
||||
initMonitorDB()
|
||||
global.LOG.Info("agent hook: init monitor db done")
|
||||
}
|
||||
|
||||
func initGlobalData() {
|
||||
|
||||
@@ -95,19 +95,32 @@ func Start() {
|
||||
viper.Init()
|
||||
dir.Init()
|
||||
log.Init()
|
||||
global.LOG.Info("agent startup: logger initialized")
|
||||
db.Init()
|
||||
global.LOG.Info("agent startup: database initialized")
|
||||
migration.Init()
|
||||
global.LOG.Info("agent startup: migration initialized")
|
||||
i18n.Init()
|
||||
global.LOG.Info("agent startup: i18n initialized")
|
||||
cache.Init()
|
||||
global.LOG.Info("agent startup: cache initialized")
|
||||
app.Init()
|
||||
global.LOG.Info("agent startup: app initialized")
|
||||
lang.Init()
|
||||
global.LOG.Info("agent startup: language initialized")
|
||||
validator.Init()
|
||||
global.LOG.Info("agent startup: validator initialized")
|
||||
cron.Run()
|
||||
global.LOG.Info("agent startup: cron initialized")
|
||||
hook.Init()
|
||||
global.LOG.Info("agent startup: hook initialized")
|
||||
go firewall.Init()
|
||||
global.LOG.Info("agent startup: firewall init scheduled")
|
||||
InitOthers()
|
||||
global.LOG.Info("agent startup: edition initialized")
|
||||
|
||||
rootRouter := router.Routers()
|
||||
global.LOG.Info("agent startup: router initialized")
|
||||
|
||||
server := &http.Server{
|
||||
Handler: rootRouter,
|
||||
@@ -120,6 +133,7 @@ func Start() {
|
||||
}
|
||||
|
||||
if global.IsMaster {
|
||||
global.LOG.Infof("agent startup: master mode, preparing unix socket %s", masterSocketPath)
|
||||
if err := prepareMasterSocketDir(masterSocketDir); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -132,11 +146,14 @@ func Start() {
|
||||
_ = listener.Close()
|
||||
panic(err)
|
||||
}
|
||||
global.LOG.Infof("agent startup: listening on unix socket %s", masterSocketPath)
|
||||
business.Init()
|
||||
global.LOG.Info("agent startup: business initialized")
|
||||
_ = server.Serve(listener)
|
||||
return
|
||||
} else {
|
||||
server.Addr = fmt.Sprintf("0.0.0.0:%s", global.CONF.Base.Port)
|
||||
global.LOG.Infof("agent startup: node mode, preparing https listener %s", server.Addr)
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
certItem, err := settingRepo.Get(settingRepo.WithByKey("ServerCrt"))
|
||||
if err != nil {
|
||||
@@ -166,6 +183,7 @@ func Start() {
|
||||
server.TLSConfig.ClientCAs = caCertPool
|
||||
}
|
||||
business.Init()
|
||||
global.LOG.Info("agent startup: business initialized")
|
||||
global.LOG.Infof("listen at https://0.0.0.0:%s", global.CONF.Base.Port)
|
||||
if err := server.ListenAndServeTLS("", ""); err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -4,7 +4,7 @@ base:
|
||||
is_demo: false
|
||||
is_offline: false
|
||||
is_fxplay: false
|
||||
is_enterprise: false
|
||||
is_enterprise: true
|
||||
port: 9999
|
||||
username: admin
|
||||
password: admin123
|
||||
|
||||
@@ -967,6 +967,10 @@ const message = {
|
||||
requestBodySize: 'Request Body Size',
|
||||
requestBodyTruncated: 'Truncated',
|
||||
requestBodyHash: 'Request Body Hash',
|
||||
responseBody: 'Response Body',
|
||||
responseBodySize: 'Response Body Size',
|
||||
responseBodyTruncated: 'Response Body Truncated',
|
||||
responseBodyHash: 'Response Body Hash',
|
||||
statusTitle: 'AI Gateway Status',
|
||||
serviceEnabled: 'Service Auto-start',
|
||||
proxyEnabled: 'Gateway Enabled',
|
||||
@@ -996,6 +1000,8 @@ const message = {
|
||||
inputTokens: 'Input Tokens',
|
||||
outputTokens: 'Output Tokens',
|
||||
totalToken: 'Total Tokens',
|
||||
cachedToken: 'Cached Tokens',
|
||||
cacheHitRate: 'Cache Hit Rate',
|
||||
activeUsers: 'Active Users',
|
||||
activeModels: 'Active Models',
|
||||
failedRequests: 'Failed Requests',
|
||||
|
||||
@@ -982,6 +982,10 @@ const message = {
|
||||
requestBodySize: 'Tamaño del cuerpo de solicitud',
|
||||
requestBodyTruncated: 'Truncado',
|
||||
requestBodyHash: 'Hash del cuerpo de solicitud',
|
||||
responseBody: 'Cuerpo de respuesta',
|
||||
responseBodySize: 'Tamaño del cuerpo de respuesta',
|
||||
responseBodyTruncated: 'Cuerpo de respuesta truncado',
|
||||
responseBodyHash: 'Hash del cuerpo de respuesta',
|
||||
statusTitle: 'Estado del gateway de IA',
|
||||
serviceEnabled: 'Inicio automático del servicio',
|
||||
proxyEnabled: 'Gateway habilitado',
|
||||
@@ -1010,6 +1014,8 @@ const message = {
|
||||
inputTokens: 'Tokens de entrada',
|
||||
outputTokens: 'Tokens de salida',
|
||||
totalToken: 'Tokens totales',
|
||||
cachedToken: 'Tokens en caché',
|
||||
cacheHitRate: 'Tasa de acierto de caché',
|
||||
activeUsers: 'Usuarios activos',
|
||||
activeModels: 'Modelos activos',
|
||||
failedRequests: 'Solicitudes fallidas',
|
||||
|
||||
@@ -972,6 +972,10 @@ const message = {
|
||||
requestBodySize: 'リクエスト本文サイズ',
|
||||
requestBodyTruncated: '切り詰め',
|
||||
requestBodyHash: 'リクエスト本文 Hash',
|
||||
responseBody: 'レスポンス本文',
|
||||
responseBodySize: 'レスポンス本文サイズ',
|
||||
responseBodyTruncated: 'レスポンス本文の切り詰め',
|
||||
responseBodyHash: 'レスポンス本文 Hash',
|
||||
statusTitle: 'AI ゲートウェイ状態',
|
||||
serviceEnabled: 'サービス自動起動',
|
||||
proxyEnabled: 'ゲートウェイ有効',
|
||||
@@ -1000,6 +1004,8 @@ const message = {
|
||||
inputTokens: '入力 Token',
|
||||
outputTokens: '出力 Token',
|
||||
totalToken: '合計 Token',
|
||||
cachedToken: 'キャッシュ Token',
|
||||
cacheHitRate: 'キャッシュヒット率',
|
||||
activeUsers: 'アクティブユーザー',
|
||||
activeModels: 'アクティブモデル',
|
||||
failedRequests: '失敗リクエスト',
|
||||
|
||||
@@ -956,6 +956,10 @@ const message = {
|
||||
requestBodySize: '요청 본문 크기',
|
||||
requestBodyTruncated: '잘림 여부',
|
||||
requestBodyHash: '요청 본문 Hash',
|
||||
responseBody: '응답 본문',
|
||||
responseBodySize: '응답 본문 크기',
|
||||
responseBodyTruncated: '응답 본문 잘림 여부',
|
||||
responseBodyHash: '응답 본문 Hash',
|
||||
statusTitle: 'AI 게이트웨이 상태',
|
||||
serviceEnabled: '서비스 자동 시작',
|
||||
proxyEnabled: '게이트웨이 활성화',
|
||||
@@ -984,6 +988,8 @@ const message = {
|
||||
inputTokens: '입력 Token',
|
||||
outputTokens: '출력 Token',
|
||||
totalToken: '총 Token',
|
||||
cachedToken: '캐시 Token',
|
||||
cacheHitRate: '캐시 적중률',
|
||||
activeUsers: '활성 사용자',
|
||||
activeModels: '활성 모델',
|
||||
failedRequests: '실패한 요청',
|
||||
|
||||
@@ -981,6 +981,10 @@ const message = {
|
||||
requestBodySize: 'Saiz Badan Permintaan',
|
||||
requestBodyTruncated: 'Dipotong',
|
||||
requestBodyHash: 'Hash Badan Permintaan',
|
||||
responseBody: 'Badan Respons',
|
||||
responseBodySize: 'Saiz Badan Respons',
|
||||
responseBodyTruncated: 'Badan Respons Dipotong',
|
||||
responseBodyHash: 'Hash Badan Respons',
|
||||
statusTitle: 'Status gateway AI',
|
||||
serviceEnabled: 'Auto mula perkhidmatan',
|
||||
proxyEnabled: 'Gateway diaktifkan',
|
||||
@@ -1009,6 +1013,8 @@ const message = {
|
||||
inputTokens: 'Token input',
|
||||
outputTokens: 'Token output',
|
||||
totalToken: 'Jumlah Token',
|
||||
cachedToken: 'Token cache',
|
||||
cacheHitRate: 'Kadar hit cache',
|
||||
activeUsers: 'Pengguna aktif',
|
||||
activeModels: 'Model aktif',
|
||||
failedRequests: 'Permintaan gagal',
|
||||
|
||||
@@ -977,6 +977,10 @@ const message = {
|
||||
requestBodySize: 'Tamanho do corpo da requisição',
|
||||
requestBodyTruncated: 'Truncado',
|
||||
requestBodyHash: 'Hash do corpo da requisição',
|
||||
responseBody: 'Corpo da resposta',
|
||||
responseBodySize: 'Tamanho do corpo da resposta',
|
||||
responseBodyTruncated: 'Corpo da resposta truncado',
|
||||
responseBodyHash: 'Hash do corpo da resposta',
|
||||
statusTitle: 'Status do gateway de IA',
|
||||
serviceEnabled: 'Inicialização automática do serviço',
|
||||
proxyEnabled: 'Gateway habilitado',
|
||||
@@ -1005,6 +1009,8 @@ const message = {
|
||||
inputTokens: 'Token de entrada',
|
||||
outputTokens: 'Token de saída',
|
||||
totalToken: 'Total de Token',
|
||||
cachedToken: 'Tokens em cache',
|
||||
cacheHitRate: 'Taxa de acerto do cache',
|
||||
activeUsers: 'Usuários ativos',
|
||||
activeModels: 'Modelos ativos',
|
||||
failedRequests: 'Requisições com falha',
|
||||
|
||||
@@ -971,6 +971,10 @@ const message = {
|
||||
requestBodySize: 'Размер тела запроса',
|
||||
requestBodyTruncated: 'Обрезано',
|
||||
requestBodyHash: 'Hash тела запроса',
|
||||
responseBody: 'Тело ответа',
|
||||
responseBodySize: 'Размер тела ответа',
|
||||
responseBodyTruncated: 'Тело ответа обрезано',
|
||||
responseBodyHash: 'Hash тела ответа',
|
||||
statusTitle: 'Статус AI-шлюза',
|
||||
serviceEnabled: 'Автозапуск сервиса',
|
||||
proxyEnabled: 'Шлюз включен',
|
||||
@@ -999,6 +1003,8 @@ const message = {
|
||||
inputTokens: 'Входные Token',
|
||||
outputTokens: 'Выходные Token',
|
||||
totalToken: 'Всего Token',
|
||||
cachedToken: 'Кэшированные Token',
|
||||
cacheHitRate: 'Попадания в кэш',
|
||||
activeUsers: 'Активные пользователи',
|
||||
activeModels: 'Активные модели',
|
||||
failedRequests: 'Неуспешные запросы',
|
||||
|
||||
@@ -979,6 +979,10 @@ const message = {
|
||||
requestBodySize: 'İstek Gövdesi Boyutu',
|
||||
requestBodyTruncated: 'Kısaltıldı',
|
||||
requestBodyHash: 'İstek Gövdesi Hash',
|
||||
responseBody: 'Yanıt Gövdesi',
|
||||
responseBodySize: 'Yanıt Gövdesi Boyutu',
|
||||
responseBodyTruncated: 'Yanıt Gövdesi Kısaltıldı',
|
||||
responseBodyHash: 'Yanıt Gövdesi Hash',
|
||||
statusTitle: 'AI Ağ Geçidi durumu',
|
||||
serviceEnabled: 'Servis otomatik başlatma',
|
||||
proxyEnabled: 'Ağ geçidi etkin',
|
||||
@@ -1007,6 +1011,8 @@ const message = {
|
||||
inputTokens: 'Girdi Token',
|
||||
outputTokens: 'Çıktı Token',
|
||||
totalToken: 'Toplam Token',
|
||||
cachedToken: 'Önbellek Token',
|
||||
cacheHitRate: 'Önbellek İsabet Oranı',
|
||||
activeUsers: 'Aktif kullanıcılar',
|
||||
activeModels: 'Aktif modeller',
|
||||
failedRequests: 'Başarısız istekler',
|
||||
|
||||
@@ -916,6 +916,10 @@ const message = {
|
||||
requestBodySize: '請求體大小',
|
||||
requestBodyTruncated: '是否截斷',
|
||||
requestBodyHash: '請求體 Hash',
|
||||
responseBody: '響應體',
|
||||
responseBodySize: '響應體大小',
|
||||
responseBodyTruncated: '響應體是否截斷',
|
||||
responseBodyHash: '響應體 Hash',
|
||||
statusTitle: 'AI 閘道狀態',
|
||||
serviceEnabled: '服務自啟',
|
||||
proxyEnabled: '閘道啟用',
|
||||
@@ -944,6 +948,8 @@ const message = {
|
||||
inputTokens: '輸入 Token',
|
||||
outputTokens: '輸出 Token',
|
||||
totalToken: '總 Token',
|
||||
cachedToken: '快取 Token',
|
||||
cacheHitRate: '快取命中率',
|
||||
activeUsers: '活躍使用者',
|
||||
activeModels: '活躍模型',
|
||||
failedRequests: '失敗請求',
|
||||
|
||||
@@ -909,6 +909,10 @@ const message = {
|
||||
requestBodySize: '请求体大小',
|
||||
requestBodyTruncated: '是否截断',
|
||||
requestBodyHash: '请求体 Hash',
|
||||
responseBody: '响应体',
|
||||
responseBodySize: '响应体大小',
|
||||
responseBodyTruncated: '响应体是否截断',
|
||||
responseBodyHash: '响应体 Hash',
|
||||
statusTitle: 'AI 网关状态',
|
||||
serviceEnabled: '服务自启',
|
||||
proxyEnabled: '网关启用',
|
||||
@@ -938,6 +942,8 @@ const message = {
|
||||
inputTokens: '输入 Token',
|
||||
outputTokens: '输出 Token',
|
||||
totalToken: '总 Token',
|
||||
cachedToken: '缓存 Token',
|
||||
cacheHitRate: '缓存命中率',
|
||||
activeUsers: '活跃用户',
|
||||
activeModels: '活跃模型',
|
||||
failedRequests: '失败请求',
|
||||
|
||||
Reference in New Issue
Block a user