@@ -3,19 +3,20 @@ package service
33import (
44 "context"
55 "fmt"
6- "io"
76 "os"
8- "os/exec"
97 "path"
108 "strings"
9+ "time"
1110
1211 "github.com/1Panel-dev/1Panel/agent/app/dto"
1312 "github.com/1Panel-dev/1Panel/agent/app/dto/request"
1413 "github.com/1Panel-dev/1Panel/agent/app/model"
1514 "github.com/1Panel-dev/1Panel/agent/app/repo"
15+ "github.com/1Panel-dev/1Panel/agent/app/task"
1616 "github.com/1Panel-dev/1Panel/agent/buserr"
1717 "github.com/1Panel-dev/1Panel/agent/constant"
1818 "github.com/1Panel-dev/1Panel/agent/global"
19+ "github.com/1Panel-dev/1Panel/agent/i18n"
1920 "github.com/1Panel-dev/1Panel/agent/utils/cmd"
2021 "github.com/1Panel-dev/1Panel/agent/utils/common"
2122 "github.com/jinzhu/copier"
@@ -25,9 +26,9 @@ type AIToolService struct{}
2526
2627type IAIToolService interface {
2728 Search (search dto.SearchWithPage ) (int64 , []dto.OllamaModelInfo , error )
28- Create (name string ) error
29+ Create (req dto. OllamaModelName ) error
2930 Close (name string ) error
30- Recreate (name string ) error
31+ Recreate (req dto. OllamaModelName ) error
3132 Delete (req dto.ForceDelete ) error
3233 Sync () ([]dto.OllamaModelDropList , error )
3334 LoadDetail (name string ) (string , error )
@@ -55,8 +56,8 @@ func (u *AIToolService) Search(req dto.SearchWithPage) (int64, []dto.OllamaModel
5556 if err := copier .Copy (& item , & itemModel ); err != nil {
5657 return 0 , nil , buserr .WithDetail ("ErrStructTransform" , err .Error (), nil )
5758 }
58- logPath := path . Join ( global . Dir . DataDir , "log" , "AITools" , itemModel . Name )
59- if _ , err := os . Stat ( logPath ); err == nil {
59+ taskModel , _ := taskRepo . GetFirst ( taskRepo . WithResourceID ( item . ID ), repo . WithByType ( task . TaskScopeAI ) )
60+ if len ( taskModel . ID ) != 0 {
6061 item .LogFileExist = true
6162 }
6263 dtoLists = append (dtoLists , item )
@@ -79,37 +80,46 @@ func (u *AIToolService) LoadDetail(name string) (string, error) {
7980 return stdout , err
8081}
8182
82- func (u * AIToolService ) Create (name string ) error {
83- if cmd .CheckIllegal (name ) {
83+ func (u * AIToolService ) Create (req dto. OllamaModelName ) error {
84+ if cmd .CheckIllegal (req . Name ) {
8485 return buserr .New ("ErrCmdIllegal" )
8586 }
86- modelInfo , _ := aiRepo .Get (repo .WithByName (name ))
87+ modelInfo , _ := aiRepo .Get (repo .WithByName (req . Name ))
8788 if modelInfo .ID != 0 {
8889 return buserr .New ("ErrRecordExist" )
8990 }
9091 containerName , err := LoadContainerName ()
9192 if err != nil {
9293 return err
9394 }
94- logItem := path .Join (global .Dir .DataDir , "log" , "AITools" , name )
95- if _ , err := os .Stat (path .Dir (logItem )); err != nil && os .IsNotExist (err ) {
96- if err = os .MkdirAll (path .Dir (logItem ), os .ModePerm ); err != nil {
97- return err
98- }
99- }
10095 info := model.OllamaModel {
101- Name : name ,
96+ Name : req . Name ,
10297 From : "local" ,
10398 Status : constant .StatusWaiting ,
10499 }
105100 if err := aiRepo .Create (& info ); err != nil {
106101 return err
107102 }
108- file , err := os . OpenFile ( logItem , os . O_WRONLY | os . O_CREATE | os . O_TRUNC , 0666 )
103+ taskItem , err := task . NewTaskWithOps ( fmt . Sprintf ( "ollama-model-%s" , req . Name ), task . TaskPull , task . TaskScopeAI , req . TaskID , info . ID )
109104 if err != nil {
105+ global .LOG .Errorf ("new task for exec shell failed, err: %v" , err )
110106 return err
111107 }
112- go pullOllamaModel (file , containerName , info )
108+ go func () {
109+ taskItem .AddSubTask (i18n .GetWithName ("OllamaModelPull" , req .Name ), func (t * task.Task ) error {
110+ return cmd .ExecShellWithTask (taskItem , time .Hour , "docker" , "exec" , containerName , "ollama" , "pull" , info .Name )
111+ }, nil )
112+ taskItem .AddSubTask (i18n .GetWithName ("OllamaModelSize" , req .Name ), func (t * task.Task ) error {
113+ itemSize , err := loadModelSize (info .Name , containerName )
114+ if len (itemSize ) != 0 {
115+ _ = aiRepo .Update (info .ID , map [string ]interface {}{"status" : constant .StatusSuccess , "size" : itemSize })
116+ } else {
117+ _ = aiRepo .Update (info .ID , map [string ]interface {}{"status" : constant .StatusFailed , "message" : err .Error ()})
118+ }
119+ return nil
120+ }, nil )
121+ _ = taskItem .Execute ()
122+ }()
113123 return nil
114124}
115125
@@ -128,11 +138,11 @@ func (u *AIToolService) Close(name string) error {
128138 return nil
129139}
130140
131- func (u * AIToolService ) Recreate (name string ) error {
132- if cmd .CheckIllegal (name ) {
141+ func (u * AIToolService ) Recreate (req dto. OllamaModelName ) error {
142+ if cmd .CheckIllegal (req . Name ) {
133143 return buserr .New ("ErrCmdIllegal" )
134144 }
135- modelInfo , _ := aiRepo .Get (repo .WithByName (name ))
145+ modelInfo , _ := aiRepo .Get (repo .WithByName (req . Name ))
136146 if modelInfo .ID == 0 {
137147 return buserr .New ("ErrRecordNotFound" )
138148 }
@@ -143,17 +153,17 @@ func (u *AIToolService) Recreate(name string) error {
143153 if err := aiRepo .Update (modelInfo .ID , map [string ]interface {}{"status" : constant .StatusWaiting , "from" : "local" }); err != nil {
144154 return err
145155 }
146- logItem := path .Join (global .Dir .DataDir , "log" , "AITools" , name )
147- if _ , err := os .Stat (path .Dir (logItem )); err != nil && os .IsNotExist (err ) {
148- if err = os .MkdirAll (path .Dir (logItem ), os .ModePerm ); err != nil {
149- return err
150- }
151- }
152- file , err := os .OpenFile (logItem , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , 0666 )
156+ taskItem , err := task .NewTaskWithOps (fmt .Sprintf ("ollama-model-%s" , req .Name ), task .TaskPull , task .TaskScopeAI , req .TaskID , modelInfo .ID )
153157 if err != nil {
158+ global .LOG .Errorf ("new task for exec shell failed, err: %v" , err )
154159 return err
155160 }
156- go pullOllamaModel (file , containerName , modelInfo )
161+ go func () {
162+ taskItem .AddSubTask (i18n .GetWithName ("OllamaModelPull" , req .Name ), func (t * task.Task ) error {
163+ return cmd .ExecShellWithTask (taskItem , time .Hour , "docker" , "exec" , containerName , "ollama" , "pull" , req .Name )
164+ }, nil )
165+ _ = taskItem .Execute ()
166+ }()
157167 return nil
158168}
159169
@@ -354,22 +364,6 @@ func LoadContainerName() (string, error) {
354364 return ollamaBaseInfo .ContainerName , nil
355365}
356366
357- func pullOllamaModel (file * os.File , containerName string , info model.OllamaModel ) {
358- defer file .Close ()
359- cmd := exec .Command ("docker" , "exec" , containerName , "ollama" , "pull" , info .Name )
360- multiWriter := io .MultiWriter (os .Stdout , file )
361- cmd .Stdout = multiWriter
362- cmd .Stderr = multiWriter
363- _ = cmd .Run ()
364- itemSize , err := loadModelSize (info .Name , containerName )
365- if len (itemSize ) != 0 {
366- _ = aiRepo .Update (info .ID , map [string ]interface {}{"status" : constant .StatusSuccess , "size" : itemSize })
367- } else {
368- _ = aiRepo .Update (info .ID , map [string ]interface {}{"status" : constant .StatusFailed , "message" : err .Error ()})
369- }
370- _ , _ = file .WriteString ("ollama pull completed!" )
371- }
372-
373367func loadModelSize (name string , containerName string ) (string , error ) {
374368 stdout , err := cmd .Execf ("docker exec %s ollama list | grep %s" , containerName , name )
375369 if err != nil {
0 commit comments