You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ai_model_manage.go 42 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
2 years ago
3 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402
  1. package repo
  2. import (
  3. "archive/zip"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "net/http"
  8. "net/url"
  9. "path"
  10. "regexp"
  11. "strings"
  12. "code.gitea.io/gitea/services/repository"
  13. "code.gitea.io/gitea/models"
  14. "code.gitea.io/gitea/modules/context"
  15. "code.gitea.io/gitea/modules/log"
  16. "code.gitea.io/gitea/modules/notification"
  17. "code.gitea.io/gitea/modules/setting"
  18. "code.gitea.io/gitea/modules/storage"
  19. "code.gitea.io/gitea/services/cloudbrain/resource"
  20. uuid "github.com/satori/go.uuid"
  21. )
  22. const (
  23. Attachment_model = "model"
  24. Model_prefix = "aimodels/"
  25. tplModelManageIndex = "repo/modelmanage/index"
  26. tplModelManageDownload = "repo/modelmanage/download"
  27. tplModelInfo = "repo/modelmanage/showinfo"
  28. tplCreateLocalModelInfo = "repo/modelmanage/create_local_1"
  29. tplCreateLocalForUploadModelInfo = "repo/modelmanage/create_local_2"
  30. tplCreateOnlineModelInfo = "repo/modelmanage/create_online"
  31. MODEL_LATEST = 1
  32. MODEL_NOT_LATEST = 0
  33. MODEL_MAX_SIZE = 1024 * 1024 * 1024
  34. STATUS_COPY_MODEL = 1
  35. STATUS_FINISHED = 0
  36. STATUS_ERROR = 2
  37. MODEL_LOCAL_TYPE = 1
  38. MODEL_ONLINE_TYPE = 0
  39. )
  40. func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, engine int, ctx *context.Context) (string, error) {
  41. aiTask, err := models.GetCloudbrainByJobIDAndVersionName(jobId, versionName)
  42. if err != nil {
  43. aiTask, err = models.GetRepoCloudBrainByJobID(ctx.Repo.Repository.ID, jobId)
  44. if err != nil {
  45. log.Info("query task error." + err.Error())
  46. return "", err
  47. } else {
  48. log.Info("query gpu train task.")
  49. }
  50. }
  51. uuid := uuid.NewV4()
  52. id := uuid.String()
  53. modelPath := id
  54. var lastNewModelId string
  55. var modelSize int64
  56. log.Info("find task name:" + aiTask.JobName)
  57. aimodels := models.QueryModelByName(name, aiTask.RepoID)
  58. if len(aimodels) > 0 {
  59. for _, model := range aimodels {
  60. if model.Version == version {
  61. return "", errors.New(ctx.Tr("repo.model.manage.create_error"))
  62. }
  63. if model.New == MODEL_LATEST {
  64. lastNewModelId = model.ID
  65. }
  66. }
  67. }
  68. cloudType := aiTask.Type
  69. modelSelectedFile := ctx.Query("modelSelectedFile")
  70. //download model zip //train type
  71. if aiTask.ComputeResource == models.NPUResource {
  72. cloudType = models.TypeCloudBrainTwo
  73. } else if aiTask.ComputeResource == models.GPUResource {
  74. cloudType = models.TypeCloudBrainOne
  75. }
  76. spec, err := resource.GetCloudbrainSpec(aiTask.ID)
  77. if err == nil {
  78. specJson, _ := json.Marshal(spec)
  79. aiTask.FlavorName = string(specJson)
  80. }
  81. accuracy := make(map[string]string)
  82. accuracy["F1"] = ""
  83. accuracy["Recall"] = ""
  84. accuracy["Accuracy"] = ""
  85. accuracy["Precision"] = ""
  86. accuracyJson, _ := json.Marshal(accuracy)
  87. log.Info("accuracyJson=" + string(accuracyJson))
  88. aiTask.ContainerIp = ""
  89. aiTaskJson, _ := json.Marshal(aiTask)
  90. isPrivate := ctx.QueryBool("isPrivate")
  91. model := &models.AiModelManage{
  92. ID: id,
  93. Version: version,
  94. VersionCount: len(aimodels) + 1,
  95. Label: label,
  96. Name: name,
  97. Description: description,
  98. New: MODEL_LATEST,
  99. Type: cloudType,
  100. Path: modelPath,
  101. Size: modelSize,
  102. AttachmentId: aiTask.Uuid,
  103. RepoId: aiTask.RepoID,
  104. UserId: ctx.User.ID,
  105. CodeBranch: aiTask.BranchName,
  106. CodeCommitID: aiTask.CommitID,
  107. Engine: int64(engine),
  108. TrainTaskInfo: string(aiTaskJson),
  109. Accuracy: string(accuracyJson),
  110. Status: STATUS_COPY_MODEL,
  111. IsPrivate: isPrivate,
  112. }
  113. err = models.SaveModelToDb(model)
  114. if err != nil {
  115. return "", err
  116. }
  117. if len(lastNewModelId) > 0 {
  118. //udpate status and version count
  119. models.ModifyModelNewProperty(lastNewModelId, MODEL_NOT_LATEST, 0)
  120. }
  121. var units []models.RepoUnit
  122. var deleteUnitTypes []models.UnitType
  123. units = append(units, models.RepoUnit{
  124. RepoID: ctx.Repo.Repository.ID,
  125. Type: models.UnitTypeModelManage,
  126. Config: &models.ModelManageConfig{
  127. EnableModelManage: true,
  128. },
  129. })
  130. deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeModelManage)
  131. models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes)
  132. go asyncToCopyModel(aiTask, id, modelSelectedFile)
  133. log.Info("save model end.")
  134. notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask)
  135. return id, nil
  136. }
  137. func asyncToCopyModel(aiTask *models.Cloudbrain, id string, modelSelectedFile string) {
  138. if aiTask.ComputeResource == models.NPUResource {
  139. modelPath, modelSize, err := downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile)
  140. if err != nil {
  141. updateStatus(id, 0, STATUS_ERROR, modelPath, err.Error())
  142. log.Info("download model from CloudBrainTwo faild." + err.Error())
  143. } else {
  144. updateStatus(id, modelSize, STATUS_FINISHED, modelPath, "")
  145. }
  146. } else if aiTask.ComputeResource == models.GPUResource {
  147. modelPath, modelSize, err := downloadModelFromCloudBrainOne(id, aiTask.JobName, "", aiTask.TrainUrl, modelSelectedFile)
  148. if err != nil {
  149. updateStatus(id, 0, STATUS_ERROR, modelPath, err.Error())
  150. log.Info("download model from CloudBrainOne faild." + err.Error())
  151. } else {
  152. updateStatus(id, modelSize, STATUS_FINISHED, modelPath, "")
  153. }
  154. }
  155. }
  156. func updateStatus(id string, modelSize int64, status int, modelPath string, statusDesc string) {
  157. if len(statusDesc) > 400 {
  158. statusDesc = statusDesc[0:400]
  159. }
  160. m, _ := models.QueryModelById(id)
  161. err := models.ModifyModelStatus(id, modelSize, status, modelPath, statusDesc)
  162. if err != nil {
  163. log.Info("update status error." + err.Error())
  164. }
  165. if m != nil {
  166. if modelSize > 0 && m.Size == 0 {
  167. go repository.ResetRepoModelNum(m.RepoId)
  168. }
  169. }
  170. }
  171. func SaveNewNameModel(ctx *context.Context) {
  172. if !ctx.Repo.CanWrite(models.UnitTypeModelManage) {
  173. ctx.Error(403, ctx.Tr("repo.model_noright"))
  174. return
  175. }
  176. name := ctx.Query("name")
  177. if name == "" {
  178. ctx.Error(500, fmt.Sprintf("name or version is null."))
  179. return
  180. }
  181. aimodels := models.QueryModelByName(name, ctx.Repo.Repository.ID)
  182. if len(aimodels) > 0 {
  183. ctx.Error(500, ctx.Tr("repo.model_rename"))
  184. return
  185. }
  186. SaveModel(ctx)
  187. ctx.Status(200)
  188. log.Info("save model end.")
  189. }
  190. func SaveLocalModel(ctx *context.Context) {
  191. if !ctx.Repo.CanWrite(models.UnitTypeModelManage) {
  192. ctx.Error(403, ctx.Tr("repo.model_noright"))
  193. return
  194. }
  195. re := map[string]string{
  196. "code": "-1",
  197. }
  198. log.Info("save SaveLocalModel start.")
  199. uuid := uuid.NewV4()
  200. id := uuid.String()
  201. name := ctx.Query("name")
  202. version := ctx.Query("version")
  203. if version == "" {
  204. version = "0.0.1"
  205. }
  206. label := ctx.Query("label")
  207. description := ctx.Query("description")
  208. engine := ctx.QueryInt("engine")
  209. taskType := ctx.QueryInt("type")
  210. isPrivate := ctx.QueryBool("isPrivate")
  211. modelActualPath := ""
  212. if taskType == models.TypeCloudBrainOne {
  213. destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(id) + "/"
  214. modelActualPath = setting.Attachment.Minio.Bucket + "/" + destKeyNamePrefix
  215. } else if taskType == models.TypeCloudBrainTwo {
  216. destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(id) + "/"
  217. modelActualPath = setting.Bucket + "/" + destKeyNamePrefix
  218. } else {
  219. re["msg"] = "type is error."
  220. ctx.JSON(200, re)
  221. return
  222. }
  223. var lastNewModelId string
  224. repoId := ctx.Repo.Repository.ID
  225. aimodels := models.QueryModelByName(name, repoId)
  226. if len(aimodels) > 0 {
  227. for _, model := range aimodels {
  228. if model.Version == version {
  229. re["msg"] = ctx.Tr("repo.model.manage.create_error")
  230. ctx.JSON(200, re)
  231. return
  232. }
  233. if model.New == MODEL_LATEST {
  234. lastNewModelId = model.ID
  235. }
  236. }
  237. }
  238. model := &models.AiModelManage{
  239. ID: id,
  240. Version: version,
  241. ModelType: MODEL_LOCAL_TYPE,
  242. VersionCount: len(aimodels) + 1,
  243. Label: label,
  244. Name: name,
  245. Description: description,
  246. New: MODEL_LATEST,
  247. Type: taskType,
  248. Path: modelActualPath,
  249. Size: 0,
  250. AttachmentId: "",
  251. RepoId: repoId,
  252. UserId: ctx.User.ID,
  253. Engine: int64(engine),
  254. TrainTaskInfo: "",
  255. Accuracy: "",
  256. Status: STATUS_FINISHED,
  257. IsPrivate: isPrivate,
  258. }
  259. err := models.SaveModelToDb(model)
  260. if err != nil {
  261. re["msg"] = err.Error()
  262. ctx.JSON(200, re)
  263. return
  264. }
  265. if len(lastNewModelId) > 0 {
  266. //udpate status and version count
  267. models.ModifyModelNewProperty(lastNewModelId, MODEL_NOT_LATEST, 0)
  268. }
  269. var units []models.RepoUnit
  270. var deleteUnitTypes []models.UnitType
  271. units = append(units, models.RepoUnit{
  272. RepoID: ctx.Repo.Repository.ID,
  273. Type: models.UnitTypeModelManage,
  274. Config: &models.ModelManageConfig{
  275. EnableModelManage: true,
  276. },
  277. })
  278. deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeModelManage)
  279. models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes)
  280. log.Info("save model end.")
  281. notification.NotifyOtherTask(ctx.User, ctx.Repo.Repository, id, name, models.ActionCreateNewModelTask)
  282. re["code"] = "0"
  283. re["id"] = id
  284. ctx.JSON(200, re)
  285. }
  286. func getSize(files []storage.FileInfo) int64 {
  287. var size int64
  288. for _, file := range files {
  289. size += file.Size
  290. }
  291. return size
  292. }
  293. func UpdateModelSize(modeluuid string) {
  294. model, err := models.QueryModelById(modeluuid)
  295. if err == nil {
  296. var size int64
  297. if model.Type == models.TypeCloudBrainOne {
  298. if strings.HasPrefix(model.Path, setting.Attachment.Minio.Bucket+"/"+Model_prefix) {
  299. files, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, model.Path[len(setting.Attachment.Minio.Bucket)+1:])
  300. if err != nil {
  301. log.Info("Failed to query model size from minio. id=" + modeluuid)
  302. }
  303. size = getSize(files)
  304. models.ModifyModelSize(modeluuid, size)
  305. }
  306. } else if model.Type == models.TypeCloudBrainTwo {
  307. if strings.HasPrefix(model.Path, setting.Bucket+"/"+Model_prefix) {
  308. files, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, model.Path[len(setting.Bucket)+1:])
  309. if err != nil {
  310. log.Info("Failed to query model size from obs. id=" + modeluuid)
  311. }
  312. size = getSize(files)
  313. models.ModifyModelSize(modeluuid, size)
  314. }
  315. }
  316. if model.Size == 0 && size > 0 {
  317. go repository.ResetRepoModelNum(model.RepoId)
  318. }
  319. } else {
  320. log.Info("not found model,uuid=" + modeluuid)
  321. }
  322. }
  323. func SaveModel(ctx *context.Context) {
  324. if !ctx.Repo.CanWrite(models.UnitTypeModelManage) {
  325. ctx.Error(403, ctx.Tr("repo.model_noright"))
  326. return
  327. }
  328. log.Info("save model start.")
  329. JobId := ctx.Query("jobId")
  330. VersionName := ctx.Query("versionName")
  331. name := ctx.Query("name")
  332. version := ctx.Query("version")
  333. label := ctx.Query("label")
  334. description := ctx.Query("description")
  335. engine := ctx.QueryInt("engine")
  336. modelSelectedFile := ctx.Query("modelSelectedFile")
  337. log.Info("engine=" + fmt.Sprint(engine) + " modelSelectedFile=" + modelSelectedFile)
  338. re := map[string]string{
  339. "code": "-1",
  340. }
  341. if JobId == "" || VersionName == "" {
  342. re["msg"] = "JobId or VersionName is null."
  343. ctx.JSON(200, re)
  344. return
  345. }
  346. if modelSelectedFile == "" {
  347. re["msg"] = "Not selected model file."
  348. ctx.JSON(200, re)
  349. return
  350. }
  351. if name == "" || version == "" {
  352. re["msg"] = "name or version is null."
  353. ctx.JSON(200, re)
  354. return
  355. }
  356. id, err := saveModelByParameters(JobId, VersionName, name, version, label, description, engine, ctx)
  357. if err != nil {
  358. log.Info("save model error." + err.Error())
  359. re["msg"] = err.Error()
  360. } else {
  361. re["code"] = "0"
  362. re["id"] = id
  363. }
  364. ctx.JSON(200, re)
  365. log.Info("save model end.")
  366. }
  367. func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir string, trainUrl string, modelSelectedFile string) (string, int64, error) {
  368. objectkey := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir), "/")
  369. if trainUrl != "" {
  370. objectkey = strings.Trim(trainUrl[len(setting.Bucket)+1:], "/")
  371. }
  372. prefix := objectkey + "/"
  373. filterFiles := strings.Split(modelSelectedFile, ";")
  374. Files := make([]string, 0)
  375. for _, shortFile := range filterFiles {
  376. Files = append(Files, prefix+shortFile)
  377. }
  378. totalSize := storage.ObsGetFilesSize(setting.Bucket, Files)
  379. if float64(totalSize) > setting.MaxModelSize*MODEL_MAX_SIZE {
  380. return "", 0, errors.New("Cannot create model, as model is exceed " + fmt.Sprint(setting.MaxModelSize) + "G.")
  381. }
  382. modelDbResult, err := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, objectkey, "")
  383. log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey)
  384. if err != nil {
  385. log.Info("get TrainJobListModel failed:", err)
  386. return "", 0, err
  387. }
  388. if len(modelDbResult) == 0 {
  389. return "", 0, errors.New("Cannot create model, as model is empty.")
  390. }
  391. destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/"
  392. size, err := storage.ObsCopyManyFile(setting.Bucket, prefix, setting.Bucket, destKeyNamePrefix, filterFiles)
  393. dataActualPath := setting.Bucket + "/" + destKeyNamePrefix
  394. return dataActualPath, size, nil
  395. }
  396. func downloadModelFromCloudBrainOne(modelUUID string, jobName string, parentDir string, trainUrl string, modelSelectedFile string) (string, int64, error) {
  397. modelActualPath := storage.GetMinioPath(jobName, "/model/")
  398. log.Info("modelActualPath=" + modelActualPath)
  399. modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/"
  400. destKeyNamePrefix := Model_prefix + models.AttachmentRelativePath(modelUUID) + "/"
  401. bucketName := setting.Attachment.Minio.Bucket
  402. log.Info("destKeyNamePrefix=" + destKeyNamePrefix + " modelSrcPrefix=" + modelSrcPrefix + " bucket=" + bucketName)
  403. filterFiles := strings.Split(modelSelectedFile, ";")
  404. Files := make([]string, 0)
  405. for _, shortFile := range filterFiles {
  406. Files = append(Files, modelSrcPrefix+shortFile)
  407. }
  408. totalSize := storage.MinioGetFilesSize(bucketName, Files)
  409. if float64(totalSize) > setting.MaxModelSize*MODEL_MAX_SIZE {
  410. return "", 0, errors.New("Cannot create model, as model is exceed " + fmt.Sprint(setting.MaxModelSize) + "G.")
  411. }
  412. size, err := storage.MinioCopyFiles(bucketName, modelSrcPrefix, destKeyNamePrefix, filterFiles)
  413. if err == nil {
  414. dataActualPath := bucketName + "/" + destKeyNamePrefix
  415. return dataActualPath, size, nil
  416. } else {
  417. return "", 0, nil
  418. }
  419. }
  420. func DeleteModelFile(ctx *context.Context) {
  421. log.Info("delete model start.")
  422. id := ctx.Query("id")
  423. fileName := ctx.Query("fileName")
  424. model, err := models.QueryModelById(id)
  425. if err == nil {
  426. var totalSize int64
  427. if model.ModelType == MODEL_LOCAL_TYPE {
  428. if model.Type == models.TypeCloudBrainOne {
  429. bucketName := setting.Attachment.Minio.Bucket
  430. objectName := model.Path[len(bucketName)+1:] + fileName
  431. log.Info("delete bucket=" + bucketName + " path=" + objectName)
  432. if strings.HasPrefix(model.Path, bucketName+"/"+Model_prefix) {
  433. totalSize = storage.MinioGetFilesSize(bucketName, []string{objectName})
  434. err := storage.Attachments.DeleteDir(objectName)
  435. if err != nil {
  436. log.Info("Failed to delete model. id=" + id)
  437. re := map[string]string{
  438. "code": "-1",
  439. }
  440. re["msg"] = err.Error()
  441. ctx.JSON(200, re)
  442. return
  443. } else {
  444. log.Info("delete minio file size is:" + fmt.Sprint(totalSize))
  445. models.ModifyModelSize(id, model.Size-totalSize)
  446. }
  447. }
  448. } else if model.Type == models.TypeCloudBrainTwo {
  449. bucketName := setting.Bucket
  450. objectName := model.Path[len(setting.Bucket)+1:] + fileName
  451. log.Info("delete bucket=" + setting.Bucket + " path=" + objectName)
  452. if strings.HasPrefix(model.Path, bucketName+"/"+Model_prefix) {
  453. totalSize = storage.ObsGetFilesSize(bucketName, []string{objectName})
  454. err := storage.ObsRemoveObject(bucketName, objectName)
  455. if err != nil {
  456. log.Info("Failed to delete model. id=" + id)
  457. re := map[string]string{
  458. "code": "-1",
  459. }
  460. re["msg"] = err.Error()
  461. ctx.JSON(200, re)
  462. return
  463. } else {
  464. log.Info("delete obs file size is:" + fmt.Sprint(totalSize))
  465. models.ModifyModelSize(id, model.Size-totalSize)
  466. }
  467. }
  468. }
  469. }
  470. if (model.Size - totalSize) <= 0 {
  471. go repository.ResetRepoModelNum(model.RepoId)
  472. }
  473. }
  474. ctx.JSON(200, map[string]string{
  475. "code": "0",
  476. })
  477. }
  478. func DeleteModel(ctx *context.Context) {
  479. log.Info("delete model start.")
  480. id := ctx.Query("id")
  481. err := deleteModelByID(ctx, id)
  482. if err != nil {
  483. re := map[string]string{
  484. "code": "-1",
  485. }
  486. re["msg"] = err.Error()
  487. ctx.JSON(200, re)
  488. } else {
  489. ctx.JSON(200, map[string]string{
  490. "code": "0",
  491. })
  492. }
  493. }
  494. func deleteModelByID(ctx *context.Context, id string) error {
  495. log.Info("delete model start. id=" + id)
  496. model, err := models.QueryModelById(id)
  497. if !isCanDelete(ctx, model.UserId) {
  498. return errors.New(ctx.Tr("repo.model_noright"))
  499. }
  500. if err == nil {
  501. if model.Type == models.TypeCloudBrainOne {
  502. bucketName := setting.Attachment.Minio.Bucket
  503. log.Info("bucket=" + bucketName + " path=" + model.Path)
  504. if strings.HasPrefix(model.Path, bucketName+"/"+Model_prefix) {
  505. err := storage.Attachments.DeleteDir(model.Path[len(bucketName)+1:])
  506. if err != nil {
  507. log.Info("Failed to delete model. id=" + id)
  508. return err
  509. }
  510. }
  511. } else if model.Type == models.TypeCloudBrainTwo {
  512. log.Info("bucket=" + setting.Bucket + " path=" + model.Path)
  513. if strings.HasPrefix(model.Path, setting.Bucket+"/"+Model_prefix) {
  514. err := storage.ObsRemoveObject(setting.Bucket, model.Path[len(setting.Bucket)+1:])
  515. if err != nil {
  516. log.Info("Failed to delete model. id=" + id)
  517. return err
  518. }
  519. }
  520. }
  521. err = models.DeleteModelById(id)
  522. if err == nil { //find a model to change new
  523. aimodels := models.QueryModelByName(model.Name, model.RepoId)
  524. if model.New == MODEL_LATEST {
  525. if len(aimodels) > 0 {
  526. //udpate status and version count
  527. models.ModifyModelNewProperty(aimodels[0].ID, MODEL_LATEST, len(aimodels))
  528. }
  529. } else {
  530. for _, tmpModel := range aimodels {
  531. if tmpModel.New == MODEL_LATEST {
  532. models.ModifyModelNewProperty(tmpModel.ID, MODEL_LATEST, len(aimodels))
  533. break
  534. }
  535. }
  536. }
  537. if model.Size > 0 {
  538. go repository.ResetRepoModelNum(model.RepoId)
  539. }
  540. }
  541. }
  542. return err
  543. }
  544. func DownloadMultiModelFile(ctx *context.Context) {
  545. log.Info("DownloadMultiModelFile start.")
  546. id := ctx.Query("id")
  547. log.Info("id=" + id)
  548. task, err := models.QueryModelById(id)
  549. if err != nil {
  550. log.Error("no such model!", err.Error())
  551. ctx.ServerError("no such model:", err)
  552. return
  553. }
  554. if !isCanDownload(ctx, task) {
  555. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  556. return
  557. }
  558. path := Model_prefix + models.AttachmentRelativePath(id) + "/"
  559. if task.Type == models.TypeCloudBrainTwo {
  560. downloadFromCloudBrainTwo(path, task, ctx, id)
  561. } else if task.Type == models.TypeCloudBrainOne {
  562. downloadFromCloudBrainOne(path, task, ctx, id)
  563. }
  564. }
  565. func MinioDownloadManyFile(path string, ctx *context.Context, returnFileName string, allFile []storage.FileInfo) {
  566. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(returnFileName))
  567. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  568. w := zip.NewWriter(ctx.Resp)
  569. defer w.Close()
  570. for _, oneFile := range allFile {
  571. if oneFile.IsDir {
  572. log.Info("zip dir name:" + oneFile.FileName)
  573. } else {
  574. log.Info("zip file name:" + oneFile.FileName)
  575. fDest, err := w.Create(oneFile.FileName)
  576. if err != nil {
  577. log.Info("create zip entry error, download file failed: %s\n", err.Error())
  578. ctx.ServerError("download file failed:", err)
  579. return
  580. }
  581. log.Info("minio file path=" + (path + oneFile.FileName))
  582. body, err := storage.Attachments.DownloadAFile(setting.Attachment.Minio.Bucket, path+oneFile.FileName)
  583. if err != nil {
  584. log.Info("download file failed: %s\n", err.Error())
  585. ctx.ServerError("download file failed:", err)
  586. return
  587. } else {
  588. defer body.Close()
  589. p := make([]byte, 1024)
  590. var readErr error
  591. var readCount int
  592. // 读取对象内容
  593. for {
  594. readCount, readErr = body.Read(p)
  595. if readCount > 0 {
  596. fDest.Write(p[:readCount])
  597. }
  598. if readErr != nil {
  599. break
  600. }
  601. }
  602. }
  603. }
  604. }
  605. }
  606. func downloadFromCloudBrainOne(path string, task *models.AiModelManage, ctx *context.Context, id string) {
  607. allFile, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, path)
  608. if err == nil {
  609. //count++
  610. models.ModifyModelDownloadCount(id)
  611. returnFileName := task.Name + "_" + task.Version + ".zip"
  612. MinioDownloadManyFile(path, ctx, returnFileName, allFile)
  613. } else {
  614. log.Info("error,msg=" + err.Error())
  615. ctx.ServerError("no file to download.", err)
  616. }
  617. }
  618. func ObsDownloadManyFile(path string, ctx *context.Context, returnFileName string, allFile []storage.FileInfo) {
  619. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(returnFileName))
  620. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  621. w := zip.NewWriter(ctx.Resp)
  622. defer w.Close()
  623. for _, oneFile := range allFile {
  624. if oneFile.IsDir {
  625. log.Info("zip dir name:" + oneFile.FileName)
  626. } else {
  627. log.Info("zip file name:" + oneFile.FileName)
  628. fDest, err := w.Create(oneFile.FileName)
  629. if err != nil {
  630. log.Info("create zip entry error, download file failed: %s\n", err.Error())
  631. ctx.ServerError("download file failed:", err)
  632. return
  633. }
  634. body, err := storage.ObsDownloadAFile(setting.Bucket, path+oneFile.FileName)
  635. if err != nil {
  636. log.Info("download file failed: %s\n", err.Error())
  637. ctx.ServerError("download file failed:", err)
  638. return
  639. } else {
  640. defer body.Close()
  641. p := make([]byte, 1024)
  642. var readErr error
  643. var readCount int
  644. // 读取对象内容
  645. for {
  646. readCount, readErr = body.Read(p)
  647. if readCount > 0 {
  648. fDest.Write(p[:readCount])
  649. }
  650. if readErr != nil {
  651. break
  652. }
  653. }
  654. }
  655. }
  656. }
  657. }
  658. func downloadFromCloudBrainTwo(path string, task *models.AiModelManage, ctx *context.Context, id string) {
  659. allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path)
  660. if err == nil {
  661. //count++
  662. models.ModifyModelDownloadCount(id)
  663. returnFileName := task.Name + "_" + task.Version + ".zip"
  664. ObsDownloadManyFile(path, ctx, returnFileName, allFile)
  665. } else {
  666. log.Info("error,msg=" + err.Error())
  667. ctx.ServerError("no file to download.", err)
  668. }
  669. }
  670. func QueryTrainJobVersionList(ctx *context.Context) {
  671. VersionListTasks, err := QueryTrainJobVersionListApi(ctx)
  672. if err != nil {
  673. ctx.JSON(200, nil)
  674. } else {
  675. ctx.JSON(200, VersionListTasks)
  676. }
  677. }
  678. func QueryTrainJobVersionListApi(ctx *context.Context) ([]*models.Cloudbrain, error) {
  679. log.Info("query train job version list. start.")
  680. JobID := ctx.Query("jobId")
  681. if JobID == "" {
  682. JobID = ctx.Query("JobId")
  683. }
  684. VersionListTasks, count, err := models.QueryModelTrainJobVersionList(JobID)
  685. log.Info("query return count=" + fmt.Sprint(count))
  686. return VersionListTasks, err
  687. }
  688. func QueryTrainJobList(ctx *context.Context) {
  689. VersionListTasks, err := QueryTrainJobListApi(ctx)
  690. if err != nil {
  691. ctx.JSON(200, nil)
  692. } else {
  693. ctx.JSON(200, VersionListTasks)
  694. }
  695. }
  696. func QueryTrainJobListApi(ctx *context.Context) ([]*models.Cloudbrain, error) {
  697. repoId := ctx.QueryInt64("repoId")
  698. VersionListTasks, count, err := models.QueryModelTrainJobList(repoId)
  699. log.Info("query return count=" + fmt.Sprint(count))
  700. return VersionListTasks, err
  701. }
  702. func QueryTrainModelFileById(ctx *context.Context) ([]storage.FileInfo, error) {
  703. JobID := ctx.Query("jobId")
  704. VersionListTasks, count, err := models.QueryModelTrainJobVersionList(JobID)
  705. if err == nil {
  706. if count == 1 {
  707. task := VersionListTasks[0]
  708. jobName := task.JobName
  709. taskType := task.Type
  710. VersionName := task.VersionName
  711. modelDbResult, err := getModelFromObjectSave(jobName, taskType, VersionName)
  712. return modelDbResult, err
  713. }
  714. }
  715. log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err)
  716. return nil, errors.New("Not found task.")
  717. }
  718. func getModelFromObjectSave(jobName string, taskType int, VersionName string) ([]storage.FileInfo, error) {
  719. if taskType == models.TypeCloudBrainTwo {
  720. objectkey := path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, VersionName) + "/"
  721. modelDbResult, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, objectkey)
  722. log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey)
  723. if err != nil {
  724. log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err)
  725. return nil, err
  726. } else {
  727. return modelDbResult, nil
  728. }
  729. } else if taskType == models.TypeCloudBrainOne {
  730. modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/"
  731. bucketName := setting.Attachment.Minio.Bucket
  732. modelDbResult, err := storage.GetAllObjectByBucketAndPrefixMinio(bucketName, modelSrcPrefix)
  733. if err != nil {
  734. log.Info("get TypeCloudBrainOne TrainJobListModel failed:", err)
  735. return nil, err
  736. } else {
  737. return modelDbResult, nil
  738. }
  739. }
  740. return nil, errors.New("Not support.")
  741. }
  742. func QueryTrainModelList(ctx *context.Context) {
  743. log.Info("query train job list. start.")
  744. jobName := ctx.Query("jobName")
  745. taskType := ctx.QueryInt("type")
  746. VersionName := ctx.Query("versionName")
  747. if VersionName == "" {
  748. VersionName = ctx.Query("VersionName")
  749. }
  750. modelDbResult, err := getModelFromObjectSave(jobName, taskType, VersionName)
  751. if err != nil {
  752. log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err)
  753. ctx.JSON(200, "")
  754. } else {
  755. ctx.JSON(200, modelDbResult)
  756. return
  757. }
  758. }
  759. func DownloadSingleModelFile(ctx *context.Context) {
  760. log.Info("DownloadSingleModelFile start.")
  761. id := ctx.Params(":ID")
  762. parentDir := ctx.Query("parentDir")
  763. fileName := ctx.Query("fileName")
  764. path := Model_prefix + models.AttachmentRelativePath(id) + "/" + parentDir + fileName
  765. task, err := models.QueryModelById(id)
  766. if err != nil {
  767. log.Error("no such model!", err.Error())
  768. ctx.ServerError("no such model:", err)
  769. return
  770. }
  771. if !isCanDownload(ctx, task) {
  772. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  773. return
  774. }
  775. if task.Type == models.TypeCloudBrainTwo {
  776. if setting.PROXYURL != "" {
  777. body, err := storage.ObsDownloadAFile(setting.Bucket, path)
  778. if err != nil {
  779. log.Info("download error.")
  780. } else {
  781. //count++
  782. models.ModifyModelDownloadCount(id)
  783. defer body.Close()
  784. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName)
  785. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  786. p := make([]byte, 1024)
  787. var readErr error
  788. var readCount int
  789. // 读取对象内容
  790. for {
  791. readCount, readErr = body.Read(p)
  792. if readCount > 0 {
  793. ctx.Resp.Write(p[:readCount])
  794. //fmt.Printf("%s", p[:readCount])
  795. }
  796. if readErr != nil {
  797. break
  798. }
  799. }
  800. }
  801. } else {
  802. url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path)
  803. if err != nil {
  804. log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
  805. ctx.ServerError("GetObsCreateSignedUrl", err)
  806. return
  807. }
  808. //count++
  809. models.ModifyModelDownloadCount(id)
  810. http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
  811. }
  812. } else if task.Type == models.TypeCloudBrainOne {
  813. log.Info("start to down load minio file.")
  814. url, err := storage.Attachments.PresignedGetURL(path, fileName)
  815. if err != nil {
  816. log.Error("Get minio get SignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
  817. ctx.ServerError("Get minio get SignedUrl failed", err)
  818. return
  819. }
  820. models.ModifyModelDownloadCount(id)
  821. http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
  822. }
  823. }
  824. func ShowModelInfo(ctx *context.Context) {
  825. ctx.Data["ID"] = ctx.Query("id")
  826. ctx.Data["name"] = ctx.Query("name")
  827. ctx.Data["isModelManage"] = true
  828. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  829. ctx.HTML(200, tplModelInfo)
  830. }
  831. func QueryModelById(ctx *context.Context) {
  832. id := ctx.Query("id")
  833. model, err := models.QueryModelById(id)
  834. if err == nil {
  835. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  836. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  837. model.IsCanDownload = isCanDownload(ctx, model)
  838. removeIpInfo(model)
  839. ctx.JSON(http.StatusOK, model)
  840. } else {
  841. ctx.JSON(http.StatusNotFound, nil)
  842. }
  843. }
  844. func ShowSingleModel(ctx *context.Context) {
  845. name := ctx.Query("name")
  846. log.Info("Show single ModelInfo start.name=" + name)
  847. models := models.QueryModelByName(name, ctx.Repo.Repository.ID)
  848. userIds := make([]int64, len(models))
  849. for i, model := range models {
  850. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  851. model.IsCanDownload = isCanDownload(ctx, model)
  852. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  853. userIds[i] = model.UserId
  854. }
  855. userNameMap := queryUserName(userIds)
  856. for _, model := range models {
  857. removeIpInfo(model)
  858. value := userNameMap[model.UserId]
  859. if value != nil {
  860. model.UserName = value.Name
  861. model.UserRelAvatarLink = value.RelAvatarLink()
  862. }
  863. }
  864. ctx.JSON(http.StatusOK, models)
  865. }
  866. func removeIpInfo(model *models.AiModelManage) {
  867. reg, _ := regexp.Compile(`[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}`)
  868. taskInfo := model.TrainTaskInfo
  869. taskInfo = reg.ReplaceAllString(taskInfo, "")
  870. model.TrainTaskInfo = taskInfo
  871. }
  872. func queryUserName(intSlice []int64) map[int64]*models.User {
  873. keys := make(map[int64]string)
  874. uniqueElements := []int64{}
  875. for _, entry := range intSlice {
  876. if _, value := keys[entry]; !value {
  877. keys[entry] = ""
  878. uniqueElements = append(uniqueElements, entry)
  879. }
  880. }
  881. result := make(map[int64]*models.User)
  882. userLists, err := models.GetUsersByIDs(uniqueElements)
  883. if err == nil {
  884. for _, user := range userLists {
  885. result[user.ID] = user
  886. }
  887. }
  888. return result
  889. }
  890. func ShowOneVersionOtherModel(ctx *context.Context) {
  891. repoId := ctx.Repo.Repository.ID
  892. name := ctx.Query("name")
  893. aimodels := models.QueryModelByName(name, repoId)
  894. userIds := make([]int64, len(aimodels))
  895. for i, model := range aimodels {
  896. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  897. model.IsCanDownload = isCanDownload(ctx, model)
  898. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  899. userIds[i] = model.UserId
  900. }
  901. userNameMap := queryUserName(userIds)
  902. for _, model := range aimodels {
  903. removeIpInfo(model)
  904. value := userNameMap[model.UserId]
  905. if value != nil {
  906. model.UserName = value.Name
  907. model.UserRelAvatarLink = value.RelAvatarLink()
  908. }
  909. }
  910. if len(aimodels) > 0 {
  911. ctx.JSON(200, aimodels[1:])
  912. } else {
  913. ctx.JSON(200, aimodels)
  914. }
  915. }
  916. func SetModelCount(ctx *context.Context) {
  917. isQueryPrivate := isQueryPrivateModel(ctx)
  918. repoId := ctx.Repo.Repository.ID
  919. Type := -1
  920. _, count, _ := models.QueryModel(&models.AiModelQueryOptions{
  921. ListOptions: models.ListOptions{
  922. Page: 1,
  923. PageSize: 2,
  924. },
  925. RepoID: repoId,
  926. Type: Type,
  927. New: MODEL_LATEST,
  928. IsOnlyThisRepo: true,
  929. Status: -1,
  930. IsQueryPrivate: isQueryPrivate,
  931. })
  932. ctx.Data["MODEL_COUNT"] = count
  933. }
  934. func ShowModelTemplate(ctx *context.Context) {
  935. ctx.Data["isModelManage"] = true
  936. repoId := ctx.Repo.Repository.ID
  937. SetModelCount(ctx)
  938. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  939. _, trainCount, _ := models.QueryModelTrainJobList(repoId)
  940. log.Info("query train count=" + fmt.Sprint(trainCount))
  941. ctx.Data["TRAIN_COUNT"] = trainCount
  942. ctx.HTML(200, tplModelManageIndex)
  943. }
  944. func isQueryRight(ctx *context.Context) bool {
  945. if ctx.Repo.Repository.IsPrivate {
  946. if ctx.Repo.CanRead(models.UnitTypeModelManage) || ctx.User.IsAdmin || ctx.Repo.IsAdmin() || ctx.Repo.IsOwner() {
  947. return true
  948. }
  949. return false
  950. } else {
  951. return true
  952. }
  953. }
  954. func isCanDownload(ctx *context.Context, task *models.AiModelManage) bool {
  955. if ctx.User == nil {
  956. return false
  957. }
  958. isCollaborator, err := ctx.Repo.Repository.IsCollaborator(ctx.User.ID)
  959. if err != nil {
  960. log.Info("query error.")
  961. }
  962. isTeamMember, err := ctx.Repo.Repository.IsInRepoTeam(ctx.User.ID)
  963. if err != nil {
  964. log.Info("query IsInRepoTeam error." + err.Error())
  965. }
  966. if ctx.User.IsAdmin || ctx.User.ID == task.UserId || isCollaborator || isTeamMember {
  967. return true
  968. }
  969. if ctx.Repo.IsOwner() {
  970. return true
  971. }
  972. if !task.IsPrivate {
  973. return true
  974. }
  975. return false
  976. }
  977. func isQueryPrivateModel(ctx *context.Context) bool {
  978. if ctx.User == nil {
  979. return false
  980. }
  981. isCollaborator, err := ctx.Repo.Repository.IsCollaborator(ctx.User.ID)
  982. if err != nil {
  983. log.Info("query IsCollaborator error." + err.Error())
  984. }
  985. isTeamMember, err := ctx.Repo.Repository.IsInRepoTeam(ctx.User.ID)
  986. if err != nil {
  987. log.Info("query IsInRepoTeam error." + err.Error())
  988. }
  989. if ctx.User.IsAdmin || isCollaborator || isTeamMember {
  990. return true
  991. }
  992. if ctx.Repo.IsOwner() {
  993. return true
  994. }
  995. return false
  996. }
  997. func isCanDelete(ctx *context.Context, modelUserId int64) bool {
  998. if ctx.User == nil {
  999. return false
  1000. }
  1001. if ctx.User.ID == modelUserId {
  1002. return true
  1003. }
  1004. return isAdminRight(ctx)
  1005. }
  1006. func isAdminRight(ctx *context.Context) bool {
  1007. if ctx.User.IsAdmin {
  1008. return true
  1009. }
  1010. if ctx.Repo.IsOwner() {
  1011. return true
  1012. }
  1013. permission, err := models.GetUserRepoPermission(ctx.Repo.Repository, ctx.User)
  1014. if err != nil {
  1015. log.Error("GetUserRepoPermission failed:%v", err.Error())
  1016. return false
  1017. }
  1018. if permission.AccessMode >= models.AccessModeAdmin {
  1019. return true
  1020. }
  1021. return false
  1022. }
  1023. func isOperModifyOrDelete(ctx *context.Context, modelUserId int64) bool {
  1024. if ctx.User == nil {
  1025. return false
  1026. }
  1027. if ctx.User.IsAdmin || ctx.User.ID == modelUserId {
  1028. return true
  1029. }
  1030. return isAdminRight(ctx)
  1031. }
  1032. func ShowModelPageInfo(ctx *context.Context) {
  1033. log.Info("ShowModelInfo start.")
  1034. if !isQueryRight(ctx) {
  1035. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  1036. return
  1037. }
  1038. page := ctx.QueryInt("page")
  1039. if page <= 0 {
  1040. page = 1
  1041. }
  1042. pageSize := ctx.QueryInt("pageSize")
  1043. if pageSize <= 0 {
  1044. pageSize = setting.UI.IssuePagingNum
  1045. }
  1046. isQueryPrivate := isQueryPrivateModel(ctx)
  1047. repoId := ctx.Repo.Repository.ID
  1048. Type := -1
  1049. modelResult, count, err := models.QueryModel(&models.AiModelQueryOptions{
  1050. ListOptions: models.ListOptions{
  1051. Page: page,
  1052. PageSize: pageSize,
  1053. },
  1054. RepoID: repoId,
  1055. Type: Type,
  1056. New: MODEL_LATEST,
  1057. IsOnlyThisRepo: true,
  1058. Status: -1,
  1059. IsQueryPrivate: isQueryPrivate,
  1060. })
  1061. if err != nil {
  1062. ctx.ServerError("Cloudbrain", err)
  1063. return
  1064. }
  1065. userIds := make([]int64, len(modelResult))
  1066. for i, model := range modelResult {
  1067. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  1068. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  1069. model.IsCanDownload = isCanDownload(ctx, model)
  1070. userIds[i] = model.UserId
  1071. }
  1072. userNameMap := queryUserName(userIds)
  1073. for _, model := range modelResult {
  1074. removeIpInfo(model)
  1075. value := userNameMap[model.UserId]
  1076. if value != nil {
  1077. model.UserName = value.Name
  1078. model.UserRelAvatarLink = value.RelAvatarLink()
  1079. }
  1080. }
  1081. mapInterface := make(map[string]interface{})
  1082. mapInterface["data"] = modelResult
  1083. mapInterface["count"] = count
  1084. ctx.JSON(http.StatusOK, mapInterface)
  1085. }
  1086. func ModifyModel(id string, description string) error {
  1087. err := models.ModifyModelDescription(id, description)
  1088. if err == nil {
  1089. log.Info("modify success.")
  1090. } else {
  1091. log.Info("Failed to modify.id=" + id + " desc=" + description + " error:" + err.Error())
  1092. }
  1093. return err
  1094. }
  1095. func ModifyModelPrivate(ctx *context.Context) {
  1096. id := ctx.Query("id")
  1097. isPrivate := ctx.QueryBool("isPrivate")
  1098. re := map[string]string{
  1099. "code": "-1",
  1100. }
  1101. task, err := models.QueryModelById(id)
  1102. if err != nil || task == nil {
  1103. re["msg"] = err.Error()
  1104. log.Error("no such model!", err.Error())
  1105. ctx.JSON(200, re)
  1106. return
  1107. }
  1108. if !isOperModifyOrDelete(ctx, task.UserId) {
  1109. re["msg"] = "No right to operation."
  1110. ctx.JSON(200, re)
  1111. return
  1112. }
  1113. err = models.ModifyModelPrivate(id, isPrivate)
  1114. if err == nil {
  1115. re["code"] = "0"
  1116. ctx.JSON(200, re)
  1117. log.Info("modify success.")
  1118. } else {
  1119. re["msg"] = err.Error()
  1120. ctx.JSON(200, re)
  1121. log.Info("Failed to modify.id=" + id + " isprivate=" + fmt.Sprint(isPrivate) + " error:" + err.Error())
  1122. }
  1123. }
  1124. func ModifyModelInfo(ctx *context.Context) {
  1125. log.Info("modify model start.")
  1126. id := ctx.Query("id")
  1127. re := map[string]string{
  1128. "code": "-1",
  1129. }
  1130. task, err := models.QueryModelById(id)
  1131. if err != nil {
  1132. re["msg"] = err.Error()
  1133. log.Error("no such model!", err.Error())
  1134. ctx.JSON(200, re)
  1135. return
  1136. }
  1137. if !isOperModifyOrDelete(ctx, task.UserId) {
  1138. re["msg"] = "No right to operation."
  1139. ctx.JSON(200, re)
  1140. return
  1141. }
  1142. if task.ModelType == MODEL_LOCAL_TYPE {
  1143. name := ctx.Query("name")
  1144. label := ctx.Query("label")
  1145. description := ctx.Query("description")
  1146. engine := ctx.QueryInt("engine")
  1147. isPrivate := ctx.QueryBool("isPrivate")
  1148. aimodels := models.QueryModelByName(name, task.RepoId)
  1149. if aimodels != nil && len(aimodels) > 0 {
  1150. if len(aimodels) == 1 {
  1151. if aimodels[0].ID != task.ID {
  1152. re["msg"] = ctx.Tr("repo.model.manage.create_error")
  1153. ctx.JSON(200, re)
  1154. return
  1155. }
  1156. } else {
  1157. re["msg"] = ctx.Tr("repo.model.manage.create_error")
  1158. ctx.JSON(200, re)
  1159. return
  1160. }
  1161. }
  1162. err = models.ModifyLocalModel(id, name, label, description, engine, isPrivate)
  1163. } else {
  1164. label := ctx.Query("label")
  1165. description := ctx.Query("description")
  1166. engine := task.Engine
  1167. name := task.Name
  1168. err = models.ModifyLocalModel(id, name, label, description, int(engine), task.IsPrivate)
  1169. }
  1170. if err != nil {
  1171. re["msg"] = err.Error()
  1172. ctx.JSON(200, re)
  1173. return
  1174. } else {
  1175. re["code"] = "0"
  1176. ctx.JSON(200, re)
  1177. }
  1178. }
  1179. func QueryModelListForPredict(ctx *context.Context) {
  1180. repoId := ctx.Repo.Repository.ID
  1181. page := ctx.QueryInt("page")
  1182. if page <= 0 {
  1183. page = -1
  1184. }
  1185. pageSize := ctx.QueryInt("pageSize")
  1186. if pageSize <= 0 {
  1187. pageSize = -1
  1188. }
  1189. isQueryPrivate := isQueryPrivateModel(ctx)
  1190. //IsOnlyThisRepo := ctx.QueryBool("isOnlyThisRepo")
  1191. modelResult, count, err := models.QueryModel(&models.AiModelQueryOptions{
  1192. ListOptions: models.ListOptions{
  1193. Page: page,
  1194. PageSize: pageSize,
  1195. },
  1196. RepoID: repoId,
  1197. Type: ctx.QueryInt("type"),
  1198. New: -1,
  1199. Status: 0,
  1200. IsOnlyThisRepo: true,
  1201. IsQueryPrivate: isQueryPrivate,
  1202. })
  1203. if err != nil {
  1204. ctx.ServerError("Cloudbrain", err)
  1205. return
  1206. }
  1207. log.Info("query return count=" + fmt.Sprint(count))
  1208. nameList := make([]string, 0)
  1209. nameMap := make(map[string][]*models.AiModelManage)
  1210. for _, model := range modelResult {
  1211. model.TrainTaskInfo = ""
  1212. model.Accuracy = ""
  1213. //removeIpInfo(model)
  1214. if _, value := nameMap[model.Name]; !value {
  1215. models := make([]*models.AiModelManage, 0)
  1216. models = append(models, model)
  1217. nameMap[model.Name] = models
  1218. nameList = append(nameList, model.Name)
  1219. } else {
  1220. nameMap[model.Name] = append(nameMap[model.Name], model)
  1221. }
  1222. }
  1223. mapInterface := make(map[string]interface{})
  1224. mapInterface["nameList"] = nameList
  1225. mapInterface["nameMap"] = nameMap
  1226. ctx.JSON(http.StatusOK, mapInterface)
  1227. }
  1228. func QueryModelFileForPredict(ctx *context.Context) {
  1229. id := ctx.Query("id")
  1230. if id == "" {
  1231. id = ctx.Query("ID")
  1232. }
  1233. ctx.JSON(http.StatusOK, QueryModelFileByID(id))
  1234. }
  1235. func QueryModelFileByID(id string) []storage.FileInfo {
  1236. model, err := models.QueryModelById(id)
  1237. if err != nil {
  1238. log.Error("no such model!", err.Error())
  1239. return nil
  1240. }
  1241. return QueryModelFileByModel(model)
  1242. }
  1243. func QueryModelFileByModel(model *models.AiModelManage) []storage.FileInfo {
  1244. if model.Type == models.TypeCloudBrainTwo {
  1245. prefix := model.Path[len(setting.Bucket)+1:]
  1246. fileinfos, _ := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix)
  1247. return fileinfos
  1248. } else if model.Type == models.TypeCloudBrainOne {
  1249. prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:]
  1250. fileinfos, _ := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, prefix)
  1251. return fileinfos
  1252. }
  1253. return nil
  1254. }
  1255. func QueryOneLevelModelFile(ctx *context.Context) {
  1256. id := ctx.Query("id")
  1257. if id == "" {
  1258. id = ctx.Query("ID")
  1259. }
  1260. parentDir := ctx.Query("parentDir")
  1261. model, err := models.QueryModelById(id)
  1262. if err != nil {
  1263. log.Error("no such model!", err.Error())
  1264. ctx.ServerError("no such model:", err)
  1265. return
  1266. }
  1267. if model.Type == models.TypeCloudBrainTwo {
  1268. log.Info("TypeCloudBrainTwo list model file.")
  1269. prefix := model.Path[len(setting.Bucket)+1:]
  1270. fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir)
  1271. if fileinfos == nil {
  1272. fileinfos = make([]storage.FileInfo, 0)
  1273. }
  1274. ctx.JSON(http.StatusOK, fileinfos)
  1275. } else if model.Type == models.TypeCloudBrainOne {
  1276. log.Info("TypeCloudBrainOne list model file.")
  1277. prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:]
  1278. fileinfos, _ := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, parentDir)
  1279. if fileinfos == nil {
  1280. fileinfos = make([]storage.FileInfo, 0)
  1281. }
  1282. ctx.JSON(http.StatusOK, fileinfos)
  1283. }
  1284. }
  1285. func CreateLocalModel(ctx *context.Context) {
  1286. ctx.Data["isModelManage"] = true
  1287. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  1288. ctx.HTML(200, tplCreateLocalModelInfo)
  1289. }
  1290. func CreateLocalModelForUpload(ctx *context.Context) {
  1291. ctx.Data["uuid"] = ctx.Query("uuid")
  1292. ctx.Data["isModelManage"] = true
  1293. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  1294. ctx.Data["max_model_size"] = setting.MaxModelSize * MODEL_MAX_SIZE
  1295. ctx.HTML(200, tplCreateLocalForUploadModelInfo)
  1296. }
  1297. func CreateOnlineModel(ctx *context.Context) {
  1298. ctx.Data["isModelManage"] = true
  1299. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  1300. ctx.HTML(200, tplCreateOnlineModelInfo)
  1301. }