Skip to content

Commit 3b1c9d9

Browse files
authored
Merge pull request #205 from APIParkLab/feature/1.5-local-model
Feature/1.5 local model
2 parents 55e9744 + 1011302 commit 3b1c9d9

File tree

15 files changed

+147
-87
lines changed

15 files changed

+147
-87
lines changed

.gitlab-ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ variables:
1010
VIEW_ADDR: http://172.18.166.219:8288
1111
SAVE_DIR: /opt/${APP}
1212
NODE_OPTIONS: --max_old_space_size=8192
13+
APIPARK_OLLAMA_BASE: http://127.0.0.1:11434
1314

1415
stages:
1516
- notice

controller/ai-local/iml.go

Lines changed: 44 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,17 @@ import (
99
"net/http"
1010
"strings"
1111

12-
"github.com/APIParkLab/APIPark/module/router"
12+
"github.com/APIParkLab/APIPark/module/subscribe"
13+
subscribe_dto "github.com/APIParkLab/APIPark/module/subscribe/dto"
1314

1415
"github.com/APIParkLab/APIPark/model/plugin_model"
1516
"github.com/APIParkLab/APIPark/service/api"
1617

18+
ai_api_dto "github.com/APIParkLab/APIPark/module/ai-api/dto"
19+
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
20+
21+
"github.com/APIParkLab/APIPark/module/router"
22+
1723
ai_api "github.com/APIParkLab/APIPark/module/ai-api"
1824

1925
"github.com/APIParkLab/APIPark/module/catalogue"
@@ -24,9 +30,6 @@ import (
2430

2531
service_dto "github.com/APIParkLab/APIPark/module/service/dto"
2632

27-
ai_api_dto "github.com/APIParkLab/APIPark/module/ai-api/dto"
28-
router_dto "github.com/APIParkLab/APIPark/module/router/dto"
29-
3033
ai_provider_local "github.com/APIParkLab/APIPark/ai-provider/local"
3134

3235
"github.com/eolinker/eosc/log"
@@ -44,7 +47,9 @@ type imlLocalModelController struct {
4447
serviceModule service.IServiceModule `autowired:""`
4548
catalogueModule catalogue.ICatalogueModule `autowired:""`
4649
aiAPIModule ai_api.IAPIModule `autowired:""`
50+
appModule service.IAppModule `autowired:""`
4751
routerModule router.IRouterModule `autowired:""`
52+
subscribeModule subscribe.ISubscribeModule `autowired:""`
4853
docModule service.IServiceDocModule `autowired:""`
4954
transaction store.ITransaction `autowired:""`
5055
}
@@ -91,15 +96,8 @@ func (i *imlLocalModelController) Deploy(ctx *gin.Context) {
9196
"code": -1, "msg": "model is required", "success": "fail",
9297
})
9398
return
94-
9599
}
96-
//err = i.initAILocalService(ctx, input.Model, input.Team)
97-
//if err != nil {
98-
// ctx.JSON(200, gin.H{
99-
// "code": -1, "msg": err.Error(), "success": "fail",
100-
// })
101-
// return
102-
//}
100+
103101
id := uuid.NewString()
104102
p, err := i.module.Deploy(ctx, input.Model, id)
105103
if err != nil {
@@ -113,10 +111,11 @@ func (i *imlLocalModelController) Deploy(ctx *gin.Context) {
113111
go func() {
114112
select {
115113
case <-ctx.Writer.CloseNotify():
116-
log.Info("client closed connection,close pipeline")
117-
ai_provider_local.CancelPipeline(input.Model, id)
114+
118115
case <-done:
116+
119117
}
118+
ai_provider_local.CancelPipeline(input.Model, id)
120119
}()
121120
var complete int64
122121
var total int64
@@ -177,29 +176,29 @@ func (i *imlLocalModelController) Deploy(ctx *gin.Context) {
177176
}
178177

179178
func (i *imlLocalModelController) DeployStart(ctx *gin.Context, input *ai_local_dto.DeployInput) error {
180-
err := i.initAILocalService(ctx, input.Model, input.Team)
179+
fn, err := i.initAILocalService(ctx, input.Model, input.Team)
181180
if err != nil {
182181
return err
183182
}
184183
id := uuid.NewString()
185-
_, err = i.module.Deploy(ctx, input.Model, id)
184+
_, err = i.module.Deploy(ctx, input.Model, id, fn)
186185
if err != nil {
187186
return err
188187
}
189188
ai_provider_local.CancelPipeline(input.Model, id)
190189
return nil
191190
}
192191

193-
func (i *imlLocalModelController) initAILocalService(ctx context.Context, model string, teamID string) error {
194-
err := i.transaction.Transaction(ctx, func(ctx context.Context) error {
195-
catalogueInfo, err := i.catalogueModule.DefaultCatalogue(ctx)
196-
if err != nil {
197-
return err
198-
}
199-
serviceId := uuid.NewString()
200-
prefix := fmt.Sprintf("/%s", serviceId[:8])
201-
providerId := "ollama"
202-
info, err := i.serviceModule.Create(ctx, teamID, &service_dto.CreateService{
192+
func (i *imlLocalModelController) initAILocalService(ctx context.Context, model string, teamID string) (func() error, error) {
193+
catalogueInfo, err := i.catalogueModule.DefaultCatalogue(ctx)
194+
if err != nil {
195+
return nil, err
196+
}
197+
serviceId := uuid.NewString()
198+
prefix := fmt.Sprintf("/%s", serviceId[:8])
199+
providerId := "ollama"
200+
err = i.transaction.Transaction(ctx, func(ctx context.Context) error {
201+
_, err = i.serviceModule.Create(ctx, teamID, &service_dto.CreateService{
203202
Id: serviceId,
204203
Name: model,
205204
Prefix: prefix,
@@ -214,10 +213,10 @@ func (i *imlLocalModelController) initAILocalService(ctx context.Context, model
214213
if err != nil {
215214
return err
216215
}
217-
err = i.module.SaveCache(ctx, model, serviceId)
218-
if err != nil {
219-
return err
220-
}
216+
return i.module.SaveCache(ctx, model, serviceId)
217+
})
218+
219+
return func() error {
221220
path := fmt.Sprintf("/%s/chat", strings.Trim(prefix, "/"))
222221
timeout := 300000
223222
retry := 0
@@ -232,11 +231,11 @@ func (i *imlLocalModelController) initAILocalService(ctx context.Context, model
232231
Type: "local",
233232
}
234233
name := "Demo AI API"
235-
description := "A demo that shows you how to use a e a Chat API."
234+
description := "This is a demo that shows you how to use a Chat API."
236235
apiId := uuid.NewString()
237236
err = i.aiAPIModule.Create(
238237
ctx,
239-
info.Id,
238+
serviceId,
240239
&ai_api_dto.CreateAPI{
241240
Id: apiId,
242241
Name: name,
@@ -262,11 +261,11 @@ func (i *imlLocalModelController) initAILocalService(ctx context.Context, model
262261
plugins["ai_formatter"] = api.PluginSetting{
263262
Config: plugin_model.ConfigType{
264263
"model": aiModel.Id,
265-
"provider": info.Provider.Id,
264+
"provider": providerId,
266265
"config": aiModel.Config,
267266
},
268267
}
269-
_, err = i.routerModule.Create(ctx, info.Id, &router_dto.Create{
268+
_, err = i.routerModule.Create(ctx, serviceId, &router_dto.Create{
270269
Id: apiId,
271270
Name: name,
272271
Path: path,
@@ -287,13 +286,19 @@ func (i *imlLocalModelController) initAILocalService(ctx context.Context, model
287286
if err != nil {
288287
return err
289288
}
290-
291-
return i.docModule.SaveServiceDoc(ctx, info.Id, &service_dto.SaveServiceDoc{
289+
apps, err := i.appModule.Search(ctx, teamID, "")
290+
if err != nil {
291+
return err
292+
}
293+
for _, app := range apps {
294+
i.subscribeModule.AddSubscriber(ctx, serviceId, &subscribe_dto.AddSubscriber{
295+
Application: app.Id,
296+
})
297+
}
298+
return i.docModule.SaveServiceDoc(ctx, serviceId, &service_dto.SaveServiceDoc{
292299
Doc: "",
293300
})
294-
})
295-
296-
return err
301+
}, err
297302
}
298303

299304
func (i *imlLocalModelController) Search(ctx *gin.Context, keyword string) ([]*ai_local_dto.LocalModelItem, error) {

controller/service/iml.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ func (i *imlServiceController) createAIService(ctx *gin.Context, teamID string,
386386
Type: modelType,
387387
}
388388
name := "Demo AI API "
389-
description := "A demo that shows you how to use Chat API."
389+
description := "This is a demo that shows you how to use a Chat API."
390390
apiId := uuid.New().String()
391391
err = i.aiAPIModule.Create(
392392
ctx,

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ go 1.23.4
44

55
toolchain go1.23.6
66

7-
//toolchain go1.21.1
8-
97
require (
108
github.com/eolinker/ap-account v1.0.15
119
github.com/eolinker/eosc v0.18.3
@@ -83,6 +81,7 @@ require (
8381
// github.com/eolinker/eosc => ../../eolinker/eosc
8482
//)
8583

86-
//replace github.com/eolinker/ap-account => ../aoaccount
84+
//replace github.com/eolinker/ap-account => ../../eolinker/ap-account
85+
8786
//
8887
//replace github.com/eolinker/go-common => ../../eolinker/go-common

module/ai-api/schema.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,13 @@ func genResponse() *openapi3.ResponseRef {
7272

7373
func genRequestBodySchema(variables []*ai_api_dto.AiPromptVariable) *openapi3.Schema {
7474
result := openapi3.NewObjectSchema()
75-
result.WithProperty("variables", genVariableSchema(variables))
75+
if len(variables) > 0 {
76+
result.WithProperty("variables", genVariableSchema(variables))
77+
result.WithRequired([]string{"variables", "messages"})
78+
}
79+
7680
result.WithPropertyRef("messages", messagesSchemaRef)
77-
result.WithRequired([]string{"variables", "messages"})
81+
7882
return result
7983
}
8084

module/ai-local/dto/input.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type CancelDeploy struct {
99
}
1010

1111
type DeployInput struct {
12-
Model string `json:"model"`
13-
Team string `json:"team"`
12+
Model string `json:"model"`
13+
Service string `json:"service"`
14+
Team string `json:"team"`
1415
}

module/ai-local/iml.go

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -130,37 +130,44 @@ func (i *imlLocalModel) Search(ctx context.Context, keyword string) ([]*ai_local
130130
}
131131

132132
func (i *imlLocalModel) ListCanInstall(ctx context.Context, keyword string) ([]*ai_local_dto.LocalModelPackageItem, error) {
133-
list, err := i.localModelPackageService.Search(ctx, keyword, nil)
134-
if err != nil {
135-
return nil, err
136-
}
137-
if keyword != "" {
138-
result := make([]*ai_local_dto.LocalModelPackageItem, 0)
139133

140-
for _, v := range list {
141-
models := ai_provider_local.ModelsCanInstallById(v.Id)
142-
for _, model := range models {
143-
result = append(result, &ai_local_dto.LocalModelPackageItem{
144-
Id: model.Id,
145-
Name: model.Name,
146-
Size: model.Size,
147-
IsPopular: model.IsPopular,
148-
})
134+
if keyword == "" {
135+
list, err := i.localModelPackageService.Search(ctx, keyword, nil)
136+
if err != nil {
137+
return nil, err
138+
}
139+
return utils.SliceToSlice(list, func(s *ai_local.LocalModelPackage) *ai_local_dto.LocalModelPackageItem {
140+
return &ai_local_dto.LocalModelPackageItem{
141+
Id: s.Id,
142+
Name: s.Name,
143+
Size: s.Size,
144+
IsPopular: s.IsPopular,
149145
}
146+
}), nil
147+
} else {
148+
info, err := i.localModelPackageService.Get(ctx, keyword)
149+
if err != nil {
150+
return nil, err
150151
}
152+
result := make([]*ai_local_dto.LocalModelPackageItem, 0)
153+
154+
//for _, v := range list {
155+
models := ai_provider_local.ModelsCanInstallById(info.Id)
156+
for _, model := range models {
157+
result = append(result, &ai_local_dto.LocalModelPackageItem{
158+
Id: model.Id,
159+
Name: model.Name,
160+
Size: model.Size,
161+
IsPopular: model.IsPopular,
162+
})
163+
}
164+
//}
151165
return result, nil
152166
}
153-
return utils.SliceToSlice(list, func(s *ai_local.LocalModelPackage) *ai_local_dto.LocalModelPackageItem {
154-
return &ai_local_dto.LocalModelPackageItem{
155-
Id: s.Id,
156-
Name: s.Name,
157-
Size: s.Size,
158-
IsPopular: s.IsPopular,
159-
}
160-
}), nil
167+
161168
}
162169

163-
func (i *imlLocalModel) pullHook() func(msg ai_provider_local.PullMessage) error {
170+
func (i *imlLocalModel) pullHook(fn ...func() error) func(msg ai_provider_local.PullMessage) error {
164171
return func(msg ai_provider_local.PullMessage) error {
165172
return i.transaction.Transaction(context.Background(), func(ctx context.Context) error {
166173

@@ -233,6 +240,12 @@ func (i *imlLocalModel) pullHook() func(msg ai_provider_local.PullMessage) error
233240
return err
234241
}
235242
if state == ai_local_dto.DeployStateFinish.Int() {
243+
for _, f := range fn {
244+
err = f()
245+
if err != nil {
246+
return err
247+
}
248+
}
236249
cfg := make(map[string]interface{})
237250
cfg["provider"] = "ollama"
238251
cfg["model"] = msg.Model
@@ -289,10 +302,19 @@ func (i *imlLocalModel) syncGateway(ctx context.Context, clusterId string, relea
289302
return nil
290303
}
291304

292-
func (i *imlLocalModel) Deploy(ctx context.Context, model string, session string) (*ai_provider_local.Pipeline, error) {
305+
func (i *imlLocalModel) Deploy(ctx context.Context, model string, session string, fn ...func() error) (*ai_provider_local.Pipeline, error) {
293306
var p *ai_provider_local.Pipeline
294307
err := i.transaction.Transaction(ctx, func(txCtx context.Context) error {
295-
_, err := i.localModelService.Get(ctx, model)
308+
item, err := i.localModelCacheService.GetByTarget(ctx, ai_local.CacheTypeService, model)
309+
if err != nil {
310+
if !errors.Is(err, gorm.ErrRecordNotFound) {
311+
return err
312+
}
313+
314+
} else {
315+
model = item.Model
316+
}
317+
info, err := i.localModelService.Get(ctx, model)
296318
if err != nil {
297319
if !errors.Is(err, gorm.ErrRecordNotFound) {
298320
return err
@@ -305,13 +327,15 @@ func (i *imlLocalModel) Deploy(ctx context.Context, model string, session string
305327
})
306328

307329
} else {
308-
state := ai_local_dto.LocalModelStateDeploying.Int()
309-
err = i.localModelService.Save(ctx, model, &ai_local.EditLocalModel{State: &state})
330+
if info.State == ai_local_dto.LocalModelStateDeployingError.Int() {
331+
state := ai_local_dto.LocalModelStateDeploying.Int()
332+
err = i.localModelService.Save(ctx, model, &ai_local.EditLocalModel{State: &state})
333+
}
310334
}
311335
if err != nil {
312336
return err
313337
}
314-
p, err = ai_provider_local.PullModel(model, session, i.pullHook())
338+
p, err = ai_provider_local.PullModel(model, session, i.pullHook(fn...))
315339
if err != nil {
316340
return err
317341
}
@@ -330,6 +354,15 @@ func (i *imlLocalModel) SaveCache(ctx context.Context, model string, target stri
330354

331355
func (i *imlLocalModel) CancelDeploy(ctx context.Context, model string) error {
332356
return i.transaction.Transaction(ctx, func(txCtx context.Context) error {
357+
item, err := i.localModelCacheService.GetByTarget(ctx, ai_local.CacheTypeService, model)
358+
if err != nil {
359+
if !errors.Is(err, gorm.ErrRecordNotFound) {
360+
return err
361+
}
362+
363+
} else {
364+
model = item.Model
365+
}
333366
list, err := i.localModelCacheService.List(ctx, model, ai_local.CacheTypeService)
334367
if err != nil {
335368
return err
@@ -428,6 +461,7 @@ func (i *imlLocalModel) OnInit() {
428461
})
429462
models, version := ai_provider_local.ModelsCanInstall()
430463
for _, model := range models {
464+
delete(oldModels, model.Id)
431465
if v, ok := oldModels[model.Id]; ok {
432466
if v.Version == version {
433467
continue
@@ -456,7 +490,6 @@ func (i *imlLocalModel) OnInit() {
456490
return
457491
}
458492
}
459-
delete(oldModels, model.Id)
460493
}
461494
for id := range oldModels {
462495
err = i.localModelPackageService.Delete(ctx, id)

0 commit comments

Comments
 (0)