diff --git a/charts/deployment.yaml b/charts/deployment.yaml
index 77b8c73..d7c9ba2 100644
--- a/charts/deployment.yaml
+++ b/charts/deployment.yaml
@@ -18,7 +18,7 @@ spec:
spec:
containers:
- name: datatunerx-ui
- image: release.daocloud.io/datatunerx/datatunerx-ui:v0.0.1-dev-abf7e99
+ image: release.daocloud.io/datatunerx/datatunerx-ui:v0.0.1-dev-fbada94
env:
- name: 'API_URL'
value: "https://10.33.1.10:6443"
diff --git a/doc/dak.md b/doc/dak.md
deleted file mode 100644
index ce3c23a..0000000
--- a/doc/dak.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# TODO
-
-## useQueryTable
-
-## Docker Image
-
-## Github Check
-
-## CI
-
-## unplugin-auto-import
-
-## I18n
-
-## 文件上传组件
-
-## tailwind CSS
diff --git a/samples/rayservice.yaml b/samples/rayservice.yaml
index 36ccfde..ec8718c 100644
--- a/samples/rayservice.yaml
+++ b/samples/rayservice.yaml
@@ -1,7 +1,7 @@
apiVersion: ray.io/v1
kind: RayService
metadata:
- name: finetune-sample5
+ name: finetune-sampleasdf
namespace: datatunerx-dev
labels:
createdByFrontend: "true"
diff --git a/src/App.vue b/src/App.vue
index a14d0c3..f822d54 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,5 +1,8 @@
-
-
-
+
+
+
+
diff --git a/src/api/ray-service.ts b/src/api/ray-service.ts
index e48e00a..7419d97 100644
--- a/src/api/ray-service.ts
+++ b/src/api/ray-service.ts
@@ -176,3 +176,8 @@ const apiVersion = 'ray.io/v1';
const kind = 'RayService';
export const rayServiceClient = new K8sClient(apiVersion, kind);
+
+export interface InferenceApplication {
+ name: string,
+ llmCheckpoint: string,
+}
diff --git a/src/components/AnakinHeader.vue b/src/components/AnakinHeader.vue
index 758641c..417ab71 100644
--- a/src/components/AnakinHeader.vue
+++ b/src/components/AnakinHeader.vue
@@ -1,33 +1,21 @@
@@ -58,7 +69,6 @@ const namespace = computed({
>
-
{{ operate.label }}
-
@@ -138,16 +141,6 @@ $datatunerx-header-color: var(--dao-navigation-090);
color: $datatunerx-header-color;
background-color: $datatunerx-header-background;
- &__product {
- width: 210px;
- /* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
- font-family: PingFang SC-Bold, PingFang SC;
- font-size: 26px;
- font-weight: bold;
- color: #fff;
- text-align: center;
- }
-
&__namespace {
margin-left: 30px;
font-size: 16px;
diff --git a/src/components/AnakinNav.vue b/src/components/AnakinNav.vue
index 697edd3..5fb1797 100644
--- a/src/components/AnakinNav.vue
+++ b/src/components/AnakinNav.vue
@@ -1,32 +1,50 @@
diff --git a/src/locales/en-US/views/InferenceApplication.json b/src/locales/en-US/views/InferenceApplication.json
index a6ea144..2aa0d45 100644
--- a/src/locales/en-US/views/InferenceApplication.json
+++ b/src/locales/en-US/views/InferenceApplication.json
@@ -36,5 +36,13 @@
"delete":{
"header": "Delete Inference Application",
"content": "Are you sure you want to delete this inference application?"
+ },
+
+ "create":{
+ "header": "Create Inference Application",
+ "name": "Name",
+ "llmCheckpoint": "Model",
+ "createSuccess": "Inference application created successfully",
+ "createFailed": "Failed to create inference application"
}
}
diff --git a/src/locales/zh-CN/views/InferenceApplication.json b/src/locales/zh-CN/views/InferenceApplication.json
index b29efcb..64d6dfc 100644
--- a/src/locales/zh-CN/views/InferenceApplication.json
+++ b/src/locales/zh-CN/views/InferenceApplication.json
@@ -36,5 +36,12 @@
"delete": {
"header": "删除推理应用",
"content": "确定要删除推理应用吗?"
+ },
+ "create": {
+ "header": "创建推理应用",
+ "name": "名称",
+ "llmCheckpoint": "模型",
+ "createSuccess": "推理应用创建成功",
+ "createFailed": "推理应用创建失败"
}
}
diff --git a/src/plugins/axios/client.ts b/src/plugins/axios/client.ts
index 41e8c9b..c06495e 100644
--- a/src/plugins/axios/client.ts
+++ b/src/plugins/axios/client.ts
@@ -1,5 +1,5 @@
import { DeleteOptions, ListMeta } from 'kubernetes-types/meta/v1';
-import { AxiosRequestConfig } from 'axios';
+import { AxiosRequestConfig, AxiosResponse } from 'axios';
import { OpPatch } from 'json-patch';
import httpClient from './index';
@@ -29,7 +29,7 @@ export class K8sClient {
list(namespace: string, config?: AxiosRequestConfig) {
const path = this.getPath(namespace);
- return this.httpClient.get>(path, config);
+ return this.httpClient.get, AxiosResponse>, D>(path, config);
}
create(namespace: string, data: T) {
diff --git a/src/router/index.ts b/src/router/index.ts
index df31119..c647b77 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -3,11 +3,11 @@ import {
createRouter, type RouteRecordRaw, type RouterHistory, type Router, createWebHistory,
} from 'vue-router';
import Guards from '@/router/guards/index';
+import RouterContent from '@/layout/RouterContent.vue';
+import ConsoleContainer from '@/layout/console-container.vue';
import Login from '@/views/login/Login.vue';
-import RouterContent from '@/views/RouterContent.vue';
-
import DatasetList from '@/views/dataset/DatasetList.vue';
import DatasetCreate from '@/views/dataset/DatasetCreate.vue';
import DatasetDetail from '@/views/dataset/DatasetDetail.vue';
@@ -31,108 +31,125 @@ const routes: Array = [
redirect: {
name: 'Login',
},
+ },
+ {
+ path: '/login',
+ name: 'Login',
+ component: Login,
+ },
+ {
+ path: '/ns',
+ name: 'ConsoleContainer',
+ component: ConsoleContainer,
children: [
{
- path: 'login',
- name: 'Login',
- component: Login,
- },
- {
- path: 'fine-tune',
+ path: ':ns',
component: RouterContent,
children: [
{
- path: '',
- name: 'FinetuneExperimentList',
- component: FinetuneExperimentList,
- },
- {
- path: 'create',
- name: 'FinetuneExperimentCreate',
- component: FinetuneExperimentCreate,
- },
- {
- path: ':name',
- name: 'FinetuneExperimentDetail',
- component: FinetuneExperimentDetail,
- },
- {
- path: ':name/job/:jobName',
- name: 'FinetuneExperimentJobDetail',
- component: FinetuneExperimentJobDetail,
- },
- ],
+ path: 'fine-tune',
+ component: RouterContent,
+ children: [
+ {
+ path: '',
+ name: 'FinetuneExperimentList',
+ component: FinetuneExperimentList,
+ },
+ {
+ path: 'create',
+ name: 'FinetuneExperimentCreate',
+ component: FinetuneExperimentCreate,
+ },
+ {
+ path: ':name',
+ name: 'FinetuneExperimentDetail',
+ component: FinetuneExperimentDetail,
+ },
+ {
+ path: ':name/job/:jobName',
+ name: 'FinetuneExperimentJobDetail',
+ component: FinetuneExperimentJobDetail,
+ },
+ ],
- },
- {
- path: 'finetune-registry',
- component: RouterContent,
- children: [
- {
- path: '',
- name: 'ModelRegistryList',
- component: ModelRegistryList,
- },
- ],
- },
- {
- path: 'datasets',
- component: RouterContent,
- children: [
- {
- path: '',
- name: 'DatasetList',
- component: DatasetList,
},
{
- path: 'create',
- name: 'DatasetCreate',
- component: DatasetCreate,
+ path: 'finetune-registry',
+ component: RouterContent,
+ children: [
+ {
+ path: '',
+ name: 'ModelRegistryList',
+ component: ModelRegistryList,
+ },
+ ],
},
{
- path: ':name',
- name: 'DatasetDetail',
- component: DatasetDetail,
+ path: 'datasets',
+ component: RouterContent,
+ children: [
+ {
+ path: '',
+ name: 'DatasetList',
+ component: DatasetList,
+ },
+ {
+ path: 'create',
+ name: 'DatasetCreate',
+ component: DatasetCreate,
+ },
+ {
+ path: ':name',
+ name: 'DatasetDetail',
+ component: DatasetDetail,
+ },
+ ],
},
- ],
- },
- {
- path: 'hyperparameter',
- component: RouterContent,
- children: [
{
- path: '',
- name: 'HyperparameterList',
- component: HyperparameterList,
- },
- {
- path: 'create',
- name: 'HyperparameterCreate',
- component: HyperparameterCreate,
- },
- {
- path: ':name',
- name: 'HyperparameterDetail',
- component: HyperparameterDetail,
- },
- ],
+ path: 'hyperparameter',
+ component: RouterContent,
+ children: [
+ {
+ path: '',
+ name: 'HyperparameterList',
+ component: HyperparameterList,
+ },
+ {
+ path: 'create',
+ name: 'HyperparameterCreate',
+ component: HyperparameterCreate,
+ },
+ {
+ path: ':name',
+ name: 'HyperparameterDetail',
+ component: HyperparameterDetail,
+ },
+ ],
- },
+ },
- {
- path: 'inference-application',
- component: RouterContent,
- children: [
{
- path: '',
- name: 'InferenceApplicationList',
- component: InferenceApplicationList,
+ path: 'inference-application',
+ component: RouterContent,
+ children: [
+ {
+ path: '',
+ name: 'InferenceApplicationList',
+ component: InferenceApplicationList,
+ },
+ ],
},
+
],
},
-
],
},
+ {
+ path: '/:pathMatch(.*)',
+ redirect: {
+ name: 'Login',
+ },
+ },
];
let router: Router | null = null;
diff --git a/src/stores/experiment.ts b/src/stores/experiment.ts
index 2cfa703..20b766e 100644
--- a/src/stores/experiment.ts
+++ b/src/stores/experiment.ts
@@ -90,6 +90,7 @@ export const useExperimentStore = defineStore('experiment', {
return stream?.read().then((result) => this.processText(result, buffer, utf8Decoder, stream));
})
.catch(() => {
+ /* eslint-disable no-console */
console.log('Error! Retrying in 5 seconds...');
setTimeout(() => this.streamUpdates(namespace, lastResourceVersion), 5000);
});
@@ -124,9 +125,10 @@ export const useExperimentStore = defineStore('experiment', {
(experiment) => experiment.metadata?.name !== event.object.metadata.name,
);
}
-
+ /* eslint-disable no-console */
console.log(event.type, event.object.metadata.name);
} catch (error) {
+ /* eslint-disable no-console */
console.log('Error while parsing', chunk, '\n', error);
}
});
diff --git a/src/stores/namespace.ts b/src/stores/namespace.ts
index 6b365e7..aa9da4a 100644
--- a/src/stores/namespace.ts
+++ b/src/stores/namespace.ts
@@ -27,6 +27,7 @@ export const useNamespaceStore = defineStore('namespace', {
nError(i18n.t('common.fetchFailed'), error);
}
},
+
setNamespace(val: string) {
localStorage.setItem(NAMESPACE, val);
this.namespace = val;
diff --git a/src/stores/user.ts b/src/stores/user.ts
index 6e72fd0..3f0d90b 100644
--- a/src/stores/user.ts
+++ b/src/stores/user.ts
@@ -1,8 +1,5 @@
import { defineStore } from 'pinia';
import { TOKEN } from '@/utils/constant';
-import { useNamespaceStore } from '@/stores/namespace';
-import { i18n } from '@/plugins/vue-i18n';
-import { nError } from '@/utils/useNoty';
import isEmpty from 'lodash/isEmpty';
export const useUserStore = defineStore('user', {
@@ -19,16 +16,6 @@ export const useUserStore = defineStore('user', {
return !isEmpty(this.token);
},
- async initView() {
- const namespaceStore = useNamespaceStore();
-
- try {
- await namespaceStore.fetchNamespace();
- } catch (error) {
- nError(i18n.t('common.fetchFailed'), error);
- }
- },
-
async login(val: string) {
this.setToken(val);
},
diff --git a/src/views/dataset/DatasetCreate.vue b/src/views/dataset/DatasetCreate.vue
index 910bb81..c9babea 100644
--- a/src/views/dataset/DatasetCreate.vue
+++ b/src/views/dataset/DatasetCreate.vue
@@ -22,7 +22,7 @@ import { useDataset } from './composition/dataset';
const { t } = useI18n();
-const namespaceStore = useNamespaceStore();
+const { namespace } = storeToRefs(useNamespaceStore());
const router = useRouter();
const { query } = useRoute();
@@ -34,7 +34,7 @@ const state = reactive({
});
const fetchPlugins = () => {
- dataPluginClient.list(namespaceStore.namespace).then(({ data }) => {
+ dataPluginClient.list(namespace.value).then(({ data }) => {
state.plugins = data.items;
});
};
@@ -133,7 +133,7 @@ const duplicateSubset = useFieldError('spec.datasetMetadata.datasetInfo.subsets'
onMounted(() => {
if (isUpdate.value) {
- fetchDataset(namespaceStore.namespace, query.name as string).then(() => {
+ fetchDataset(namespace.value, query.name as string).then(() => {
resetForm({ values: dataset.value });
});
}
@@ -203,25 +203,24 @@ const hasMarginBottom = computed(() => {
const toList = () => {
router.push({
name: 'DatasetList',
+ params: {
+ ns: namespace.value,
+ },
});
};
-// const onSubmit = () => {
-// validate().then((valid) => {
-// console.log('valid', valid);
-// });
-// };
+watch(namespace, toList);
const onSubmit = handleSubmit(async (values) => {
try {
if (isUpdate.value && values.metadata?.name) {
await datasetClient.update(
- namespaceStore.namespace,
+ namespace.value,
values.metadata?.name,
convertDatasetForPost(values),
);
} else {
- await datasetClient.create(namespaceStore.namespace, convertDatasetForPost(values));
+ await datasetClient.create(namespace.value, convertDatasetForPost(values));
}
nSuccess(
t('common.notySuccess', {
diff --git a/src/views/dataset/DatasetDetail.vue b/src/views/dataset/DatasetDetail.vue
index 15f961f..3343b7c 100644
--- a/src/views/dataset/DatasetDetail.vue
+++ b/src/views/dataset/DatasetDetail.vue
@@ -104,7 +104,10 @@ const onEdit = () => {
};
const toList = () => {
- router.push({ name: 'DatasetList' });
+ router.push({
+ name: 'DatasetList',
+ params: { ns: namespace.value },
+ });
};
watch(namespace, toList);
diff --git a/src/views/dataset/DatasetList.vue b/src/views/dataset/DatasetList.vue
index fbc8085..2963865 100644
--- a/src/views/dataset/DatasetList.vue
+++ b/src/views/dataset/DatasetList.vue
@@ -1,6 +1,6 @@
diff --git a/src/views/hyperparameter/HyperparameterList.vue b/src/views/hyperparameter/HyperparameterList.vue
index 5d8ab31..2565792 100644
--- a/src/views/hyperparameter/HyperparameterList.vue
+++ b/src/views/hyperparameter/HyperparameterList.vue
@@ -17,6 +17,19 @@ const { t } = useI18n();
const router = useRouter();
const { namespace } = storeToRefs(useNamespaceStore());
+const searchOptions = [
+ {
+ key: 'metadata.name',
+ label: t('views.Hyperparameter.name'),
+ single: true,
+ },
+ {
+ key: 'spec.objective.type',
+ label: t('views.Hyperparameter.fineTuningType'),
+ single: true,
+ },
+];
+
const columns = defineColumns([
{
id: 'name',
@@ -34,6 +47,7 @@ const columns = defineColumns([
{
id: 'createAt',
header: t('common.createTime'),
+ sortable: true,
},
{
id: 'action',
@@ -43,12 +57,11 @@ const columns = defineColumns([
]);
const {
- isLoading, pagedData, page, pageSize, total, handleRefresh, search,
-} = useQueryTable(async () => hyperparameterClient.list(namespace.value));
+ isLoading, pagedData, page, pageSize, total, handleRefresh, search, sort,
+} = useQueryTable(() => hyperparameterClient.list(namespace.value));
const { onConfirmDelete } = useDeleteHyperparameter(namespace, handleRefresh);
-// 监听命名空间变化,重新加载数据集
watch(namespace, handleRefresh);
const regroupParameters = (parameters: Parameters) => {
@@ -86,12 +99,14 @@ const onCreate = () => {
diff --git a/src/views/inference-application/InferenceApplicationCreate.vue b/src/views/inference-application/InferenceApplicationCreate.vue
new file mode 100644
index 0000000..c2921e6
--- /dev/null
+++ b/src/views/inference-application/InferenceApplicationCreate.vue
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/inference-application/InferenceApplicationList.vue b/src/views/inference-application/InferenceApplicationList.vue
index 320bf61..f136644 100644
--- a/src/views/inference-application/InferenceApplicationList.vue
+++ b/src/views/inference-application/InferenceApplicationList.vue
@@ -5,6 +5,8 @@ import {
import { useNamespaceStore } from '@/stores/namespace';
import { useQueryTable } from '@/hooks/useQueryTable';
import { defineColumns } from '@dao-style/core';
+import { useDateFormat } from '@dao-style/extend';
+
import ApplicationStatusComponent from './components/application-status.vue';
import { useDeleteInferenceApplication } from './composition/inference-application';
@@ -35,6 +37,7 @@ const columns = defineColumns([
{
id: 'createAt',
header: t('common.createTime'),
+ sortable: true,
},
{
id: 'action',
@@ -44,12 +47,10 @@ const columns = defineColumns([
]);
const {
- isLoading, pagedData, page, pageSize, total, handleRefresh, search,
-} = useQueryTable(async () => rayServiceClient.list(namespace.value));
+ isLoading, pagedData, page, pageSize, total, handleRefresh, search, sort,
+} = useQueryTable(() => rayServiceClient.list(namespace.value), { keys: ['status'] });
-watch(namespace, () => {
- handleRefresh();
-});
+watch(namespace, handleRefresh);
const { onConfirmDelete } = useDeleteInferenceApplication(namespace, handleRefresh);
@@ -81,9 +82,10 @@ const selectable = (row: RayService) => {
{
+
+
+ {{ useDateFormat(row.metadata?.creationTimestamp) }}
+
diff --git a/src/views/inference-application/composition/inference-application.ts b/src/views/inference-application/composition/inference-application.ts
index acfa41f..b180f54 100644
--- a/src/views/inference-application/composition/inference-application.ts
+++ b/src/views/inference-application/composition/inference-application.ts
@@ -1,6 +1,7 @@
-import { rayServiceClient, RayService } from '@/api/ray-service';
+import { rayServiceClient, RayService, InferenceApplication } from '@/api/ray-service';
import { createDialog } from '@dao-style/extend';
import ConfirmDeleteDialog from '@/components/ConfirmDeleteDialog.vue';
+import InferenceApplicationCreate from '../InferenceApplicationCreate.vue';
export function useDeleteInferenceApplication(namespace: Ref, handleRefresh: () => void) {
const { t } = useI18n();
@@ -22,3 +23,19 @@ export function useDeleteInferenceApplication(namespace: Ref, handleRefr
onConfirmDelete,
};
}
+
+export function useCreateInferenceApplication(handleRefresh: () => void) {
+ const onCreate = async (model:InferenceApplication) => {
+ const dialog = createDialog(InferenceApplicationCreate);
+
+ await dialog.show({
+ modelValue: model,
+ });
+
+ handleRefresh();
+ };
+
+ return {
+ onCreate,
+ };
+}
diff --git a/src/views/login/Login.vue b/src/views/login/Login.vue
index 089d82d..54056c0 100644
--- a/src/views/login/Login.vue
+++ b/src/views/login/Login.vue
@@ -23,14 +23,14 @@ const { handleSubmit } = useForm({
const onSubmit = handleSubmit(async (values) => {
await userStore.login(values.token);
router.push({
- name: 'FinetuneExperimentList',
+ name: 'ConsoleContainer',
});
});
onMounted(async () => {
if (loginSuccess.value) {
router.push({
- name: 'FinetuneExperimentList',
+ name: 'ConsoleContainer',
});
}
});
diff --git a/src/views/model-registry/ModelRegistryList.vue b/src/views/model-registry/ModelRegistryList.vue
index e967ef5..21acb8f 100644
--- a/src/views/model-registry/ModelRegistryList.vue
+++ b/src/views/model-registry/ModelRegistryList.vue
@@ -8,18 +8,19 @@ import ConfirmDeleteDialog from '@/components/ConfirmDeleteDialog.vue';
import CardLayoutContainer from '@/components/CardLayoutContainer.vue';
import ModelCard from './components/ModelCard.vue';
+import { useCreateInferenceApplication } from '../inference-application/composition/inference-application';
const { namespace } = storeToRefs(useNamespaceStore());
const { t } = useI18n();
const {
isLoading, pagedData, page, pageSize, total, handleRefresh, search,
-} = useQueryTable(
- async () => llmCheckpointClient.list(namespace.value),
-);
+} = useQueryTable(() => llmCheckpointClient.list(namespace.value));
watch(namespace, handleRefresh);
+const { onCreate } = useCreateInferenceApplication(handleRefresh);
+
const deleteFn = (name: string) => llmCheckpointClient.delete(namespace.value, name).then(() => {
handleRefresh();
});
@@ -43,7 +44,7 @@ const onConfirmDelete = (name: string) => {
:title="$t('views.ModelRegistry.modelRegistry')"
/>
@@ -55,6 +56,7 @@ const onConfirmDelete = (name: string) => {
:key="registry.metadata?.name"
:data="registry"
@on-delete="onConfirmDelete"
+ @on-create="onCreate"
/>
diff --git a/src/views/model-registry/components/ModelCard.vue b/src/views/model-registry/components/ModelCard.vue
index 861d376..a72d7c9 100644
--- a/src/views/model-registry/components/ModelCard.vue
+++ b/src/views/model-registry/components/ModelCard.vue
@@ -1,7 +1,5 @@