fix: add worker token do not update

This commit is contained in:
jialin
2025-11-20 10:31:27 +08:00
parent 2687fb187d
commit 5d383ec39b
11 changed files with 197 additions and 19 deletions
@@ -11,6 +11,7 @@ interface ViewerProps {
options?: Global.BaseOption<string>[]; options?: Global.BaseOption<string>[];
defaultValue?: string; defaultValue?: string;
headerHeight?: number; headerHeight?: number;
height?: number;
lang?: string; lang?: string;
onChange?: (value: string | number) => void; onChange?: (value: string | number) => void;
} }
@@ -31,6 +32,7 @@ const CommandViewer: React.FC<ViewerProps> = (props) => {
defaultValue, defaultValue,
options = [], options = [],
headerHeight = 40, headerHeight = 40,
height = 380,
lang, lang,
onChange onChange
} = props || {}; } = props || {};
@@ -66,7 +68,7 @@ const CommandViewer: React.FC<ViewerProps> = (props) => {
} }
> >
<HighlightCode <HighlightCode
height={380} height={height}
theme="dark" theme="dark"
code={code} code={code}
lang={lang || value} lang={lang || value}
+2 -1
View File
@@ -36,6 +36,7 @@ import PoolRows from './components/pool-rows';
import { ProviderType, ProviderValueMap } from './config'; import { ProviderType, ProviderValueMap } from './config';
import { import {
ClusterListItem, ClusterListItem,
CredentialListItem,
ClusterFormData as FormData, ClusterFormData as FormData,
ClusterListItem as ListItem, ClusterListItem as ListItem,
NodePoolFormData NodePoolFormData
@@ -231,7 +232,7 @@ const Clusters: React.FC = () => {
useEffect(() => { useEffect(() => {
const fetchCredentialList = async () => { const fetchCredentialList = async () => {
const data = await queryCredentialList({ page: -1 }); const data = await queryCredentialList({ page: -1 });
const list = data?.items?.map((item) => ({ const list = data?.items?.map((item: CredentialListItem) => ({
label: item.name, label: item.name,
value: item.id value: item.id
})); }));
@@ -79,6 +79,9 @@ const AddWorker: React.FC<AddWorkerProps> = (props) => {
if (open && cluster_id && firstLoad.current) { if (open && cluster_id && firstLoad.current) {
handleOnClusterChange(cluster_id); handleOnClusterChange(cluster_id);
} }
return () => {
firstLoad.current = true;
};
}, [open, cluster_id]); }, [open, cluster_id]);
return ( return (
@@ -17,10 +17,11 @@ import { useIntl, useNavigate } from '@umijs/max';
import { useMemoizedFn } from 'ahooks'; import { useMemoizedFn } from 'ahooks';
import { Button, Tag } from 'antd'; import { Button, Tag } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import { useMemo } from 'react'; import { useEffect, useMemo } from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { modelCategoriesMap } from '../config'; import { modelCategoriesMap } from '../config';
import { ListItem } from '../config/types'; import { ListItem } from '../config/types';
import useGenericProxy from '../hooks/use-generic-proxy';
const GPUSTACK_API = GPUSTACK_API_BASE_URL; const GPUSTACK_API = GPUSTACK_API_BASE_URL;
@@ -75,7 +76,7 @@ const Tips = styled.div`
gap: 8px; gap: 8px;
} }
dd { dd {
margin-bottom: 16px; margin-bottom: 0;
} }
`; `;
@@ -98,21 +99,22 @@ interface ApiAccessInfoProps {
const ApiAccessInfo = ({ open, data, onClose }: ApiAccessInfoProps) => { const ApiAccessInfo = ({ open, data, onClose }: ApiAccessInfoProps) => {
const intl = useIntl(); const intl = useIntl();
const navigate = useNavigate(); const navigate = useNavigate();
const { GenericProxyCommandCode, openProxyModal } = useGenericProxy();
const getModelCategory = useMemoizedFn((categories: string[]) => { const getProxyEndPoint = useMemoizedFn((categories: string[]) => {
for (const [category, config] of Object.entries(API_MAP)) { for (const [category, config] of Object.entries(API_MAP)) {
if (categories.includes(category)) { if (categories.includes(category)) {
return `${MODEL_PROXY}${config.api}`; return `${MODEL_PROXY}${config.api}`;
} }
} }
return `${MODEL_PROXY}${CHAT_API}`; return `${window.location.origin}${MODEL_PROXY}/<YOUR_API_PATH>`;
}); });
const endPoint = useMemo(() => { const endPoint = useMemo(() => {
if (!data.generic_proxy) { if (!data.generic_proxy) {
return `${window.location.origin}/${GPUSTACK_API}`; return `${window.location.origin}/${GPUSTACK_API}`;
} }
return getModelCategory(data.categories || []); return getProxyEndPoint(data.categories || []);
}, [data]); }, [data]);
const isRanker = useMemo(() => { const isRanker = useMemo(() => {
@@ -123,6 +125,12 @@ const ApiAccessInfo = ({ open, data, onClose }: ApiAccessInfoProps) => {
onClose(); onClose();
}; };
useEffect(() => {
if (open && data.generic_proxy) {
openProxyModal(data);
}
}, [open, data, openProxyModal]);
return ( return (
<ScrollerModal <ScrollerModal
open={open} open={open}
@@ -130,7 +138,7 @@ const ApiAccessInfo = ({ open, data, onClose }: ApiAccessInfoProps) => {
top: '20%' top: '20%'
}} }}
title={intl.formatMessage({ id: 'models.table.button.apiAccessInfo' })} title={intl.formatMessage({ id: 'models.table.button.apiAccessInfo' })}
width={550} width={600}
destroyOnHidden destroyOnHidden
closable={true} closable={true}
maskClosable={false} maskClosable={false}
@@ -156,12 +164,17 @@ const ApiAccessInfo = ({ open, data, onClose }: ApiAccessInfoProps) => {
></dd> ></dd>
</dl> </dl>
</Tips> </Tips>
{data.generic_proxy && (
<div style={{ paddingLeft: 20, marginBottom: 12 }}>
{GenericProxyCommandCode}
</div>
)}
<ApiAccessInfoWrapper> <ApiAccessInfoWrapper>
<span className="label"> <span className="label">
{intl.formatMessage({ id: 'models.table.apiAccessInfo.endpoint' })} {intl.formatMessage({ id: 'models.table.apiAccessInfo.endpoint' })}
</span> </span>
<span className="value"> <span className="value">
<AutoTooltip ghost maxWidth={data.generic_proxy ? 300 : 180}> <AutoTooltip ghost maxWidth={data.generic_proxy ? 400 : 180}>
{endPoint} {endPoint}
</AutoTooltip> </AutoTooltip>
{!data.generic_proxy && ( {!data.generic_proxy && (
+1 -1
View File
@@ -106,7 +106,7 @@ const KVCacheForm = () => {
)} )}
min={0} min={0}
step={1} step={1}
precision={1} precision={0}
/> />
</Form.Item> </Form.Item>
<Form.Item<FormData> name={['extended_kv_cache', 'chunk_size']}> <Form.Item<FormData> name={['extended_kv_cache', 'chunk_size']}>
@@ -0,0 +1,149 @@
import CommandViewer from '@/pages/_components/command-viewer';
import {
AUDIO_SPEECH_TO_TEXT_API,
AUDIO_TEXT_TO_SPEECH_API,
CHAT_API,
CREAT_IMAGE_API,
EMBEDDING_API,
MODEL_PROXY,
RERANKER_API
} from '@/pages/playground/apis';
import {
generateSpeechToTextCurlCode,
generateTextToSpeechCurlCode
} from '@/pages/playground/view-code/audio';
import { generateEmbeddingCurlCode } from '@/pages/playground/view-code/embedding';
import { generateImageCurlCode } from '@/pages/playground/view-code/image';
import { generateLLmCurlCode } from '@/pages/playground/view-code/llm';
import { generateRerankCurlCode } from '@/pages/playground/view-code/rerank';
import { useMemoizedFn } from 'ahooks';
import { useState } from 'react';
import { modelCategoriesMap } from '../config';
const API_MAP: Record<
string,
{ api: string; parameters: any; generateCurlCode: (args: any) => string }
> = {
[modelCategoriesMap.embedding]: {
api: EMBEDDING_API,
parameters: {
query: 'What are the benefits of regular exercise?',
documents: [
'Regular physical activity helps improve cardiovascular health and mental well-being.',
'Eating too much sugar can lead to health issues.',
'Exercise is often done in gyms or outdoors.'
]
},
generateCurlCode: generateEmbeddingCurlCode
},
[modelCategoriesMap.llm]: {
api: CHAT_API,
parameters: {
messages: [
{
role: 'user',
content: 'Hello, introduce yourself'
}
]
},
generateCurlCode: generateLLmCurlCode
},
[modelCategoriesMap.image]: {
api: CREAT_IMAGE_API,
parameters: {},
generateCurlCode: generateImageCurlCode
},
[modelCategoriesMap.text_to_speech]: {
api: AUDIO_TEXT_TO_SPEECH_API,
parameters: {
response_format: 'mp3',
input: ''
},
generateCurlCode: generateTextToSpeechCurlCode
},
[modelCategoriesMap.speech_to_text]: {
api: AUDIO_SPEECH_TO_TEXT_API,
parameters: {},
generateCurlCode: generateSpeechToTextCurlCode
},
[modelCategoriesMap.reranker]: {
api: RERANKER_API,
parameters: {
messages: [
{
role: 'user',
content: 'Hello, introduce yourself'
}
]
},
generateCurlCode: generateRerankCurlCode
}
};
const langOptions = [{ label: 'Curl', value: 'bash' }];
const useGenericProxy = () => {
const [modalStatus, setModalStatus] = useState<{
codeValue: string;
}>({ codeValue: '' });
const getModelCategory = (categories: string[]) => {
for (const [category, config] of Object.entries(API_MAP)) {
if (categories.includes(category)) {
return {
category,
api: `${MODEL_PROXY}${config.api}`,
parameters: config.parameters,
generateCurlCode: config.generateCurlCode
};
}
}
return {
category: modelCategoriesMap.llm,
api: CHAT_API,
parameters: {
messages: [
{
role: 'user',
content: 'Hello, introduce yourself'
}
]
},
generateCurlCode: generateLLmCurlCode
};
};
const openProxyModal = useMemoizedFn((data?: any) => {
const { api, generateCurlCode, parameters } = getModelCategory(
data?.categories || []
);
setModalStatus({
codeValue: generateCurlCode({
api,
modelProxy: true,
parameters: {
model: data?.name || ''
}
})
});
});
const GenericProxyCommandCode = (
<CommandViewer
code={modalStatus.codeValue}
copyText={modalStatus.codeValue}
options={langOptions}
defaultValue={'bash'}
height={200}
></CommandViewer>
);
return {
GenericProxyCommandCode,
openProxyModal,
setModalStatus
};
};
export default useGenericProxy;
+4 -2
View File
@@ -1,5 +1,5 @@
import _ from 'lodash'; import _ from 'lodash';
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis'; import { GPUSTACK_API, MODEL_PROXY, OPENAI_COMPATIBLE } from '../apis';
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils'; import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
export const generateSpeechToTextCurlCode = ({ export const generateSpeechToTextCurlCode = ({
@@ -9,7 +9,9 @@ export const generateSpeechToTextCurlCode = ({
}: Record<string, any>) => { }: Record<string, any>) => {
const host = window.location.origin; const host = window.location.origin;
// replace url OPENAI_COMPATIBLE with GPUSTACK // replace url OPENAI_COMPATIBLE with GPUSTACK
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API); const api = modelProxy
? `${MODEL_PROXY}/\${YOUR_API_PATH}`
: url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
// ========================= Curl ========================= // ========================= Curl =========================
const curlCode = ` const curlCode = `
+4 -2
View File
@@ -1,4 +1,4 @@
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis'; import { GPUSTACK_API, MODEL_PROXY, OPENAI_COMPATIBLE } from '../apis';
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils'; import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
export const generateEmbeddingCurlCode = ({ export const generateEmbeddingCurlCode = ({
@@ -7,7 +7,9 @@ export const generateEmbeddingCurlCode = ({
parameters parameters
}: Record<string, any>) => { }: Record<string, any>) => {
const host = window.location.origin; const host = window.location.origin;
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API); const api = modelProxy
? `${MODEL_PROXY}/\${YOUR_API_PATH}`
: url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
// ========================= Curl ========================= // ========================= Curl =========================
const curlCode = ` const curlCode = `
+4 -2
View File
@@ -1,5 +1,5 @@
import _ from 'lodash'; import _ from 'lodash';
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis'; import { GPUSTACK_API, MODEL_PROXY, OPENAI_COMPATIBLE } from '../apis';
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils'; import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
export const generateImageCurlCode = ({ export const generateImageCurlCode = ({
@@ -10,7 +10,9 @@ export const generateImageCurlCode = ({
edit = false edit = false
}: Record<string, any>) => { }: Record<string, any>) => {
const host = window.location.origin; const host = window.location.origin;
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API); const api = modelProxy
? `${MODEL_PROXY}/\${YOUR_API_PATH}`
: url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
// ========================= Curl ========================= // ========================= Curl =========================
let curlCode = ` let curlCode = `
+4 -2
View File
@@ -1,4 +1,4 @@
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis'; import { GPUSTACK_API, MODEL_PROXY, OPENAI_COMPATIBLE } from '../apis';
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils'; import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
export const generateLLmCurlCode = ({ export const generateLLmCurlCode = ({
@@ -7,7 +7,9 @@ export const generateLLmCurlCode = ({
parameters parameters
}: Record<string, any>) => { }: Record<string, any>) => {
const host = window.location.origin; const host = window.location.origin;
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API); const api = modelProxy
? `${MODEL_PROXY}/\${YOUR_API_PATH}`
: url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
// ========================= Curl ========================= // ========================= Curl =========================
const curlCode = ` const curlCode = `
+3 -1
View File
@@ -1,3 +1,4 @@
import { MODEL_PROXY } from '../apis';
import { formatCurlArgs } from './utils'; import { formatCurlArgs } from './utils';
export const generateRerankCurlCode = ({ export const generateRerankCurlCode = ({
@@ -6,10 +7,11 @@ export const generateRerankCurlCode = ({
parameters parameters
}: Record<string, any>) => { }: Record<string, any>) => {
const host = window.location.origin; const host = window.location.origin;
const apiUrl = modelProxy ? `${MODEL_PROXY}/\${YOUR_API_PATH}` : api;
// ========================= Curl ========================= // ========================= Curl =========================
const curlCode = ` const curlCode = `
curl ${host}${api} \\ curl ${host}${apiUrl} \\
-H "Content-Type: application/json" \\ -H "Content-Type: application/json" \\
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''} -H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
${formatCurlArgs(parameters, false)}`.trim(); ${formatCurlArgs(parameters, false)}`.trim();