diff --git a/index.html b/index.html
index 9ea8def296..a5aab2968a 100644
--- a/index.html
+++ b/index.html
@@ -32,8 +32,8 @@
NODE_ENV: 'production'
}
};
- globalThis.packageVersion = "24.09.0-alpha.1";
- globalThis.buildNumber = "6011";
+ globalThis.packageVersion = "25.1.0-alpha.1";
+ globalThis.buildNumber = "6441";
diff --git a/manifest.json b/manifest.json
index ea4a8b3a3d..191cb43f3b 100644
--- a/manifest.json
+++ b/manifest.json
@@ -3,7 +3,7 @@
"manifest_version": 9,
"name": "Backend.AI Web UI",
"short_name": "BackendAIWebUI",
- "version": "24.09.0-alpha.1",
+ "version": "25.1.0-alpha.1",
"start_url": "/",
"display": "standalone",
"background_color": "#fff",
diff --git a/package.json b/package.json
index 46ae97c2e4..d04c7c752c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "backend.ai-webui",
"productName": "Backend.AI Desktop",
- "version": "24.09.0-alpha.1",
+ "version": "25.1.0-alpha.1",
"repository": "https://github.com/lablup/backend.ai-webui.git",
"author": "Lablup Inc. ",
"license": "LGPL-3.0-or-later",
diff --git a/react/package.json b/react/package.json
index 5bedcca981..7178df7bd4 100644
--- a/react/package.json
+++ b/react/package.json
@@ -1,6 +1,6 @@
{
"name": "backend-ai-webui-react",
- "version": "24.09.0-alpha.1",
+ "version": "25.1.0-alpha.1",
"private": true,
"dependencies": {
"@ai-sdk/openai": "^1.0.11",
diff --git a/react/src/App.tsx b/react/src/App.tsx
index 98b76919d6..d87a54a9e5 100644
--- a/react/src/App.tsx
+++ b/react/src/App.tsx
@@ -64,7 +64,13 @@ const ComputeSessionList = React.lazy(
() => import('./components/ComputeSessionList'),
);
const AgentSummaryPage = React.lazy(() => import('./pages/AgentSummaryPage'));
-
+/**
+ * Pages for Model Player
+ */
+const PlaygroundPage = React.lazy(
+ () => import('./components/lablupTalkativotUI/LLMPlaygroundPage'),
+);
+const ModelStorePage = React.lazy(() => import('./pages/ModelStorePage'));
interface CustomHandle {
title?: string;
labelKey?: string;
@@ -106,17 +112,17 @@ const router = createBrowserRouter([
children: [
{
path: '/',
- element: ,
+ element: ,
},
{
//for electron dev mode
path: '/build/electron-app/app/index.html',
- element: ,
+ element: ,
},
{
//for electron prod mode
path: '/app/index.html',
- element: ,
+ element: ,
},
{
path: '/summary',
@@ -359,6 +365,19 @@ const router = createBrowserRouter([
path: '*',
element: <>>,
},
+ /**
+ * Pages for Model Player
+ */
+ {
+ path: '/playground',
+ handle: { labelKey: 'webui.menu.Playground' },
+ Component: PlaygroundPage,
+ },
+ {
+ path: '/model-store',
+ handle: { labelKey: 'webui.menu.ModelStore' },
+ Component: ModelStorePage,
+ },
],
},
]);
diff --git a/react/src/components/BAIIcons/VLLMIcon.tsx b/react/src/components/BAIIcons/VLLMIcon.tsx
new file mode 100644
index 0000000000..feaf304d7f
--- /dev/null
+++ b/react/src/components/BAIIcons/VLLMIcon.tsx
@@ -0,0 +1,23 @@
+import { ReactComponent as logo } from './vllm-color.svg';
+import Icon from '@ant-design/icons';
+import { CustomIconComponentProps } from '@ant-design/icons/lib/components/Icon';
+
+interface CustomIconProps
+ extends Omit {
+ size?: number;
+}
+
+const VLLMIcon: React.FC = (props) => {
+ return (
+
+ );
+};
+
+export default VLLMIcon;
diff --git a/react/src/components/BAIIcons/vllm-color.svg b/react/src/components/BAIIcons/vllm-color.svg
new file mode 100644
index 0000000000..54acc3de2d
--- /dev/null
+++ b/react/src/components/BAIIcons/vllm-color.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/react/src/components/ChatContent.tsx b/react/src/components/ChatContent.tsx
new file mode 100644
index 0000000000..ff6f8f159c
--- /dev/null
+++ b/react/src/components/ChatContent.tsx
@@ -0,0 +1,122 @@
+import { useTanQuery } from '../hooks/reactQueryAlias';
+import { ChatContentEndpointDetailQuery } from './__generated__/ChatContentEndpointDetailQuery.graphql';
+import { Model } from './lablupTalkativotUI/ChatUIModal';
+import LLMChatCard from './lablupTalkativotUI/LLMChatCard';
+import { ReloadOutlined } from '@ant-design/icons';
+import { Alert, Button } from 'antd';
+import graphql from 'babel-plugin-relay/macro';
+import _ from 'lodash';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useLazyLoadQuery } from 'react-relay/hooks';
+
+interface ChatContentProps {
+ endpointId: string;
+ endpointUrl: string;
+ basePath: string;
+}
+
+const ChatContent: React.FC = ({
+ endpointId,
+ endpointUrl,
+ basePath,
+}) => {
+ const { t } = useTranslation();
+
+ const { endpoint_token_list } =
+ useLazyLoadQuery(
+ graphql`
+ query ChatContentEndpointDetailQuery(
+ $endpointId: UUID!
+ $tokenListOffset: Int!
+ $tokenListLimit: Int!
+ ) {
+ endpoint_token_list(
+ limit: $tokenListLimit
+ offset: $tokenListOffset
+ endpoint_id: $endpointId
+ ) {
+ total_count
+ items {
+ id
+ token
+ endpoint_id
+ created_at
+ valid_until
+ }
+ }
+ }
+ `,
+ {
+ tokenListLimit: 100,
+ tokenListOffset: 0,
+ endpointId: endpointId as string,
+ },
+ {
+ fetchPolicy: 'network-only',
+ },
+ );
+
+ const newestValidToken =
+ _.orderBy(endpoint_token_list?.items, ['valid_until'], ['desc'])[0]
+ ?.token ?? '';
+
+ const {
+ data: modelsResult,
+ // error,
+ refetch,
+ } = useTanQuery<{
+ data: Array;
+ }>({
+ queryKey: ['models', endpointUrl],
+ queryFn: () => {
+ return fetch(new URL(basePath + '/models', endpointUrl).toString(), {
+ headers: {
+ Authorization: `BackendAI ${newestValidToken}`,
+ },
+ })
+ .then((res) => res.json())
+ .catch((err) => {
+ console.log(err);
+ });
+ },
+ });
+
+ return (
+ ({
+ id: m.id,
+ name: m.id,
+ }))}
+ apiKey={newestValidToken}
+ fetchOnClient
+ style={{ flex: 1 }}
+ allowCustomModel={false}
+ alert={
+ _.isEmpty(modelsResult?.data) && (
+ }
+ onClick={() => {
+ refetch();
+ }}
+ >
+ {t('button.Refresh')}
+
+ }
+ />
+ )
+ }
+ modelId={modelsResult?.data?.[0].id ?? 'custom'}
+ modelToken={newestValidToken}
+ />
+ );
+};
+
+export default ChatContent;
diff --git a/react/src/components/ImportFromHuggingFacePanel.tsx b/react/src/components/ImportFromHuggingFacePanel.tsx
new file mode 100644
index 0000000000..2f3638499b
--- /dev/null
+++ b/react/src/components/ImportFromHuggingFacePanel.tsx
@@ -0,0 +1,61 @@
+import Flex from '../components/Flex';
+import BAICard from './BAICard';
+import { App, Button, Input, theme } from 'antd';
+import type { GetProps } from 'antd';
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+const ImportFromHuggingFacePanel: React.FC = () => {
+ const { t } = useTranslation();
+ const { token } = theme.useToken();
+ const { message } = App.useApp();
+ const [search, setSearch] = useState('');
+ type SearchProps = GetProps;
+
+ const { Search } = Input;
+ const onSearch: SearchProps['onSearch'] = (value, _e, info) => {
+ // TODO: download model from hugging face by URL
+ setSearch(value);
+ };
+
+ return (
+
+
+ {
+ message.info({
+ key: 'import-from-hugging-face',
+ content: 'Only available for administrators.',
+ });
+ }}
+ // FIXME: Temporary use hardcoded color for the button background
+ style={{ color: token.colorBgBase, backgroundColor: '#FF7A00' }}
+ >
+ Download
+
+ }
+ size="large"
+ onSearch={onSearch}
+ />
+
+
+ );
+};
+
+export default ImportFromHuggingFacePanel;
diff --git a/react/src/components/MainLayout/WebUISider.tsx b/react/src/components/MainLayout/WebUISider.tsx
index 5e4eb9c145..026ad52b8a 100644
--- a/react/src/components/MainLayout/WebUISider.tsx
+++ b/react/src/components/MainLayout/WebUISider.tsx
@@ -16,6 +16,7 @@ import WebUILink from '../WebUILink';
import { PluginPage, WebUIPluginType } from './MainLayout';
import {
ApiOutlined,
+ AppstoreOutlined,
BarChartOutlined,
CloudUploadOutlined,
ControlOutlined,
@@ -24,6 +25,7 @@ import {
FileDoneOutlined,
HddOutlined,
InfoCircleOutlined,
+ MessageOutlined,
SolutionOutlined,
ToolOutlined,
UserOutlined,
@@ -85,67 +87,86 @@ const WebUISider: React.FC = (props) => {
const primaryColors = usePrimaryColors();
const generalMenu = filterEmptyItem([
+ // {
+ // label: {t('webui.menu.Summary')},
+ // icon: ,
+ // key: 'summary',
+ // },
+ // {
+ // label: {t('webui.menu.Sessions')},
+ // icon: ,
+ // key: 'job',
+ // },
{
- label: {t('webui.menu.Summary')},
- icon: ,
- key: 'summary',
- },
- {
- label: {t('webui.menu.Sessions')},
- icon: ,
- key: 'job',
- },
- supportServing && {
- label: {t('webui.menu.Serving')},
- icon: ,
- key: 'serving',
- },
- {
- label: {t('webui.menu.Import&Run')},
- icon: ,
- key: 'import',
- },
- {
- label: {t('webui.menu.Data&Storage')},
- icon: ,
- key: 'data',
- },
- supportUserCommittedImage && {
label: (
-
- {t('webui.menu.MyEnvironments')}
-
+ {t('webui.menu.Playground')}
),
- icon: ,
- key: 'my-environment',
+ icon: ,
+ key: 'playground',
},
- !isHideAgents && {
+ {
label: (
-
- {t('webui.menu.AgentSummary')}
-
+ {t('webui.menu.ModelStore')}
),
- icon: ,
- key: 'agent-summary',
+ icon: ,
+ key: 'model-store',
},
- {
+ supportServing && {
label: (
- {t('webui.menu.Statistics')}
+ {t('modelserving.menu.MyServices')}
),
- icon: ,
- key: 'statistics',
- },
- !!fasttrackEndpoint && {
- label: t('webui.menu.FastTrack'),
- icon: ,
- key: 'pipeline',
- onClick: () => {
- window.open(fasttrackEndpoint, '_blank', 'noopener noreferrer');
- },
+ icon: ,
+ key: 'serving',
},
+ // {
+ // label: {t('webui.menu.Import&Run')},
+ // icon: ,
+ // key: 'import',
+ // },
+ // {
+ // label: (
+ // {t('modelserving.menu.ModelList')}
+ // ),
+ // icon: ,
+ // key: 'data',
+ // },
+ // supportUserCommittedImage && {
+ // label: (
+ //
+ // {t('webui.menu.MyEnvironments')}
+ //
+ // ),
+ // icon: ,
+ // key: 'my-environment',
+ // },
+ // !isHideAgents && {
+ // label: (
+ //
+ // {t('webui.menu.AgentSummary')}
+ //
+ // ),
+ // icon: ,
+ // key: 'agent-summary',
+ // },
+ // {
+ // label: (
+ // {t('webui.menu.Statistics')}
+ // ),
+ // icon: ,
+ // key: 'statistics',
+ // },
+ // !!fasttrackEndpoint && {
+ // label: t('webui.menu.FastTrack'),
+ // icon: ,
+ // key: 'pipeline',
+ // onClick: () => {
+ // window.open(fasttrackEndpoint, '_blank', 'noopener noreferrer');
+ // },
+ // },
]);
- const adminMenu: MenuProps['items'] = [
+ const adminMenu: MenuProps['items'] = [];
+ /*[
{
label: {t('webui.menu.Users')},
icon: ,
@@ -168,8 +189,10 @@ const WebUISider: React.FC = (props) => {
key: 'resource-policy',
},
];
+ */
- const superAdminMenu: MenuProps['items'] = [
+ const superAdminMenu: MenuProps['items'] = [];
+ /*[
{
label: {t('webui.menu.Resources')},
icon: ,
@@ -196,9 +219,7 @@ const WebUISider: React.FC = (props) => {
icon: ,
key: 'information',
},
- ];
-
- const pluginMap: Record = {
+ ]*/ const pluginMap: Record = {
'menuitem-user': generalMenu,
'menuitem-admin': adminMenu,
'menuitem-superadmin': superAdminMenu,
@@ -255,7 +276,7 @@ const WebUISider: React.FC = (props) => {
height: themeConfig?.logo?.size?.height || 24,
cursor: 'pointer',
}}
- onClick={() => webuiNavigate(themeConfig?.logo?.href || '/summary')}
+ onClick={() => webuiNavigate(themeConfig?.logo?.href || '/serving')}
/>
}
theme={currentSiderTheme}
@@ -275,7 +296,7 @@ const WebUISider: React.FC = (props) => {
height: themeConfig?.logo.sizeCollapsed?.height ?? 24,
cursor: 'pointer',
}}
- onClick={() => webuiNavigate(themeConfig?.logo?.href || '/summary')}
+ onClick={() => webuiNavigate(themeConfig?.logo?.href || '/serving')}
/>
}
logoTitle={themeConfig?.logo?.logoTitle || siteDescription || 'WebUI'}
@@ -340,6 +361,7 @@ const WebUISider: React.FC = (props) => {
]}
items={
// TODO: add plugin menu
+ /*
currentUserRole === 'superadmin'
? [
{
@@ -381,6 +403,8 @@ const WebUISider: React.FC = (props) => {
},
]
: []
+ */
+ []
}
/>
diff --git a/react/src/components/ModelCardChat.tsx b/react/src/components/ModelCardChat.tsx
new file mode 100644
index 0000000000..cd4728e443
--- /dev/null
+++ b/react/src/components/ModelCardChat.tsx
@@ -0,0 +1,111 @@
+import { useUpdatableState } from '../hooks';
+import ChatContent from './ChatContent';
+import { ModelCardChatQuery } from './__generated__/ModelCardChatQuery.graphql';
+import { Alert, Card, theme } from 'antd/lib';
+import graphql from 'babel-plugin-relay/macro';
+import _ from 'lodash';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useLazyLoadQuery } from 'react-relay';
+
+// TODO: fetch endpoint list, filter endpoint by name and send it ot LLMChatCard
+
+interface ModelCardChatProps {
+ modelName?: string;
+ basePath?: string;
+}
+
+const ModelCardChat: React.FC = ({
+ modelName,
+ basePath = 'v1',
+}) => {
+ const { t } = useTranslation();
+ const { token } = theme.useToken();
+ const [fetchKey, updateFetchKey] = useUpdatableState('first');
+
+ const { endpoint_list } = useLazyLoadQuery(
+ graphql`
+ query ModelCardChatQuery(
+ $offset: Int!
+ $limit: Int!
+ $filter: String
+ $projectID: UUID
+ ) {
+ endpoint_list(
+ offset: $offset
+ limit: $limit
+ project: $projectID
+ filter: $filter
+ ) {
+ items {
+ name
+ endpoint_id
+ url
+ model
+ status
+ }
+ }
+ }
+ `,
+ {
+ limit: 100,
+ offset: 0,
+ filter: `name ilike "%${modelName}%"`,
+ },
+ {
+ fetchPolicy: 'network-only',
+ fetchKey,
+ },
+ );
+
+ const healthyEndpoint = _.filter(endpoint_list?.items, (item) => {
+ return item?.status == 'HEALTHY';
+ });
+
+ // FIXME: temporally render chat UI only if at least one endpoint is healthy.
+ return healthyEndpoint.length > 0 ? (
+
+ ) : (
+ ,
+ ]}
+ />
+ );
+};
+
+export default ModelCardChat;
diff --git a/react/src/components/ModelCardModal.tsx b/react/src/components/ModelCardModal.tsx
index 9e22386ab7..80f149b120 100644
--- a/react/src/components/ModelCardModal.tsx
+++ b/react/src/components/ModelCardModal.tsx
@@ -1,27 +1,33 @@
import { useBackendAIImageMetaData } from '../hooks';
+import { useUpdatableState } from '../hooks';
import BAIModal, { BAIModalProps } from './BAIModal';
import Flex from './Flex';
+import ModelCardChat from './ModelCardChat';
import ModelCloneModal from './ModelCloneModal';
+import ModelTryContent from './ModelTryContent';
import ResourceNumber from './ResourceNumber';
import { ModelCardModalFragment$key } from './__generated__/ModelCardModalFragment.graphql';
-import { BankOutlined, CopyOutlined, FileOutlined } from '@ant-design/icons';
+import { BankOutlined, FileOutlined } from '@ant-design/icons';
import {
Alert,
Button,
Card,
Col,
Descriptions,
+ Divider,
Empty,
Grid,
Row,
Tag,
Typography,
+ Tabs,
theme,
+ Skeleton,
} from 'antd';
import graphql from 'babel-plugin-relay/macro';
import dayjs from 'dayjs';
-import _ from 'lodash';
-import { Cog, FolderX } from 'lucide-react';
+import _, { head } from 'lodash';
+import { FolderX } from 'lucide-react';
import Markdown from 'markdown-to-jsx';
import React, { Suspense, useState } from 'react';
import { useTranslation } from 'react-i18next';
@@ -29,6 +35,7 @@ import { useFragment } from 'react-relay';
interface ModelCardModalProps extends BAIModalProps {
modelCardModalFrgmt?: ModelCardModalFragment$key | null;
+ // basePath?: string;
onRequestClose: () => void;
}
const ModelCardModal: React.FC = ({
@@ -130,269 +137,341 @@ const ModelCardModal: React.FC = ({
,
]}
>
- {model_card?.error_msg ? (
-
-
-
-
- ) : (
- <>
-
-
- {model_card?.category && (
-
- {model_card?.category}
-
- )}
- {model_card?.task && (
- }>
+
- {model_card?.task}
-
- )}
- {model_card?.label &&
- _.map(model_card?.label, (label) => (
-
- {label}
-
- ))}
- {model_card?.license && (
- }
- bordered={false}
- color="geekblue"
- style={{ marginRight: 0 }}
+
+
+
+
+
+
+
+
+ ),
+ },
+ {
+ key: 'modelcard',
+ label: t('modelStore.ModelCard'),
+ children: model_card?.error_msg ? (
+
+
+
+
+ ) : (
+ <>
+
- {model_card?.license}
-
- )}
-
-
- {/* }
- size="small"
- disabled
- >
- {t('button.Download')}
- */}
- }>
- {t('modelStore.FinetuneModel')}
-
- }
- size="small"
- disabled={!model_card?.vfolder?.cloneable}
- onClick={() => {
- // const event = new CustomEvent('backend-ai-vfolder-cloning', {
- // detail: {
- // // TODO: change this to vfolder name
- // name: mode_card?.name,
- // },
- // });
- // onRequestClose();
- // document.dispatchEvent(event);
- setVisibleCloneModal(true);
- }}
- >
- {t('modelStore.CloneToFolder')}
-
-
-
-
-
-
- {!!model_card?.description ? (
- <>
-
- {t('modelStore.Description')}
-
-
+ {model_card?.category && (
+
+ {model_card?.category}
+
+ )}
+ {model_card?.task && (
+
+ {model_card?.task}
+
+ )}
+ {model_card?.label &&
+ _.map(model_card?.label, (label) => (
+
+ {label}
+
+ ))}
+ {model_card?.license && (
+ }
+ bordered={false}
+ color="geekblue"
+ style={{ marginRight: 0 }}
+ >
+ {model_card?.license}
+
+ )}
+
+
+ {/* }
+ size="small"
+ disabled
+ >
+ {t('button.Download')}
+ */}
+ {/* }>
+ {t('modelStore.FinetuneModel')}
+
+ }
size="small"
- style={{
- whiteSpace: 'pre-wrap',
- minHeight: screen.lg ? 100 : undefined,
- height: screen.lg ? 'calc(100vh - 590px)' : undefined,
- maxHeight: 'calc(100vh - 590px)',
- overflow: 'auto',
+ disabled={!model_card?.vfolder?.cloneable}
+ onClick={() => {
+ // const event = new CustomEvent('backend-ai-vfolder-cloning', {
+ // detail: {
+ // // TODO: change this to vfolder name
+ // name: mode_card?.name,
+ // },
+ // });
+ // onRequestClose();
+ // document.dispatchEvent(event);
+ setVisibleCloneModal(true);
}}
>
- (
-
- ),
- }}
- >
- {model_card?.description}
-
-
- >
- ) : null}
-
- {_.map(
- _.filter(
- _.castArray(model_card?.framework),
- (v) => !_.isEmpty(v),
+ {t('modelStore.CloneToFolder')}
+ */}
+
+
+
+
+
+ {!!model_card?.description ? (
+ <>
+
+ {t('modelStore.Description')}
+
+
+ (
+
+ ),
+ }}
+ >
+ {model_card?.description}
+
+
+ >
+ ) : null}
+
+ {_.map(
+ _.filter(
+ _.castArray(model_card?.framework),
+ (v) => !_.isEmpty(v),
+ ),
+ (framework, index) => {
+ const targetImageKey = framework?.replace(
+ /\s*\d+\s*$/,
+ '',
+ );
+ const imageInfo = _.find(
+ metadata?.imageInfo,
+ (imageInfo) =>
+ imageInfo?.name === targetImageKey,
+ );
+ const uniqueKey = `${framework}-${index}`;
+ return imageInfo?.icon ? (
+
+
+ {framework}
+
+ ) : (
+
+ {framework}
+
+ );
+ },
+ )}
+
),
- (framework, index) => {
- const targetImageKey = framework?.replace(
- /\s*\d+\s*$/,
- '',
- );
- const imageInfo = _.find(
- metadata?.imageInfo,
- (imageInfo) =>
- imageInfo?.name === targetImageKey,
- );
- const uniqueKey = `${framework}-${index}`;
- return imageInfo?.icon ? (
-
-
- {framework}
-
- ) : (
-
- {framework}
-
- );
- },
- )}
-
- ),
- },
- {
- key: 'created',
- label: t('modelStore.Created'),
- children: dayjs(model_card?.created_at).format('lll'),
- },
- {
- key: 'last_modified',
- label: t('modelStore.LastModified'),
- children: dayjs(model_card?.modified_at).format('lll'),
- },
- {
- key: 'min_resource',
- label: t('modelStore.MinResource'),
- children: (
-
- {model_card?.min_resource &&
- _.map(
- JSON.parse(model_card?.min_resource),
- (value, type) => {
- return (
-
- );
- },
- )}
-
- ),
- },
- ]}
- />
-
-
- {!!model_card?.readme ? (
-
-
-
- README.md
+ },
+ {
+ key: 'created',
+ label: t('modelStore.Created'),
+ children: dayjs(model_card?.created_at).format(
+ 'lll',
+ ),
+ },
+ {
+ key: 'last_modified',
+ label: t('modelStore.LastModified'),
+ children: dayjs(model_card?.modified_at).format(
+ 'lll',
+ ),
+ },
+ {
+ key: 'min_resource',
+ label: t('modelStore.MinResource'),
+ children: (
+
+ {model_card?.min_resource &&
+ _.map(
+ JSON.parse(model_card?.min_resource),
+ (value, type) => {
+ return (
+
+ );
+ },
+ )}
+
+ ),
+ },
+ ]}
+ />
- }
- styles={{
- body: {
- padding: token.paddingLG,
- overflow: 'auto',
- height: screen.lg ? 'calc(100vh - 287px)' : undefined,
- minHeight: 200,
- },
- }}
- >
- {model_card?.readme || ''}
-
-
- ) : null}
-
- >
- )}
+
+ {!!model_card?.readme ? (
+
+
+
+ README.md
+
+ }
+ styles={{
+ body: {
+ padding: token.paddingLG,
+ overflow: 'auto',
+ height: screen.lg
+ ? 'calc(100vh - 287px)'
+ : undefined,
+ minHeight: 200,
+ },
+ }}
+ >
+ {model_card?.readme || ''}
+
+
+ ) : null}
+
+ >
+ ),
+ },
+ ]}
+ />
= ({
+ modelName,
+ modelStorageHost,
+ minAIAcclResource,
+ title,
+ ...props
+}) => {
+ const { t } = useTranslation();
+ const { token } = theme.useToken();
+ const baiClient = useSuspendedBackendaiClient();
+ const baiRequestWithPromise = useBaiSignedRequestWithPromise();
+ const currentDomain = useCurrentDomainValue();
+ const currentProject = useCurrentProjectValue();
+ const currentResourceGroupByProject = useCurrentResourceGroupValue();
+ const [fetchKey, updateFetchKey] = useUpdatableState('first');
+ const { upsertNotification } = useSetBAINotification();
+
+ const { data: allFolderList } = useSuspenseTanQuery({
+ queryKey: ['allFolderList', fetchKey, currentProject.id],
+ queryFn: () => {
+ const search = new URLSearchParams();
+ search.set('group_id', currentProject.id);
+ return baiRequestWithPromise({
+ method: 'GET',
+ url: `/folders?${search.toString()}`,
+ }) as Promise;
+ },
+ staleTime: 1000,
+ });
+
+ const { data: accessibleStorageHostList } = useSuspenseTanQuery({
+ queryKey: ['accessibleStorageHostList', fetchKey, currentProject.id],
+ queryFn: () => {
+ return baiRequestWithPromise({
+ method: 'GET',
+ url: `/folders/_/hosts`,
+ });
+ },
+ staleTime: 1000,
+ });
+
+ const lowestUsageHost = _.minBy(
+ _.map(accessibleStorageHostList?.allowed, (host) => ({
+ host,
+ volume_info: accessibleStorageHostList?.volume_info?.[host],
+ })),
+ 'volume_info.usage.percentage',
+ )?.host;
+
+ const myModelStoreList = _.filter(
+ allFolderList,
+ (vFolder) =>
+ vFolder.ownership_type === 'user' && vFolder.usage_mode === 'model',
+ );
+
+ const filteredModelStoreList = myModelStoreList.filter((vFolder) =>
+ vFolder.name.includes(modelName || ''),
+ );
+
+ const mutationToClone = useTanMutation<
+ {
+ bgtask_id: string;
+ id: string;
+ },
+ { type?: string; title?: string; message?: string },
+ {
+ input: any;
+ name: string;
+ }
+ >({
+ // @ts-ignore
+ mutationFn: ({ input, name }: { input: any; name: string }) => {
+ return baiClient.vfolder.clone(input, name);
+ },
+ });
+
+ const { data: availableRuntimes } = useSuspenseTanQuery<{
+ runtimes: { name: string; human_readable_name: string }[];
+ }>({
+ queryKey: ['baiClient.modelService.runtime.list'],
+ queryFn: () => {
+ return baiClient.isManagerVersionCompatibleWith('24.03.5')
+ ? baiRequestWithPromise({
+ method: 'GET',
+ url: `/services/_/runtimes`,
+ })
+ : Promise.resolve({
+ runtimes: [
+ {
+ name: 'custom',
+ human_readable_name: 'Custom (Default)',
+ },
+ ],
+ });
+ },
+ staleTime: 1000,
+ });
+
+ const mutationToCreateService = useTanMutation<
+ unknown,
+ {
+ message?: string;
+ },
+ ServiceLauncherFormValue
+ >({
+ mutationFn: (values) => {
+ const environ: { [key: string]: string } = {};
+ if (values.envvars) {
+ values.envvars.forEach((v) => (environ[v.variable] = v.value));
+ }
+ const body: ServiceCreateType = {
+ name: values.serviceName,
+ desired_session_count: values.desiredRoutingCount,
+ image:
+ `${values.environments.image?.registry}/${values.environments.image?.name}:${values.environments.image?.tag}` as string,
+ architecture: values.environments.image?.architecture as string,
+ // FIXME: hardcode this part by selected option (vLLM, NIM, Custom)
+ // ...getImageInfoFromInputInCreating(
+ // checkManualImageAllowed(
+ // baiClient._config.allow_manual_image_name_for_session,
+ // values.environments?.manual,
+ // ),
+ // values,
+ // ),
+ runtime_variant: values.runtimeVariant,
+ group: baiClient.current_group, // current Project Group,
+ domain: currentDomain, // current Domain Group,
+ cluster_size: values.cluster_size,
+ cluster_mode: values.cluster_mode,
+ open_to_public: values.openToPublic,
+ config: {
+ model: values.vFolderID,
+ model_version: 1, // FIXME: hardcoded. change it with option later
+ model_mount_destination: '/models', // FIXME: hardcoded. change it with option later
+ environ, // FIXME: hardcoded. change it with option later
+ scaling_group: 'nvidia-H100', // FIXME: hardcoded. change it with option later as well, values.resourceGroup,
+ resources: {
+ // FIXME: manually convert to string since server-side only allows [str,str] tuple
+ cpu: values.resource.cpu.toString(),
+ mem: values.resource.mem,
+ ...(values.resource.accelerator > 0
+ ? {
+ [values.resource.acceleratorType]:
+ // FIXME: manually convert to string since server-side only allows [str,str] tuple
+ values.resource.accelerator.toString(),
+ }
+ : undefined),
+ },
+ resource_opts: {
+ shmem:
+ compareNumberWithUnits(values.resource.mem, '4g') > 0 &&
+ compareNumberWithUnits(values.resource.shmem, '1g') < 0
+ ? '1g'
+ : values.resource.shmem,
+ },
+ },
+ };
+ return baiSignedRequestWithPromise({
+ method: 'POST',
+ url: '/services',
+ body,
+ client: baiClient,
+ });
+ },
+ });
+
+ const getServiceInputByRuntimeVariant = (
+ runtimeVariant: string,
+ vfolderID: string,
+ ): ServiceLauncherFormValue => {
+ const model = modelName?.includes('stable-diffusion-3-medium')
+ ? 'stable-diffusion-3m'
+ : modelName;
+ return {
+ serviceName: `${model}-${generateRandomString(4)}`,
+ desiredRoutingCount: 1,
+ // FIXME: hard-coded images for vLLM, NIM, Custom
+ environments: {
+ image: {
+ registry: 'cr.backend.ai',
+ name: (() => {
+ if (modelName?.includes('stable-diffusion')) {
+ return 'testing/ngc-pytorch';
+ }
+ switch (runtimeVariant) {
+ case 'nim':
+ return 'testing/ngc-nim';
+ case 'vllm':
+ case 'custom':
+ default:
+ return 'testing/vllm';
+ }
+ })(),
+ tag: (() => {
+ if (modelName?.includes('stable-diffusion')) {
+ return '24.07-pytorch2.4-py310-cuda12.5';
+ }
+ switch (runtimeVariant) {
+ case 'vllm':
+ case 'custom':
+ default:
+ return '0.6.2-cuda12.1-ubuntu22.04';
+ case 'nim':
+ return 'ngc-nim:1.0.0-llama3.8b-h100x1-fp16';
+ }
+ })(),
+ architecture: 'x86_64',
+ base_image_name: undefined,
+ digest: undefined,
+ humanized_name: undefined,
+ id: undefined,
+ installed: undefined,
+ labels: undefined,
+ namespace: undefined,
+ resource_limits: undefined,
+ tags: undefined,
+ version: undefined,
+ },
+ environment: '',
+ version: '',
+ },
+ // FIXME: temporally hard-coded runtime variant
+ runtimeVariant: modelName?.includes('stable-diffusion')
+ ? 'custom'
+ : runtimeVariant,
+ cluster_size: 1,
+ cluster_mode: 'single-node',
+ openToPublic: true,
+ resourceGroup: currentResourceGroupByProject as string,
+ resource: {
+ cpu: 4,
+ mem: '32g',
+ accelerator: minAIAcclResource,
+ acceleratorType: 'cuda.shares',
+ shmem: '1g',
+ },
+ vFolderID: vfolderID, // TODO: add cloned folder result
+ modelMountDestination: '/models',
+ modelDefinitionPath: '',
+ vfoldersAliasMap: {},
+ envvars: [],
+ enabledAutomaticShmem: false,
+ };
+ };
+
+ const cloneOrCreateModelService = (runtimeVariant: string) => {
+ let modelId = 'vllm-model';
+ switch (runtimeVariant) {
+ case 'vllm':
+ default:
+ break;
+ case 'nim':
+ case 'custom':
+ modelId = 'custom';
+ break;
+ }
+ if (filteredModelStoreList.length < 1) {
+ mutationToClone.mutate(
+ {
+ input: {
+ // FIXME: hardcoded
+ cloneable: true,
+ permission: 'wd', // write-delete permission
+ target_host: modelStorageHost, // lowestUsageHost, // clone to accessible and lowest usage storage host
+ target_name: `${modelName}-1`,
+ usage_mode: 'model',
+ },
+ name: `${modelName}`,
+ },
+ {
+ onSuccess: (data) => {
+ upsertNotification({
+ key: `modelStore.clone. + ${modelName}-1`,
+ open: true,
+ onClose: () => {
+ upsertNotification({
+ key: `modelStore.clone. + ${modelName}-1`,
+ open: false,
+ backgroundTask: {
+ percent: 0,
+ status: 'pending',
+ },
+ to: '',
+ toText: '',
+ });
+ },
+ extraDescription: '(1 / 2)',
+ backgroundTask: {
+ status: 'pending',
+ percent: 50,
+ taskId: data.bgtask_id,
+ statusDescriptions: {
+ pending: 'Downloading model is in progress...', // t('data.folders.FolderClonePending'),
+ resolved: 'Successfully downloaded model.', // t('data.folders.FolderCloned'),
+ rejected:
+ 'Downloading model failed. Please check storage quota and try again.', // t('data.folders.FolderCloneFailed'),
+ },
+ onResolve: () => {
+ mutationToCreateService.mutate(
+ getServiceInputByRuntimeVariant('vllm', `${modelName}-1`),
+ {
+ onSuccess: (result: any) => {
+ upsertNotification({
+ key: result?.endpoint_id,
+ open: true,
+ message: 'Starting model service...',
+ duration: 0,
+ backgroundTask: {
+ promise: new Promise((resolve, reject) => {
+ let progress = 0;
+ const interval = setInterval(async () => {
+ try {
+ progress += 5;
+ upsertNotification({
+ key: result?.endpoint_id,
+ backgroundTask: {
+ status: 'pending',
+ percent: progress > 100 ? 100 : progress,
+ },
+ });
+ const routingStatus =
+ await baiRequestWithPromise({
+ method: 'GET',
+ url: `/services/${result?.endpoint_id}`,
+ });
+ if (routingStatus.active_routes.length > 0) {
+ clearInterval(interval);
+ return resolve();
+ }
+ if (progress >= 100) {
+ throw new Error(
+ 'Model service failed to start. Please check the service status.',
+ );
+ }
+ } catch (error) {
+ clearInterval(interval);
+ return reject();
+ }
+ }, 5000);
+ }),
+ statusDescriptions: {
+ pending: 'Model service is starting...',
+ resolved: 'Model service is now ready!',
+ rejected:
+ 'Model service failed to start. Please check the service status.',
+ },
+ status: 'pending',
+ percent: 0,
+ onResolve: () => {
+ upsertNotification({
+ duration: 0,
+ key: result?.endpoint_id,
+ backgroundTask: {
+ status: 'resolved',
+ percent: 100,
+ },
+ message: '',
+ to: `/playground?endpointId=${result?.endpoint_id}&modelId=vllm-model`, // PATH to playground page
+ toText: 'Play your model now!',
+ });
+ },
+ onFailed: () => {
+ upsertNotification({
+ key: result?.endpoint_id,
+ duration: 0,
+ backgroundTask: {
+ status: 'rejected',
+ percent: 99,
+ },
+ message: '',
+ to: `/serving/${result?.endpoint_id}`,
+ toText: 'Go to service detail page',
+ });
+ },
+ },
+ });
+ },
+ onError: () => {
+ // TODO: show a notification to go to service detail page
+ },
+ },
+ );
+ },
+ },
+ });
+ },
+ onError: () => {
+ // TODO: show a notification for clone error
+ },
+ },
+ );
+ } else {
+ mutationToCreateService.mutate(
+ getServiceInputByRuntimeVariant(
+ runtimeVariant,
+ filteredModelStoreList[0].id,
+ ),
+ {
+ onSuccess: (result: any) => {
+ upsertNotification({
+ key: result?.endpoint_id,
+ open: true,
+ message: 'Starting model service...',
+ duration: 0,
+ backgroundTask: {
+ promise: new Promise((resolve, reject) => {
+ let progress = 0;
+ const interval = setInterval(async () => {
+ try {
+ progress += 5;
+ upsertNotification({
+ key: result?.endpoint_id,
+ backgroundTask: {
+ status: 'pending',
+ percent: progress > 100 ? 100 : progress,
+ },
+ });
+ const routingStatus = await baiRequestWithPromise({
+ method: 'GET',
+ url: `/services/${result?.endpoint_id}`,
+ });
+ if (routingStatus.active_routes.length > 0) {
+ clearInterval(interval);
+ return resolve();
+ }
+ if (progress >= 100) {
+ throw new Error(
+ 'Model service failed to start. Please check the service status.',
+ );
+ }
+ } catch (error) {
+ clearInterval(interval);
+ return reject();
+ }
+ }, 5000);
+ }),
+ statusDescriptions: {
+ pending: 'Model service is starting...',
+ resolved: 'Model service is now ready!',
+ rejected:
+ 'Model service failed to start. Please check the service status.',
+ },
+ status: 'pending',
+ percent: 0,
+ onResolve: () => {
+ upsertNotification({
+ duration: 0,
+ key: result?.endpoint_id,
+ backgroundTask: {
+ status: 'resolved',
+ percent: 100,
+ },
+ message: '',
+ to: `/playground?endpointId=${result?.endpoint_id}&modelId=${modelId}`, // PATH to playground page
+ toText: 'Play your model now!',
+ });
+ },
+ onFailed: () => {
+ upsertNotification({
+ duration: 0,
+ key: result?.endpoint_id,
+ backgroundTask: {
+ status: 'rejected',
+ percent: 99,
+ },
+ message: '',
+ to: `/serving/${result?.endpoint_id}`,
+ toText: 'Go to service detail page',
+ });
+ },
+ },
+ });
+ },
+ onError: () => {
+ // TODO: show a notification to go to service detail page
+ },
+ },
+ );
+ }
+ };
+
+ return (
+ <>
+ {title && (
+
+ {title}
+
+ )}
+
+
+
+ >
+ );
+};
+
+export default ModelTryContent;
diff --git a/react/src/components/lablupTalkativotUI/ChatMessage.tsx b/react/src/components/lablupTalkativotUI/ChatMessage.tsx
index 6f3104e68f..ae429fc186 100644
--- a/react/src/components/lablupTalkativotUI/ChatMessage.tsx
+++ b/react/src/components/lablupTalkativotUI/ChatMessage.tsx
@@ -103,8 +103,9 @@ const ChatMessage: React.FC<{
direction="column"
style={{
borderRadius: token.borderRadius,
- borderColor: token.colorBorderSecondary,
- borderWidth: token.lineWidth,
+ border: _.isEmpty(message.experimental_attachments)
+ ? `${token.lineWidth}px solid ${token.colorBorderSecondary}`
+ : 'none',
padding: '1em',
paddingTop: 0,
paddingBottom: 0,
diff --git a/react/src/components/lablupTalkativotUI/LLMChatCard.tsx b/react/src/components/lablupTalkativotUI/LLMChatCard.tsx
index 8ccb89afcf..d7305f7fa7 100644
--- a/react/src/components/lablupTalkativotUI/LLMChatCard.tsx
+++ b/react/src/components/lablupTalkativotUI/LLMChatCard.tsx
@@ -268,6 +268,7 @@ const LLMChatCard: React.FC = ({
width: '100%',
display: 'flex',
flexDirection: 'column',
+ minHeight: '50vh',
}}
styles={{
body: {
@@ -292,7 +293,7 @@ const LLMChatCard: React.FC = ({
= ({ ...props }) => {
const { token } = theme.useToken();
const { t } = useTranslation();
// Set the initial list to have two items
- const { list, remove, getKey, push } = useDynamicList(['0', '1']);
+ const { list, remove, getKey, push } = useDynamicList(['0']);
const [isSynchronous, setSynchronous] = useState(false);
diff --git a/react/src/components/lablupTalkativotUI/VirtualChatMessageList.tsx b/react/src/components/lablupTalkativotUI/VirtualChatMessageList.tsx
index 755436f90c..df802971be 100644
--- a/react/src/components/lablupTalkativotUI/VirtualChatMessageList.tsx
+++ b/react/src/components/lablupTalkativotUI/VirtualChatMessageList.tsx
@@ -59,7 +59,7 @@ const VirtualChatMessageList: React.FC = ({
}
enableExtraHover={m.role === 'user'}
extra={
- m.role !== 'user' ? (
+ m.role !== 'user' && m.content ? (
void;
+ onFailed?: (notification: NotificationState) => void;
taskId?: string;
percent?: number;
status: 'pending' | 'rejected' | 'resolved';
@@ -71,6 +73,7 @@ export const useBAINotificationEffect = () => {
listeningPromiseKeysRef.current.push(notification.key);
notification.backgroundTask?.promise
.then(() => {
+ notification?.backgroundTask?.onResolve?.(notification);
upsertNotification({
key: notification.key,
// message: notification.message,
@@ -79,10 +82,11 @@ export const useBAINotificationEffect = () => {
backgroundTask: {
status: 'resolved',
},
- duration: CLOSING_DURATION,
+ duration: 0, // CLOSING_DURATION,
});
})
.catch((e) => {
+ notification?.backgroundTask?.onFailed?.(notification);
upsertNotification({
key: notification.key,
description:
@@ -148,6 +152,8 @@ export const useBAINotificationEffect = () => {
listeningTaskIdsRef.current,
notification.backgroundTask?.taskId,
);
+ notification?.backgroundTask?.onResolve?.(notification);
+ notification?.backgroundTask?.onFailed?.(notification);
sse.close();
if (_.startsWith(_.toString(notification.key), 'image-rescan:')) {
const event = new CustomEvent('image-rescanned');
@@ -164,6 +170,8 @@ export const useBAINotificationEffect = () => {
});
});
const failHandler = (e: any) => {
+ notification?.backgroundTask?.onResolve?.(notification);
+ notification?.backgroundTask?.onFailed?.(notification);
listeningTaskIdsRef.current = _.without(
listeningTaskIdsRef.current,
notification.backgroundTask?.taskId,
@@ -188,6 +196,8 @@ export const useBAINotificationEffect = () => {
sse.addEventListener('bgtask_failed', failHandler);
sse.addEventListener('task_failed', (e) => {
const data = JSON.parse(e['data']);
+ notification?.backgroundTask?.onResolve?.(notification);
+ notification?.backgroundTask?.onFailed?.(notification);
upsertNotification({
key: notification.key,
message: notification.message,
@@ -204,6 +214,8 @@ export const useBAINotificationEffect = () => {
});
sse.addEventListener('bgtask_cancelled', (e) => {
+ notification?.backgroundTask?.onResolve?.(notification);
+ notification?.backgroundTask?.onFailed?.(notification);
listeningTaskIdsRef.current = _.without(
listeningTaskIdsRef.current,
notification.backgroundTask?.taskId,
diff --git a/react/src/pages/ModelStoreListPage.tsx b/react/src/pages/ModelStoreListPage.tsx
index 7235ade9e0..7e964435d2 100644
--- a/react/src/pages/ModelStoreListPage.tsx
+++ b/react/src/pages/ModelStoreListPage.tsx
@@ -1,4 +1,5 @@
import Flex from '../components/Flex';
+import ImportFromHuggingFacePanel from '../components/ImportFromHuggingFacePanel';
import ModelCardModal from '../components/ModelCardModal';
import TextHighlighter from '../components/TextHighlighter';
import { ModelCardModalFragment$key } from '../components/__generated__/ModelCardModalFragment.graphql';
@@ -15,6 +16,7 @@ import {
Tag,
theme,
Typography,
+ Image,
} from 'antd';
import { createStyles } from 'antd-style';
import graphql from 'babel-plugin-relay/macro';
@@ -43,7 +45,13 @@ const ModelStoreListPage: React.FC = () => {
const [selectedCategories, setSelectedCategories] = useState([]);
const [selectedTasks, setSelectedTasks] = useState([]);
const [selectedLabels, setSelectedLabels] = useState([]);
-
+ const [paginationState] = useState<{
+ current: number;
+ pageSize: number;
+ }>({
+ current: 1,
+ pageSize: 100,
+ });
const { styles } = useStyles();
const [currentModelInfo, setCurrentModelInfo] =
@@ -71,6 +79,10 @@ const ModelStoreListPage: React.FC = () => {
license
min_resource
error_msg @since(version: "24.03.7")
+ vfolder {
+ id
+ name
+ }
...ModelCardModalFragment
}
}
@@ -91,8 +103,6 @@ const ModelStoreListPage: React.FC = () => {
},
);
- // const filterInfo = _.map
-
const fieldsValues = useMemo(() => {
const result: {
task: string[];
@@ -126,6 +136,7 @@ const ModelStoreListPage: React.FC = () => {
gap="lg"
style={{ padding: token.paddingLG }}
>
+
{
edge?.node)
.filter((info) => {
@@ -229,6 +240,24 @@ const ModelStoreListPage: React.FC = () => {
_.includes(selectedTasks, info?.task)) &&
passSearchFilter
);
+ })
+ .sort((a, b) => {
+ const specialNames = [
+ 'gemma-2-27b-it',
+ 'stable-diffusion-3-medium',
+ ];
+ const aIndex = specialNames.indexOf(a?.name || '');
+ const bIndex = specialNames.indexOf(b?.name || '');
+
+ if (aIndex !== -1 && bIndex !== -1) {
+ return aIndex - bIndex;
+ } else if (aIndex !== -1) {
+ return -1;
+ } else if (bIndex !== -1) {
+ return 1;
+ } else {
+ return 0;
+ }
})}
renderItem={(item) => (
{
style={{
height: '100%',
}}
- size="small"
- >
-
- {item?.description && (
-
-
- {item?.description}
-
-
- )}
- {item?.category && (
-
-
- {item?.category}
-
-
- )}
- {item?.task && (
-
-
- {item?.task}
-
-
- )}
- {item?.label &&
- _.map(item?.label, (label) => (
-
+ children={
+
+
+
+
- {label}
+ {item?.description}
-
- ))}
- {item?.error_msg && (
-
- {item.error_msg}
-
- }
- type="error"
- showIcon
- />
- )}
-
-
+
+
+
+ {item?.category && (
+
+
+ {item?.category}
+
+
+ )}
+ {item?.task && (
+
+
+ {item?.task}
+
+
+ )}
+ {item?.label &&
+ _.map(item?.label, (label) => (
+
+
+ {label}
+
+
+ ))}
+ {item?.error_msg && (
+
+ {item.error_msg}
+
+ }
+ type="error"
+ showIcon
+ />
+ )}
+
+
+ }
+ >
)}
/>
diff --git a/react/src/pages/ModelStorePage.tsx b/react/src/pages/ModelStorePage.tsx
new file mode 100644
index 0000000000..9ce3c38e8e
--- /dev/null
+++ b/react/src/pages/ModelStorePage.tsx
@@ -0,0 +1,17 @@
+import { Skeleton, theme } from 'antd';
+import React, { Suspense } from 'react';
+
+const ModelStoreListPage = React.lazy(() => import('./ModelStoreListPage'));
+const ModelStorePage: React.FC = () => {
+ const { token } = theme.useToken();
+
+ return (
+ }
+ >
+
+
+ );
+};
+
+export default ModelStorePage;
diff --git a/react/src/pages/Page401.tsx b/react/src/pages/Page401.tsx
index ca83319b92..920d3e9bc4 100644
--- a/react/src/pages/Page401.tsx
+++ b/react/src/pages/Page401.tsx
@@ -38,7 +38,7 @@ const Page401 = () => {
diff --git a/react/src/pages/Page404.tsx b/react/src/pages/Page404.tsx
index 63c5a2b1a0..c8726be068 100644
--- a/react/src/pages/Page404.tsx
+++ b/react/src/pages/Page404.tsx
@@ -38,7 +38,7 @@ const Page404 = () => {
diff --git a/react/src/pages/ServingPage.tsx b/react/src/pages/ServingPage.tsx
index 78a89a85e0..f77c78f82b 100644
--- a/react/src/pages/ServingPage.tsx
+++ b/react/src/pages/ServingPage.tsx
@@ -49,11 +49,6 @@ const ServingPage: React.FC = ({ ...props }) => {
return (
{
- setCurTabKey(key as TabKey);
- }}
- tabList={tabList}
styles={{
body: {
padding: 0,
@@ -62,12 +57,13 @@ const ServingPage: React.FC = ({ ...props }) => {
},
}}
>
- {curTabKey === 'services' ? (
- }
- >
-
-
+ }
+ >
+
+
+ {/* {curTabKey === 'services' ? (
+
) : null}
{curTabKey === 'chatting' && baiClient._config.enableLLMPlayground ? (
= ({ ...props }) => {
>
- ) : null}
+ ) : null} */}
);
diff --git a/react/src/pages/VFolderListPage.tsx b/react/src/pages/VFolderListPage.tsx
index f3d8f10069..d6ea1f9a25 100644
--- a/react/src/pages/VFolderListPage.tsx
+++ b/react/src/pages/VFolderListPage.tsx
@@ -27,16 +27,14 @@ const StorageStatusPanelFallback = React.lazy(() =>
);
type TabKey =
- | 'general'
- | 'data'
- | 'automount'
- | 'model'
- | 'model-store'
- | 'trash-bin';
+ // | 'general'
+ // | 'data'
+ // | 'automount'
+ 'model' | 'model-store' | 'trash-bin';
interface VFolderListPageProps {}
-const tabParam = withDefault(StringParam, 'general');
+const tabParam = withDefault(StringParam, 'model-store');
const VFolderListPage: React.FC = (props) => {
const { t } = useTranslation();
@@ -87,6 +85,7 @@ const VFolderListPage: React.FC = (props) => {
}[curTabKey];
const tabList = filterEmptyItem([
+ /*
{
key: 'general',
tab: t('data.Folders'),
@@ -99,6 +98,7 @@ const VFolderListPage: React.FC = (props) => {
key: 'automount',
tab: t('data.AutomountFolders'),
},
+ */
{
key: 'model',
tab: t('data.Models'),
diff --git a/resources/i18n/de.json b/resources/i18n/de.json
index 91f3e3b6e3..4029120b31 100644
--- a/resources/i18n/de.json
+++ b/resources/i18n/de.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Geben sie ihre E-Mail Adresse ein",
"DisMatchUserEmail": "Die E-Mail-Adresse des Benutzers stimmt nicht überein",
"MyEnvironments": "Meine Umgebungen",
- "ResourcePolicy": "Ressourcenpolitik"
+ "ResourcePolicy": "Ressourcenpolitik",
+ "Playground": "Spielplatz",
+ "ModelStore": "Modellladen"
},
"YouAreOffline": "Offline: Keine Verbindung zu einem Netzwerk.",
"YouAreOnline": "Sie sind jetzt online",
@@ -1705,7 +1707,10 @@
"category": "Kategorie",
"CloneToFolder": "In einen Ordner klonen",
"FolderAlreadyExists": "Ein Ordner mit diesem Namen existiert bereits.",
- "FinetuneModel": "Feinabstimmung des Modells"
+ "FinetuneModel": "Feinabstimmung des Modells",
+ "Experience": "Erfahrung",
+ "ModelCard": "Modellkarte",
+ "ImportFromHuggingFace": "Import aus Hugging Face"
},
"table": {
"SettingTable": "Sitzordnung bei Tisch",
@@ -1756,5 +1761,12 @@
"hour": "Stunde",
"day": "day",
"week": "Woche"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Modelldienstleistungen",
+ "ModelList": "Modellliste",
+ "MyServices": "Meine Dienste"
+ }
}
}
diff --git a/resources/i18n/el.json b/resources/i18n/el.json
index 5c7c778246..a1a1e3cbda 100644
--- a/resources/i18n/el.json
+++ b/resources/i18n/el.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Συμπληρώστε το email σας",
"DisMatchUserEmail": "Το email χρήστη δεν ταιριάζει",
"MyEnvironments": "Τα περιβάλλοντα μου",
- "ResourcePolicy": "Πολιτική Πόρων"
+ "ResourcePolicy": "Πολιτική Πόρων",
+ "Playground": "Παιδική χαρά",
+ "ModelStore": "Κατάστημα μοντέλων"
},
"YouAreOffline": "Offline: Δεν είναι συνδεδεμένος σε κανένα δίκτυο.",
"YouAreOnline": "Είστε πλέον συνδεδεμένοι",
@@ -1705,7 +1707,10 @@
"category": "Κατηγορία",
"CloneToFolder": "Κλωνοποίηση σε φάκελο",
"FolderAlreadyExists": "Ένας φάκελος με αυτό το όνομα υπάρχει ήδη.",
- "FinetuneModel": "Μοντέλο Finetune"
+ "FinetuneModel": "Μοντέλο Finetune",
+ "Experience": "Εμπειρία",
+ "ModelCard": "Κάρτα μοντέλου",
+ "ImportFromHuggingFace": "Εισαγωγή από το πρόσωπο που αγκαλιάζει"
},
"table": {
"SettingTable": "Ρύθμιση πίνακα",
@@ -1756,5 +1761,12 @@
"hour": "ώρα",
"day": "day",
"week": "εβδομάδα"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Υπηρεσίες μοντέλου",
+ "ModelList": "Λίστα μοντέλων",
+ "MyServices": "Οι υπηρεσίες μου"
+ }
}
}
diff --git a/resources/i18n/en.json b/resources/i18n/en.json
index a861332a66..3ec31463aa 100644
--- a/resources/i18n/en.json
+++ b/resources/i18n/en.json
@@ -64,7 +64,9 @@
"InvalidBlankEmail": "Enter your e-mail",
"DisMatchUserEmail": "User E-mail does not match",
"MyEnvironments": "My Environments",
- "ResourcePolicy": "Resource Policy"
+ "ResourcePolicy": "Resource Policy",
+ "Playground": "Playground",
+ "ModelStore": "Model Store"
},
"YouAreOffline": "Offline: Not connected to any networks.",
"YouAreOnline": "You are now online",
@@ -565,7 +567,8 @@
"Expand": "Expand",
"Clear": "Clear",
"Apply": "Apply",
- "CopySomething": "Copy {{name}}"
+ "CopySomething": "Copy {{name}}",
+ "GoBackToModelServicesPage": "Go back to model services page"
},
"agent": {
"Endpoint": "Endpoint",
@@ -1713,7 +1716,10 @@
"category": "Category",
"CloneToFolder": "Clone to a folder",
"FolderAlreadyExists": "A folder with this name already exists.",
- "FinetuneModel": "Finetune Model"
+ "FinetuneModel": "Finetune Model",
+ "Experience": "Experience",
+ "ModelCard": "Model Card",
+ "ImportFromHuggingFace": "Import From Hugging Face"
},
"tourguide": {
"NeoSessionLauncher": {
@@ -1760,5 +1766,12 @@
"hour": "hour",
"day": "day",
"week": "week"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Model Services",
+ "ModelList": "Model List",
+ "MyServices": "My Services"
+ }
}
}
diff --git a/resources/i18n/es.json b/resources/i18n/es.json
index 128622e793..1e19f87494 100644
--- a/resources/i18n/es.json
+++ b/resources/i18n/es.json
@@ -1674,7 +1674,9 @@
"InvalidBlankEmail": "Introduce tu correo electrónico",
"DisMatchUserEmail": "El correo electrónico del usuario no coincide",
"MyEnvironments": "Mis ambientes",
- "ResourcePolicy": "Política de recursos"
+ "ResourcePolicy": "Política de recursos",
+ "Playground": "Patio de juegos",
+ "ModelStore": "Tienda de modelos"
},
"NetworkSoftTimeout": "El servidor está tardando más en responder. Por favor, espere un momento"
},
@@ -1707,7 +1709,10 @@
"category": "Categoría",
"CloneToFolder": "Clonar en una carpeta",
"FolderAlreadyExists": "Ya existe una carpeta con este nombre.",
- "FinetuneModel": "Modelo de ajuste fino"
+ "FinetuneModel": "Modelo de ajuste fino",
+ "Experience": "Experiencia",
+ "ModelCard": "Tarjeta modelo",
+ "ImportFromHuggingFace": "Importar desde la cara abrazada"
},
"table": {
"SettingTable": "Ajuste de la tabla",
@@ -1758,5 +1763,12 @@
"hour": "hora",
"day": "day",
"week": "semana"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Servicios modelo",
+ "ModelList": "Lista de modelos",
+ "MyServices": "Mis servicios"
+ }
}
}
diff --git a/resources/i18n/fi.json b/resources/i18n/fi.json
index bb7af91ce5..9c0d361aff 100644
--- a/resources/i18n/fi.json
+++ b/resources/i18n/fi.json
@@ -1672,7 +1672,9 @@
"InvalidBlankEmail": "Syötä sähköpostiosoitteesi",
"DisMatchUserEmail": "Käyttäjän sähköpostiosoite ei täsmää",
"MyEnvironments": "Omat ympäristöt",
- "ResourcePolicy": "Resurssipolitiikka"
+ "ResourcePolicy": "Resurssipolitiikka",
+ "Playground": "Leikkikenttä",
+ "ModelStore": "Mallikauppa"
},
"NetworkSoftTimeout": "Palvelimen vastaus kestää kauemmin. Odota hetki"
},
@@ -1705,7 +1707,10 @@
"Version": "Versio",
"CloneToFolder": "Kloonaa kansioon",
"FolderAlreadyExists": "Tämän niminen kansio on jo olemassa.",
- "FinetuneModel": "Finetune malli"
+ "FinetuneModel": "Finetune malli",
+ "Experience": "Kokea",
+ "ModelCard": "Mallikortti",
+ "ImportFromHuggingFace": "Tuo halaavista kasvoista"
},
"table": {
"SettingTable": "Kattaus",
@@ -1755,5 +1760,12 @@
"hour": "tunnin",
"day": "day",
"week": "viikko"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Mallipalvelut",
+ "ModelList": "Malliluettelo",
+ "MyServices": "Omat palvelut"
+ }
}
}
diff --git a/resources/i18n/fr.json b/resources/i18n/fr.json
index 3b48649e92..379a8fc0dc 100644
--- a/resources/i18n/fr.json
+++ b/resources/i18n/fr.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Entrer votre Email",
"DisMatchUserEmail": "L'e-mail de l'utilisateur ne correspond pas",
"MyEnvironments": "Mes environnements",
- "ResourcePolicy": "Politique des ressources"
+ "ResourcePolicy": "Politique des ressources",
+ "Playground": "Aire de jeux",
+ "ModelStore": "Magasin de modèles"
},
"YouAreOffline": "Hors ligne : N'est connecté à aucun réseau.",
"YouAreOnline": "Vous êtes maintenant en ligne",
@@ -1705,7 +1707,10 @@
"category": "Catégorie",
"CloneToFolder": "Cloner dans un dossier",
"FolderAlreadyExists": "Un dossier portant ce nom existe déjà.",
- "FinetuneModel": "Modèle de réglage fin"
+ "FinetuneModel": "Modèle de réglage fin",
+ "Experience": "Expérience",
+ "ModelCard": "Carte modèle",
+ "ImportFromHuggingFace": "Importer depuis un visage câlin"
},
"table": {
"SettingTable": "Paramètre de table",
@@ -1756,5 +1761,12 @@
"hour": "heure",
"day": "day",
"week": "semaine"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Services de modèles",
+ "ModelList": "Liste des modèles",
+ "MyServices": "Mes prestations"
+ }
}
}
diff --git a/resources/i18n/id.json b/resources/i18n/id.json
index c55d137862..7ab792fb71 100644
--- a/resources/i18n/id.json
+++ b/resources/i18n/id.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Masukkan email Anda",
"DisMatchUserEmail": "Email Pengguna tidak cocok",
"MyEnvironments": "Lingkungan Saya",
- "ResourcePolicy": "Kebijakan Sumber Daya"
+ "ResourcePolicy": "Kebijakan Sumber Daya",
+ "Playground": "Tempat bermain",
+ "ModelStore": "Toko Model"
},
"YouAreOffline": "Offline: Tidak terhubung ke jaringan apa pun.",
"YouAreOnline": "Anda sekarang online",
@@ -1705,7 +1707,10 @@
"category": "Kategori",
"CloneToFolder": "Mengkloning ke folder",
"FolderAlreadyExists": "Folder dengan nama ini sudah ada.",
- "FinetuneModel": "Penyempurnaan Model"
+ "FinetuneModel": "Penyempurnaan Model",
+ "Experience": "Pengalaman",
+ "ModelCard": "Kartu Model",
+ "ImportFromHuggingFace": "Impor Dari Memeluk Wajah"
},
"table": {
"SettingTable": "Penataan meja",
@@ -1756,5 +1761,12 @@
"hour": "jam",
"day": "day",
"week": "pekan"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Layanan Model",
+ "ModelList": "Daftar Model",
+ "MyServices": "Layanan Saya"
+ }
}
}
diff --git a/resources/i18n/it.json b/resources/i18n/it.json
index fd8f072619..4965ea624b 100644
--- a/resources/i18n/it.json
+++ b/resources/i18n/it.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Inserisci il tuo indirizzo email",
"DisMatchUserEmail": "L'e-mail dell'utente non corrisponde",
"MyEnvironments": "I miei ambienti",
- "ResourcePolicy": "Politica delle risorse"
+ "ResourcePolicy": "Politica delle risorse",
+ "Playground": "Parco giochi",
+ "ModelStore": "Negozio di modelli"
},
"YouAreOffline": "Non in linea: Non è collegato ad alcuna rete.",
"YouAreOnline": "Ora sei online",
@@ -1705,7 +1707,10 @@
"category": "Categoria",
"CloneToFolder": "Clonare in una cartella",
"FolderAlreadyExists": "Una cartella con questo nome esiste già.",
- "FinetuneModel": "Modello di messa a punto"
+ "FinetuneModel": "Modello di messa a punto",
+ "Experience": "Esperienza",
+ "ModelCard": "Scheda modello",
+ "ImportFromHuggingFace": "Importa da viso abbracciato"
},
"table": {
"SettingTable": "Impostazione della tabella",
@@ -1756,5 +1761,12 @@
"hour": "ora",
"day": "day",
"week": "settimana"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Servizi modello",
+ "ModelList": "Elenco dei modelli",
+ "MyServices": "I miei servizi"
+ }
}
}
diff --git a/resources/i18n/ja.json b/resources/i18n/ja.json
index a1cc356da1..73f936fe9f 100644
--- a/resources/i18n/ja.json
+++ b/resources/i18n/ja.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "メールアドレスを入力",
"DisMatchUserEmail": "ユーザーの電子メールが一致しません",
"MyEnvironments": "私の環境",
- "ResourcePolicy": "リソースポリシー"
+ "ResourcePolicy": "リソースポリシー",
+ "Playground": "遊び場",
+ "ModelStore": "模型店"
},
"YouAreOffline": "オフライン:どのネットワークにも接続されていない。",
"YouAreOnline": "あなたは今オンラインです",
@@ -1705,7 +1707,10 @@
"category": "カテゴリー",
"CloneToFolder": "フォルダへのクローン",
"FolderAlreadyExists": "この名前のフォルダはすでに存在する。",
- "FinetuneModel": "ファインチューンモデル"
+ "FinetuneModel": "ファインチューンモデル",
+ "Experience": "経験",
+ "ModelCard": "モデルカード",
+ "ImportFromHuggingFace": "ハグフェイスからインポート"
},
"table": {
"SettingTable": "テーブルセッティング",
@@ -1756,5 +1761,12 @@
"hour": "時間",
"day": "日",
"week": "週"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "モデルサービス",
+ "ModelList": "機種一覧",
+ "MyServices": "私のサービス"
+ }
}
}
diff --git a/resources/i18n/ko.json b/resources/i18n/ko.json
index dc783239f0..2e9c109759 100644
--- a/resources/i18n/ko.json
+++ b/resources/i18n/ko.json
@@ -65,7 +65,9 @@
"InvalidBlankPassword": "패스워드를 입력하세요.",
"DisMatchUserEmail": "사용자 E-mail이 일치하지 않습니다.",
"MyEnvironments": "나의 실행 환경",
- "ResourcePolicy": "자원 정책"
+ "ResourcePolicy": "자원 정책",
+ "Playground": "플레이그라운드",
+ "ModelStore": "모델 스토어"
},
"YouAreOffline": "오프라인: 네트워크에 연결되어 있지 않습니다.",
"YouAreOnline": "온라인 상태가 되었습니다",
@@ -1707,7 +1709,10 @@
"CloneInfo": "새로운 사용자 폴더로 복제됩니다.",
"CloneToFolder": "폴더로 복제",
"FolderAlreadyExists": "같은 이름의 폴더가 존재합니다.",
- "FinetuneModel": "모델 파인튜닝"
+ "FinetuneModel": "모델 파인튜닝",
+ "Experience": "사용해보기",
+ "ModelCard": "모델 카드",
+ "ImportFromHuggingFace": "Hugging Face 에서 가져오기"
},
"table": {
"SettingTable": "테이블 설정",
@@ -1758,5 +1763,12 @@
"hour": "시간",
"day": "일",
"week": "주"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "모델 서비스",
+ "ModelList": "모델 리스트",
+ "MyServices": "실행중인 서비스"
+ }
}
}
diff --git a/resources/i18n/mn.json b/resources/i18n/mn.json
index f47c018975..3cd313750e 100644
--- a/resources/i18n/mn.json
+++ b/resources/i18n/mn.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Имэйлээ оруулна уу",
"DisMatchUserEmail": "Хэрэглэгчийн имэйл таарахгүй байна",
"MyEnvironments": "Миний орчин",
- "ResourcePolicy": "Нөөцийн бодлого"
+ "ResourcePolicy": "Нөөцийн бодлого",
+ "Playground": "Тоглоомын талбай",
+ "ModelStore": "Загварын дэлгүүр"
},
"YouAreOffline": "Офлайн: Ямар ч сүлжээнд холбогдоогүй.",
"YouAreOnline": "Та одоо онлайн байна",
@@ -1705,7 +1707,10 @@
"category": "Ангилал",
"CloneToFolder": "Хавтас руу клон хийх",
"FolderAlreadyExists": "Ийм нэртэй хавтас аль хэдийн байна.",
- "FinetuneModel": "Finetune загвар"
+ "FinetuneModel": "Finetune загвар",
+ "Experience": "Туршлага",
+ "ModelCard": "Загварын карт",
+ "ImportFromHuggingFace": "Тэврэх нүүрээс импортлох"
},
"table": {
"SettingTable": "Хүснэгтийн тохиргоо",
@@ -1756,5 +1761,12 @@
"hour": "цаг",
"day": "day",
"week": "долоо хоног"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Загвар үйлчилгээ",
+ "ModelList": "Загварын жагсаалт",
+ "MyServices": "Миний үйлчилгээ"
+ }
}
}
diff --git a/resources/i18n/ms.json b/resources/i18n/ms.json
index 3a23655c01..7b2e539944 100644
--- a/resources/i18n/ms.json
+++ b/resources/i18n/ms.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Masukkan emel anda",
"DisMatchUserEmail": "E-mel Pengguna tidak sepadan",
"MyEnvironments": "Persekitaran Saya",
- "ResourcePolicy": "Dasar Sumber"
+ "ResourcePolicy": "Dasar Sumber",
+ "Playground": "Taman permainan",
+ "ModelStore": "Kedai Model"
},
"YouAreOffline": "Luar talian: Tidak disambungkan ke mana-mana rangkaian.",
"YouAreOnline": "Anda kini dalam talian",
@@ -1705,7 +1707,10 @@
"category": "kategori",
"CloneToFolder": "Klon ke folder",
"FolderAlreadyExists": "Folder dengan nama ini sudah wujud.",
- "FinetuneModel": "Model Finetune"
+ "FinetuneModel": "Model Finetune",
+ "Experience": "Pengalaman",
+ "ModelCard": "Kad Model",
+ "ImportFromHuggingFace": "Import Dari Muka Berpeluk"
},
"table": {
"SelectColumnToDisplay": "Pilih untuk lajur untuk dipaparkan",
@@ -1756,5 +1761,12 @@
"hour": "jam",
"day": "day",
"week": "minggu"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Perkhidmatan Model",
+ "ModelList": "Senarai Model",
+ "MyServices": "Perkhidmatan Saya"
+ }
}
}
diff --git a/resources/i18n/pl.json b/resources/i18n/pl.json
index 49fa0ae652..3b5cd83650 100644
--- a/resources/i18n/pl.json
+++ b/resources/i18n/pl.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Wprowadź swój email",
"DisMatchUserEmail": "Adres e-mail użytkownika nie jest zgodny",
"MyEnvironments": "Moje Środowiska",
- "ResourcePolicy": "Polityka zasobów"
+ "ResourcePolicy": "Polityka zasobów",
+ "Playground": "Plac gier i zabaw",
+ "ModelStore": "Sklep modelarski"
},
"YouAreOffline": "Offline: Brak połączenia z siecią.",
"YouAreOnline": "Jesteś teraz online",
@@ -1705,7 +1707,10 @@
"category": "Kategoria",
"CloneToFolder": "Klonowanie do folderu",
"FolderAlreadyExists": "Folder o tej nazwie już istnieje.",
- "FinetuneModel": "Dostosuj model"
+ "FinetuneModel": "Dostosuj model",
+ "Experience": "Doświadczenie",
+ "ModelCard": "Karta Modelowa",
+ "ImportFromHuggingFace": "Importuj z przytulającej twarzy"
},
"table": {
"SettingTable": "Nakrycie stołu",
@@ -1756,5 +1761,12 @@
"hour": "godzina",
"day": "day",
"week": "tydzień"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Usługi modelarskie",
+ "ModelList": "Lista modeli",
+ "MyServices": "Moje usługi"
+ }
}
}
diff --git a/resources/i18n/pt-BR.json b/resources/i18n/pt-BR.json
index 8cf39c15b3..3781d7ed91 100644
--- a/resources/i18n/pt-BR.json
+++ b/resources/i18n/pt-BR.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Digite seu e-mail",
"DisMatchUserEmail": "E-mail do usuário não corresponde",
"MyEnvironments": "Meus ambientes",
- "ResourcePolicy": "Política de Recursos"
+ "ResourcePolicy": "Política de Recursos",
+ "Playground": "Parque infantil",
+ "ModelStore": "Loja de modelos"
},
"YouAreOffline": "Desligado: Não está ligado a nenhuma rede.",
"YouAreOnline": "Agora você está online",
@@ -1705,7 +1707,10 @@
"category": "Categoria",
"CloneToFolder": "Clonar para uma pasta",
"FolderAlreadyExists": "Já existe uma pasta com este nome.",
- "FinetuneModel": "Modelo de ajuste fino"
+ "FinetuneModel": "Modelo de ajuste fino",
+ "Experience": "Experiência",
+ "ModelCard": "Cartão Modelo",
+ "ImportFromHuggingFace": "Importar do rosto abraçado"
},
"table": {
"SettingTable": "Configuração de mesa",
@@ -1756,5 +1761,12 @@
"hour": "hora",
"day": "day",
"week": "semana"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Serviços de modelo",
+ "ModelList": "Lista de modelos",
+ "MyServices": "Meus serviços"
+ }
}
}
diff --git a/resources/i18n/pt.json b/resources/i18n/pt.json
index 997cf704de..52f4af7269 100644
--- a/resources/i18n/pt.json
+++ b/resources/i18n/pt.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Digite seu e-mail",
"DisMatchUserEmail": "E-mail do usuário não corresponde",
"MyEnvironments": "Meus ambientes",
- "ResourcePolicy": "Política de Recursos"
+ "ResourcePolicy": "Política de Recursos",
+ "Playground": "Parque infantil",
+ "ModelStore": "Loja de modelos"
},
"YouAreOffline": "Desligado: Não está ligado a nenhuma rede.",
"YouAreOnline": "Agora você está online",
@@ -1705,7 +1707,10 @@
"CloneInfo": "Ele será clonado como sua pasta de tipo de usuário.",
"CloneToFolder": "Clonar para uma pasta",
"FolderAlreadyExists": "Já existe uma pasta com este nome.",
- "FinetuneModel": "Modelo de ajuste fino"
+ "FinetuneModel": "Modelo de ajuste fino",
+ "Experience": "Experiência",
+ "ModelCard": "Cartão Modelo",
+ "ImportFromHuggingFace": "Importar do rosto abraçado"
},
"table": {
"SettingTable": "Configuração de mesa",
@@ -1756,5 +1761,12 @@
"hour": "hora",
"day": "day",
"week": "semana"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Serviços de modelo",
+ "ModelList": "Lista de modelos",
+ "MyServices": "Meus serviços"
+ }
}
}
diff --git a/resources/i18n/ru.json b/resources/i18n/ru.json
index 7a6592a45b..d877a30ab4 100644
--- a/resources/i18n/ru.json
+++ b/resources/i18n/ru.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Введите адрес электронной почты",
"DisMatchUserEmail": "Электронная почта пользователя не совпадает",
"MyEnvironments": "Моя среда",
- "ResourcePolicy": "Ресурсная политика"
+ "ResourcePolicy": "Ресурсная политика",
+ "Playground": "Детская площадка",
+ "ModelStore": "Модельный магазин"
},
"YouAreOffline": "Не в сети: Не подключен ни к одной сети.",
"YouAreOnline": "Вы сейчас в сети",
@@ -1705,7 +1707,10 @@
"category": "Категория",
"CloneToFolder": "Клонирование в папку",
"FolderAlreadyExists": "Папка с таким именем уже существует.",
- "FinetuneModel": "Точная настройка модели"
+ "FinetuneModel": "Точная настройка модели",
+ "Experience": "Опыт",
+ "ModelCard": "Модель карты",
+ "ImportFromHuggingFace": "Импорт из обнимающего лица"
},
"table": {
"SettingTable": "Сервировка стола",
@@ -1756,5 +1761,12 @@
"hour": "час",
"day": "day",
"week": "неделя"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "Модельные услуги",
+ "ModelList": "Список моделей",
+ "MyServices": "Мои услуги"
+ }
}
}
diff --git a/resources/i18n/th.json b/resources/i18n/th.json
index 5fa2078538..f54fc3ab0e 100644
--- a/resources/i18n/th.json
+++ b/resources/i18n/th.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "ใส่อีเมลของคุณ",
"DisMatchUserEmail": "อีเมลผู้ใช้ไม่ตรงกัน",
"MyEnvironments": "สภาพแวดล้อมของฉัน",
- "ResourcePolicy": "นโยบายทรัพยากร"
+ "ResourcePolicy": "นโยบายทรัพยากร",
+ "Playground": "สนามเด็กเล่น",
+ "ModelStore": "ร้านโมเดล"
},
"YouAreOffline": "ออฟไลน์: ไม่ได้เชื่อมต่อกับเครือข่ายใดๆ",
"YouAreOnline": "คุณออนไลน์แล้ว",
@@ -1689,7 +1691,10 @@
"category": "หมวดหมู่",
"CloneToFolder": "โคลนไปยังโฟลเดอร์",
"FolderAlreadyExists": "มีโฟลเดอร์ชื่อนี้อยู่แล้ว",
- "FinetuneModel": "ปรับแต่งโมเดล"
+ "FinetuneModel": "ปรับแต่งโมเดล",
+ "Experience": "ประสบการณ์",
+ "ModelCard": "การ์ดโมเดล",
+ "ImportFromHuggingFace": "นำเข้าจากกอดใบหน้า"
},
"tourguide": {
"NeoSessionLauncher": {
@@ -1736,5 +1741,12 @@
"hour": "ชั่วโมง",
"day": "day",
"week": "สัปดาห์"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelServices": "บริการโมเดล",
+ "ModelList": "รายการรุ่น",
+ "MyServices": "บริการของฉัน"
+ }
}
}
diff --git a/resources/i18n/tr.json b/resources/i18n/tr.json
index 400ae355f8..5319cda759 100644
--- a/resources/i18n/tr.json
+++ b/resources/i18n/tr.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "E-postanızı giriniz",
"DisMatchUserEmail": "Kullanıcı E-postası eşleşmiyor",
"MyEnvironments": "Ortamlarım",
- "ResourcePolicy": "Kaynak Politikası"
+ "ResourcePolicy": "Kaynak Politikası",
+ "Playground": "Bahçesi",
+ "ModelStore": "Model Mağazası"
},
"YouAreOffline": "Çevrimdışı: Herhangi bir ağa bağlı değil.",
"YouAreOnline": "artık çevrimiçisin",
@@ -1704,7 +1706,10 @@
"category": "Kategori",
"CloneToFolder": "Bir klasöre klonlama",
"FolderAlreadyExists": "Bu isimde bir klasör zaten mevcut.",
- "FinetuneModel": "İnce Ayar Modeli"
+ "FinetuneModel": "İnce Ayar Modeli",
+ "Experience": "Deneyim",
+ "ModelCard": "Model Kartı",
+ "ImportFromHuggingFace": "Sarılma Yüzünden İçe Aktar"
},
"table": {
"SettingTable": "Tablo Ayarı",
@@ -1755,5 +1760,10 @@
"hour": "saat",
"day": "day",
"week": "hafta"
+ },
+ "modelserving": {
+ "menu": {
+ "MyServices": "Hizmetlerim"
+ }
}
}
diff --git a/resources/i18n/vi.json b/resources/i18n/vi.json
index 4104b6610e..b648f27acd 100644
--- a/resources/i18n/vi.json
+++ b/resources/i18n/vi.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "Nhập email của bạn",
"DisMatchUserEmail": "E-mail của người dùng không khớp",
"MyEnvironments": "Môi trường của tôi",
- "ResourcePolicy": "Chính sách tài nguyên"
+ "ResourcePolicy": "Chính sách tài nguyên",
+ "Playground": "Sân chơi",
+ "ModelStore": "Cửa hàng mô hình"
},
"YouAreOffline": "Ngoại tuyến: Không kết nối với bất kỳ mạng nào.",
"YouAreOnline": "Bạn hiện đang trực tuyến",
@@ -1705,7 +1707,10 @@
"category": "Loại",
"CloneToFolder": "Sao chép vào một thư mục",
"FolderAlreadyExists": "Một thư mục có tên này đã tồn tại.",
- "FinetuneModel": "Mô hình Finetune"
+ "FinetuneModel": "Mô hình Finetune",
+ "Experience": "Kinh nghiệm",
+ "ModelCard": "Thẻ mẫu",
+ "ImportFromHuggingFace": "Nhập Từ Ôm Mặt"
},
"table": {
"SettingTable": "Cài đặt bảng",
@@ -1756,5 +1761,11 @@
"hour": "giờ",
"day": "day",
"week": "tuần"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelList": "Danh sách mẫu",
+ "MyServices": "Dịch vụ của tôi"
+ }
}
}
diff --git a/resources/i18n/zh-CN.json b/resources/i18n/zh-CN.json
index 6749d68cba..621ac718eb 100644
--- a/resources/i18n/zh-CN.json
+++ b/resources/i18n/zh-CN.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "输入你的电子邮箱",
"DisMatchUserEmail": "用户电子邮件不匹配",
"MyEnvironments": "我的环境",
- "ResourcePolicy": "资源政策"
+ "ResourcePolicy": "资源政策",
+ "Playground": "操场",
+ "ModelStore": "模型店"
},
"YouAreOffline": "脱机:未连接任何网络。",
"YouAreOnline": "您现在在线",
@@ -1706,7 +1708,10 @@
"category": "类别",
"CloneToFolder": "克隆到文件夹",
"FolderAlreadyExists": "该名称的文件夹已经存在。",
- "FinetuneModel": "微调模型"
+ "FinetuneModel": "微调模型",
+ "Experience": "经验",
+ "ModelCard": "型号卡",
+ "ImportFromHuggingFace": "从拥抱脸导入"
},
"table": {
"SettingTable": "桌面设置",
@@ -1757,5 +1762,11 @@
"hour": "小时",
"day": "day",
"week": "星期"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelList": "型号列表",
+ "MyServices": "我的服务"
+ }
}
}
diff --git a/resources/i18n/zh-TW.json b/resources/i18n/zh-TW.json
index d0e87d4cc2..922067a502 100644
--- a/resources/i18n/zh-TW.json
+++ b/resources/i18n/zh-TW.json
@@ -65,7 +65,9 @@
"InvalidBlankEmail": "輸入你的電子郵件信箱",
"DisMatchUserEmail": "使用者電子郵件不符",
"MyEnvironments": "我的環境",
- "ResourcePolicy": "資源政策"
+ "ResourcePolicy": "資源政策",
+ "Playground": "操場",
+ "ModelStore": "模型店"
},
"YouAreOffline": "脱机:未连接任何网络。",
"YouAreOnline": "您現在在線",
@@ -1706,7 +1708,10 @@
"category": "類別",
"CloneToFolder": "克隆到文件夹",
"FolderAlreadyExists": "该名称的文件夹已经存在。",
- "FinetuneModel": "微調模型"
+ "FinetuneModel": "微調模型",
+ "Experience": "經驗",
+ "ModelCard": "型號卡",
+ "ImportFromHuggingFace": "從擁抱臉導入"
},
"table": {
"SettingTable": "桌面設定",
@@ -1757,5 +1762,11 @@
"hour": "小時",
"day": "day",
"week": "星期"
+ },
+ "modelserving": {
+ "menu": {
+ "ModelList": "型號列表",
+ "MyServices": "我的服務"
+ }
}
}
diff --git a/resources/images/model-player/Llama-2-13b-chat-hf.jpeg b/resources/images/model-player/Llama-2-13b-chat-hf.jpeg
new file mode 100644
index 0000000000..022f7dc51f
Binary files /dev/null and b/resources/images/model-player/Llama-2-13b-chat-hf.jpeg differ
diff --git a/resources/images/model-player/Meta-Llama-3-8B-Instruct.jpeg b/resources/images/model-player/Meta-Llama-3-8B-Instruct.jpeg
new file mode 100644
index 0000000000..a92c1d78a7
Binary files /dev/null and b/resources/images/model-player/Meta-Llama-3-8B-Instruct.jpeg differ
diff --git a/resources/images/model-player/Mistral-7B-Instruct-v0.1.jpeg b/resources/images/model-player/Mistral-7B-Instruct-v0.1.jpeg
new file mode 100644
index 0000000000..e46e758467
Binary files /dev/null and b/resources/images/model-player/Mistral-7B-Instruct-v0.1.jpeg differ
diff --git a/resources/images/model-player/Mixtral-8x7B-Instruct-v0.1.jpeg b/resources/images/model-player/Mixtral-8x7B-Instruct-v0.1.jpeg
new file mode 100644
index 0000000000..34ac27aa93
Binary files /dev/null and b/resources/images/model-player/Mixtral-8x7B-Instruct-v0.1.jpeg differ
diff --git a/resources/images/model-player/Qwen2-7B-Instruct.jpeg b/resources/images/model-player/Qwen2-7B-Instruct.jpeg
new file mode 100644
index 0000000000..b1dcfe79bf
Binary files /dev/null and b/resources/images/model-player/Qwen2-7B-Instruct.jpeg differ
diff --git a/resources/images/model-player/Yi-1.5-9B-Chat.jpeg b/resources/images/model-player/Yi-1.5-9B-Chat.jpeg
new file mode 100644
index 0000000000..10f424840f
Binary files /dev/null and b/resources/images/model-player/Yi-1.5-9B-Chat.jpeg differ
diff --git a/resources/images/model-player/bert-large-cased.jpeg b/resources/images/model-player/bert-large-cased.jpeg
new file mode 100644
index 0000000000..02b347925c
Binary files /dev/null and b/resources/images/model-player/bert-large-cased.jpeg differ
diff --git a/resources/images/model-player/calm3-22b-chat.jpeg b/resources/images/model-player/calm3-22b-chat.jpeg
new file mode 100644
index 0000000000..39ed22d82d
Binary files /dev/null and b/resources/images/model-player/calm3-22b-chat.jpeg differ
diff --git a/resources/images/model-player/clip-vit-large-patch14.jpeg b/resources/images/model-player/clip-vit-large-patch14.jpeg
new file mode 100644
index 0000000000..949af54d17
Binary files /dev/null and b/resources/images/model-player/clip-vit-large-patch14.jpeg differ
diff --git a/resources/images/model-player/efficientnet-b0.jpeg b/resources/images/model-player/efficientnet-b0.jpeg
new file mode 100644
index 0000000000..d7f3594573
Binary files /dev/null and b/resources/images/model-player/efficientnet-b0.jpeg differ
diff --git a/resources/images/model-player/falcon-7b-instruct.jpeg b/resources/images/model-player/falcon-7b-instruct.jpeg
new file mode 100644
index 0000000000..033f64bb5a
Binary files /dev/null and b/resources/images/model-player/falcon-7b-instruct.jpeg differ
diff --git a/resources/images/model-player/flan-t5-xxl.jpeg b/resources/images/model-player/flan-t5-xxl.jpeg
new file mode 100644
index 0000000000..10ce65ae2e
Binary files /dev/null and b/resources/images/model-player/flan-t5-xxl.jpeg differ
diff --git a/resources/images/model-player/gemma-1.1-2b-it.jpeg b/resources/images/model-player/gemma-1.1-2b-it.jpeg
new file mode 100644
index 0000000000..30984bd9e2
Binary files /dev/null and b/resources/images/model-player/gemma-1.1-2b-it.jpeg differ
diff --git a/resources/images/model-player/gemma-2-27b-it.jpeg b/resources/images/model-player/gemma-2-27b-it.jpeg
new file mode 100644
index 0000000000..6ca94dac74
Binary files /dev/null and b/resources/images/model-player/gemma-2-27b-it.jpeg differ
diff --git a/resources/images/model-player/hf-logo.png b/resources/images/model-player/hf-logo.png
new file mode 100644
index 0000000000..49e2841dd5
Binary files /dev/null and b/resources/images/model-player/hf-logo.png differ
diff --git a/resources/images/model-player/hugging-face-background.jpg b/resources/images/model-player/hugging-face-background.jpg
new file mode 100644
index 0000000000..8636743fe1
Binary files /dev/null and b/resources/images/model-player/hugging-face-background.jpg differ
diff --git a/resources/images/model-player/llama-3.1-8b-it.jpeg b/resources/images/model-player/llama-3.1-8b-it.jpeg
new file mode 100644
index 0000000000..6beba14772
Binary files /dev/null and b/resources/images/model-player/llama-3.1-8b-it.jpeg differ
diff --git a/resources/images/model-player/sdxl-turbo.jpeg b/resources/images/model-player/sdxl-turbo.jpeg
new file mode 100644
index 0000000000..9452ba3a6a
Binary files /dev/null and b/resources/images/model-player/sdxl-turbo.jpeg differ
diff --git a/resources/images/model-player/stable-diffusion-2.jpeg b/resources/images/model-player/stable-diffusion-2.jpeg
new file mode 100644
index 0000000000..363b7a2c40
Binary files /dev/null and b/resources/images/model-player/stable-diffusion-2.jpeg differ
diff --git a/resources/images/model-player/stable-diffusion-3-medium.jpeg b/resources/images/model-player/stable-diffusion-3-medium.jpeg
new file mode 100644
index 0000000000..f824c41c2c
Binary files /dev/null and b/resources/images/model-player/stable-diffusion-3-medium.jpeg differ
diff --git a/resources/images/model-player/stable-diffusion-v1-5.jpeg b/resources/images/model-player/stable-diffusion-v1-5.jpeg
new file mode 100644
index 0000000000..8afb7ed5c7
Binary files /dev/null and b/resources/images/model-player/stable-diffusion-v1-5.jpeg differ
diff --git a/resources/images/model-player/talkativot-UI.jpeg b/resources/images/model-player/talkativot-UI.jpeg
new file mode 100644
index 0000000000..e5f6390063
Binary files /dev/null and b/resources/images/model-player/talkativot-UI.jpeg differ
diff --git a/resources/images/model-player/whisper-large-v3.jpeg b/resources/images/model-player/whisper-large-v3.jpeg
new file mode 100644
index 0000000000..0e30907e72
Binary files /dev/null and b/resources/images/model-player/whisper-large-v3.jpeg differ
diff --git a/src/backend-ai-app.ts b/src/backend-ai-app.ts
index c92c60e16d..fac7a07f83 100644
--- a/src/backend-ai-app.ts
+++ b/src/backend-ai-app.ts
@@ -20,6 +20,7 @@ export const navigate =
'/experiment',
'/data',
'/my-environment',
+ '/model-store',
'/statistics',
'/usersettings',
'/agent',
@@ -48,7 +49,7 @@ export const navigate =
}
let page;
if (['/', 'build', '/build', 'app', '/app'].includes(path)) {
- page = 'summary';
+ page = 'playground';
} else if (path[0] === '/') {
page = path.slice(1);
} else {
diff --git a/src/components/backend-ai-error-view.ts b/src/components/backend-ai-error-view.ts
index 447b03acb9..5b83d095db 100644
--- a/src/components/backend-ai-error-view.ts
+++ b/src/components/backend-ai-error-view.ts
@@ -70,8 +70,8 @@ export default class BackendAIErrorView extends BackendAIPage {
* @param {string} url - page to redirect from the current page.
*/
_moveTo(url = '') {
- const page = url !== '' ? url : 'summary';
- globalThis.history.pushState({}, '', '/summary');
+ const page = url !== '' ? url : 'playground';
+ globalThis.history.pushState({}, '', '/playground');
store.dispatch(navigate(decodeURIComponent('/' + page), {}));
document.dispatchEvent(
new CustomEvent('react-navigate', {
@@ -97,8 +97,8 @@ export default class BackendAIErrorView extends BackendAIPage {
unelevated
fullwidth
id="go-to-summary"
- label="${_t('button.GoBackToSummaryPage')}"
- @click="${() => this._moveTo('summary')}"
+ label="${_t('button.GoBackToModelServicesPage')}"
+ @click="${() => this._moveTo('playground')}"
>
diff --git a/src/components/backend-ai-permission-denied-view.ts b/src/components/backend-ai-permission-denied-view.ts
index 503a11adba..eb2a89ed04 100644
--- a/src/components/backend-ai-permission-denied-view.ts
+++ b/src/components/backend-ai-permission-denied-view.ts
@@ -113,8 +113,8 @@ export default class BackendAIPermissionDeniedView extends BackendAIPage {
* @param {string} url - page to redirect from the current page.
*/
_moveTo(url = '') {
- const page = url !== '' ? url : 'summary';
- globalThis.history.pushState({}, '', '/summary');
+ const page = url !== '' ? url : 'playground';
+ globalThis.history.pushState({}, '', '/playground');
store.dispatch(navigate(decodeURIComponent('/' + page), {}));
}
diff --git a/src/components/backend-ai-webui.ts b/src/components/backend-ai-webui.ts
index df6e289260..70cd4515f7 100644
--- a/src/components/backend-ai-webui.ts
+++ b/src/components/backend-ai-webui.ts
@@ -162,6 +162,8 @@ export default class BackendAIWebUI extends connect(store)(LitElement) {
'settings',
'maintenance',
'serving',
+ 'playground',
+ 'model-store',
'service',
'service/start',
'service/update',
diff --git a/version.json b/version.json
index ae38cc4889..830faf2fb5 100644
--- a/version.json
+++ b/version.json
@@ -1 +1 @@
-{ "package": "24.09.0-alpha.1", "buildNumber": "6111", "buildDate": "240703.130731", "revision": "d8cea1cb" }
+{ "package": "25.1.0-alpha.1", "buildNumber": "6441", "buildDate": "250105.230113", "revision": "c18dd4be5" }