feat: generic_proxy
This commit is contained in:
@@ -56,7 +56,9 @@ const icons = {
|
|||||||
type: 'icon-lock_open_right'
|
type: 'icon-lock_open_right'
|
||||||
}),
|
}),
|
||||||
LockPerson: React.createElement(IconFont, { type: 'icon-lock_person' }),
|
LockPerson: React.createElement(IconFont, { type: 'icon-lock_person' }),
|
||||||
LockOpen: React.createElement(IconFont, { type: 'icon-lock_open' })
|
LockOpen: React.createElement(IconFont, { type: 'icon-lock_open' }),
|
||||||
|
Permission: React.createElement(IconFont, { type: 'icon-permission' }),
|
||||||
|
CaptivePortal: React.createElement(IconFont, { type: 'icon-captive_portal' })
|
||||||
};
|
};
|
||||||
|
|
||||||
export default icons;
|
export default icons;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createFromIconfontCN } from '@ant-design/icons';
|
|||||||
// import './iconfont/iconfont.js';
|
// import './iconfont/iconfont.js';
|
||||||
|
|
||||||
const IconFont = createFromIconfontCN({
|
const IconFont = createFromIconfontCN({
|
||||||
scriptUrl: '//at.alicdn.com/t/c/font_4613488_ipdaaask7g.js'
|
scriptUrl: '//at.alicdn.com/t/c/font_4613488_ga8perwfeom.js'
|
||||||
});
|
});
|
||||||
|
|
||||||
export default IconFont;
|
export default IconFont;
|
||||||
|
|||||||
@@ -14,6 +14,17 @@ type WatchConfig =
|
|||||||
| { watch: true; API: string; polling?: false | undefined }
|
| { watch: true; API: string; polling?: false | undefined }
|
||||||
| { polling: true; watch: false | undefined; API?: string };
|
| { polling: true; watch: false | undefined; API?: string };
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param contentForDelete i18n key for delete confirmation modal content
|
||||||
|
* @param fetchAPI API function to fetch data, should return a promise with Global.PageResponse<T>
|
||||||
|
* @param deleteAPI API function to delete an item, should return a promise
|
||||||
|
* @param defaultData default data list
|
||||||
|
* @param events events to watch for chunked updates, default: ['UPDATE', 'DELETE']
|
||||||
|
* @param defaultQueryParams default query parameters for fetching data
|
||||||
|
* @param isInfiniteScroll whether to use infinite scroll mode , use in card list
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
export default function useTableFetch<T>(
|
export default function useTableFetch<T>(
|
||||||
options: {
|
options: {
|
||||||
fetchAPI: (params: any) => Promise<Global.PageResponse<T>>;
|
fetchAPI: (params: any) => Promise<Global.PageResponse<T>>;
|
||||||
|
|||||||
@@ -244,5 +244,8 @@ export default {
|
|||||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||||
'models.catalog.button.explore': 'Explore Other Models',
|
'models.catalog.button.explore': 'Explore Other Models',
|
||||||
'models.catalog.precision': 'Precision',
|
'models.catalog.precision': 'Precision',
|
||||||
'models.form.gpuPerReplica.tips': 'Enter a custom number'
|
'models.form.gpuPerReplica.tips': 'Enter a custom number',
|
||||||
|
'models.form.generic_proxy': 'Enable Generic Proxy',
|
||||||
|
'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
||||||
|
'models.form.generic_proxy.button': 'Generic Proxy'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -244,7 +244,10 @@ export default {
|
|||||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||||
'models.catalog.button.explore': 'Explore Other Models',
|
'models.catalog.button.explore': 'Explore Other Models',
|
||||||
'models.catalog.precision': 'Precision',
|
'models.catalog.precision': 'Precision',
|
||||||
'models.form.gpuPerReplica.tips': 'Enter a custom number'
|
'models.form.gpuPerReplica.tips': 'Enter a custom number',
|
||||||
|
'models.form.generic_proxy': 'Enable Generic Proxy',
|
||||||
|
'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
||||||
|
'models.form.generic_proxy.button': 'Generic Proxy'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -316,6 +319,9 @@ export default {
|
|||||||
// 49. 'models.form.rules.name': 'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
// 49. 'models.form.rules.name': 'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||||
// 50. 'models.catalog.button.explore': 'Explore Other Models',
|
// 50. 'models.catalog.button.explore': 'Explore Other Models',
|
||||||
// 51. 'models.catalog.precision': 'Precision',
|
// 51. 'models.catalog.precision': 'Precision',
|
||||||
// 52. 'models.form.gpuPerReplica.tips': 'Enter a custom number'
|
// 52. 'models.form.gpuPerReplica.tips': 'Enter a custom number',
|
||||||
|
// 53. 'models.form.generic_proxy': 'Enable Generic Proxy',
|
||||||
|
// 54. 'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
||||||
|
// 55. 'models.form.generic_proxy.button': 'Generic Proxy'
|
||||||
|
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -245,10 +245,16 @@ export default {
|
|||||||
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||||
'models.catalog.button.explore': 'Изучить другие модели',
|
'models.catalog.button.explore': 'Изучить другие модели',
|
||||||
'models.catalog.precision': 'Точность',
|
'models.catalog.precision': 'Точность',
|
||||||
'models.form.gpuPerReplica.tips': 'Enter a custom number'
|
'models.form.gpuPerReplica.tips': 'Enter a custom number',
|
||||||
|
'models.form.generic_proxy': 'Enable Generic Proxy',
|
||||||
|
'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
||||||
|
'models.form.generic_proxy.button': 'Generic Proxy'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
// 1. 'models.form.rules.name': 'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
// 1. 'models.form.rules.name': 'Up to 63 characters; letters, numbers, dots (.), underscores (_), and hyphens (-) only; must start and end with an alphanumeric character.',
|
||||||
// 2. 'models.form.gpuPerReplica.tips': 'Enter a custom number'
|
// 2. 'models.form.gpuPerReplica.tips': 'Enter a custom number',
|
||||||
|
// 3. 'models.form.generic_proxy': 'Enable Generic Proxy',
|
||||||
|
// 4. 'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
||||||
|
// 5. 'models.form.generic_proxy.button': 'Generic Proxy'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -231,5 +231,8 @@ export default {
|
|||||||
'长度不超过 63 个字符,只能包含字母、数字、点(.)、下划线(_)和连字符(-),且必须以字母或数字开头和结尾。',
|
'长度不超过 63 个字符,只能包含字母、数字、点(.)、下划线(_)和连字符(-),且必须以字母或数字开头和结尾。',
|
||||||
'models.catalog.button.explore': '浏览其他模型',
|
'models.catalog.button.explore': '浏览其他模型',
|
||||||
'models.catalog.precision': '精度',
|
'models.catalog.precision': '精度',
|
||||||
'models.form.gpuPerReplica.tips': '输入自定义数值'
|
'models.form.gpuPerReplica.tips': '输入自定义数值',
|
||||||
|
'models.form.generic_proxy': '启用通用代理',
|
||||||
|
'models.form.generic_proxy.tips': '启用通用代理',
|
||||||
|
'models.form.generic_proxy.button': '通用代理'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import useCredentialColumns from './hooks/use-credential-columns';
|
|||||||
|
|
||||||
const addActions = [
|
const addActions = [
|
||||||
{
|
{
|
||||||
label: 'Digital Ocean',
|
label: 'DigitalOcean',
|
||||||
locale: false,
|
locale: false,
|
||||||
key: ProviderValueMap.DigitalOcean,
|
key: ProviderValueMap.DigitalOcean,
|
||||||
value: ProviderValueMap.DigitalOcean,
|
value: ProviderValueMap.DigitalOcean,
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ export const ActionList: ActionItem[] = [
|
|||||||
key: 'chat',
|
key: 'chat',
|
||||||
icon: icons.ExperimentOutlined
|
icon: icons.ExperimentOutlined
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// label: 'models.form.generic_proxy.button',
|
||||||
|
// key: 'proxy',
|
||||||
|
// icon: icons.CaptivePortal
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
label: 'models.table.button.apiAccessInfo',
|
label: 'models.table.button.apiAccessInfo',
|
||||||
key: 'api',
|
key: 'api',
|
||||||
@@ -68,7 +73,7 @@ export const ActionList: ActionItem[] = [
|
|||||||
{
|
{
|
||||||
label: 'models.button.accessSettings',
|
label: 'models.button.accessSettings',
|
||||||
key: 'accessControl',
|
key: 'accessControl',
|
||||||
icon: icons.Private
|
icon: icons.Permission
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'common.button.delete',
|
label: 'common.button.delete',
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export interface FormData {
|
|||||||
local_path?: string;
|
local_path?: string;
|
||||||
model_scope_model_id?: string;
|
model_scope_model_id?: string;
|
||||||
model_scope_file_path?: string;
|
model_scope_file_path?: string;
|
||||||
|
generic_proxy?: boolean;
|
||||||
gpu_selector?: {
|
gpu_selector?: {
|
||||||
gpu_ids?: string[];
|
gpu_ids?: string[];
|
||||||
gpu_type?: string;
|
gpu_type?: string;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ const AdvanceConfig = () => {
|
|||||||
}, [backend, backendOptions]);
|
}, [backend, backendOptions]);
|
||||||
|
|
||||||
const handleEnviromentVarsChange = (labels: Record<string, any>) => {
|
const handleEnviromentVarsChange = (labels: Record<string, any>) => {
|
||||||
console.log('handleEnviromentVarsChange', labels);
|
|
||||||
form.setFieldValue('env', labels);
|
form.setFieldValue('env', labels);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,6 +133,20 @@ const AdvanceConfig = () => {
|
|||||||
})}
|
})}
|
||||||
></CheckboxField>
|
></CheckboxField>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{/* <Form.Item<FormData>
|
||||||
|
name="generic_proxy"
|
||||||
|
valuePropName="checked"
|
||||||
|
style={{ marginBottom: 8 }}
|
||||||
|
>
|
||||||
|
<CheckboxField
|
||||||
|
description={intl.formatMessage({
|
||||||
|
id: 'models.form.generic_proxy.tips'
|
||||||
|
})}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
id: 'models.form.generic_proxy'
|
||||||
|
})}
|
||||||
|
></CheckboxField>
|
||||||
|
</Form.Item> */}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ const ScheduleTypeForm: React.FC = () => {
|
|||||||
<InputWrapper>
|
<InputWrapper>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
min={1}
|
min={1}
|
||||||
max={16}
|
max={64}
|
||||||
step={1}
|
step={1}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
defaultValue={
|
defaultValue={
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import ScrollerModal from '@/components/scroller-modal';
|
||||||
|
import CommandViewer from '@/pages/_components/command-viewer';
|
||||||
|
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '@/pages/playground/apis';
|
||||||
|
import { formatCurlArgs } from '@/pages/playground/view-code/utils';
|
||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
const langOptions = [{ label: 'Curl', value: 'bash' }];
|
||||||
|
|
||||||
|
const generateCode = ({ api: url, parameters }: Record<string, any>) => {
|
||||||
|
const host = window.location.origin;
|
||||||
|
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
||||||
|
|
||||||
|
// ========================= Curl =========================
|
||||||
|
const curlCode = `
|
||||||
|
curl ${host}${api} \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
||||||
|
${formatCurlArgs(parameters, false)}`.trim();
|
||||||
|
};
|
||||||
|
|
||||||
|
const useGenericProxy = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const [modalStatus, setModalStatus] = useState<{
|
||||||
|
open: boolean;
|
||||||
|
codeValue: string;
|
||||||
|
}>({ open: false, codeValue: '' });
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
setModalStatus({
|
||||||
|
open: false,
|
||||||
|
codeValue: ''
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const openProxyModal = (data?: any) => {
|
||||||
|
setModalStatus({
|
||||||
|
open: true,
|
||||||
|
codeValue: data?.generic_proxy_command || ''
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const GenericProxyModal = () => {
|
||||||
|
return (
|
||||||
|
<ScrollerModal
|
||||||
|
title={intl.formatMessage({
|
||||||
|
id: 'models.form.generic_title.button'
|
||||||
|
})}
|
||||||
|
open={modalStatus.open}
|
||||||
|
centered={true}
|
||||||
|
onCancel={onCancel}
|
||||||
|
destroyOnHidden={true}
|
||||||
|
closeIcon={true}
|
||||||
|
maskClosable={false}
|
||||||
|
keyboard={false}
|
||||||
|
width={700}
|
||||||
|
footer={false}
|
||||||
|
>
|
||||||
|
<CommandViewer
|
||||||
|
code={modalStatus.codeValue}
|
||||||
|
copyText={modalStatus.codeValue}
|
||||||
|
options={langOptions}
|
||||||
|
defaultValue={'bash'}
|
||||||
|
></CommandViewer>
|
||||||
|
</ScrollerModal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
GenericProxyModal,
|
||||||
|
openProxyModal,
|
||||||
|
setModalStatus
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useGenericProxy;
|
||||||
Reference in New Issue
Block a user