chore: generic_prox ux
This commit is contained in:
@@ -83,6 +83,4 @@ const SegmentLine: React.FC<SegmentLineProps> = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
SegmentLine.displayName = 'SegmentLine';
|
|
||||||
|
|
||||||
export default SegmentLine;
|
export default SegmentLine;
|
||||||
|
|||||||
@@ -6,3 +6,5 @@ export const DEFAULT_ENTER_PAGE = {
|
|||||||
user: '/models/user-models',
|
user: '/models/user-models',
|
||||||
login: '/login'
|
login: '/login'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const GPUSTACK_API_BASE_URL = 'v1';
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default {
|
|||||||
'clusters.create.addworker.tips':
|
'clusters.create.addworker.tips':
|
||||||
' Please make sure the prerequisites for <a href={link} target="_blank">{label}</a> are met before executing the following command.',
|
' Please make sure the prerequisites for <a href={link} target="_blank">{label}</a> are met before executing the following command.',
|
||||||
'clusters.create.addCommand.tips':
|
'clusters.create.addCommand.tips':
|
||||||
' On the Worker that needs to be added, run the following command to join it to the cluster.',
|
'On the Worker that needs to be added, run the following command to join it to the cluster.',
|
||||||
'clusters.create.register.tips':
|
'clusters.create.register.tips':
|
||||||
' On the Kubernetes cluster that needs to be added, run the following command to join its nodes to the cluster.',
|
' On the Kubernetes cluster that needs to be added, run the following command to join its nodes to the cluster.',
|
||||||
'cluster.create.checkEnv.tips':
|
'cluster.create.checkEnv.tips':
|
||||||
|
|||||||
@@ -246,7 +246,10 @@ export default {
|
|||||||
'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': 'Enable Generic Proxy',
|
||||||
'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
'models.form.generic_proxy.tips':
|
||||||
|
'After enabling the generic proxy, you can access URI paths that do not follow the OpenAI API standard.',
|
||||||
'models.form.generic_proxy.button': 'Generic Proxy',
|
'models.form.generic_proxy.button': 'Generic Proxy',
|
||||||
'models.accessControlModal.includeusers': 'Include Users'
|
'models.accessControlModal.includeusers': 'Include Users',
|
||||||
|
'models.table.genericProxy':
|
||||||
|
'Refer to the curl example below. The proxy forwards requests with the /model/proxy prefix to the corresponding model. You need to specify the model name either in the <span class="bold-text">X-GPUStack-Model</span> request header or in the "model" property of the JSON body.'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export default {
|
|||||||
'clusters.create.addworker.tips':
|
'clusters.create.addworker.tips':
|
||||||
' Please make sure the prerequisites for <a href={link} target="_blank">{label}</a> are met before executing the following command.',
|
' Please make sure the prerequisites for <a href={link} target="_blank">{label}</a> are met before executing the following command.',
|
||||||
'clusters.create.addCommand.tips':
|
'clusters.create.addCommand.tips':
|
||||||
' On the Worker that needs to be added, run the following command to join it to the cluster.',
|
'On the Worker that needs to be added, run the following command to join it to the cluster.',
|
||||||
'cluster.create.checkEnv.tips':
|
'cluster.create.checkEnv.tips':
|
||||||
'Use the following command to check if the environment is ready',
|
'Use the following command to check if the environment is ready',
|
||||||
'clusters.create.register.tips':
|
'clusters.create.register.tips':
|
||||||
@@ -101,7 +101,7 @@ export default {
|
|||||||
// 37. 'clusters.create.noRegions': 'No regions available',
|
// 37. 'clusters.create.noRegions': 'No regions available',
|
||||||
// 38. 'clusters.workerpool.batchSize.desc': 'Number of workers created simultaneously in the Worker pool',
|
// 38. 'clusters.workerpool.batchSize.desc': 'Number of workers created simultaneously in the Worker pool',
|
||||||
// 39. 'clusters.create.addworker.tips': ' Please make sure the prerequisites for <a href={link} target="_blank">{label}</a> are met before executing the following command.',
|
// 39. 'clusters.create.addworker.tips': ' Please make sure the prerequisites for <a href={link} target="_blank">{label}</a> are met before executing the following command.',
|
||||||
// 40. 'clusters.create.addCommand.tips': ' On the Worker that needs to be added, run the following command to join it to the cluster.',
|
// 40. 'clusters.create.addCommand.tips': 'On the Worker that needs to be added, run the following command to join it to the cluster.',
|
||||||
// 41. 'cluster.create.checkEnv.tips': 'Use the following command to check if the environment is ready',
|
// 41. 'cluster.create.checkEnv.tips': 'Use the following command to check if the environment is ready',
|
||||||
// 42. 'clusters.create.register.tips': ' On the Kubernetes cluster that needs to be added, run the following command to join its nodes to the cluster.',
|
// 42. 'clusters.create.register.tips': ' On the Kubernetes cluster that needs to be added, run the following command to join its nodes to the cluster.',
|
||||||
// 43. 'cluster.provider.comingsoon': 'Coming soon',
|
// 43. 'cluster.provider.comingsoon': 'Coming soon',
|
||||||
|
|||||||
@@ -246,9 +246,12 @@ export default {
|
|||||||
'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': 'Enable Generic Proxy',
|
||||||
'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
'models.form.generic_proxy.tips':
|
||||||
|
'After enabling the generic proxy, you can access URI paths that do not follow the OpenAI API standard.',
|
||||||
'models.form.generic_proxy.button': 'Generic Proxy',
|
'models.form.generic_proxy.button': 'Generic Proxy',
|
||||||
'models.accessControlModal.includeusers': 'Include Users'
|
'models.accessControlModal.includeusers': 'Include Users',
|
||||||
|
'models.table.genericProxy':
|
||||||
|
'Refer to the curl example below. The proxy forwards requests with the /model/proxy prefix to the corresponding model. You need to specify the model name either in the <span class="bold-text">X-GPUStack-Model</span> request header or in the "model" property of the JSON body.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
@@ -322,8 +325,9 @@ export default {
|
|||||||
// 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',
|
// 53. 'models.form.generic_proxy': 'Enable Generic Proxy',
|
||||||
// 54. 'models.form.generic_proxy.tips': 'Enable Generic Proxy',
|
// 54. 'models.form.generic_proxy.tips': 'After enabling the generic proxy, you can access URI paths that do not follow the OpenAI API standard.',
|
||||||
// 55. 'models.form.generic_proxy.button': 'Generic Proxy',
|
// 55. 'models.form.generic_proxy.button': 'Generic Proxy',
|
||||||
// 56. 'models.accessControlModal.includeusers': 'Include Users'
|
// 56. 'models.accessControlModal.includeusers': 'Include Users',
|
||||||
|
// 57. 'models.table.genericProxy': 'Refer to the curl example below. The proxy forwards requests with the /model/proxy prefix to the corresponding model. You need to specify the model name either in the <span class="bold-text">X-GPUStack-Model</span> request header or in the "model" property of the JSON body.'
|
||||||
|
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -249,9 +249,11 @@ export default {
|
|||||||
'models.form.generic_proxy': 'Включить универсальный прокси',
|
'models.form.generic_proxy': 'Включить универсальный прокси',
|
||||||
'models.form.generic_proxy.tips': 'Включить универсальный прокси',
|
'models.form.generic_proxy.tips': 'Включить универсальный прокси',
|
||||||
'models.form.generic_proxy.button': 'Универсальный прокси',
|
'models.form.generic_proxy.button': 'Универсальный прокси',
|
||||||
'models.accessControlModal.includeusers': 'Включить пользователей'
|
'models.accessControlModal.includeusers': 'Включить пользователей',
|
||||||
|
'models.table.genericProxy':
|
||||||
|
'Refer to the curl example below. The proxy forwards requests with the /model/proxy prefix to the corresponding model. You need to specify the model name either in the <span class="bold-text">X-GPUStack-Model</span> request header or in the "model" property of the JSON body.'
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
// ========== To-Do: Translate Keys (Remove After Translation) ==========
|
||||||
|
// 7. 'models.table.genericProxy': 'Refer to the curl example below. The proxy forwards requests with the /model/proxy prefix to the corresponding model. You need to specify the model name either in the <span class="bold-text">X-GPUStack-Model</span> request header or in the "model" property of the JSON body.'
|
||||||
// ========== End of To-Do List ==========
|
// ========== End of To-Do List ==========
|
||||||
|
|||||||
@@ -233,7 +233,10 @@ export default {
|
|||||||
'models.catalog.precision': '精度',
|
'models.catalog.precision': '精度',
|
||||||
'models.form.gpuPerReplica.tips': '输入自定义数值',
|
'models.form.gpuPerReplica.tips': '输入自定义数值',
|
||||||
'models.form.generic_proxy': '启用通用代理',
|
'models.form.generic_proxy': '启用通用代理',
|
||||||
'models.form.generic_proxy.tips': '启用通用代理',
|
'models.form.generic_proxy.tips':
|
||||||
|
'启用通用代理后可支持访问非 openai-API 标准的 URI 路径。',
|
||||||
'models.form.generic_proxy.button': '通用代理',
|
'models.form.generic_proxy.button': '通用代理',
|
||||||
'models.accessControlModal.includeusers': '显示用户'
|
'models.accessControlModal.includeusers': '显示用户',
|
||||||
|
'models.table.genericProxy':
|
||||||
|
'参考下面 curl 的方式,代理会将 /model/proxy 前缀的请求转发到对应的模型,需要在 <span class="bold-text">X-GPUStack-Model</span> 请求头或 JSON 请求体 "model" 属性设置模型名称。'
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -107,9 +107,6 @@ const AddWorkerStep: React.FC<AddModalProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Title>
|
|
||||||
{intl.formatMessage({ id: 'clusters.create.supportedGpu' })}
|
|
||||||
</Title>
|
|
||||||
<SupportedGPUs
|
<SupportedGPUs
|
||||||
onSelect={handleSelectProvider}
|
onSelect={handleSelectProvider}
|
||||||
current={currentGPU}
|
current={currentGPU}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ import {
|
|||||||
SourceType
|
SourceType
|
||||||
} from '../config/types';
|
} from '../config/types';
|
||||||
import useFormInitialValues from '../hooks/use-form-initial-values';
|
import useFormInitialValues from '../hooks/use-form-initial-values';
|
||||||
|
import useGenericProxy from '../hooks/use-generic-proxy';
|
||||||
import useModelsColumns from '../hooks/use-models-columns';
|
import useModelsColumns from '../hooks/use-models-columns';
|
||||||
import AccessControlModal from './access-control-modal';
|
import AccessControlModal from './access-control-modal';
|
||||||
import APIAccessInfoModal from './api-access-info';
|
import APIAccessInfoModal from './api-access-info';
|
||||||
@@ -195,6 +196,8 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
});
|
});
|
||||||
const modalRef = useRef<any>(null);
|
const modalRef = useRef<any>(null);
|
||||||
|
|
||||||
|
const { GenericProxyModal, openProxyModal } = useGenericProxy();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (deleteIds?.length) {
|
if (deleteIds?.length) {
|
||||||
rowSelection.removeSelectedKey(deleteIds);
|
rowSelection.removeSelectedKey(deleteIds);
|
||||||
@@ -456,6 +459,10 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
handleViewAPIInfo(row);
|
handleViewAPIInfo(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (val === 'proxy') {
|
||||||
|
openProxyModal(row);
|
||||||
|
}
|
||||||
|
|
||||||
if (val === 'stop') {
|
if (val === 'stop') {
|
||||||
modalRef.current?.show({
|
modalRef.current?.show({
|
||||||
content: 'models.instances',
|
content: 'models.instances',
|
||||||
@@ -789,6 +796,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
currentData={openAccessControlModal.currentData}
|
currentData={openAccessControlModal.currentData}
|
||||||
action={openAccessControlModal.action}
|
action={openAccessControlModal.action}
|
||||||
></AccessControlModal>
|
></AccessControlModal>
|
||||||
|
{GenericProxyModal}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ export const ActionList: ActionItem[] = [
|
|||||||
key: 'chat',
|
key: 'chat',
|
||||||
icon: icons.ExperimentOutlined
|
icon: icons.ExperimentOutlined
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// label: 'models.form.generic_proxy.button',
|
label: 'models.form.generic_proxy.button',
|
||||||
// key: 'proxy',
|
key: 'proxy',
|
||||||
// icon: icons.CaptivePortal
|
icon: icons.CaptivePortal
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
label: 'models.table.button.apiAccessInfo',
|
label: 'models.table.button.apiAccessInfo',
|
||||||
key: 'api',
|
key: 'api',
|
||||||
@@ -197,6 +197,7 @@ export const modelFileActions = [
|
|||||||
|
|
||||||
export const categoryToPathMap: Record<string, string> = {
|
export const categoryToPathMap: Record<string, string> = {
|
||||||
[modelCategoriesMap.llm]: '/playground/chat',
|
[modelCategoriesMap.llm]: '/playground/chat',
|
||||||
|
[modelCategoriesMap.image]: '/playground/text-to-image',
|
||||||
[modelCategoriesMap.text_to_speech]: '/playground/speech?type=tts',
|
[modelCategoriesMap.text_to_speech]: '/playground/speech?type=tts',
|
||||||
[modelCategoriesMap.speech_to_text]: '/playground/speech?type=stt',
|
[modelCategoriesMap.speech_to_text]: '/playground/speech?type=stt',
|
||||||
[modelCategoriesMap.reranker]: '/playground/rerank',
|
[modelCategoriesMap.reranker]: '/playground/rerank',
|
||||||
|
|||||||
@@ -287,6 +287,7 @@ export const modelCategoriesMap = {
|
|||||||
|
|
||||||
export const categoryOptions = [
|
export const categoryOptions = [
|
||||||
{ label: 'LLM', value: modelCategoriesMap.llm },
|
{ label: 'LLM', value: modelCategoriesMap.llm },
|
||||||
|
{ label: 'Image', value: modelCategoriesMap.image },
|
||||||
{ label: 'Embedding', value: modelCategoriesMap.embedding },
|
{ label: 'Embedding', value: modelCategoriesMap.embedding },
|
||||||
{ label: 'Reranker', value: modelCategoriesMap.reranker },
|
{ label: 'Reranker', value: modelCategoriesMap.reranker },
|
||||||
{ label: 'Text-to-Speech', value: modelCategoriesMap.text_to_speech },
|
{ label: 'Text-to-Speech', value: modelCategoriesMap.text_to_speech },
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ const AdvanceConfig = () => {
|
|||||||
})}
|
})}
|
||||||
></CheckboxField>
|
></CheckboxField>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{/* <Form.Item<FormData>
|
<Form.Item<FormData>
|
||||||
name="generic_proxy"
|
name="generic_proxy"
|
||||||
valuePropName="checked"
|
valuePropName="checked"
|
||||||
style={{ marginBottom: 8 }}
|
style={{ marginBottom: 8 }}
|
||||||
@@ -146,7 +146,7 @@ const AdvanceConfig = () => {
|
|||||||
id: 'models.form.generic_proxy'
|
id: 'models.form.generic_proxy'
|
||||||
})}
|
})}
|
||||||
></CheckboxField>
|
></CheckboxField>
|
||||||
</Form.Item> */}
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,15 +1,62 @@
|
|||||||
import ScrollerModal from '@/components/scroller-modal';
|
import ScrollerModal from '@/components/scroller-modal';
|
||||||
import CommandViewer from '@/pages/_components/command-viewer';
|
import CommandViewer from '@/pages/_components/command-viewer';
|
||||||
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '@/pages/playground/apis';
|
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 { formatCurlArgs } from '@/pages/playground/view-code/utils';
|
import { formatCurlArgs } from '@/pages/playground/view-code/utils';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { modelCategoriesMap } from '../config';
|
||||||
|
|
||||||
|
const API_MAP: Record<
|
||||||
|
string,
|
||||||
|
{ api: string; generateCurlCode: (args: any) => string }
|
||||||
|
> = {
|
||||||
|
[modelCategoriesMap.embedding]: {
|
||||||
|
api: EMBEDDING_API,
|
||||||
|
generateCurlCode: generateEmbeddingCurlCode
|
||||||
|
},
|
||||||
|
[modelCategoriesMap.llm]: {
|
||||||
|
api: CHAT_API,
|
||||||
|
generateCurlCode: generateLLmCurlCode
|
||||||
|
},
|
||||||
|
[modelCategoriesMap.image]: {
|
||||||
|
api: CREAT_IMAGE_API,
|
||||||
|
generateCurlCode: generateImageCurlCode
|
||||||
|
},
|
||||||
|
[modelCategoriesMap.text_to_speech]: {
|
||||||
|
api: AUDIO_TEXT_TO_SPEECH_API,
|
||||||
|
generateCurlCode: generateTextToSpeechCurlCode
|
||||||
|
},
|
||||||
|
[modelCategoriesMap.speech_to_text]: {
|
||||||
|
api: AUDIO_SPEECH_TO_TEXT_API,
|
||||||
|
generateCurlCode: generateSpeechToTextCurlCode
|
||||||
|
},
|
||||||
|
[modelCategoriesMap.reranker]: {
|
||||||
|
api: RERANKER_API,
|
||||||
|
generateCurlCode: generateRerankCurlCode
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const langOptions = [{ label: 'Curl', value: 'bash' }];
|
const langOptions = [{ label: 'Curl', value: 'bash' }];
|
||||||
|
|
||||||
const generateCode = ({ api: url, parameters }: Record<string, any>) => {
|
const generateCode = ({ api: url, parameters }: Record<string, any>) => {
|
||||||
const host = window.location.origin;
|
const host = window.location.origin;
|
||||||
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
const api = '/model/proxy/v1/';
|
||||||
|
|
||||||
// ========================= Curl =========================
|
// ========================= Curl =========================
|
||||||
const curlCode = `
|
const curlCode = `
|
||||||
@@ -17,6 +64,8 @@ curl ${host}${api} \\
|
|||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
||||||
${formatCurlArgs(parameters, false)}`.trim();
|
${formatCurlArgs(parameters, false)}`.trim();
|
||||||
|
|
||||||
|
return curlCode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useGenericProxy = () => {
|
const useGenericProxy = () => {
|
||||||
@@ -33,38 +82,67 @@ const useGenericProxy = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getModelCategory = (categories: string[]) => {
|
||||||
|
for (const [category, config] of Object.entries(API_MAP)) {
|
||||||
|
if (categories.includes(category)) {
|
||||||
|
return {
|
||||||
|
category,
|
||||||
|
api: `${MODEL_PROXY}${config.api}`,
|
||||||
|
generateCurlCode: config.generateCurlCode
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
category: modelCategoriesMap.llm,
|
||||||
|
api: CHAT_API,
|
||||||
|
generateCurlCode: generateLLmCurlCode
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const openProxyModal = (data?: any) => {
|
const openProxyModal = (data?: any) => {
|
||||||
|
const { api, generateCurlCode } = getModelCategory(data?.categories || []);
|
||||||
|
|
||||||
setModalStatus({
|
setModalStatus({
|
||||||
open: true,
|
open: true,
|
||||||
codeValue: data?.generic_proxy_command || ''
|
codeValue: generateCurlCode({
|
||||||
|
api,
|
||||||
|
modelProxy: true,
|
||||||
|
parameters: {
|
||||||
|
model: data?.name || ''
|
||||||
|
}
|
||||||
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const GenericProxyModal = () => {
|
const GenericProxyModal = (
|
||||||
return (
|
<ScrollerModal
|
||||||
<ScrollerModal
|
title={intl.formatMessage({
|
||||||
title={intl.formatMessage({
|
id: 'models.form.generic_proxy.button'
|
||||||
id: 'models.form.generic_title.button'
|
})}
|
||||||
})}
|
open={modalStatus.open}
|
||||||
open={modalStatus.open}
|
centered={true}
|
||||||
centered={true}
|
onCancel={onCancel}
|
||||||
onCancel={onCancel}
|
destroyOnHidden={true}
|
||||||
destroyOnHidden={true}
|
closeIcon={true}
|
||||||
closeIcon={true}
|
maskClosable={false}
|
||||||
maskClosable={false}
|
keyboard={false}
|
||||||
keyboard={false}
|
width={700}
|
||||||
width={700}
|
footer={false}
|
||||||
footer={false}
|
>
|
||||||
>
|
<div
|
||||||
<CommandViewer
|
style={{ marginBottom: 8 }}
|
||||||
code={modalStatus.codeValue}
|
dangerouslySetInnerHTML={{
|
||||||
copyText={modalStatus.codeValue}
|
__html: intl.formatMessage({ id: 'models.table.genericProxy' })
|
||||||
options={langOptions}
|
}}
|
||||||
defaultValue={'bash'}
|
></div>
|
||||||
></CommandViewer>
|
<CommandViewer
|
||||||
</ScrollerModal>
|
code={modalStatus.codeValue}
|
||||||
);
|
copyText={modalStatus.codeValue}
|
||||||
};
|
options={langOptions}
|
||||||
|
defaultValue={'bash'}
|
||||||
|
></CommandViewer>
|
||||||
|
</ScrollerModal>
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
GenericProxyModal,
|
GenericProxyModal,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
|
import { GPUSTACK_API_BASE_URL } from '@/config/settings';
|
||||||
import { request } from '@umijs/max';
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
export const OPENAI_COMPATIBLE = 'v1-openai';
|
export const OPENAI_COMPATIBLE = 'v1-openai';
|
||||||
|
|
||||||
export const GPUSTACK_API = 'v1';
|
export const GPUSTACK_API = GPUSTACK_API_BASE_URL;
|
||||||
|
|
||||||
export const CHAT_API = `/${OPENAI_COMPATIBLE}/chat/completions`;
|
export const CHAT_API = `/${OPENAI_COMPATIBLE}/chat/completions`;
|
||||||
|
|
||||||
@@ -19,6 +20,8 @@ export const AUDIO_TEXT_TO_SPEECH_API = `/${OPENAI_COMPATIBLE}/audio/speech`;
|
|||||||
|
|
||||||
export const AUDIO_SPEECH_TO_TEXT_API = `/${OPENAI_COMPATIBLE}/audio/transcriptions`;
|
export const AUDIO_SPEECH_TO_TEXT_API = `/${OPENAI_COMPATIBLE}/audio/transcriptions`;
|
||||||
|
|
||||||
|
export const MODEL_PROXY = '/model/proxy';
|
||||||
|
|
||||||
export async function execChatCompletions(params: any) {
|
export async function execChatCompletions(params: any) {
|
||||||
return request(`${CHAT_API}`, {
|
return request(`${CHAT_API}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
|||||||
width={600}
|
width={600}
|
||||||
footer={null}
|
footer={null}
|
||||||
>
|
>
|
||||||
<div style={{ marginBottom: '10px' }}>
|
<div style={{ marginBottom: '8px' }}>
|
||||||
{intl.formatMessage({ id: 'playground.viewcode.info' })}
|
{intl.formatMessage({ id: 'playground.viewcode.info' })}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -81,7 +81,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
|||||||
onChange={handleOnChangeLang}
|
onChange={handleOnChangeLang}
|
||||||
></CommandViewer>
|
></CommandViewer>
|
||||||
<div
|
<div
|
||||||
style={{ marginTop: 10, display: 'flex', alignItems: 'baseline' }}
|
style={{ marginTop: 8, display: 'flex', alignItems: 'baseline' }}
|
||||||
>
|
>
|
||||||
<BulbOutlined className="m-r-8" />
|
<BulbOutlined className="m-r-8" />
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
||||||
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
||||||
|
|
||||||
export const speechToTextCode = ({
|
export const generateSpeechToTextCurlCode = ({
|
||||||
api: url,
|
api: url,
|
||||||
|
modelProxy,
|
||||||
parameters
|
parameters
|
||||||
}: Record<string, any>) => {
|
}: Record<string, any>) => {
|
||||||
const host = window.location.origin;
|
const host = window.location.origin;
|
||||||
@@ -13,12 +14,26 @@ export const speechToTextCode = ({
|
|||||||
const curlCode = `
|
const curlCode = `
|
||||||
curl ${host}${api} \\
|
curl ${host}${api} \\
|
||||||
-H "Content-Type: multipart/form-data" \\
|
-H "Content-Type: multipart/form-data" \\
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||||
-F file="@/path/to/file/audio.mp3;type=audio/mpeg" \\
|
-F file="@/path/to/file/audio.mp3;type=audio/mpeg" \\
|
||||||
${formatCurlArgs(parameters, true)}`
|
${formatCurlArgs(parameters, true)}`
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/\\$/g, '');
|
.replace(/\\$/g, '');
|
||||||
|
|
||||||
|
return curlCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const speechToTextCode = ({
|
||||||
|
api: url,
|
||||||
|
parameters
|
||||||
|
}: Record<string, any>) => {
|
||||||
|
const host = window.location.origin;
|
||||||
|
// replace url OPENAI_COMPATIBLE with GPUSTACK
|
||||||
|
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
||||||
|
|
||||||
|
// ========================= Curl =========================
|
||||||
|
const curlCode = generateSpeechToTextCurlCode({ api: url, parameters });
|
||||||
|
|
||||||
// ========================= Python =========================
|
// ========================= Python =========================
|
||||||
const pythonCode = `
|
const pythonCode = `
|
||||||
from openai import OpenAI\n
|
from openai import OpenAI\n
|
||||||
@@ -67,8 +82,9 @@ main();`.trim();
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TextToSpeechCode = ({
|
export const generateTextToSpeechCurlCode = ({
|
||||||
api: url,
|
api: url,
|
||||||
|
modelProxy,
|
||||||
parameters
|
parameters
|
||||||
}: Record<string, any>) => {
|
}: Record<string, any>) => {
|
||||||
const host = window.location.origin;
|
const host = window.location.origin;
|
||||||
@@ -78,9 +94,22 @@ export const TextToSpeechCode = ({
|
|||||||
const curlCode = `
|
const curlCode = `
|
||||||
curl ${host}${api} \\
|
curl ${host}${api} \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||||
${formatCurlArgs(parameters, false)} \\\n--output output.${parameters.response_format}`.trim();
|
${formatCurlArgs(parameters, false)} \\\n--output output.${parameters.response_format}`.trim();
|
||||||
|
|
||||||
|
return curlCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TextToSpeechCode = ({
|
||||||
|
api: url,
|
||||||
|
parameters
|
||||||
|
}: Record<string, any>) => {
|
||||||
|
const host = window.location.origin;
|
||||||
|
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
||||||
|
|
||||||
|
// ========================= Curl =========================
|
||||||
|
const curlCode = generateTextToSpeechCurlCode({ api: url, parameters });
|
||||||
|
|
||||||
// ========================= Python =========================
|
// ========================= Python =========================
|
||||||
const pythonCode = `
|
const pythonCode = `
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
||||||
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
||||||
|
|
||||||
export const generateEmbeddingCode = ({
|
export const generateEmbeddingCurlCode = ({
|
||||||
api: url,
|
api: url,
|
||||||
|
modelProxy,
|
||||||
parameters
|
parameters
|
||||||
}: Record<string, any>) => {
|
}: Record<string, any>) => {
|
||||||
const host = window.location.origin;
|
const host = window.location.origin;
|
||||||
@@ -12,9 +13,22 @@ export const generateEmbeddingCode = ({
|
|||||||
const curlCode = `
|
const curlCode = `
|
||||||
curl ${host}${api} \\
|
curl ${host}${api} \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||||
${formatCurlArgs(parameters, false)}`.trim();
|
${formatCurlArgs(parameters, false)}`.trim();
|
||||||
|
|
||||||
|
return curlCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateEmbeddingCode = ({
|
||||||
|
api: url,
|
||||||
|
parameters
|
||||||
|
}: Record<string, any>) => {
|
||||||
|
const host = window.location.origin;
|
||||||
|
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
||||||
|
|
||||||
|
// ========================= Curl =========================
|
||||||
|
const curlCode = generateEmbeddingCurlCode({ api: url, parameters });
|
||||||
|
|
||||||
// ========================= Python =========================
|
// ========================= Python =========================
|
||||||
const pythonCode = `
|
const pythonCode = `
|
||||||
from openai import OpenAI\n
|
from openai import OpenAI\n
|
||||||
|
|||||||
@@ -2,6 +2,38 @@ import _ from 'lodash';
|
|||||||
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
||||||
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
||||||
|
|
||||||
|
export const generateImageCurlCode = ({
|
||||||
|
api: url,
|
||||||
|
parameters,
|
||||||
|
modelProxy,
|
||||||
|
isFormdata = false,
|
||||||
|
edit = false
|
||||||
|
}: Record<string, any>) => {
|
||||||
|
const host = window.location.origin;
|
||||||
|
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
||||||
|
|
||||||
|
// ========================= Curl =========================
|
||||||
|
let curlCode = `
|
||||||
|
curl ${host}${api} \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||||
|
${formatCurlArgs(parameters, isFormdata)}`.trim();
|
||||||
|
|
||||||
|
if (edit) {
|
||||||
|
curlCode = `
|
||||||
|
curl ${host}${api} \\
|
||||||
|
-H "Content-Type: multipart/form-data" \\
|
||||||
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||||
|
-F image="@image.png" \\
|
||||||
|
-F mask="@mask.png" \\
|
||||||
|
${formatCurlArgs(_.omit(parameters, ['mask', 'image']), isFormdata)}`
|
||||||
|
.trim()
|
||||||
|
.replace(/\\$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
return curlCode;
|
||||||
|
};
|
||||||
|
|
||||||
export const generateImageCode = ({
|
export const generateImageCode = ({
|
||||||
api: url,
|
api: url,
|
||||||
parameters,
|
parameters,
|
||||||
@@ -12,23 +44,12 @@ export const generateImageCode = ({
|
|||||||
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
||||||
|
|
||||||
// ========================= Curl =========================
|
// ========================= Curl =========================
|
||||||
let curlCode = `
|
let curlCode = generateImageCurlCode({
|
||||||
curl ${host}${api} \\
|
api: url,
|
||||||
-H "Content-Type: application/json" \\
|
parameters,
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
isFormdata,
|
||||||
${formatCurlArgs(parameters, isFormdata)}`.trim();
|
edit
|
||||||
|
});
|
||||||
if (edit) {
|
|
||||||
curlCode = `
|
|
||||||
curl ${host}${api} \\
|
|
||||||
-H "Content-Type: multipart/form-data" \\
|
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
|
||||||
-F image="@image.png" \\
|
|
||||||
-F mask="@mask.png" \\
|
|
||||||
${formatCurlArgs(_.omit(parameters, ['mask', 'image']), isFormdata)}`
|
|
||||||
.trim()
|
|
||||||
.replace(/\\$/, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================= Python =========================
|
// ========================= Python =========================
|
||||||
const pythonCode = `
|
const pythonCode = `
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
||||||
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
||||||
|
|
||||||
export const generateLLMCode = ({
|
export const generateLLmCurlCode = ({
|
||||||
api: url,
|
api: url,
|
||||||
|
modelProxy,
|
||||||
parameters
|
parameters
|
||||||
}: Record<string, any>) => {
|
}: Record<string, any>) => {
|
||||||
const host = window.location.origin;
|
const host = window.location.origin;
|
||||||
@@ -12,9 +13,22 @@ export const generateLLMCode = ({
|
|||||||
const curlCode = `
|
const curlCode = `
|
||||||
curl ${host}${api} \\
|
curl ${host}${api} \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||||
${formatCurlArgs(parameters, false)}`.trim();
|
${formatCurlArgs(parameters, false)}`.trim();
|
||||||
|
|
||||||
|
return curlCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateLLMCode = ({
|
||||||
|
api: url,
|
||||||
|
parameters
|
||||||
|
}: Record<string, any>) => {
|
||||||
|
const host = window.location.origin;
|
||||||
|
const api = url.replace(OPENAI_COMPATIBLE, GPUSTACK_API);
|
||||||
|
|
||||||
|
// ========================= Curl =========================
|
||||||
|
const curlCode = generateLLmCurlCode({ api: url, parameters });
|
||||||
|
|
||||||
// ========================= Python =========================
|
// ========================= Python =========================
|
||||||
const pythonCode = `
|
const pythonCode = `
|
||||||
from openai import OpenAI\n
|
from openai import OpenAI\n
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { formatCurlArgs } from './utils';
|
import { formatCurlArgs } from './utils';
|
||||||
|
|
||||||
export const generateRerankCode = ({
|
export const generateRerankCurlCode = ({
|
||||||
api,
|
api,
|
||||||
|
modelProxy,
|
||||||
parameters
|
parameters
|
||||||
}: Record<string, any>) => {
|
}: Record<string, any>) => {
|
||||||
const host = window.location.origin;
|
const host = window.location.origin;
|
||||||
@@ -10,9 +11,21 @@ export const generateRerankCode = ({
|
|||||||
const curlCode = `
|
const curlCode = `
|
||||||
curl ${host}${api} \\
|
curl ${host}${api} \\
|
||||||
-H "Content-Type: application/json" \\
|
-H "Content-Type: application/json" \\
|
||||||
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\${modelProxy ? `\n-H "X-GPUStack-Model: ${parameters.model}" \\` : ''}
|
||||||
${formatCurlArgs(parameters, false)}`.trim();
|
${formatCurlArgs(parameters, false)}`.trim();
|
||||||
|
|
||||||
|
return curlCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateRerankCode = ({
|
||||||
|
api,
|
||||||
|
parameters
|
||||||
|
}: Record<string, any>) => {
|
||||||
|
const host = window.location.origin;
|
||||||
|
|
||||||
|
// ========================= Curl =========================
|
||||||
|
const curlCode = generateRerankCurlCode({ api, parameters });
|
||||||
|
|
||||||
// ========================= Python =========================
|
// ========================= Python =========================
|
||||||
const pythonCode = `
|
const pythonCode = `
|
||||||
import requests\n
|
import requests\n
|
||||||
|
|||||||
Reference in New Issue
Block a user