422 Commits

Author SHA1 Message Date
  choikeith af78dbd0f9 Merge remote-tracking branch 'upstream/V20230215' into V20221228 2 years ago
  zouap 152dc61a98 Merge pull request 'fix-3325 前端代码回退, 分支分页解决不了快慢问题,后端去掉分页' (#3633) from fix-3325 into V20230215 2 years ago
  ychao d5a6d505c4 去掉分支分页接口,增加分支获取改为迭代的接口 2 years ago
  zhoupzh bad85c3b1d Merge branch 'V20230215' into fix-3325 2 years ago
  zhoupzh d1850f65ff Merge branch 'fix-3325' of openi.pcl.ac.cn:OpenI/aiforge into fix-3325 2 years ago
  zhoupzh 98ef0711d0 fix issue 2 years ago
  chenyifan01 f8bca93307 Merge pull request '修复训练任务修改时多节点扣费问题' (#3632) from fix-3629 into V20230215 2 years ago
  chenyifan01 e673101554 #3629 2 years ago
  chenshihai b99ba1a35b Merge pull request 'fix issue' (#3626) from fix-3325 into V20230215 2 years ago
  zhoupzh 0049e79c2d Merge branch 'V20230215' into fix-3325 2 years ago
  zhoupzh 8439efe4f3 fix issue 2 years ago
  zouap 6371c00f3f Merge pull request 'fix-3325' (#3625) from fix-3325 into V20230215 2 years ago
  zhoupzh 85c391f926 清除console 2 years ago
  zhoupzh 8dda5158a3 清除console 2 years ago
  zhoupzh 778f8324b2 Merge branch 'fix-3325' of openi.pcl.ac.cn:OpenI/aiforge into fix-3325 2 years ago
  zhoupzh 6dcc859044 fix issue 2 years ago
  zouap 81b68e0e46 Merge branch 'V20230215' into fix-3325 2 years ago
  zhoupzh 45b2532aa6 Merge branch 'fix-3325' of openi.pcl.ac.cn:OpenI/aiforge into fix-3325 2 years ago
  zhoupzh 30a792e57e 分支分批次加载前端修改 2 years ago
  zhoupzh f669707705 Merge pull request '#3620 【积分消耗】修改多节点的npu训练任务,界面显示预计可用xx小时未考虑多节点' (#3623) from fix-csh into V20230215 2 years ago
  ychao 40086de476 改成按字母序 2 years ago
  chenshihai d61776d33a Merge branch 'V20230215' into fix-csh 2 years ago
  chenshihai ca5096fcbf #3620 2 years ago
  ychao 876d2efb32 提交代码 2 years ago
  chenyifan01 8f9859847a Merge pull request '#2417 修复notebook问题' (#3621) from fix-2417 into V20230215 2 years ago
  chenyifan01 671aee1bb8 #2417 2 years ago
  chenyifan01 70279c3acb Merge pull request '修复模型安全评测页没提示框问题' (#3616) from fix-2417 into V20230215 2 years ago
  chenyifan01 edd51e1d92 #2417 2 years ago
  ychao e6163ac15b branch search 2 years ago
  ychao bfd4d59ce6 提交代码 2 years ago
  chenyifan01 fdc93d7e5b Merge pull request '#2417' (#3615) from fix-2417 into V20230215 2 years ago
  chenyifan01 3a0ea089e9 #2417 2 years ago
  zhoupzh 9fd4295d09 Merge pull request '积分相关BUG修复(#3598,#3584,#3585,#3581,#3583,#3588,#3580)' (#3611) from fix-csh into V20230215 2 years ago
  chenshihai 24b9db38e0 Merge branch 'V20230215' into fix-csh 2 years ago
  chenshihai c8afb6d2e1 积分相关BUG修复(#3598,#3584,#3585,#3581,#3583,#3588,#3580) 2 years ago
  chenyifan01 e86e6bccb9 Merge pull request '修复模型评测任务可同时创建两个的问题' (#3609) from fix-2417 into V20230215 2 years ago
  chenyifan01 29b980aacc #2417 2 years ago
  ychao 42cc982953 Merge pull request '1、issue置顶功能合入,2、解决新版训练任务资源监控数据问题,3、新增下载训练任务所有结果的API接口。4、去掉同步镜像时往Action表中插入的类型为19、20的无用数据' (#3608) from zouap into V20230215 2 years ago
  zouap 12e63f0ebf Merge branch 'V20230215' into zouap 2 years ago
  chenyifan01 51ca0f4a5c Merge pull request '修复评测任务可同时创建两个的问题' (#3607) from fix-2417 into V20230215 2 years ago
  zouap bd39e03524 去掉action表中增加的镜像同步数据 2 years ago
  chenyifan01 051ef03870 #2417 2 years ago
  zouap 81708321ba Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap 2c973dedaa 去掉action表中增加的镜像同步数据 2 years ago
  chenyifan01 842c8e9a1e Merge pull request '优化“积分余额不足”返回速度' (#3605) from fix-3599 into V20230215 2 years ago
  chenyifan01 a7b2eaa0e5 #3599 2 years ago
  zhoupzh f372215f72 fix issue 2 years ago
  ychao ad071fd406 Merge pull request '修复相同类型,不同计算资源任务之间未共享限制的bug' (#3603) from fix-2417 into V20230215 2 years ago
  chenyifan01 b7755341e8 Merge remote-tracking branch 'origin/V20230215' into fix-2417 2 years ago
  chenyifan01 13498b8310 fix bug 2 years ago
  chenyifan01 d539987b5c fix bug 2 years ago
  ychao e801a68898 提交代码 2 years ago
  zhoupzh 8910bfa617 fix issue 2 years ago
  zouap 55bcd99d3d 提交代码。增加置顶功能。 2 years ago
  zouap 4174e094a5 智算网络相关接口修改。 2 years ago
  zouap f3a817bc19 Merge remote-tracking branch 'origin/V20230215' into zouap 2 years ago
  zouap 81ed291aac Merge pull request 'mod npu command' (#3590) from npu-train-new into V20230215 2 years ago
  lewis 452132c1f3 Merge branch 'V20230215' of openi.pcl.ac.cn:OpenI/aiforge into npu-train-new 2 years ago
  zouap fa5e71fc54 智算任务监控接口变动 2 years ago
  zouap c95c0dd748 智算任务监控接口变动 2 years ago
  zouap 9a262a20c4 issue中增加置顶属性 2 years ago
  ychao 82327a3676 Merge pull request '解决相关Bug' (#3589) from zouap into V20230215 2 years ago
  zouap 12a7bebe80 Merge branch 'V20230215' into zouap 2 years ago
  ychao 30b74d57b6 Merge pull request '不同集群的训练任务共用1个任务的数量限制' (#3577) from fix-2417 into V20230215 2 years ago
  chenyifan01 82630d5a68 Merge remote-tracking branch 'origin/V20230215' into fix-2417 2 years ago
  chenyifan01 3562f64af0 Merge pull request '修复#3574' (#3575) from fix-3574 into V20230215 2 years ago
  chenyifan01 4daf5e5cb7 #3574 2 years ago
  zouap 686c514c7d 修正SQL注入问题 2 years ago
  zouap f9c2043f22 修正SQL注入的问题 2 years ago
  zouap 00b3f9dc46 修正SQL注入的问题 2 years ago
  zouap 2e0ea2e200 提交代码,解决id问题 2 years ago
  zouap 1cfc1cf65c 提交代码,解决id问题 2 years ago
  ychao 7108f766f9 Merge pull request '修复智算NPU任务积分消耗完后不能自动停止的问题' (#3572) from fix-2901 into V20230215 2 years ago
  chenyifan01 83e987abde #2901 2 years ago
  zouap dda57af14e 解决Bug #3257 2 years ago
  liuzx fce26fbc50 Merge pull request '给Mlops新增一个接口' (#3561) from fix-mlops into V20230215 2 years ago
  ychao f43020f035 提交代码 2 years ago
  ychao 7658370707 Merge pull request 'V20221228' (#3559) from V20221228 into develop 2 years ago
  ychao 8412cf18d3 Merge pull request '解决运营统计及年度报告中用户云脑任务数量不准确的问题。' (#3558) from zouap into V20221228 2 years ago
  zouap 728c998abf Merge branch 'V20221228' into zouap 2 years ago
  zouap 8a3700c827 提交代码,解决云脑任务数量不准确的问题 2 years ago
  zouap 51d08b6d0f 解决云脑任务数不准确的Bug 2 years ago
  zouap 52d3ab8b54 提交代码,解决故障 2 years ago
  zouap 5707e6969a 提交代码,调试bug 2 years ago
  zouap 5abe5e5c14 Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap 5741edfeb1 提交代码,调试bug 2 years ago
  ychao 20e80c5eb2 Merge pull request '对象传递修改成指针传递' (#3557) from zouap into V20221228 2 years ago
  zouap 40b53cb3e9 Merge branch 'V20221228' into zouap 2 years ago
  zouap afc362d047 还原部分代码。 2 years ago
  zouap c096dbf2d7 还原周度数据代码 2 years ago
  zouap 1bba6a8fde 提交代码,增加打印 2 years ago
  ychao 452ddfab08 Merge pull request 'fix-token-error' (#3556) from fix-notebook into V20221228 2 years ago
  ychao d01c0c485d fix-token-error 2 years ago
  ychao 12a9f01972 Merge pull request '#3553 【gcu调试】首页动态中的任务类型显示不对' (#3554) from fix-csh into V20221228 2 years ago
  chenshihai 1931a71f72 Merge branch 'V20221228' into fix-csh 2 years ago
  chenshihai 752477ea0f #3553 【gcu调试】首页动态中的任务类型显示不对 2 years ago
  ychao 86f233da48 Merge pull request 'add agreement links' (#3549) from fix-csh into V20221228 2 years ago
  zouap 9ea4fb98ef Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap 52d5aa1708 提交代码,解决问题 2 years ago
  chenshihai 2b8185ee51 add agreement links 2 years ago
  ychao 3d4e04ea39 Merge pull request '依瞳模型管理中查询训练任务接口增加其它属性。' (#3545) from zouap into V20221228 2 years ago
  zouap 1e474b4fc8 Merge branch 'V20221228' into zouap 2 years ago
  zouap 02f4af34b3 Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap 36976b8f91 解决查询模型管理的训练任务属性问题 2 years ago
  ychao 07bcd349b3 Merge pull request '提升action表查询速度' (#3544) from zouap into V20221228 2 years ago
  zouap 0d3e1ae883 Merge branch 'V20221228' into zouap 2 years ago
  zouap f6dc11037a 优化查询action表 2 years ago
  zouap e09cd9ddb4 Merge pull request 'fix-3262' (#3543) from fix-3262 into V20221228 2 years ago
  zouap f90ce96f66 提交代码,提升查询action表的速度。 2 years ago
  changeorl 1ed1f83424 解决冲突 2 years ago
  liuzx 8769465a4d Merge pull request 'fix-3480' (#3539) from fix-3339 into V20221228 2 years ago
  zouap 39265d9d20 Merge branch 'V20221228' into fix-3339 2 years ago
  chenshihai 2eec01ec0b Merge pull request 'fix issue' (#3540) from zpz-issue-1228 into V20221228 2 years ago
  zhoupzh f19ee6f7ad fix issue 2 years ago
  liuzx 66c4868e60 Merge remote-tracking branch 'origin/V20221228' into fix-3339 2 years ago
  liuzx 25ba6c092e fix-3480 2 years ago
  ychao 559c5b6adb Merge pull request '年度报告中增加评测任务属性' (#3538) from zouap into V20221228 2 years ago
  zouap fd15655504 Merge branch 'V20221228' into zouap 2 years ago
  chenshihai d261de706a Merge pull request '增加年度报告隐私协议' (#3537) from zpz-issue-1228 into V20221228 2 years ago
  zhoupzh df6c3103a1 Merge branch 'V20221228' into zpz-issue-1228 2 years ago
  zhoupzh 598a92c7ec fix issue 2 years ago
  zouap 72102c526e 提交代码,增加年度报告中的评测任务字段 2 years ago
  ychao 4d91de677f Merge pull request 'gcu代码合并到里程碑分支' (#3529) from gcu into V20221228 2 years ago
  lewis 86c69fabba mod npu command 2 years ago
  zouap 3eece6ec6d 年度报告中增加评测任务统计 2 years ago
  zouap caaf1426a8 增加评测任务数量 2 years ago
  zouap 9def35594b 提交代码,解决用户增长趋势问题 2 years ago
  zouap dac7cab477 提交代码,解决用户增长趋势问题 2 years ago
  chenshihai f08a0b8ee9 Merge remote-tracking branch 'origin/V20221228' into gcu 2 years ago
  chenshihai 7c689c4b48 Merge pull request 'zpz-issue-1228' (#3528) from zpz-issue-1228 into V20221228 2 years ago
  zhoupzh df11043a04 Merge branch 'V20221228' into zpz-issue-1228 2 years ago
  zhoupzh 07b08edd38 fix issue 2 years ago
  chenyifan01 2e3824540e #2417 2 years ago
  chenyifan01 9ea723e215 Merge remote-tracking branch 'origin/gcu' into fix-2417 2 years ago
  zhoupzh fa79d8e814 fix issue 2 years ago
  chenshihai f149b9a813 Merge remote-tracking branch 'origin/V20221228' into gcu 2 years ago
  chenyifan01 f7c85b2b92 #2417 2 years ago
  zouap 07f2eb8fad Merge pull request 'fix-3470' (#3526) from fix-3470 into V20221228 2 years ago
  liuzx 39d2891c61 fix-3470 2 years ago
  zouap 5153875bc7 增加打印 2 years ago
  zouap fa08c43245 Merge remote-tracking branch 'origin/V20221228' into zouap 2 years ago
  zouap b5a552a459 Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap 3952a2f60c #3088 【模型安全评测】testing状态增加图标显示 2 years ago
  zhoupzh 927893aeec Merge pull request 'update signup invitation tips' (#3520) from fix-csh into V20221228 2 years ago
  chenshihai f78cf3fdf6 Merge remote-tracking branch 'origin/V20221228' into fix-csh 2 years ago
  chenshihai 27c5165430 update signup invitation tips 2 years ago
  ychao 40f49edd7c Merge pull request '解决文件中出现以\r结尾的字符串问题。' (#3518) from zouap into V20221228 2 years ago
  zouap a87a3f33ad Merge branch 'V20221228' into zouap 2 years ago
  zouap bd9ea70be9 提交代码,解决回车换行符的bug 2 years ago
  zouap 75f01526bf 提交代码,解决回车换行符的bug 2 years ago
  zouap ae326f6c18 解决回车换行符号 2 years ago
  zouap 385539c6da Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap e03a89bd26 提交代码,强行去掉CSV末尾的特殊字符 2 years ago
  ychao f7e0a8088c Merge pull request '提交代码,增加数据打印' (#3516) from zouap into V20221228 2 years ago
  zouap db974794e9 Merge branch 'V20221228' into zouap 2 years ago
  zouap d514a82418 提交代码,增加数据打印 2 years ago
  chenyifan01 3e3dcf09cb #3448 2 years ago
  chenyifan01 cb4318577d #3448 2 years ago
  chenyifan01 0db748aca7 #3448 2 years ago
  chenyifan01 755b24c25c #3448 2 years ago
  chenyifan01 bf692ebb99 Merge remote-tracking branch 'origin/gcu' into gcu 2 years ago
  chenyifan01 30a5a01181 #3448 2 years ago
  ychao 0449d4dc0d Merge pull request '用户年度报告,2023年注册用户获取报告时返回正确的注册日期。' (#3503) from zouap into V20221228 2 years ago
  zhoupzh f51aab9256 Merge pull request 'fix go top error in wechat browser' (#3505) from fix-csh into V20221228 2 years ago
  zouap 273b74dd11 Merge branch 'V20221228' into zouap 2 years ago
  chenshihai 0f7718ec6d Merge remote-tracking branch 'origin/V20221228' into fix-csh 2 years ago
  chenshihai 1ecf111e28 fix go top error in wechat browser 2 years ago
  zouap 4c82737188 Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap dfefa70bb9 提交代码。 2 years ago
  zhoupzh 67d2414981 Merge pull request 'fix signup page error in slow network environment' (#3500) from fix-csh into V20221228 2 years ago
  chenshihai 23779a594f Merge remote-tracking branch 'origin/V20221228' into fix-csh 2 years ago
  chenshihai 09d82378e8 fix signup page error in slow network environment 2 years ago
  ychao e7dc9eb505 Merge pull request '解决用户年度报告重定向问题。' (#3499) from zouap into V20221228 2 years ago
  zouap 8e5a0af1da Merge branch 'V20221228' into zouap 2 years ago
  zouap 7ace826c41 解决用户年度报告重定向问题 2 years ago
  zouap fcc3824bbd 提交代码,增加登录重定向 2 years ago
  zouap 8738240554 增加打印信息 2 years ago
  zouap 0647c5e9f9 提交代码。 2 years ago
  zouap 74b81213eb 登录跳转问题 2 years ago
  zouap 1baef88c4c Merge branch 'zouap' of https://git.openi.org.cn/OpenI/aiforge into zouap 2 years ago
  zouap 784fff22eb 提交代码。 2 years ago
  ychao 00c7dca517 Merge pull request '解决年度报告中的云脑任务数量不对的问题。' (#3490) from zouap into V20221228 2 years ago
  zouap 43657e9abc Merge branch 'V20221228' into zouap 2 years ago
  zouap 4bf61de411 解决云脑任务具体数量错误问题。 2 years ago
  zouap 4908fbc193 提交代码,解决一下云脑任务统计数据 2 years ago
  chenshihai 00a41367d1 Merge remote-tracking branch 'origin/V20221228' into gcu 2 years ago
  zhoupzh 42716659b7 Merge pull request '#3313,#3329' (#3487) from fix-3313 into V20221228 2 years ago
  chenshihai 085030a171 update 2 years ago
  chenshihai 60a0699875 Merge remote-tracking branch 'origin/V20221228' into fix-3313 2 years ago
  chenshihai a19b3608aa Merge remote-tracking branch 'origin/V20221228' into gcu 2 years ago
  zhoupzh 5516634eba Merge pull request '#3471 首页增加开源打榜第五期banner' (#3486) from dev-csh into V20221228 2 years ago
  chenshihai fdbd0e699d Merge remote-tracking branch 'origin/V20221228' into dev-csh 2 years ago
  chenshihai b96a1efded Merge pull request 'fix issue' (#3484) from annual-report into V20221228 2 years ago
  zhoupzh aff3766fe4 Merge branch 'V20221228' into annual-report 2 years ago
  zhoupzh 451163fb1f fix issue 2 years ago
  chenshihai bb85c2227b Merge pull request '个人中心和后台管理新增SNN4ECOSET任务' (#3482) from zpz-issue-1228 into V20221228 2 years ago
  zhoupzh 6c4fcd49f1 Merge branch 'V20221228' into zpz-issue-1228 2 years ago
  zhoupzh e85705fee5 fix issue 2 years ago
  zhoupzh 7c6154a4c7 fix issue 2 years ago
  zhoupzh b36fe82580 fix issue 2 years ago
  zhoupzh eb38a801a4 fix issue 2 years ago
  zhoupzh e230e86b21 Merge branch 'zpz-issue-1228' of openi.pcl.ac.cn:OpenI/aiforge into zpz-issue-1228 2 years ago
  zhoupzh f4f5a1e0d3 fix issue 2 years ago
  ychao 1bea07d5a7 Merge pull request '年度报告打榜数据合入及#3428' (#3481) from zouap into V20221228 2 years ago
  zouap 48489ac5f9 Merge remote-tracking branch 'origin/V20221228' into zouap 2 years ago
  zouap 44bbf46343 解决多节点训练日志下载问题 2 years ago
  chenyifan01 b5e5831c33 Merge remote-tracking branch 'origin/V20221228' into fix-2417 2 years ago
  zouap a61e87c9f5 Merge pull request 'mlops 数据集上传增加鉴权功能' (#3479) from file-notebook-new into V20221228 2 years ago
  zouap f4bcfea712 Merge branch 'V20221228' into file-notebook-new 2 years ago
  ychao 743fae8c72 mlops 数据集上传增加鉴权功能 2 years ago
  zouap d883eec2e5 多节点日志下载问题。 2 years ago
  chenyifan01 07b43961a3 #3448 2 years ago
  zouap 9abdd2c49b Merge pull request 'file-notebook-new,修改数据库字段长度,正常至少支持10个文件同时在同一个环境打开。' (#3478) from file-notebook-new into V20221228 2 years ago
  zouap 77943686bc Merge branch 'V20221228' into file-notebook-new 2 years ago
  ychao 0d6fc4aea1 Merge branch 'file-notebook-new' of https://openi.pcl.ac.cn/OpenI/aiforge into file-notebook-new 2 years ago
  ychao 124e1ab94e 提交代码 2 years ago
  chenyifan01 63bc4d1df9 Merge remote-tracking branch 'origin/V20221228' into gcu 2 years ago
  zouap 9143e16643 Merge pull request '修复多文件notebook环境记录的描述,boot_file等超过数据库字符长度限制的情况' (#3476) from file-notebook-new into V20221228 2 years ago
  zouap 886a154726 Merge branch 'V20221228' into file-notebook-new 2 years ago
  ychao 01b24703c7 修复多文件notebook环境记录的描述,boot_file等超过字符长度限制的情况 2 years ago
  zouap 5fb1a56ddc Merge pull request 'file-notebook-new' (#3474) from file-notebook-new into V20221228 2 years ago
  zouap 16f5bba339 Merge branch 'V20221228' into file-notebook-new 2 years ago
  ychao e874557c2d Merge branch 'file-notebook-new' of https://openi.pcl.ac.cn/OpenI/aiforge into file-notebook-new 2 years ago
  ychao eeabf642bc 提交代码 2 years ago
  chenshihai e3dc0ad98d Merge remote-tracking branch 'origin/V20221228' into dev-csh 2 years ago
  chenshihai c19465b621 #3471 首页增加开源打榜第五期banner 2 years ago
  chenshihai aa5eb4e7e6 Merge pull request 'zpz-issue-1228' (#3473) from zpz-issue-1228 into V20221228 2 years ago
  zhoupzh affc4c5a7f Merge branch 'V20221228' into zpz-issue-1228 2 years ago
  zhoupzh 67033bf802 fix issue 2 years ago
  zouap a3d4a917d0 年度数据中增加个人名次最好的周度数据 2 years ago
  zhoupzh 593d931a40 fix issue 2 years ago
  zhoupzh 4692e85abd fix issue 2 years ago
  zouap 67730854bd 提交代码,解决打榜数据问题。 2 years ago
  zhoupzh 8e9efaf8c3 Merge pull request '#3314 注册和登录页面,增加开发者大会的活动链接' (#3472) from fix-csh into V20221228 2 years ago
  chenshihai aa5b5dd981 Merge remote-tracking branch 'origin/V20221228' into fix-csh 2 years ago
  chenshihai ccc9b562fa update 2 years ago
  zouap 393dda00a4 Merge pull request 'fix-3459' (#3469) from file-notebook-new into V20221228 2 years ago
  zouap c4901dadd4 Merge branch 'V20221228' into file-notebook-new 2 years ago
  ychao 8f37e3baf4 fix-3459 2 years ago
  chenshihai 35f3f75b43 Merge remote-tracking branch 'origin/V20221228' into fix-csh 2 years ago
  zhoupzh 59622d0858 Merge pull request 'fix-lang 多语言处理' (#3464) from fix-lang into V20221228 2 years ago
  chenshihai 0e5aa886c7 Merge branch 'V20221228' into fix-lang 3 years ago
  chenshihai ed66020ba9 update 3 years ago
  chenshihai eeb1de0a94 update 3 years ago
  zouap f7156e6bc9 Merge pull request '智算训练任务系统调度失败将错误原因放日志中' (#3463) from fix-3339 into V20221228 3 years ago
  zouap b68e6fe828 Merge branch 'V20221228' into fix-3339 3 years ago
  zouap f2721e0533 Merge pull request '数字看板云脑任务分析相关页面增加GCU信息' (#3462) from fix-3342 into V20221228 3 years ago
  zouap 8f4a636fa6 Merge branch 'V20221228' into fix-3342 3 years ago
  liuzx da9cd10a2e Merge branch 'V20221228' into fix-3339 3 years ago
  zouap fc09b91492 Merge pull request 'fix-3319' (#3460) from fix-3319 into V20221228 3 years ago
  liuzx 463952c61b fix-3339 3 years ago
  liuzx f267d8dc5c Merge branch 'V20221228' into fix-3342 3 years ago
  chenshihai 18136b8a8f Merge remote-tracking branch 'origin/V20221228' into fix-lang 3 years ago
  chenyifan01 3b0be00d7c Merge remote-tracking branch 'origin/V20221228' into gcu 3 years ago
  zouap ccfe2ea166 Merge branch 'V20221228' into fix-3319 3 years ago
  chenyifan01 a0a2d65ab3 Merge pull request '修复仓库迁移时没有描述信息的bug' (#3461) from migrate-v2 into V20221228 3 years ago
  chenyifan01 2e6ceb835d fix repo migrate bug 3 years ago
  chenyifan01 90e280a37d Merge remote-tracking branch 'origin/gcu' into fix-2417 3 years ago
  chenyifan01 4017242a5f #2417 3 years ago
  liuzx a9cd02268d Merge remote-tracking branch 'origin/V20221228' into fix-3319 3 years ago
  liuzx b30d23ff9b fix-3339 3 years ago
  chenshihai ae2384fe23 Merge pull request 'fix issue' (#3454) from fix-3262 into V20221228 3 years ago
  zhoupzh 151a56df38 Merge branch 'V20221228' into fix-3262 3 years ago
  zhoupzh 8d8047c675 fix issue 3 years ago
  zouap b5999e5894 Merge pull request 'fix-3406 【调试任务】一部分智算npu调试任务再次调试失败 和 云脑任务文件清理增加智算GPU任务的清理' (#3447) from fix-3248 into V20221228 3 years ago
  zouap f3581bdc17 Merge branch 'V20221228' into fix-3248 3 years ago
  ychao a353739f15 提交代码 3 years ago
  chenshihai e602562f8e #3444 3 years ago
  zhoupzh 218efada06 Merge pull request '#3441' (#3442) from fix-3441 into V20221228 3 years ago
  chenshihai 897ab1d28f #3441 3 years ago
  chenyifan01 c49fb55f29 #3431 3 years ago
  chenyifan01 7f6ff85773 Merge remote-tracking branch 'origin/gcu' into gcu 3 years ago
  chenyifan01 b3c0f7bd10 #3431 3 years ago
  chenshihai 5d886fc24d gcu 3 years ago
  chenshihai 1d1295f840 Merge pull request 'zpz-issue-1228' (#3437) from zpz-issue-1228 into V20221228 3 years ago
  zhoupzh 3b2ad85a81 fix issue 3 years ago
  zouap f146d56238 Merge pull request 'fix-3248-评测任务支持一种新类型' (#3439) from fix-3248 into V20221228 3 years ago
  ychao e818365c10 merge 3 years ago
  zhoupzh 1b16f09fa1 fix issue 3 years ago
  zhoupzh e2d566f233 fix issue 3 years ago
  zhoupzh 51c205d1c7 fix issue 3 years ago
  zouap 2c52340c7f Merge pull request 'fix-3262' (#3434) from fix-3262 into V20221228 3 years ago
  zhoupzh 7f46ac8d6b Merge branch 'V20221228' into fix-3262 3 years ago
  zouap 0b63c015ee 提交代码。 3 years ago
  zouap b19816da60 Merge branch 'zpz-issue-1228' of https://git.openi.org.cn/OpenI/aiforge into zpz-issue-1228 3 years ago
  zouap 0187046d03 GPU推理下载多个文件修改。 3 years ago
  zhoupzh 2b7eda3ef4 fix issue 3 years ago
  zhoupzh e28728f708 Merge branch 'zpz-issue-1228' of openi.pcl.ac.cn:OpenI/aiforge into zpz-issue-1228 3 years ago
  zhoupzh 2066796468 fix issue 3 years ago
  zouap 8c51f9b77f 提交代码,解决权限问题。 3 years ago
  zouap 07e94e8a60 增加打印信息。 3 years ago
  zouap 12af2c2771 解决OBS下载多个文件时多了一个斜杠问题。 3 years ago
  zhoupzh 2d5d41befe fix issue 3 years ago
  zhoupzh e7cc96ffa2 fix issue 3 years ago
  zhoupzh 2031ea50da fix issue 3 years ago
  chenshihai 4da18f658d internationalization 3 years ago
  chenshihai efc2f85da8 internationalization 3 years ago
  zhoupzh 31d1ae4736 Merge branch 'V20221228' into zpz-issue-1228 3 years ago
  ychao 0cdf10ac7b Merge pull request '相关Bug #3346 及MLOPS调试新增接口合并。' (#3435) from zouap into V20221228 3 years ago
  zouap 3ac5945e4c 前端恢复原状 3 years ago
  zouap 2fb4d8dc7b 前端恢复原状 3 years ago
  zouap 77553fbeb7 前端恢复原状 3 years ago
  zouap afba35d489 提交代码,增加下载所有接口。 3 years ago
  zouap d19a062d72 提交代码,增加下载所有接口。 3 years ago
  zouap edc4900f51 提交代码,增加下载所有接口。 3 years ago
  zouap bf41f55e6f 提交代码,增加下载所有接口。 3 years ago
  zouap 338c3d4e02 提交代码,增加下载所有接口。 3 years ago
  chenshihai 557e981caa internationalization 3 years ago
  ychao 0c10cd634d mlops 3 years ago
  ychao 020bba5c38 提交代码 3 years ago
  chenyifan01 c5657bda9e #3431 3 years ago
  chenyifan01 b0801e6b42 Merge remote-tracking branch 'origin/V20221228' into gcu 3 years ago
  zouap b50ddeaa62 Merge remote-tracking branch 'origin/V20221228' into zouap 3 years ago
  ychao 2a4c1e29a7 提交代码 3 years ago
  chenshihai 7d51991215 Merge remote-tracking branch 'origin/V20221228' into fix-3313 3 years ago
  ychao efca9ac316 提交代码 3 years ago
  zhoupzh 39323f0969 Merge branch 'fix-3262' of openi.pcl.ac.cn:OpenI/aiforge into fix-3262 3 years ago
  zhoupzh 72f8c58611 fix issue 3 years ago
  zhoupzh d90808804e Merge branch 'V20221228' into fix-3262 3 years ago
  zhoupzh d7efd833c3 fix issue 3 years ago
  zhoupzh 8de95dcacb fix issue 3 years ago
  zhoupzh 2a77c0585d fix issue 3 years ago
  zhoupzh f6aa6e8d22 Merge branch 'fix-3248' of openi.pcl.ac.cn:OpenI/aiforge into fix-3248 3 years ago
  zhoupzh 733f1d95e9 fix issue 3 years ago
  zhoupzh cc04a20d0e fix issue 3 years ago
  zhoupzh c0b3ed5560 fix issue 3 years ago
  zhoupzh d87722f2d8 fix issue 3 years ago
  zhoupzh 09cc4e3f84 fix issue 3 years ago
  zhoupzh bd2ad47d4c fix issue 3 years ago
  zhoupzh 8edcd7d096 fix issue 3 years ago
  zhoupzh 079807c270 fix issue 3 years ago
  zhoupzh 55b1bdb1c2 fix issue 3 years ago
  zhoupzh 21cf7fbc8d fix issue 3 years ago
  zhoupzh fb3ff3d071 fix issue 3 years ago
  zhoupzh d58847296f fix issue 3 years ago
  zhoupzh 671b55c689 fix issue 3 years ago
  ychao b0f18ff074 提交diam 3 years ago
  zhoupzh b2265d00a1 fix issue 3 years ago
  zhoupzh 98e0a770d4 fix issue 3 years ago
  zhoupzh 31aa33f921 fix issue 3 years ago
  zhoupzh 79ebde98de fix issue 3 years ago
  zhoupzh 8c45b5865c fix issue 3 years ago
  zouap d0d8bad140 提交代码,解决用户图像更新问题 3 years ago
  zouap 437b465f31 提交代码,解决用户图像更新问题 3 years ago
  zhoupzh a88ab8a2ac fix issue 3 years ago
  zhoupzh 63f374b019 fix issue 3 years ago
  chenshihai 77dceb20fe #3313 3 years ago
  zhoupzh 3862ba6f0d fix issue 3 years ago
  chenshihai d50103d3b7 gcu 3 years ago
  zhoupzh e6b3253add fix issue 3 years ago
  zhoupzh afd9b31a1c fix issue 3 years ago
  Gitea 747785cf1a fix-3262 3 years ago
  chenshihai f389b35ef5 Merge remote-tracking branch 'origin/V20221228' into fix-csh 3 years ago
  zhoupzh 8fae5b816e solve conflict 3 years ago
  zhoupzh f2cc9f808d Merge branch 'V20221228' into fix-3262 3 years ago
  Gitea 4524ce79b7 fix-3262 3 years ago
  Gitea 68505c0c80 调试限制数据及大小 3 years ago
  liuzx 3e0f70aea1 fix-3342 3 years ago
  chenshihai c8cf6d34b8 Merge remote-tracking branch 'origin/V20221228' into gcu 3 years ago
  ychao f4be9ecc44 merge 3 years ago
  chenshihai 928b37b5e7 Merge remote-tracking branch 'origin/V20221228' into fix-3313 3 years ago
  chenshihai 11495623c5 #3313 发布新版本的时候不用清空缓存 3 years ago
  liuzx 622e57da86 fix-3319 3 years ago
  liuzx dd426bcca5 fix-3319 3 years ago
  chenshihai c14d828b34 Merge remote-tracking branch 'origin/V20221214' into fix-csh 3 years ago
  chenshihai 14607910e2 #3314 注册和登录页面,增加开发者大会的活动链接 3 years ago
  liuzx 5e65f0fc10 fix-3319 3 years ago
  liuzx 406d2aa41b fix-3319 3 years ago
  chenshihai 798d7a24a4 update 3 years ago
  chenyifan01 9112ff89ca Merge remote-tracking branch 'origin/gcu' into gcu 3 years ago
  chenyifan01 dd66e627c8 #3277 3 years ago
  chenshihai 9b22ed316b gcu 3 years ago
  chenyifan01 39007e5a60 Merge remote-tracking branch 'origin/grampus-notebook' into gcu 3 years ago
  chenyifan01 be3cd0bbaa #3277 3 years ago
  chenyifan01 8411cd5bbc Merge remote-tracking branch 'origin/grampus-notebook' into gcu 3 years ago
  chenyifan01 fca6c191ce Merge remote-tracking branch 'origin/grampus-notebook' into gcu 3 years ago
  chenyifan01 e86a8c4676 Merge remote-tracking branch 'origin/V20221214' into gcu 3 years ago
  chenyifan01 f7f4935564 #3277 3 years ago
  chenyifan01 64d010af63 #3277 3 years ago
  chenyifan01 3258d9e7f3 #3277 3 years ago
  chenyifan01 19ce11a96f Merge remote-tracking branch 'origin/V20221214' into gcu 3 years ago
  ychao 4ddd3abab3 提交代码 3 years ago
  chenyifan01 d49b974a04 Merge remote-tracking branch 'origin/V20221214' into gcu 3 years ago
  ychao c35c8f2eb4 模型评测增加类型 3 years ago
  chenyifan01 3f44696a41 #3277 3 years ago
  chenyifan01 b30d5dfccc #3277 3 years ago
  chenyifan01 bd6daf4559 #3277 3 years ago
  chenyifan01 809b4b0fc2 #3277 3 years ago
  chenyifan01 e07f4315be #3277 3 years ago
  chenyifan01 98c1512207 #3277 3 years ago
  chenyifan01 8b5e692cd3 #3277 3 years ago
  chenyifan01 896debae7d #3277 3 years ago
  chenyifan01 df23f3e3f7 #3277 3 years ago
  chenyifan01 eceb18eb10 #3277 3 years ago
  chenyifan01 a908c679d2 #3277 3 years ago
  chenyifan01 6a7df0460b #3277 3 years ago
  chenyifan01 ea52df232d Merge remote-tracking branch 'origin/V20221214' into gcu 3 years ago
  chenyifan01 e8fa11c79f Merge remote-tracking branch 'origin/grampus-notebook' into gcu 3 years ago
  chenyifan01 8549034d3a Merge remote-tracking branch 'origin/gcu' into gcu 3 years ago
  chenyifan01 142b0f83eb #3277 3 years ago
  chenshihai d7c317794f gcu 3 years ago
  chenshihai 9693fb941b gcu 3 years ago
  chenyifan01 6760703eba Merge remote-tracking branch 'origin/V20221214' into gcu 3 years ago
  chenyifan01 dd01ab029c Merge remote-tracking branch 'origin/grampus-notebook' into gcu 3 years ago
  chenyifan01 752efc0f7f #3277 3 years ago
  chenyifan01 4002509968 #3277 3 years ago
  chenyifan01 31cb5840d3 Merge remote-tracking branch 'origin/V20221214' into gcu 3 years ago
  chenshihai 0be5c00ca8 gcu 3 years ago
  chenyifan01 4616b9be8d #3277 3 years ago
  chenyifan01 08f04ed6bb Merge remote-tracking branch 'origin/V20221214' into gcu 3 years ago
  Gitea 4a5f9cd4c8 fix-3262 3 years ago
  Gitea bc1b1683f2 fix3262 3 years ago
  Gitea 504f6bd462 fix-3262 3 years ago
  zhoupzh 2f01491f94 去除console打印信息 3 years ago
  zhoupzh 8de31e8bf0 fix issue 3 years ago
  Gitea bbf4d0623f 限制调试数据集大小 3 years ago
  Gitea 49e821d89e fix-3262 3 years ago
  Gitea 4a4a02cc90 fix-3262 3 years ago
  Gitea 2a77370d02 fix-3262 3 years ago
  Gitea 3280eb2c12 fix-3262 3 years ago
  Gitea 90a0ef946a fix-3262 3 years ago
  Gitea 3a26a12a53 fix-3262 3 years ago
100 changed files with 2458 additions and 1329 deletions
Split View
  1. +1
    -0
      .gitignore
  2. +1
    -0
      custom/public/css/placeholder-home.css
  3. +1
    -0
      custom/public/css/placeholder.css
  4. BIN
      custom/public/img/home-banner-02-1.jpg
  5. BIN
      custom/public/img/home-banner-02-2.png
  6. +45
    -0
      custom/public/img/logo-w-origin.svg
  7. +1
    -45
      custom/public/img/logo-w.svg
  8. +1
    -0
      custom/public/js/placeholder-home.js
  9. +1
    -0
      custom/public/js/placeholder.js
  10. +3
    -1
      models/action.go
  11. +8
    -17
      models/ai_model_manage.go
  12. +11
    -0
      models/attachment.go
  13. +116
    -41
      models/cloudbrain.go
  14. +27
    -1
      models/issue.go
  15. +5
    -0
      models/point_account.go
  16. +1
    -0
      models/task_config.go
  17. +6
    -1
      models/user.go
  18. +24
    -0
      models/user_analysis_for_activity.go
  19. +185
    -54
      models/user_business_analysis.go
  20. +3
    -3
      models/user_business_struct.go
  21. +1
    -0
      modules/auth/modelarts.go
  22. +7
    -20
      modules/cloudbrain/cloudbrain.go
  23. +6
    -1
      modules/context/auth.go
  24. +2
    -2
      modules/context/repo.go
  25. +3
    -3
      modules/convert/cloudbrain.go
  26. +105
    -0
      modules/git/repo_branch.go
  27. +65
    -10
      modules/grampus/grampus.go
  28. +3
    -9
      modules/grampus/resty.go
  29. +3
    -4
      modules/modelarts/modelarts.go
  30. +6
    -0
      modules/redis/redis_key/cloudbrain_redis_key.go
  31. +3
    -0
      modules/repository/repo.go
  32. +19
    -0
      modules/setting/setting.go
  33. +16
    -0
      modules/storage/minio_ext.go
  34. +33
    -4
      modules/storage/obs.go
  35. +27
    -27
      modules/structs/cloudbrain.go
  36. +9
    -1
      modules/templates/helper.go
  37. +26
    -4
      options/locale/locale_en-US.ini
  38. +26
    -5
      options/locale/locale_zh-CN.ini
  39. +34
    -65
      package-lock.json
  40. +8
    -5
      public/home/home.js
  41. BIN
      public/img/login_bg_default.png
  42. +1
    -1
      routers/admin/cloudbrains.go
  43. +6
    -0
      routers/api/v1/api.go
  44. +45
    -0
      routers/api/v1/repo/attachments.go
  45. +2
    -0
      routers/api/v1/repo/cloudbrain.go
  46. +48
    -18
      routers/api/v1/repo/cloudbrain_dashboard.go
  47. +22
    -0
      routers/api/v1/repo/datasets.go
  48. +5
    -0
      routers/api/v1/repo/modelmanage.go
  49. +20
    -0
      routers/api/v1/user/repo.go
  50. +4
    -0
      routers/home.go
  51. +1
    -1
      routers/repo/ai_model_manage.go
  52. +23
    -7
      routers/repo/aisafety.go
  53. +248
    -161
      routers/repo/cloudbrain.go
  54. +1
    -0
      routers/repo/dataset.go
  55. +195
    -98
      routers/repo/grampus.go
  56. +24
    -0
      routers/repo/issue.go
  57. +172
    -121
      routers/repo/modelarts.go
  58. +24
    -20
      routers/routes/routes.go
  59. +14
    -7
      routers/user/auth.go
  60. +1
    -1
      routers/user/home.go
  61. +14
    -14
      services/cloudbrain/clear.go
  62. +30
    -0
      services/cloudbrain/cloudbrainTask/ai_model.go
  63. +21
    -18
      services/cloudbrain/cloudbrainTask/count.go
  64. +54
    -47
      services/cloudbrain/cloudbrainTask/inference.go
  65. +99
    -61
      services/cloudbrain/cloudbrainTask/notebook.go
  66. +33
    -44
      services/cloudbrain/cloudbrainTask/train.go
  67. +20
    -0
      services/cloudbrain/lock.go
  68. +31
    -0
      services/lock/cloudbrain_name_lock.go
  69. +30
    -0
      services/lock/cloudbrain_uniqueness_lock.go
  70. +17
    -0
      services/lock/lock.go
  71. +42
    -0
      services/lock/lock_operator.go
  72. +4
    -4
      services/mirror/mirror.go
  73. +10
    -6
      services/reward/point/account/point_account.go
  74. +1
    -1
      services/socketwrap/clientManager.go
  75. +8
    -8
      templates/admin/cloudbrain/list.tmpl
  76. +2
    -0
      templates/admin/cloudbrain/search.tmpl
  77. +1
    -0
      templates/admin/cloudbrain/search_dashboard.tmpl
  78. +35
    -0
      templates/annual_privacy.tmpl
  79. +9
    -9
      templates/base/footer.tmpl
  80. +10
    -0
      templates/base/footer_content.tmpl
  81. +7
    -7
      templates/base/footer_fluid.tmpl
  82. +10
    -10
      templates/base/head.tmpl
  83. +10
    -10
      templates/base/head_course.tmpl
  84. +10
    -10
      templates/base/head_fluid.tmpl
  85. +14
    -14
      templates/base/head_home.tmpl
  86. +10
    -10
      templates/base/head_pro.tmpl
  87. +2
    -0
      templates/custom/header.tmpl
  88. +39
    -1
      templates/custom/home/home_top.tmpl
  89. +2
    -2
      templates/custom/task_wait_count.tmpl
  90. +1
    -0
      templates/explore/images.tmpl
  91. +4
    -4
      templates/explore/organizations.tmpl
  92. +2
    -2
      templates/explore/repo_orgtop.tmpl
  93. +1
    -1
      templates/explore/search_new.tmpl
  94. +3
    -1
      templates/home.tmpl
  95. +125
    -259
      templates/repo/cloudbrain/benchmark/new.tmpl
  96. +30
    -21
      templates/repo/cloudbrain/benchmark/show.tmpl
  97. +1
    -1
      templates/repo/cloudbrain/inference/new.tmpl
  98. +12
    -4
      templates/repo/cloudbrain/inference/show.tmpl
  99. +3
    -2
      templates/repo/cloudbrain/new.tmpl
  100. +3
    -0
      templates/repo/cloudbrain/show.tmpl

+ 1
- 0
.gitignore View File

@@ -56,6 +56,7 @@ coverage.all
/custom/conf/app.ini
!/custom/conf/app.ini.sample
/custom/public/kanban
/custom/public/annual-report
/data
/indexers
/log


+ 1
- 0
custom/public/css/placeholder-home.css View File

@@ -0,0 +1 @@
/* placeholder-home.css */

+ 1
- 0
custom/public/css/placeholder.css View File

@@ -0,0 +1 @@
/* placeholder.css */

BIN
custom/public/img/home-banner-02-1.jpg View File

Before After
Width: 1920  |  Height: 548  |  Size: 152 KiB

BIN
custom/public/img/home-banner-02-2.png View File

Before After
Width: 790  |  Height: 315  |  Size: 247 KiB

+ 45
- 0
custom/public/img/logo-w-origin.svg View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 26.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 160 64" style="enable-background:new 0 0 160 64;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{display:none;fill:#FFFFFF;}
</style>
<g>
<path class="st0" d="M105.3,33.3H87.1c-2.6,0.1-4,1.3-4,3.8v8.3c0.1,2.2,1.5,3.3,4,3.5h18c2.5-0.1,3.8-1.3,3.9-3.6v-8.2
c0.1-2-1.4-3.6-3.4-3.8C105.6,33.3,105.4,33.3,105.3,33.3z M104.6,43.9c-0.1,1-0.7,1.5-1.9,1.7H89.3c-1.3-0.3-1.8-0.7-1.9-1.7v-5.4
c0-1,0.8-1.9,1.8-1.9c0,0,0.1,0,0.1,0h13.1c1.1,0,2,0.8,2.1,2L104.6,43.9z"/>
<path class="st0" d="M81,25.3v-4.7c0-1.1,0.9-2.1,2.1-2.1h19c1.4-0.1,2.1,0.5,2.1,1.8v3.3c0,1.1-0.7,1.7-1.9,1.7H82.8v3.2H105
c2.3,0,3.6-1.1,3.6-3.2v-6.4c0.2-1.8-1.1-3.4-2.8-3.6c-0.3,0-0.5,0-0.8,0h-9.7v-2.6h-4.6v2.6H80.3c-2.6,0-3.9,1.2-3.9,3.9v12.3
c0,5.8-0.9,11.6-2.6,17.1l4.3,0.8c1.8-5.5,2.7-11.3,2.8-17.1v-7.2H81z"/>
<path class="st0" d="M116.2,30.4l4.4,2.4c2.6-1.9,4.4-4.6,5.1-7.6h7.8v-3.2h-7.1c0.2-1.3,0.3-2.6,0.3-3.9h6.6v-3.2h-12.3v-2h-4.6
V18h5.8c0,1.3-0.1,2.6-0.3,3.9h-6.7v3.3h5.8C120.4,27.5,118.6,29.4,116.2,30.4z"/>
<path class="st0" d="M126.5,26.7c1.2,1.8,2.1,3.8,2.9,5.8h4.9c-0.8-2-1.8-4-2.9-5.8H126.5z"/>
<path class="st0" d="M145.4,33.5h-24.7c-2.4,0.3-3.8,1.4-3.9,3.5v6.2h28.4v1.3c0,1.1-0.7,1.7-2.1,1.7h-19.7c-1.3,0-1.9-0.5-1.9-1.5
h-4.5V46c0,1.9,1.6,3.5,3.5,3.6h25.1c2.6-0.1,4-1.3,4-3.5v-9C149.2,35,147.5,33.5,145.4,33.5z M145,39.9h-23.7v-1.1
c0-1,0.8-1.9,1.8-1.9c0,0,0.1,0,0.1,0H143c1.3,0,2.1,0.7,2.1,1.9L145,39.9z"/>
<path class="st0" d="M147.3,14h-8.2c-2.2,0.1-3.5,1.1-3.8,2.9v11.7c0.1,1.6,1.4,2.9,3.1,2.9h8.7c1.9-0.1,3.1-1.1,3.1-2.9V17
C150.4,15.4,149.4,14.3,147.3,14z M146,26.2c0,1.4-0.7,2.1-1.9,2.1h-2.4c-1,0-1.8-0.8-1.8-1.8c0-0.1,0-0.1,0-0.2v-7
c0-1,0.8-1.9,1.8-1.9c0,0,0.1,0,0.1,0h2c1.1,0,2.1,0.8,2.1,1.9l0,0L146,26.2z"/>
</g>
<path class="st1" d="M67.2,44.1V20c0-2.6-1.4-5.1-3.7-6.4l-20.9-12c-2.3-1.3-5.1-1.3-7.4,0l-20.9,12c-2.3,1.3-3.7,3.8-3.7,6.4v24.1
c0,2.6,1.4,5.1,3.7,6.4l20.9,12c2.3,1.3,5.1,1.3,7.4,0l20.9-12C65.8,49.2,67.2,46.7,67.2,44.1z"/>
<path class="st0" d="M61.9,15.4L42,3.9c-1.9-1.1-4.3-1.1-6.2,0L15.9,15.4c-1.9,1.1-3.1,3.2-3.1,5.4v22.9c0,2.2,1.2,4.3,3.1,5.4
l3.8,2c0.8,0.4,0.8,1,0.8,1.9c0,0,0,0.1,0,0.1c0.1,1.6,1.8,3.5,4.2,3.5c2.3,0,4.3-1.9,4.4-4.2c0-1.6-0.8-3.1-2.3-3.9
c-0.6-0.3-1.7-0.5-2.9-0.4c-0.9,0.1-1,0.6-2.8-0.5l-2.8-1.6c-0.8-0.5-1.7-1.3-1.6-2.3V22c0-1.8,0.8-2.8,2.1-3.5L37,7.8
C38.1,7,40.2,7.2,41.5,8l16.4,9.5c2.9,1.6,3,3,3,4v19.7c0,2.3-1.5,4-2.3,4.5l-15.1,8.5C42.8,54.5,42,54,42,53.3l0-2.5
c0-0.1,0-0.3,0-0.4v-2.5c0-0.8,0.4-1.6,1.1-2l8.8-5.7c1.4-0.9,2-1.7,2-3.8L53.7,28c0-1,0.4-1.9,1.2-2.5c1.5-1.3,2-3.7,0.8-5.6
c-0.8-1.4-2.4-2.2-4-2c-1.6,0.1-2.8,1-3.5,2.4c-0.5,1-0.6,2.2-0.3,3.3c0.2,0.8,0.7,1.4,1.3,2c0.7,0.6,1.2,1.5,1.2,2.5v7.2
c0,1.1-0.5,2.1-1.5,2.7l-5.5,2.8c-0.7,0.5-1.6,0-1.6-0.8l-0.2-17.1c0-1,0.5-1.9,1.2-2.5c0.4-0.3,0.7-0.8,1-1.3
c0.7-1.3,0.7-2.9-0.1-4.3c-0.8-1.4-2.5-2.2-4.1-2.1c-2.9,0.3-4.6,3.1-3.8,5.7c0.2,0.8,0.7,1.4,1.3,2c0.7,0.6,1.2,1.5,1.2,2.5v9.9
c0,0.8-0.8,1.3-1.5,0.9L34,32.5c-0.7-0.4-1.2-1.2-1.2-2.1v-2.2c0-1,0.4-1.9,1.2-2.5c1.5-1.3,2-3.7,0.8-5.6c-0.8-1.3-2.4-2.1-4-2
c-2.9,0.2-4.7,3.1-3.8,5.7c0.2,0.8,0.7,1.5,1.3,2c0.7,0.6,1.2,1.5,1.2,2.5l0,3.5c0,1,0,2,1.6,3.1l5.5,3c0.7,0.4,1.2,1.2,1.2,2.1v4.5
c0,0.8-0.8,1.3-1.5,0.9L26.6,41c-0.7-0.4-1.2-1.2-1.2-2.1l-0.2-6.1c0-1,0.4-1.8,1.1-2.5c1.4-1.3,1.9-3.4,0.9-5.3
c-0.8-1.4-2.4-2.3-4-2.2c-2.9,0.2-4.6,3-3.8,5.6c0.2,0.7,0.7,1.4,1.2,1.9c0.7,0.6,1.1,1.5,1.1,2.5l-0.5,6.8c0,1.9,0.3,2.8,1.8,3.5
l11.8,6.3c1,0.6,1.6,1.7,1.6,2.8l0,3.1c0,3.1,4.3,5.7,8.7,3.3l16.4-9.8c1.9-1,3.2-3,3.4-5.2V20.7C65,18.5,63.8,16.5,61.9,15.4z
M24.2,50.7c1.1,0,2,0.9,2,2c0,1.1-0.9,2-2,2c-1.1,0-2-0.9-2-2C22.2,51.7,23.1,50.7,24.2,50.7z M48.7,21.5c0-1.1,0.9-2,2-2
s2,0.9,2,2c0,1.1-0.9,2-2,2S48.7,22.6,48.7,21.5z M30.6,23.8c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.1,0,2,0.9,2,2S31.8,23.8,30.6,23.8z
M22.2,26.4c0-1.1,0.9-2,2-2c1.1,0,2,0.9,2,2s-0.9,2-2,2C23.1,28.4,22.2,27.5,22.2,26.4z M40,17.9c-1.1,0-2-0.9-2-2c0-1.1,0.9-2,2-2
c1.1,0,2,0.9,2,2C42,17,41.1,17.9,40,17.9z"/>
</svg>

+ 1
- 45
custom/public/img/logo-w.svg
File diff suppressed because it is too large
View File


+ 1
- 0
custom/public/js/placeholder-home.js View File

@@ -0,0 +1 @@
/* placeholder-home.js */

+ 1
- 0
custom/public/js/placeholder.js View File

@@ -0,0 +1 @@
/* placeholder.js */

+ 3
- 1
models/action.go View File

@@ -67,6 +67,7 @@ const (
ActionChangeUserAvatar //38
ActionCreateGrampusNPUDebugTask //39
ActionCreateGrampusGPUDebugTask //40
ActionCreateGrampusGCUDebugTask //41
)

// Action represents user operation type and other information to
@@ -380,7 +381,8 @@ func (a *Action) IsCloudbrainAction() bool {
ActionCreateGrampusGPUDebugTask,
ActionCreateGrampusNPUDebugTask,
ActionCreateGrampusNPUTrainTask,
ActionCreateGrampusGPUTrainTask:
ActionCreateGrampusGPUTrainTask,
ActionCreateGrampusGCUDebugTask:
return true
}
return false


+ 8
- 17
models/ai_model_manage.go View File

@@ -237,13 +237,10 @@ func QueryModelConvertByName(name string, repoId int64) ([]*AiModelConvert, erro
func QueryModelConvertById(id string) (*AiModelConvert, error) {
sess := x.NewSession()
defer sess.Close()
sess.Select("*").Table(new(AiModelConvert)).Where("id='" + id + "'")
aiModelManageConvertList := make([]*AiModelConvert, 0)
err := sess.Find(&aiModelManageConvertList)
if err == nil {
if len(aiModelManageConvertList) == 1 {
return aiModelManageConvertList[0], nil
}
re := new(AiModelConvert)
isExist, err := sess.Table(new(AiModelConvert)).ID(id).Get(re)
if err == nil && isExist {
return re, nil
}
return nil, err
}
@@ -251,16 +248,10 @@ func QueryModelConvertById(id string) (*AiModelConvert, error) {
func QueryModelById(id string) (*AiModelManage, error) {
sess := x.NewSession()
defer sess.Close()
sess.Select("*").Table("ai_model_manage").
Where("id='" + id + "'")
aiModelManageList := make([]*AiModelManage, 0)
err := sess.Find(&aiModelManageList)
if err == nil {
if len(aiModelManageList) == 1 {
return aiModelManageList[0], nil
}
} else {
log.Info("error=" + err.Error())
re := new(AiModelManage)
isExist, err := sess.Table(new(AiModelManage)).ID(id).Get(re)
if err == nil && isExist {
return re, nil
}
return nil, err
}


+ 11
- 0
models/attachment.go View File

@@ -259,6 +259,17 @@ func GetAttachmentsByCommentID(commentID int64) ([]*Attachment, error) {
return getAttachmentsByCommentID(x, commentID)
}

func GetAttachmentByDatasetIdFileName(fileName string, datasetId int64) (*Attachment, error) {
attach := &Attachment{DatasetID: datasetId, Name: fileName}
has, err := x.Get(attach)
if err != nil {
return nil, err
} else if !has {
return nil, err
}
return attach, nil
}

func getAttachmentsByCommentID(e Engine, commentID int64) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10)
return attachments, e.Where("comment_id=?", commentID).Find(&attachments)


+ 116
- 41
models/cloudbrain.go View File

@@ -30,11 +30,13 @@ const (
TypeCDCenter //成都智算中心

TypeCloudBrainAll = -1
AccCardsNumAll = -1
)

const (
NPUResource = "NPU"
GPUResource = "CPU/GPU"
GCUResource = "GCU"
AllResource = "all"

//notebook storage category
@@ -60,6 +62,7 @@ const (
JobTypeModelSafety JobType = "MODELSAFETY"
JobTypeSnn4imagenet JobType = "SNN4IMAGENET"
JobTypeBrainScore JobType = "BRAINSCORE"
JobTypeSnn4Ecoset JobType = "SNN4ECOSET"
JobTypeTrain JobType = "TRAIN"
JobTypeInference JobType = "INFERENCE"

@@ -134,6 +137,11 @@ const (
//ComputeResource
GPU = "GPU"
NPU = "NPU"
GCU = "GCU"
)

const (
AIModelPath = "aimodels/"
)

type Cloudbrain struct {
@@ -179,14 +187,14 @@ type Cloudbrain struct {
AiCenter string //grampus ai center: center_id+center_name

TrainUrl string //输出模型的obs路径
BranchName string //分支名称
BranchName string `xorm:"varchar(2550)"` //分支名称
Parameters string //传给modelarts的param参数
BootFile string //启动文件
BootFile string `xorm:"varchar(2550)"` //启动文件
DataUrl string `xorm:"varchar(3500)"` //数据集的obs路径
LogUrl string //日志输出的obs路径
PreVersionId int64 //父版本的版本id
FlavorCode string //modelarts上的规格id
Description string `xorm:"varchar(256)"` //描述
Description string `xorm:"varchar(2550)"` //描述
WorkServerNumber int //节点数
FlavorName string //规格名称
EngineName string //引擎名称
@@ -302,6 +310,9 @@ func (task *Cloudbrain) IsUserHasRight(user *User) bool {
func (task *Cloudbrain) IsGPUTask() bool {
return task.ComputeResource == GPUResource
}
func (task *Cloudbrain) IsGCUTask() bool {
return task.ComputeResource == GCUResource
}
func (task *Cloudbrain) IsNPUTask() bool {
return task.ComputeResource == NPUResource
}
@@ -335,6 +346,19 @@ func IsModelArtsDebugJobTerminal(status string) bool {
func IsCloudBrainOneDebugJobTerminal(status string) bool {
return status == string(JobStopped) || status == string(JobFailed) || status == string(JobSucceeded)
}
func IsModelBenchMarkJobType(jobType string) bool {
types := AllBenchMarkJobTYpe()
for _, t := range types {
if jobType == string(t) {
return true
}
}
return false
}

func AllBenchMarkJobTYpe() []JobType {
return []JobType{JobTypeBenchmark, JobTypeModelSafety, JobTypeSnn4imagenet, JobTypeBrainScore, JobTypeSnn4Ecoset}
}

func ParseAndSetDurationFromCloudBrainOne(result JobResultPayload, task *Cloudbrain) {
isActivated := result.JobStatus.CreatedTime > 0
@@ -449,29 +473,32 @@ type GetImagesPayload struct {

type CloudbrainsOptions struct {
ListOptions
RepoID int64 // include all repos if empty
UserID int64
JobID string
SortType string
CloudbrainIDs []int64
JobStatus []string
JobStatusNot bool
Keyword string
Type int
JobTypes []string
VersionName string
IsLatestVersion string
JobTypeNot bool
NeedRepoInfo bool
RepoIDList []int64
BeginTime time.Time
EndTime time.Time
ComputeResource string
BeginTimeUnix int64
EndTimeUnix int64
AiCenter string
NeedDeleteInfo string
Cluster string
RepoID int64 // include all repos if empty
UserID int64
JobID string
SortType string
CloudbrainIDs []int64
JobStatus []string
JobStatusNot bool
Keyword string
Type int
JobTypes []string
VersionName string
IsLatestVersion string
JobTypeNot bool
NeedRepoInfo bool
RepoIDList []int64
BeginTime time.Time
EndTime time.Time
ComputeResource string
BeginTimeUnix int64
EndTimeUnix int64
AiCenter string
NeedDeleteInfo string
Cluster string
AccCardType string
AccCardsNum int
WorkServerNumber int
}

type TaskPod struct {
@@ -1453,7 +1480,7 @@ type GetNotebookListResult struct {
NotebookList []NotebookList `json:"data"`
}

//Grampus
// Grampus
type GrampusResult struct {
ErrorCode int `json:"errorCode"`
ErrorMsg string `json:"errorMsg"`
@@ -1559,7 +1586,8 @@ type CreateGrampusJobResponse struct {

type GetGrampusJobResponse struct {
GrampusResult
JobInfo GrampusJobInfo `json:"otJob"`
JobInfo GrampusJobInfo `json:"otJob"`
ExitDiagnostics string `json:"exitDiagnostics"`
}

type GrampusNotebookResponse struct {
@@ -1643,6 +1671,15 @@ type Metrics struct {
Value []string `json:"value"` //获取的监控值的序列,元素为String类型
}

type NewModelArtsMetricStatisticResult struct {
MetricsInfo []NewModelArtsMetrics `json:"metrics"` //监控详情
}

type NewModelArtsMetrics struct {
Metric string `json:"metric"` //监控指标项
Value []float32 `json:"value"` //获取的监控值的序列,元素为float类型
}

func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
sess := x.NewSession()
defer sess.Close()
@@ -1841,7 +1878,7 @@ func QueryModelTrainJobList(repoId int64) ([]*Cloudbrain, int, error) {
// )

cloudbrains := make([]*Cloudbrain, 0)
if err := sess.Select("job_id,display_job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC").
if err := sess.Select("*").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC").
Find(&cloudbrains); err != nil {
return nil, 0, fmt.Errorf("Find: %v", err)
}
@@ -2168,7 +2205,7 @@ func GetCloudBrainUnStoppedJob() ([]*Cloudbrain, error) {
Find(&cloudbrains)
}

func GetCloudBrainOneStoppedNotDebugJobDaysAgo(days int, limit int) ([]*Cloudbrain, error) {
func GetGPUStoppedNotDebugJobDaysAgo(days int, limit int) ([]*Cloudbrain, error) {
cloudbrains := make([]*Cloudbrain, 0, 10)
endTimeBefore := time.Now().Unix() - int64(days)*24*3600
missEndTimeBefore := endTimeBefore - 24*3600
@@ -2177,22 +2214,24 @@ func GetCloudBrainOneStoppedNotDebugJobDaysAgo(days int, limit int) ([]*Cloudbra
JobStopped, JobSucceeded, JobFailed, ModelArtsCreateFailed, ModelArtsStartFailed, ModelArtsUnavailable, ModelArtsResizFailed, ModelArtsDeleted,
ModelArtsStopped, ModelArtsTrainJobCanceled, ModelArtsTrainJobCheckFailed, ModelArtsTrainJobCompleted, ModelArtsTrainJobDeleteFailed, ModelArtsTrainJobDeployServiceFailed,
ModelArtsTrainJobFailed, ModelArtsTrainJobImageFailed, ModelArtsTrainJobKilled, ModelArtsTrainJobLost, ModelArtsTrainJobSubmitFailed, ModelArtsTrainJobSubmitModelFailed).
Where("(((end_time is null or end_time=0) and updated_unix<? and updated_unix != 0 ) or (end_time<? and end_time != 0)) and cleared=false and type=0 and job_type != 'DEBUG'", missEndTimeBefore, endTimeBefore).
Where("(((end_time is null or end_time=0) and updated_unix<? and updated_unix != 0 ) or (end_time<? and end_time != 0)) and cleared=false and (type=0 or (type =2 and compute_resource='CPU/GPU')) and job_type != 'DEBUG'", missEndTimeBefore, endTimeBefore).
Limit(limit).
Find(&cloudbrains)
}

/**
本方法考虑了再次调试的情况,多次调试取最后一次的任务的结束时间
/*
*

本方法考虑了再次调试的情况,多次调试取最后一次的任务的结束时间
*/
func GetCloudBrainOneStoppedDebugJobDaysAgo(days int, limit int) ([]*Cloudbrain, error) {
func GetGPUStoppedDebugJobDaysAgo(days int, limit int) ([]*Cloudbrain, error) {
cloudbrains := make([]*Cloudbrain, 0, 10)
endTimeBefore := time.Now().Unix() - int64(days)*24*3600
missEndTimeBefore := endTimeBefore - 24*3600
sql := `SELECT id,job_name,job_id from (SELECT DISTINCT ON (job_name)
id, job_name, job_id,status,end_time,updated_unix,cleared
FROM cloudbrain
where type=0 and job_type='DEBUG'
where (type=0 or (type =2 and compute_resource='CPU/GPU')) and job_type='DEBUG'
ORDER BY job_name, updated_unix DESC) a
where status in ('STOPPED','SUCCEEDED','FAILED') and (((end_time is null or end_time=0) and updated_unix<? and updated_unix != 0 ) or (end_time<? and end_time != 0)) and cleared=false`

@@ -2295,11 +2334,10 @@ func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTy
}
return sess.Count(new(Cloudbrain))
}
func GetNotFinalStatusTaskCount(userID int64, notFinalStatus []string, jobTypes []JobType, cloudbrainTypes []int, computeResource string) (int, error) {
func GetNotFinalStatusTaskCount(userID int64, notFinalStatus []string, jobTypes []JobType) (int, error) {
count, err := x.In("status", notFinalStatus).
In("job_type", jobTypes).
In("type", cloudbrainTypes).
And("user_id = ? and compute_resource = ?", userID, computeResource).Count(new(Cloudbrain))
And("user_id = ? ", userID).Count(new(Cloudbrain))
return int(count), err
}

@@ -2431,18 +2469,44 @@ func CloudbrainAll(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
)
}

if opts.WorkServerNumber > 0 {
if opts.WorkServerNumber == 1 {
cond = cond.And(builder.Or(
builder.Eq{"cloudbrain.work_server_number": 0},
builder.Eq{"cloudbrain.work_server_number": 1},
builder.IsNull{"cloudbrain.work_server_number"},
))
} else {
cond = cond.And(
builder.Eq{"cloudbrain.work_server_number": opts.WorkServerNumber},
)
}
}

if opts.AccCardType != "" {
cond = cond.And(builder.Eq{"cloudbrain_spec.acc_card_type": opts.AccCardType})
}
if opts.AccCardsNum >= 0 {
cond = cond.And(builder.Eq{"cloudbrain_spec.acc_cards_num": opts.AccCardsNum})
}

var count int64
var err error
condition := "cloudbrain.user_id = `user`.id"
if len(opts.Keyword) == 0 {
count, err = sess.Unscoped().Where(cond).Count(new(Cloudbrain))
count, err = sess.Table(&Cloudbrain{}).Unscoped().Where(cond).
Join("left", "`user`", condition).
Join("left", "cloudbrain_spec", "cloudbrain.id = cloudbrain_spec.cloudbrain_id").
Count(new(CloudbrainInfo))
} else {
lowerKeyWord := strings.ToLower(opts.Keyword)

cond = cond.And(builder.Or(builder.Like{"LOWER(cloudbrain.job_name)", lowerKeyWord},
builder.Like{"LOWER(cloudbrain.display_job_name)", lowerKeyWord}, builder.Like{"`user`.lower_name", lowerKeyWord}))
count, err = sess.Table(&Cloudbrain{}).Unscoped().Where(cond).
Join("left", "`user`", condition).Count(new(CloudbrainInfo))
Join("left", "`user`", condition).
Join("left", "cloudbrain_spec", "cloudbrain.id = cloudbrain_spec.cloudbrain_id").
Count(new(CloudbrainInfo))

}

@@ -2464,6 +2528,7 @@ func CloudbrainAll(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) {
cloudbrains := make([]*CloudbrainInfo, 0, setting.UI.IssuePagingNum)
if err := sess.Table(&Cloudbrain{}).Unscoped().Where(cond).
Join("left", "`user`", condition).
Join("left", "cloudbrain_spec", "cloudbrain.id = cloudbrain_spec.cloudbrain_id").
Find(&cloudbrains); err != nil {
return nil, 0, fmt.Errorf("Find: %v", err)
}
@@ -2618,6 +2683,8 @@ type DatasetInfo struct {
DataLocalPath string
Name string
FullName string
Type int
Size int64
}

func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetInfo, string, error) {
@@ -2657,8 +2724,14 @@ func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetIn
if len(grampusType) > 0 {
if grampusType[0] == GPU {
dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID
} else {
} else if grampusType[0] == NPU {
dataLocalPath = setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + "/"
} else if grampusType[0] == GCU {
if attach.Type == TypeCloudBrainOne {
dataLocalPath = setting.Attachment.Minio.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID
} else {
dataLocalPath = setting.BasePath + path.Join(attach.UUID[0:1], attach.UUID[1:2]) + "/" + attach.UUID + "/"
}
}

} else {
@@ -2673,6 +2746,8 @@ func GetDatasetInfo(uuidStr string, grampusType ...string) (map[string]DatasetIn
DataLocalPath: dataLocalPath,
Name: fileName,
FullName: attach.Name,
Type: attach.Type,
Size: attach.Size,
}
if i == 0 {
datasetNames = attach.Name


+ 27
- 1
models/issue.go View File

@@ -69,7 +69,8 @@ type Issue struct {

//block_chain
Amount int64
IsTransformed bool `xorm:"INDEX NOT NULL DEFAULT false"`
IsTransformed bool `xorm:"INDEX NOT NULL DEFAULT false"`
StayTop int64 `xorm:"NOT NULL DEFAULT 0"`
}

var (
@@ -775,6 +776,19 @@ func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
return sess.Commit()
}

func (issue *Issue) ChangeStayTop(doer *User, stayTop int64) (err error) {
issue.StayTop = stayTop
sess := x.NewSession()
defer sess.Close()
if err = sess.Begin(); err != nil {
return err
}
if err = updateIssueCols(sess, issue, "stay_top"); err != nil {
return fmt.Errorf("UpdateIssueCols,stayTop: %v", err)
}
return sess.Commit()
}

// ChangeRef changes issue ref, as the given user.
func (issue *Issue) ChangeRef(doer *User, newRef string) (err error) {
oldRef := issue.Ref
@@ -1116,6 +1130,7 @@ type IssuesOptions struct {
// sortIssuesSession sort an issues-related session based on the provided
// sortType string
func sortIssuesSession(sess *xorm.Session, sortType string, priorityRepoID int64) {
sess.Desc("issue.stay_top")
switch sortType {
case "oldest":
sess.Asc("issue.created_unix")
@@ -1966,3 +1981,14 @@ func UpdateReactionsMigrationsByType(gitServiceType structs.GitServiceType, orig
})
return err
}

func GetMaxStayTop(repoId int64) int64 {
re := new(Issue)
isExist, err := x.Table(new(Issue)).Where("repo_id="+fmt.Sprint(repoId)).Desc("stay_top").Limit(1, 0).Get(re)
if err == nil {
if isExist {
return re.StayTop + 1
}
}
return 1
}

+ 5
- 0
models/point_account.go View File

@@ -140,3 +140,8 @@ func GetPointAccountMapByUserIds(userIds []int64) (map[int64]*PointAccount, erro
}
return accountMap, nil
}

type PointDeductCondition struct {
SpecUnitPrice int
WorkServerNumber int
}

+ 1
- 0
models/task_config.go View File

@@ -39,6 +39,7 @@ func GetTaskTypeFromAction(a ActionType) TaskType {
ActionCreateGrampusGPUDebugTask,
ActionCreateGrampusNPUDebugTask,
ActionCreateGrampusNPUTrainTask,
ActionCreateGrampusGCUDebugTask,
ActionCreateGrampusGPUTrainTask:
return TaskCreateCloudbrainTask
case ActionCreateRepo:


+ 6
- 1
models/user.go View File

@@ -16,6 +16,7 @@ import (
"fmt"
_ "image/jpeg" // Needed for jpeg support
"image/png"
"math/rand"
"os"
"path/filepath"
"regexp"
@@ -495,7 +496,11 @@ func (u *User) RealSizedAvatarLink(size int) string {
// may either be a sub-URL to this site, or a full URL to an external avatar
// service.
func (u *User) RelAvatarLink() string {
return u.SizedRelAvatarLink(base.DefaultAvatarSize)
append := ""
if u.UseCustomAvatar {
append = "?" + fmt.Sprint(rand.Intn(100))
}
return u.SizedRelAvatarLink(base.DefaultAvatarSize) + append
}

// AvatarLink returns user avatar absolute link.


+ 24
- 0
models/user_analysis_for_activity.go View File

@@ -1,6 +1,7 @@
package models

import (
"encoding/json"
"fmt"
"time"

@@ -450,19 +451,42 @@ func QueryUserLoginInfo(userIds []int64) []*UserLoginLog {
return loginList
}

var WeekBonusData = make(map[int64][]int)

func QueryUserAnnualReport(userId int64) *UserSummaryCurrentYear {
statictisSess := xStatistic.NewSession()
defer statictisSess.Close()
log.Info("userId=" + fmt.Sprint(userId))
if len(WeekBonusData) == 0 {
WeekBonusData = getBonusWeekDataMap()
}

reList := make([]*UserSummaryCurrentYear, 0)
err := statictisSess.Select("*").Table(new(UserSummaryCurrentYear)).Where("id=" + fmt.Sprint(userId)).Find(&reList)
if err == nil {
if len(reList) > 0 {
record, ok := WeekBonusData[userId]
if ok {
bonusInfo := make(map[string]int)
bonusInfo["order"] = record[0]
bonusInfo["money"] = record[1]
bonusInfo["week"] = record[2]
bonusInfo["num"] = record[3]
bonusInfoJson, _ := json.Marshal(bonusInfo)
reList[0].WeekBonusData = string(bonusInfoJson)
}
return reList[0]
}
} else {
log.Info("error:=" + err.Error())
}
dbuser, err := GetUserByID(userId)
if err == nil {
return &UserSummaryCurrentYear{
ID: dbuser.ID,
Name: dbuser.Name,
RegistDate: dbuser.CreatedUnix,
}
}
return nil
}

+ 185
- 54
models/user_business_analysis.go View File

@@ -330,7 +330,7 @@ func QueryUserStaticDataForUserDefine(opts *UserBusinessAnalysisQueryOptions, wi
DataDate := currentTimeNow.Format("2006-01-02 15:04")

CodeMergeCountMap := queryPullRequest(start_unix, end_unix)
CommitCountMap, _ := queryCommitAction(start_unix, end_unix, 5)
CommitCountMap := queryCommitAction(start_unix, end_unix, 5)
IssueCountMap := queryCreateIssue(start_unix, end_unix)

CommentCountMap := queryComment(start_unix, end_unix)
@@ -586,7 +586,7 @@ func refreshUserStaticTable(wikiCountMap map[string]int, tableName string, pageS
startTime := currentTimeNow.AddDate(0, 0, -1)

CodeMergeCountMap := queryPullRequest(start_unix, end_unix)
CommitCountMap, _ := queryCommitAction(start_unix, end_unix, 5)
CommitCountMap := queryCommitAction(start_unix, end_unix, 5)
IssueCountMap := queryCreateIssue(start_unix, end_unix)

CommentCountMap := queryComment(start_unix, end_unix)
@@ -762,7 +762,8 @@ func RefreshUserYearTable(pageStartTime time.Time, pageEndTime time.Time) {
end_unix := pageEndTime.Unix()

CodeMergeCountMap := queryPullRequest(start_unix, end_unix)
CommitCountMap, mostActiveMap := queryCommitAction(start_unix, end_unix, 5)
CommitCountMap := queryCommitAction(start_unix, end_unix, 5)
mostActiveMap := queryMostActiveCommitAction(start_unix, end_unix)
IssueCountMap := queryCreateIssue(start_unix, end_unix)

CommentCountMap := queryComment(start_unix, end_unix)
@@ -841,17 +842,21 @@ func RefreshUserYearTable(pageStartTime time.Time, pageEndTime time.Time) {
repoInfo := getRepoDetailInfo(DetailInfoMap, dateRecordAll.ID, MostDownloadMap)
dataSetInfo, datasetscore := getDataSetInfo(dateRecordAll.ID, CreatedDataset, dataSetDownloadMap, CommitDatasetNumMap, CollectedDataset)
scoreMap["datasetscore"] = datasetscore
codeInfo, codescore := getCodeInfo(dateRecordAll)
codeInfo, codescore := getCodeInfo(&dateRecordAll)
scoreMap["codescore"] = codescore
cloudBrainInfo := getCloudBrainInfo(dateRecordAll, CloudBrainTaskItemMap, scoreMap)
cloudBrainInfo := getCloudBrainInfo(&dateRecordAll, CloudBrainTaskItemMap, scoreMap)
playARoll := getPlayARoll(bonusMap, dateRecordAll.Name, scoreMap)
exteral := 0
if int(subTime.Hours())%24 > 0 {
exteral = 1
}
re := &UserSummaryCurrentYear{
ID: dateRecordAll.ID,
Name: dateRecordAll.Name,
Email: dateRecordAll.Email,
Phone: dateRecordAll.Phone,
RegistDate: dateRecordAll.RegistDate,
DateCount: int(subTime.Hours()) / 24,
DateCount: int(subTime.Hours())/24 + exteral,
MostActiveDay: mostActiveDay,
RepoInfo: repoInfo,
DataSetInfo: dataSetInfo,
@@ -869,15 +874,74 @@ func RefreshUserYearTable(pageStartTime time.Time, pageEndTime time.Time) {
log.Info("update user year data finished. ")
}

func isUserYearData(tableName string) bool {
if tableName == "user_business_analysis_current_year" {
currentTimeNow := time.Now()
if currentTimeNow.Year() >= 2023 {
return false
func getBonusWeekDataMap() map[int64][]int {
bonusMap := make(map[int64][]int)
url := setting.RecommentRepoAddr + "bonus/weekdata/record.txt"
content, err := GetContentFromPromote(url)
if err == nil {
filenames := strings.Split(content, "\n")
for i := 0; i < len(filenames); i++ {
if strings.HasSuffix(filenames[i], "\r") {
filenames[i] = filenames[i][0 : len(filenames[i])-len("\r")]
}
url = setting.RecommentRepoAddr + "bonus/weekdata/" + filenames[i]
csvContent, err1 := GetContentFromPromote(url)
if err1 == nil {
//read csv
lines := strings.Split(csvContent, "\n")
for j := 1; j < len(lines); j++ {
if strings.HasSuffix(lines[j], "\r") {
lines[j] = lines[j][0 : len(lines[j])-len("\r")]
}
log.Info("aLine=" + lines[j])
aLine := strings.Split(lines[j], ",")
if len(aLine) < 4 {
continue
}
userId := getInt64Value(aLine[0])
order := getIntValue(aLine[2])
money := getIntValue(aLine[3])
week, num := getWeekAndNum(filenames[i])
//log.Info("userId=" + fmt.Sprint(userId) + " order=" + fmt.Sprint(order) + " money=" + fmt.Sprint(money) + " week=" + fmt.Sprint(week) + " num=" + fmt.Sprint(num))
//email := lines[2]
record, ok := bonusMap[userId]
if !ok {
record = make([]int, 4)
record[0] = order
record[1] = money
record[2] = week
record[3] = num
bonusMap[userId] = record
} else {
if record[0] > order {
record[0] = order
record[1] = money
record[2] = week
record[3] = num
} else {
if record[0] == order && record[1] < money {
record[1] = money
record[2] = week
record[3] = num
}
}
}
}
}
}
return true
}
return false
return bonusMap
}

func getWeekAndNum(name string) (int, int) {
name = name[0 : len(name)-4]
tmp := strings.Split(name, "_")
if len(tmp) == 2 {
week := getIntValue(tmp[0])
num := getIntValue(tmp[1])
return week, num
}
return 0, 0
}

func getBonusMap() map[string]map[string]int {
@@ -887,12 +951,18 @@ func getBonusMap() map[string]map[string]int {
if err == nil {
filenames := strings.Split(content, "\n")
for i := 0; i < len(filenames); i++ {
if strings.HasSuffix(filenames[i], "\r") {
filenames[i] = filenames[i][0 : len(filenames[i])-len("\r")]
}
url = setting.RecommentRepoAddr + "bonus/" + filenames[i]
csvContent, err1 := GetContentFromPromote(url)
if err1 == nil {
//read csv
lines := strings.Split(csvContent, "\n")
for j := 1; j < len(lines); j++ {
if strings.HasSuffix(lines[j], "\r") {
lines[j] = lines[j][0 : len(lines[j])-len("\r")]
}
aLine := strings.Split(lines[j], ",")
if len(aLine) < 7 {
continue
@@ -923,6 +993,14 @@ func getIntValue(val string) int {
return 0
}

func getInt64Value(val string) int64 {
i, err := strconv.ParseInt(val, 10, 64)
if err == nil {
return i
}
return 0
}

func getPlayARoll(bonusMap map[string]map[string]int, userName string, scoreMap map[string]float64) string {
bonusInfo := make(map[string]string)
record, ok := bonusMap[userName]
@@ -943,7 +1021,7 @@ func getPlayARoll(bonusMap map[string]map[string]int, userName string, scoreMap
}
}

func getCloudBrainInfo(dateRecordAll UserBusinessAnalysisAll, CloudBrainTaskItemMap map[string]int, scoreMap map[string]float64) string {
func getCloudBrainInfo(dateRecordAll *UserBusinessAnalysisAll, CloudBrainTaskItemMap map[string]int, scoreMap map[string]float64) string {
trainscore := 0.0
debugscore := 0.0
runtime := 0.0
@@ -959,19 +1037,16 @@ func getCloudBrainInfo(dateRecordAll UserBusinessAnalysisAll, CloudBrainTaskItem
trainscore = float64(dateRecordAll.GpuTrainJob+dateRecordAll.NpuTrainJob) / float64(50)
}
cloudBrainInfo["inference_task_num"] = fmt.Sprint(dateRecordAll.NpuInferenceJob + CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_GpuInferenceJob"])
cloudBrainInfo["benchmark_task_num"] = fmt.Sprint(dateRecordAll.GpuBenchMarkJob)
cloudBrainInfo["card_runtime"] = fmt.Sprint(dateRecordAll.CloudBrainRunTime)
if dateRecordAll.CloudBrainRunTime >= 100 {
runtime = float64(dateRecordAll.CloudBrainRunTime) / float64(100)
}
cloudBrainInfo["card_runtime_money"] = fmt.Sprint(dateRecordAll.CloudBrainRunTime * 5)
cloudBrainInfo["CloudBrainOne"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_CloudBrainOne"])
cloudBrainInfo["CloudBrainTwo"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_CloudBrainTwo"])
cloudBrainInfo["C2Net"] = fmt.Sprint(CloudBrainTaskItemMap[fmt.Sprint(dateRecordAll.ID)+"_C2Net"])

cloudBrainInfoJson, _ := json.Marshal(cloudBrainInfo)
scoreMap["trainscore"] = trainscore
scoreMap["debugscore"] = debugscore
scoreMap["runtime"] = runtime
return string(cloudBrainInfoJson)
} else {
scoreMap["trainscore"] = trainscore
@@ -981,7 +1056,7 @@ func getCloudBrainInfo(dateRecordAll UserBusinessAnalysisAll, CloudBrainTaskItem
}
}

func getCodeInfo(dateRecordAll UserBusinessAnalysisAll) (string, float64) {
func getCodeInfo(dateRecordAll *UserBusinessAnalysisAll) (string, float64) {
if dateRecordAll.CommitCount > 0 {
codeInfo := make(map[string]string)
codeInfo["commit_count"] = fmt.Sprint(dateRecordAll.CommitCount)
@@ -1165,7 +1240,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,

DataDate := CountDate.Format("2006-01-02")
CodeMergeCountMap := queryPullRequest(start_unix, end_unix)
CommitCountMap, _ := queryCommitAction(start_unix, end_unix, 5)
CommitCountMap := queryCommitAction(start_unix, end_unix, 5)
IssueCountMap := queryCreateIssue(start_unix, end_unix)

CommentCountMap := queryComment(start_unix, end_unix)
@@ -1311,7 +1386,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time,
useMetrics.TotalActivateRegistUser = getMapKeyStringValue("TotalActivateRegistUser", userMetrics)
useMetrics.TotalHasActivityUser = getMapKeyStringValue("TotalHasActivityUser", userMetrics)
useMetrics.CurrentDayRegistUser = getMapKeyStringValue("CurrentDayRegistUser", userMetrics)
count, err = sess.Where("type=0").Count(new(User))
count, err = sess.Where("type=0 and created_unix<=" + fmt.Sprint(end_unix)).Count(new(User))
if err != nil {
log.Info("query user error. return.")
}
@@ -1659,52 +1734,48 @@ func queryPullRequest(start_unix int64, end_unix int64) map[int64]int {
return resultMap
}

func queryCommitAction(start_unix int64, end_unix int64, actionType int64) (map[int64]int, map[int64]map[string]int) {
func queryMostActiveCommitAction(start_unix int64, end_unix int64) map[int64]map[string]int {
sess := x.NewSession()
defer sess.Close()
resultMap := make(map[int64]int)
mostActiveMap := make(map[int64]map[string]int)
cond := "user_id=act_user_id and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix)

count, err := sess.Where(cond).Count(new(Action))
if err != nil {
log.Info("query action error. return.")
return resultMap, mostActiveMap
return mostActiveMap
}

var indexTotal int64
indexTotal = 0
for {
sess.Select("id,user_id,op_type,act_user_id,created_unix").Table("action").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal))
actionList := make([]*Action, 0)
sess.Find(&actionList)

log.Info("query action size=" + fmt.Sprint(len(actionList)))
actionList, err := sess.QueryInterface("select id,user_id,op_type,act_user_id,created_unix from public.action where " + cond + " order by id asc limit " + fmt.Sprint(PAGE_SIZE) + " offset " + fmt.Sprint(indexTotal))
if err != nil {
log.Info("error:" + err.Error())
continue
}
log.Info("query mostactive action size=" + fmt.Sprint(len(actionList)))
for _, actionRecord := range actionList {
if int64(actionRecord.OpType) == actionType {
if _, ok := resultMap[actionRecord.UserID]; !ok {
resultMap[actionRecord.UserID] = 1
} else {
resultMap[actionRecord.UserID] += 1
}
}
key := getDate(actionRecord.CreatedUnix)
if _, ok := mostActiveMap[actionRecord.UserID]; !ok {
userId := convertInterfaceToInt64(actionRecord["user_id"])
created_unix := timeutil.TimeStamp(convertInterfaceToInt64(actionRecord["created_unix"]))
key := getDate(created_unix)
if _, ok := mostActiveMap[userId]; !ok {
tmpMap := make(map[string]int)
tmpMap[key] = 1
mostActiveMap[actionRecord.UserID] = tmpMap
mostActiveMap[userId] = tmpMap
} else {
mostActiveMap[actionRecord.UserID][key] = getMapKeyStringValue(key, mostActiveMap[actionRecord.UserID]) + 1
mostActiveMap[userId][key] = getMapKeyStringValue(key, mostActiveMap[userId]) + 1
}
utcTime := actionRecord.CreatedUnix.AsTime()
utcTime := created_unix.AsTime()
hour := utcTime.Hour()
if hour >= 0 && hour <= 5 {
key = "hour_hour"
if getMapKeyStringValue(key, mostActiveMap[actionRecord.UserID]) < hour {
mostActiveMap[actionRecord.UserID][key] = hour
mostActiveMap[actionRecord.UserID]["hour_day"] = utcTime.Day()
mostActiveMap[actionRecord.UserID]["hour_month"] = int(utcTime.Month())
mostActiveMap[actionRecord.UserID]["hour_year"] = utcTime.Year()
if getMapKeyStringValue(key, mostActiveMap[userId]) < hour {
mostActiveMap[userId][key] = hour
mostActiveMap[userId]["hour_day"] = utcTime.Day()
mostActiveMap[userId]["hour_month"] = int(utcTime.Month())
mostActiveMap[userId]["hour_year"] = utcTime.Year()
}
}
}
@@ -1713,9 +1784,60 @@ func queryCommitAction(start_unix int64, end_unix int64, actionType int64) (map[
break
}
}
return mostActiveMap
}

func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[int64]int {
sess := x.NewSession()
defer sess.Close()
resultMap := make(map[int64]int)
cond := "op_type=" + fmt.Sprint(actionType) + " and user_id=act_user_id and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix)
count, err := sess.Where(cond).Count(new(Action))
if err != nil {
log.Info("query action error. return.")
return resultMap
}
var indexTotal int64
indexTotal = 0
for {
actionList, err := sess.QueryInterface("select id,user_id,op_type,act_user_id,created_unix from public.action where " + cond + " order by id asc limit " + fmt.Sprint(PAGE_SIZE) + " offset " + fmt.Sprint(indexTotal))
if err != nil {
log.Info("error:" + err.Error())
continue
}
log.Info("query action size=" + fmt.Sprint(len(actionList)))
for _, actionRecord := range actionList {
userId := convertInterfaceToInt64(actionRecord["user_id"])

return resultMap, mostActiveMap
if _, ok := resultMap[userId]; !ok {
resultMap[userId] = 1
} else {
resultMap[userId] += 1
}

}
indexTotal += PAGE_SIZE
if indexTotal >= count {
break
}
}
return resultMap
}

func convertInterfaceToInt64(obj interface{}) int64 {
switch obj.(type) {
case int8:
return int64(obj.(int8))
case int16:
return int64(obj.(int16))
case int32:
return int64(obj.(int32))
case int64:
return obj.(int64)
}
return 0
}

func getDate(createTime timeutil.TimeStamp) string {
return createTime.Format("2006-01-02")
}
@@ -2178,7 +2300,7 @@ func queryUserCreateRepo(start_unix int64, end_unix int64) (map[int64]int, map[s
var indexTotal int64
indexTotal = 0
for {
sess.Select("id,owner_id,name,is_private,clone_cnt").Table("repository").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal))
sess.Select("id,owner_id,name,is_private,clone_cnt,alias").Table("repository").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal))
repoList := make([]*Repository, 0)
sess.Find(&repoList)
log.Info("query Repository size=" + fmt.Sprint(len(repoList)))
@@ -2401,6 +2523,13 @@ func queryUserModelConvert(start_unix int64, end_unix int64) map[int64]int {
return resultMap
}

func isBenchMark(JobType string) bool {
if JobType == "BENCHMARK" || JobType == "MODELSAFETY" || JobType == "SNN4IMAGENET" || JobType == "BRAINSCORE" || JobType == "SNN4ECOSET" {
return true
}
return false
}

func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[string]int) {
sess := x.NewSession()
defer sess.Close()
@@ -2408,15 +2537,16 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s
resultItemMap := make(map[string]int)

cond := " created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix)
count, err := sess.Where(cond).Count(new(Cloudbrain))
count, err := sess.Where(cond).Unscoped().Count(new(Cloudbrain))
if err != nil {
log.Info("query cloudbrain error. return.")
return resultMap, resultItemMap
}
log.Info("cloudbrain count=" + fmt.Sprint(count))
var indexTotal int64
indexTotal = 0
for {
sess.Select("id,job_type,user_id,duration,train_job_duration,type").Table("cloudbrain").Unscoped().Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal))
sess.Select("id,job_type,user_id,duration,train_job_duration,type,compute_resource").Table("cloudbrain").Unscoped().Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal))
cloudTaskList := make([]*Cloudbrain, 0)
sess.Find(&cloudTaskList)
log.Info("query cloudbrain size=" + fmt.Sprint(len(cloudTaskList)))
@@ -2435,6 +2565,8 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s
setMapKey("NpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap)
} else if cloudTaskRecord.JobType == "INFERENCE" {
setMapKey("NpuInferenceJob", cloudTaskRecord.UserID, 1, resultItemMap)
} else if isBenchMark(cloudTaskRecord.JobType) {
setMapKey("GpuBenchMarkJob", cloudTaskRecord.UserID, 1, resultItemMap)
} else {
setMapKey("NpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap)
}
@@ -2444,12 +2576,12 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s
setMapKey("GpuTrainJob", cloudTaskRecord.UserID, 1, resultItemMap)
} else if cloudTaskRecord.JobType == "INFERENCE" {
setMapKey("GpuInferenceJob", cloudTaskRecord.UserID, 1, resultItemMap)
} else if cloudTaskRecord.JobType == "BENCHMARK" {
} else if isBenchMark(cloudTaskRecord.JobType) {
setMapKey("GpuBenchMarkJob", cloudTaskRecord.UserID, 1, resultItemMap)
} else {
setMapKey("GpuDebugJob", cloudTaskRecord.UserID, 1, resultItemMap)
}
} else if cloudTaskRecord.Type == 2 {
} else if cloudTaskRecord.Type == 2 || cloudTaskRecord.Type == 3 {
setMapKey("C2Net", cloudTaskRecord.UserID, 1, resultItemMap)
if cloudTaskRecord.ComputeResource == NPUResource {
if cloudTaskRecord.JobType == "TRAIN" {
@@ -2471,7 +2603,6 @@ func queryCloudBrainTask(start_unix int64, end_unix int64) (map[int64]int, map[s
break
}
}

return resultMap, resultItemMap
}



+ 3
- 3
models/user_business_struct.go View File

@@ -18,9 +18,9 @@ type UserSummaryCurrentYear struct {
CodeInfo string `xorm:"varchar(500)"` //代码提交次数,提交总代码行数,最晚的提交时间
CloudBrainInfo string `xorm:"varchar(1000)"` //,创建了XX 个云脑任务,调试任务XX 个,训练任务XX 个,推理任务XX 个,累计运行了XXXX 卡时,累计节省xxxxx 元
//这些免费的算力资源分别有,XX% 来自鹏城云脑1,XX% 来自鹏城云脑2,XX% 来自智算网络
PlayARoll string `xorm:"varchar(500)"` //你参加了XX 次“我为开源打榜狂”活动,累计上榜XX 次,总共获得了社区XXX 元的激励
Label string `xorm:"varchar(500)"`
PlayARoll string `xorm:"varchar(500)"` //你参加了XX 次“我为开源打榜狂”活动,累计上榜XX 次,总共获得了社区XXX 元的激励
WeekBonusData string `xorm:"-"`
Label string `xorm:"varchar(500)"`
}

type UserBusinessAnalysisCurrentYear struct {


+ 1
- 0
modules/auth/modelarts.go View File

@@ -28,6 +28,7 @@ type CreateModelArtsNotebookForm struct {
LabelName string `form:"label_names"`
PreTrainModelUrl string `form:"pre_train_model_url"`
SpecId int64 `form:"spec_id" binding:"Required"`
DatasetName string `form:"dataset_name"`
}

func (f *CreateModelArtsNotebookForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {


+ 7
- 20
modules/cloudbrain/cloudbrain.go View File

@@ -32,10 +32,10 @@ const (
Snn4imagenetMountPath = "/snn4imagenet"
BrainScoreMountPath = "/brainscore"
TaskInfoName = "/taskInfo"
Snn4imagenetCommand = `/opt/conda/bin/python /snn4imagenet/testSNN_script.py --modelname '%s' --modelpath '/dataset' --modeldescription '%s' >/model/benchmark-log.txt`
BrainScoreCommand = `bash /brainscore/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/dataset' -d '%s' >/model/benchmark-log.txt`
SubTaskName = "task1"
Snn4imagenetCommand = `/opt/conda/bin/python /benchmark/testSNN_script.py --modelname '%s' --modelpath '/pretrainmodel/%s' --modeldescription '%s' >/model/benchmark-log.txt`
BrainScoreCommand = `bash /benchmark/brainscore_test_par4shSrcipt.sh -b '%s' -n '%s' -p '/pretrainmodel/%s' -d '%s' >/model/benchmark-log.txt`
Snn4EcosetCommand = `/opt/conda/bin/python /benchmark/testSNN_script.py --datapath '/dataset' --modelname '%s' --modelpath '/pretrainmodel/%s' --modeldescription '%s' >/model/benchmark-log.txt`
SubTaskName = "task1"

Success = "S000"

@@ -257,20 +257,6 @@ func GenerateTask(req GenerateCloudBrainTaskReq) (string, error) {
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: req.Snn4ImageNetPath,
MountPath: Snn4imagenetMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: req.BrainScorePath,
MountPath: BrainScoreMountPath,
ReadOnly: true,
},
},
{
HostPath: models.StHostPath{
Path: req.ResultPath,
@@ -406,7 +392,7 @@ func GenerateTask(req GenerateCloudBrainTaskReq) (string, error) {
}

func IsBenchmarkJob(jobType string) bool {
return string(models.JobTypeModelSafety) == jobType || string(models.JobTypeBenchmark) == jobType || string(models.JobTypeBrainScore) == jobType || string(models.JobTypeSnn4imagenet) == jobType
return string(models.JobTypeModelSafety) == jobType || string(models.JobTypeBenchmark) == jobType || string(models.JobTypeBrainScore) == jobType || string(models.JobTypeSnn4imagenet) == jobType || string(models.JobTypeSnn4Ecoset) == jobType
}

func GetWaitingCloudbrainCount(cloudbrainType int, computeResource string, jobTypes ...models.JobType) int64 {
@@ -675,6 +661,7 @@ func IsElementExist(s []string, str string) bool {
return false
}


func GetCloudBrainByIdOrJobId(id string, initialQuery string) (*models.Cloudbrain, error) {
_, err := strconv.ParseInt(id, 10, 64)
var job *models.Cloudbrain
@@ -709,7 +696,7 @@ type GenerateModelArtsNotebookReq struct {

ImageId string
AutoStopDurationMs int64
BranchName string
BranchName string

Spec *models.Specification
ModelName string


+ 6
- 1
modules/context/auth.go View File

@@ -81,7 +81,12 @@ func Toggle(options *ToggleOptions) macaron.Handler {

// Redirect to dashboard if user tries to visit any non-login page.
if options.SignOutRequired && ctx.IsSigned && ctx.Req.URL.RequestURI() != "/" {
ctx.Redirect(setting.AppSubURL + "/")
redirectTo := ctx.Query("redirect_to")
if len(redirectTo) > 0 {
ctx.Redirect(redirectTo)
} else {
ctx.Redirect(setting.AppSubURL + "/")
}
return
}



+ 2
- 2
modules/context/repo.go View File

@@ -532,7 +532,7 @@ func RepoAssignment() macaron.Handler {

duration := time.Since(startTime)
log.Info("GetTags cost: %v seconds", duration.Seconds())
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 0)
brs, total, err := ctx.Repo.GitRepo.GetBranchNames(0, 0)
if err != nil {
ctx.ServerError("GetBranches", err)
return
@@ -542,7 +542,7 @@ func RepoAssignment() macaron.Handler {
log.Info("GetBranches cost: %v seconds", duration.Seconds())

ctx.Data["Branches"] = brs
ctx.Data["BranchesCount"] = len(brs)
ctx.Data["BranchesCount"] = total

ctx.Data["TagName"] = ctx.Repo.TagName



+ 3
- 3
modules/convert/cloudbrain.go View File

@@ -28,9 +28,9 @@ func ToCloudBrain(task *models.Cloudbrain) *api.Cloudbrain {
BootFile: task.BootFile,
Description: task.Description,
ModelName: task.ModelName,
ModelVersion: task.ModelVersion,
CkptName: task.CkptName,
VersionName: task.VersionName,
ModelVersion: task.ModelVersion,
CkptName: task.CkptName,

StartTime: int64(task.StartTime),
EndTime: int64(task.EndTime),


+ 105
- 0
modules/git/repo_branch.go View File

@@ -173,6 +173,111 @@ func (repo *Repository) GetBranches(skip, limit int) ([]string, int, error) {
return callShowRef(repo.Path, BranchPrefix, "--heads", skip, limit)
}

func (repo *Repository) GetBranchNames(skip, limit int) ([]string, int, error) {
return callShowRefNew(repo.Path, BranchPrefix, []string{BranchPrefix}, skip, limit)
}

func callShowRefNew(repoPath, trimPrefix string, extraArgs []string, skip, limit int) (branchNames []string, countAll int, err error) {

countAll, err = walkShowRef(repoPath, extraArgs, skip, limit, func(_, branchName string) error {
branchName = strings.TrimPrefix(branchName, trimPrefix)
branchNames = append(branchNames, branchName)
return nil
})
return branchNames, countAll, err
}

func walkShowRef(repoPath string, extraArgs []string, skip, limit int, walkfn func(sha1, refname string) error) (countAll int, err error) {
stdoutReader, stdoutWriter := io.Pipe()
defer func() {
_ = stdoutReader.Close()
_ = stdoutWriter.Close()
}()

go func() {
stderrBuilder := &strings.Builder{}
args := []string{"for-each-ref", "--format=%(objectname) %(refname)"}
args = append(args, extraArgs...)
err := NewCommand(args...).RunInDirPipeline(repoPath, stdoutWriter, stderrBuilder)
if err != nil {
if stderrBuilder.Len() == 0 {
_ = stdoutWriter.Close()
return
}
_ = stdoutWriter.CloseWithError(ConcatenateError(err, stderrBuilder.String()))
} else {
_ = stdoutWriter.Close()
}
}()

i := 0
bufReader := bufio.NewReader(stdoutReader)
for i < skip {
_, isPrefix, err := bufReader.ReadLine()
if err == io.EOF {
return i, nil
}
if err != nil {
return 0, err
}
if !isPrefix {
i++
}
}
for limit == 0 || i < skip+limit {
// The output of show-ref is simply a list:
// <sha> SP <ref> LF
sha, err := bufReader.ReadString(' ')
if err == io.EOF {
return i, nil
}
if err != nil {
return 0, err
}

branchName, err := bufReader.ReadString('\n')
if err == io.EOF {
// This shouldn't happen... but we'll tolerate it for the sake of peace
return i, nil
}
if err != nil {
return i, err
}

if len(branchName) > 0 {
branchName = branchName[:len(branchName)-1]
}

if len(sha) > 0 {
sha = sha[:len(sha)-1]
}

err = walkfn(sha, branchName)
if err != nil {
return i, err
}
i++
}
// count all refs
for limit != 0 {
_, isPrefix, err := bufReader.ReadLine()
if err == io.EOF {
return i, nil
}
if err != nil {
return 0, err
}
if !isPrefix {
i++
}
}
return i, nil
}

func isBranchMatch(branchName string, search string) bool {
return search == "" || (search != "" && strings.Contains(branchName, search))
}

// callShowRef return refs, if limit = 0 it will not limit
func callShowRef(repoPath, prefix, arg string, skip, limit int) (branchNames []string, countAll int, err error) {
stdoutReader, stdoutWriter := io.Pipe()


+ 65
- 10
modules/grampus/grampus.go View File

@@ -19,6 +19,7 @@ const (

ProcessorTypeNPU = "npu.huawei.com/NPU"
ProcessorTypeGPU = "nvidia.com/gpu"
ProcessorTypeGCU = "enflame-tech.com/gcu"

GpuWorkDir = "/tmp/"
NpuWorkDir = "/cache/"
@@ -108,6 +109,7 @@ type GenerateNotebookJobReq struct {
Spec *models.Specification
CodeName string
ModelPath string //参考启智GPU调试, 挂载/model目录用户的模型可以输出到这个目录
ModelStorageType int
}

func getEndPoint() string {
@@ -148,6 +150,36 @@ func getDatasetGPUGrampus(datasetInfos map[string]models.DatasetInfo) ([]models.
}
return datasetGrampus, command
}
func getDatasetGCUGrampus(datasetInfos map[string]models.DatasetInfo) ([]models.GrampusDataset, string) {
var datasetGrampus []models.GrampusDataset
var command = ""
obsEndPoint := getEndPoint()
for uuid, datasetInfo := range datasetInfos {
if datasetInfo.Type == models.TypeCloudBrainOne {
datasetGrampus = append(datasetGrampus, models.GrampusDataset{
Name: datasetInfo.FullName,
Bucket: setting.Attachment.Minio.Bucket,
EndPoint: setting.Attachment.Minio.Endpoint,
ObjectKey: datasetInfo.DataLocalPath,
ReadOnly: true,
ContainerPath: "/dataset1/" + datasetInfo.Name,
})

command += "cp /dataset1/'" + datasetInfo.Name + "'/" + uuid + " /dataset/'" + datasetInfo.FullName + "';"

} else {
datasetGrampus = append(datasetGrampus, models.GrampusDataset{
Name: datasetInfo.FullName,
Bucket: setting.Bucket,
EndPoint: obsEndPoint,
ObjectKey: datasetInfo.DataLocalPath + datasetInfo.FullName,
ContainerPath: "/dataset/" + datasetInfo.Name,
})
}

}
return datasetGrampus, command
}

func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (jobId string, err error) {
createTime := timeutil.TimeStampNow()
@@ -178,25 +210,45 @@ func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (job
imageUrl = ""
req.Command = ""
} else {
datasetGrampus, cpCommand = getDatasetGPUGrampus(req.DatasetInfos)
if ProcessorTypeGCU == req.ProcessType {
datasetGrampus, cpCommand = getDatasetGCUGrampus(req.DatasetInfos)
} else {
datasetGrampus, cpCommand = getDatasetGPUGrampus(req.DatasetInfos)
}
if len(req.ModelName) != 0 {
datasetGrampus = append(datasetGrampus, models.GrampusDataset{
Name: req.ModelName,
Bucket: setting.Attachment.Minio.Bucket,
EndPoint: setting.Attachment.Minio.Endpoint,
ObjectKey: req.PreTrainModelPath,
ReadOnly: true,
ContainerPath: cloudbrain.PretrainModelMountPath,
})
if req.ModelStorageType == models.TypeCloudBrainOne {
datasetGrampus = append(datasetGrampus, models.GrampusDataset{
Name: req.ModelName,
Bucket: setting.Attachment.Minio.Bucket,
EndPoint: setting.Attachment.Minio.Endpoint,
ObjectKey: req.PreTrainModelPath,
ReadOnly: true,
ContainerPath: cloudbrain.PretrainModelMountPath,
})
} else {
datasetGrampus = append(datasetGrampus, models.GrampusDataset{
Name: req.ModelName,
Bucket: setting.Bucket,
EndPoint: getEndPoint(),
ReadOnly: true,
ObjectKey: req.PreTrainModelPath,
ContainerPath: cloudbrain.PretrainModelMountPath,
})
}

}
codeArchiveName := cloudbrain.DefaultBranchName + ".zip"
codeGrampus = models.GrampusDataset{
Name: req.CodeName,
Bucket: setting.Attachment.Minio.Bucket,
EndPoint: setting.Attachment.Minio.Endpoint,
ObjectKey: req.CodeStoragePath + cloudbrain.DefaultBranchName + ".zip",
ObjectKey: req.CodeStoragePath + codeArchiveName,
ReadOnly: false,
ContainerPath: cloudbrain.CodeMountPath,
}
if ProcessorTypeGCU == req.ProcessType {
imageUrl = ""
}
req.Command = fmt.Sprintf(CommandGpuDebug, cpCommand, setting.CullIdleTimeout, setting.CullIdleTimeout, setting.CullInterval, setting.CullIdleTimeout, setting.CullInterval)
log.Info("debug command:" + req.Command)

@@ -215,6 +267,7 @@ func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (job
AutoStopDuration: autoStopDurationMs,
Capacity: setting.Capacity,
Command: req.Command,
CenterID: req.Spec.GetAvailableCenterIds(ctx.User.ID),
},
},
})
@@ -263,6 +316,8 @@ func GenerateNotebookJob(ctx *context.Context, req *GenerateNotebookJobReq) (job
actionType = models.ActionCreateGrampusNPUDebugTask
} else if req.ComputeResource == models.GPUResource {
actionType = models.ActionCreateGrampusGPUDebugTask
} else if req.ComputeResource == models.GCUResource {
actionType = models.ActionCreateGrampusGCUDebugTask
}
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {


+ 3
- 9
modules/grampus/resty.go View File

@@ -198,7 +198,6 @@ sendjob:
SetAuthToken(TOKEN).
SetResult(&result).
Get(HOST + urlTrainJob + "/" + jobID)

if err != nil {
return nil, fmt.Errorf("resty GetJob: %v", err)
}
@@ -316,10 +315,10 @@ func GetTrainJobLog(jobID string) (string, error) {
return logContent, nil
}

func GetGrampusMetrics(jobID string) (models.GetTrainJobMetricStatisticResult, error) {
func GetGrampusMetrics(jobID string) (models.NewModelArtsMetricStatisticResult, error) {
checkSetting()
client := getRestyClient()
var result models.GetTrainJobMetricStatisticResult
var result models.NewModelArtsMetricStatisticResult
res, err := client.R().
SetAuthToken(TOKEN).
Get(HOST + urlTrainJob + "/" + jobID + "/task/0/replica/0/metrics")
@@ -332,12 +331,7 @@ func GetGrampusMetrics(jobID string) (models.GetTrainJobMetricStatisticResult, e
return result, fmt.Errorf("json.Unmarshal failed(%s): %v", res.String(), err.Error())
}
if res.StatusCode() != http.StatusOK {
log.Error("Call GrampusMetrics failed(%d):%s(%s)", res.StatusCode(), result.ErrorCode, result.ErrorMsg)
return result, fmt.Errorf("Call GrampusMetrics failed(%d):%d(%s)", res.StatusCode(), result.ErrorCode, result.ErrorMsg)
}
if !result.IsSuccess {
log.Error("GetGrampusMetrics(%s) failed", jobID)
return result, fmt.Errorf("GetGrampusMetrics failed:%s", result.ErrorMsg)
return result, fmt.Errorf("Call GrampusMetrics failed(%d)", res.StatusCode())
}
return result, nil
}


+ 3
- 4
modules/modelarts/modelarts.go View File

@@ -22,9 +22,9 @@ import (
const (
//notebook

storageTypeOBS = "obs"
autoStopDuration = 4 * 60 * 60
AutoStopDurationMs = 4 * 60 * 60 * 1000
storageTypeOBS = "obs"
autoStopDuration = 4 * 60 * 60
AutoStopDurationMs = 4 * 60 * 60 * 1000

CodePath = "/code/"
OutputPath = "/output/"
@@ -168,7 +168,6 @@ type OrgMultiNode struct {
Node []int `json:"node"`
}


type Parameters struct {
Parameter []struct {
Label string `json:"label"`


+ 6
- 0
modules/redis/redis_key/cloudbrain_redis_key.go View File

@@ -1,7 +1,13 @@
package redis_key

import "fmt"

const CLOUDBRAIN_PREFIX = "cloudbrain"

func CloudbrainBindingJobNameKey(repoId string, jobType string, jobName string) string {
return KeyJoin(CLOUDBRAIN_PREFIX, repoId, jobType, jobName, "redis_key")
}

func CloudbrainUniquenessKey(userId int64, jobType string) string {
return KeyJoin(CLOUDBRAIN_PREFIX, fmt.Sprint(userId), jobType, "uniqueness")
}

+ 3
- 0
modules/repository/repo.go View File

@@ -139,6 +139,9 @@ func MigrateRepositoryGitData(doer, u *models.User, repo *models.Repository, opt
}

repo.IsMirror = true
if repo.Description == "" {
repo.Description = opts.Description
}
err = models.UpdateRepository(repo, false)
} else {
repo, err = CleanUpMigrateInfo(repo)


+ 19
- 0
modules/setting/setting.go View File

@@ -520,6 +520,7 @@ var (
MaxDatasetNum int
CullIdleTimeout string
CullInterval string
DebugAttachSize int

//benchmark config
IsBenchmarkEnabled bool
@@ -545,6 +546,12 @@ var (
BrainScoreName string
BrainScoreServerHost string

IsSnn4EcosetEnabled bool
Snn4EcosetOwner string
Snn4EcosetName string
Snn4EcosetServerHost string
Snn4AttachmentName string

//blockchain config
BlockChainHost string
CommitValidDate string
@@ -685,6 +692,8 @@ var (
IncubationSourceOrgName string
PaperRepoTopicName string

CloudbrainUniquenessLockTime time.Duration

//nginx proxy
PROXYURL string
RadarMap = struct {
@@ -1502,6 +1511,9 @@ func NewContext() {
MaxDatasetNum = sec.Key("MAX_DATASET_NUM").MustInt(5)
CullIdleTimeout = sec.Key("CULL_IDLE_TIMEOUT").MustString("900")
CullInterval = sec.Key("CULL_INTERVAL").MustString("60")
DebugAttachSize = sec.Key("DEBUG_ATTACH_SIZE").MustInt(20)

CloudbrainUniquenessLockTime = sec.Key("UNIQUENESS_LOCK_TIME").MustDuration(5 * time.Minute)

sec = Cfg.Section("benchmark")
IsBenchmarkEnabled = sec.Key("ENABLED").MustBool(false)
@@ -1527,6 +1539,13 @@ func NewContext() {
BrainScoreName = sec.Key("NAME").MustString("")
BrainScoreServerHost = sec.Key("HOST").MustString("")

sec = Cfg.Section("snn4ecoset")
IsSnn4EcosetEnabled = sec.Key("ENABLED").MustBool(false)
Snn4EcosetOwner = sec.Key("OWNER").MustString("")
Snn4EcosetName = sec.Key("NAME").MustString("")
Snn4EcosetServerHost = sec.Key("HOST").MustString("")
Snn4AttachmentName = sec.Key("DATASET").MustString("")

sec = Cfg.Section("blockchain")
BlockChainHost = sec.Key("HOST").MustString("http://192.168.136.66:3302/")
CommitValidDate = sec.Key("COMMIT_VALID_DATE").MustString("2021-01-15")


+ 16
- 0
modules/storage/minio_ext.go View File

@@ -391,3 +391,19 @@ func GetPartInfos(objectName string, uploadID string) (string, error) {

return chunks, nil
}

func IsObjectExist4Minio(bucket, objectName string) (bool, error) {
_, core, err := getClients()
if err != nil {
log.Error("getClients failed:", err.Error())
return false, err
}

_, err = core.StatObject(bucket, objectName, miniov6.StatObjectOptions{})
if err != nil {
log.Error("GetObjectMetadata error.%v", err)
return false, err
}

return true, nil
}

+ 33
- 4
modules/storage/obs.go View File

@@ -614,7 +614,7 @@ func ObsCreateObject(path string) error {
return nil
}

func GetObsLogFileName(prefix string) (string, error) {
func GetObsLogFileName(prefix string) ([]FileInfo, error) {
input := &obs.ListObjectsInput{}
input.Bucket = setting.Bucket
input.Prefix = prefix
@@ -622,10 +622,39 @@ func GetObsLogFileName(prefix string) (string, error) {
output, err := ObsCli.ListObjects(input)
if err != nil {
log.Error("PutObject failed:", err.Error())
return "", err
return nil, err
}
if output == nil || len(output.Contents) == 0 {
return "", errors.New("obs log files not exist")
return nil, errors.New("obs log files not exist")
}
fileInfos := make([]FileInfo, 0)
for _, val := range output.Contents {
//result[num] = c.Key
if strings.HasSuffix(val.Key, ".log") {
log.Info("log fileName=" + val.Key)
fileInfo := FileInfo{
ModTime: val.LastModified.Local().Format("2006-01-02 15:04:05"),
FileName: val.Key[len(prefix)-3:], //加上 job
Size: val.Size,
IsDir: false,
ParenDir: prefix[0 : len(prefix)-3],
}
fileInfos = append(fileInfos, fileInfo)
}

}
return fileInfos, nil
}

func IsObjectExist4Obs(bucket, key string) (bool, error) {

_, err := ObsCli.GetObjectMetadata(&obs.GetObjectMetadataInput{
Bucket: bucket,
Key: key,
})
if err != nil {
log.Error("GetObjectMetadata error.%v", err)
return false, err
}
return output.Contents[0].Key, nil
return true, nil
}

+ 27
- 27
modules/structs/cloudbrain.go View File

@@ -51,33 +51,33 @@ type CreateFileNotebookJobOption struct {
}

type Cloudbrain struct {
ID int64 `json:"id"`
JobID string `json:"job_id"`
JobType string `json:"job_type"`
Type int `json:"type"`
DisplayJobName string `json:"display_job_name"`
Status string `json:"status"`
CreatedUnix int64 `json:"created_unix"`
RepoID int64 `json:"repo_id"`
Duration int64 `json:"duration"` //运行时长 单位秒
TrainJobDuration string `json:"train_job_duration"`
ImageID string `json:"image_id"` //grampus image_id
Image string `json:"image"`
Uuid string `json:"uuid"` //数据集id
DatasetName string `json:"dataset_name"`
ComputeResource string `json:"compute_resource"` //计算资源,例如npu
AiCenter string `json:"ai_center"` //grampus ai center: center_id+center_name
BranchName string `json:"branch_name"` //分支名称
Parameters string `json:"parameters"` //传给modelarts的param参数
BootFile string `json:"boot_file"` //启动文件
Description string `json:"description"` //描述
ModelName string `json:"model_name"` //模型名称
ModelVersion string `json:"model_version"` //模型版本
CkptName string `json:"ckpt_name"` //权重文件名称
StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
Spec *SpecificationShow `json:"spec"`
ID int64 `json:"id"`
JobID string `json:"job_id"`
JobType string `json:"job_type"`
Type int `json:"type"`
DisplayJobName string `json:"display_job_name"`
Status string `json:"status"`
CreatedUnix int64 `json:"created_unix"`
RepoID int64 `json:"repo_id"`
Duration int64 `json:"duration"` //运行时长 单位秒
TrainJobDuration string `json:"train_job_duration"`
ImageID string `json:"image_id"` //grampus image_id
Image string `json:"image"`
Uuid string `json:"uuid"` //数据集id
DatasetName string `json:"dataset_name"`
ComputeResource string `json:"compute_resource"` //计算资源,例如npu
AiCenter string `json:"ai_center"` //grampus ai center: center_id+center_name
BranchName string `json:"branch_name"` //分支名称
Parameters string `json:"parameters"` //传给modelarts的param参数
BootFile string `json:"boot_file"` //启动文件
Description string `json:"description"` //描述
ModelName string `json:"model_name"` //模型名称
ModelVersion string `json:"model_version"` //模型版本
CkptName string `json:"ckpt_name"` //权重文件名称
StartTime int64 `json:"start_time"`
EndTime int64 `json:"end_time"`
VersionName string `json:"version_name"`
Spec *SpecificationShow `json:"spec"`
}

type SpecificationShow struct {


+ 9
- 1
modules/templates/helper.go View File

@@ -104,11 +104,16 @@ func NewFuncMap() []template.FuncMap {
"AllowedReactions": func() []string {
return setting.UI.Reactions
},
"DebugAttachSize": func() int {
return setting.DebugAttachSize * 1000 * 1000 * 1000
},
"AvatarLink": models.AvatarLink,
"Safe": Safe,
"SafeJS": SafeJS,
"Str2html": Str2html,
"subOne": subOne,
"addOne": addOne,
"TimeStampNow": timeutil.TimeStampNow,
"TimeSince": timeutil.TimeSince,
"TimeSinceUnix": timeutil.TimeSinceUnix,
"TimeSinceUnix1": timeutil.TimeSinceUnix1,
@@ -369,6 +374,7 @@ func NewTextFuncMap() []texttmpl.FuncMap {
"AppDomain": func() string {
return setting.Domain
},
"TimeStampNow": timeutil.TimeStampNow,
"TimeSince": timeutil.TimeSince,
"TimeSinceUnix": timeutil.TimeSinceUnix,
"TimeSinceUnix1": timeutil.TimeSinceUnix1,
@@ -476,7 +482,9 @@ func Str2html(raw string) template.HTML {
func subOne(length int) int {
return length - 1
}

func addOne(length int64) int64 {
return length + 1
}
// Escape escapes a HTML string
func Escape(raw string) string {
return html.EscapeString(raw)


+ 26
- 4
options/locale/locale_en-US.ini View File

@@ -406,6 +406,8 @@ sspi_auth_failed = SSPI authentication failed
change_email = Change email
change_email_address = Change email address
new_email_address = New email address
openi_community_really_awesome = OpenI, Really Awesome!

[phone]
format_err=The format of phone number is wrong.
query_err=Fail to query phone number, please try again later.
@@ -1061,8 +1063,12 @@ model_rename=Duplicate model name, please modify model name.

notebook_file_not_exist=Notebook file does not exist.
notebook_select_wrong=Please select a Notebook(.ipynb) file first.
notebook_path_too_long=The total length of selected file or files path exceed 255 characters, please select a shorter path file or change the file path.
notebook_branch_name_too_long=The total length of branch or branches name exceed 255 characters, please select a file in other branch.
notebook_file_no_right=You have no right to access the Notebook(.ipynb) file.
notebook_repo_conflict=The files in different branches of the same repository can not run together.
debug_again_fail=Fail to restart debug task, please try again later.
debug_again_fail_forever=The task was scheduled failed last time, can not restart.

date=Date
repo_add=Project Increment
@@ -1080,6 +1086,7 @@ delete=Delete
more=More
gpu_type_all=All
model_download=Model Download
all_result_download=All result download
submit_image=Submit Image
modify_image=Modify Image
image_exist=Image name has been used, please use a new one.
@@ -1092,8 +1099,8 @@ image_delete_fail=Failed to delete image, please try again later.
image_overwrite=You had submitted the same name image before, are you sure to overwrite the original image?
download=Download
score=Score
wait_count_start = There are currently
wait_count_end = tasks queued
wait_count_start = Your current queue position is
wait_count_end =
file_limit_100 = Display up to 100 files or folders in a single directory
images.name = Image Tag
images.name_placerholder = Please enter the image name
@@ -1167,7 +1174,7 @@ modelarts.train_job.new_train=New Train Task
modelarts.train_job.new_infer=New Inference Task
modelarts.train_job.config=Configuration information
modelarts.train_job.new=New train Task
modelarts.train_job.new_place=The description should not exceed 256 characters
modelarts.train_job.new_place=The description should not exceed 255 characters
modelarts.model_name=Model Name
modelarts.model_size=Model Size
modelarts.import_model=Import Model
@@ -1258,6 +1265,13 @@ modelarts.fullscreen_log_file = View in full screen
modelarts.exit_full_screen = Exit fullscreen
modelarts.no_node_right = The value of 'Amount of Compute Node' is wrong, you have no right to use the current value of 'Amount of Compute Node'.

scrolled_logs_top = You have scrolled to the top of the log
scrolled_logs_top_pls_retry = You have scrolled to the top of the log, please try again later!
scrolled_logs_bottom = You have scrolled to the bottom of the log
scrolled_logs_bottom_pls_retry = You have scrolled to the bottom of the log, please try again later!

canceled_operation = You have canceled the operation
successfully_deleted = Successfully deleted

debug_task_not_created = Debug task has not been created
train_task_not_created = Train task has not been created
@@ -1346,6 +1360,7 @@ modelconvert.inputshapeerror=Format input error, please input such as: 1,1,32,32
modelconvert.manage.create_error1=A model transformation task with the same name already exists.
modelconvert.manage.create_error2=Only one running model transformation task can be created.
modelconvert.manage.model_not_exist=The model in the task does not exist or has been deleted.
modelconvert.manage.model_file_not_exist=The model file in the task does not exist or has been deleted.
modelconvert.manage.no_operate_right=You have no right to do the operation.

debug.manage.model_not_exist=The model in the task does not exist or has been deleted, please create a new debug job.
@@ -1471,7 +1486,7 @@ blame = Blame
normal_view = Normal View
line = line
lines = lines
notebook_open = Open in Notebook
notebook_open = Run Online

editor.new_file = New File
editor.upload_file = Upload File
@@ -1717,6 +1732,9 @@ issues.attachment.open_tab = `Click to see "%s" in a new tab`
issues.attachment.download = `Click to download "%s"`
issues.subscribe = Subscribe
issues.unsubscribe = Unsubscribe
issues.top_task=Top issue
issues.top = Top
issues.cancel_topping = Cancel topping
issues.lock = Lock conversation
issues.unlock = Unlock conversation
issues.lock.unknown_reason = Cannot lock an issue with an unknown reason.
@@ -3132,6 +3150,7 @@ task_gpudebugjob=`created CPU/GPU type debugging task <a href="%s/cloudbrain/%s"
task_npudebugjob=`created NPU type debugging task <a href="%s/modelarts/notebook/%s">%s</a>`
task_c2net_gpudebugjob=`created CPU/GPU type debugging task <a href="%s/grampus/notebook/%s">%s</a>`
task_c2net_npudebugjob=`created NPU type debugging task <a href="%s/grampus/notebook/%s">%s</a>`
task_c2ent_gcudebugjob=`created GCU type debugging task <a href="%s/grampus/notebook/%s">%s</a>`
task_nputrainjob=`created NPU training task <a href="%s/modelarts/train-job/%s">%s</a>`
task_inferencejob=`created reasoning task <a href="%s/modelarts/inference-job/%s">%s</a>`
task_benchmark=`created profiling task <a href="%s/cloudbrain/benchmark/%s">%s</a>`
@@ -3292,6 +3311,7 @@ point_hr = Point/hr
DEBUG = DEBUG
SNN4IMAGENET = BENCHMARK
BRAINSCORE = BENCHMARK
SNN4ECOSET = BENCHMARK
MODELSAFETY = BENCHMARK
TRAIN = TRAIN
INFERENCE = INFERENCE
@@ -3305,7 +3325,9 @@ Stopped_failed=Fail to stop the job, please try again later.
Stopped_success_update_status_fail=Succeed in stopping th job, but failed to update the job status and duration time.
load_code_failed=Fail to load code, please check if the right branch is selected.

error.debug_datasetsize = The size of dataset exceeds limitation (%dGB)
error.dataset_select = dataset select error:the count exceed the limit or has same name
error.partial_datasets_not_available = There are non-existent or deleted files in the selected dataset file, please select again
new_train_gpu_tooltips = The code is storaged in <strong style="color:#010101">%s</strong>, the dataset is storaged in <strong style="color:#010101">%s</strong>, the pre-trained model is storaged in the run parameter <strong style="color:#010101">%s</strong>, and please put your model into <strong style="color:#010101">%s</strong> then you can download it online
new_debug_gpu_tooltips = The code is storaged in <strong style="color:#010101">%s</strong>, the dataset is storaged in <strong style="color:#010101">%s</strong>, the pre-trained model is storaged in the <strong style="color:#010101">%s</strong>, and please put your model into <strong style="color:#010101">%s</strong> then you can download it online
new_debug_gpu_tooltips1 = The code is storaged in <strong style="color:#010101">%s</strong>, the dataset is storaged in <strong style="color:#010101">%s</strong>, the pre-trained model is storaged in the <strong style="color:#010101">%s</strong>.


+ 26
- 5
options/locale/locale_zh-CN.ini View File

@@ -73,7 +73,7 @@ your_starred=已点赞
your_settings=设置
invite_friends=邀请好友
your_friend=您的好友
invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources=邀请您加入 AI协作平台,畅享充沛的免费算力资源!
invite_you_to_join_the_OpenI_AI_Collaboration_Platform_and_enjoy_abundant_free_computing_resources=邀请您加入 AI协作平台,畅享充沛的普惠算力资源!
recommender=推荐人

all=所有
@@ -409,6 +409,8 @@ sspi_auth_failed=SSPI 认证失败
change_email=修改邮箱
change_email_address=修改邮箱地址
new_email_address=新邮箱地址
openi_community_really_awesome= 确实给力

[phone]
format_err=手机号格式错误。
query_err=查询手机号失败,请稍后再试。
@@ -1060,8 +1062,12 @@ model_rename=模型名称重复,请修改模型名称

notebook_file_not_exist=Notebook文件不存在。
notebook_select_wrong=请先选择Notebook(.ipynb)文件。
notebook_path_too_long=选择的一个或多个Notebook文件路径总长度超过255个字符,请选择路径较短的文件或调整文件路径。
notebook_branch_name_too_long=选择的一个或多个Notebook文件分支名总长度超过255个字符,请选择其他分支的文件。
notebook_file_no_right=您没有这个Notebook文件的读权限。
notebook_repo_conflict=同一个仓库的不同分支文件不能同时运行。
debug_again_fail=再次调试失败,请稍后再试。
debug_again_fail_forever=这个任务之前没有调度成功,不能再次调试。

date=日期
repo_add=新增项目
@@ -1079,6 +1085,7 @@ delete=删除
more=更多
gpu_type_all=全部
model_download=结果下载
all_result_download=全部结果下载
submit_image=提交镜像
modify_image=修改镜像
image_exist=镜像Tag已被使用,请修改镜像Tag。
@@ -1091,8 +1098,8 @@ image_delete_fail=删除镜像失败,请稍后再试。
image_overwrite=您已经提交过相同名称的镜像,您确定要覆盖原来提交的镜像吗?
download=模型下载
score=评分
wait_count_start = 当前有
wait_count_end = 个任务正在排队
wait_count_start = 您当前排队位置是第
wait_count_end =
file_limit_100 = 单目录下最多显示100个文件或文件夹
images.name = 镜像Tag
images.name_placerholder = 请输入镜像Tag
@@ -1270,6 +1277,13 @@ modelarts.fullscreen_log_file=全屏查看
modelarts.exit_full_screen=退出全屏
modelarts.no_node_right = 计算节点数的值配置错误,您没有权限使用当前配置的计算节点数。

scrolled_logs_top = 您已翻阅至日志顶部
scrolled_logs_top_pls_retry = 您已翻阅至日志顶部,请稍后再试!
scrolled_logs_bottom = 您已翻阅至日志底部
scrolled_logs_bottom_pls_retry = 您已翻阅至日志底部,请稍后再试!

canceled_operation = 您已取消操作
successfully_deleted = 删除成功

debug_task_not_created = 未创建过调试任务
train_task_not_created = 未创建过训练任务
@@ -1360,6 +1374,7 @@ modelconvert.modelfileempty=请选择模型文件。
modelconvert.manage.create_error1=相同的名称模型转换任务已经存在。
modelconvert.manage.create_error2=只能创建一个正在运行的模型转换任务。
modelconvert.manage.model_not_exist=任务中选择的模型不存在或者已被删除。
modelconvert.manage.model_file_not_exist=任务中选择的模型文件不存在或者已被删除。
modelconvert.manage.no_operate_right=您没有操作权限。


@@ -1489,7 +1504,7 @@ normal_view=普通视图
line=行
lines=行

notebook_open = 在Notebook中打开
notebook_open = 在线运行

editor.new_file=新建文件
editor.upload_file=上传文件
@@ -1734,6 +1749,9 @@ issues.attachment.open_tab=`在新的标签页中查看 '%s'`
issues.attachment.download=`点击下载 '%s'`
issues.subscribe=订阅
issues.unsubscribe=取消订阅
issues.top_task=置顶任务
issues.top=置顶
issues.cancel_topping=取消置顶
issues.lock=锁定对话
issues.unlock=解锁对话
issues.lock.unknown_reason=由于未知原因无法锁定。
@@ -3151,6 +3169,7 @@ task_gpudebugjob=`创建了CPU/GPU类型调试任务 <a href="%s/cloudbrain/%s">
task_npudebugjob=`创建了NPU类型调试任务 <a href="%s/modelarts/notebook/%s">%s</a>`
task_c2net_gpudebugjob=`创建了CPU/GPU类型调试任务 <a href="%s/grampus/notebook/%s">%s</a>`
task_c2net_npudebugjob=`创建了NPU类型调试任务 <a href="%s/grampus/notebook/%s">%s</a>`
task_c2ent_gcudebugjob=`创建了GCU类型调试任务 <a href="%s/grampus/notebook/%s">%s</a>`
task_nputrainjob=`创建了NPU类型训练任务 <a href="%s/modelarts/train-job/%s">%s</a>`
task_inferencejob=`创建了推理任务 <a href="%s/modelarts/inference-job/%s">%s</a>`
task_benchmark=`创建了评测任务 <a href="%s/cloudbrain/benchmark/%s">%s</a>`
@@ -3313,6 +3332,7 @@ point_hr = 积分/时
DEBUG = 调试任务
SNN4IMAGENET = 评测任务
BRAINSCORE = 评测任务
SNN4ECOSET = 评测任务
MODELSAFETY = 评测任务
TRAIN = 训练任务
INFERENCE = 推理任务
@@ -3326,8 +3346,9 @@ Stopped_failed=任务停止失败,请稍后再试。
Stopped_success_update_status_fail=任务停止成功,状态及运行时间更新失败。
load_code_failed=代码加载失败,请确认选择了正确的分支。

error.debug_datasetsize = 数据集大小超过限制(%dGB)
error.dataset_select = 数据集选择错误:数量超过限制或者有同名数据集
error.partial_datasets_not_available = 选择的数据集文件中有不存在或已删除的文件,请重新选择
new_train_gpu_tooltips = 训练脚本存储在 <strong style="color:#010101">%s</strong> 中,数据集存储在 <strong style="color:#010101">%s</strong> 中,预训练模型存放在运行参数 <strong style="color:#010101">%s</strong> 中,训练输出请存储在 <strong style="color:#010101">%s</strong> 中以供后续下载。
new_debug_gpu_tooltips = 项目代码存储在 <strong style="color:#010101">%s</strong> 中,数据集存储在 <strong style="color:#010101">%s</strong> 中,选择的模型存储在 <strong style="color:#010101">%s</strong> 中,调试输出请存储在 <strong style="color:#010101">%s</strong> 中以供后续下载。
new_debug_gpu_tooltips1 = 项目代码存储在 <strong style="color:#010101">%s</strong> 中,数据集存储在 <strong style="color:#010101">%s</strong> 中,选择的模型存储在 <strong style="color:#010101">%s</strong> 中。


+ 34
- 65
package-lock.json View File

@@ -1982,28 +1982,6 @@
"object.assign": "^4.1.0"
}
},
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"requires": {
"babel-runtime": "^6.26.0",
"core-js": "^2.5.0",
"regenerator-runtime": "^0.10.5"
},
"dependencies": {
"core-js": {
"version": "2.6.12",
"resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.12.tgz?cache=0&sync_timestamp=1611040749668&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.12.tgz",
"integrity": "sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw="
},
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
}
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
@@ -2194,9 +2172,9 @@
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"blueimp-md5": {
"version": "2.18.0",
"resolved": "https://registry.npm.taobao.org/blueimp-md5/download/blueimp-md5-2.18.0.tgz",
"integrity": "sha1-EVK+EzXwxrORHtnjbbVPPmrFKTU="
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz",
"integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w=="
},
"bn.js": {
"version": "5.1.1",
@@ -3536,6 +3514,11 @@
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
"integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI="
},
"dayjs": {
"version": "1.10.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
"integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig=="
},
"de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
@@ -4152,25 +4135,29 @@
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"esdk-obs-browserjs": {
"version": "3.20.7",
"resolved": "https://registry.npm.taobao.org/esdk-obs-browserjs/download/esdk-obs-browserjs-3.20.7.tgz",
"integrity": "sha1-vhziRlKEhW3PgZPl0DyX68bJI0s=",
"version": "3.22.3",
"resolved": "https://registry.npmjs.org/esdk-obs-browserjs/-/esdk-obs-browserjs-3.22.3.tgz",
"integrity": "sha512-MATZXp0FwjPtKG9tpdfURa3koUarR/ev+tbO0oUKgj0GRt0798ZxmfCvYvRpgNst4w1ht4E79ikD4H40UYLgPA==",
"requires": {
"axios": "^0.19.0",
"babel-polyfill": "^6.26.0",
"blueimp-md5": "^2.10.0",
"js-base64": "^2.3.2",
"jssha": "^2.3.1",
"urijs": "^1.19.1"
"axios": "^0.26.1",
"blueimp-md5": "^2.18.0",
"js-base64": "^3.7.1",
"jssha": "^3.2.0",
"urijs": "^1.19.7"
},
"dependencies": {
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npm.taobao.org/axios/download/axios-0.19.2.tgz?cache=0&sync_timestamp=1608609215811&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxios%2Fdownload%2Faxios-0.19.2.tgz",
"integrity": "sha1-PqNsXYgY0NX4qKl6bTa4bNwAyyc=",
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"requires": {
"follow-redirects": "1.5.10"
"follow-redirects": "^1.14.8"
}
},
"js-base64": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.3.tgz",
"integrity": "sha512-PAr6Xg2jvd7MCR6Ld9Jg3BmTcjYsHEBx1VlwEwULb/qowPf5VD9kEMagj23Gm7JRnSvE/Da/57nChZjnvL8v6A=="
}
}
},
@@ -5382,27 +5369,9 @@
}
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.10.tgz?cache=0&sync_timestamp=1611606737937&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.5.10.tgz",
"integrity": "sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=",
"requires": {
"debug": "=3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz?cache=0&sync_timestamp=1607566533140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.1.0.tgz",
"integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA=="
},
"fomantic-ui": {
"version": "2.8.4",
@@ -7884,9 +7853,9 @@
}
},
"jssha": {
"version": "2.4.2",
"resolved": "https://registry.npm.taobao.org/jssha/download/jssha-2.4.2.tgz",
"integrity": "sha1-2VCwlWNJKL1rK9odQtqaOnYtZek="
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/jssha/-/jssha-3.3.0.tgz",
"integrity": "sha512-w9OtT4ALL+fbbwG3gw7erAO0jvS5nfvrukGPMWIAoea359B26ALXGpzy4YJSp9yGnpUvuvOw1nSjSoHDfWSr1w=="
},
"just-debounce": {
"version": "1.0.0",
@@ -14400,9 +14369,9 @@
}
},
"urijs": {
"version": "1.19.6",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.6.tgz",
"integrity": "sha512-eSXsXZ2jLvGWeLYlQA3Gh36BcjF+0amo92+wHPyN1mdR8Nxf75fuEuYTd9c0a+m/vhCjRK0ESlE9YNLW+E1VEw=="
"version": "1.19.11",
"resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz",
"integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="
},
"urix": {
"version": "0.1.0",


+ 8
- 5
public/home/home.js View File

@@ -243,11 +243,12 @@ document.onreadystatechange = function () {
html += recordPrefix + actionName;
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>"
}
else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30" || record.OpType == "31" || record.OpType == "32" || record.OpType == "33"){
else if(record.OpType == "24" || record.OpType == "26" || record.OpType == "27" || record.OpType == "28" || record.OpType == "30"
|| record.OpType == "31" || record.OpType == "32" || record.OpType == "33"){
html += recordPrefix + actionName;
html += " <a href=\"" + getTaskLink(record) + "\" rel=\"nofollow\">" + record.RefName + "</a>"
}
else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40"){
else if(record.OpType == "25" || record.OpType == "29" || record.OpType == "39" || record.OpType == "40" || record.OpType == "41"){
html += recordPrefix + actionName;
html += " <a href=\"" + getTaskLink(record) + "\" rel=\"nofollow\">" + record.RefName + "</a>"
}
@@ -294,7 +295,7 @@ function getTaskLink(record){
re = re + "/cloudbrain/train-job/" + record.Content;
}else if(record.OpType == 32 || record.OpType == 33){
re = re + "/grampus/train-job/" + record.Content;
}else if(record.OpType == 39 || record.OpType == 40){
}else if(record.OpType == 39 || record.OpType == 40 || record.OpType == 41){
re = re + "/grampus/notebook/" + record.Content;
}
@@ -453,9 +454,10 @@ var actionNameZH={
"33":"创建了CPU/GPU类型训练任务",
"35":"创建的数据集 {dataset} 被设置为推荐数据集",
"36":"提交了镜像 {image}",
"37": "提交的镜像 {image} 被设置为推荐镜像",
"37":"提交的镜像 {image} 被设置为推荐镜像",
"39":"创建了CPU/GPU类型调试任务",
"40":"创建了NPU类型调试任务",
"41":"创建了GCU类型调试任务",
};

var actionNameEN={
@@ -486,9 +488,10 @@ var actionNameEN={
"33":" created CPU/GPU type training task",
"35":" created dataset {dataset} was set as recommended dataset",
"36":"committed image {image}",
"37": "committed image {image} was set as recommended image",
"37":"committed image {image} was set as recommended image",
"39":" created CPU/GPU type debugging task ",
"40":" created NPU type debugging task ",
"41":" created GCU type debugging task ",
};

var repoAndOrgZH={


BIN
public/img/login_bg_default.png View File

Before After
Width: 1200  |  Height: 938  |  Size: 138 KiB

+ 1
- 1
routers/admin/cloudbrains.go View File

@@ -53,7 +53,7 @@ func CloudBrains(ctx *context.Context) {
var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet), string(models.JobTypeSnn4Ecoset))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}


+ 6
- 0
routers/api/v1/api.go View File

@@ -549,6 +549,8 @@ func RegisterRoutes(m *macaron.Macaron) {

}, reqToken())

m.Get("/compute-nodes", reqToken(), user.GetComputeNodes)

// Notifications
m.Group("/notifications", func() {
m.Combo("").
@@ -736,6 +738,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Combo("/repositories/:id", reqToken()).Get(repo.GetByID)

m.Group("/datasets/:username/:reponame", func() {
m.Get("", repo.CurrentRepoDatasetInfoWithoutAttachment)
m.Get("/current_repo", repo.CurrentRepoDatasetMultiple)
m.Get("/my_datasets", repo.MyDatasetsMultiple)
m.Get("/public_datasets", repo.PublicDatasetMultiple)
@@ -999,6 +1002,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("", repo.GetModelArtsTrainJobVersion)
m.Get("/detail", reqToken(), reqRepoReader(models.UnitTypeCloudBrain), repo.CloudBrainShow)
m.Get("/model_list", repo.CloudBrainModelList)
m.Get("/download_multi_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.CloudBrainStop)
m.Put("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GeneralCloudBrainJobStop)
})
@@ -1051,6 +1055,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/stop_version", repo.StopTrainJobVersion)
m.Get("/model_list", repo.ModelList)
m.Get("/metric_statistics", repo.TrainJobGetMetricStatistic)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRightForTrain, repo.MultiModelDownload)
})
})
m.Group("/inference-job", func() {
@@ -1073,6 +1078,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/stop_version", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo_ext.GrampusStopJob)
m.Get("/log", repo_ext.GrampusGetLog)
m.Get("/metrics", repo_ext.GrampusMetrics)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Get("/download_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo_ext.GrampusDownloadLog)
})
})


+ 45
- 0
routers/api/v1/repo/attachments.go View File

@@ -1,22 +1,67 @@
package repo

import (
"net/http"

"code.gitea.io/gitea/modules/log"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
routeRepo "code.gitea.io/gitea/routers/repo"
)

func GetSuccessChunks(ctx *context.APIContext) {
if errStr := checkDatasetPermission(ctx); errStr != "" {
ctx.JSON(http.StatusForbidden, ctx.Tr(errStr))
}

routeRepo.GetSuccessChunks(ctx.Context)
}

func checkDatasetPermission(ctx *context.APIContext) string {
datasetId := ctx.QueryInt64("dataset_id")

dataset, err := models.GetDatasetByID(datasetId)
if err != nil {
log.Warn("can not find dataset", err)

return "dataset.query_dataset_fail"
}
repo, err := models.GetRepositoryByID(dataset.RepoID)
if err != nil {
log.Warn("can not find repo", err)
return "dataset.query_dataset_fail"
}

permission, err := models.GetUserRepoPermission(repo, ctx.User)
if err != nil {
log.Warn("can not find repo permission for user", err)
return "dataset.query_dataset_fail"
}
if !permission.CanWrite(models.UnitTypeDatasets) {

return "error.no_right"
}
return ""
}

func NewMultipart(ctx *context.APIContext) {
if errStr := checkDatasetPermission(ctx); errStr != "" {
ctx.JSON(http.StatusForbidden, ctx.Tr(errStr))
}
routeRepo.NewMultipart(ctx.Context)
}
func GetMultipartUploadUrl(ctx *context.APIContext) {
if errStr := checkDatasetPermission(ctx); errStr != "" {
ctx.JSON(http.StatusForbidden, ctx.Tr(errStr))
}
routeRepo.GetMultipartUploadUrl(ctx.Context)
}

func CompleteMultipart(ctx *context.APIContext) {
if errStr := checkDatasetPermission(ctx); errStr != "" {
ctx.JSON(http.StatusForbidden, ctx.Tr(errStr))
}
routeRepo.CompleteMultipart(ctx.Context)

}


+ 2
- 0
routers/api/v1/repo/cloudbrain.go View File

@@ -160,6 +160,7 @@ func GetFileNoteBookInfo(ctx *context.APIContext) {
"imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
"imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
"imageNpuDescription": setting.FileNoteBook.ImageNPUDescription,
"cloudBrainPaySwitch": setting.CloudBrainPaySwitch,
})
} else {
ctx.JSON(http.StatusOK, map[string]interface{}{
@@ -173,6 +174,7 @@ func GetFileNoteBookInfo(ctx *context.APIContext) {
"imageCpuDescription": setting.FileNoteBook.ImageCPUDescription,
"imageGpuDescription": setting.FileNoteBook.ImageGPUDescription,
"imageNpuDescription": setting.FileNoteBook.ImageNPUCDDescription,
"cloudBrainPaySwitch": setting.CloudBrainPaySwitch,
})

}


+ 48
- 18
routers/api/v1/repo/cloudbrain_dashboard.go View File

@@ -623,7 +623,7 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
}

jobTypeList := []string{string(models.JobTypeDebug), string(models.JobTypeTrain), string(models.JobTypeInference), string(models.JobTypeBenchmark),
string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet)}
string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet), string(models.JobTypeSnn4Ecoset)}
for _, v := range jobTypeList {
if _, ok := cloudOneJobTypeRes[v]; !ok {
cloudOneJobTypeRes[v] = 0
@@ -645,7 +645,7 @@ func GetAllCloudbrainsPeriodDistribution(ctx *context.Context) {
}
}

ComputeResourceList := []string{"CPU/GPU", "NPU"}
ComputeResourceList := []string{"CPU/GPU", "NPU", "GCU"}
for _, v := range ComputeResourceList {
if _, ok := cloudBrainComputeResource[v]; !ok {
cloudBrainComputeResource[v] = 0
@@ -687,7 +687,6 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
return
}
recordBeginTime := recordCloudbrain[0].Cloudbrain.CreatedUnix
endTime := time.Now()
listType := ctx.Query("listType")
jobType := ctx.Query("jobType")
jobStatus := ctx.Query("jobStatus")
@@ -695,6 +694,33 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
aiCenter := ctx.Query("aiCenter")
needDeleteInfo := ctx.Query("needDeleteInfo")

accCardType := ctx.Query("accCardType")
accCardsNum := ctx.QueryInt("accCardsNum")
workServerNumber := ctx.QueryInt("workServerNumber")
beginTimeStr := ctx.QueryTrim("beginTime")
endTimeStr := ctx.QueryTrim("endTime")
var beginTimeUnix int64
var endTimeUnix int64
if beginTimeStr == "" || endTimeStr == "" {
beginTimeUnix = int64(recordBeginTime)
endTimeUnix = time.Now().Unix()
} else {
beginTime, err := time.ParseInLocation("2006-01-02T15:04:05", beginTimeStr, time.Local)
if err != nil {
log.Error("Can not ParseInLocation.", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("ParseInLocation_get_error"))
return
}
beginTimeUnix = beginTime.Unix()
endTime, err := time.ParseInLocation("2006-01-02T15:04:05", endTimeStr, time.Local)
if err != nil {
log.Error("Can not ParseInLocation.", err)
ctx.Error(http.StatusBadRequest, ctx.Tr("ParseInLocation_get_error"))
return
}
endTimeUnix = endTime.Unix()
}

if cloudBrainType == models.TypeCloudBrainOne && aiCenter == models.AICenterOfCloudBrainOne {
aiCenter = ""
}
@@ -730,7 +756,7 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet), string(models.JobTypeSnn4Ecoset))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}
@@ -753,18 +779,21 @@ func GetCloudbrainsDetailData(ctx *context.Context) {
Page: page,
PageSize: pageSize,
},
Keyword: keyword,
Type: cloudBrainType,
ComputeResource: listType,
JobTypeNot: jobTypeNot,
JobStatusNot: jobStatusNot,
JobStatus: jobStatuses,
JobTypes: jobTypes,
NeedRepoInfo: true,
BeginTimeUnix: int64(recordBeginTime),
EndTimeUnix: endTime.Unix(),
AiCenter: aiCenter,
NeedDeleteInfo: needDeleteInfo,
Keyword: keyword,
Type: cloudBrainType,
ComputeResource: listType,
JobTypeNot: jobTypeNot,
JobStatusNot: jobStatusNot,
JobStatus: jobStatuses,
JobTypes: jobTypes,
NeedRepoInfo: true,
BeginTimeUnix: beginTimeUnix,
EndTimeUnix: endTimeUnix,
AiCenter: aiCenter,
NeedDeleteInfo: needDeleteInfo,
AccCardType: accCardType,
AccCardsNum: accCardsNum,
WorkServerNumber: workServerNumber,
})
if err != nil {
ctx.ServerError("Get job failed:", err)
@@ -1039,7 +1068,7 @@ func getCloudbrainCount(beginTime time.Time, endTime time.Time, cloudbrains []*m
}
}

ComputeResourceList := []string{"CPU/GPU", "NPU"}
ComputeResourceList := []string{"CPU/GPU", "NPU", "GCU"}
for _, v := range ComputeResourceList {
if _, ok := cloudBrainComputeResource[v]; !ok {
cloudBrainComputeResource[v] = 0
@@ -1231,8 +1260,8 @@ func DownloadCloudBrainBoard(ctx *context.Context) {
Type: models.TypeCloudBrainAll,
BeginTimeUnix: int64(recordBeginTime),
EndTimeUnix: endTime.Unix(),
AccCardsNum: models.AccCardsNumAll,
})
log.Info("totalcountisis:", total)

if err != nil {
log.Warn("Can not get cloud brain info", err)
@@ -1261,6 +1290,7 @@ func DownloadCloudBrainBoard(ctx *context.Context) {
BeginTimeUnix: int64(recordBeginTime),
EndTimeUnix: endTime.Unix(),
NeedRepoInfo: true,
AccCardsNum: models.AccCardsNumAll,
})
if err != nil {
log.Warn("Can not get cloud brain info", err)


+ 22
- 0
routers/api/v1/repo/datasets.go View File

@@ -51,6 +51,28 @@ func CurrentRepoDatasetMultiple(ctx *context.APIContext) {

}

func CurrentRepoDatasetInfoWithoutAttachment(ctx *context.APIContext) {
dataset, err := models.GetDatasetByRepo(ctx.Repo.Repository)

if err != nil {
log.Warn("can not get dataset.", err)
ctx.JSON(200, map[string]interface{}{
"code": 0,
"message": "",
"data": []*api.Dataset{},
})
return
}

dataset.Repo = ctx.Repo.Repository
ctx.JSON(200, map[string]interface{}{
"code": 0,
"message": "",
"data": []*api.Dataset{convert.ToDataset(dataset)},
})

}

func MyDatasetsMultiple(ctx *context.APIContext) {

opts := &models.SearchDatasetOptions{


+ 5
- 0
routers/api/v1/repo/modelmanage.go View File

@@ -165,3 +165,8 @@ func QueryModelConvertByName(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, nil)
}
}

func MultiModelDownload(ctx *context.APIContext) {
log.Info("MultiModelDownload by api.")
routerRepo.MultiModelDownload(ctx.Context)
}

+ 20
- 0
routers/api/v1/user/repo.go View File

@@ -5,6 +5,7 @@
package user

import (
"code.gitea.io/gitea/modules/modelarts"
"net/http"

"code.gitea.io/gitea/models"
@@ -146,3 +147,22 @@ func ListOrgRepos(ctx *context.APIContext) {

listUserRepos(ctx, ctx.Org.Organization, ctx.IsSigned)
}

func GetComputeNodes(ctx *context.APIContext) {
taskeType := ctx.QueryInt("type")
if taskeType == 2 {
ctx.JSON(http.StatusOK, []int{1})
} else {
modelarts.InitMultiNode()
if modelarts.MultiNodeConfig != nil {
for _, info := range modelarts.MultiNodeConfig.Info {
if isInOrg, _ := models.IsOrganizationMemberByOrgName(info.Org, ctx.User.ID); isInOrg {
ctx.JSON(http.StatusOK, info.Node)
return
}
}
}
ctx.JSON(http.StatusOK, []int{1})
}

}

+ 4
- 0
routers/home.go View File

@@ -42,6 +42,7 @@ const (
tplExploreImages base.TplName = "explore/images"
tplExploreExploreDataAnalysis base.TplName = "explore/data_analysis"
tplHomeTerm base.TplName = "terms"
tplHomeAnnual base.TplName = "annual_privacy"
tplHomePrivacy base.TplName = "privacy"
tplResoruceDesc base.TplName = "resource_desc"
tplRepoSquare base.TplName = "explore/repos/square"
@@ -966,6 +967,9 @@ func RecommendHomeInfo(ctx *context.Context) {
func HomeTerm(ctx *context.Context) {
ctx.HTML(200, tplHomeTerm)
}
func HomeAnnual(ctx *context.Context) {
ctx.HTML(200, tplHomeAnnual)
}

func HomePrivacy(ctx *context.Context) {
ctx.HTML(200, tplHomePrivacy)


+ 1
- 1
routers/repo/ai_model_manage.go View File

@@ -76,7 +76,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio
cloudType := aiTask.Type
modelSelectedFile := ctx.Query("modelSelectedFile")
//download model zip //train type
if aiTask.ComputeResource == models.NPUResource {
if aiTask.ComputeResource == models.NPUResource || aiTask.ComputeResource == models.GCUResource {
cloudType = models.TypeCloudBrainTwo
} else if aiTask.ComputeResource == models.GPUResource {
cloudType = models.TypeCloudBrainOne


+ 23
- 7
routers/repo/aisafety.go View File

@@ -2,6 +2,8 @@ package repo

import (
"bufio"
"code.gitea.io/gitea/services/cloudbrain/cloudbrainTask"
"code.gitea.io/gitea/services/lock"
"encoding/json"
"errors"
"fmt"
@@ -508,7 +510,7 @@ func AiSafetyCreateForGetGPU(ctx *context.Context) {
} else {
log.Info("The GPU WaitCount not get")
}
NotStopTaskCount, _ := models.GetModelSafetyCountByUserID(ctx.User.ID)
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeBenchmark))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount
ctx.HTML(200, tplModelSafetyTestCreateGpu)
}
@@ -552,7 +554,7 @@ func AiSafetyCreateForGetNPU(ctx *context.Context) {
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount
log.Info("The NPU WaitCount is " + fmt.Sprint(waitCount))
NotStopTaskCount, _ := models.GetModelSafetyCountByUserID(ctx.User.ID)
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeBenchmark))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount
ctx.HTML(200, tplModelSafetyTestCreateNpu)
}
@@ -575,7 +577,21 @@ func AiSafetyCreateForPost(ctx *context.Context) {
tpname = tplCloudBrainModelSafetyNewGpu
}

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeModelSafety), displayJobName)
lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeBenchmark)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
modelSafetyNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr(errMsg), tpname, nil)
return
}

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeBenchmark), displayJobName)
if err == nil {
if len(tasks) != 0 {
log.Error("the job name did already exist", ctx.Data["MsgID"])
@@ -598,7 +614,7 @@ func AiSafetyCreateForPost(ctx *context.Context) {
return
}

count, err := models.GetModelSafetyCountByUserID(ctx.User.ID)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeBenchmark))
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
modelSafetyNewDataPrepare(ctx)
@@ -681,7 +697,7 @@ func createForNPU(ctx *context.Context, jobName string) error {
//ctx.RenderWithErr("Resource specification not available", tplCloudBrainModelSafetyNewNpu, nil)
return errors.New("Resource specification not available")
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
return errors.New(ctx.Tr("points.insufficient_points_balance"))
}
@@ -838,7 +854,7 @@ func createForGPU(ctx *context.Context, jobName string) error {
return errors.New("Resource specification not available")
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
return errors.New(ctx.Tr("points.insufficient_points_balance"))
}
@@ -959,7 +975,7 @@ func modelSafetyNewDataPrepare(ctx *context.Context) error {
ctx.Data["ckpt_name"] = ctx.Query("ckpt_name")
ctx.Data["model_name"] = ctx.Query("model_name")
ctx.Data["model_version"] = ctx.Query("model_version")
NotStopTaskCount, _ := models.GetModelSafetyCountByUserID(ctx.User.ID)
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeBenchmark))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

if ctx.QueryInt("type") == models.TypeCloudBrainOne {


+ 248
- 161
routers/repo/cloudbrain.go View File

@@ -2,6 +2,7 @@ package repo

import (
"bufio"
"code.gitea.io/gitea/services/lock"
"encoding/json"
"errors"
"fmt"
@@ -40,8 +41,6 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/util"
@@ -135,7 +134,7 @@ func cloudBrainNewDataPrepare(ctx *context.Context, jobType string) error {
defaultMode = "alogrithm"
}
ctx.Data["benchmarkMode"] = defaultMode
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, jobType)
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

if ctx.Cloudbrain != nil {
@@ -229,15 +228,37 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
tpl = tplCloudBrainTrainJobNew
}

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobType(jobType),
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: form.JobType}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr(errMsg), tpl, &form)
return
}
defer lock.UnLock()

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
if err == nil {
@@ -269,7 +290,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
return
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, jobType)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
@@ -285,7 +306,7 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
}
var datasetInfos map[string]models.DatasetInfo
var datasetNames string
//var
var attachSize int64
if uuids != "" {
datasetInfos, datasetNames, err = models.GetDatasetInfo(uuids)
if err != nil {
@@ -294,6 +315,18 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form)
return
}

if jobType == string(models.JobTypeDebug) {
for _, infos := range datasetInfos {
attachSize += infos.Size
}
if attachSize > int64(setting.DebugAttachSize*1000*1000*1000) {
log.Error("The DatasetSize exceeds the limit (%dGB)", setting.DebugAttachSize) // GB
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.debug_datasetsize", setting.DebugAttachSize), tpl, &form)
return
}
}
}

command := cloudbrain.GetCloudbrainDebugCommand()
@@ -329,24 +362,6 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {

commitID, _ := ctx.Repo.GitRepo.GetBranchCommitID(branchName)

spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobType(jobType),
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}

req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
@@ -387,7 +402,6 @@ func cloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
req.ModelVersion = form.ModelVersion
req.PreTrainModelPath = setting.Attachment.Minio.RealPath + form.PreTrainModelUrl
req.PreTrainModelUrl = form.PreTrainModelUrl

}

_, err = cloudbrain.GenerateTask(req)
@@ -451,15 +465,36 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra
repo := ctx.Repo.Repository
tpl := tplCloudBrainInferenceJobNew

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: jobType}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr(errMsg), tpl, &form)
return
}
defer lock.UnLock()

ckptUrl := setting.Attachment.Minio.RealPath + form.TrainUrl + form.CkptName
log.Info("ckpt url:" + ckptUrl)
@@ -502,7 +537,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra
return
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, jobType)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
@@ -536,22 +571,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form)
return
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}

req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
@@ -592,8 +612,10 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, form auth.CreateCloudBra

}

/**
检查用户传输的参数是否符合专属资源池
/*
*

检查用户传输的参数是否符合专属资源池
*/
func checkCloudBrainSpecialPool(ctx *context.Context, jobType string, queue string, resourceSpecId int) string {
if cloudbrain.SpecialPools != nil {
@@ -634,25 +656,21 @@ func CloudBrainRestart(ctx *context.Context) {
var errorMsg = ""
var status = string(models.JobWaiting)
task := ctx.Cloudbrain
for {
if task.Status != string(models.JobStopped) && task.Status != string(models.JobSucceeded) && task.Status != string(models.JobFailed) {
log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = "the job is not stopped"
break
}

if task.Image == "" || task.GpuQueue == "" || task.Type != models.TypeCloudBrainOne {
log.Error("the job(%s) version is too old", task.JobName, ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = "the job's version is too old and can not be restarted"
break
lockOperator, errMsg := cloudbrainService.Lock4CloudbrainRestart(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{JobType: task.JobType}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()) {
log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = "you have no right to restart the job"
if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = ctx.Tr(errMsg)
}
for {
if errorMsg != "" {
break
}

@@ -676,13 +694,34 @@ func CloudBrainRestart(ctx *context.Context) {
}
task.Spec = spec

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
resultCode = "-1"
errorMsg = ctx.Tr("points.insufficient_points_balance")
break
}

if task.Status != string(models.JobStopped) && task.Status != string(models.JobSucceeded) && task.Status != string(models.JobFailed) {
log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = "the job is not stopped"
break
}

if task.Image == "" || task.GpuQueue == "" || task.Type != models.TypeCloudBrainOne {
log.Error("the job(%s) version is too old", task.JobName, ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = "the job's version is too old and can not be restarted"
break
}

if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()) {
log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"])
resultCode = "-1"
errorMsg = "you have no right to restart the job"
break
}

if _, err := os.Stat(getOldJobPath(task)); err != nil {
log.Error("Can not find job minio path", err)
resultCode = "-1"
@@ -690,7 +729,7 @@ func CloudBrainRestart(ctx *context.Context) {
break
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, string(models.JobTypeDebug))
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
resultCode = "-1"
@@ -843,7 +882,7 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName, jobType models.Jo

if task.JobType == string(models.JobTypeBenchmark) {
task.BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.algorithm")
} else if task.JobType == string(models.JobTypeSnn4imagenet) || task.JobType == string(models.JobTypeBrainScore) {
} else if models.IsModelBenchMarkJobType(task.JobType) {
task.BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.model")
task.BenchmarkTypeName = task.JobType
ctx.Data["BenchmarkTypeName"] = task.JobType
@@ -1309,8 +1348,8 @@ func DeleteJobsByRepoID(repoID int64) {
DeleteJobs(cloudBrains)
}

/**
/*
*
*/
func StopJobs(cloudBrains []*models.Cloudbrain) {

@@ -1340,14 +1379,11 @@ func StopJobs(cloudBrains []*models.Cloudbrain) {
logErrorAndUpdateJobStatus(err, taskInfo)
}
} else if taskInfo.Type == models.TypeC2Net {
if taskInfo.JobType == string(models.JobTypeTrain) {
err := retry(3, time.Second*30, func() error {
_, err := grampus.StopJob(taskInfo.JobID)
return err
})
logErrorAndUpdateJobStatus(err, taskInfo)
}

err := retry(3, time.Second*30, func() error {
_, err := grampus.StopJob(taskInfo.JobID, taskInfo.JobType)
return err
})
logErrorAndUpdateJobStatus(err, taskInfo)
}
}
}
@@ -1692,6 +1728,8 @@ func GetRate(ctx *context.Context) {
ctx.Redirect(setting.Snn4imagenetServerHost)
} else if job.JobType == string(models.JobTypeBrainScore) {
ctx.Redirect(setting.BrainScoreServerHost)
} else if job.JobType == string(models.JobTypeSnn4Ecoset) {
ctx.Redirect(setting.Snn4EcosetServerHost)
} else {
log.Error("JobType error:%s", job.JobType, ctx.Data["msgID"])
}
@@ -2164,7 +2202,7 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
}

var jobTypes []string
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet), string(models.JobTypeModelSafety))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet), string(models.JobTypeSnn4Ecoset), string(models.JobTypeModelSafety))
ciTasks, count, err := models.Cloudbrains(&models.CloudbrainsOptions{
ListOptions: models.ListOptions{
Page: page,
@@ -2197,14 +2235,16 @@ func CloudBrainBenchmarkIndex(ctx *context.Context) {
ciTasks[i].BenchmarkTypeName = ""
if ciTasks[i].JobType == string(models.JobTypeBenchmark) {
ciTasks[i].BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.algorithm")
} else if ciTasks[i].JobType == string(models.JobTypeSnn4imagenet) || ciTasks[i].JobType == string(models.JobTypeBrainScore) {
} else if models.IsModelBenchMarkJobType(ciTasks[i].JobType) {
ciTasks[i].BenchmarkType = ctx.Tr("repo.cloudbrain.benchmark.model")
ciTasks[i].BenchmarkTypeName = ciTasks[i].JobType

if ciTasks[i].JobType == string(models.JobTypeSnn4imagenet) {
ciTasks[i].BenchmarkTypeRankLink = setting.Snn4imagenetServerHost
} else {
} else if ciTasks[i].JobType == string(models.JobTypeBrainScore) {
ciTasks[i].BenchmarkTypeRankLink = setting.BrainScoreServerHost
} else {
ciTasks[i].BenchmarkTypeRankLink = setting.Snn4EcosetServerHost
}

}
@@ -2373,17 +2413,38 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo
ctx.Data["benchmarkTypeID"] = benchmarkTypeID
ctx.Data["benchmark_child_types_id_hidden"] = benchmarkChildTypeID

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), form.JobType, displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeBenchmark,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tplCloudBrainBenchmarkNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplCloudBrainBenchmarkNew, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeBenchmark)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplCloudBrainBenchmarkNew, &form)
ctx.RenderWithErr(ctx.Tr(errMsg), tplCloudBrainBenchmarkNew, &form)
return
}
defer lock.UnLock()

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeBenchmark), displayJobName)
if err == nil {
if len(tasks) != 0 {
log.Error("the job name did already exist", ctx.Data["MsgID"])
@@ -2414,24 +2475,7 @@ func BenchMarkAlgorithmCreate(ctx *context.Context, form auth.CreateCloudBrainFo
return
}

spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeBenchmark,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tplCloudBrainBenchmarkNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplCloudBrainBenchmarkNew, &form)
return
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeBenchmark))
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
@@ -2554,7 +2598,6 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
displayJobName := form.DisplayJobName
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
image := form.Image
uuid := form.Attachment
jobType := form.JobType
codePath := setting.JobPath + jobName + cloudbrain.CodeMountPath
branchName := cloudbrain.DefaultBranchName
@@ -2563,17 +2606,39 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
tpl := tplCloudBrainBenchmarkNew
command := cloudbrain.GetCloudbrainDebugCommand()

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeBenchmark,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}
defer lock.UnLock()

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, jobType, displayJobName)
lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeBenchmark)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr(errMsg), tpl, &form)
return
}

tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeBenchmark), displayJobName)
if err == nil {
if len(tasks) != 0 {
log.Error("the job name did already exist", ctx.Data["MsgID"])
@@ -2596,14 +2661,14 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
return
}

if jobType != string(models.JobTypeSnn4imagenet) && jobType != string(models.JobTypeBrainScore) {
if !models.IsModelBenchMarkJobType(jobType) {
log.Error("jobtype error:", jobType, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("jobtype error", tpl, &form)
return
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeBenchmark))
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
@@ -2625,46 +2690,41 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
mkModelPath(modelPath)
uploadCodeToMinio(modelPath, jobName, cloudbrain.ModelMountPath+"/")

snn4imagenetPath := setting.JobPath + jobName + cloudbrain.Snn4imagenetMountPath
benchmarkPath := setting.JobPath + jobName + cloudbrain.BenchMarkMountPath
if setting.IsSnn4imagenetEnabled && jobType == string(models.JobTypeSnn4imagenet) {
downloadRateCode(repo, jobName, setting.Snn4imagenetOwner, setting.Snn4imagenetName, snn4imagenetPath, "", "", ctx.User.Name)
uploadCodeToMinio(snn4imagenetPath+"/", jobName, cloudbrain.Snn4imagenetMountPath+"/")
command = fmt.Sprintf(cloudbrain.Snn4imagenetCommand, displayJobName, trimSpaceNewlineInString(form.Description))
downloadRateCode(repo, jobName, setting.Snn4imagenetOwner, setting.Snn4imagenetName, benchmarkPath, "", "", ctx.User.Name)
uploadCodeToMinio(benchmarkPath+"/", jobName, cloudbrain.BenchMarkMountPath+"/")
command = fmt.Sprintf(cloudbrain.Snn4imagenetCommand, displayJobName, form.CkptName, trimSpaceNewlineInString(form.Description))

}
benchmarkChildTypeID := 0
brainScorePath := setting.JobPath + jobName + cloudbrain.BrainScoreMountPath
if setting.IsBrainScoreEnabled && jobType == string(models.JobTypeBrainScore) {
downloadRateCode(repo, jobName, setting.BrainScoreOwner, setting.BrainScoreName, brainScorePath, "", "", ctx.User.Name)
uploadCodeToMinio(brainScorePath+"/", jobName, cloudbrain.BrainScoreMountPath+"/")
downloadRateCode(repo, jobName, setting.BrainScoreOwner, setting.BrainScoreName, benchmarkPath, "", "", ctx.User.Name)
uploadCodeToMinio(benchmarkPath+"/", jobName, cloudbrain.BenchMarkMountPath+"/")
benchmarkChildTypeID = form.BenchmarkChildTypeID
command = fmt.Sprintf(cloudbrain.BrainScoreCommand, getBrainRegion(benchmarkChildTypeID), displayJobName, trimSpaceNewlineInString(form.Description))
command = fmt.Sprintf(cloudbrain.BrainScoreCommand, getBrainRegion(benchmarkChildTypeID), displayJobName, form.CkptName, trimSpaceNewlineInString(form.Description))
}
var uuid string
var datasetInfos map[string]models.DatasetInfo
var datasetNames string
if setting.IsSnn4EcosetEnabled && jobType == string(models.JobTypeSnn4Ecoset) {
downloadRateCode(repo, jobName, setting.Snn4EcosetOwner, setting.Snn4EcosetName, benchmarkPath, "", "", ctx.User.Name)
uploadCodeToMinio(benchmarkPath+"/", jobName, cloudbrain.BenchMarkMountPath+"/")
command = fmt.Sprintf(cloudbrain.Snn4EcosetCommand, displayJobName, form.CkptName, trimSpaceNewlineInString(form.Description))

datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid)
if err != nil {
log.Error("GetDatasetInfo failed: %v", err, ctx.Data["MsgID"])
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form)
return
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeBenchmark,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}
attachment, err := getEcosetAttachment()
if err != nil {
log.Error("load benchmark code failed", err)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain.morethanonejob"), tpl, &form)
return
}
uuid = attachment.UUID
datasetInfos, datasetNames, _ = models.GetDatasetInfo(uuid)

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
cloudBrainNewDataPrepare(ctx, jobType)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}

log.Info("Command=" + command)
log.Info("ModelPath=" + storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"))
req := cloudbrain.GenerateCloudBrainTaskReq{
@@ -2679,8 +2739,6 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
CodePath: storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"),
ModelPath: storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"),
BenchmarkPath: storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"),
Snn4ImageNetPath: storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"),
BrainScorePath: storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"),
JobType: jobType,
Description: form.Description,
BranchName: branchName,
@@ -2692,6 +2750,14 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
ResultPath: storage.GetMinioPath(jobName, cloudbrain.ResultPath+"/"),
Spec: spec,
}
if form.ModelName != "" {
req.ModelName = form.ModelName
req.LabelName = form.LabelName
req.CkptName = form.CkptName
req.ModelVersion = form.ModelVersion
req.PreTrainModelPath = setting.Attachment.Minio.RealPath + form.PreTrainModelUrl
req.PreTrainModelUrl = form.PreTrainModelUrl
}

_, err = cloudbrain.GenerateTask(req)
if err != nil {
@@ -2703,6 +2769,21 @@ func ModelBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainForm)
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/cloudbrain/benchmark")
}

func getEcosetAttachment() (*models.Attachment, error) {
ecosetRepo, err := models.GetRepositoryByOwnerAndName(setting.Snn4EcosetOwner, setting.Snn4EcosetName)
if err != nil {
return nil, err
}

datasetInfo, err := models.GetDatasetByRepo(ecosetRepo)
if err != nil {
return nil, err
}

return models.GetAttachmentByDatasetIdFileName(setting.Snn4AttachmentName, datasetInfo.ID)

}

func getBrainRegion(benchmarkChildTypeID int) string {
values := []string{"V1", "V2", "V4", "IT"}
return values[benchmarkChildTypeID]
@@ -2763,18 +2844,24 @@ func InferenceCloudBrainJobShow(ctx *context.Context) {
cloudBrainShow(ctx, tplCloudBrainInferenceJobShow, models.JobTypeInference)
}

func DownloadInferenceResultFile(ctx *context.Context) {
func DownloadGPUInferenceResultFile(ctx *context.Context) {
var jobID = ctx.Params(":jobid")
var versionName = ctx.Query("version_name")
task, err := models.GetCloudbrainByJobIDAndVersionName(jobID, versionName)
task, err := models.GetCloudbrainByJobID(jobID)
if err != nil {
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error())
return
}

allFile, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, task.ResultUrl)
returnFileName := task.DisplayJobName + ".zip"
MinioDownloadManyFile(task.ResultUrl, ctx, returnFileName, allFile)
parentDir := ctx.Query("parentDir")
filePath := "jobs/" + task.JobName + "/result/" + parentDir
log.Info("prefix=" + filePath)
allFile, err := storage.GetAllObjectByBucketAndPrefixMinio(setting.Attachment.Minio.Bucket, filePath)
if err == nil {
returnFileName := task.DisplayJobName + ".zip"
MinioDownloadManyFile(filePath, ctx, returnFileName, allFile)
} else {
log.Info("error,msg=" + err.Error())
ctx.ServerError("no file to download.", err)
}
}

func getInferenceJobCommand(form auth.CreateCloudBrainInferencForm) (string, error) {


+ 1
- 0
routers/repo/dataset.go View File

@@ -373,6 +373,7 @@ func datasetMultiple(ctx *context.Context, opts *models.SearchDatasetOptions) {
}

data, err := json.Marshal(datasets)
log.Info("datakey", string(data))
if err != nil {
log.Error("json.Marshal failed:", err.Error())
ctx.JSON(200, map[string]string{


+ 195
- 98
routers/repo/grampus.go View File

@@ -11,6 +11,8 @@ import (
"strconv"
"strings"

"code.gitea.io/gitea/services/lock"

"code.gitea.io/gitea/modules/urfs_client/urchin"
"code.gitea.io/gitea/routers/response"

@@ -27,8 +29,6 @@ import (
"code.gitea.io/gitea/modules/grampus"
"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"github.com/unknwon/com"
@@ -53,6 +53,8 @@ const (
//NPU
tplGrampusNotebookNPUNew base.TplName = "repo/grampus/notebook/npu/new"
tplGrampusTrainJobNPUNew base.TplName = "repo/grampus/trainjob/npu/new"
//GCU
tplGrampusNotebookGCUNew base.TplName = "repo/grampus/notebook/gcu/new"
)

func GrampusNotebookNew(ctx *context.Context) {
@@ -61,6 +63,8 @@ func GrampusNotebookNew(ctx *context.Context) {
processType := grampus.ProcessorTypeGPU
if notebookType == 1 {
processType = grampus.ProcessorTypeNPU
} else if notebookType == 2 {
processType = grampus.ProcessorTypeGCU
}
err := grampusNotebookNewDataPrepare(ctx, processType)
if err != nil {
@@ -69,8 +73,10 @@ func GrampusNotebookNew(ctx *context.Context) {
}
if processType == grampus.ProcessorTypeGPU {
ctx.HTML(http.StatusOK, tplGrampusNotebookGPUNew)
} else {
} else if processType == grampus.ProcessorTypeNPU {
ctx.HTML(http.StatusOK, tplGrampusNotebookNPUNew)
} else if processType == grampus.ProcessorTypeGCU {
ctx.HTML(http.StatusOK, tplGrampusNotebookGCUNew)
}

}
@@ -117,15 +123,44 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook
computeSource = models.NPUResource
computeSourceSimple = models.NPU
codeStoragePath = grampus.JobPath + jobName + modelarts.CodePath
} else if form.Type == 2 {
tpl = tplGrampusNotebookGCUNew
processType = grampus.ProcessorTypeGCU
computeSource = models.GCUResource
computeSourceSimple = models.GCU
codeStoragePath = setting.CBCodePathPrefix + jobName + cloudbrain.CodeMountPath + "/"
}

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName))
defer lock.UnLock()
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
//check specification
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeDebug,
ComputeResource: computeSourceSimple,
Cluster: models.C2NetCluster,
})
if err != nil || spec == nil {
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tpl, &form)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeDebug)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr(errMsg), tpl, &form)
return
}

@@ -136,7 +171,7 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook
}

//check count limit
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeDebug), computeSource)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))
if err != nil {
log.Error("GetGrampusCountByUserID failed:%v", err, ctx.Data["MsgID"])
grampusNotebookNewDataPrepare(ctx, processType)
@@ -169,27 +204,9 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook
}
}

//check specification
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeDebug,
ComputeResource: computeSourceSimple,
Cluster: models.C2NetCluster,
})
if err != nil || spec == nil {
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tpl, &form)
return
}

var datasetInfos map[string]models.DatasetInfo
var datasetNames string
var attachSize int64
//var
if uuid != "" {
datasetInfos, datasetNames, err = models.GetDatasetInfo(uuid, computeSourceSimple)
@@ -199,6 +216,21 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.dataset_select"), tpl, &form)
return
}
uuidArray := strings.Split(uuid, ";")
if datasetInfos == nil || len(datasetInfos) < len(uuidArray) {
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.partial_datasets_not_available"), tpl, &form)
return
}
for _, infos := range datasetInfos {
attachSize += infos.Size
}
if attachSize > int64(setting.DebugAttachSize*1000*1000*1000) {
log.Error("The DatasetSize exceeds the limit (%dGB)", setting.DebugAttachSize) // GB
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.debug_datasetsize", setting.DebugAttachSize), tpl, &form)
return
}
}

//prepare code and out path
@@ -215,7 +247,7 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook
return
}

if processType == grampus.ProcessorTypeGPU {
if processType == grampus.ProcessorTypeGPU || processType == grampus.ProcessorTypeGCU {
if err := uploadCodeToMinio(codeLocalPath+"/", jobName, cloudbrain.CodeMountPath+"/"); err != nil {
log.Error("Failed to uploadCodeToMinio: %s (%v)", repo.FullName(), err, ctx.Data["MsgID"])
grampusNotebookNewDataPrepare(ctx, processType)
@@ -255,20 +287,26 @@ func GrampusNotebookCreate(ctx *context.Context, form auth.CreateGrampusNotebook

if form.ModelName != "" { //使用预训练模型训练

_, err := models.QueryModelByPath(form.PreTrainModelUrl)
m, err := models.QueryModelByPath(form.PreTrainModelUrl)
if err != nil {
log.Error("Can not find model", err)
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr("repo.modelconvert.manage.model_not_exist"), tpl, &form)
return
}
if !cloudbrainTask.IsModelFileExists(m, form.CkptName) {
log.Error("model file not exist.name = %s", form.CkptName)
grampusNotebookNewDataPrepare(ctx, processType)
ctx.RenderWithErr(ctx.Tr("repo.modelconvert.manage.model_file_not_exist"), tpl, &form)
return
}
req.ModelName = form.ModelName
req.LabelName = form.LabelName
req.CkptName = form.CkptName
req.ModelVersion = form.ModelVersion
req.PreTrainModelUrl = form.PreTrainModelUrl
req.PreTrainModelPath = getPreTrainModelPath(form.PreTrainModelUrl, form.CkptName)
req.ModelStorageType = m.Type
}

_, err = grampus.GenerateNotebookJob(ctx, req)
@@ -287,7 +325,7 @@ func grampusNotebookNewDataPrepare(ctx *context.Context, processType string) err
ctx.Data["display_job_name"] = displayJobName

//get valid images
if processType == grampus.ProcessorTypeNPU {
if processType == grampus.ProcessorTypeNPU || processType == grampus.ProcessorTypeGCU {
images, err := grampus.GetImages(processType, string(models.JobTypeDebug))
if err != nil {
log.Error("GetImages failed:", err.Error())
@@ -303,6 +341,10 @@ func grampusNotebookNewDataPrepare(ctx *context.Context, processType string) err
computeResourceSimple = models.NPU
datasetType = models.TypeCloudBrainTwo
computeResource = models.NPUResource
} else if processType == grampus.ProcessorTypeGCU {
computeResourceSimple = models.GCU
datasetType = models.TypeCloudBrainAll
computeResource = models.GCUResource
}

prepareGrampusSpecs(ctx, computeResourceSimple, models.JobTypeDebug)
@@ -320,7 +362,7 @@ func grampusNotebookNewDataPrepare(ctx *context.Context, processType string) err
ctx.Data["datasetType"] = datasetType
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeC2Net, computeResource, models.JobTypeDebug)
ctx.Data["WaitCount"] = waitCount
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeDebug), computeResource)
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

ctx.Data["code_path"] = cloudbrain.CodeMountPath
@@ -367,14 +409,14 @@ func grampusTrainJobNewDataPrepare(ctx *context.Context, processType string) err
ctx.Data["datasetType"] = models.TypeCloudBrainOne
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeC2Net, models.GPUResource, models.JobTypeTrain)
ctx.Data["WaitCount"] = waitCount
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.GPUResource)
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

} else if processType == grampus.ProcessorTypeNPU {
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeC2Net, models.NPUResource, models.JobTypeTrain)
ctx.Data["WaitCount"] = waitCount
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.NPUResource)
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount
}

@@ -476,19 +518,42 @@ func grampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
image := strings.TrimSpace(form.Image)
tpl := tplGrampusTrainJobGPUNew

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
if !jobNamePattern.MatchString(displayJobName) {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplGrampusTrainJobGPUNew, &form)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form)
return
}
defer lock.UnLock()

if !jobNamePattern.MatchString(displayJobName) {
//check specification
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.GPU,
Cluster: models.C2NetCluster,
})
if err != nil || spec == nil {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplGrampusTrainJobGPUNew, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeTrain)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr(ctx.Tr(errMsg), tpl, &form)
return
}

@@ -501,7 +566,7 @@ func grampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
}

//check count limit
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.GPUResource)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
if err != nil {
log.Error("GetGrampusCountByUserID failed:%v", err, ctx.Data["MsgID"])
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
@@ -542,25 +607,6 @@ func grampusTrainJobGpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
}
}

//check specification
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.GPU,
Cluster: models.C2NetCluster,
})
if err != nil || spec == nil {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeGPU)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplGrampusTrainJobGPUNew, &form)
return
}

//check dataset

datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid, models.GPU)
@@ -724,19 +770,41 @@ func grampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
engineName := form.EngineName
tpl := tplGrampusTrainJobNPUNew

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
if !jobNamePattern.MatchString(displayJobName) {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplGrampusTrainJobNPUNew, &form)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form)
return
}
defer lock.UnLock()

if !jobNamePattern.MatchString(displayJobName) {
//check specification
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.NPU,
Cluster: models.C2NetCluster,
})
if err != nil || spec == nil {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tpl, &form)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplGrampusTrainJobNPUNew, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeTrain)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr(errMsg), tpl, &form)
return
}

@@ -749,7 +817,7 @@ func grampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
}

//check count limit
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeTrain), models.NPUResource)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
if err != nil {
log.Error("GetGrampusCountByUserID failed:%v", err, ctx.Data["MsgID"])
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
@@ -790,24 +858,6 @@ func grampusTrainJobNpuCreate(ctx *context.Context, form auth.CreateGrampusTrain
}
}

//check specification
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.NPU,
Cluster: models.C2NetCluster,
})
if err != nil || spec == nil {
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr("Resource specification not available", tpl, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
grampusTrainJobNewDataPrepare(ctx, grampus.ProcessorTypeNPU)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplGrampusTrainJobNPUNew, &form)
return
}

//check dataset
datasetInfos, datasetNames, err := models.GetDatasetInfo(uuid, models.NPU)
if err != nil {
@@ -1239,7 +1289,7 @@ func GrampusTrainJobShow(ctx *context.Context) {
return
}
task.ContainerIp = ""
task.User, _ = models.GetUserByID(task.UserID)
if task.DeletedAt.IsZero() { //normal record
result, err := grampus.GetJob(task.JobID)
if err != nil {
@@ -1308,6 +1358,7 @@ func GrampusTrainJobShow(ctx *context.Context) {
taskList := make([]*models.Cloudbrain, 0)
taskList = append(taskList, task)
prepareSpec4Show(ctx, task)

ctx.Data["version_list_task"] = taskList
ctx.Data["datasetDownload"] = GetCloudBrainDataSetInfo(task.Uuid, task.DatasetName, false)
ctx.Data["canDownload"] = cloudbrain.CanModifyJob(ctx, task)
@@ -1348,16 +1399,39 @@ func GrampusGetLog(ctx *context.Context) {
return
}

result, err := grampus.GetJob(jobID)
if err != nil {
log.Error("GetJob(%s) failed:%v", job.JobName, err)
ctx.JSON(http.StatusOK, map[string]interface{}{
"JobName": job.JobName,
"Content": "",
"CanLogDownload": false,
})
return
}
exitDiagnostics := ""
if result != nil {
exitDiagnostics = result.ExitDiagnostics
}

content, err := grampus.GetTrainJobLog(job.JobID)
if err != nil {
log.Error("GetTrainJobLog failed: %v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, map[string]interface{}{
"JobName": job.JobName,
"Content": "",
"Content": exitDiagnostics,
"CanLogDownload": false,
})
return
}

if result != nil {
job.Status = grampus.TransTrainJobStatus(result.JobInfo.Status)
if job.Status == models.GrampusStatusFailed {
content = content + "\n" + exitDiagnostics
}
}

canLogDownload := err == nil && job.IsUserHasRight(ctx.User)
ctx.JSON(http.StatusOK, map[string]interface{}{
"JobName": job.JobName,
@@ -1383,7 +1457,7 @@ func GrampusMetrics(ctx *context.Context) {
}
ctx.JSON(http.StatusOK, map[string]interface{}{
"JobID": jobID,
"Interval": result.Interval,
"Interval": 0,
"MetricsInfo": result.MetricsInfo,
})

@@ -1451,7 +1525,7 @@ func generateCommand(repoName, processorType, codeRemotePath, dataRemotePath, bo
var commandCode string
if processorType == grampus.ProcessorTypeNPU {
paramCode += " --model_url=" + modelRemoteObsUrl
commandCode = "/bin/bash /home/work/run_train_for_openi.sh /home/work/openi.py " + grampus.NpuLocalLogUrl + paramCode + ";"
commandCode = "source /home/ma-user/.bashrc;python /home/ma-user/davinci/train/davincirun.py python /home/ma-user/openi.py " + paramCode + ";"
} else if processorType == grampus.ProcessorTypeGPU {
if pretrainModelFileName != "" {
paramCode += " --ckpt_url" + "=" + workDir + "pretrainmodel/" + pretrainModelFileName
@@ -1601,7 +1675,22 @@ func GrampusNotebookRestart(ctx *context.Context) {
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainRestart(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{JobType: task.JobType}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
errorMsg = ctx.Tr(errMsg)
}

for {
if errorMsg != "" {
break
}

if task.Status != models.GrampusStatusStopped && task.Status != models.GrampusStatusSucceeded && task.Status != models.GrampusStatusFailed {
log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"])
@@ -1609,7 +1698,7 @@ func GrampusNotebookRestart(ctx *context.Context) {
break
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeC2Net, string(models.JobTypeDebug), task.ComputeResource)
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))

if err != nil {
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -1636,7 +1725,11 @@ func GrampusNotebookRestart(ctx *context.Context) {
if task.ComputeResource == models.NPUResource {
computeSourceSimple = models.NPU
action = models.ActionCreateGrampusNPUDebugTask
} else if task.ComputeResource == models.GCUResource {
computeSourceSimple = models.GCU
action = models.ActionCreateGrampusGCUDebugTask
}

spec, err = resource.GetAndCheckSpec(ctx.User.ID, oldSpec.ID, models.FindSpecsOptions{
JobType: models.JobType(task.JobType),
ComputeResource: computeSourceSimple,
@@ -1647,12 +1740,12 @@ func GrampusNotebookRestart(ctx *context.Context) {
errorMsg = "Resource specification not support any more"
break
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
errorMsg = ctx.Tr("points.insufficient_points_balance")
break
}
if task.IsGPUTask() {
if task.IsGPUTask() || task.IsGCUTask() {
if _, err := os.Stat(getOldJobPath(task)); err != nil {
log.Error("Can not find job minio path", err)
resultCode = "-1"
@@ -1682,6 +1775,10 @@ func GrampusNotebookRestart(ctx *context.Context) {
if res.GrampusResult.ErrorCode != 0 || res.NewId == "" {
log.Error("ManageNotebook2 failed:" + res.GrampusResult.ErrorMsg)
errorMsg = ctx.Tr("repo.debug_again_fail")
if res.GrampusResult.ErrorCode == 5005 {
errorMsg = ctx.Tr("repo.debug_again_fail_forever")
}

break
}



+ 24
- 0
routers/repo/issue.go View File

@@ -2079,3 +2079,27 @@ func attachmentsHTML(ctx *context.Context, attachments []*models.Attachment) str
}
return attachHTML
}

func SetIssueStayTop(ctx *context.Context) {
issue := GetActionIssue(ctx)
if ctx.Written() {
return
}
isStayTop := ctx.QueryBool("isStayTop")
if !ctx.IsSigned || (!issue.IsPoster(ctx.User.ID) && !ctx.Repo.CanWriteIssuesOrPulls(issue.IsPull)) {
ctx.Error(403)
return
}
var stayTop int64
stayTop = 0
if isStayTop {
stayTop = models.GetMaxStayTop(ctx.Repo.Repository.ID)
}
err := issue.ChangeStayTop(ctx.User, stayTop)
if err != nil {
log.Info("update stay top error," + err.Error())
}
ctx.JSON(200, map[string]interface{}{
"code": 0,
})
}

+ 172
- 121
routers/repo/modelarts.go View File

@@ -2,6 +2,7 @@ package repo

import (
"archive/zip"
"code.gitea.io/gitea/services/lock"
"encoding/json"
"errors"
"fmt"
@@ -35,8 +36,6 @@ import (
"code.gitea.io/gitea/modules/modelarts"
"code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/obs"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/timeutil"
@@ -147,7 +146,7 @@ func notebookNewDataPrepare(ctx *context.Context) error {

waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug))
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

return nil
@@ -176,17 +175,42 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm
imageId := form.ImageId
repo := ctx.Repo.Repository

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
var aiCenterCode = models.AICenterOfCloudBrainTwo
if setting.ModelartsCD.Enabled {
aiCenterCode = models.AICenterOfChengdu
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeDebug,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: aiCenterCode})
if err != nil || spec == nil {
notebookNewDataPrepare(ctx)
ctx.RenderWithErr("Resource specification not available", tplModelArtsNotebookNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
notebookNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsNotebookNew, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeDebug)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
notebookNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsNotebookNew, &form)
ctx.RenderWithErr(ctx.Tr(errMsg), tplModelArtsNotebookNew, &form)
return
}
defer lock.UnLock()

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug))
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))

if err != nil {
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -218,25 +242,20 @@ func Notebook2Create(ctx *context.Context, form auth.CreateModelArtsNotebookForm
return
}
}
var aiCenterCode = models.AICenterOfCloudBrainTwo
if setting.ModelartsCD.Enabled {
aiCenterCode = models.AICenterOfChengdu
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeDebug,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: aiCenterCode})
if err != nil || spec == nil {
notebookNewDataPrepare(ctx)
ctx.RenderWithErr("Resource specification not available", tplModelArtsNotebookNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
notebookNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsNotebookNew, &form)
return

var datasetInfos map[string]models.DatasetInfo
var attachSize int64
if uuid != "" {
datasetInfos, _, err = models.GetDatasetInfo(uuid)
for _, infos := range datasetInfos {
attachSize += infos.Size
}
if attachSize > int64(setting.DebugAttachSize*1000*1000*1000) {
log.Error("The DatasetSize exceeds the limit (%dGB)", setting.DebugAttachSize) //GB
notebookNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("cloudbrain.error.debug_datasetsize", setting.DebugAttachSize), tplModelArtsNotebookNew, &form)
return
}
}

req := cloudbrain.GenerateModelArtsNotebookReq{
@@ -441,7 +460,7 @@ func NotebookDebug2(ctx *context.Context) {
}

if ctx.QueryTrim("file") != "" {
ctx.Redirect(getFileUrl(result.Url, ctx.QueryTrim("file")) + "?token=" + result.Token)
ctx.Redirect(getFileUrl(result.Url, ctx.QueryTrim("file")) + "&token=" + result.Token)
} else {
if task.BootFile != "" {
go cloudbrainTask.UploadNotebookFiles(task)
@@ -467,7 +486,7 @@ func getFileUrl(url string, filename string) string {
}
}

return url + middle + filename
return url + middle + filename + "?reset"
}

func NotebookRestart(ctx *context.Context) {
@@ -478,8 +497,21 @@ func NotebookRestart(ctx *context.Context) {
var spec *models.Specification

task := ctx.Cloudbrain
lockOperator, errMsg := cloudbrainService.Lock4CloudbrainRestart(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{JobType: task.JobType}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
errorMsg = ctx.Tr(errMsg)
}
for {
if errMsg != "" {
break
}
ctx.CheckWechatBind()
if ctx.Written() {
return
@@ -490,7 +522,7 @@ func NotebookRestart(ctx *context.Context) {
break
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug))
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))

if err != nil {
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -526,7 +558,7 @@ func NotebookRestart(ctx *context.Context) {
errorMsg = "Resource specification not support any more"
break
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
errorMsg = ctx.Tr("points.insufficient_points_balance")
break
@@ -859,7 +891,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error {
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain))
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

setMultiNodeIfConfigureMatch(ctx)
@@ -1029,7 +1061,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error {
ctx.Data["config_list"] = configList.ParaConfigs
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain))
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

return nil
@@ -1067,17 +1099,38 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
return
}

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {
trainJobNewDataPrepare(ctx)
ctx.RenderWithErr("Resource specification not available", tplModelArtsTrainJobNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice, WorkServerNumber: form.WorkServerNumber}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
trainJobNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsTrainJobNew, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeTrain)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
trainJobNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsTrainJobNew, &form)
ctx.RenderWithErr(ctx.Tr(errMsg), tplModelArtsTrainJobNew, &form)
return
}
defer lock.UnLock()

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain))
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))

if err != nil {
log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -1108,23 +1161,6 @@ func TrainJobCreate(ctx *context.Context, form auth.CreateModelArtsTrainJobForm)
return
}

spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {
trainJobNewDataPrepare(ctx)
ctx.RenderWithErr("Resource specification not available", tplModelArtsTrainJobNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice*form.WorkServerNumber) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
trainJobNewDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsTrainJobNew, &form)
return
}

//Determine whether the task name of the task in the project is duplicated
tasks, err := models.GetCloudbrainsByDisplayJobName(repo.ID, string(models.JobTypeTrain), displayJobName)
if err == nil {
@@ -1445,6 +1481,37 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
ctx.Data["PageIsTrainJob"] = true
var jobID = ctx.Params(":jobid")

spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {
trainJobNewVersionDataPrepare(ctx)
ctx.RenderWithErr("Resource specification not available", tplModelArtsTrainJobVersionNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice, WorkServerNumber: form.WorkServerNumber}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
trainJobNewVersionDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsTrainJobVersionNew, &form)
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: form.DisplayJobName, JobType: string(models.JobTypeTrain)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
trainJobNewVersionDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr(errMsg), tplModelArtsTrainJobVersionNew, &form)
return
}

errStr := checkMultiNode(ctx.User.ID, form.WorkServerNumber)
if errStr != "" {
trainJobNewVersionDataPrepare(ctx)
@@ -1452,7 +1519,7 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
return
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeTrain))
count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
if err != nil {
log.Error("GetCloudbrainTrainJobCountByUserID failed:%v", err, ctx.Data["MsgID"])
trainJobNewVersionDataPrepare(ctx)
@@ -1496,16 +1563,6 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
EngineName := form.EngineName
isLatestVersion := modelarts.IsLatestVersion

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeTrain), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
trainJobNewVersionDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsTrainJobVersionNew, &form)
return
}
defer lock.UnLock()

canNewJob, _ := canUserCreateTrainJobVersion(ctx, latestTask.UserID)
if !canNewJob {
trainJobNewVersionDataPrepare(ctx)
@@ -1528,23 +1585,6 @@ func TrainJobCreateVersion(ctx *context.Context, form auth.CreateModelArtsTrainJ
return
}

spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {
trainJobNewVersionDataPrepare(ctx)
ctx.RenderWithErr("Resource specification not available", tplModelArtsTrainJobVersionNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
trainJobNewVersionDataPrepare(ctx)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsTrainJobVersionNew, &form)
return
}

//todo: del the codeLocalPath
_, err = ioutil.ReadDir(codeLocalPath)
if err == nil {
@@ -2093,17 +2133,38 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference
return
}

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeInference), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {
inferenceJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_samejob_err"), tplModelArtsInferenceJobNew, &form)
ctx.RenderWithErr("Resource specification not available", tplModelArtsInferenceJobNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
inferenceJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsInferenceJobNew, &form)
return
}
defer lock.UnLock()

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeInference))
lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeInference)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
inferenceJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr(ctx.Tr(errMsg), tplModelArtsInferenceJobNew, &form)
return
}

count, err := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeInference))

if err != nil {
log.Error("GetCloudbrainInferenceJobCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -2152,23 +2213,6 @@ func InferenceJobCreate(ctx *context.Context, form auth.CreateModelArtsInference
}
}

spec, err := resource.GetAndCheckSpec(ctx.User.ID, form.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {
inferenceJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr("Resource specification not available", tplModelArtsInferenceJobNew, &form)
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
inferenceJobErrorNewDataPrepare(ctx, form)
ctx.RenderWithErr(ctx.Tr("points.insufficient_points_balance"), tplModelArtsInferenceJobNew, &form)
return
}

//todo: del the codeLocalPath
_, err = ioutil.ReadDir(codeLocalPath)
if err == nil {
@@ -2513,7 +2557,7 @@ func inferenceJobNewDataPrepare(ctx *context.Context) error {
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeInference))
NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeInference))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount

return nil
@@ -2593,7 +2637,8 @@ func inferenceJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModel
ctx.Data["datasetType"] = models.TypeCloudBrainTwo
waitCount := cloudbrain.GetWaitingCloudbrainCount(models.TypeCloudBrainTwo, "")
ctx.Data["WaitCount"] = waitCount

NotStopTaskCount, _ := cloudbrainTask.GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeInference))
ctx.Data["NotStopTaskCount"] = NotStopTaskCount
return nil
}
func InferenceJobShow(ctx *context.Context) {
@@ -2673,6 +2718,8 @@ func MultiModelDownload(ctx *context.Context) {

if task.ComputeResource == models.NPUResource {
path := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, task.JobName, setting.OutPutPath, versionName, parentDir), "/")
path = strings.TrimSuffix(path, "/")
path += "/"
allFile, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, path)
if err == nil {
returnFileName := task.DisplayJobName + ".zip"
@@ -2874,15 +2921,19 @@ func TrainJobDownloadLogFile(ctx *context.Context) {
ctx.ServerError("GetObsLogFileName", err)
return
}

url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, key)
if err != nil {
log.Error("GetObsCreateSignedUrlByBucketAndKey failed: %v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetObsCreateSignedUrlByBucketAndKey", err)
return
if len(key) > 1 {
ObsDownloadManyFile(prefix[0:len(prefix)-3], ctx, task.DisplayJobName+".zip", key)
} else {
url, err := storage.GetObsCreateSignedUrlByBucketAndKey(setting.Bucket, key[0].ParenDir+key[0].FileName)
if err != nil {
log.Error("GetObsCreateSignedUrlByBucketAndKey failed: %v", err.Error(), ctx.Data["msgID"])
ctx.ServerError("GetObsCreateSignedUrlByBucketAndKey", err)
return
}
ctx.Resp.Header().Set("Cache-Control", "max-age=0")
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect)
}
ctx.Resp.Header().Set("Cache-Control", "max-age=0")
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusTemporaryRedirect)

}
func getDatasUrlListByUUIDS(uuidStr string) ([]models.Datasurl, string, string, bool, error) {
var isMultiDataset bool


+ 24
- 20
routers/routes/routes.go View File

@@ -359,6 +359,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/all/dosearch/", routers.SearchApi)
m.Post("/user/login/kanban", user.SignInPostAPI)
m.Get("/home/term", routers.HomeTerm)
m.Get("/home/annual_privacy", routers.HomeAnnual)
m.Get("/home/notice", routers.HomeNoticeTmpl)
m.Get("/home/privacy", routers.HomePrivacy)
m.Get("/extension/tuomin/upload", modelapp.ProcessImageUI)
@@ -1005,6 +1006,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/title", repo.UpdateIssueTitle)
m.Post("/content", repo.UpdateIssueContent)
m.Post("/watch", repo.IssueWatch)
m.Post("/setstaytop", repo.SetIssueStayTop)
m.Group("/dependency", func() {
m.Post("/add", repo.AddDependency)
m.Post("/delete", repo.RemoveDependency)
@@ -1189,7 +1191,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDownloadMultiModel)
})
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.CloudBrainNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), context.PointAccount(), repo.CloudBrainCreate)

m.Group("/benchmark", func() {
m.Get("", reqRepoCloudBrainReader, repo.CloudBrainBenchmarkIndex)
@@ -1200,7 +1202,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate)
})
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.CloudBrainBenchmarkNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainBenchmarkCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), context.PointAccount(), repo.CloudBrainBenchmarkCreate)
m.Get("/get_child_types", repo.GetChildTypes)
})

@@ -1210,24 +1212,24 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainTrainJobDel)
//m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels)
m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainDownloadModel)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDownloadMultiModel)
m.Get("/download_multi_model", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.CloudBrainDownloadMultiModel)
//m.Get("/get_log", cloudbrain.AdminOrJobCreaterRightForTrain, repo.GetLogFromModelDir)
//m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.CloudBrainTrainJobVersionNew)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainTrainJobVersionCreate)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, context.PointAccount(), repo.CloudBrainTrainJobVersionNew)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateCloudBrainForm{}), context.PointAccount(), repo.CloudBrainTrainJobVersionCreate)
})
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.CloudBrainTrainJobNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), context.PointAccount(), repo.CloudBrainCreate)
})
m.Group("/inference-job", func() {
m.Group("/:jobid", func() {
m.Get("", reqRepoCloudBrainReader, repo.InferenceCloudBrainJobShow)
m.Get("/result_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.CloudBrainDownloadInferenceResult)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDownloadMultiModel)
m.Get("/downloadall", repo.DownloadInferenceResultFile)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRightForTrain, repo.CloudBrainDownloadMultiModel)
m.Get("/downloadall", cloudbrain.AdminOrJobCreaterRightForTrain, repo.DownloadGPUInferenceResultFile)
})
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.InferenceCloudBrainJobNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainInferencForm{}), repo.CloudBrainInferenceJobCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainInferencForm{}), context.PointAccount(), repo.CloudBrainInferenceJobCreate)
})
}, context.RepoRef())
m.Group("/grampus", func() {
@@ -1241,7 +1243,7 @@ func RegisterRoutes(m *macaron.Macaron) {
})

m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.GrampusNotebookNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateGrampusNotebookForm{}), repo.GrampusNotebookCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateGrampusNotebookForm{}), context.PointAccount(), repo.GrampusNotebookCreate)
})

m.Group("/train-job", func() {
@@ -1250,16 +1252,17 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusStopJob)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.GrampusTrainJobDel)
m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, repo.GrampusTrainJobVersionNew)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateGrampusTrainJobForm{}), repo.GrampusTrainJobVersionCreate)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, context.PointAccount(), repo.GrampusTrainJobVersionNew)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateGrampusTrainJobForm{}), context.PointAccount(), repo.GrampusTrainJobVersionCreate)
})
m.Group("/gpu", func() {
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.GrampusTrainJobGPUNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateGrampusTrainJobForm{}), repo.GrampusTrainJobGpuCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateGrampusTrainJobForm{}), context.PointAccount(), repo.GrampusTrainJobGpuCreate)
})
m.Group("/npu", func() {
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.GrampusTrainJobNPUNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateGrampusTrainJobForm{}), repo.GrampusTrainJobNpuCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateGrampusTrainJobForm{}), context.PointAccount(), repo.GrampusTrainJobNpuCreate)
})
})
}, context.RepoRef())
@@ -1308,7 +1311,7 @@ func RegisterRoutes(m *macaron.Macaron) {
})
m.Get("/create_gpu", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.AiSafetyCreateForGetGPU)
m.Get("/create_npu", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.AiSafetyCreateForGetNPU)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, repo.AiSafetyCreateForPost)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.AiSafetyCreateForPost)
}, context.RepoRef())

m.Group("/debugjob", func() {
@@ -1325,7 +1328,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel)
})
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.NotebookNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsNotebookForm{}), repo.Notebook2Create)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsNotebookForm{}), context.PointAccount(), repo.Notebook2Create)
})

m.Group("/train-job", func() {
@@ -1335,12 +1338,13 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobStop)
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRightForTrain, repo.TrainJobDel)
m.Get("/model_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ModelDownload)
m.Get("/download_multi_model", cloudbrain.AdminOrJobCreaterRightForTrain, repo.MultiModelDownload)
m.Get("/download_log_file", cloudbrain.AdminOrJobCreaterRightForTrain, repo.TrainJobDownloadLogFile)
m.Get("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, context.PointAccount(), repo.TrainJobNewVersion)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion)
m.Post("/create_version", reqWechatBind, cloudbrain.AdminOrJobCreaterRightForTrain, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), context.PointAccount(), repo.TrainJobCreateVersion)
})
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.TrainJobNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), context.PointAccount(), repo.TrainJobCreate)

m.Get("/para-config-list", reqRepoCloudBrainReader, repo.TrainJobGetConfigList)
})
@@ -1350,10 +1354,10 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/:jobid", func() {
m.Get("", reqRepoCloudBrainReader, repo.InferenceJobShow)
m.Get("/result_download", cloudbrain.AdminOrJobCreaterRightForTrain, repo.ResultDownload)
m.Get("/downloadall", repo.DownloadMultiResultFile)
m.Get("/downloadall", cloudbrain.AdminOrJobCreaterRightForTrain, repo.DownloadMultiResultFile)
})
m.Get("/create", reqWechatBind, reqRepoCloudBrainWriter, context.PointAccount(), repo.InferenceJobNew)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsInferenceJobForm{}), repo.InferenceJobCreate)
m.Post("/create", reqWechatBind, reqRepoCloudBrainWriter, bindIgnErr(auth.CreateModelArtsInferenceJobForm{}), context.PointAccount(), repo.InferenceJobCreate)
})
}, context.RepoRef())



+ 14
- 7
routers/user/auth.go View File

@@ -36,6 +36,7 @@ import (
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/externalaccount"
"code.gitea.io/gitea/services/mailer"
"code.gitea.io/gitea/services/repository"

"gitea.com/macaron/captcha"
"github.com/markbates/goth"
@@ -120,7 +121,6 @@ func checkAutoLogin(ctx *context.Context) bool {
ctx.ServerError("AutoSignIn", err)
return true
}

redirectTo := ctx.Query("redirect_to")
if len(redirectTo) > 0 {
ctx.SetCookie("redirect_to", redirectTo, 0, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
@@ -129,7 +129,6 @@ func checkAutoLogin(ctx *context.Context) bool {
}

if isSucceed {

isCourse := ctx.QueryBool("course")
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true)
if redirectTo == "" && isCourse {
@@ -137,7 +136,6 @@ func checkAutoLogin(ctx *context.Context) bool {
ctx.RedirectToFirst(redirectToCourse)
} else {
ctx.RedirectToFirst(redirectTo, setting.AppSubURL+string(setting.LandingPageURL))

}
return true
}
@@ -145,10 +143,14 @@ func checkAutoLogin(ctx *context.Context) bool {
return false
}

func getActivityTpl() string {
result, _ := repository.RecommendContentFromPromote(setting.RecommentRepoAddr + "/signin/activity_tpl")
return result
}

// SignIn render sign in page
func SignIn(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("sign_in")

// Check auto-login.
if checkAutoLogin(ctx) {
return
@@ -168,6 +170,7 @@ func SignIn(ctx *context.Context) {
ctx.Data["PageIsLogin"] = true
ctx.Data["EnableSSPI"] = models.IsSSPIEnabled()
ctx.Data["EnableCloudBrain"] = true
ctx.Data["ActivityTpl"] = getActivityTpl()

ctx.HTML(200, tplSignIn)
}
@@ -185,6 +188,7 @@ func SignInCloudBrain(ctx *context.Context) {
ctx.Data["PageIsSignIn"] = true
ctx.Data["PageIsCloudBrainLogin"] = true
ctx.Data["EnableCloudBrain"] = true
ctx.Data["ActivityTpl"] = getActivityTpl()

ctx.HTML(200, tplSignInCloudBrain)
}
@@ -197,6 +201,7 @@ func SignInPhone(ctx *context.Context) {
}

ctx.Data["PageIsPhoneLogin"] = true
ctx.Data["ActivityTpl"] = getActivityTpl()

ctx.HTML(200, tplSignInPhone)
}
@@ -206,6 +211,7 @@ func SignInPhonePost(ctx *context.Context, form auth.PhoneNumberCodeForm) {
ctx.Data["PageIsPhoneLogin"] = true
ctx.Data["IsCourse"] = ctx.QueryBool("course")
ctx.Data["EnableCloudBrain"] = true
ctx.Data["ActivityTpl"] = getActivityTpl()

if ctx.HasError() {
ctx.HTML(200, tplSignInPhone)
@@ -270,7 +276,6 @@ func SignInPostAPI(ctx *context.Context) {

func SignInPostCommon(ctx *context.Context, form auth.SignInForm) {
ctx.Data["Title"] = ctx.Tr("sign_in")

orderedOAuth2Names, oauth2Providers, err := models.GetActiveOAuth2Providers()
if err != nil {
ctx.ServerError("UserSignIn", err)
@@ -285,7 +290,6 @@ func SignInPostCommon(ctx *context.Context, form auth.SignInForm) {
ctx.Data["IsCourse"] = ctx.QueryBool("course")
ctx.Data["EnableSSPI"] = models.IsSSPIEnabled()
ctx.Data["EnableCloudBrain"] = true

if ctx.HasError() {
ctx.HTML(200, tplSignIn)
return
@@ -356,6 +360,7 @@ func SignInPostCommon(ctx *context.Context, form auth.SignInForm) {
func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) {
ctx.Data["PageIsCloudBrainLogin"] = true
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login/cloud_brain"
ctx.Data["ActivityTpl"] = getActivityTpl()
SignInPostCommon(ctx, form)
}

@@ -363,6 +368,7 @@ func SignInCloudBrainPost(ctx *context.Context, form auth.SignInForm) {
func SignInPost(ctx *context.Context, form auth.SignInForm) {
ctx.Data["PageIsLogin"] = true
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
ctx.Data["ActivityTpl"] = getActivityTpl()
SignInPostCommon(ctx, form)
}

@@ -757,7 +763,6 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR
}
return redirectTo
}

if obeyRedirect {
ctx.Redirect(setting.AppSubURL + "/dashboard")
}
@@ -1257,6 +1262,7 @@ func SignUp(ctx *context.Context) {

//Show Disabled Registration message if DisableRegistration or AllowOnlyExternalRegistration options are true
ctx.Data["DisableRegistration"] = setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration
ctx.Data["ActivityTpl"] = getActivityTpl()

ctx.HTML(200, tplSignUp)
}
@@ -1272,6 +1278,7 @@ func SignUpPost(ctx *context.Context, cpt *captcha.Captcha, form auth.RegisterFo
ctx.Data["CaptchaType"] = setting.Service.CaptchaType
ctx.Data["RecaptchaSitekey"] = setting.Service.RecaptchaSitekey
ctx.Data["PageIsSignUp"] = true
ctx.Data["ActivityTpl"] = getActivityTpl()

//Permission denied if DisableRegistration or AllowOnlyExternalRegistration options are true
if setting.Service.DisableRegistration || setting.Service.AllowOnlyExternalRegistration {


+ 1
- 1
routers/user/home.go View File

@@ -779,7 +779,7 @@ func Cloudbrains(ctx *context.Context) {
var jobTypes []string
jobTypeNot := false
if jobType == string(models.JobTypeBenchmark) {
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet))
jobTypes = append(jobTypes, string(models.JobTypeBenchmark), string(models.JobTypeModelSafety), string(models.JobTypeBrainScore), string(models.JobTypeSnn4imagenet), string(models.JobTypeSnn4Ecoset))
} else if jobType != "all" && jobType != "" {
jobTypes = append(jobTypes, jobType)
}


+ 14
- 14
services/cloudbrain/clear.go View File

@@ -14,21 +14,21 @@ import (

func ClearCloudbrainResultSpace() {
log.Info("clear cloudbrain one result space begin.")
if !setting.ClearStrategy.Enabled{
if !setting.ClearStrategy.Enabled {
return
}

tasks, err := models.GetCloudBrainOneStoppedNotDebugJobDaysAgo(setting.ClearStrategy.ResultSaveDays, setting.ClearStrategy.BatchSize)
tasks, err := models.GetGPUStoppedNotDebugJobDaysAgo(setting.ClearStrategy.ResultSaveDays, setting.ClearStrategy.BatchSize)
if err != nil {
log.Warn("Failed to get cloudbrain, clear result failed.", err)
return
}
debugTasks, err := models.GetCloudBrainOneStoppedDebugJobDaysAgo(setting.ClearStrategy.ResultSaveDays, setting.ClearStrategy.DebugJobSize)
debugTasks, err := models.GetGPUStoppedDebugJobDaysAgo(setting.ClearStrategy.ResultSaveDays, setting.ClearStrategy.DebugJobSize)
if err != nil {
log.Warn("Failed to get debug cloudbrain.", err)

}
tasks=append(tasks,debugTasks...)
tasks = append(tasks, debugTasks...)

if err != nil {
log.Warn("Failed to get cloudbrain, clear result failed.", err)
@@ -38,7 +38,7 @@ func ClearCloudbrainResultSpace() {
for _, task := range tasks {
err := DeleteCloudbrainOneJobStorage(task.JobName)
if err == nil {
log.Info("clear job in cloudbrain table:"+task.JobName)
log.Info("clear job in cloudbrain table:" + task.JobName)
ids = append(ids, task.ID)
}
}
@@ -69,10 +69,10 @@ func clearMinioHistoryTrashFile() {
SortModTimeAscend(miniofiles)
for _, file := range miniofiles {

if file.Name()!="" && file.ModTime().Before(time.Now().AddDate(0, 0, -setting.ClearStrategy.TrashSaveDays)) {
if file.Name() != "" && file.ModTime().Before(time.Now().AddDate(0, 0, -setting.ClearStrategy.TrashSaveDays)) {

has,err:=models.IsCloudbrainExistByJobName(file.Name())
if err==nil && !has {
has, err := models.IsCloudbrainExistByJobName(file.Name())
if err == nil && !has {
dirPath := setting.CBCodePathPrefix + file.Name() + "/"
log.Info("clear job in minio trash:" + file.Name())
storage.Attachments.DeleteDir(dirPath)
@@ -90,7 +90,7 @@ func clearMinioHistoryTrashFile() {
}
}

func clearLocalHistoryTrashFile() {
func clearLocalHistoryTrashFile() {
files, err := ioutil.ReadDir(setting.JobPath)
processCount := 0
if err != nil {
@@ -99,11 +99,11 @@ func clearLocalHistoryTrashFile() {
SortModTimeAscend(files)
for _, file := range files {
//清理n天前的历史垃圾数据,清理job目录
if file.Name()!="" && file.ModTime().Before(time.Now().AddDate(0, 0, -setting.ClearStrategy.TrashSaveDays)) {
has,err:=models.IsCloudbrainExistByJobName(file.Name())
if err==nil && !has{
if file.Name() != "" && file.ModTime().Before(time.Now().AddDate(0, 0, -setting.ClearStrategy.TrashSaveDays)) {
has, err := models.IsCloudbrainExistByJobName(file.Name())
if err == nil && !has {
os.RemoveAll(setting.JobPath + file.Name())
log.Info("clear job in local trash:"+file.Name())
log.Info("clear job in local trash:" + file.Name())
processCount++
}
if processCount == setting.ClearStrategy.BatchSize {
@@ -127,7 +127,7 @@ func SortModTimeAscend(files []os.FileInfo) {

func DeleteCloudbrainOneJobStorage(jobName string) error {

if jobName==""{
if jobName == "" {
return nil
}
//delete local


+ 30
- 0
services/cloudbrain/cloudbrainTask/ai_model.go View File

@@ -0,0 +1,30 @@
package cloudbrainTask

import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
)

func IsModelFileExists(model *models.AiModelManage, fileName string) bool {
if model.Type == models.TypeCloudBrainTwo {
key := models.AIModelPath + models.AttachmentRelativePath(model.ID) + "/" + fileName
log.Info("IsModelFileExists TypeCloudBrainTwo key=%s", key)
isExist, err := storage.IsObjectExist4Obs(setting.Bucket, key)
if err != nil {
return false
}
return isExist
} else if model.Type == models.TypeCloudBrainOne {
prefix := models.AIModelPath + models.AttachmentRelativePath(model.ID) + "/"
objectName := prefix + fileName
log.Info("IsModelFileExists TypeCloudBrainOne objectName=%s", objectName)
isExist, err := storage.IsObjectExist4Minio(setting.Attachment.Minio.Bucket, objectName)
if err != nil {
return false
}
return isExist
}
return false
}

+ 21
- 18
services/cloudbrain/cloudbrainTask/count.go View File

@@ -1,7 +1,6 @@
package cloudbrainTask

import (
"fmt"
"strconv"

"code.gitea.io/gitea/models"
@@ -16,7 +15,7 @@ type StatusInfo struct {

var CloudbrainOneNotFinalStatuses = []string{string(models.JobWaiting), string(models.JobRunning)}
var CloudbrainTwoNotFinalStatuses = []string{string(models.ModelArtsTrainJobInit), string(models.ModelArtsTrainJobImageCreating), string(models.ModelArtsTrainJobSubmitTrying), string(models.ModelArtsTrainJobWaiting), string(models.ModelArtsTrainJobRunning), string(models.ModelArtsTrainJobScaling), string(models.ModelArtsTrainJobCheckInit), string(models.ModelArtsTrainJobCheckRunning), string(models.ModelArtsTrainJobCheckRunningCompleted)}
var GrampusNotFinalStatuses = []string{models.GrampusStatusWaiting, models.GrampusStatusRunning}
var GrampusNotFinalStatuses = []string{models.GrampusStatusWaiting, models.GrampusStatusRunning, models.GrampusStatusPending}
var StatusInfoDict = map[string]StatusInfo{string(models.JobTypeDebug) + "-" + strconv.Itoa(models.TypeCloudBrainOne): {
CloudBrainTypes: []int{models.TypeCloudBrainOne},
JobType: []models.JobType{models.JobTypeDebug},
@@ -34,7 +33,7 @@ var StatusInfoDict = map[string]StatusInfo{string(models.JobTypeDebug) + "-" + s
ComputeResource: models.GPUResource,
}, string(models.JobTypeBenchmark) + "-" + strconv.Itoa(models.TypeCloudBrainOne): {
CloudBrainTypes: []int{models.TypeCloudBrainOne},
JobType: []models.JobType{models.JobTypeBenchmark, models.JobTypeBrainScore, models.JobTypeSnn4imagenet},
JobType: []models.JobType{models.JobTypeBenchmark, models.JobTypeBrainScore, models.JobTypeSnn4imagenet, models.JobTypeSnn4Ecoset},
NotFinalStatuses: CloudbrainOneNotFinalStatuses,
ComputeResource: models.GPUResource,
}, string(models.JobTypeDebug) + "-" + strconv.Itoa(models.TypeCloudBrainTwo): {
@@ -72,25 +71,29 @@ var StatusInfoDict = map[string]StatusInfo{string(models.JobTypeDebug) + "-" + s
JobType: []models.JobType{models.JobTypeDebug},
NotFinalStatuses: GrampusNotFinalStatuses,
ComputeResource: models.NPUResource,
}, string(models.JobTypeDebug) + "-" + strconv.Itoa(models.TypeC2Net) + "-" + models.GCUResource: {
CloudBrainTypes: []int{models.TypeC2Net},
JobType: []models.JobType{models.JobTypeDebug},
NotFinalStatuses: GrampusNotFinalStatuses,
ComputeResource: models.GCUResource,
}}

func GetNotFinalStatusTaskCount(uid int64, cloudbrainType int, jobType string, computeResource ...string) (int, error) {
jobNewType := jobType
if jobType == string(models.JobTypeSnn4imagenet) || jobType == string(models.JobTypeBrainScore) {
jobNewType = string(models.JobTypeBenchmark)
}
var alleNotFinalStatuses = []string{string(models.JobWaiting), string(models.JobRunning), string(models.ModelArtsTrainJobInit), string(models.ModelArtsTrainJobImageCreating), string(models.ModelArtsTrainJobSubmitTrying), string(models.ModelArtsTrainJobWaiting), string(models.ModelArtsTrainJobRunning), string(models.ModelArtsTrainJobScaling), string(models.ModelArtsTrainJobCheckInit), string(models.ModelArtsTrainJobCheckRunning), string(models.ModelArtsTrainJobCheckRunningCompleted), models.GrampusStatusWaiting, models.GrampusStatusRunning, models.GrampusStatusPending,
string(models.ModelArtsCreateQueue),
string(models.ModelArtsCreating),
string(models.ModelArtsStartQueuing),
string(models.ModelArtsReadyToStart),
string(models.ModelArtsStarting),
string(models.ModelArtsRestarting),
string(models.ModelArtsRunning),
}

key := jobNewType + "-" + strconv.Itoa(cloudbrainType)
if len(computeResource) > 0 && cloudbrainType == models.TypeC2Net {
key = key + "-" + computeResource[0]
func GetNotFinalStatusTaskCount(uid int64, jobType string) (int, error) {
jobNewType := []models.JobType{models.JobType(jobType)}
if models.IsModelBenchMarkJobType(jobType) {
jobNewType = models.AllBenchMarkJobTYpe()
}

if statusInfo, ok := StatusInfoDict[key]; ok {

return models.GetNotFinalStatusTaskCount(uid, statusInfo.NotFinalStatuses, statusInfo.JobType, statusInfo.CloudBrainTypes, statusInfo.ComputeResource)

} else {
return 0, fmt.Errorf("Can not find the status info.")
}
return models.GetNotFinalStatusTaskCount(uid, alleNotFinalStatuses, jobNewType)

}

+ 54
- 47
services/cloudbrain/cloudbrainTask/inference.go View File

@@ -2,9 +2,10 @@ package cloudbrainTask

import (
"bufio"
cloudbrainService "code.gitea.io/gitea/services/cloudbrain"
"code.gitea.io/gitea/services/lock"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
@@ -24,8 +25,6 @@ import (
"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/util"
@@ -48,13 +47,32 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, option api.CreateTrainJo
labelName := option.LabelName
repo := ctx.Repo.Repository

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
defer lock.UnLock()
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, option.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("Resource specification is not available"))
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: jobType}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr(errMsg)))
return
}

@@ -96,7 +114,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, option api.CreateTrainJo
return
}

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
count, err := GetNotFinalStatusTaskCount(ctx.User.ID, jobType)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error"))
@@ -128,21 +146,7 @@ func CloudBrainInferenceJobCreate(ctx *context.Context, option api.CreateTrainJo
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.error.dataset_select")))
return
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, option.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("Resource specification is not available"))
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}
req := cloudbrain.GenerateCloudBrainTaskReq{
Ctx: ctx,
DisplayJobName: displayJobName,
@@ -216,17 +220,36 @@ func ModelArtsInferenceJobCreate(ctx *context.Context, option api.CreateTrainJob
return
}

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeInference), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
spec, err := resource.GetAndCheckSpec(ctx.User.ID, option.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("Resource specification not available"))
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: ctx.Repo.Repository, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeInference)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr(errMsg)))
return
}
defer lock.UnLock()

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeInference))
count, err := GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeInference))
if err != nil {
log.Error("GetCloudbrainInferenceJobCountByUserID failed:%v", err, ctx.Data["MsgID"])

@@ -273,22 +296,6 @@ func ModelArtsInferenceJobCreate(ctx *context.Context, option api.CreateTrainJob
}
}

spec, err := resource.GetAndCheckSpec(ctx.User.ID, option.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeInference,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainTwo})
if err != nil || spec == nil {

ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("Resource specification not available"))
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}

//todo: del the codeLocalPath
_, err = ioutil.ReadDir(codeLocalPath)
if err == nil {


+ 99
- 61
services/cloudbrain/cloudbrainTask/notebook.go View File

@@ -1,6 +1,7 @@
package cloudbrainTask

import (
"code.gitea.io/gitea/services/lock"
"fmt"
"net/http"
"path"
@@ -15,8 +16,6 @@ import (

"code.gitea.io/gitea/modules/cloudbrain"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/services/cloudbrain/resource"
"code.gitea.io/gitea/services/reward/point/account"
@@ -35,6 +34,7 @@ const NoteBookExtension = ".ipynb"
const CPUType = 0
const GPUType = 1
const NPUType = 2
const CharacterLength = 2550

func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption) {

@@ -46,6 +46,14 @@ func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOp
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_select_wrong")))
return
}
if len(getBootFile(option.File, option.OwnerName, option.ProjectName)) > CharacterLength {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_path_too_long")))
return
}
if len(option.BranchName) > CharacterLength {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_branch_name_too_long")))
return
}

isNotebookFileExist, _ := isNoteBookFileExist(ctx, option)
if !isNotebookFileExist {
@@ -105,14 +113,29 @@ func FileNotebookCreate(ctx *context.Context, option api.CreateFileNotebookJobOp
err = downloadCode(sourceRepo, getCodePath(noteBook.JobName, sourceRepo), option.BranchName)
if err != nil {
log.Error("download code failed", err)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
return
if !strings.Contains(err.Error(), "already exists and is not an empty directory") {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.load_code_failed")))
return
}
}
}
if !isRepoFileMatch(option, noteBook) {
noteBook.BootFile += ";" + getBootFile(option.File, option.OwnerName, option.ProjectName)
noteBook.BranchName += ";" + option.BranchName
noteBook.Description += ";" + getDescription(option)
if len(noteBook.BootFile)+len(getBootFile(option.File, option.OwnerName, option.ProjectName))+1 <= CharacterLength {
noteBook.BootFile += ";" + getBootFile(option.File, option.OwnerName, option.ProjectName)
} else {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_path_too_long")))
return
}
if len(noteBook.BranchName)+len(option.BranchName)+1 <= CharacterLength {
noteBook.BranchName += ";" + option.BranchName
} else {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.notebook_branch_name_too_long")))
return
}

if len(noteBook.Description)+len(getDescription(option))+1 <= CharacterLength {
noteBook.Description += ";" + getDescription(option)
}

err := models.UpdateJob(noteBook)
if err != nil {
@@ -308,12 +331,36 @@ func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNot
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)
jobType := string(models.JobTypeDebug)

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), jobType, displayJobName))
defer lock.UnLock()
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
specId := setting.FileNoteBook.SpecIdGPU
if option.Type == 0 {
specId = setting.FileNoteBook.SpecIdCPU
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobType(jobType),
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}

lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: repo, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: jobType}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr(errMsg)))
return
}

@@ -332,7 +379,7 @@ func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNot
}
}

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainOne, jobType)
count, err := GetNotFinalStatusTaskCount(ctx.User.ID, jobType)
if err != nil {
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi("system error."))
@@ -355,25 +402,7 @@ func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNot
return
}
command := cloudbrain.GetCloudbrainDebugCommand()
specId := setting.FileNoteBook.SpecIdGPU
if option.Type == 0 {
specId = setting.FileNoteBook.SpecIdCPU
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobType(jobType),
ComputeResource: models.GPU,
Cluster: models.OpenICluster,
AiCenterCode: models.AICenterOfCloudBrainOne})
if err != nil || spec == nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
return
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}
ctx.Repo = &context.Repository{
Repository: repo,
}
@@ -417,7 +446,7 @@ func cloudBrainFileNoteBookCreate(ctx *context.Context, option api.CreateFileNot
}

func getCloudbrainType(optionType int) int {
if optionType < 1 {
if optionType <= GPUType {
return models.TypeCloudBrainOne
}
if setting.ModelartsCD.Enabled {
@@ -431,23 +460,52 @@ func getCodePath(jobName string, repo *models.Repository) string {
}

func getDescription(option api.CreateFileNotebookJobOption) string {
return option.OwnerName + "/" + option.ProjectName + "/" + option.File
des := option.OwnerName + "/" + option.ProjectName + "/" + option.File
if len(des) <= CharacterLength {
return des
}
return ""
}

func modelartsFileNoteBookCreate(ctx *context.Context, option api.CreateFileNotebookJobOption, repo *models.Repository, sourceRepo *models.Repository) {
displayJobName := cloudbrainService.GetDisplayJobName(ctx.User.Name)
jobName := util.ConvertDisplayJobNameToJobName(displayJobName)

lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(repo.ID), string(models.JobTypeDebug), displayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("repo.cloudbrain_samejob_err")))
var aiCenterCode = models.AICenterOfCloudBrainTwo
var specId = setting.FileNoteBook.SpecIdNPU
if setting.ModelartsCD.Enabled {
aiCenterCode = models.AICenterOfChengdu
specId = setting.FileNoteBook.SpecIdNPUCD
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobTypeDebug,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: aiCenterCode})
if err != nil || spec == nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}
defer lock.UnLock()

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, models.TypeCloudBrainTwo, string(models.JobTypeDebug))
lockOperator, errMsg := cloudbrainService.Lock4CloudbrainCreation(&lock.LockContext{Repo: repo, Task: &models.Cloudbrain{DisplayJobName: displayJobName, JobType: string(models.JobTypeDebug)}, User: ctx.User})
defer func() {
if lockOperator != nil {
lockOperator.Unlock()
}
}()

if errMsg != "" {
log.Error("lock processed failed:%s", errMsg, ctx.Data["MsgID"])
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr(errMsg)))
return
}

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeDebug))

if err != nil {
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"])
@@ -486,26 +544,6 @@ func modelartsFileNoteBookCreate(ctx *context.Context, option api.CreateFileNote
return
}

var aiCenterCode = models.AICenterOfCloudBrainTwo
var specId = setting.FileNoteBook.SpecIdNPU
if setting.ModelartsCD.Enabled {
aiCenterCode = models.AICenterOfChengdu
specId = setting.FileNoteBook.SpecIdNPUCD
}
spec, err := resource.GetAndCheckSpec(ctx.User.ID, specId, models.FindSpecsOptions{
JobType: models.JobTypeDebug,
ComputeResource: models.NPU,
Cluster: models.OpenICluster,
AiCenterCode: aiCenterCode})
if err != nil || spec == nil {
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("cloudbrain.wrong_specification")))
return
}
if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d ", ctx.User.ID, spec.ID)
ctx.JSON(http.StatusOK, models.BaseErrorMessageApi(ctx.Tr("points.insufficient_points_balance")))
return
}
ctx.Repo = &context.Repository{
Repository: repo,
}


+ 33
- 44
services/cloudbrain/cloudbrainTask/train.go View File

@@ -435,6 +435,38 @@ func GrampusTrainJobGpuCreate(ctx *context.Context, option api.CreateTrainJobOpt
}

func checkParameters(ctx *context.Context, option api.CreateTrainJobOption, lock *redis_lock.DistributeLock, repo *models.Repository) (*models.Specification, map[string]models.DatasetInfo, string, error) {
//check specification
computeType := models.GPU

if isNpuTask(option) {
computeType = models.NPU
}
cluster := models.OpenICluster
if isC2NetTask(option) {
cluster = models.C2NetCluster
}
aiCenterCode := ""
if option.Type == TaskTypeCloudbrainOne {
aiCenterCode = models.AICenterOfCloudBrainOne
} else if option.Type == TaskTypeModelArts {
aiCenterCode = models.AICenterOfCloudBrainTwo
}

spec, err := resource.GetAndCheckSpec(ctx.User.ID, option.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: computeType,
Cluster: cluster,
AiCenterCode: aiCenterCode,
})
if err != nil || spec == nil {
return nil, nil, "", fmt.Errorf("Resource specification is not available.")
}

if !account.IsPointBalanceEnough(ctx.User.ID, models.PointDeductCondition{SpecUnitPrice: spec.UnitPrice}) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
return nil, nil, "", fmt.Errorf(ctx.Tr("points.insufficient_points_balance"))
}

isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("lock processed failed:%v", err, ctx.Data["MsgID"])
@@ -452,18 +484,7 @@ func checkParameters(ctx *context.Context, option api.CreateTrainJobOption, lock
return nil, nil, "", fmt.Errorf(ctx.Tr("repo.cloudbrain_bootfile_err"))
}

computeResource := models.GPUResource
if isNpuTask(option) {
computeResource = models.NPUResource
}

//check count limit
taskType := option.Type
if isC2NetTask(option) {
taskType = 2
}

count, err := GetNotFinalStatusTaskCount(ctx.User.ID, taskType, string(models.JobTypeTrain), computeResource)
count, err := GetNotFinalStatusTaskCount(ctx.User.ID, string(models.JobTypeTrain))
if err != nil {
log.Error("GetCountByUserID failed:%v", err, ctx.Data["MsgID"])
return nil, nil, "", fmt.Errorf("system error")
@@ -494,38 +515,6 @@ func checkParameters(ctx *context.Context, option api.CreateTrainJobOption, lock
}
}

//check specification
computeType := models.GPU

if isNpuTask(option) {
computeType = models.NPU
}
cluster := models.OpenICluster
if isC2NetTask(option) {
cluster = models.C2NetCluster
}
aiCenterCode := ""
if option.Type == TaskTypeCloudbrainOne {
aiCenterCode = models.AICenterOfCloudBrainOne
} else if option.Type == TaskTypeModelArts {
aiCenterCode = models.AICenterOfCloudBrainTwo
}

spec, err := resource.GetAndCheckSpec(ctx.User.ID, option.SpecId, models.FindSpecsOptions{
JobType: models.JobTypeTrain,
ComputeResource: computeType,
Cluster: cluster,
AiCenterCode: aiCenterCode,
})
if err != nil || spec == nil {
return nil, nil, "", fmt.Errorf("Resource specification is not available.")
}

if !account.IsPointBalanceEnough(ctx.User.ID, spec.UnitPrice) {
log.Error("point balance is not enough,userId=%d specId=%d", ctx.User.ID, spec.ID)
return nil, nil, "", fmt.Errorf(ctx.Tr("points.insufficient_points_balance"))
}

//check dataset
var datasetInfos map[string]models.DatasetInfo
var datasetNames string


+ 20
- 0
services/cloudbrain/lock.go View File

@@ -0,0 +1,20 @@
package cloudbrain

import "code.gitea.io/gitea/services/lock"

func Lock4CloudbrainCreation(ctx *lock.LockContext) (*lock.LockChainOperator, string) {
op := lock.NewLockChainOperator(ctx).Add(lock.CloudbrainUniquenessLock{}).Add(lock.CloudbrainDisplayJobNameLock{})
errCode := op.Lock()
if errCode != "" {
return nil, errCode
}
return op, ""
}
func Lock4CloudbrainRestart(ctx *lock.LockContext) (*lock.LockChainOperator, string) {
op := lock.NewLockChainOperator(ctx).Add(lock.CloudbrainUniquenessLock{})
errCode := op.Lock()
if errCode != "" {
return nil, errCode
}
return op, ""
}

+ 31
- 0
services/lock/cloudbrain_name_lock.go View File

@@ -0,0 +1,31 @@
package lock

import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"fmt"
)

type CloudbrainDisplayJobNameLock struct {
}

func (c CloudbrainDisplayJobNameLock) IsMatch(ctx *LockContext) bool {
return true
}

func (c CloudbrainDisplayJobNameLock) Lock(ctx *LockContext) string {
lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(ctx.Repo.ID), ctx.Task.JobType, ctx.Task.DisplayJobName))
isOk, err := lock.Lock(models.CloudbrainKeyDuration)
if !isOk {
log.Error("CloudbrainDisplayJobNameLock lock failed:%v", err)
return "repo.cloudbrain_samejob_err"
}
return ""
}

func (c CloudbrainDisplayJobNameLock) Unlock(ctx *LockContext) error {
lock := redis_lock.NewDistributeLock(redis_key.CloudbrainBindingJobNameKey(fmt.Sprint(ctx.Repo.ID), ctx.Task.JobType, ctx.Task.DisplayJobName))
return lock.UnLock()
}

+ 30
- 0
services/lock/cloudbrain_uniqueness_lock.go View File

@@ -0,0 +1,30 @@
package lock

import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/redis/redis_key"
"code.gitea.io/gitea/modules/redis/redis_lock"
"code.gitea.io/gitea/modules/setting"
)

type CloudbrainUniquenessLock struct {
}

func (c CloudbrainUniquenessLock) IsMatch(ctx *LockContext) bool {
return true
}

func (c CloudbrainUniquenessLock) Lock(ctx *LockContext) string {
lock := redis_lock.NewDistributeLock(redis_key.CloudbrainUniquenessKey(ctx.User.ID, ctx.Task.JobType))
isOk, err := lock.Lock(setting.CloudbrainUniquenessLockTime)
if !isOk {
log.Error("CloudbrainDisplayJobNameLock lock failed:%v", err)
return "repo.cloudbrain.morethanonejob"
}
return ""
}

func (c CloudbrainUniquenessLock) Unlock(ctx *LockContext) error {
lock := redis_lock.NewDistributeLock(redis_key.CloudbrainUniquenessKey(ctx.User.ID, ctx.Task.JobType))
return lock.UnLock()
}

+ 17
- 0
services/lock/lock.go View File

@@ -0,0 +1,17 @@
package lock

import (
"code.gitea.io/gitea/models"
)

type LockContext struct {
Repo *models.Repository
Task *models.Cloudbrain
User *models.User
}

type Lock interface {
IsMatch(ctx *LockContext) bool
Lock(ctx *LockContext) string
Unlock(ctx *LockContext) error
}

+ 42
- 0
services/lock/lock_operator.go View File

@@ -0,0 +1,42 @@
package lock

type LockChainOperator struct {
chainList []Lock
lockedList []Lock
ctx *LockContext
}

func NewLockChainOperator(ctx *LockContext) *LockChainOperator {
return &LockChainOperator{ctx: ctx}
}

func (b *LockChainOperator) Add(l Lock) *LockChainOperator {
b.chainList = append(b.chainList, l)
return b
}

func (b *LockChainOperator) Lock() string {
for i := 0; i < len(b.chainList); i++ {
l := b.chainList[i]
if !l.IsMatch(b.ctx) {
continue
}

if errCode := l.Lock(b.ctx); errCode != "" {
b.Unlock()
return errCode
}
b.lockedList = append(b.lockedList, l)
}
return ""
}

func (b *LockChainOperator) Unlock() error {
if b.chainList == nil || len(b.chainList) == 0 {
return nil
}
for j := len(b.lockedList) - 1; j >= 0; j-- {
b.lockedList[j].Unlock(b.ctx)
}
return nil
}

+ 4
- 4
services/mirror/mirror.go View File

@@ -252,7 +252,7 @@ func runSync(m *models.Mirror) ([]*mirrorSyncResult, bool) {
}
}

branches, _, err := repo_module.GetBranches(m.Repo,0,0)
branches, _, err := repo_module.GetBranches(m.Repo, 0, 0)
if err != nil {
log.Error("GetBranches: %v", err)
return nil, false
@@ -382,17 +382,17 @@ func syncMirror(repoID string) {
continue
}

tp, _ := git.SplitRefName(result.refName)
//tp, _ := git.SplitRefName(result.refName)

// Create reference
if result.oldCommitID == gitShortEmptySha {
notification.NotifySyncCreateRef(m.Repo.MustOwner(), m.Repo, tp, result.refName)
//notification.NotifySyncCreateRef(m.Repo.MustOwner(), m.Repo, tp, result.refName)
continue
}

// Delete reference
if result.newCommitID == gitShortEmptySha {
notification.NotifySyncDeleteRef(m.Repo.MustOwner(), m.Repo, tp, result.refName)
//notification.NotifySyncDeleteRef(m.Repo.MustOwner(), m.Repo, tp, result.refName)
continue
}



+ 10
- 6
services/reward/point/account/point_account.go View File

@@ -68,20 +68,24 @@ func InitAccount(userId int64) (*models.PointAccount, error) {

}

//IsPointBalanceEnough check whether the user's point balance is bigger than task unit price
func IsPointBalanceEnough(targetUserId int64, unitPrice int) bool {
//IsPointBalanceEnough check whether the user's point balance is enough to start the task
func IsPointBalanceEnough(targetUserId int64, c models.PointDeductCondition) bool {
if !setting.CloudBrainPaySwitch {
return true
}
if unitPrice == 0 {
return true
}
a, err := GetAccount(targetUserId)
if err != nil {
log.Error("IsPointBalanceEnough GetAccount error,err=%v", err)
return false
}
return a.Balance >= int64(unitPrice)
if c.SpecUnitPrice == 0 {
return true
}
if c.WorkServerNumber <= 0 {
c.WorkServerNumber = 1
}

return a.Balance >= int64(c.SpecUnitPrice*c.WorkServerNumber)
}

func SearchPointAccount(opt models.SearchPointAccountOpts) (*models.SearchPointAccountResponse, error) {


+ 1
- 1
services/socketwrap/clientManager.go View File

@@ -10,7 +10,7 @@ import (
"github.com/elliotchance/orderedmap"
)

var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40}
var opTypes = []int{1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 39, 40, 41}

type ClientsManager struct {
Clients *orderedmap.OrderedMap


+ 8
- 8
templates/admin/cloudbrain/list.tmpl View File

@@ -89,21 +89,21 @@
<div class="row">
<!-- 任务名 -->
{{$JobID := '0'}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY"}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "MODELSAFETY" "SNN4ECOSET"}}
{{$JobID = .Cloudbrain.ID}}
{{else}}
{{$JobID = .JobID}}
{{end}}
<!-- {{$JobID}} -->
<div class="two wide column nowrap" style="width:10% !important;">
{{if eq .JobType "DEBUG"}}
{{if eq .JobType "DEBUG"}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px">
<span class="fitted"
style="width: 90%;vertical-align: middle;">{{.DisplayJobName}}</span>
</a>
{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}
{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET")}}
<a class="title"
href="{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}/cloudbrain/benchmark/{{$JobID}}"
title="{{.DisplayJobName}}" style="font-size: 14px;padding-right:0px">
@@ -233,7 +233,7 @@
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}}
<a style="margin: 0 1rem;" id="ai-debug-{{$JobID}}"
class='ui basic ai_debug {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button'
data-jobid="{{$JobID}}"
data-jobid="{{$JobID}}"
data-repopath='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}/{{$JobID}}/'>
{{$.i18n.Tr "repo.debug"}}
</a>
@@ -263,7 +263,7 @@
</a>
</form>
{{else}}
{{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE"}}
{{if eq .JobType "DEBUG" "BENCHMARK" "SNN4IMAGENET" "BRAINSCORE" "SNN4ECOSET"}}
<form id="stopForm-{{$JobID}}" style="margin-left:-1px;">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;" id="ai-stop-{{$JobID}}"
@@ -305,11 +305,11 @@
</form>
{{else}}
<form class="ui compact buttons" id="delForm-{{$JobID}}"
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?ishomepage=true'
action='{{AppSubUrl}}/{{.Repo.OwnerName}}/{{.Repo.Name}}{{if eq .JobType "BENCHMARK"}}/cloudbrain/benchmark{{else if or (eq .JobType "SNN4IMAGENET") (eq .JobType "BRAINSCORE") (eq .JobType "SNN4ECOSET")}}/cloudbrain{{else if eq .JobType "DEBUG"}}{{if eq .Cloudbrain.Type 2}}/grampus/notebook{{else}}{{if eq .ComputeResource "CPU/GPU"}}/cloudbrain{{else}}/modelarts/notebook{{end}}{{end}}{{else if eq .JobType "TRAIN"}}{{if eq .Cloudbrain.Type 1}}/modelarts/train-job{{else if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{else if eq .Cloudbrain.Type 2}}/grampus/train-job{{end}}{{else if eq .JobType "INFERENCE"}}{{if eq .Cloudbrain.Type 0}}/cloudbrain/train-job{{end}}{{end}}/{{$JobID}}/del?isadminpage=true'
method="post">
{{$.CsrfTokenHtml}}
<a style="padding: 0.5rem 1rem;margin-left:0.2rem" id="ai-delete-{{$JobID}}"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?ishomepage=true"
data-repopath="{{.Repo.OwnerName}}/{{.Repo.Name}}/modelarts/inference-job/{{$JobID}}/del_version?isadminpage=true"
data-version="{{.VersionName}}" class="ui basic ai_delete blue button"
style="border-radius: .28571429rem;">
{{$.i18n.Tr "repo.delete"}}
@@ -321,7 +321,7 @@
</div>
{{else}}
{{$JobID := '0'}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK"}}
{{if eq .JobType "DEBUG" "SNN4IMAGENET" "BRAINSCORE" "BENCHMARK" "SNN4ECOSET"}}
{{$JobID = .Cloudbrain.ID}}
{{else}}
{{$JobID = .JobID}}


+ 2
- 0
templates/admin/cloudbrain/search.tmpl View File

@@ -35,6 +35,7 @@
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4IMAGENET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="SNN4IMAGENET">SNN4IMAGENET</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=BRAINSCORE&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="BRAINSCORE">BRAINSCORE</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=MODELSAFETY&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="MODELSAFETY">MODELSAFETY</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType=SNN4ECOSET&listType={{$.ListType}}&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="MODELSAFETY">SNN4ECOSET</a>
</div>
</div>
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">
@@ -44,6 +45,7 @@
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value='{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}'>{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=CPU/GPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="CPU/GPU">CPU/GPU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=NPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="NPU">NPU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=GCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="GCU">GCU</a>
</div>
</div>
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">


+ 1
- 0
templates/admin/cloudbrain/search_dashboard.tmpl View File

@@ -55,6 +55,7 @@
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value='{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}'>{{.i18n.Tr "admin.cloudbrain.all_computing_resources"}}</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=CPU/GPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="CPU/GPU">CPU/GPU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=NPU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="NPU">NPU</a>
<a class="item" href="{{$.Link}}?q={{$.Keyword}}&jobType={{$.JobType}}&listType=GCU&jobStatus={{$.JobStatus}}&cluster={{$.cluster}}&aiCenter={{$.aiCenter}}" data-value="GCU">GCU</a>
</div>
</div>
<div class="ui selection dropdown" style="min-width: 10em;min-height:2.6em;border-radius: .28571429rem;margin-right: 1em;padding: .67em 3.2em .7em 1em;">


+ 35
- 0
templates/annual_privacy.tmpl View File

@@ -0,0 +1,35 @@
{{template "base/head_home" .}}
<div class="ui container">
<h1 class="ui center am-pt-30 am-pb-20">OpenI 2022年度报告授权协议</h1>
<div class="ui divider am-pb-10"></div>
<p>
感谢您阅读《OpenI 2022年度报告授权协议》!在您正式使用OpenI 2022年度报告之前应仔细阅读并充分理解本协议中的全部内容,如您不同意本协议中的任何条款,请立即停止使用OpenI 2022年度报告。您使用OpenI 2022年度报告的行为将被视为已经仔细阅读、充分理解并毫无保留地接受本协议所有条款。
</p>
<p>
<strong>1. 制作年度报告</strong>
</p>
<p>
OpenI 2022年度报告将根据您在平台的历史信息,帮助您生成一份专属年度报告。为此,我们将使用2022自然年度您在OpenI 产生的行为信息,包括但不限于用户名、注册时间、创建项目数、项目下载次数、commit次数、代码行数、创建数据集、上传数据集文件、数据集被收藏数、数据集下载数、云脑任务所有相关数据( GPU/NPU 调试任务、训练任务、运行卡时)。您理解并同意,上述信息是OpenI 生成年度报告的必备信息,如您拒绝授权使用,OpenI 将无法为您制作并提供专属年度报告。未经您的书面同意,我们保证不以超越本协议约定范围使用您的个人信息。
</p>
<p>
<strong>2. 使用年度报告</strong>
</p>
<p>
OpenI 提供的年度报告仅限您个人使用,您可自行留存欣赏或无偿分享、公开。您理解并同意,如因您分享、公开年度报告而产生的任何损失(包括但不限于个人信息泄露等)应由您自行承担,请您在分享、公开年度报告前审慎考虑。
</p>
<p>
<strong>3. 知识产权</strong>
</p>
<p>
年度报告及其内容(包括但不限于软件、技术、程序、网页、文字、图片、音频、视频、页面设计、商标等)的知识产权由OpenI 享有,您理解并同意,您不得超越本协议目的使用年度报告中的内容素材,如您希望以任何形式将年度报告中的内容素材用于本协议约定范围之外,应当经过所有实际权利人的书面许可。
</p>
<p>
<strong>4. 隐私政策</strong>
</p>
<p>
其他本隐私保护指引未有涉及的,将适用<a target="_blank" href="/home/term/">《OpenI AI协作平台使用协议》</a>和<a target="_blank" href="/home/privacy/">《OpenI AI协作平台隐私协议》</a>。
</p>

</div>
{{template "base/footer" .}}

+ 9
- 9
templates/base/footer.tmpl View File

@@ -17,9 +17,9 @@

{{if .RequireSimpleMDE}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js?v={{MD5 AppVer}}"></script>
<script>
CodeMirror.modeURL = "{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/%N/%N.js";
</script>
@@ -27,10 +27,10 @@

<!-- Third-party libraries -->
{{if .RequireMinicolors}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js?v={{MD5 AppVer}}"></script>
{{end}}
{{if .RequireU2F}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js?v={{MD5 AppVer}}"></script>
{{end}}
{{if .EnableCaptcha}}
{{if eq .CaptchaType "recaptcha"}}
@@ -38,17 +38,17 @@
{{end}}
{{end}}
{{if .RequireTribute}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js?v={{MD5 AppVer}}"></script>
{{end}}
{{if .PageIsHome}}
<script rel="stylesheet" src="{{StaticUrlPrefix}}/vendor/plugins/jquery.particleground/jquery.particleground.min.js"></script>
<script rel="stylesheet" src="{{StaticUrlPrefix}}/vendor/plugins/jquery.particleground/jquery.particleground.min.js?v={{MD5 AppVer}}"></script>
{{end}}
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script>
{{template "custom/footer" .}}
{{if .PageIsHome}}
<!--script src="https://www.jq22.com/jquery/jquery-1.10.2.js"></script-->
<script src="/rotation3D/vue-2.6.10.min.js"></script>
<!--script src="https://www.jq22.com/jquery/jquery-1.10.2.js?v={{MD5 AppVer}}"></script-->
<script src="/rotation3D/vue-2.6.10.min.js?v={{MD5 AppVer}}"></script>
<script src="/rotation3D/rotation3D.js?v={{MD5 AppVer}}"></script>
<script>
var jobTask={};


+ 10
- 0
templates/base/footer_content.tmpl View File

@@ -1,3 +1,13 @@
<style>
@media only screen and (max-width: 767px) {
.mobile-text-align-center {
text-align: center !important;
}
.mobile-justify-content-center {
justify-content: center !important;
}
}
</style>
<footer style="border-top:none;">
<div class="ui container">
<div class="ui grid">


+ 7
- 7
templates/base/footer_fluid.tmpl View File

@@ -14,9 +14,9 @@
<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script>
{{if .RequireSimpleMDE}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js?v={{MD5 AppVer}}"></script>
<script>
CodeMirror.modeURL = "{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/%N/%N.js";
</script>
@@ -24,10 +24,10 @@
<!-- Third-party libraries -->
{{if .RequireMinicolors}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js?v={{MD5 AppVer}}"></script>
{{end}}
{{if .RequireU2F}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/u2f/index.js?v={{MD5 AppVer}}"></script>
{{end}}
{{if .EnableCaptcha}}
{{if eq .CaptchaType "recaptcha"}}
@@ -35,10 +35,10 @@
{{end}}
{{end}}
{{if .RequireTribute}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.min.js?v={{MD5 AppVer}}"></script>
{{end}}
{{if .PageIsHome}}
<script rel="stylesheet" src="{{StaticUrlPrefix}}/vendor/plugins/jquery.particleground/jquery.particleground.min.js"></script>
<script rel="stylesheet" src="{{StaticUrlPrefix}}/vendor/plugins/jquery.particleground/jquery.particleground.min.js?v={{MD5 AppVer}}"></script>
{{end}}
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script>


+ 10
- 10
templates/base/head.tmpl View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
<link rel="manifest" href="{{AppSubUrl}}/manifest.json?v={{MD5 AppVer}}" crossorigin="use-credentials">
{{if UseServiceWorker}}
<script>
if ('serviceWorker' in navigator) {
@@ -115,18 +115,18 @@
window.sessionStorage.removeItem('_csrf');
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css">
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png?v={{MD5 AppVer}}">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg?v={{MD5 AppVer}}" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png?v={{MD5 AppVer}}" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css?v={{MD5 AppVer}}">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous">
{{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css?v={{MD5 AppVer}}">
{{end}}

{{if .RequireTribute}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
@@ -137,7 +137,7 @@
</style>
</noscript>
{{if .RequireMinicolors}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css?v={{MD5 AppVer}}">
{{end}}
<style class="list-search-style"></style>
{{if .PageIsUserProfile}}
@@ -179,7 +179,7 @@
{{else if ne DefaultTheme "gitea"}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css">
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css?v={{MD5 AppVer}}">
{{template "custom/header" .}}

<script>
@@ -191,7 +191,7 @@ var _hmt = _hmt || [];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script src="/self/func.js" type="text/javascript"></script>
<script src="/self/func.js?v={{MD5 AppVer}}" type="text/javascript"></script>
</head>
<body>
{{template "custom/body_outer_pre" .}}


+ 10
- 10
templates/base/head_course.tmpl View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
<link rel="manifest" href="{{AppSubUrl}}/manifest.json?v={{MD5 AppVer}}" crossorigin="use-credentials">
{{if UseServiceWorker}}
<script>
if ('serviceWorker' in navigator) {
@@ -115,18 +115,18 @@
window.sessionStorage.removeItem('_csrf');
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css">
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png?v={{MD5 AppVer}}">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg?v={{MD5 AppVer}}" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png?v={{MD5 AppVer}}" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css?v={{MD5 AppVer}}">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous">
{{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css?v={{MD5 AppVer}}">
{{end}}

{{if .RequireTribute}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
@@ -137,7 +137,7 @@
</style>
</noscript>
{{if .RequireMinicolors}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css?v={{MD5 AppVer}}">
{{end}}
<style class="list-search-style"></style>
{{if .PageIsUserProfile}}
@@ -179,7 +179,7 @@
{{else if ne DefaultTheme "gitea"}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css">
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css?v={{MD5 AppVer}}">
{{template "custom/header" .}}

<script>
@@ -191,7 +191,7 @@ var _hmt = _hmt || [];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script src="/self/func.js" type="text/javascript"></script>
<script src="/self/func.js?v={{MD5 AppVer}}" type="text/javascript"></script>
</head>
<body>
{{template "custom/body_outer_pre" .}}


+ 10
- 10
templates/base/head_fluid.tmpl View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
<link rel="manifest" href="{{AppSubUrl}}/manifest.json?v={{MD5 AppVer}}" crossorigin="use-credentials">
{{if UseServiceWorker}}
<script>
if ('serviceWorker' in navigator) {
@@ -115,18 +115,18 @@
window.sessionStorage.removeItem('_csrf');
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css">
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png?v={{MD5 AppVer}}">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg?v={{MD5 AppVer}}" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png?v={{MD5 AppVer}}" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css?v={{MD5 AppVer}}">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous">
{{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css?v={{MD5 AppVer}}">
{{end}}

{{if .RequireTribute}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
@@ -137,7 +137,7 @@
</style>
</noscript>
{{if .RequireMinicolors}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css?v={{MD5 AppVer}}">
{{end}}
<style class="list-search-style"></style>
{{if .PageIsUserProfile}}
@@ -179,7 +179,7 @@
{{else if ne DefaultTheme "gitea"}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css">
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css?v={{MD5 AppVer}}">
{{template "custom/header" .}}

<script>
@@ -191,7 +191,7 @@ var _hmt = _hmt || [];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script src="/self/func.js" type="text/javascript"></script>
<script src="/self/func.js?v={{MD5 AppVer}}" type="text/javascript"></script>

</head>
<body>


+ 14
- 14
templates/base/head_home.tmpl View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
<link rel="manifest" href="{{AppSubUrl}}/manifest.json?v={{MD5 AppVer}}" crossorigin="use-credentials">
{{if UseServiceWorker}}
<script>
if ('serviceWorker' in navigator) {
@@ -115,19 +115,19 @@
window.sessionStorage.removeItem('_csrf');
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css">
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png?v={{MD5 AppVer}}">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg?v={{MD5 AppVer}}" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png?v={{MD5 AppVer}}" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css?v={{MD5 AppVer}}">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous">
<link rel="stylesheet" href="/css/git.openi.css">
<link rel="stylesheet" href="/css/git.openi.css?v={{MD5 AppVer}}">
{{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css?v={{MD5 AppVer}}">
{{end}}

{{if .RequireTribute}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
@@ -138,7 +138,7 @@
</style>
</noscript>
{{if .RequireMinicolors}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css?v={{MD5 AppVer}}">
{{end}}
<style class="list-search-style"></style>
{{if .PageIsUserProfile}}
@@ -191,14 +191,14 @@ var _hmt = _hmt || [];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script src="/self/func.js" type="text/javascript"></script>
<script src="/self/func.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<!--RemixIcon Fonts v2.5.0-->
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css">
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css?v={{MD5 AppVer}}">
<!-- Swiper -->
<link rel="stylesheet" href="/swiper/swiper-bundle.min.css">
<script src="/swiper/swiper-bundle.min.js"></script>
<link rel="stylesheet" href="/swiper/swiper-bundle.min.css?v={{MD5 AppVer}}">
<script src="/swiper/swiper-bundle.min.js?v={{MD5 AppVer}}"></script>
<!-- rotation3D -->
<link rel="stylesheet" href="/rotation3D/rotation3D.css">
<link rel="stylesheet" href="/rotation3D/rotation3D.css?v={{MD5 AppVer}}">
</head>
<body>
{{template "custom/body_outer_pre" .}}


+ 10
- 10
templates/base/head_pro.tmpl View File

@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title>
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials">
<link rel="manifest" href="{{AppSubUrl}}/manifest.json?v={{MD5 AppVer}}" crossorigin="use-credentials">
{{if UseServiceWorker}}
<script>
if ('serviceWorker' in navigator) {
@@ -115,18 +115,18 @@
window.sessionStorage.removeItem('_csrf');
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css">
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png?v={{MD5 AppVer}}">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg?v={{MD5 AppVer}}" color="#609926">
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png?v={{MD5 AppVer}}" title="{{AppName}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css?v={{MD5 AppVer}}">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous">
{{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css?v={{MD5 AppVer}}">
{{end}}

{{if .RequireTribute}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
@@ -137,7 +137,7 @@
</style>
</noscript>
{{if .RequireMinicolors}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css?v={{MD5 AppVer}}">
{{end}}
<style class="list-search-style"></style>
{{if .PageIsUserProfile}}
@@ -179,7 +179,7 @@
{{else if ne DefaultTheme "gitea"}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}">
{{end}}
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css">
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css?v={{MD5 AppVer}}">
{{template "custom/header" .}}

<script>
@@ -191,7 +191,7 @@ var _hmt = _hmt || [];
s.parentNode.insertBefore(hm, s);
})();
</script>
<script src="/self/func.js" type="text/javascript"></script>
<script src="/self/func.js?v={{MD5 AppVer}}" type="text/javascript"></script>

</head>
<body>


+ 2
- 0
templates/custom/header.tmpl View File

@@ -0,0 +1,2 @@
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/placeholder.css?v={{TimeStampNow}}">
<script src="{{StaticUrlPrefix}}/js/placeholder.js?v={{TimeStampNow}}"></script>

+ 39
- 1
templates/custom/home/home_top.tmpl View File

@@ -1786,8 +1786,40 @@
background-repeat: no-repeat;
background-size: cover;
padding: 45% 0;
}
}
}

._hm-pg-bg-4 {
background: url(/img/home-banner-02-1.jpg);
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
._hm-pg-bg-4-content {
position: absolute;
margin: auto;
left: 0;
top: -10%;
right: 0;
bottom: 0;
display: block;
width: 790px;
height: 315px;
background: url(/img/home-banner-02-2.png);
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
@media only screen and (max-width: 767px) {
._hm-pg-bg-4 {
background-size: 200% 100%;
}
._hm-pg-bg-4-content {
top: -15%;
width: 90%;
height: 150px;
}
}
</style>
<div class="_hm-bg-container">
<div class="_hm-pg _hm-pg-static">
@@ -2029,12 +2061,18 @@
<div class="_hm-big-btn-c"></div>
</div>
</div>
<div class="_hm-pg _hm-pg-bg-4">
<a target="_blank;" href="//www.krtcgo.com/index.php?m=content&c=index&a=lists&catid=225">
<div class="_hm-pg-bg-4-content" style="animation:_hm-slide-in-left-once 0.5s"></div>
</a>
</div>
</div>
<div class="_hm-slide-btn _hm-slide-btn-left"></div>
<div class="_hm-slide-btn _hm-slide-btn-right"></div>
<div class="_hm-slide-pagination-c">
<div class="_hm-slide-pagination-item _hm-slide-pagination-item-active"></div>
<div class="_hm-slide-pagination-item"></div>
<div class="_hm-slide-pagination-item"></div>
</div>
</div>
<div class="ui container _hm-container">


+ 2
- 2
templates/custom/task_wait_count.tmpl View File

@@ -1,7 +1,7 @@
<div style="display:inline-block;">
<div style="display:flex;align-items:center;color:#f2711c;">
<i class="ri-error-warning-line" style="margin-right: 0.5rem; font-size: 14px"></i>
<span style="font-size: 12px">{{.i18n.Tr "repo.wait_count_start"}} <span class="__task_wait_count__">{{.WaitCount}}</span> {{.i18n.Tr "repo.wait_count_end"}}</span>
<span style="font-size: 12px">{{.i18n.Tr "repo.wait_count_start"}} <span class="__task_wait_count__">{{if not .WaitCount}}1{{else}}{{addOne .WaitCount}}{{end}}</span> {{.i18n.Tr "repo.wait_count_end"}}</span>
</div>
</div>
<script>
@@ -12,7 +12,7 @@
var specsSelEl = $('select#__specs__');
var seldOption = specsSelEl.find('option:selected');
var queueCode = seldOption.attr('queueCode');
$('span.__task_wait_count__').text(queuesDetail[queueCode] || 0);
$('span.__task_wait_count__').text((queuesDetail[queueCode] || 0) +1);
};
$('body').on('change', 'select#__specs__', function(e) {
changeSpecs();


+ 1
- 0
templates/explore/images.tmpl View File

@@ -1,4 +1,5 @@
{{template "base/head" .}}
<div class="alert"></div>
<div id="images"></div>
<!-- 确认模态框 -->
<div id="deletemodel">


+ 4
- 4
templates/explore/organizations.tmpl View File

@@ -1,8 +1,8 @@

<link rel="stylesheet" href="/swiper/swiper-bundle.min.css">
<link rel="stylesheet" href="/css/git.openi.css">
<script src="/swiper/swiper-bundle.min.js"></script>
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="/swiper/swiper-bundle.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="/css/git.openi.css?v={{MD5 AppVer}}">
<script src="/swiper/swiper-bundle.min.js?v={{MD5 AppVer}}"></script>
<script src="/self/js/jquery.min.js?v={{MD5 AppVer}}" type="text/javascript"></script>

{{template "base/head" .}}
<div class="explore users">


+ 2
- 2
templates/explore/repo_orgtop.tmpl View File

@@ -1,5 +1,5 @@
<script src="/swiper/swiper-bundle.min.js"></script>
<link href="/swiper/swiper-bundle.min.css" rel="stylesheet">
<script src="/swiper/swiper-bundle.min.js?v={{MD5 AppVer}}"></script>
<link href="/swiper/swiper-bundle.min.css?v={{MD5 AppVer}}" rel="stylesheet">

<style>
.explore .repos--seach{


+ 1
- 1
templates/explore/search_new.tmpl View File

@@ -86,7 +86,7 @@
</div>

</div>
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<script src="/self/js/jquery.min.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<script src="/home/search.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<div class="am-mt-30"></div>



+ 3
- 1
templates/home.tmpl View File

@@ -1,4 +1,6 @@
{{template "base/head_home" .}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/placeholder-home.css?v={{TimeStampNow}}">
<script src="{{StaticUrlPrefix}}/js/placeholder-home.js?v={{TimeStampNow}}"></script>
<div class="ui vertical masthead secondary hometop segment" style="background:transparent;margin-bottom:0">
{{template "custom/home/home_top" .}}
</div>
@@ -160,7 +162,7 @@
-->

<!-- <div class="am-mt-30"></div> -->
<script src="/self/js/jquery.min.js" type="text/javascript"></script>
<script src="/self/js/jquery.min.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<script src="/home/home.js?v={{MD5 AppVer}}" type="text/javascript"></script>




+ 125
- 259
templates/repo/cloudbrain/benchmark/new.tmpl View File

@@ -1,37 +1,9 @@
{{template "base/head" .}}
<style>
.unite {
font-family: SourceHanSansSC-medium !important;
color: rgba(16, 16, 16, 100) !important;
}

.title {
font-size: 16px !important;
padding-left: 3rem !important;
}

.min_title{
font-size: 14px !important;
margin-bottom: 2rem !important;
}

.width81 {
margin-left: 1.5rem;
width: 81% !important;
}

.width48 {
width: 48.5% !important;
}

.nowrapx {
white-space: nowrap !important;
}
</style>
{{template "custom/global_mask" .}}
<div class="repository">
{{template "repo/header" .}}
<div class="ui container">
<div class="cloudbrain-type" style="display: none;" data-repo-link="{{.RepoLink}}" data-flag-model="true"></div>
{{if eq .NotStopTaskCount 0}}
{{template "base/alert" .}}
{{end}}
@@ -54,7 +26,7 @@
<a class="active item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
<a class="item aisafety_benchmark"
href="{{.RepoLink}}/modelsafety/create_gpu">模型安全评测</a>
href="{{.RepoLink}}/modelsafety/create_gpu">{{.i18n.Tr "modelsafety.model_security_evaluation"}}</a>
</div>
</div>
<div>
@@ -78,21 +50,12 @@
onkeydown="this.value=this.value.substring(0, 255)"
onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
</div>

<!--<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label>
<select id="cloudbrain_gpu_type" class="ui search dropdown width48" placeholder="选择GPU类型"
name="gpu_type">
{{range .benchmark_gpu_types}}
<option value="{{.Queue}}">{{.Value}}</option>
{{end}}
</select>
</div>-->
<div class="required unite min_title two inline fields" style="margin-left: 80px;">
<div class="required min_title two inline fields" style="margin-left: 80px;">
<div class="required ten wide field" style="width: 26.5% !important;">
<label style="font-weight: normal;">{{.i18n.Tr "cloudbrain.task_type"}}</label>&nbsp;
<select id="cloudbrain_job_type" class="ui search dropdown job_type"
<select id="cloudbrain_job_type" class="ui search dropdown job_type"
placeholder="select {{.i18n.Tr "cloudbrain.task_type"}}" name="job_type">
<option value="SNN4ECOSET">SNN4ECOSET</option>
<option value="SNN4IMAGENET">SNN4IMAGENET</option>
<option value="BRAINSCORE">BRAINSCORE</option>
</select>
@@ -116,22 +79,10 @@
<a id="benchmark_model_example" href="https://openi.pcl.ac.cn/BDIP/snn4imagenet"
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>
{{template "custom/select_model" .}}
<div id="images-new-cb">
</div>
{{template "custom/select_dataset_train" .}}
<!--<div class="required min_title inline field" style="margin-top:2rem;">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="cloudbrain_resource_spec" class="ui search dropdown"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
name="resource_spec_id">
{{range .benchmark_resource_specs}}
<option name="resource_spec_id" value="{{.Id}}">
{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}
</option>
{{end}}
</select>
</div>-->
<div class="required min_title inline field" style="margin-top:2rem;">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown width48"
@@ -156,7 +107,7 @@
<button class="ui create_train_job green button {{if eq .NotStopTaskCount 1}}disabled{{end}}">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
<a class="ui button" href="{{.RepoLink}}/cloudbrain/benchmark">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>
</form>
@@ -173,7 +124,7 @@
<a class="item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
<a class="item aisafety_benchmark"
href="{{.RepoLink}}/modelsafety/create_gpu">模型安全评测</a>
href="{{.RepoLink}}/modelsafety/create_gpu">{{.i18n.Tr "modelsafety.model_security_evaluation"}}</a>
</div>
</div>

@@ -199,20 +150,11 @@
onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
</div>

<!--<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.gpu_type"}}</label>
<select id="cloudbrain_gpu_type" class="ui search dropdown" placeholder="选择GPU类型"
style='width:385px' name="gpu_type">
{{range .benchmark_gpu_types}}
<option value="{{.Queue}}">{{.Value}}</option>
{{end}}
</select>
</div>-->
<div class="required unite inline min_title fields" style="width: 90%;margin-left: 5.7rem;">&nbsp;
<div class="required inline min_title fields" style="width: 90%;margin-left: 5.7rem;">&nbsp;
<div class="required eight wide field">
<label style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_type"}}</label>

<select class="ui fluid selection search dropdown" id="benchmark_types_id"
<select class="ui fluid selection search dropdown benchmark_types_id"
name="benchmark_types_id">
{{range .benchmark_types}}
{{if eq .Id $.benchmarkTypeID}}
@@ -226,26 +168,13 @@
<div class="eight wide field" id="engine_name">
<input type="hidden" id="benchmark_child_types_id_hidden" name="benchmark_child_types_id_hidden" value="{{.benchmark_child_types_id_hidden}}">
<label style="font-weight: normal;white-space: nowrap;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_child_type"}}</label>
<select class="ui fluid selection dropdown nowrapx" id="benchmark_child_types_id" style='width: 100%;' name="benchmark_child_types_id">
<select class="ui fluid selection dropdown " id="benchmark_child_types_id" style='width: 100%;' name="benchmark_child_types_id">
</select>
</div>
</div>
<div id="images-new-cb">
</div>

<!--<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="cloudbrain_resource_spec" class="ui search dropdown"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px'
name="resource_spec_id">
{{range .benchmark_resource_specs}}
<option name="resource_spec_id" value="{{.Id}}">
{{$.i18n.Tr "cloudbrain.gpu_num"}}:{{.GpuNum}},{{$.i18n.Tr "cloudbrain.cpu_num"}}:{{.CpuNum}},{{$.i18n.Tr "cloudbrain.memory"}}(MB):{{.MemMiB}},{{$.i18n.Tr "cloudbrain.shared_memory"}}(MB):{{.ShareMemMiB}}
</option>
{{end}}
</select>
</div>-->

<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown width48"
@@ -282,197 +211,134 @@
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>


<div class="inline unite min_title field">
<label class="label-fix-width" style="font-weight: normal;"></label>
<button class="ui create_train_job green button {{if eq .NotStopTaskCount 1}}disabled{{end}}">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>
</form>
{{else if eq .benchmarkMode "aisafety"}}
<form id="form_id" class="ui form alogrithm_form" action="{{.Link}}?benchmarkMode=alogrithm" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="update">
<input type="hidden" name="job_type" value="BENCHMARK">
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_scenes"}}</label>
<div class="ui blue small menu compact selectcloudbrain">
<a class="item alogrithm_benchmark"
href="{{.Link}}?benchmarkMode=alogrithm">{{.i18n.Tr "repo.cloudbrain.benchmark.algorithm"}}</a>
<a class="item model_benchmark"
href="{{.Link}}?benchmarkMode=model">{{.i18n.Tr "repo.cloudbrain.benchmark.model"}}</a>
<a class="active item aisafety_benchmark"
href="{{.RepoLink}}/modelsafety/create_gpu">模型安全评测</a>
</div>
</div>

<div>
<div class="min_title inline field" style="margin-top:-10px;">
<label class="label-fix-width" style="font-weight: normal;"></label>
{{template "custom/task_wait_count" .}}
</div>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "repo.modelarts.train_job.job_name"}}</label>
<input style="width: 80%;" name="display_job_name" id="trainjob_job_name"
placeholder={{.i18n.Tr "repo.modelarts.train_job.job_name"}} value="{{.display_job_name}}"
tabindex="3" autofocus required maxlength="36">
<span class="tooltips" style="display: block;margin-left: 11.5rem;">{{.i18n.Tr "repo.cloudbrain_jobname_err"}}</span>
</div>
<div class="min_title inline field">
<label class="label-fix-width" style="font-weight: normal;"
for="description">{{.i18n.Tr "repo.modelarts.train_job.description"}}</label>
<textarea style="width: 80%;" id="description" name="description" rows="3" maxlength="254"
placeholder={{.i18n.Tr "repo.modelarts.train_job.new_place"}}
onchange="this.value=this.value.substring(0, 255)"
onkeydown="this.value=this.value.substring(0, 255)"
onkeyup="this.value=this.value.substring(0, 255)">{{.description}}</textarea>
</div>


<div id="images-new-cb">
</div>

<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_specification"}}</label>
<select id="__specs__" class="ui search dropdown width48"
placeholder="{{.i18n.Tr "cloudbrain.select_specification"}}" style='width:385px' ovalue="{{.spec_id}}"
name="spec_id">
</select>
<span><i class="question circle icon link"></i></span>
<a href="{{AppSubUrl}}/resource_desc" target="_blank">{{.i18n.Tr "custom.resource_description"}}</a>
</div>

<div class="inline min_title field required">
<label class="label-fix-width" style="font-weight: normal;">推理程序</label>
<input disabled="disabled" style="width: 33.5%;" name="test_file" id="test_file" value="test.py"
tabindex="3" autofocus required maxlength="254">
<a id="test_href_id" href="https://openi.pcl.ac.cn/CV_benchmark/CV_reID_benchmark"
target="_blank">{{.i18n.Tr "cloudbrain.view_sample"}}</a>
</div>


<div class="inline unite min_title field">
<div class="inline min_title field">
<label class="label-fix-width" style="font-weight: normal;"></label>
<button class="ui create_train_job green button {{if eq .NotStopTaskCount 1}}disabled{{end}}">
{{.i18n.Tr "repo.cloudbrain.new"}}
</button>
<a class="ui button" href="/">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
<a class="ui button" href="{{.RepoLink}}/cloudbrain/benchmark">{{.i18n.Tr "repo.cloudbrain.cancel"}}</a>
</div>
</div>
</form>

{{end}}
</div>
</div>
</div>
{{template "base/footer" .}}
<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<script src="{{StaticUrlPrefix}}/js/cloudbrainNew.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<script>
let form = document.getElementById('form_id');
let createFlag = false
form.onsubmit = function (e) {
if(createFlag) return false
createFlag = true
}
let repolink = {{.RepoLink }}
let url_href = window.location.pathname.split('create')[0]
$(".ui.button").attr('href', url_href)
$('.menu .item')
.tab();
$('#benchmark_types_id').change(function () {
setChildType();
})
$(document).ready(() => {
$('.ui.search.dropdown.job_type').dropdown({
onChange: function (value, text, $selectedItem) {
if (value === "BRAINSCORE") {
$('#brainscore_child_type').css('display', 'block')
$('#benchmark_model_example').attr('href', 'https://openi.pcl.ac.cn/BDIP/similarity2brain_ann')
} else {
$('#brainscore_child_type').css('display', 'none')
$('#benchmark_model_example').attr('href', 'https://openi.pcl.ac.cn/BDIP/snn4imagenet')
}
}
})
})
function setChildType() {
let type_id = $('#benchmark_types_id').val();
if (type_id == 3) {
$('#train_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_MOT_benchmark');
$('#test_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_MOT_benchmark');
} else {
$('#train_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_reID_benchmark');
$('#test_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_reID_benchmark');
}
let child_selected_id = $('#benchmark_child_types_id_hidden').val();
$.get(`${repolink}/cloudbrain/benchmark/get_child_types?benchmark_type_id=${type_id}`, (data) => {
const n_length = data['child_types'].length
let html = ''
for (let i = 0; i < n_length; i++) {
if (child_selected_id == data['child_types'][i].id) {
html += `<option value="${data['child_types'][i].id}" selected="true">${data['child_types'][i].value}</option>`;
} else {
html += `<option value="${data['child_types'][i].id}">${data['child_types'][i].value}</option>`;
}
}
document.getElementById("benchmark_child_types_id").innerHTML = html;
})
}
document.onreadystatechange = function () {
if (document.readyState === "complete") {
if ($('input[name=benchmarkMode]').val() === 'alogrithm' || $('input[name=benchmarkMode]').val() === '') {
setChildType();
}
}
}
var isValidate = false;
function validate() {
$('.ui.form')
.form({
on: 'blur',
fields: {
image: {
identifier: 'image',
rules: [
{
type: 'empty',
promt: ''
}
]
},
display_job_name: {
identifier: 'display_job_name',
rules: [
{
type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]',
promt: ''
}
]
},
spec_id: {
identifier: 'spec_id',
rules: [{ type: 'empty' }]
}
},
onSuccess: function () {
// $('.ui.page.dimmer').dimmer('show')
document.getElementById("mask").style.display = "block"
isValidate = true;
},
onFailure: function (e) {
isValidate = false;
return false;
}
})
}
// let repolink = {{.RepoLink }}
// $('#benchmark_types_id').change(function () {
// console.log("----")
// // setChildType();
// })
// $("#benchmark_types_id").dropdown({
// onChange:function (value, text, $selectedItem){
// console.log(value)
// }
// })
// $(document).ready(() => {
// $('.ui.search.dropdown.job_type').dropdown({
// onChange: function (value, text, $selectedItem) {
// console.log(value)
// if (value === "BRAINSCORE") {
// $('#brainscore_child_type').css('display', 'block')
// $('#benchmark_model_example').attr('href', 'https://openi.pcl.ac.cn/BDIP/similarity2brain_ann')
// } else {
// $('#brainscore_child_type').css('display', 'none')
// $('#benchmark_model_example').attr('href', 'https://openi.pcl.ac.cn/BDIP/snn4imagenet')
// }
// }
// })
// })
// function setChildType(type_id=1) {
// if (type_id == 3) {
// $('#train_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_MOT_benchmark');
// $('#test_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_MOT_benchmark');
// } else {
// $('#train_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_reID_benchmark');
// $('#test_href_id').attr('href', 'https://openi.pcl.ac.cn/CV_benchmark/CV_reID_benchmark');
// }
// let child_selected_id = $('#benchmark_child_types_id_hidden').val();
// $.get(`${repolink}/cloudbrain/benchmark/get_child_types?benchmark_type_id=${type_id}`, (data) => {
// const n_length = data['child_types'].length
// let html = ''
// for (let i = 0; i < n_length; i++) {
// if (child_selected_id == data['child_types'][i].id) {
// html += `<option value="${data['child_types'][i].id}" selected="true">${data['child_types'][i].value}</option>`;
// } else {
// html += `<option value="${data['child_types'][i].id}">${data['child_types'][i].value}</option>`;
// }
// }
// document.getElementById("benchmark_child_types_id").innerHTML = html;
// })
// }
// $(document).ready(function (){
// console.log("00")
// $(".ui.selection.dropdown.benchmark_types_id").dropdown({
// onChange:function (value, text, $selectedItem){
// console.log(value)
// setChildType(value)
// }
// })
// })
// document.onreadystatechange = function () {
// if (document.readyState === "complete") {
// if ($('input[name=benchmarkMode]').val() === 'alogrithm' || $('input[name=benchmarkMode]').val() === '') {
// setChildType();
// }
// }
// }
// var isValidate = false;
// function validate() {
// $('.ui.form')
// .form({
// on: 'blur',
// fields: {
// image: {
// identifier: 'image',
// rules: [
// {
// type: 'empty',
// promt: ''
// }
// ]
// },
// display_job_name: {
// identifier: 'display_job_name',
// rules: [
// {
// type: 'regExp[/^[a-z0-9][a-z0-9-_]{1,34}[a-z0-9-]$/]',
// promt: ''
// }
// ]
// },
// spec_id: {
// identifier: 'spec_id',
// rules: [{ type: 'empty' }]
// }
// },
// onSuccess: function () {
// // $('.ui.page.dimmer').dimmer('show')
// document.getElementById("mask").style.display = "block"
// isValidate = true;
// },
// onFailure: function (e) {
// isValidate = false;
// return false;
// }
// })
// }

validate()
$('.ui.create_train_job.green.button').click(function (e) {
validate()
})
// validate()
// $('.ui.create_train_job.green.button').click(function (e) {
// validate()
// })

;(function() {
var SPECS = {{ .benchmark_specs }};


+ 30
- 21
templates/repo/cloudbrain/benchmark/show.tmpl View File

@@ -206,7 +206,7 @@
<table class="ti-form">
<tbody class="ti-text-form">

{{if eq .JobType "BENCHMARK"}}
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain.benchmark.evaluate_train"}}
@@ -214,11 +214,7 @@

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{if eq .JobType "BENCHMARK"}}
train.py
{{else}}
--
{{end}}
</div>
</td>
</tr>
@@ -228,16 +224,39 @@
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">
{{if eq .JobType "BENCHMARK"}}
test.py
{{else}}
--
{{end}}
</div>
</td>
</tr>
{{else}}
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.model_name"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">{{if .ModelName}}{{.ModelName}}{{else}}--{{end}}</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelconvert.modelversion"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">{{if .ModelVersion}}{{.ModelVersion}}{{else}}--{{end}}</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.infer_job_model_file"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w">{{if .CkptName}}{{.CkptName}}{{else}}--{{end}}</div>
</td>
</tr>
{{end}}
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.modelarts.train_job.description"}}
@@ -271,17 +290,7 @@
<div class="text-span text-span-w"></div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.model_manager"}}
</td>

<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-mirror">
{{.DatasetName}}
</div>
</td>
</tr>
<tr class="ti-no-ng-animate">
<td class="ti-no-ng-animate ti-text-form-label text-width80">
{{$.i18n.Tr "repo.cloudbrain_creator"}}


+ 1
- 1
templates/repo/cloudbrain/inference/new.tmpl View File

@@ -40,7 +40,7 @@
{{template "base/alert" .}}
{{end}}
{{template "custom/alert_cb" .}}
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-queue="{{.QueuesDetail}}" data-queue-start="{{.i18n.Tr "repo.wait_count_start"}}" data-queue-end="{{.i18n.Tr "repo.wait_count_end"}}"></div>
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}"></div>
<h4 class="ui top attached header">
{{.i18n.Tr "repo.modelarts.train_job.new_infer"}}
</h4>


+ 12
- 4
templates/repo/cloudbrain/inference/show.tmpl View File

@@ -371,10 +371,18 @@
<div class="ui tab" data-tab="four">
<input type="hidden" name="model{{.VersionName}}" value="-1">
<input type="hidden" name="modelback{{.VersionName}}" value="-1">
<div class='ui breadcrumb model_file_bread' id='file_breadcrumb{{.VersionName}}'>
<div class="active section">{{.VersionName}}</div>
<div class="divider"> / </div>

<div style="display: flex;justify-content: space-between;">
<div class='ui breadcrumb model_file_bread' id='file_breadcrumb{{.VersionName}}'>
<div class="active section">{{.VersionName}}</div>
<div class="divider"> / </div>
</div>
<a id="{{.VersionName}}-result-down" style="padding-right: 1%;display: none;"
class='{{if $.canDownload}}ti-download-file{{else}}disabled{{end}} file-info'
href="{{$.RepoLink}}/cloudbrain/inference-job/{{.JobID}}/downloadall?version_name={{.VersionName}}">
<i class="ri-download-cloud-2-line"></i>
<span style="margin-left: 0.3rem;">{{$.i18n.Tr "repo.all_result_download"}}</span>
</a>
</div>
<div id="dir_list{{.VersionName}}">



+ 3
- 2
templates/repo/cloudbrain/new.tmpl View File

@@ -23,7 +23,7 @@
<div class="repository">
{{template "repo/header" .}}
<div class="ui container">
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-queue="{{.QueuesDetail}}" data-queue-start="{{.i18n.Tr "repo.wait_count_start"}}" data-queue-end="{{.i18n.Tr "repo.wait_count_end"}}" data-flag-model="true"></div>
<div class="cloudbrain-type" style="display: none;" data-cloudbrain-type="{{.datasetType}}" data-repo-link="{{.RepoLink}}" data-flag-model="true" data-dataset-uuid="{{.attachment}}" data-dataset-name="{{.dataset_name}}" data-exceed-size="{{DebugAttachSize}}"></div>
{{if eq .NotStopTaskCount 0}}
{{template "base/alert" .}}
{{end}}
@@ -38,6 +38,7 @@
<form id="form_id" class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name='isBranches' value="{{.Branches}}">
<input type="hidden" id="ai_image_name" value="{{.image}}">
<h4 class="train-job-title ui header ">{{.i18n.Tr "repo.modelarts.train_job.basic_info"}}:</h4>
<div class="required min_title inline field">
<label class="label-fix-width" style="font-weight: normal;">{{.i18n.Tr "cloudbrain.resource_cluster"}}</label>
@@ -184,7 +185,7 @@
<span><i class="question circle icon link"></i></span>
<a href="{{AppSubUrl}}/resource_desc" target="_blank">{{.i18n.Tr "custom.resource_description"}}</a>
{{if .CloudBrainPaySwitch}}
<div class="cloudbrain_resource_spec_blance_tip" style="padding:0 5px;margin:6px 0;margin-left:265px;font-size:12px;width: 50%!important;">
<div class="cloudbrain_resource_spec_blance_tip" style="padding:0 5px;margin:6px 0;margin-left:154px;font-size:12px;width:48.5%!important;">
<span>{{$.i18n.Tr "points.balance_of_points"}}<span style="color:red;margin: 0 3px">{{.PointAccount.Balance}}</span>{{$.i18n.Tr "points.points"}}</span><span>{{$.i18n.Tr "points.expected_time"}}<span style="color:red;margin: 0 3px" class="can-use-time"></span>{{$.i18n.Tr "points.hours"}}</span>
<span style="float:right;">
<i class="question circle icon link" data-position="right center" data-variation="mini"></i>


+ 3
- 0
templates/repo/cloudbrain/show.tmpl View File

@@ -111,7 +111,9 @@
<td class="ti-text-form-content">
<div class="text-span text-span-w" id="{{.VersionName}}-code">
{{.BranchName}}
{{if not .BootFile}}
<span style="margin-left:1rem" class="ui label">{{SubStr .CommitID 0 10}}</span>
{{end}}
</div>
</td>
</tr>
@@ -376,6 +378,7 @@
{{template "base/footer" .}}
<script src="{{StaticUrlPrefix}}/js/specsuse.js?v={{MD5 AppVer}}" type="text/javascript"></script>
<script>
$('.menu .item').tab()
$(document).ready(function () {
$('.ui.accordion').accordion({ selector: { trigger: '.icon' } });


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save
Baidu
map