diff --git a/agent/app/dto/agents.go b/agent/app/dto/agents.go
index 5cac7ece8..a218c8618 100644
--- a/agent/app/dto/agents.go
+++ b/agent/app/dto/agents.go
@@ -318,6 +318,7 @@ type AgentAccountModelDiscoverReq struct {
}
type AgentAccountModelCreateReq struct {
+ TaskID string `json:"taskID"`
AccountID uint `json:"accountId" validate:"required"`
Model AgentAccountModel `json:"model" validate:"required"`
}
@@ -328,8 +329,9 @@ type AgentAccountModelUpdateReq struct {
}
type AgentAccountModelDeleteReq struct {
- AccountID uint `json:"accountId" validate:"required"`
- RecordID uint `json:"recordId" validate:"required"`
+ DeleteFiles bool `json:"deleteFiles"`
+ AccountID uint `json:"accountId" validate:"required"`
+ RecordID uint `json:"recordId" validate:"required"`
}
type AgentAccountCreateReq struct {
diff --git a/agent/app/service/agents.go b/agent/app/service/agents.go
index 9796114d7..13cdfbcae 100644
--- a/agent/app/service/agents.go
+++ b/agent/app/service/agents.go
@@ -1298,6 +1298,31 @@ func (a AgentService) CreateAccountModel(req dto.AgentAccountModelCreateReq) err
if _, ok := findAgentAccountModelForProvider(account.Provider, models, nextModel.ID); ok {
return buserr.New("ErrRecordExist")
}
+ if account.Provider == "ollama" {
+ if account.AppInstallID != 0 {
+ install, err := appInstallRepo.GetFirst(repo.WithByID(account.AppInstallID))
+ if err != nil {
+ return err
+ }
+ if install.App.Key != "ollama" || !install.SyncModelAccount {
+ return buserr.New("ErrAgentAccountUnavailable")
+ }
+ localModels, err := aiRepo.List()
+ if err != nil {
+ return err
+ }
+ for _, item := range localModels {
+ if sameProviderModelID("ollama", item.Name, nextModel.ID) {
+ return (&AIToolService{}).Recreate(dto.OllamaModelName{Name: item.Name, TaskID: req.TaskID})
+ }
+ }
+ return (&AIToolService{}).Create(dto.OllamaModelName{Name: nextModel.ID, TaskID: req.TaskID})
+ }
+ nextModel.ID, err = resolveExistingOllamaModel(account, nextModel.ID)
+ if err != nil {
+ return err
+ }
+ }
sortOrder := len(models) + 1
record := &model.AgentAccountModel{
AccountID: account.ID,
@@ -1328,6 +1353,15 @@ func (a AgentService) UpdateAccountModel(req dto.AgentAccountModelUpdateReq) err
if err != nil {
return err
}
+ if account.Provider == "ollama" && !sameProviderModelID("ollama", record.Model, nextModel.ID) {
+ if account.AppInstallID != 0 {
+ return buserr.New("ErrInvalidParams")
+ }
+ nextModel.ID, err = resolveExistingOllamaModel(account, nextModel.ID)
+ if err != nil {
+ return err
+ }
+ }
nextModel.RecordID = req.Model.RecordID
for _, item := range models {
if item.RecordID == req.Model.RecordID {
@@ -1366,6 +1400,10 @@ func (a AgentService) UpdateAccountModel(req dto.AgentAccountModelUpdateReq) err
}
func (a AgentService) DeleteAccountModel(req dto.AgentAccountModelDeleteReq) error {
+ ollamaModelMu.Lock()
+ defer ollamaModelMu.Unlock()
+ agentAccountMutationMu.Lock()
+ defer agentAccountMutationMu.Unlock()
account, err := agentAccountRepo.GetFirst(repo.WithByID(req.AccountID))
if err != nil {
return err
@@ -1391,6 +1429,44 @@ func (a AgentService) DeleteAccountModel(req dto.AgentAccountModelDeleteReq) err
if err := ensureAccountModelsNotBound(account, nextModels); err != nil {
return err
}
+ if req.DeleteFiles && account.Provider != "ollama" {
+ return buserr.New("ErrAgentProviderNotSupported")
+ }
+ if req.DeleteFiles {
+ if account.AppInstallID != 0 {
+ install, err := appInstallRepo.GetFirst(repo.WithByID(account.AppInstallID))
+ if err != nil {
+ return err
+ }
+ if install.App.Key != "ollama" {
+ return buserr.New("ErrAgentAccountUnavailable")
+ }
+ localModels, err := aiRepo.List()
+ if err != nil {
+ return err
+ }
+ localIDs := make([]uint, 0)
+ for _, item := range localModels {
+ if !sameProviderModelID("ollama", item.Name, record.Model) {
+ continue
+ }
+ if item.Status == constant.StatusWaiting {
+ return buserr.New("TaskIsExecuting")
+ }
+ localIDs = append(localIDs, item.ID)
+ }
+ if err := cmd.NewCommandMgr().Run("docker", "exec", install.ContainerName, "ollama", "rm", record.Model); err != nil {
+ return err
+ }
+ if len(localIDs) > 0 {
+ if err := aiRepo.Delete(repo.WithByIDs(localIDs)); err != nil {
+ return err
+ }
+ }
+ } else if err := deleteRemoteOllamaModel(account, record.Model); err != nil {
+ return err
+ }
+ }
if err := agentAccountModelRepo.DeleteByID(req.RecordID); err != nil {
return err
}
diff --git a/agent/app/service/agents_local.go b/agent/app/service/agents_local.go
index 885acd0c4..090cd5b84 100644
--- a/agent/app/service/agents_local.go
+++ b/agent/app/service/agents_local.go
@@ -1,13 +1,19 @@
package service
import (
+ "bytes"
+ "encoding/json"
"errors"
"fmt"
+ "net/http"
"strings"
+ "time"
"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/app/model"
+ providercatalog "github.com/1Panel-dev/1Panel/agent/app/provider"
"github.com/1Panel-dev/1Panel/agent/app/repo"
+ "github.com/1Panel-dev/1Panel/agent/buserr"
"github.com/1Panel-dev/1Panel/agent/constant"
"github.com/1Panel-dev/1Panel/agent/global"
terminalai "github.com/1Panel-dev/1Panel/agent/utils/terminal/ai"
@@ -136,6 +142,62 @@ func syncOllamaModelAccount(install model.AppInstall, baseURL string, updateBase
return err
}
+func updateOllamaModelPool(modelName string, remove bool) error {
+ install, err := appInstallRepo.LoadInstallAppByKeyAndName("ollama", "")
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ if !install.SyncModelAccount {
+ return nil
+ }
+ agentAccountMutationMu.Lock()
+ defer agentAccountMutationMu.Unlock()
+ account, err := agentAccountRepo.GetFirst(repo.WithByAppInstallID(install.ID), repo.WithByProvider("ollama"))
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return nil
+ }
+ if err != nil {
+ return err
+ }
+ models, err := loadAgentAccountModels(account)
+ if err != nil {
+ return err
+ }
+ if remove {
+ for _, item := range models {
+ if !sameProviderModelID("ollama", item.ID, modelName) {
+ continue
+ }
+ if err := agentAccountModelRepo.DeleteByID(item.RecordID); err != nil {
+ return err
+ }
+ }
+ if sameProviderModelID("ollama", account.VerifyModel, modelName) {
+ account.VerifyModel = ""
+ if err := agentAccountRepo.Save(account); err != nil {
+ return err
+ }
+ }
+ if err := compactPersistedAgentAccountModelSortOrder(account.ID); err != nil {
+ return err
+ }
+ } else {
+ if _, exists := findAgentAccountModelForProvider("ollama", models, modelName); exists {
+ return nil
+ }
+ record := &model.AgentAccountModel{AccountID: account.ID, Model: modelName, Name: modelName, SortOrder: len(models) + 1}
+ if err := agentAccountModelRepo.Create(record); err != nil {
+ return err
+ }
+ }
+ terminalai.InvalidateTerminalRuntimeCache()
+ terminalai.InvalidateFileAIRuntimeCache()
+ return nil
+}
+
func loadOllamaModelAccountAddress(install model.AppInstall) (string, string, error) {
addressType := install.ModelAccountBaseURLType
if addressType == "" {
@@ -200,3 +262,39 @@ func ResolveLocalModelAccountBaseURL(addressType, customURL, containerName, cont
return fmt.Sprintf("http://%s:%s/v1", containerName, containerPort), nil
}
}
+
+func deleteRemoteOllamaModel(account *model.AgentAccount, modelName string) error {
+ body, err := json.Marshal(map[string]string{"model": modelName})
+ if err != nil {
+ return err
+ }
+ baseURL := strings.TrimSuffix(strings.TrimRight(account.BaseURL, "/"), "/v1")
+ req, err := http.NewRequest(http.MethodDelete, baseURL+"/api/delete", bytes.NewReader(body))
+ if err != nil {
+ return err
+ }
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+account.APIKey)
+ resp, err := (&http.Client{Timeout: 30 * time.Second}).Do(req)
+ if err != nil {
+ return err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
+ return fmt.Errorf("delete Ollama model failed: %s", resp.Status)
+ }
+ return nil
+}
+
+func resolveExistingOllamaModel(account *model.AgentAccount, modelID string) (string, error) {
+ available, err := providercatalog.DiscoverModels(account.BaseURL, account.APIKey)
+ if err != nil {
+ return "", buserr.WithErr("ErrAgentAccountUnavailable", err)
+ }
+ for _, id := range available {
+ if sameProviderModelID("ollama", id, modelID) {
+ return id, nil
+ }
+ }
+ return "", buserr.New("ErrRecordNotFound")
+}
diff --git a/agent/app/service/agents_utils.go b/agent/app/service/agents_utils.go
index c2f1119d5..518340e5d 100644
--- a/agent/app/service/agents_utils.go
+++ b/agent/app/service/agents_utils.go
@@ -1517,6 +1517,14 @@ func sameProviderModelID(provider, left, right string) bool {
}
leftComparable := providercatalog.NormalizeModelID(provider, leftTrimmed)
rightComparable := providercatalog.NormalizeModelID(provider, rightTrimmed)
+ if provider == "ollama" {
+ if leftComparable != "" && !strings.Contains(path.Base(leftComparable), ":") {
+ leftComparable += ":latest"
+ }
+ if rightComparable != "" && !strings.Contains(path.Base(rightComparable), ":") {
+ rightComparable += ":latest"
+ }
+ }
return leftComparable != "" && leftComparable == rightComparable
}
diff --git a/agent/app/service/ai.go b/agent/app/service/ai.go
index f8bb0f5c5..3bab2d784 100644
--- a/agent/app/service/ai.go
+++ b/agent/app/service/ai.go
@@ -117,6 +117,7 @@ func (u *AIToolService) Create(req dto.OllamaModelName) error {
}
taskItem, err := task.NewTaskWithOps(fmt.Sprintf("ollama-model-%s", req.Name), task.TaskPull, task.TaskScopeAI, req.TaskID, info.ID)
if err != nil {
+ _ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
global.LOG.Errorf("new task for exec shell failed, err: %v", err)
return err
}
@@ -126,19 +127,17 @@ func (u *AIToolService) Create(req dto.OllamaModelName) error {
}, nil)
taskItem.AddSubTask(i18n.GetWithName("OllamaModelSize", req.Name), func(t *task.Task) error {
itemSize, err := loadModelSize(info.Name, containerName)
- if len(itemSize) != 0 {
- _ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusSuccess, "size": itemSize})
- } else {
- _ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
+ if err != nil {
+ return err
}
- return nil
+ return aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusSuccess, "size": itemSize})
+ }, nil)
+ taskItem.AddSubTask(i18n.GetMsgByKey("TaskSync"), func(t *task.Task) error {
+ return updateOllamaModelPool(info.Name, false)
}, nil)
if err := taskItem.Execute(); err != nil {
_ = aiRepo.Update(info.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
}
- if err := SyncOllamaModelAccount(false); err != nil {
- global.LOG.Errorf("sync Ollama model account after pull: %v", err)
- }
}()
return nil
}
@@ -167,6 +166,9 @@ func (u *AIToolService) Recreate(req dto.OllamaModelName) error {
if modelInfo.ID == 0 {
return buserr.New("ErrRecordNotFound")
}
+ if modelInfo.Status == constant.StatusWaiting {
+ return buserr.New("TaskIsExecuting")
+ }
containerName, err := LoadContainerName()
if err != nil {
return err
@@ -176,6 +178,7 @@ func (u *AIToolService) Recreate(req dto.OllamaModelName) error {
}
taskItem, err := task.NewTaskWithOps(fmt.Sprintf("ollama-model-%s", req.Name), task.TaskPull, task.TaskScopeAI, req.TaskID, modelInfo.ID)
if err != nil {
+ _ = aiRepo.Update(modelInfo.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
global.LOG.Errorf("new task for exec shell failed, err: %v", err)
return err
}
@@ -185,19 +188,17 @@ func (u *AIToolService) Recreate(req dto.OllamaModelName) error {
}, nil)
taskItem.AddSubTask(i18n.GetWithName("OllamaModelSize", req.Name), func(t *task.Task) error {
itemSize, err := loadModelSize(modelInfo.Name, containerName)
- if len(itemSize) != 0 {
- _ = aiRepo.Update(modelInfo.ID, map[string]interface{}{"status": constant.StatusSuccess, "size": itemSize})
- } else {
- _ = aiRepo.Update(modelInfo.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
+ if err != nil {
+ return err
}
- return nil
+ return aiRepo.Update(modelInfo.ID, map[string]interface{}{"status": constant.StatusSuccess, "size": itemSize})
+ }, nil)
+ taskItem.AddSubTask(i18n.GetMsgByKey("TaskSync"), func(t *task.Task) error {
+ return updateOllamaModelPool(modelInfo.Name, false)
}, nil)
if err := taskItem.Execute(); err != nil {
_ = aiRepo.Update(modelInfo.ID, map[string]interface{}{"status": constant.StatusFailed, "message": err.Error()})
}
- if err := SyncOllamaModelAccount(false); err != nil {
- global.LOG.Errorf("sync Ollama model account after pull: %v", err)
- }
}()
return nil
}
@@ -219,11 +220,16 @@ func (u *AIToolService) Delete(req dto.ForceDelete) error {
return fmt.Errorf("handle ollama rm %s failed, %v", item.Name, err)
}
}
- _ = aiRepo.Delete(repo.WithByID(item.ID))
+ if err := aiRepo.Delete(repo.WithByID(item.ID)); err != nil {
+ return err
+ }
+ if err := updateOllamaModelPool(item.Name, true); err != nil {
+ return err
+ }
logItem := path.Join(global.Dir.DataDir, "log", "AITools", item.Name)
_ = os.Remove(logItem)
}
- return SyncOllamaModelAccount(false)
+ return nil
}
func (u *AIToolService) SyncAccount(req dto.OllamaModelAccountSync) error {
diff --git a/frontend/src/api/interface/ai.ts b/frontend/src/api/interface/ai.ts
index 5100e601f..8e6fd205b 100644
--- a/frontend/src/api/interface/ai.ts
+++ b/frontend/src/api/interface/ai.ts
@@ -677,6 +677,7 @@ export namespace AI {
}
export interface AgentAccountModelCreateReq {
+ taskID?: string;
accountId: number;
model: AgentAccountModel;
}
@@ -687,6 +688,7 @@ export namespace AI {
}
export interface AgentAccountModelDeleteReq {
+ deleteFiles?: boolean;
accountId: number;
recordId: number;
}
diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts
index ba78691a0..5d81e7c92 100644
--- a/frontend/src/lang/modules/en.ts
+++ b/frontend/src/lang/modules/en.ts
@@ -844,6 +844,9 @@ const message = {
discoverModelsFailedUseDefaults: 'Failed to get models. Default models are being used.',
accountModelsDuplicate: 'Duplicate models were found in the catalog',
modelPool: 'Model Pool',
+ ollamaRegisterOnly:
+ 'Only register models already available on this Ollama service. No download will be started.',
+ deleteModelFiles: 'Also delete model files from the Ollama service',
fallbackModels: 'Fallback Models',
addFallbackModel: 'Add Fallback Model',
fallbackModelsEmpty: 'No fallback models configured',
diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts
index 2b41b80ee..270c85477 100644
--- a/frontend/src/lang/modules/es-es.ts
+++ b/frontend/src/lang/modules/es-es.ts
@@ -849,6 +849,9 @@ const message = {
'No se pudieron obtener los modelos. Se usarán los modelos predeterminados.',
accountModelsDuplicate: 'Existen modelos duplicados en el catálogo',
modelPool: 'Pool de modelos',
+ ollamaRegisterOnly:
+ 'Solo se registran modelos ya disponibles en este servicio Ollama. No se iniciará ninguna descarga.',
+ deleteModelFiles: 'Eliminar también los archivos del modelo del servicio Ollama',
fallbackModels: 'Modelos de respaldo',
addFallbackModel: 'Agregar modelo de respaldo',
fallbackModelsEmpty: 'No hay modelos de respaldo configurados',
diff --git a/frontend/src/lang/modules/fa.ts b/frontend/src/lang/modules/fa.ts
index b86d16aa5..b6d3c4585 100644
--- a/frontend/src/lang/modules/fa.ts
+++ b/frontend/src/lang/modules/fa.ts
@@ -839,6 +839,8 @@ const message = {
discoverModelsFailedUseDefaults: 'دریافت مدلها ناموفق بود. از مدلهای پیشفرض استفاده میشود.',
accountModelsDuplicate: 'مدلهای تکراری در کاتالوگ یافت شد',
modelPool: 'مجموعه مدلها',
+ ollamaRegisterOnly: 'فقط مدلهای موجود در این سرویس Ollama ثبت میشوند. دانلودی آغاز نخواهد شد.',
+ deleteModelFiles: 'فایلهای مدل نیز از سرویس Ollama حذف شوند',
fallbackModels: 'مدلهای جایگزین',
addFallbackModel: 'افزودن مدل جایگزین',
fallbackModelsEmpty: 'هیچ مدل جایگزینی پیکربندی نشده است',
diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts
index e6c505574..e45e1da2b 100644
--- a/frontend/src/lang/modules/ja.ts
+++ b/frontend/src/lang/modules/ja.ts
@@ -843,6 +843,8 @@ const message = {
discoverModelsFailedUseDefaults: 'モデルを取得できませんでした。デフォルトモデルを使用しています。',
accountModelsDuplicate: 'カタログに重複したモデルがあります',
modelPool: 'モデルプール',
+ ollamaRegisterOnly: 'この Ollama サービスに存在するモデルのみを登録します。ダウンロードは開始されません。',
+ deleteModelFiles: 'Ollama サービス上のモデルファイルも削除する',
fallbackModels: 'フォールバックモデル',
addFallbackModel: 'フォールバックモデルを追加',
fallbackModelsEmpty: 'フォールバックモデルは未設定です',
diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts
index 7fd7cf28c..6627603c5 100644
--- a/frontend/src/lang/modules/ko.ts
+++ b/frontend/src/lang/modules/ko.ts
@@ -833,6 +833,8 @@ const message = {
discoverModelsFailedUseDefaults: '모델을 가져오지 못했습니다. 기본 모델을 사용합니다.',
accountModelsDuplicate: '카탈로그에 중복된 모델이 있습니다',
modelPool: '모델 풀',
+ ollamaRegisterOnly: '이 Ollama 서비스에 이미 있는 모델만 등록합니다. 다운로드는 시작되지 않습니다.',
+ deleteModelFiles: 'Ollama 서비스의 모델 파일도 삭제',
fallbackModels: '폴백 모델',
addFallbackModel: '폴백 모델 추가',
fallbackModelsEmpty: '구성된 폴백 모델이 없습니다',
diff --git a/frontend/src/lang/modules/lo.ts b/frontend/src/lang/modules/lo.ts
index efcbda156..fee995160 100644
--- a/frontend/src/lang/modules/lo.ts
+++ b/frontend/src/lang/modules/lo.ts
@@ -831,6 +831,8 @@ const message = {
discoverModelsFailedUseDefaults: 'ດຶງລາຍການໂມເດວບໍ່ສຳເລັດ. ກຳລັງໃຊ້ໂມເດວເລີ່ມຕົ້ນ.',
accountModelsDuplicate: 'ພົບໂມເດວທີ່ຊ້ຳກັນໃນລາຍການ',
modelPool: 'ກຸ່ມໂມເດວ (Model Pool)',
+ ollamaRegisterOnly: 'ລົງທະບຽນສະເພາະໂມເດວທີ່ມີຢູ່ໃນບໍລິການ Ollama ນີ້ແລ້ວ. ຈະບໍ່ເລີ່ມດາວໂຫຼດ.',
+ deleteModelFiles: 'ລຶບໄຟລ໌ໂມເດວອອກຈາກບໍລິການ Ollama ນຳ',
fallbackModels: 'ໂມເດວສຳຮອງ (Fallback)',
addFallbackModel: 'ເພີ່ມໂມເດວສຳຮອງ',
fallbackModelsEmpty: 'ຍັງບໍ່ໄດ້ຕັ້ງຄ່າໂມເດວສຳຮອງ',
diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts
index 29ccfa760..a83b0861b 100644
--- a/frontend/src/lang/modules/ms.ts
+++ b/frontend/src/lang/modules/ms.ts
@@ -853,6 +853,9 @@ const message = {
discoverModelsFailedUseDefaults: 'Gagal mendapatkan model. Model lalai sedang digunakan.',
accountModelsDuplicate: 'Terdapat model pendua dalam katalog',
modelPool: 'Katalog model',
+ ollamaRegisterOnly:
+ 'Daftar hanya model yang sudah tersedia pada perkhidmatan Ollama ini. Tiada muat turun akan dimulakan.',
+ deleteModelFiles: 'Padam juga fail model daripada perkhidmatan Ollama',
fallbackModels: 'Model fallback',
addFallbackModel: 'Tambah model fallback',
fallbackModelsEmpty: 'Tiada model fallback dikonfigurasikan',
diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts
index 39ea98415..1cd0b58f6 100644
--- a/frontend/src/lang/modules/pt-br.ts
+++ b/frontend/src/lang/modules/pt-br.ts
@@ -846,6 +846,9 @@ const message = {
discoverModelsFailedUseDefaults: 'Não foi possível obter os modelos. Os modelos padrão estão em uso.',
accountModelsDuplicate: 'Há modelos duplicados no catálogo',
modelPool: 'Catálogo de modelos',
+ ollamaRegisterOnly:
+ 'Registre apenas modelos já disponíveis neste serviço Ollama. Nenhum download será iniciado.',
+ deleteModelFiles: 'Excluir também os arquivos do modelo do serviço Ollama',
fallbackModels: 'Modelos de fallback',
addFallbackModel: 'Adicionar modelo de fallback',
fallbackModelsEmpty: 'Nenhum modelo de fallback configurado',
diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts
index 60f029c72..c7795e5a3 100644
--- a/frontend/src/lang/modules/ru.ts
+++ b/frontend/src/lang/modules/ru.ts
@@ -841,6 +841,9 @@ const message = {
discoverModelsFailedUseDefaults: 'Не удалось получить модели. Используются модели по умолчанию.',
accountModelsDuplicate: 'В каталоге обнаружены повторяющиеся модели',
modelPool: 'Каталог моделей',
+ ollamaRegisterOnly:
+ 'Регистрируются только модели, уже доступные в этом сервисе Ollama. Загрузка не запускается.',
+ deleteModelFiles: 'Также удалить файлы модели из сервиса Ollama',
fallbackModels: 'Резервные модели',
addFallbackModel: 'Добавить резервную модель',
fallbackModelsEmpty: 'Резервные модели не настроены',
diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts
index 9d236f310..fbe6f057f 100644
--- a/frontend/src/lang/modules/tr.ts
+++ b/frontend/src/lang/modules/tr.ts
@@ -849,6 +849,8 @@ const message = {
discoverModelsFailedUseDefaults: 'Modeller alınamadı. Varsayılan modeller kullanılıyor.',
accountModelsDuplicate: 'Katalogda yinelenen modeller bulundu',
modelPool: 'Model kataloğu',
+ ollamaRegisterOnly: 'Yalnızca bu Ollama hizmetinde mevcut modeller kaydedilir. İndirme başlatılmaz.',
+ deleteModelFiles: 'Model dosyalarını da Ollama hizmetinden sil',
fallbackModels: 'Yedek modeller',
addFallbackModel: 'Yedek model ekle',
fallbackModelsEmpty: 'Yapılandırılmış yedek model yok',
diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts
index 288116a1f..750cd12f0 100644
--- a/frontend/src/lang/modules/zh-Hant.ts
+++ b/frontend/src/lang/modules/zh-Hant.ts
@@ -804,6 +804,8 @@ const message = {
discoverModelsFailedUseDefaults: '無法取得模型,已改用預設模型',
accountModelsDuplicate: '模型清單中有重複項目,請檢查後再試一次',
modelPool: '模型池',
+ ollamaRegisterOnly: '僅登記此 Ollama 服務上已存在的模型,不會觸發下載。',
+ deleteModelFiles: '同時刪除 Ollama 服務上的模型檔案',
fallbackModels: '備用模型',
addFallbackModel: '新增備用模型',
fallbackModelsEmpty: '尚未設定備用模型',
diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts
index 3a6c602dd..3df0b30d9 100644
--- a/frontend/src/lang/modules/zh.ts
+++ b/frontend/src/lang/modules/zh.ts
@@ -821,6 +821,8 @@ const message = {
discoverModelsFailedUseDefaults: '获取模型失败,已使用默认模型',
accountModelsDuplicate: '模型池中存在重复模型,请检查后重试',
modelPool: '模型池',
+ ollamaRegisterOnly: '仅登记此 Ollama 服务上已存在的模型,不会触发下载。',
+ deleteModelFiles: '同时删除 Ollama 服务上的模型文件',
fallbackModels: '备用模型',
addFallbackModel: '新增备用模型',
fallbackModelsEmpty: '尚未配置备用模型',
diff --git a/frontend/src/views/ai/model/components/model-pool/index.vue b/frontend/src/views/ai/model/components/model-pool/index.vue
index 9a5ddccec..ab4763e63 100644
--- a/frontend/src/views/ai/model/components/model-pool/index.vue
+++ b/frontend/src/views/ai/model/components/model-pool/index.vue
@@ -26,10 +26,13 @@
-
-
+
+
+
+ {{ $t('aiTools.agents.ollamaRegisterOnly') }}
+
@@ -39,17 +42,28 @@
-
+
+
+
+
+
+
+ {{ $t('aiTools.agents.deleteModelFiles') }}
+
+
+