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 41 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
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
3 years ago
3 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. package repo
  2. import (
  3. "archive/zip"
  4. "code.gitea.io/gitea/services/repository"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "net/http"
  9. "net/url"
  10. "path"
  11. "regexp"
  12. "strings"
  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. log.Info("query train job version list. start.")
  672. JobID := ctx.Query("jobId")
  673. if JobID == "" {
  674. JobID = ctx.Query("JobId")
  675. }
  676. VersionListTasks, count, err := models.QueryModelTrainJobVersionList(JobID)
  677. log.Info("query return count=" + fmt.Sprint(count))
  678. if err != nil {
  679. ctx.ServerError("QueryTrainJobList:", err)
  680. } else {
  681. ctx.JSON(200, VersionListTasks)
  682. }
  683. }
  684. func QueryTrainJobList(ctx *context.Context) {
  685. log.Info("query train job list. start.")
  686. repoId := ctx.QueryInt64("repoId")
  687. VersionListTasks, count, err := models.QueryModelTrainJobList(repoId)
  688. log.Info("query return count=" + fmt.Sprint(count))
  689. if err != nil {
  690. ctx.ServerError("QueryTrainJobList:", err)
  691. } else {
  692. ctx.JSON(200, VersionListTasks)
  693. }
  694. }
  695. func QueryTrainModelFileById(ctx *context.Context) ([]storage.FileInfo, error) {
  696. JobID := ctx.Query("jobId")
  697. VersionListTasks, count, err := models.QueryModelTrainJobVersionList(JobID)
  698. if err == nil {
  699. if count == 1 {
  700. task := VersionListTasks[0]
  701. jobName := task.JobName
  702. taskType := task.Type
  703. VersionName := task.VersionName
  704. modelDbResult, err := getModelFromObjectSave(jobName, taskType, VersionName)
  705. return modelDbResult, err
  706. }
  707. }
  708. log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err)
  709. return nil, errors.New("Not found task.")
  710. }
  711. func getModelFromObjectSave(jobName string, taskType int, VersionName string) ([]storage.FileInfo, error) {
  712. if taskType == models.TypeCloudBrainTwo {
  713. objectkey := path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, VersionName) + "/"
  714. modelDbResult, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, objectkey)
  715. log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey)
  716. if err != nil {
  717. log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err)
  718. return nil, err
  719. } else {
  720. return modelDbResult, nil
  721. }
  722. } else if taskType == models.TypeCloudBrainOne {
  723. modelSrcPrefix := setting.CBCodePathPrefix + jobName + "/model/"
  724. bucketName := setting.Attachment.Minio.Bucket
  725. modelDbResult, err := storage.GetAllObjectByBucketAndPrefixMinio(bucketName, modelSrcPrefix)
  726. if err != nil {
  727. log.Info("get TypeCloudBrainOne TrainJobListModel failed:", err)
  728. return nil, err
  729. } else {
  730. return modelDbResult, nil
  731. }
  732. }
  733. return nil, errors.New("Not support.")
  734. }
  735. func QueryTrainModelList(ctx *context.Context) {
  736. log.Info("query train job list. start.")
  737. jobName := ctx.Query("jobName")
  738. taskType := ctx.QueryInt("type")
  739. VersionName := ctx.Query("versionName")
  740. if VersionName == "" {
  741. VersionName = ctx.Query("VersionName")
  742. }
  743. modelDbResult, err := getModelFromObjectSave(jobName, taskType, VersionName)
  744. if err != nil {
  745. log.Info("get TypeCloudBrainTwo TrainJobListModel failed:", err)
  746. ctx.JSON(200, "")
  747. } else {
  748. ctx.JSON(200, modelDbResult)
  749. return
  750. }
  751. }
  752. func DownloadSingleModelFile(ctx *context.Context) {
  753. log.Info("DownloadSingleModelFile start.")
  754. id := ctx.Params(":ID")
  755. parentDir := ctx.Query("parentDir")
  756. fileName := ctx.Query("fileName")
  757. path := Model_prefix + models.AttachmentRelativePath(id) + "/" + parentDir + fileName
  758. task, err := models.QueryModelById(id)
  759. if err != nil {
  760. log.Error("no such model!", err.Error())
  761. ctx.ServerError("no such model:", err)
  762. return
  763. }
  764. if !isCanDownload(ctx, task) {
  765. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  766. return
  767. }
  768. if task.Type == models.TypeCloudBrainTwo {
  769. if setting.PROXYURL != "" {
  770. body, err := storage.ObsDownloadAFile(setting.Bucket, path)
  771. if err != nil {
  772. log.Info("download error.")
  773. } else {
  774. //count++
  775. models.ModifyModelDownloadCount(id)
  776. defer body.Close()
  777. ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+fileName)
  778. ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
  779. p := make([]byte, 1024)
  780. var readErr error
  781. var readCount int
  782. // 读取对象内容
  783. for {
  784. readCount, readErr = body.Read(p)
  785. if readCount > 0 {
  786. ctx.Resp.Write(p[:readCount])
  787. //fmt.Printf("%s", p[:readCount])
  788. }
  789. if readErr != nil {
  790. break
  791. }
  792. }
  793. }
  794. } else {
  795. url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, path)
  796. if err != nil {
  797. log.Error("GetObsCreateSignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
  798. ctx.ServerError("GetObsCreateSignedUrl", err)
  799. return
  800. }
  801. //count++
  802. models.ModifyModelDownloadCount(id)
  803. http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
  804. }
  805. } else if task.Type == models.TypeCloudBrainOne {
  806. log.Info("start to down load minio file.")
  807. url, err := storage.Attachments.PresignedGetURL(path, fileName)
  808. if err != nil {
  809. log.Error("Get minio get SignedUrl failed: %v", err.Error(), ctx.Data["msgID"])
  810. ctx.ServerError("Get minio get SignedUrl failed", err)
  811. return
  812. }
  813. models.ModifyModelDownloadCount(id)
  814. http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently)
  815. }
  816. }
  817. func ShowModelInfo(ctx *context.Context) {
  818. ctx.Data["ID"] = ctx.Query("id")
  819. ctx.Data["name"] = ctx.Query("name")
  820. ctx.Data["isModelManage"] = true
  821. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  822. ctx.HTML(200, tplModelInfo)
  823. }
  824. func QueryModelById(ctx *context.Context) {
  825. id := ctx.Query("id")
  826. model, err := models.QueryModelById(id)
  827. if err == nil {
  828. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  829. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  830. model.IsCanDownload = isCanDownload(ctx, model)
  831. removeIpInfo(model)
  832. ctx.JSON(http.StatusOK, model)
  833. } else {
  834. ctx.JSON(http.StatusNotFound, nil)
  835. }
  836. }
  837. func ShowSingleModel(ctx *context.Context) {
  838. name := ctx.Query("name")
  839. log.Info("Show single ModelInfo start.name=" + name)
  840. models := models.QueryModelByName(name, ctx.Repo.Repository.ID)
  841. userIds := make([]int64, len(models))
  842. for i, model := range models {
  843. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  844. model.IsCanDownload = isCanDownload(ctx, model)
  845. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  846. userIds[i] = model.UserId
  847. }
  848. userNameMap := queryUserName(userIds)
  849. for _, model := range models {
  850. removeIpInfo(model)
  851. value := userNameMap[model.UserId]
  852. if value != nil {
  853. model.UserName = value.Name
  854. model.UserRelAvatarLink = value.RelAvatarLink()
  855. }
  856. }
  857. ctx.JSON(http.StatusOK, models)
  858. }
  859. func removeIpInfo(model *models.AiModelManage) {
  860. reg, _ := regexp.Compile(`[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}`)
  861. taskInfo := model.TrainTaskInfo
  862. taskInfo = reg.ReplaceAllString(taskInfo, "")
  863. model.TrainTaskInfo = taskInfo
  864. }
  865. func queryUserName(intSlice []int64) map[int64]*models.User {
  866. keys := make(map[int64]string)
  867. uniqueElements := []int64{}
  868. for _, entry := range intSlice {
  869. if _, value := keys[entry]; !value {
  870. keys[entry] = ""
  871. uniqueElements = append(uniqueElements, entry)
  872. }
  873. }
  874. result := make(map[int64]*models.User)
  875. userLists, err := models.GetUsersByIDs(uniqueElements)
  876. if err == nil {
  877. for _, user := range userLists {
  878. result[user.ID] = user
  879. }
  880. }
  881. return result
  882. }
  883. func ShowOneVersionOtherModel(ctx *context.Context) {
  884. repoId := ctx.Repo.Repository.ID
  885. name := ctx.Query("name")
  886. aimodels := models.QueryModelByName(name, repoId)
  887. userIds := make([]int64, len(aimodels))
  888. for i, model := range aimodels {
  889. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  890. model.IsCanDownload = isCanDownload(ctx, model)
  891. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  892. userIds[i] = model.UserId
  893. }
  894. userNameMap := queryUserName(userIds)
  895. for _, model := range aimodels {
  896. removeIpInfo(model)
  897. value := userNameMap[model.UserId]
  898. if value != nil {
  899. model.UserName = value.Name
  900. model.UserRelAvatarLink = value.RelAvatarLink()
  901. }
  902. }
  903. if len(aimodels) > 0 {
  904. ctx.JSON(200, aimodels[1:])
  905. } else {
  906. ctx.JSON(200, aimodels)
  907. }
  908. }
  909. func SetModelCount(ctx *context.Context) {
  910. isQueryPrivate := isQueryPrivateModel(ctx)
  911. repoId := ctx.Repo.Repository.ID
  912. Type := -1
  913. _, count, _ := models.QueryModel(&models.AiModelQueryOptions{
  914. ListOptions: models.ListOptions{
  915. Page: 1,
  916. PageSize: 2,
  917. },
  918. RepoID: repoId,
  919. Type: Type,
  920. New: MODEL_LATEST,
  921. IsOnlyThisRepo: true,
  922. Status: -1,
  923. IsQueryPrivate: isQueryPrivate,
  924. })
  925. ctx.Data["MODEL_COUNT"] = count
  926. }
  927. func ShowModelTemplate(ctx *context.Context) {
  928. ctx.Data["isModelManage"] = true
  929. repoId := ctx.Repo.Repository.ID
  930. SetModelCount(ctx)
  931. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  932. _, trainCount, _ := models.QueryModelTrainJobList(repoId)
  933. log.Info("query train count=" + fmt.Sprint(trainCount))
  934. ctx.Data["TRAIN_COUNT"] = trainCount
  935. ctx.HTML(200, tplModelManageIndex)
  936. }
  937. func isQueryRight(ctx *context.Context) bool {
  938. if ctx.Repo.Repository.IsPrivate {
  939. if ctx.Repo.CanRead(models.UnitTypeModelManage) || ctx.User.IsAdmin || ctx.Repo.IsAdmin() || ctx.Repo.IsOwner() {
  940. return true
  941. }
  942. return false
  943. } else {
  944. return true
  945. }
  946. }
  947. func isCanDownload(ctx *context.Context, task *models.AiModelManage) bool {
  948. if ctx.User == nil {
  949. return false
  950. }
  951. isCollaborator, err := ctx.Repo.Repository.IsCollaborator(ctx.User.ID)
  952. if err != nil {
  953. log.Info("query error.")
  954. }
  955. isTeamMember, err := ctx.Repo.Repository.IsInRepoTeam(ctx.User.ID)
  956. if err != nil {
  957. log.Info("query IsInRepoTeam error." + err.Error())
  958. }
  959. if ctx.User.IsAdmin || ctx.User.ID == task.UserId || isCollaborator || isTeamMember {
  960. return true
  961. }
  962. if ctx.Repo.IsOwner() {
  963. return true
  964. }
  965. if !task.IsPrivate {
  966. return true
  967. }
  968. return false
  969. }
  970. func isQueryPrivateModel(ctx *context.Context) bool {
  971. if ctx.User == nil {
  972. return false
  973. }
  974. isCollaborator, err := ctx.Repo.Repository.IsCollaborator(ctx.User.ID)
  975. if err != nil {
  976. log.Info("query IsCollaborator error." + err.Error())
  977. }
  978. isTeamMember, err := ctx.Repo.Repository.IsInRepoTeam(ctx.User.ID)
  979. if err != nil {
  980. log.Info("query IsInRepoTeam error." + err.Error())
  981. }
  982. if ctx.User.IsAdmin || isCollaborator || isTeamMember {
  983. return true
  984. }
  985. if ctx.Repo.IsOwner() {
  986. return true
  987. }
  988. return false
  989. }
  990. func isCanDelete(ctx *context.Context, modelUserId int64) bool {
  991. if ctx.User == nil {
  992. return false
  993. }
  994. if ctx.User.ID == modelUserId {
  995. return true
  996. }
  997. return isAdminRight(ctx)
  998. }
  999. func isAdminRight(ctx *context.Context) bool {
  1000. if ctx.User.IsAdmin {
  1001. return true
  1002. }
  1003. if ctx.Repo.IsOwner() {
  1004. return true
  1005. }
  1006. permission, err := models.GetUserRepoPermission(ctx.Repo.Repository, ctx.User)
  1007. if err != nil {
  1008. log.Error("GetUserRepoPermission failed:%v", err.Error())
  1009. return false
  1010. }
  1011. if permission.AccessMode >= models.AccessModeAdmin {
  1012. return true
  1013. }
  1014. return false
  1015. }
  1016. func isOperModifyOrDelete(ctx *context.Context, modelUserId int64) bool {
  1017. if ctx.User == nil {
  1018. return false
  1019. }
  1020. if ctx.User.IsAdmin || ctx.User.ID == modelUserId {
  1021. return true
  1022. }
  1023. return isAdminRight(ctx)
  1024. }
  1025. func ShowModelPageInfo(ctx *context.Context) {
  1026. log.Info("ShowModelInfo start.")
  1027. if !isQueryRight(ctx) {
  1028. ctx.NotFound(ctx.Req.URL.RequestURI(), nil)
  1029. return
  1030. }
  1031. page := ctx.QueryInt("page")
  1032. if page <= 0 {
  1033. page = 1
  1034. }
  1035. pageSize := ctx.QueryInt("pageSize")
  1036. if pageSize <= 0 {
  1037. pageSize = setting.UI.IssuePagingNum
  1038. }
  1039. isQueryPrivate := isQueryPrivateModel(ctx)
  1040. repoId := ctx.Repo.Repository.ID
  1041. Type := -1
  1042. modelResult, count, err := models.QueryModel(&models.AiModelQueryOptions{
  1043. ListOptions: models.ListOptions{
  1044. Page: page,
  1045. PageSize: pageSize,
  1046. },
  1047. RepoID: repoId,
  1048. Type: Type,
  1049. New: MODEL_LATEST,
  1050. IsOnlyThisRepo: true,
  1051. Status: -1,
  1052. IsQueryPrivate: isQueryPrivate,
  1053. })
  1054. if err != nil {
  1055. ctx.ServerError("Cloudbrain", err)
  1056. return
  1057. }
  1058. userIds := make([]int64, len(modelResult))
  1059. for i, model := range modelResult {
  1060. model.IsCanOper = isOperModifyOrDelete(ctx, model.UserId)
  1061. model.IsCanDelete = isCanDelete(ctx, model.UserId)
  1062. model.IsCanDownload = isCanDownload(ctx, model)
  1063. userIds[i] = model.UserId
  1064. }
  1065. userNameMap := queryUserName(userIds)
  1066. for _, model := range modelResult {
  1067. removeIpInfo(model)
  1068. value := userNameMap[model.UserId]
  1069. if value != nil {
  1070. model.UserName = value.Name
  1071. model.UserRelAvatarLink = value.RelAvatarLink()
  1072. }
  1073. }
  1074. mapInterface := make(map[string]interface{})
  1075. mapInterface["data"] = modelResult
  1076. mapInterface["count"] = count
  1077. ctx.JSON(http.StatusOK, mapInterface)
  1078. }
  1079. func ModifyModel(id string, description string) error {
  1080. err := models.ModifyModelDescription(id, description)
  1081. if err == nil {
  1082. log.Info("modify success.")
  1083. } else {
  1084. log.Info("Failed to modify.id=" + id + " desc=" + description + " error:" + err.Error())
  1085. }
  1086. return err
  1087. }
  1088. func ModifyModelPrivate(ctx *context.Context) {
  1089. id := ctx.Query("id")
  1090. isPrivate := ctx.QueryBool("isPrivate")
  1091. re := map[string]string{
  1092. "code": "-1",
  1093. }
  1094. task, err := models.QueryModelById(id)
  1095. if err != nil || task == nil {
  1096. re["msg"] = err.Error()
  1097. log.Error("no such model!", err.Error())
  1098. ctx.JSON(200, re)
  1099. return
  1100. }
  1101. if !isOperModifyOrDelete(ctx, task.UserId) {
  1102. re["msg"] = "No right to operation."
  1103. ctx.JSON(200, re)
  1104. return
  1105. }
  1106. err = models.ModifyModelPrivate(id, isPrivate)
  1107. if err == nil {
  1108. re["code"] = "0"
  1109. ctx.JSON(200, re)
  1110. log.Info("modify success.")
  1111. } else {
  1112. re["msg"] = err.Error()
  1113. ctx.JSON(200, re)
  1114. log.Info("Failed to modify.id=" + id + " isprivate=" + fmt.Sprint(isPrivate) + " error:" + err.Error())
  1115. }
  1116. }
  1117. func ModifyModelInfo(ctx *context.Context) {
  1118. log.Info("modify model start.")
  1119. id := ctx.Query("id")
  1120. re := map[string]string{
  1121. "code": "-1",
  1122. }
  1123. task, err := models.QueryModelById(id)
  1124. if err != nil {
  1125. re["msg"] = err.Error()
  1126. log.Error("no such model!", err.Error())
  1127. ctx.JSON(200, re)
  1128. return
  1129. }
  1130. if !isOperModifyOrDelete(ctx, task.UserId) {
  1131. re["msg"] = "No right to operation."
  1132. ctx.JSON(200, re)
  1133. return
  1134. }
  1135. if task.ModelType == MODEL_LOCAL_TYPE {
  1136. name := ctx.Query("name")
  1137. label := ctx.Query("label")
  1138. description := ctx.Query("description")
  1139. engine := ctx.QueryInt("engine")
  1140. isPrivate := ctx.QueryBool("isPrivate")
  1141. aimodels := models.QueryModelByName(name, task.RepoId)
  1142. if aimodels != nil && len(aimodels) > 0 {
  1143. if len(aimodels) == 1 {
  1144. if aimodels[0].ID != task.ID {
  1145. re["msg"] = ctx.Tr("repo.model.manage.create_error")
  1146. ctx.JSON(200, re)
  1147. return
  1148. }
  1149. } else {
  1150. re["msg"] = ctx.Tr("repo.model.manage.create_error")
  1151. ctx.JSON(200, re)
  1152. return
  1153. }
  1154. }
  1155. err = models.ModifyLocalModel(id, name, label, description, engine, isPrivate)
  1156. } else {
  1157. label := ctx.Query("label")
  1158. description := ctx.Query("description")
  1159. engine := task.Engine
  1160. name := task.Name
  1161. err = models.ModifyLocalModel(id, name, label, description, int(engine), task.IsPrivate)
  1162. }
  1163. if err != nil {
  1164. re["msg"] = err.Error()
  1165. ctx.JSON(200, re)
  1166. return
  1167. } else {
  1168. re["code"] = "0"
  1169. ctx.JSON(200, re)
  1170. }
  1171. }
  1172. func QueryModelListForPredict(ctx *context.Context) {
  1173. repoId := ctx.Repo.Repository.ID
  1174. page := ctx.QueryInt("page")
  1175. if page <= 0 {
  1176. page = -1
  1177. }
  1178. pageSize := ctx.QueryInt("pageSize")
  1179. if pageSize <= 0 {
  1180. pageSize = -1
  1181. }
  1182. isQueryPrivate := isQueryPrivateModel(ctx)
  1183. //IsOnlyThisRepo := ctx.QueryBool("isOnlyThisRepo")
  1184. modelResult, count, err := models.QueryModel(&models.AiModelQueryOptions{
  1185. ListOptions: models.ListOptions{
  1186. Page: page,
  1187. PageSize: pageSize,
  1188. },
  1189. RepoID: repoId,
  1190. Type: ctx.QueryInt("type"),
  1191. New: -1,
  1192. Status: 0,
  1193. IsOnlyThisRepo: true,
  1194. IsQueryPrivate: isQueryPrivate,
  1195. })
  1196. if err != nil {
  1197. ctx.ServerError("Cloudbrain", err)
  1198. return
  1199. }
  1200. log.Info("query return count=" + fmt.Sprint(count))
  1201. nameList := make([]string, 0)
  1202. nameMap := make(map[string][]*models.AiModelManage)
  1203. for _, model := range modelResult {
  1204. model.TrainTaskInfo = ""
  1205. model.Accuracy = ""
  1206. //removeIpInfo(model)
  1207. if _, value := nameMap[model.Name]; !value {
  1208. models := make([]*models.AiModelManage, 0)
  1209. models = append(models, model)
  1210. nameMap[model.Name] = models
  1211. nameList = append(nameList, model.Name)
  1212. } else {
  1213. nameMap[model.Name] = append(nameMap[model.Name], model)
  1214. }
  1215. }
  1216. mapInterface := make(map[string]interface{})
  1217. mapInterface["nameList"] = nameList
  1218. mapInterface["nameMap"] = nameMap
  1219. ctx.JSON(http.StatusOK, mapInterface)
  1220. }
  1221. func QueryModelFileForPredict(ctx *context.Context) {
  1222. id := ctx.Query("id")
  1223. if id == "" {
  1224. id = ctx.Query("ID")
  1225. }
  1226. ctx.JSON(http.StatusOK, QueryModelFileByID(id))
  1227. }
  1228. func QueryModelFileByID(id string) []storage.FileInfo {
  1229. model, err := models.QueryModelById(id)
  1230. if err == nil {
  1231. if model.Type == models.TypeCloudBrainTwo {
  1232. prefix := model.Path[len(setting.Bucket)+1:]
  1233. fileinfos, _ := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix)
  1234. return fileinfos
  1235. } else if model.Type == models.TypeCloudBrainOne {
  1236. prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:]
  1237. fileinfos, _ := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, prefix)
  1238. return fileinfos
  1239. }
  1240. } else {
  1241. log.Error("no such model!", err.Error())
  1242. }
  1243. return nil
  1244. }
  1245. func QueryOneLevelModelFile(ctx *context.Context) {
  1246. id := ctx.Query("id")
  1247. if id == "" {
  1248. id = ctx.Query("ID")
  1249. }
  1250. parentDir := ctx.Query("parentDir")
  1251. model, err := models.QueryModelById(id)
  1252. if err != nil {
  1253. log.Error("no such model!", err.Error())
  1254. ctx.ServerError("no such model:", err)
  1255. return
  1256. }
  1257. if model.Type == models.TypeCloudBrainTwo {
  1258. log.Info("TypeCloudBrainTwo list model file.")
  1259. prefix := model.Path[len(setting.Bucket)+1:]
  1260. fileinfos, _ := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir)
  1261. if fileinfos == nil {
  1262. fileinfos = make([]storage.FileInfo, 0)
  1263. }
  1264. ctx.JSON(http.StatusOK, fileinfos)
  1265. } else if model.Type == models.TypeCloudBrainOne {
  1266. log.Info("TypeCloudBrainOne list model file.")
  1267. prefix := model.Path[len(setting.Attachment.Minio.Bucket)+1:]
  1268. fileinfos, _ := storage.GetOneLevelAllObjectUnderDirMinio(setting.Attachment.Minio.Bucket, prefix, parentDir)
  1269. if fileinfos == nil {
  1270. fileinfos = make([]storage.FileInfo, 0)
  1271. }
  1272. ctx.JSON(http.StatusOK, fileinfos)
  1273. }
  1274. }
  1275. func CreateLocalModel(ctx *context.Context) {
  1276. ctx.Data["isModelManage"] = true
  1277. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  1278. ctx.HTML(200, tplCreateLocalModelInfo)
  1279. }
  1280. func CreateLocalModelForUpload(ctx *context.Context) {
  1281. ctx.Data["uuid"] = ctx.Query("uuid")
  1282. ctx.Data["isModelManage"] = true
  1283. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  1284. ctx.Data["max_model_size"] = setting.MaxModelSize * MODEL_MAX_SIZE
  1285. ctx.HTML(200, tplCreateLocalForUploadModelInfo)
  1286. }
  1287. func CreateOnlineModel(ctx *context.Context) {
  1288. ctx.Data["isModelManage"] = true
  1289. ctx.Data["ModelManageAccess"] = ctx.Repo.CanWrite(models.UnitTypeModelManage)
  1290. ctx.HTML(200, tplCreateOnlineModelInfo)
  1291. }