Skip to content

Commit 90eca45

Browse files
authored
feat: Merge code of gpu from dev (#7982)
1 parent efa2fa9 commit 90eca45

File tree

57 files changed

+4067
-359
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+4067
-359
lines changed

agent/app/api/v2/ai.go

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
package v2
2+
3+
import (
4+
"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
5+
"github.com/1Panel-dev/1Panel/agent/app/dto"
6+
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/gpu"
7+
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/gpu/common"
8+
"github.com/1Panel-dev/1Panel/agent/utils/ai_tools/xpu"
9+
"github.com/gin-gonic/gin"
10+
)
11+
12+
// @Tags AI
13+
// @Summary Create Ollama model
14+
// @Accept json
15+
// @Param request body dto.OllamaModelName true "request"
16+
// @Success 200
17+
// @Security ApiKeyAuth
18+
// @Security Timestamp
19+
// @Router /ai/ollama/model [post]
20+
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型 [name]","formatEN":"add Ollama model [name]"}
21+
func (b *BaseApi) CreateOllamaModel(c *gin.Context) {
22+
var req dto.OllamaModelName
23+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
24+
return
25+
}
26+
27+
if err := aiToolService.Create(req.Name); err != nil {
28+
helper.BadRequest(c, err)
29+
return
30+
}
31+
helper.SuccessWithData(c, nil)
32+
}
33+
34+
// @Tags AI
35+
// @Summary Rereate Ollama model
36+
// @Accept json
37+
// @Param request body dto.OllamaModelName true "request"
38+
// @Success 200
39+
// @Security ApiKeyAuth
40+
// @Security Timestamp
41+
// @Router /ai/ollama/model/recreate [post]
42+
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"添加 Ollama 模型重试 [name]","formatEN":"re-add Ollama model [name]"}
43+
func (b *BaseApi) RecreateOllamaModel(c *gin.Context) {
44+
var req dto.OllamaModelName
45+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
46+
return
47+
}
48+
49+
if err := aiToolService.Recreate(req.Name); err != nil {
50+
helper.BadRequest(c, err)
51+
return
52+
}
53+
helper.SuccessWithData(c, nil)
54+
}
55+
56+
// @Tags AI
57+
// @Summary Close Ollama model conn
58+
// @Accept json
59+
// @Param request body dto.OllamaModelName true "request"
60+
// @Success 200
61+
// @Security ApiKeyAuth
62+
// @Security Timestamp
63+
// @Router /ai/ollama/model/close [post]
64+
// @x-panel-log {"bodyKeys":["name"],"paramKeys":[],"BeforeFunctions":[],"formatZH":"关闭 Ollama 模型连接 [name]","formatEN":"close conn for Ollama model [name]"}
65+
func (b *BaseApi) CloseOllamaModel(c *gin.Context) {
66+
var req dto.OllamaModelName
67+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
68+
return
69+
}
70+
71+
if err := aiToolService.Close(req.Name); err != nil {
72+
helper.BadRequest(c, err)
73+
return
74+
}
75+
helper.SuccessWithData(c, nil)
76+
}
77+
78+
// @Tags AI
79+
// @Summary Sync Ollama model list
80+
// @Success 200 {array} dto.OllamaModelDropList
81+
// @Security ApiKeyAuth
82+
// @Security Timestamp
83+
// @Router /ai/ollama/model/sync [post]
84+
// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"同步 Ollama 模型列表","formatEN":"sync Ollama model list"}
85+
func (b *BaseApi) SyncOllamaModel(c *gin.Context) {
86+
list, err := aiToolService.Sync()
87+
if err != nil {
88+
helper.BadRequest(c, err)
89+
return
90+
}
91+
helper.SuccessWithData(c, list)
92+
}
93+
94+
// @Tags AI
95+
// @Summary Page Ollama models
96+
// @Accept json
97+
// @Param request body dto.SearchWithPage true "request"
98+
// @Success 200 {object} dto.PageResult
99+
// @Security ApiKeyAuth
100+
// @Security Timestamp
101+
// @Router /ai/ollama/model/search [post]
102+
func (b *BaseApi) SearchOllamaModel(c *gin.Context) {
103+
var req dto.SearchWithPage
104+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
105+
return
106+
}
107+
108+
total, list, err := aiToolService.Search(req)
109+
if err != nil {
110+
helper.BadRequest(c, err)
111+
return
112+
}
113+
114+
helper.SuccessWithData(c, dto.PageResult{
115+
Items: list,
116+
Total: total,
117+
})
118+
}
119+
120+
// @Tags AI
121+
// @Summary Page Ollama models
122+
// @Accept json
123+
// @Param request body dto.OllamaModelName true "request"
124+
// @Success 200 {string} details
125+
// @Security ApiKeyAuth
126+
// @Security Timestamp
127+
// @Router /ai/ollama/model/load [post]
128+
func (b *BaseApi) LoadOllamaModelDetail(c *gin.Context) {
129+
var req dto.OllamaModelName
130+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
131+
return
132+
}
133+
134+
detail, err := aiToolService.LoadDetail(req.Name)
135+
if err != nil {
136+
helper.BadRequest(c, err)
137+
return
138+
}
139+
140+
helper.SuccessWithData(c, detail)
141+
}
142+
143+
// @Tags AI
144+
// @Summary Delete Ollama model
145+
// @Accept json
146+
// @Param request body dto.ForceDelete true "request"
147+
// @Success 200
148+
// @Security ApiKeyAuth
149+
// @Security Timestamp
150+
// @Router /ai/ollama/model/del [post]
151+
// @x-panel-log {"bodyKeys":["ids"],"paramKeys":[],"BeforeFunctions":[{"input_column":"id","input_value":"ids","isList":true,"db":"ollama_models","output_column":"name","output_value":"names"}],"formatZH":"删除 Ollama 模型 [names]","formatEN":"remove Ollama model [names]"}
152+
func (b *BaseApi) DeleteOllamaModel(c *gin.Context) {
153+
var req dto.ForceDelete
154+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
155+
return
156+
}
157+
158+
if err := aiToolService.Delete(req); err != nil {
159+
helper.BadRequest(c, err)
160+
return
161+
}
162+
163+
helper.SuccessWithOutData(c)
164+
}
165+
166+
// @Tags AI
167+
// @Summary Load gpu / xpu info
168+
// @Accept json
169+
// @Success 200
170+
// @Security ApiKeyAuth
171+
// @Security Timestamp
172+
// @Router /ai/gpu/load [get]
173+
func (b *BaseApi) LoadGpuInfo(c *gin.Context) {
174+
ok, client := gpu.New()
175+
if ok {
176+
info, err := client.LoadGpuInfo()
177+
if err != nil {
178+
helper.BadRequest(c, err)
179+
return
180+
}
181+
helper.SuccessWithData(c, info)
182+
return
183+
}
184+
xpuOK, xpuClient := xpu.New()
185+
if xpuOK {
186+
info, err := xpuClient.LoadGpuInfo()
187+
if err != nil {
188+
helper.BadRequest(c, err)
189+
return
190+
}
191+
helper.SuccessWithData(c, info)
192+
return
193+
}
194+
helper.SuccessWithData(c, &common.GpuInfo{})
195+
}
196+
197+
// @Tags AI
198+
// @Summary Bind domain
199+
// @Accept json
200+
// @Param request body dto.OllamaBindDomain true "request"
201+
// @Success 200
202+
// @Security ApiKeyAuth
203+
// @Security Timestamp
204+
// @Router /ai/domain/bind [post]
205+
func (b *BaseApi) BindDomain(c *gin.Context) {
206+
var req dto.OllamaBindDomain
207+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
208+
return
209+
}
210+
if err := aiToolService.BindDomain(req); err != nil {
211+
helper.BadRequest(c, err)
212+
return
213+
}
214+
helper.SuccessWithOutData(c)
215+
}
216+
217+
// @Tags AI
218+
// @Summary Get bind domain
219+
// @Accept json
220+
// @Param request body dto.OllamaBindDomainReq true "request"
221+
// @Success 200 {object} dto.OllamaBindDomainRes
222+
// @Security ApiKeyAuth
223+
// @Security Timestamp
224+
// @Router /ai/domain/get [post]
225+
func (b *BaseApi) GetBindDomain(c *gin.Context) {
226+
var req dto.OllamaBindDomainReq
227+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
228+
return
229+
}
230+
res, err := aiToolService.GetBindDomain(req)
231+
if err != nil {
232+
helper.BadRequest(c, err)
233+
return
234+
}
235+
helper.SuccessWithData(c, res)
236+
}
237+
238+
// Tags AI
239+
// Summary Update bind domain
240+
// Accept json
241+
// Param request body dto.OllamaBindDomain true "request"
242+
// Success 200
243+
// Security ApiKeyAuth
244+
// Security Timestamp
245+
// Router /ai/domain/update [post]
246+
func (b *BaseApi) UpdateBindDomain(c *gin.Context) {
247+
var req dto.OllamaBindDomain
248+
if err := helper.CheckBindAndValidate(&req, c); err != nil {
249+
return
250+
}
251+
if err := aiToolService.UpdateBindDomain(req); err != nil {
252+
helper.BadRequest(c, err)
253+
return
254+
}
255+
helper.SuccessWithOutData(c)
256+
}

agent/app/api/v2/entry.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ var (
1616
appService = service.NewIAppService()
1717
appInstallService = service.NewIAppInstalledService()
1818

19+
aiToolService = service.NewIAIToolService()
20+
1921
containerService = service.NewIContainerService()
2022
composeTemplateService = service.NewIComposeTemplateService()
2123
imageRepoService = service.NewIImageRepoService()

agent/app/api/v2/terminal.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
"github.com/1Panel-dev/1Panel/agent/app/dto"
13+
"github.com/1Panel-dev/1Panel/agent/app/service"
1314
"github.com/1Panel-dev/1Panel/agent/global"
1415
"github.com/1Panel-dev/1Panel/agent/utils/cmd"
1516
"github.com/1Panel-dev/1Panel/agent/utils/terminal"
@@ -165,6 +166,70 @@ func (b *BaseApi) ContainerWsSsh(c *gin.Context) {
165166
}
166167
}
167168

169+
func (b *BaseApi) OllamaWsSsh(c *gin.Context) {
170+
wsConn, err := upGrader.Upgrade(c.Writer, c.Request, nil)
171+
if err != nil {
172+
global.LOG.Errorf("gin context http handler failed, err: %v", err)
173+
return
174+
}
175+
defer wsConn.Close()
176+
177+
if global.CONF.Base.IsDemo {
178+
if wshandleError(wsConn, errors.New(" demo server, prohibit this operation!")) {
179+
return
180+
}
181+
}
182+
183+
cols, err := strconv.Atoi(c.DefaultQuery("cols", "80"))
184+
if wshandleError(wsConn, errors.WithMessage(err, "invalid param cols in request")) {
185+
return
186+
}
187+
rows, err := strconv.Atoi(c.DefaultQuery("rows", "40"))
188+
if wshandleError(wsConn, errors.WithMessage(err, "invalid param rows in request")) {
189+
return
190+
}
191+
name := c.Query("name")
192+
if cmd.CheckIllegal(name) {
193+
if wshandleError(wsConn, errors.New(" The command contains illegal characters.")) {
194+
return
195+
}
196+
}
197+
container, err := service.LoadContainerName()
198+
if wshandleError(wsConn, errors.WithMessage(err, " load container name for ollama failed")) {
199+
return
200+
}
201+
commands := []string{"ollama", "run", name}
202+
203+
pidMap := loadMapFromDockerTop(container)
204+
fmt.Println("pidMap")
205+
for k, v := range pidMap {
206+
fmt.Println(k, v)
207+
}
208+
itemCmds := append([]string{"exec", "-it", container}, commands...)
209+
slave, err := terminal.NewCommand(itemCmds)
210+
if wshandleError(wsConn, err) {
211+
return
212+
}
213+
defer killBash(container, strings.Join(commands, " "), pidMap)
214+
defer slave.Close()
215+
216+
tty, err := terminal.NewLocalWsSession(cols, rows, wsConn, slave, false)
217+
if wshandleError(wsConn, err) {
218+
return
219+
}
220+
221+
quitChan := make(chan bool, 3)
222+
tty.Start(quitChan)
223+
go slave.Wait(quitChan)
224+
225+
<-quitChan
226+
227+
global.LOG.Info("websocket finished")
228+
if wshandleError(wsConn, err) {
229+
return
230+
}
231+
}
232+
168233
func wshandleError(ws *websocket.Conn, err error) bool {
169234
if err != nil {
170235
global.LOG.Errorf("handler ws faled:, err: %v", err)

agent/app/dto/ai.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package dto
2+
3+
import "time"
4+
5+
type OllamaModelInfo struct {
6+
ID uint `json:"id"`
7+
Name string `json:"name"`
8+
Size string `json:"size"`
9+
From string `json:"from"`
10+
LogFileExist bool `json:"logFileExist"`
11+
12+
Status string `json:"status"`
13+
Message string `json:"message"`
14+
CreatedAt time.Time `json:"createdAt"`
15+
}
16+
17+
type OllamaModelDropList struct {
18+
ID uint `json:"id"`
19+
Name string `json:"name"`
20+
}
21+
22+
type OllamaModelName struct {
23+
Name string `json:"name"`
24+
}
25+
26+
type OllamaBindDomain struct {
27+
Domain string `json:"domain" validate:"required"`
28+
AppInstallID uint `json:"appInstallID" validate:"required"`
29+
SSLID uint `json:"sslID"`
30+
WebsiteID uint `json:"websiteID"`
31+
IPList string `json:"ipList"`
32+
}
33+
34+
type OllamaBindDomainReq struct {
35+
AppInstallID uint `json:"appInstallID" validate:"required"`
36+
}
37+
38+
type OllamaBindDomainRes struct {
39+
Domain string `json:"domain"`
40+
SSLID uint `json:"sslID"`
41+
AllowIPs []string `json:"allowIPs"`
42+
WebsiteID uint `json:"websiteID"`
43+
ConnUrl string `json:"connUrl"`
44+
}

agent/app/dto/common_req.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,8 @@ type UpdateGroup struct {
7171
type OperateWithTask struct {
7272
TaskID string `json:"taskID"`
7373
}
74+
75+
type ForceDelete struct {
76+
IDs []uint `json:"ids"`
77+
ForceDelete bool `json:"forceDelete"`
78+
}

0 commit comments

Comments
 (0)