chore: languages settings

main
jialin 2 years ago
parent de96c3d81d
commit 64683fdeb6

@ -6,7 +6,7 @@ export default [
// redirect: ''
// },
{
name: 'Dashboard',
name: 'dashboard',
path: '/dashboard',
key: 'dashboard',
icon: 'home',
@ -14,7 +14,7 @@ export default [
component: './dashboard'
},
{
name: 'Playground',
name: 'playground',
title: 'Playground',
path: '/playground',
key: 'playground',
@ -22,28 +22,28 @@ export default [
component: './playground'
},
{
name: 'Models',
name: 'models',
path: '/models',
key: 'models',
icon: 'Block',
component: './llmodels'
},
{
name: 'Resources',
name: 'resources',
path: '/resources',
key: 'resources',
icon: 'CloudServer',
component: './resources'
},
{
name: 'API Keys',
name: 'apikeys',
path: '/api-keys',
key: 'apikeys',
icon: 'LockOutlined',
component: './api-keys'
},
{
name: 'Users',
name: 'users',
path: '/users',
key: 'users',
icon: 'Team',
@ -51,7 +51,7 @@ export default [
component: './users'
},
{
name: 'Profile',
name: 'profile',
path: '/profile',
key: 'profile',
hideInMenu: true,
@ -59,7 +59,7 @@ export default [
icon: 'User'
},
{
name: 'Login',
name: 'login',
path: '/login',
key: 'login',
layout: false,

@ -10,6 +10,7 @@ import {
history,
matchRoutes,
useAppData,
useIntl,
useLocation,
useNavigate,
type IRoute
@ -78,6 +79,7 @@ const mapRoutes = (routes: IRoute[], role: string) => {
export default (props: any) => {
const location = useLocation();
const navigate = useNavigate();
const intl = useIntl();
const { clientRoutes, pluginManager } = useAppData();
const initialInfo = (useModel && useModel('@@initialState')) || {
@ -94,7 +96,10 @@ export default (props: any) => {
locale: true
};
const formatMessage = undefined;
const formatMessage = (args) => {
console.log('formatMessage', args);
return intl.formatMessage({ id: args.id });
};
const runtimeConfig = {
...initialInfo,
@ -158,8 +163,8 @@ export default (props: any) => {
history.push(pathname);
}
}}
formatMessage={userConfig.formatMessage || formatMessage}
menu={{ locale: userConfig.locale }}
formatMessage={formatMessage}
menu={{ locale: true }}
logo={Logo}
menuItemRender={(menuItemProps, defaultDom) => {
console.log('meurender=========', { defaultDom });

@ -16,6 +16,7 @@ export function getRightRenderContent(opts: {
setInitialState: any;
}) {
console.log('runtimeConfig==', opts.runtimeConfig, opts);
// const intl = useIntl();
if (opts.runtimeConfig.rightRender) {
return opts.runtimeConfig.rightRender(
opts.initialState,
@ -64,7 +65,10 @@ export function getRightRenderContent(opts: {
icon={
<span style={{ fontSize: '12px' }}>
<GlobalOutlined />
<span className="m-l-8"></span>
<span className="m-l-8">
{/* {FormattedMessage({ id: 'common.settings.language' })} */}
Language
</span>
</span>
}
></SelectLang>
@ -83,7 +87,8 @@ export function getRightRenderContent(opts: {
label: (
<>
<SettingOutlined />
{/* {intl.formatMessage({ id: 'common.button.settings' })} */}
Settings
</>
),
onClick: () => {
@ -107,7 +112,8 @@ export function getRightRenderContent(opts: {
label: (
<>
<LogoutOutlined />
退
{/* {intl.formatMessage({ id: 'common.button.logout' })} */}
Logout
</>
),
onClick: () => {

@ -1,9 +1,13 @@
import common from './en-US/common';
import menu from './en-US/menu';
import models from './en-US/models';
import playground from './en-US/playground';
import resources from './en-US/resources';
export default {
...common,
...menu,
...models
...models,
...playground,
...resources
};

@ -0,0 +1,5 @@
export default {
'apikeys.title': 'API Keys',
'apikeys.button.create': 'New API Key',
'apikeys.form.expiretime': 'Expiration'
};

@ -41,6 +41,7 @@ export default {
'common.button.edit': 'Edit',
'common.button.authorize': 'Role Authorization',
'common.button.confirm': 'Confirm',
'common.button.viewlog': 'View Logs',
'common.table.operation': 'Operation',
'common.table.createTime': 'Created',
'common.table.updateTime': 'Updated',
@ -173,6 +174,10 @@ export default {
'common.nodata.created': 'No {type} has been created yet',
'common.nodata.added': 'No {type} has been added yet',
'common.status.edited': 'Edited',
'common.table.user': '用户',
'common.settings.instructions': 'Instructions'
'common.table.user': 'User',
'common.settings.instructions': 'Instructions',
'common.settings.language': 'Language',
'common.delete.confirm':
'Are you sure you want to delete the selected {type}?',
'common.filter.name': 'Filter by name'
};

@ -1 +1,10 @@
export default {};
export default {
'menu.dashboard': 'Dashboard',
'menu.playground': 'Playground',
'menu.models': 'Models',
'menu.resources': 'Resources',
'menu.apikeys': 'API Keys',
'menu.users': 'Users',
'menu.profile': 'Profile',
'menu.login': 'Login'
};

@ -1,3 +1,14 @@
export default {
'models.button.deploy': 'Deploy Model'
'models.button.deploy': 'Deploy Model',
'models.title': 'Models',
'models.table.models': 'models',
'models.table.name': 'Model Name',
'models.form.source': 'Source',
'models.form.repoid': 'Repo ID',
'models.form.repoid.desc': 'Only .gguf format is supported',
'models.form.filename': 'File Name',
'models.form.replicas': 'Replicas',
'models.form.s3address': 'S3 Address',
'models.openinplayground': 'Open in Playground',
'models.instances': 'instances'
};

@ -0,0 +1,17 @@
export default {
'playground.system.tips': 'Enter system message here...',
'playground.title': 'Playground',
'playground.system': 'System',
'playground.user': 'User',
'playground.assistant': 'Assistant',
'playground.newMessage': 'New Message',
'playground.viewcode': 'View Code',
'playground.model': 'Model',
'playground.parameters': 'Parameters',
'playground.viewcode.info':
'You can use the following code to start integrating your current prompt and settings into your application.',
'playground.completion': 'Completion',
'playground.prompt': 'Prompt',
'playground.tokenusage': 'Token Usage',
'models.openinplayground': 'Open in Playground'
};

@ -0,0 +1,11 @@
export default {
'resources.title': 'Resources',
'resources.nodes': 'Nodes',
'resources.table.hostname': 'Hostname',
'resources.table.ip': 'IP',
'resources.table.cpu': 'CPU',
'resources.table.memory': 'Memory',
'resources.table.gpu': 'GPU',
'resources.table.disk': 'Storage',
'resources.table.vram': 'VRAM'
};

@ -1,9 +1,13 @@
import menu from './en-US/menu';
import common from './zh-CN/common';
import models from './zh-CN/models';
import playground from './zh-CN/playground';
import resources from './zh-CN/resources';
export default {
...common,
...menu,
...models
...models,
...playground,
...resources
};

@ -0,0 +1,5 @@
export default {
'apikeys.title': 'API 密钥',
'apikeys.button.create': '新建 API 密钥',
'apikeys.form.expiretime': '过期时间'
};

@ -40,6 +40,7 @@ export default {
'common.button.edit': '编辑',
'common.button.authorize': '角色授权',
'common.button.confirm': '确定',
'common.button.viewlog': '查看日志',
'common.table.operation': '操作',
'common.table.createTime': '创建时间',
'common.table.updateTime': '更新时间',
@ -170,5 +171,8 @@ export default {
'common.nodata.added': '尚未添加{type}',
'common.status.edited': '已编辑',
'common.table.user': '用户',
'common.settings.instructions': '操作指引'
'common.settings.instructions': '操作指引',
'common.settings.language': '语言',
'common.delete.confirm': '确定删除选中的{type}吗?',
'common.filter.name': '名称查询'
};

@ -1 +1,10 @@
export default {};
export default {
'menu.dashboard': '概览',
'menu.playground': '对话',
'menu.models': '模型',
'menu.resources': '资源',
'menu.apikeys': 'API 密钥',
'menu.users': '用户',
'menu.profile': '个人信息',
'menu.login': '登录'
};

@ -1,3 +1,14 @@
export default {
'models.button.deploy': 'Deploy Model'
'models.button.deploy': '部署模型',
'models.title': '模型',
'models.table.models': '模型',
'models.table.name': '模型名称',
'models.form.source': '来源',
'models.form.repoid': '仓库 ID',
'models.form.repoid.desc': '只支持 .gguf 格式',
'models.form.filename': '文件名',
'models.form.replicas': '副本数',
'models.form.s3address': 'S3 地址',
'models.openinplayground': '在 Playground 中打开',
'models.instances': '实例'
};

@ -0,0 +1,16 @@
export default {
'playground.system.tips': '在这里输入系统消息...',
'playground.title': '对话',
'playground.system': '系统',
'playground.user': '用户',
'playground.assistant': '助手',
'playground.newMessage': '新消息',
'playground.viewcode': '查看代码',
'playground.model': '模型',
'playground.parameters': '参数',
'playground.viewcode.info':
'你可以使用以下代码将当前的提示和设置集成到你的应用程序中。',
'playground.completion': '补全',
'playground.prompt': '提示',
'playground.tokenusage': 'Token 使用量'
};

@ -0,0 +1,11 @@
export default {
'resources.title': '资源',
'resources.nodes': '节点',
'resources.table.hostname': '主机名',
'resources.table.ip': 'IP',
'resources.table.cpu': 'CPU',
'resources.table.memory': '内存',
'resources.table.gpu': 'GPU',
'resources.table.disk': '磁盘',
'resources.table.vram': '显存'
};

@ -1,7 +1,7 @@
import { request } from '@umijs/max';
import { FormData, ListItem } from '../config/types';
export const APIS_KEYS_API = '/api_keys';
export const APIS_KEYS_API = '/api-keys';
export async function queryApisKeysList(
params: Global.Pagination & { query?: string }

@ -27,37 +27,6 @@ import { FormData, ListItem } from './config/types';
const { Column } = Table;
const list = [
{
key: '1',
name: 'local',
secretKey: `auk_uzem...owsa`,
lastusedTime: '2024-05-22 12:20:10',
createTime: '2024-05-20 12:13:25'
},
{
key: '2',
name: 'dev',
secretKey: `auk_uzem...okwa`,
lastusedTime: '2024-05-19 13:30:22',
createTime: '2024-05-18 10:28:32'
},
{
key: '3',
name: 'prod',
secretKey: `auk_uzem...uuds`,
lastusedTime: '2024-05-18 10:28:32',
createTime: '2024-05-17 08:21:09'
},
{
key: '4',
name: 'test',
secretKey: `auk_uzem...uksa`,
lastusedTime: '2024-05-18 10:28:32',
createTime: '2024-05-16 13:33:23'
}
];
const Models: React.FC = () => {
const rowSelection = useTableRowSelection();
const { sortOrder, setSortOrder } = useTableSort({

@ -9,7 +9,7 @@ import {
export const MODELS_API = '/models';
export const MODEL_INSTANCE_API = '/model_instances';
export const MODEL_INSTANCE_API = '/model-instances';
// ===================== Models =====================
export async function queryModelsList(

@ -5,6 +5,7 @@ import SealSelect from '@/components/seal-form/seal-select';
import { PageAction } from '@/config';
import { PageActionType } from '@/config/types';
import { convertFileSize } from '@/utils';
import { useIntl } from '@umijs/max';
import { Form, Input, Modal } from 'antd';
import _ from 'lodash';
import { useEffect, useState } from 'react';
@ -31,6 +32,7 @@ const sourceOptions = [
const AddModal: React.FC<AddModalProps> = (props) => {
const { title, action, open, onOk, onCancel } = props || {};
const [form] = Form.useForm();
const intl = useIntl();
const modelSource = Form.useWatch('source', form);
const [repoOptions, setRepoOptions] = useState<
{ label: string; value: string }[]
@ -42,7 +44,8 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const initFormValue = () => {
if (action === PageAction.CREATE && open) {
form.setFieldsValue({
source: 'huggingface'
source: 'huggingface',
replicas: 1
});
}
};
@ -51,9 +54,7 @@ const AddModal: React.FC<AddModalProps> = (props) => {
initFormValue();
}, [open]);
const handleInputRepoChange = (value: string) => {
console.log('repo change', value);
};
const handleInputRepoChange = (value: string) => {};
const fileNamLabel = (item: any) => {
return (
@ -87,7 +88,6 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const handleRepoOnBlur = (e: any) => {
const repo = form.getFieldValue('huggingface_repo_id');
console.log('repo blur', repo);
handleRepoSelect(repo);
};
@ -119,28 +119,48 @@ const AddModal: React.FC<AddModalProps> = (props) => {
<>
<Form.Item<FormData>
name="huggingface_repo_id"
rules={[{ required: true }]}
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.input'
},
{ name: intl.formatMessage({ id: 'models.form.repoid' }) }
)
}
]}
>
<SealAutoComplete
label="Repo ID"
label={intl.formatMessage({ id: 'models.form.repoid' })}
required
showSearch
onBlur={handleRepoOnBlur}
onChange={handleInputRepoChange}
onSearch={debounceSearch}
options={repoOptions}
description="Only .gguf format is supported"
description={intl.formatMessage({ id: 'models.form.repoid.desc' })}
>
<Input.Search style={{ width: '520px' }}></Input.Search>
</SealAutoComplete>
</Form.Item>
<Form.Item<FormData>
name="huggingface_filename"
rules={[{ required: true }]}
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.input'
},
{ name: intl.formatMessage({ id: 'models.form.filename' }) }
)
}
]}
>
<SealAutoComplete
showSearch
label="File Name"
label={intl.formatMessage({ id: 'models.form.filename' })}
required
options={fileOptions}
></SealAutoComplete>
@ -152,8 +172,26 @@ const AddModal: React.FC<AddModalProps> = (props) => {
const renderS3Fields = () => {
return (
<>
<Form.Item<FormData> name="s3_address" rules={[{ required: true }]}>
<SealInput.Input label="S3 Address" required></SealInput.Input>
<Form.Item<FormData>
name="s3_address"
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.input'
},
{ name: intl.formatMessage({ id: 'models.form.s3address' }) }
)
}
]}
>
<SealInput.Input
label={intl.formatMessage({
id: 'models.form.s3address'
})}
required
></SealInput.Input>
</Form.Item>
</>
);
@ -164,9 +202,22 @@ const AddModal: React.FC<AddModalProps> = (props) => {
<>
<Form.Item<FormData>
name="ollama_library_model_name"
rules={[{ required: true }]}
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.input'
},
{ name: intl.formatMessage({ id: 'models.table.name' }) }
)
}
]}
>
<SealInput.Input label="Model Name" required></SealInput.Input>
<SealInput.Input
label={intl.formatMessage({ id: 'models.table.name' })}
required
></SealInput.Input>
</Form.Item>
</>
);
@ -212,28 +263,80 @@ const AddModal: React.FC<AddModalProps> = (props) => {
}
>
<Form name="addModalForm" form={form} onFinish={onOk} preserve={false}>
<Form.Item<FormData> name="name" rules={[{ required: true }]}>
<SealInput.Input label="Name" required></SealInput.Input>
<Form.Item<FormData>
name="name"
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.input'
},
{ name: intl.formatMessage({ id: 'common.table.name' }) }
)
}
]}
>
<SealInput.Input
label={intl.formatMessage({
id: 'common.table.name'
})}
required
></SealInput.Input>
</Form.Item>
<Form.Item<FormData> name="source" rules={[{ required: true }]}>
<Form.Item<FormData>
name="source"
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.select'
},
{ name: intl.formatMessage({ id: 'models.form.source' }) }
)
}
]}
>
<SealSelect
label="Source"
label={intl.formatMessage({
id: 'models.form.source'
})}
options={sourceOptions}
required
onChange={handleSourceChange}
></SealSelect>
</Form.Item>
{renderFieldsBySource()}
<Form.Item<FormData> name="replicas" rules={[{ required: true }]}>
<Form.Item<FormData>
name="replicas"
rules={[
{
required: true,
message: intl.formatMessage(
{
id: 'common.form.rule.input'
},
{ name: intl.formatMessage({ id: 'models.form.replicas' }) }
)
}
]}
>
<SealInput.Number
style={{ width: '100%' }}
label="Replicas"
label={intl.formatMessage({
id: 'models.form.replicas'
})}
required
min={1}
></SealInput.Number>
</Form.Item>
<Form.Item<FormData> name="description">
<SealInput.TextArea label="Description"></SealInput.TextArea>
<SealInput.TextArea
label={intl.formatMessage({
id: 'common.table.description'
})}
></SealInput.TextArea>
</Form.Item>
</Form>
</Modal>

@ -178,7 +178,6 @@ const Models: React.FC = () => {
const handleAddModal = () => {
setOpenAddModal(true);
setAction(PageAction.CREATE);
setTitle('Deploy Model');
};
const handleClickMenu = (e: any) => {
@ -186,10 +185,9 @@ const Models: React.FC = () => {
};
const handleModalOk = async (data: FormData) => {
console.log('handleModalOk', data);
await createModel({ data });
setOpenAddModal(false);
message.success('successfully!');
message.success(intl.formatMessage({ id: 'common.message.success' }));
};
const handleModalCancel = () => {
@ -203,10 +201,13 @@ const Models: React.FC = () => {
const handleDelete = async (row: any) => {
Modal.confirm({
title: '',
content: 'Are you sure you want to delete the selected models?',
content: intl.formatMessage(
{ id: 'common.delete.confirm' },
{ type: intl.formatMessage({ id: 'models.table.models' }) }
),
async onOk() {
await deleteModel(row.id);
message.success('successfully!');
message.success(intl.formatMessage({ id: 'common.message.success' }));
fetchData();
},
onCancel() {
@ -217,10 +218,13 @@ const Models: React.FC = () => {
const handleDeleteBatch = () => {
Modal.confirm({
title: '',
content: 'Are you sure you want to delete the selected models?',
content: intl.formatMessage(
{ id: 'common.delete.confirm' },
{ type: intl.formatMessage({ id: 'models.table.models' }) }
),
async onOk() {
await handleBatchRequest(rowSelection.selectedRowKeys, deleteModel);
message.success('successfully!');
message.success(intl.formatMessage({ id: 'common.message.success' }));
fetchData();
},
onCancel() {
@ -244,7 +248,7 @@ const Models: React.FC = () => {
source: row.source
};
await createModelInstance({ data });
message.success('successfully!');
message.success(intl.formatMessage({ id: 'common.message.success' }));
} catch (error) {}
};
@ -258,11 +262,13 @@ const Models: React.FC = () => {
const handleDeleteInstace = (row: any) => {
Modal.confirm({
title: '',
content: 'Are you sure you want to delete the instance?',
content: intl.formatMessage(
{ id: 'common.delete.confirm' },
{ type: intl.formatMessage({ id: 'models.instances' }) }
),
async onOk() {
console.log('OK');
await deleteModelInstance(row.id);
message.success('successfully!');
message.success(intl.formatMessage({ id: 'common.message.success' }));
fetchData();
},
onCancel() {
@ -343,7 +349,11 @@ const Models: React.FC = () => {
<Col span={7}>
{hoverChildIndex === `${item.id}-${index}` && (
<Space size={20}>
<Tooltip title="Delete">
<Tooltip
title={intl.formatMessage({
id: 'common.button.delete'
})}
>
<Button
size="small"
danger
@ -351,7 +361,11 @@ const Models: React.FC = () => {
icon={<DeleteOutlined></DeleteOutlined>}
></Button>
</Tooltip>
<Tooltip title="View Logs">
<Tooltip
title={intl.formatMessage({
id: 'common.button.viewlog'
})}
>
<Button
size="small"
onClick={() => handleViewLogs(item)}
@ -375,7 +389,7 @@ const Models: React.FC = () => {
<PageContainer
ghost
header={{
title: 'Models'
title: intl.formatMessage({ id: 'models.title' })
}}
extra={[]}
>
@ -384,7 +398,7 @@ const Models: React.FC = () => {
left={
<Space>
<Input
placeholder="名称查询"
placeholder={intl.formatMessage({ id: 'common.filter.name' })}
style={{ width: 300 }}
allowClear
onChange={handleNameChange}
@ -413,7 +427,7 @@ const Models: React.FC = () => {
onClick={handleDeleteBatch}
disabled={!rowSelection.selectedRowKeys.length}
>
Delete
{intl?.formatMessage?.({ id: 'common.button.delete' })}
</Button>
</Access>
</Space>
@ -440,7 +454,7 @@ const Models: React.FC = () => {
}}
>
<SealColumn
title="Model Name"
title={intl.formatMessage({ id: 'models.table.name' })}
dataIndex="name"
key="name"
width={400}
@ -461,7 +475,7 @@ const Models: React.FC = () => {
/>
<SealColumn
span={8}
title="Create Time"
title={intl.formatMessage({ id: 'common.table.createTime' })}
dataIndex="created_at"
key="createTime"
defaultSortOrder="descend"
@ -474,12 +488,16 @@ const Models: React.FC = () => {
/>
<SealColumn
span={8}
title="Operation"
title={intl.formatMessage({ id: 'common.table.operation' })}
key="operation"
render={(text, record) => {
return !record.transition ? (
<Space size={20}>
<Tooltip title="Open in PlayGround">
<Tooltip
title={intl.formatMessage({
id: 'models.openinplayground'
})}
>
<Button
size="small"
type="primary"
@ -487,7 +505,9 @@ const Models: React.FC = () => {
icon={<WechatWorkOutlined />}
></Button>
</Tooltip>
<Tooltip title="Delete">
<Tooltip
title={intl.formatMessage({ id: 'common.button.delete' })}
>
<Button
size="small"
type="primary"
@ -505,12 +525,12 @@ const Models: React.FC = () => {
<AddModal
open={openAddModal}
action={action}
title={title}
title={intl.formatMessage({ id: 'models.button.deploy' })}
onCancel={handleModalCancel}
onOk={handleModalOk}
></AddModal>
<ViewLogsModal
title="View Logs"
title={intl.formatMessage({ id: 'common.button.viewlog' })}
open={openLogModal}
onCancel={handleLogModalCancel}
></ViewLogsModal>

@ -63,7 +63,7 @@ const Login = () => {
return (
<Form
form={form}
style={{ width: '400px', margin: '5% auto 0' }}
style={{ width: '400px', margin: '0 auto', paddingTop: '5%' }}
onFinish={handleLogin}
>
<div>{renderLogo()}</div>

@ -4,6 +4,7 @@ import {
PlusOutlined,
SaveOutlined
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Col, Row, Space } from 'antd';
import '../style/chat-footer.less';
@ -17,6 +18,7 @@ interface ChatFooterProps {
}
const ChatFooter: React.FC<ChatFooterProps> = (props) => {
const intl = useIntl();
const { onSubmit, onClear, onNewMessage, onView, feedback, disabled } = props;
return (
<div className="chat-footer">
@ -29,14 +31,14 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
icon={<PlusOutlined />}
onClick={onNewMessage}
>
New Message
{intl.formatMessage({ id: 'playground.newMessage' })}
</Button>
<Button
icon={<DeleteOutlined></DeleteOutlined>}
onClick={onClear}
disabled={disabled}
>
Clear
{intl.formatMessage({ id: 'common.button.clear' })}
</Button>
</Space>
</Col>
@ -48,7 +50,7 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
onClick={onView}
disabled={disabled}
>
View Code
{intl.formatMessage({ id: 'playground.viewcode' })}
</Button>
<Button
disabled={disabled}
@ -56,7 +58,7 @@ const ChatFooter: React.FC<ChatFooterProps> = (props) => {
icon={<SaveOutlined></SaveOutlined>}
onClick={onSubmit}
>
Submit
{intl.formatMessage({ id: 'common.button.submit' })}
</Button>
</Space>
</Col>

@ -1,6 +1,7 @@
import TransitionWrapper from '@/components/transition';
import { EyeInvisibleOutlined } from '@ant-design/icons';
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import { Button, Input, Spin } from 'antd';
import _ from 'lodash';
import { useRef, useState } from 'react';
@ -34,6 +35,7 @@ const MessageList: React.FC<MessageProps> = (props) => {
}
]);
const intl = useIntl();
const [systemMessage, setSystemMessage] = useState('');
const [show, setShow] = useState(false);
const [loading, setLoading] = useState(false);
@ -73,7 +75,8 @@ const MessageList: React.FC<MessageProps> = (props) => {
...messageList
]
: [...messageList],
...parameters
...parameters,
stream: true
};
const data = await execChatCompletions(chatParams);
const assistant = _.get(data, ['choices', '0', 'message']);
@ -118,14 +121,15 @@ const MessageList: React.FC<MessageProps> = (props) => {
const handleUpdateMessage = (index: number, message: MessageItemProps) => {
messageList[index] = message;
console.log('updatemessage========', index, message);
setMessageList([...messageList]);
};
const renderLabel = () => {
return (
<div className="system-message-wrap ">
<span className="title">System</span>
<span className="title">
{intl.formatMessage({ id: 'playground.system' })}
</span>
<Button type="primary" size="small">
<EyeInvisibleOutlined />
</Button>
@ -145,7 +149,7 @@ const MessageList: React.FC<MessageProps> = (props) => {
value={systemMessage}
variant="filled"
autoSize={true}
placeholder="Enter system message here..."
placeholder={intl.formatMessage({ id: 'playground.system.tips' })}
onChange={handleSystemMessageChange}
></Input.TextArea>
</TransitionWrapper>
@ -193,9 +197,9 @@ const MessageList: React.FC<MessageProps> = (props) => {
open={show}
systemMessage={systemMessage}
messageList={messageList}
parameters={parameters}
parameters={{ ...parameters, stream: true }}
onCancel={handleCloseViewCode}
title="View code"
title={intl.formatMessage({ id: 'playground.viewcode' })}
></ViewCodeModal>
</div>
);

@ -1,6 +1,6 @@
import { MinusCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Input } from 'antd';
import _ from 'lodash';
import { memo, useEffect, useRef, useState } from 'react';
import { Roles } from '../config';
import '../style/message-item.less';
@ -18,6 +18,7 @@ const MessageItem: React.FC<{
isFocus: boolean;
onDelete: () => void;
}> = ({ message, isFocus, onDelete, updateMessage }) => {
const intl = useIntl();
const [roleType, setRoleType] = useState(message.role);
const [isTyping, setIsTyping] = useState(false);
const [messageContent, setMessageContent] = useState(message.content);
@ -87,7 +88,7 @@ const MessageItem: React.FC<{
<div className="message-item">
<div className="role-type">
<Button onClick={handleRoleChange} type="text">
{_.upperFirst(roleType)}
{intl.formatMessage({ id: `playground.${roleType}` })}
</Button>
</div>
<div className="message-content-input">

@ -3,6 +3,7 @@ import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { INPUT_WIDTH } from '@/constants';
import { queryModelsList } from '@/pages/llmodels/apis';
import { useIntl } from '@umijs/max';
import { Button, Form, InputNumber, Slider } from 'antd';
import _ from 'lodash';
import { useEffect, useState } from 'react';
@ -29,6 +30,7 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
selectedModel,
setParams
}) => {
const intl = useIntl();
const [ModelList, setModelList] = useState([]);
const initialValues = {
seed: null,
@ -137,17 +139,22 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
onFinishFailed={handleOnFinishFailed}
>
<div>
<h3 className="m-b-20 m-l-10">Model</h3>
<h3 className="m-b-20 m-l-10">
{intl.formatMessage({ id: 'playground.model' })}
</h3>
<Form.Item<ParamsSettingsFormProps>
name="model"
rules={[{ required: true }]}
>
<SealSelect options={ModelList} label="Model"></SealSelect>
<SealSelect
options={ModelList}
label={intl.formatMessage({ id: 'playground.model' })}
></SealSelect>
</Form.Item>
<h3 className="m-b-20 m-l-10 flex-between flex-center">
<span>Parameters</span>
<span>{intl.formatMessage({ id: 'playground.parameters' })}</span>
<Button size="small" onClick={handleResetParams}>
Reset
{intl.formatMessage({ id: 'common.button.reset' })}
</Button>
</h3>
<Form.Item<ParamsSettingsFormProps>
@ -195,10 +202,6 @@ const ParamsSettings: React.FC<ParamsSettingsProps> = ({
onChange={(val) => handleFieldValueChange(val, 'max_tokens')}
></Slider>
</FieldWrapper>
{/* <SealInput.Number
label="Max Tokens"
style={{ width: INPUT_WIDTH.mini }}
></SealInput.Number> */}
</Form.Item>
<Form.Item<ParamsSettingsFormProps>
name="top_p"

@ -1,3 +1,4 @@
import { useIntl } from '@umijs/max';
import { Space, Tooltip } from 'antd';
import '../style/reference-params.less';
@ -10,6 +11,7 @@ interface ReferenceParamsProps {
}
const ReferenceParams = (props: ReferenceParamsProps) => {
const intl = useIntl();
const { usage } = props;
if (!usage) {
return null;
@ -19,12 +21,21 @@ const ReferenceParams = (props: ReferenceParamsProps) => {
<Tooltip
title={
<Space>
<span>Completion: {usage.completion_tokens}</span>
<span>Prompt: {usage.prompt_tokens}</span>
<span>
{intl.formatMessage({ id: 'playground.completion' })}:{' '}
{usage.completion_tokens}
</span>
<span>
{intl.formatMessage({ id: 'playground.prompt' })}:{' '}
{usage.prompt_tokens}
</span>
</Space>
}
>
<span>Token Usage: {usage.total_tokens}</span>
<span>
{intl.formatMessage({ id: 'playground.tokenusage' })}:{' '}
{usage.total_tokens}
</span>
</Tooltip>
</div>
);

@ -1,5 +1,6 @@
import EditorWrap from '@/components/editor-wrap';
import Editor from '@monaco-editor/react';
import { useIntl } from '@umijs/max';
import { Modal, Spin } from 'antd';
import _ from 'lodash';
import React, { useEffect, useRef, useState } from 'react';
@ -23,6 +24,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
parameters = {}
} = props || {};
const intl = useIntl();
const editorRef = useRef(null);
const [loaded, setLoaded] = useState(false);
const [codeValue, setCodeValue] = useState('');
@ -34,16 +36,24 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
{ label: 'Nodejs', value: 'javascript' }
];
useEffect(() => {
generateCode();
}, [lang, systemMessage, messageList, parameters]);
const formatCode = () => {
if (editorRef.current) {
setTimeout(() => {
editorRef.current
?.getAction?.('editor.action.formatDocument')
?.run()
.then(() => {
console.log('format success');
});
}, 100);
}
};
const generateCode = () => {
if (lang === 'shell') {
const systemList = systemMessage
? [{ role: 'system', content: systemMessage }]
: [];
const code = `curl ${window.location.origin}/v1/chat/completions \n-H "Content-Type: application/json" \n-H "Authorization: Bearer $\{GPUSTACK_API_KEY}\" \n-d '${JSON.stringify(
const code = `curl ${window.location.origin}/v1/chat/completions \n-H "Content-Type: application/json" \n-H "Authorization: Bearer $\{GPUSTACK_API_KEY}" \n-d '${JSON.stringify(
{
...parameters,
messages: [...systemList, ...messageList]
@ -92,19 +102,6 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
setLoaded(true);
};
function formatCode() {
if (editorRef.current) {
setTimeout(() => {
editorRef.current
?.getAction?.('editor.action.formatDocument')
?.run()
.then(() => {
console.log('format success');
});
}, 100);
}
}
const handleOnChangeLang = (value: string) => {
setLang(value);
};
@ -124,6 +121,10 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
}
};
useEffect(() => {
generateCode();
}, [lang, systemMessage, messageList, parameters]);
return (
<>
<Modal
@ -139,8 +140,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
footer={null}
>
<div style={{ marginBottom: '10px' }}>
You can use the following code to start integrating your current
prompt and settings into your application.
{intl.formatMessage({ id: 'playground.viewcode.info' })}
</div>
<Spin spinning={!loaded}>
<EditorWrap
@ -162,10 +162,6 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
/>
</EditorWrap>
</Spin>
<div style={{ marginTop: '10px' }}>
our API Key can be foundhere You should use environment variables or a
secret management tool to expose your key to your applications.
</div>
</Modal>
</>
);

@ -5,10 +5,10 @@ export const Roles = {
export const playGroundRoles = [
{
key: 'user',
label: 'User'
label: 'playground.user'
},
{
key: 'assistant',
label: 'Assistant'
label: 'playground.assitant'
}
];

@ -4,6 +4,7 @@ import StatusTag from '@/components/status-tag';
import useTableRowSelection from '@/hooks/use-table-row-selection';
import useTableSort from '@/hooks/use-table-sort';
import { SyncOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Input, Space, Table } from 'antd';
import _ from 'lodash';
import { useEffect, useState } from 'react';
@ -16,6 +17,7 @@ const Models: React.FC = () => {
const { sortOrder, setSortOrder } = useTableSort({
defaultSortOrder: 'descend'
});
const intl = useIntl();
const [total, setTotal] = useState(0);
const [loading, setLoading] = useState(false);
const [dataSource, setDataSource] = useState<ListItem[]>([]);
@ -86,7 +88,9 @@ const Models: React.FC = () => {
left={
<Space>
<Input
placeholder="名称查询"
placeholder={intl.formatMessage({
id: 'common.filter.name'
})}
style={{ width: 300 }}
onChange={handleNameChange}
></Input>
@ -114,9 +118,13 @@ const Models: React.FC = () => {
onChange: handlePageChange
}}
>
<Column title="Host Name" dataIndex="hostname" key="hostname" />
<Column
title="State"
title={intl.formatMessage({ id: 'resources.table.hostname' })}
dataIndex="hostname"
key="hostname"
/>
<Column
title={intl.formatMessage({ id: 'common.table.status' })}
dataIndex="state"
key="state"
render={(text, record: ListItem) => {
@ -145,7 +153,7 @@ const Models: React.FC = () => {
}}
/>
<Column
title="Memory"
title={intl.formatMessage({ id: 'resources.table.memory' })}
dataIndex="memory"
key="Memory"
render={(text, record: ListItem) => {
@ -177,7 +185,15 @@ const Models: React.FC = () => {
}}
/>
<Column
title="VRAM"
title={intl.formatMessage({ id: 'resources.table.disk' })}
dataIndex="storage"
key="storage"
render={(text, record: ListItem) => {
return <ProgressBar percent={0}></ProgressBar>;
}}
/>
<Column
title={intl.formatMessage({ id: 'resources.table.vram' })}
dataIndex="VRAM"
key="VRAM"
render={(text, record: ListItem) => {

@ -1,4 +1,5 @@
import { PageContainer } from '@ant-design/pro-components';
import { useIntl } from '@umijs/max';
import type { TabsProps } from 'antd';
import { Tabs } from 'antd';
import { useState } from 'react';
@ -20,6 +21,8 @@ const items: TabsProps['items'] = [
const Resources = () => {
const [activeKey, setActiveKey] = useState('test');
const intl = useIntl();
const handleChangeTab = (key: string) => {
setActiveKey(key);
};
@ -28,7 +31,7 @@ const Resources = () => {
<PageContainer
ghost
header={{
title: 'Resources'
title: intl.formatMessage({ id: 'resources.title' })
}}
extra={[]}
>

Loading…
Cancel
Save