mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-10-09 16:00:29 +00:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d674f14ad | ||
|
|
b772effacd | ||
|
|
2417cc9eed | ||
|
|
c0796dc7c4 | ||
|
|
ff9747560e | ||
|
|
9c2828385b | ||
|
|
ad5df58d0f | ||
|
|
bb5e0f98c2 | ||
|
|
bfa2eb43ea | ||
|
|
be27983938 | ||
|
|
7ff1819799 | ||
|
|
7ff39c91da |
@@ -14,6 +14,8 @@ type TensorRTLLMCreate struct {
|
||||
ModelDir string `json:"modelDir" validate:"required"`
|
||||
Image string `json:"image" validate:"required"`
|
||||
Command string `json:"command" validate:"required"`
|
||||
ModelType string `json:"modelType"`
|
||||
ModelSpeedup bool `json:"modelSpeedup"`
|
||||
DockerConfig
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ type Cronjob struct {
|
||||
EntryIDs string `json:"entryIDs"`
|
||||
Records []JobRecords `json:"records"`
|
||||
Secret string `json:"secret"`
|
||||
|
||||
Config string `json:"config"`
|
||||
}
|
||||
|
||||
type JobRecords struct {
|
||||
|
||||
@@ -2,14 +2,18 @@ package model
|
||||
|
||||
type MonitorBase struct {
|
||||
BaseModel
|
||||
Cpu float64 `json:"cpu"`
|
||||
Cpu float64 `json:"cpu"`
|
||||
TopCPU string `json:"topCPU"`
|
||||
TopCPUItems interface{} `gorm:"-" json:"topCPUItems"`
|
||||
|
||||
Memory float64 `json:"memory"`
|
||||
TopMem string `json:"topMem"`
|
||||
TopMemItems interface{} `gorm:"-" json:"topMemItems"`
|
||||
|
||||
LoadUsage float64 `json:"loadUsage"`
|
||||
CpuLoad1 float64 `json:"cpuLoad1"`
|
||||
CpuLoad5 float64 `json:"cpuLoad5"`
|
||||
CpuLoad15 float64 `json:"cpuLoad15"`
|
||||
|
||||
Memory float64 `json:"memory"`
|
||||
}
|
||||
|
||||
type MonitorIO struct {
|
||||
|
||||
@@ -6,8 +6,9 @@ type TensorRTLLM struct {
|
||||
DockerCompose string `json:"dockerCompose"`
|
||||
ContainerName string `json:"containerName"`
|
||||
Message string `json:"message"`
|
||||
//Port int `json:"port"`
|
||||
Status string `json:"status"`
|
||||
Env string `json:"env"`
|
||||
TaskID string `json:"taskID"`
|
||||
Status string `json:"status"`
|
||||
Env string `json:"env"`
|
||||
TaskID string `json:"taskID"`
|
||||
ModelType string `json:"modelType"`
|
||||
ModelSpeedup bool `json:"modelSpeedup"`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/request"
|
||||
"github.com/1Panel-dev/1Panel/agent/app/dto/response"
|
||||
@@ -12,10 +13,13 @@ import (
|
||||
"github.com/1Panel-dev/1Panel/agent/global"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/compose"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/docker"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/env"
|
||||
"github.com/1Panel-dev/1Panel/agent/utils/files"
|
||||
"github.com/subosito/gotenv"
|
||||
"gopkg.in/yaml.v3"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -52,7 +56,7 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR
|
||||
serverDTO.ModelDir = envs["MODEL_PATH"]
|
||||
serverDTO.Dir = path.Join(global.Dir.TensorRTLLMDir, item.Name)
|
||||
serverDTO.Image = envs["IMAGE"]
|
||||
serverDTO.Command = envs["COMMAND"]
|
||||
serverDTO.Command = getCommand(item.Env)
|
||||
|
||||
for k, v := range envs {
|
||||
if strings.Contains(k, "CONTAINER_PORT") || strings.Contains(k, "HOST_PORT") {
|
||||
@@ -81,31 +85,25 @@ func (t TensorRTLLMService) Page(req request.TensorRTLLMSearch) response.TensorR
|
||||
}
|
||||
|
||||
composeByte, err := files.NewFileOp().GetContent(path.Join(global.Dir.TensorRTLLMDir, item.Name, "docker-compose.yml"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
serverDTO.Environments, err = getDockerComposeEnvironments(composeByte)
|
||||
if err != nil {
|
||||
continue
|
||||
if err == nil {
|
||||
serverDTO.Environments, _ = getDockerComposeEnvironments(composeByte)
|
||||
}
|
||||
volumes, err := getDockerComposeVolumes(composeByte)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var defaultVolumes = map[string]string{
|
||||
"${MODEL_PATH}": "/models",
|
||||
}
|
||||
for _, volume := range volumes {
|
||||
exist := false
|
||||
for key, value := range defaultVolumes {
|
||||
if key == volume.Source && value == volume.Target {
|
||||
exist = true
|
||||
break
|
||||
}
|
||||
if err == nil {
|
||||
var defaultVolumes = map[string]string{
|
||||
"${MODEL_PATH}": "${MODEL_PATH}",
|
||||
}
|
||||
if !exist {
|
||||
serverDTO.Volumes = append(serverDTO.Volumes, volume)
|
||||
for _, volume := range volumes {
|
||||
exist := false
|
||||
for key, value := range defaultVolumes {
|
||||
if key == volume.Source && value == volume.Target {
|
||||
exist = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !exist {
|
||||
serverDTO.Volumes = append(serverDTO.Volumes, volume)
|
||||
}
|
||||
}
|
||||
}
|
||||
items = append(items, serverDTO)
|
||||
@@ -159,16 +157,15 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e
|
||||
|
||||
delete(serviceValue, "environment")
|
||||
var environments []interface{}
|
||||
environments = append(environments, fmt.Sprintf("MODEL_PATH=%s", create.ModelDir))
|
||||
for _, e := range create.Environments {
|
||||
environments = append(environments, fmt.Sprintf("%s=%s", e.Key, e.Value))
|
||||
}
|
||||
if len(environments) > 0 {
|
||||
serviceValue["environment"] = environments
|
||||
}
|
||||
serviceValue["environment"] = environments
|
||||
|
||||
var volumes []interface{}
|
||||
var defaultVolumes = map[string]string{
|
||||
"${MODEL_PATH}": "/models",
|
||||
"${MODEL_PATH}": "${MODEL_PATH}",
|
||||
}
|
||||
for k, v := range defaultVolumes {
|
||||
volumes = append(volumes, fmt.Sprintf("%s:%s", k, v))
|
||||
@@ -188,23 +185,24 @@ func handleLLMParams(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) e
|
||||
}
|
||||
|
||||
func handleLLMEnv(llm *model.TensorRTLLM, create request.TensorRTLLMCreate) gotenv.Env {
|
||||
env := make(gotenv.Env)
|
||||
env["CONTAINER_NAME"] = create.ContainerName
|
||||
env["MODEL_PATH"] = create.ModelDir
|
||||
env["VERSION"] = create.Version
|
||||
env["IMAGE"] = create.Image
|
||||
env["COMMAND"] = create.Command
|
||||
envMap := make(gotenv.Env)
|
||||
envMap["CONTAINER_NAME"] = create.ContainerName
|
||||
envMap["MODEL_PATH"] = create.ModelDir
|
||||
envMap["VERSION"] = create.Version
|
||||
envMap["IMAGE"] = create.Image
|
||||
envMap["COMMAND"] = create.Command
|
||||
for i, port := range create.ExposedPorts {
|
||||
containerPortStr := fmt.Sprintf("CONTAINER_PORT_%d", i)
|
||||
hostPortStr := fmt.Sprintf("HOST_PORT_%d", i)
|
||||
hostIPStr := fmt.Sprintf("HOST_IP_%d", i)
|
||||
env[containerPortStr] = strconv.Itoa(port.ContainerPort)
|
||||
env[hostPortStr] = strconv.Itoa(port.HostPort)
|
||||
env[hostIPStr] = port.HostIP
|
||||
envMap[containerPortStr] = strconv.Itoa(port.ContainerPort)
|
||||
envMap[hostPortStr] = strconv.Itoa(port.HostPort)
|
||||
envMap[hostIPStr] = port.HostIP
|
||||
}
|
||||
envStr, _ := gotenv.Marshal(env)
|
||||
orders := []string{"MODEL_PATH", "COMMAND"}
|
||||
envStr, _ := env.MarshalWithOrder(envMap, orders)
|
||||
llm.Env = envStr
|
||||
return env
|
||||
return envMap
|
||||
}
|
||||
|
||||
func (t TensorRTLLMService) Create(create request.TensorRTLLMCreate) error {
|
||||
@@ -227,27 +225,34 @@ func (t TensorRTLLMService) Create(create request.TensorRTLLMCreate) error {
|
||||
}
|
||||
|
||||
tensorrtLLMDir := path.Join(global.Dir.TensorRTLLMDir, create.Name)
|
||||
filesOP := files.NewFileOp()
|
||||
if !filesOP.Stat(tensorrtLLMDir) {
|
||||
_ = filesOP.CreateDir(tensorrtLLMDir, 0644)
|
||||
filesOp := files.NewFileOp()
|
||||
if !filesOp.Stat(tensorrtLLMDir) {
|
||||
_ = filesOp.CreateDir(tensorrtLLMDir, 0644)
|
||||
}
|
||||
if create.ModelSpeedup {
|
||||
if err := handleModelArchive(create.ModelType, create.ModelDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
tensorrtLLM := &model.TensorRTLLM{
|
||||
Name: create.Name,
|
||||
ContainerName: create.ContainerName,
|
||||
Status: constant.StatusStarting,
|
||||
ModelType: create.ModelType,
|
||||
ModelSpeedup: create.ModelSpeedup,
|
||||
}
|
||||
|
||||
if err := handleLLMParams(tensorrtLLM, create); err != nil {
|
||||
return err
|
||||
}
|
||||
env := handleLLMEnv(tensorrtLLM, create)
|
||||
envMap := handleLLMEnv(tensorrtLLM, create)
|
||||
llmDir := path.Join(global.Dir.TensorRTLLMDir, create.Name)
|
||||
envPath := path.Join(llmDir, ".env")
|
||||
if err := gotenv.Write(env, envPath); err != nil {
|
||||
if err := env.WriteWithOrder(envMap, envPath, []string{"MODEL_PATH", "COMMAND"}); err != nil {
|
||||
return err
|
||||
}
|
||||
dockerComposePath := path.Join(llmDir, "docker-compose.yml")
|
||||
if err := filesOP.SaveFile(dockerComposePath, tensorrtLLM.DockerCompose, 0644); err != nil {
|
||||
if err := filesOp.SaveFile(dockerComposePath, tensorrtLLM.DockerCompose, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
tensorrtLLM.Status = constant.StatusStarting
|
||||
@@ -269,18 +274,20 @@ func (t TensorRTLLMService) Update(req request.TensorRTLLMUpdate) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
tensorrtLLM.ModelType = req.ModelType
|
||||
tensorrtLLM.ModelSpeedup = req.ModelSpeedup
|
||||
tensorrtLLM.ContainerName = req.ContainerName
|
||||
|
||||
if err := handleLLMParams(tensorrtLLM, req.TensorRTLLMCreate); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
env := handleLLMEnv(tensorrtLLM, req.TensorRTLLMCreate)
|
||||
envStr, _ := gotenv.Marshal(env)
|
||||
envMap := handleLLMEnv(tensorrtLLM, req.TensorRTLLMCreate)
|
||||
envStr, _ := gotenv.Marshal(envMap)
|
||||
tensorrtLLM.Env = envStr
|
||||
llmDir := path.Join(global.Dir.TensorRTLLMDir, tensorrtLLM.Name)
|
||||
envPath := path.Join(llmDir, ".env")
|
||||
if err := gotenv.Write(env, envPath); err != nil {
|
||||
if err := env.WriteWithOrder(envMap, envPath, []string{"MODEL_PATH", "COMMAND"}); err != nil {
|
||||
return err
|
||||
}
|
||||
dockerComposePath := path.Join(llmDir, "docker-compose.yml")
|
||||
@@ -381,3 +388,51 @@ func syncTensorRTLLMContainerStatus(tensorrtLLM *model.TensorRTLLM) error {
|
||||
}
|
||||
return tensorrtLLMRepo.Save(tensorrtLLM)
|
||||
}
|
||||
|
||||
func findModelArchive(modelType string) (string, error) {
|
||||
const baseDir = "/home/models"
|
||||
prefix := fmt.Sprintf("FusionXplay_%s_Accelerator", modelType)
|
||||
|
||||
entries, err := os.ReadDir(baseDir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read %s: %w", baseDir, err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
name := entry.Name()
|
||||
if strings.HasPrefix(name, prefix) && strings.HasSuffix(name, ".tar.gz") {
|
||||
return filepath.Join(baseDir, name), nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New(fmt.Sprintf("no FusionXplay_%s_Accelerator*.tar.gz found in /home/models", modelType))
|
||||
}
|
||||
|
||||
func handleModelArchive(modelType string, modelDir string) error {
|
||||
filePath, err := findModelArchive(modelType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fileOp := files.NewFileOp()
|
||||
if err = fileOp.TarGzExtractPro(filePath, modelDir, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = fileOp.ChmodR(path.Join(modelDir, "fusionxpark_accelerator"), 0755, false); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getCommand(envStr string) string {
|
||||
lines := strings.Split(envStr, "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "COMMAND=") {
|
||||
return strings.TrimPrefix(line, "COMMAND=")
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ services:
|
||||
networks:
|
||||
- 1panel-network
|
||||
volumes:
|
||||
- ${MODEL_PATH}:/models
|
||||
- ${MODEL_PATH}:${MODEL_PATH}
|
||||
ipc: host
|
||||
ulimits:
|
||||
memlock:
|
||||
|
||||
@@ -47,6 +47,10 @@ func InitAgentDB() {
|
||||
migrations.UpdateCronjobSpec,
|
||||
migrations.UpdateWebsiteSSLAddColumn,
|
||||
migrations.AddTensorRTLLMModel,
|
||||
migrations.UpdateMonitorInterval,
|
||||
migrations.AddMonitorProcess,
|
||||
migrations.UpdateCronJob,
|
||||
migrations.UpdateTensorrtLLM,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -634,3 +635,48 @@ var AddTensorRTLLMModel = &gormigrate.Migration{
|
||||
return tx.AutoMigrate(&model.TensorRTLLM{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateMonitorInterval = &gormigrate.Migration{
|
||||
ID: "20251026-update-monitor-interval",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
var monitorInterval model.Setting
|
||||
if err := tx.Where("key = ?", "MonitorInterval").First(&monitorInterval).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
interval, _ := strconv.Atoi(monitorInterval.Value)
|
||||
if interval == 0 {
|
||||
interval = 300
|
||||
}
|
||||
if err := tx.Model(&model.Setting{}).
|
||||
Where("key = ?", "MonitorInterval").
|
||||
Updates(map[string]interface{}{"value": fmt.Sprintf("%v", interval*60)}).
|
||||
Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Create(&model.Setting{Key: "DefaultIO", Value: "all"}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddMonitorProcess = &gormigrate.Migration{
|
||||
ID: "20251202-add-monitor-process",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return global.MonitorDB.AutoMigrate(&model.MonitorBase{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateCronJob = &gormigrate.Migration{
|
||||
ID: "20251202-update-cronjob",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.Cronjob{})
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateTensorrtLLM = &gormigrate.Migration{
|
||||
ID: "20251110-update-tensorrt-llm",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
return tx.AutoMigrate(&model.TensorRTLLM{})
|
||||
},
|
||||
}
|
||||
|
||||
Vendored
+57
-3
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func Write(envMap map[string]string, filename string) error {
|
||||
content, err := marshal(envMap)
|
||||
content, err := Marshal(envMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -26,7 +26,7 @@ func Write(envMap map[string]string, filename string) error {
|
||||
return file.Sync()
|
||||
}
|
||||
|
||||
func marshal(envMap map[string]string) (string, error) {
|
||||
func Marshal(envMap map[string]string) (string, error) {
|
||||
lines := make([]string, 0, len(envMap))
|
||||
for k, v := range envMap {
|
||||
if d, err := strconv.Atoi(v); err == nil && !isStartWithZero(v) {
|
||||
@@ -37,10 +37,64 @@ func marshal(envMap map[string]string) (string, error) {
|
||||
lines = append(lines, fmt.Sprintf(`%s="%s"`, k, v))
|
||||
}
|
||||
}
|
||||
sort.Strings(lines)
|
||||
return strings.Join(lines, "\n"), nil
|
||||
}
|
||||
|
||||
func WriteWithOrder(envMap map[string]string, filename string, orders []string) error {
|
||||
content, err := MarshalWithOrder(envMap, orders)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
_, err = file.WriteString(content + "\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return file.Sync()
|
||||
}
|
||||
|
||||
func MarshalWithOrder(envMap map[string]string, orders []string) (string, error) {
|
||||
lines := make([]string, 0, len(envMap))
|
||||
for _, k := range orders {
|
||||
if v, ok := envMap[k]; ok {
|
||||
lines = append(lines, formatEnvLine(k, v))
|
||||
}
|
||||
}
|
||||
|
||||
extraKeys := make([]string, 0)
|
||||
for k := range envMap {
|
||||
found := false
|
||||
for _, okk := range orders {
|
||||
if k == okk {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
extraKeys = append(extraKeys, k)
|
||||
}
|
||||
}
|
||||
sort.Strings(extraKeys)
|
||||
for _, k := range extraKeys {
|
||||
lines = append(lines, formatEnvLine(k, envMap[k]))
|
||||
}
|
||||
return strings.Join(lines, "\n"), nil
|
||||
}
|
||||
|
||||
func formatEnvLine(k, v string) string {
|
||||
if d, err := strconv.Atoi(v); err == nil && !isStartWithZero(v) {
|
||||
return fmt.Sprintf(`%s=%d`, k, d)
|
||||
} else if hasEvenDoubleQuotes(v) {
|
||||
return fmt.Sprintf(`%s='%s'`, k, v)
|
||||
} else {
|
||||
return fmt.Sprintf(`%s="%s"`, k, v)
|
||||
}
|
||||
}
|
||||
|
||||
func GetEnvValueByKey(envPath, key string) (string, error) {
|
||||
envMap, err := godotenv.Read(envPath)
|
||||
if err != nil {
|
||||
|
||||
+3
-3
@@ -17,11 +17,11 @@ download_resources() {
|
||||
fi
|
||||
|
||||
if [ ! -f "1panel-core.service" ]; then
|
||||
wget https://github.com/1Panel-dev/installer/raw/v2/1panel-core.service
|
||||
wget https://github.com/1Panel-dev/installer/raw/v2/initscript/1panel-core.service
|
||||
fi
|
||||
|
||||
if [ ! -f "1panel-agent.service" ]; then
|
||||
wget https://github.com/1Panel-dev/installer/raw/v2/1panel-agent.service
|
||||
wget https://github.com/1Panel-dev/installer/raw/v2/initscript/1panel-agent.service
|
||||
fi
|
||||
|
||||
if [ ! -d "lang" ]; then
|
||||
@@ -68,4 +68,4 @@ if [ "$1" = "compress_binary" ]; then
|
||||
compress_binary "$2" "$3"
|
||||
else
|
||||
download_resources
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -2,6 +2,8 @@ package v2
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||
"github.com/1Panel-dev/1Panel/core/app/dto"
|
||||
@@ -125,6 +127,20 @@ func (b *BaseApi) GetResponsePage(c *gin.Context) {
|
||||
helper.SuccessWithData(c, pageCode)
|
||||
}
|
||||
|
||||
func (b *BaseApi) GetWelcomePage(c *gin.Context) {
|
||||
count, _, _ := logService.PageLoginLog(c, dto.SearchLgLogWithPage{PageInfo: dto.PageInfo{Page: 1, PageSize: 10}})
|
||||
if count != 1 {
|
||||
helper.Success(c)
|
||||
return
|
||||
}
|
||||
file, err := os.ReadFile(path.Join(global.CONF.Base.InstallDir, "1panel/welcome/index.html"))
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
helper.SuccessWithData(c, string(file))
|
||||
}
|
||||
|
||||
// @Tags Auth
|
||||
// @Summary Get Setting For Login
|
||||
// @Success 200 {object} dto.SystemSetting
|
||||
|
||||
@@ -16,5 +16,6 @@ func (s *BaseRouter) InitRouter(Router *gin.RouterGroup) {
|
||||
baseRouter.POST("/login", baseApi.Login)
|
||||
baseRouter.POST("/logout", baseApi.LogOut)
|
||||
baseRouter.GET("/setting", baseApi.GetLoginSetting)
|
||||
baseRouter.GET("/welcome", baseApi.GetWelcomePage)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/init/db"
|
||||
"github.com/1Panel-dev/1Panel/core/init/geo"
|
||||
@@ -56,8 +57,12 @@ func Start() {
|
||||
global.CONF.Conn.BindAddress = fmt.Sprintf("[%s]", global.CONF.Conn.BindAddress)
|
||||
}
|
||||
server := &http.Server{
|
||||
Addr: global.CONF.Conn.BindAddress + ":" + global.CONF.Conn.Port,
|
||||
Handler: rootRouter,
|
||||
Addr: global.CONF.Conn.BindAddress + ":" + global.CONF.Conn.Port,
|
||||
Handler: rootRouter,
|
||||
ReadHeaderTimeout: 5 * time.Second,
|
||||
ReadTimeout: 600 * time.Second,
|
||||
WriteTimeout: 600 * time.Second,
|
||||
IdleTimeout: 240 * time.Second,
|
||||
}
|
||||
ln, err := net.Listen(tcpItem, server.Addr)
|
||||
if err != nil {
|
||||
|
||||
@@ -20,3 +20,7 @@ export const logOutApi = () => {
|
||||
export const getLoginSetting = () => {
|
||||
return http.get<Login.LoginSetting>('/core/auth/setting');
|
||||
};
|
||||
|
||||
export const getWelcomePage = () => {
|
||||
return http.get<string>('/core/auth/welcome');
|
||||
};
|
||||
|
||||
@@ -109,7 +109,7 @@ const mobile = computed(() => {
|
||||
return globalStore.isMobile();
|
||||
});
|
||||
const tableRef = ref();
|
||||
const tableHeight = ref(0);
|
||||
const tableHeight = ref<number | string>('');
|
||||
const menuRef = ref<HTMLElement | null>(null);
|
||||
const leftSelect = ref(false);
|
||||
|
||||
|
||||
@@ -728,9 +728,11 @@ const message = {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: 'Model Directory',
|
||||
commandHelper:
|
||||
'After /models in the startup command, the model name needs to be completed; if external access is required, set the port in the command to be the same as the application port',
|
||||
'If external access is needed, set the port in the command to be the same as the application port',
|
||||
imageAlert:
|
||||
'Due to the large image size, it is recommended to manually download the image to the server before installation',
|
||||
modelSpeedup: 'Enable model acceleration',
|
||||
modelType: 'Model type',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -729,9 +729,11 @@ const message = {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: 'Directorio del Modelo',
|
||||
commandHelper:
|
||||
'Después de /models en el comando de inicio, se debe completar el nombre del modelo; si se requiere acceso externo, configure el puerto en el comando para que sea el mismo que el puerto de la aplicación',
|
||||
'Si se necesita acceso externo, establezca el puerto en el comando para que sea el mismo que el puerto de la aplicación',
|
||||
imageAlert:
|
||||
'Debido al gran tamaño de la imagen, se recomienda descargar manualmente la imagen al servidor antes de la instalación',
|
||||
modelSpeedup: 'Habilitar aceleración de modelo',
|
||||
modelType: 'Tipo de modelo',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -716,9 +716,11 @@ const message = {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: 'モデルディレクトリ',
|
||||
commandHelper:
|
||||
'起動コマンドの /models の後にはモデル名を補完する必要があります;外部アクセスが必要な場合は、コマンド内のポートをアプリケーションポートと同じに設定してください',
|
||||
'外部アクセスが必要な場合は、コマンド内のポートをアプリケーションポートと同じに設定してください',
|
||||
imageAlert:
|
||||
'イメージサイズが大きいため、インストール前にサーバーにイメージを手動でダウンロードすることをお勧めします',
|
||||
modelSpeedup: 'モデル加速を有効化',
|
||||
modelType: 'モデルタイプ',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -711,9 +711,10 @@ const message = {
|
||||
tensorRT: {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: '모델 디렉토리',
|
||||
commandHelper:
|
||||
'시작 명령의 /models 뒤에는 모델 이름을 완성해야 합니다; 외부 액세스가 필요한 경우 명령의 포트를 애플리케이션 포트와 동일하게 설정하세요',
|
||||
commandHelper: '외부 액세스가 필요한 경우 명령에서 포트를 애플리케이션 포트와 동일하게 설정하십시오',
|
||||
imageAlert: '이미지 크기가 크므로 설치 전에 서버에 이미지를 수동으로 다운로드하는 것이 좋습니다',
|
||||
modelSpeedup: '모델 가속 활성화',
|
||||
modelType: '모델 유형',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -728,10 +728,11 @@ const message = {
|
||||
tensorRT: {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: 'Direktori Model',
|
||||
commandHelper:
|
||||
'Selepas /models dalam arahan permulaan, nama model perlu dilengkapkan; jika akses luar diperlukan, tetapkan port dalam arahan sama dengan port aplikasi',
|
||||
commandHelper: 'Jika akses luar diperlukan, tetapkan port dalam arahan sama dengan port aplikasi',
|
||||
imageAlert:
|
||||
'Disebabkan saiz imej yang besar, disyorkan untuk memuat turun imej secara manual ke pelayan sebelum pemasangan',
|
||||
modelSpeedup: 'Dayakan pecutan model',
|
||||
modelType: 'Jenis model',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -725,9 +725,11 @@ const message = {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: 'Diretório do Modelo',
|
||||
commandHelper:
|
||||
'Após /models no comando de inicialização, o nome do modelo precisa ser completado; se for necessário acesso externo, defina a porta no comando para ser a mesma que a porta do aplicativo',
|
||||
'Se for necessário acesso externo, defina a porta no comando para ser a mesma que a porta do aplicativo',
|
||||
imageAlert:
|
||||
'Devido ao grande tamanho da imagem, recomenda-se baixar manualmente a imagem para o servidor antes da instalação',
|
||||
modelSpeedup: 'Ativar aceleração de modelo',
|
||||
modelType: 'Tipo de modelo',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -722,10 +722,11 @@ const message = {
|
||||
tensorRT: {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: 'Каталог модели',
|
||||
commandHelper:
|
||||
'После /models в команде запуска необходимо указать имя модели; если требуется внешний доступ, установите порт в команде таким же, как порт приложения',
|
||||
commandHelper: 'Если требуется внешний доступ, установите порт в команде таким же, как порт приложения',
|
||||
imageAlert:
|
||||
'Из-за большого размера образа рекомендуется вручную загрузить образ на сервер перед установкой',
|
||||
modelSpeedup: 'Включить ускорение модели',
|
||||
modelType: 'Тип модели',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -737,9 +737,11 @@ const message = {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: 'Model Dizini',
|
||||
commandHelper:
|
||||
'Başlatma komutundaki /models sonrasında model adı tamamlanmalıdır; harici erişim gerekiyorsa, komuttaki bağlantı noktasını uygulama bağlantı noktasıyla aynı olacak şekilde ayarlayın',
|
||||
'Harici erişim gerekiyorsa, komuttaki bağlantı noktasını uygulama bağlantı noktasıyla aynı olacak şekilde ayarlayın',
|
||||
imageAlert:
|
||||
'Görüntü boyutu büyük olduğundan, kurulumdan önce görüntüyü sunucuya manuel olarak indirmeniz önerilir',
|
||||
modelSpeedup: 'Model hızlandırmayı etkinleştir',
|
||||
modelType: 'Model türü',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -700,8 +700,10 @@ const message = {
|
||||
tensorRT: {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: '模型目錄',
|
||||
commandHelper: '啟動指令中的 /models 後需補全模型名稱;若需外部訪問,請將指令中的埠設定為與應用埠相同',
|
||||
commandHelper: '若需外部訪問,請將命令中的端口設置為與應用端口相同',
|
||||
imageAlert: '由於鏡像較大,建議先手動將鏡像下載到伺服器後再進行安裝',
|
||||
modelSpeedup: '啟用模型加速',
|
||||
modelType: '模型類型',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -700,8 +700,10 @@ const message = {
|
||||
tensorRT: {
|
||||
llm: 'TensorRT LLM',
|
||||
modelDir: '模型目录',
|
||||
commandHelper: '启动命令中的 /models 后需补全模型名称;若需外部访问,请将命令中的端口设置为与应用端口相同',
|
||||
commandHelper: '若需外部访问,请将命令中的端口设置为与应用端口相同',
|
||||
imageAlert: '由于镜像较大,建议先手动将镜像下载到服务器后再进行安装',
|
||||
modelSpeedup: '启用模型加速',
|
||||
modelType: '模型类型',
|
||||
},
|
||||
},
|
||||
container: {
|
||||
|
||||
@@ -192,7 +192,7 @@ const buttons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.start'),
|
||||
disabled: (row: AI.TensorRTLLM) => {
|
||||
return row.status === 'running';
|
||||
return row.status === 'Running';
|
||||
},
|
||||
click: (row: AI.TensorRTLLM) => {
|
||||
operate(row, 'start');
|
||||
@@ -201,7 +201,7 @@ const buttons = [
|
||||
{
|
||||
label: i18n.global.t('commons.button.stop'),
|
||||
disabled: (row: AI.TensorRTLLM) => {
|
||||
return row.status !== 'running';
|
||||
return row.status !== 'Running';
|
||||
},
|
||||
click: (row: AI.TensorRTLLM) => {
|
||||
operate(row, 'stop');
|
||||
@@ -209,9 +209,6 @@ const buttons = [
|
||||
},
|
||||
{
|
||||
label: i18n.global.t('commons.button.restart'),
|
||||
disabled: (row: AI.TensorRTLLM) => {
|
||||
return row.status !== 'running';
|
||||
},
|
||||
click: (row: AI.TensorRTLLM) => {
|
||||
operate(row, 'restart');
|
||||
},
|
||||
|
||||
@@ -14,6 +14,20 @@
|
||||
<el-form-item :label="$t('app.version')" prop="version">
|
||||
<el-input v-model.trim="tensorRTLLM.version" />
|
||||
</el-form-item>
|
||||
<div v-if="isFxplay">
|
||||
<el-form-item :label="$t('aiTools.tensorRT.modelSpeedup')" prop="modelSpeedup">
|
||||
<el-switch v-model="tensorRTLLM.modelSpeedup" @change="changeModelSpeedup"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('aiTools.tensorRT.modelType')"
|
||||
prop="modelType"
|
||||
v-if="tensorRTLLM.modelSpeedup"
|
||||
>
|
||||
<el-select v-model="tensorRTLLM.modelType">
|
||||
<el-option label="Qwen3" value="Qwen3" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<el-form-item :label="$t('aiTools.tensorRT.modelDir')" prop="modelDir">
|
||||
<el-input v-model="tensorRTLLM.modelDir">
|
||||
<template #prepend>
|
||||
@@ -62,6 +76,8 @@ import i18n from '@/lang';
|
||||
import { ElForm, FormInstance } from 'element-plus';
|
||||
import { createTensorRTLLM, updateTensorRTLLM } from '@/api/modules/ai';
|
||||
import { MsgSuccess } from '@/utils/message';
|
||||
import { useGlobalStore } from '@/composables/useGlobalStore';
|
||||
const { isFxplay } = useGlobalStore();
|
||||
|
||||
const loading = ref(false);
|
||||
const mode = ref('create');
|
||||
@@ -73,10 +89,12 @@ const newTensorRTLLM = () => {
|
||||
version: '1.2.0rc0',
|
||||
modelDir: '',
|
||||
image: 'nvcr.io/nvidia/tensorrt-llm/release',
|
||||
command: 'bash -c "trtllm-serve /models/ --host 0.0.0.0 --port 8000"',
|
||||
command: 'bash -c "trtllm-serve ${MODEL_PATH} --host 0.0.0.0 --port 8000"',
|
||||
exposedPorts: [],
|
||||
environments: [],
|
||||
volumes: [],
|
||||
modelSpeedup: false,
|
||||
modelType: 'Qwen3',
|
||||
};
|
||||
};
|
||||
const modelDirRef = ref();
|
||||
@@ -101,6 +119,7 @@ const openEdit = (rowData: any): void => {
|
||||
if (tensorRTLLM.value.exposedPorts == null) {
|
||||
tensorRTLLM.value.exposedPorts = [];
|
||||
}
|
||||
tensorRTLLM.value.command = rowData.command.slice(1, -1).replace(/^'|'$/g, '').replace(/\\"/g, '"');
|
||||
drawerVisiable.value = true;
|
||||
};
|
||||
|
||||
@@ -112,6 +131,15 @@ const getModelDir = (path: string) => {
|
||||
tensorRTLLM.value.modelDir = path;
|
||||
};
|
||||
|
||||
const changeModelSpeedup = () => {
|
||||
if (tensorRTLLM.value.modelSpeedup) {
|
||||
tensorRTLLM.value.command =
|
||||
'bash -c "${MODEL_PATH}/fusionxpark_accelerator --model_path ${MODEL_PATH} --host 0.0.0.0 --port 8000"';
|
||||
} else {
|
||||
tensorRTLLM.value.command = 'bash -c "trtllm-serve ${MODEL_PATH} --host 0.0.0.0 --port 8000"';
|
||||
}
|
||||
};
|
||||
|
||||
const rules = reactive({
|
||||
name: [Rules.requiredInput],
|
||||
version: [Rules.requiredInput],
|
||||
@@ -119,6 +147,7 @@ const rules = reactive({
|
||||
containerName: [Rules.requiredInput],
|
||||
image: [Rules.requiredInput],
|
||||
command: [Rules.requiredInput],
|
||||
modelType: [Rules.requiredSelect],
|
||||
});
|
||||
|
||||
const formRef = ref<FormInstance>();
|
||||
|
||||
@@ -302,6 +302,10 @@
|
||||
|
||||
<LicenseImport ref="licenseRef" />
|
||||
<QuickJump @search="onLoadBaseInfo(false, 'all')" ref="quickJumpRef" />
|
||||
|
||||
<DialogPro v-model="welcomeOpen" size="w-70" id="welcomeDialog">
|
||||
<div ref="shadowContainer" />
|
||||
</DialogPro>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -323,6 +327,7 @@ import { getSettingInfo, listAllSimpleNodes, loadUpgradeInfo } from '@/api/modul
|
||||
import { GlobalStore } from '@/store';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { routerToFileWithPath, routerToPath } from '@/utils/router';
|
||||
import { getWelcomePage } from '@/api/modules/auth';
|
||||
const router = useRouter();
|
||||
const globalStore = GlobalStore();
|
||||
|
||||
@@ -331,6 +336,9 @@ const appRef = ref();
|
||||
|
||||
const isSafety = ref();
|
||||
|
||||
const welcomeOpen = ref();
|
||||
const shadowContainer = ref();
|
||||
|
||||
const chartOption = ref('network');
|
||||
let timer: NodeJS.Timer | null = null;
|
||||
let isInit = ref<boolean>(true);
|
||||
@@ -692,6 +700,21 @@ const fetchData = () => {
|
||||
onLoadSimpleNode();
|
||||
};
|
||||
|
||||
const loadWelcome = async () => {
|
||||
await getWelcomePage().then((res) => {
|
||||
if (res.data) {
|
||||
welcomeOpen.value = true;
|
||||
nextTick(() => {
|
||||
const shadowRoot = shadowContainer.value.attachShadow({ mode: 'open' });
|
||||
shadowRoot.innerHTML = res.data;
|
||||
});
|
||||
localStorage.setItem('welcomeShow', 'false');
|
||||
} else {
|
||||
localStorage.setItem('welcomeShow', 'false');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
onBeforeRouteUpdate((to, from, next) => {
|
||||
if (to.name === 'home') {
|
||||
clearTimer();
|
||||
@@ -707,6 +730,9 @@ const clearTimer = () => {
|
||||
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
if (localStorage.getItem('welcomeShow') !== 'false') {
|
||||
loadWelcome();
|
||||
}
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane :label="$t('commons.table.port')">
|
||||
<PortConfig :exposedPorts="runtime.exposedPorts" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('runtime.environment')">
|
||||
<Environment :environments="runtime.environments" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('container.mount')">
|
||||
<Volumes :volumes="runtime.volumes" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('runtime.extraHosts')">
|
||||
<ExtraHosts :extraHosts="runtime.extraHosts" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import PortConfig from '@/views/website/runtime/components/port/index.vue';
|
||||
import Environment from '@/views/website/runtime/components/environment/index.vue';
|
||||
import Volumes from '@/views/website/runtime/components/volume/index.vue';
|
||||
import ExtraHosts from '@/views/website/runtime/components/extra_hosts/index.vue';
|
||||
import { useVModel } from '@vueuse/core';
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
interface RuntimeConfigFields {
|
||||
exposedPorts: any[];
|
||||
environments: any[];
|
||||
volumes: any[];
|
||||
extraHosts: any[];
|
||||
}
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: Object as PropType<RuntimeConfigFields>,
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: RuntimeConfigFields];
|
||||
}>();
|
||||
|
||||
const runtime = useVModel(props, 'modelValue', emit);
|
||||
</script>
|
||||
Reference in New Issue
Block a user