chore: show llm code with common component
This commit is contained in:
@@ -27,7 +27,7 @@ const TableRow: React.FC<
|
|||||||
rowIndex,
|
rowIndex,
|
||||||
expandable,
|
expandable,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
expandedRowKeys,
|
expandedRowKeys = [],
|
||||||
rowKey,
|
rowKey,
|
||||||
childParentKey,
|
childParentKey,
|
||||||
columns,
|
columns,
|
||||||
@@ -80,6 +80,12 @@ const TableRow: React.FC<
|
|||||||
return rowSelection?.selectedRowKeys?.includes(record[rowKey]);
|
return rowSelection?.selectedRowKeys?.includes(record[rowKey]);
|
||||||
}, [rowSelection?.selectedRowKeys, record, rowKey]);
|
}, [rowSelection?.selectedRowKeys, record, rowKey]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (expandedRowKeys?.length === 0) {
|
||||||
|
setCurrentExpand(false);
|
||||||
|
}
|
||||||
|
}, [expandedRowKeys.length]);
|
||||||
|
|
||||||
const renderChildrenData = () => {
|
const renderChildrenData = () => {
|
||||||
if (childrenData.length === 0) {
|
if (childrenData.length === 0) {
|
||||||
// return (
|
// return (
|
||||||
|
|||||||
@@ -9,11 +9,8 @@ import React, {
|
|||||||
useRef,
|
useRef,
|
||||||
useState
|
useState
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import {
|
import { CHAT_API } from '../apis';
|
||||||
OpenAIViewCode,
|
import { Roles, generateMessagesByListContent } from '../config';
|
||||||
Roles,
|
|
||||||
generateMessagesByListContent
|
|
||||||
} from '../config';
|
|
||||||
import { ChatParamsConfig } from '../config/params-config';
|
import { ChatParamsConfig } from '../config/params-config';
|
||||||
import { MessageItem, MessageItemAction } from '../config/types';
|
import { MessageItem, MessageItemAction } from '../config/types';
|
||||||
import { LLM_METAKEYS, llmInitialValues } from '../hooks/config';
|
import { LLM_METAKEYS, llmInitialValues } from '../hooks/config';
|
||||||
@@ -21,12 +18,13 @@ import useChatCompletion from '../hooks/use-chat-completion';
|
|||||||
import { useInitLLmMeta } from '../hooks/use-init-meta';
|
import { useInitLLmMeta } from '../hooks/use-init-meta';
|
||||||
import '../style/ground-left.less';
|
import '../style/ground-left.less';
|
||||||
import '../style/system-message-wrap.less';
|
import '../style/system-message-wrap.less';
|
||||||
|
import { generateLLMCode } from '../view-code/llm';
|
||||||
import DynamicParams from './dynamic-params';
|
import DynamicParams from './dynamic-params';
|
||||||
import MessageInput from './message-input';
|
import MessageInput from './message-input';
|
||||||
import MessageContent from './multiple-chat/message-content';
|
import MessageContent from './multiple-chat/message-content';
|
||||||
import SystemMessage from './multiple-chat/system-message';
|
import SystemMessage from './multiple-chat/system-message';
|
||||||
import ReferenceParams from './reference-params';
|
import ReferenceParams from './reference-params';
|
||||||
import ViewCodeModal from './view-code-modal';
|
import ViewCommonCode from './view-common-code';
|
||||||
|
|
||||||
interface MessageProps {
|
interface MessageProps {
|
||||||
modelList: Global.BaseOption<string>[];
|
modelList: Global.BaseOption<string>[];
|
||||||
@@ -89,13 +87,19 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const viewCodeMessage = useMemo(() => {
|
const viewCodeContent = useMemo(() => {
|
||||||
const resultList = systemMessage
|
const resultList = systemMessage
|
||||||
? [{ role: Roles.System, content: systemMessage }]
|
? [{ role: Roles.System, content: systemMessage }]
|
||||||
: [];
|
: [];
|
||||||
const list = generateMessagesByListContent([...messageList]);
|
const list = generateMessagesByListContent([...messageList]);
|
||||||
return [...resultList, ...list];
|
return generateLLMCode({
|
||||||
}, [messageList, systemMessage]);
|
api: CHAT_API,
|
||||||
|
parameters: {
|
||||||
|
...parameters,
|
||||||
|
messages: [...resultList, ...list]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [messageList, systemMessage, parameters]);
|
||||||
|
|
||||||
const handleSendMessage = (message: Omit<MessageItem, 'uid'>) => {
|
const handleSendMessage = (message: Omit<MessageItem, 'uid'>) => {
|
||||||
const currentMessage =
|
const currentMessage =
|
||||||
@@ -189,17 +193,11 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<ViewCommonCode
|
||||||
<ViewCodeModal
|
|
||||||
{...OpenAIViewCode.chat}
|
|
||||||
open={show}
|
open={show}
|
||||||
payload={{
|
viewCodeContent={viewCodeContent}
|
||||||
messages: viewCodeMessage
|
|
||||||
}}
|
|
||||||
parameters={parameters}
|
|
||||||
onCancel={handleCloseViewCode}
|
onCancel={handleCloseViewCode}
|
||||||
title={intl.formatMessage({ id: 'playground.viewcode' })}
|
></ViewCommonCode>
|
||||||
></ViewCodeModal>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -22,11 +22,8 @@ import React, {
|
|||||||
useState
|
useState
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import 'simplebar-react/dist/simplebar.min.css';
|
import 'simplebar-react/dist/simplebar.min.css';
|
||||||
import {
|
import { CHAT_API } from '../../apis';
|
||||||
OpenAIViewCode,
|
import { Roles, generateMessagesByListContent } from '../../config';
|
||||||
Roles,
|
|
||||||
generateMessagesByListContent
|
|
||||||
} from '../../config';
|
|
||||||
import CompareContext from '../../config/compare-context';
|
import CompareContext from '../../config/compare-context';
|
||||||
import { ChatParamsConfig } from '../../config/params-config';
|
import { ChatParamsConfig } from '../../config/params-config';
|
||||||
import { MessageItem, ModelSelectionItem } from '../../config/types';
|
import { MessageItem, ModelSelectionItem } from '../../config/types';
|
||||||
@@ -34,9 +31,10 @@ import { LLM_METAKEYS, llmInitialValues } from '../../hooks/config';
|
|||||||
import useChatCompletion from '../../hooks/use-chat-completion';
|
import useChatCompletion from '../../hooks/use-chat-completion';
|
||||||
import { useInitLLmMeta } from '../../hooks/use-init-meta';
|
import { useInitLLmMeta } from '../../hooks/use-init-meta';
|
||||||
import '../../style/model-item.less';
|
import '../../style/model-item.less';
|
||||||
|
import { generateLLMCode } from '../../view-code/llm';
|
||||||
import DynamicParams from '../dynamic-params';
|
import DynamicParams from '../dynamic-params';
|
||||||
import ReferenceParams from '../reference-params';
|
import ReferenceParams from '../reference-params';
|
||||||
import ViewCodeModal from '../view-code-modal';
|
import ViewCommonCode from '../view-common-code';
|
||||||
import MessageContent from './message-content';
|
import MessageContent from './message-content';
|
||||||
import SystemMessage from './system-message';
|
import SystemMessage from './system-message';
|
||||||
|
|
||||||
@@ -92,13 +90,20 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef((props, ref) => {
|
|||||||
loading
|
loading
|
||||||
} = useChatCompletion(scroller);
|
} = useChatCompletion(scroller);
|
||||||
|
|
||||||
const viewCodeMessage = useMemo(() => {
|
const viewCodeContent = useMemo(() => {
|
||||||
const resultList = systemMessage
|
const resultList = systemMessage
|
||||||
? [{ role: Roles.System, content: systemMessage }]
|
? [{ role: Roles.System, content: systemMessage }]
|
||||||
: [];
|
: [];
|
||||||
const list = generateMessagesByListContent([...messageList]);
|
const list = generateMessagesByListContent([...messageList]);
|
||||||
return [...resultList, ...list];
|
|
||||||
}, [messageList, systemMessage]);
|
return generateLLMCode({
|
||||||
|
api: CHAT_API,
|
||||||
|
parameters: {
|
||||||
|
...parameters,
|
||||||
|
messages: [...resultList, ...list]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [messageList, systemMessage, parameters]);
|
||||||
|
|
||||||
const abortFetch = () => {
|
const abortFetch = () => {
|
||||||
handleStopConversation();
|
handleStopConversation();
|
||||||
@@ -338,16 +343,11 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef((props, ref) => {
|
|||||||
<Spin spinning={loading} size="small" style={{ width: '100%' }} />
|
<Spin spinning={loading} size="small" style={{ width: '100%' }} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ViewCodeModal
|
<ViewCommonCode
|
||||||
{...OpenAIViewCode.chat}
|
|
||||||
open={show}
|
open={show}
|
||||||
payload={{
|
viewCodeContent={viewCodeContent}
|
||||||
messages: viewCodeMessage
|
|
||||||
}}
|
|
||||||
parameters={parameters}
|
|
||||||
onCancel={handleCloseViewCode}
|
onCancel={handleCloseViewCode}
|
||||||
title={intl.formatMessage({ id: 'playground.viewcode' })}
|
></ViewCommonCode>
|
||||||
></ViewCodeModal>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,197 +0,0 @@
|
|||||||
import EditorWrap from '@/components/editor-wrap';
|
|
||||||
import HighlightCode from '@/components/highlight-code';
|
|
||||||
import { BulbOutlined } from '@ant-design/icons';
|
|
||||||
import { useIntl } from '@umijs/max';
|
|
||||||
import { Button, Modal } from 'antd';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import React, { useMemo, useState } from 'react';
|
|
||||||
import { GPUSTACK_API } from '../apis';
|
|
||||||
|
|
||||||
type ViewModalProps = {
|
|
||||||
systemMessage?: string;
|
|
||||||
messageList?: any[];
|
|
||||||
payload: Record<string, any>;
|
|
||||||
parameters: any;
|
|
||||||
title: string;
|
|
||||||
api: string;
|
|
||||||
clientType: string;
|
|
||||||
logcommand?: string;
|
|
||||||
open: boolean;
|
|
||||||
onCancel: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const langMap = {
|
|
||||||
shell: 'bash',
|
|
||||||
python: 'python',
|
|
||||||
javascript: 'javascript'
|
|
||||||
};
|
|
||||||
|
|
||||||
const langOptions = [
|
|
||||||
{ label: 'Curl', value: langMap.shell },
|
|
||||||
{ label: 'Python', value: langMap.python },
|
|
||||||
{ label: 'Nodejs', value: langMap.javascript }
|
|
||||||
];
|
|
||||||
|
|
||||||
const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
|
||||||
const {
|
|
||||||
title,
|
|
||||||
open,
|
|
||||||
api,
|
|
||||||
clientType,
|
|
||||||
logcommand,
|
|
||||||
onCancel,
|
|
||||||
payload,
|
|
||||||
parameters = {}
|
|
||||||
} = props || {};
|
|
||||||
|
|
||||||
const intl = useIntl();
|
|
||||||
const [lang, setLang] = useState(langMap.shell);
|
|
||||||
|
|
||||||
const BaseURL = `${window.location.origin}/${GPUSTACK_API}`;
|
|
||||||
|
|
||||||
const formatPyParams = (params: any) => {
|
|
||||||
return _.keys(params).reduce((acc: string, key: string) => {
|
|
||||||
if (params[key] === null) {
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
const value =
|
|
||||||
typeof params[key] === 'object'
|
|
||||||
? JSON.stringify(params[key], null, 2)
|
|
||||||
: `"${params[key]}"`;
|
|
||||||
return acc + ` ${key}=${value},\n`;
|
|
||||||
}, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
const codeValue = useMemo(() => {
|
|
||||||
const consoleLog = logcommand
|
|
||||||
? `console.log(response.${logcommand});\n`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const printLog = logcommand ? `print(response.${logcommand})` : '';
|
|
||||||
|
|
||||||
if (lang === langMap.shell) {
|
|
||||||
const code = `curl ${window.location.origin}/${GPUSTACK_API}/${api} \\\n-H "Content-Type: application/json" \\\n-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\\n-d '${JSON.stringify(
|
|
||||||
{
|
|
||||||
...parameters,
|
|
||||||
...payload
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
2
|
|
||||||
)}'`;
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
if (lang === langMap.javascript) {
|
|
||||||
const code = `const OpenAI = require("openai");\n\nconst openai = new OpenAI({\n "apiKey": "YOUR_GPUSTACK_API_KEY",\n "baseURL": "${BaseURL}"\n});\n\nasync function main(){\n const params = ${JSON.stringify(
|
|
||||||
{
|
|
||||||
...parameters,
|
|
||||||
...payload
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
4
|
|
||||||
)};\nconst response = await openai.${clientType}(params);\n ${consoleLog}}\nmain();`;
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
if (lang === langMap.python) {
|
|
||||||
const formattedParams = _.keys(parameters).reduce(
|
|
||||||
(acc: string, key: string) => {
|
|
||||||
if (parameters[key] === null) {
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
const value =
|
|
||||||
typeof parameters[key] === 'string'
|
|
||||||
? `"${parameters[key]}"`
|
|
||||||
: parameters[key];
|
|
||||||
return acc + ` ${key}=${value},\n`;
|
|
||||||
},
|
|
||||||
''
|
|
||||||
);
|
|
||||||
const params = formatPyParams(payload);
|
|
||||||
const code = `from openai import OpenAI\n\nclient = OpenAI(\n base_url="${BaseURL}", \n api_key="YOUR_GPUSTACK_API_KEY"\n)\n\nresponse = client.${clientType}(\n${formattedParams}${params})\n${printLog}`;
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}, [lang, payload, parameters, api, clientType, logcommand]);
|
|
||||||
|
|
||||||
const handleOnChangeLang = (value: string | number) => {
|
|
||||||
setLang(value as string);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setLang(langMap.shell);
|
|
||||||
onCancel();
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal
|
|
||||||
title={title}
|
|
||||||
open={open}
|
|
||||||
centered={true}
|
|
||||||
onCancel={handleClose}
|
|
||||||
destroyOnClose={true}
|
|
||||||
closeIcon={true}
|
|
||||||
maskClosable={false}
|
|
||||||
keyboard={false}
|
|
||||||
width={600}
|
|
||||||
footer={null}
|
|
||||||
>
|
|
||||||
<div style={{ marginBottom: '10px' }}>
|
|
||||||
{intl.formatMessage({ id: 'playground.viewcode.info' })}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<EditorWrap
|
|
||||||
copyText={codeValue}
|
|
||||||
langOptions={langOptions}
|
|
||||||
defaultValue={langMap.shell}
|
|
||||||
showHeader={true}
|
|
||||||
onChangeLang={handleOnChangeLang}
|
|
||||||
styles={{
|
|
||||||
wrapper: {
|
|
||||||
backgroundColor: 'var(--color-editor-dark)'
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<HighlightCode
|
|
||||||
height={380}
|
|
||||||
theme="dark"
|
|
||||||
code={codeValue}
|
|
||||||
lang={lang}
|
|
||||||
copyable={false}
|
|
||||||
></HighlightCode>
|
|
||||||
</EditorWrap>
|
|
||||||
<div
|
|
||||||
style={{ marginTop: 10, display: 'flex', alignItems: 'baseline' }}
|
|
||||||
>
|
|
||||||
<BulbOutlined className="m-r-8" />
|
|
||||||
<span>
|
|
||||||
{intl.formatMessage(
|
|
||||||
{ id: 'playground.viewcode.tips' },
|
|
||||||
{
|
|
||||||
here: (
|
|
||||||
<Button
|
|
||||||
type="link"
|
|
||||||
size="small"
|
|
||||||
href="#/api-keys"
|
|
||||||
target="_blank"
|
|
||||||
style={{ paddingInline: 2 }}
|
|
||||||
>
|
|
||||||
<span>
|
|
||||||
{' '}
|
|
||||||
{intl.formatMessage({
|
|
||||||
id: 'playground.viewcode.here'
|
|
||||||
})}
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(ViewCodeModal);
|
|
||||||
@@ -6,7 +6,7 @@ import { Button, Modal } from 'antd';
|
|||||||
import React, { useMemo, useState } from 'react';
|
import React, { useMemo, useState } from 'react';
|
||||||
|
|
||||||
type ViewModalProps = {
|
type ViewModalProps = {
|
||||||
title: string;
|
title?: string;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
viewCodeContent: {
|
viewCodeContent: {
|
||||||
curlCode: string;
|
curlCode: string;
|
||||||
@@ -59,7 +59,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
title={title}
|
title={title || intl.formatMessage({ id: 'playground.viewcode' })}
|
||||||
open={open}
|
open={open}
|
||||||
centered={true}
|
centered={true}
|
||||||
onCancel={handleClose}
|
onCancel={handleClose}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { GPUSTACK_API, OPENAI_COMPATIBLE } from '../apis';
|
||||||
|
import { fomatNodeJsParams, formatCurlArgs, formatPyParams } from './utils';
|
||||||
|
|
||||||
|
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 = `
|
||||||
|
curl ${host}${api} \\
|
||||||
|
-H "Content-Type: application/json" \\
|
||||||
|
-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\
|
||||||
|
${formatCurlArgs(parameters, false)}`.trim();
|
||||||
|
|
||||||
|
// ========================= Python =========================
|
||||||
|
const pythonCode = `
|
||||||
|
from openai import OpenAI\n
|
||||||
|
client = OpenAI(
|
||||||
|
base_url="${host}/${GPUSTACK_API}",
|
||||||
|
api_key="YOUR_GPUSTACK_API_KEY"
|
||||||
|
)
|
||||||
|
|
||||||
|
response = client.chat.completions.create((\n${formatPyParams({ ...parameters })})\n
|
||||||
|
print(response.choices[0].message.content)`.trim();
|
||||||
|
|
||||||
|
// ========================= Node.js =========================
|
||||||
|
const params = fomatNodeJsParams({
|
||||||
|
...parameters
|
||||||
|
});
|
||||||
|
|
||||||
|
const nodeJsCode = `
|
||||||
|
const OpenAI = require("openai");
|
||||||
|
|
||||||
|
const openai = new OpenAI({
|
||||||
|
"apiKey": "YOUR_GPUSTACK_API_KEY",
|
||||||
|
"baseURL": "${host}/${GPUSTACK_API}"
|
||||||
|
});
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const params = ${params};
|
||||||
|
const response = await openai.chat.completions.create(params);
|
||||||
|
console.log(response.choices[0].message.content);
|
||||||
|
}
|
||||||
|
main();`.trim();
|
||||||
|
|
||||||
|
return {
|
||||||
|
curlCode,
|
||||||
|
pythonCode,
|
||||||
|
nodeJsCode
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -22,10 +22,14 @@ export const formatPyParams = (parameters: Record<string, any>) => {
|
|||||||
if (parameters[key] === null || parameters[key] === undefined) {
|
if (parameters[key] === null || parameters[key] === undefined) {
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
const vauleType = typeof parameters[key];
|
||||||
const value =
|
const value =
|
||||||
typeof parameters[key] === 'object'
|
vauleType === 'object'
|
||||||
? JSON.stringify(parameters[key], null, 2)
|
? JSON.stringify(parameters[key], null, 2)
|
||||||
: `"${parameters[key]}"`;
|
: vauleType === 'string'
|
||||||
|
? `"${parameters[key]}"`
|
||||||
|
: parameters[key];
|
||||||
|
|
||||||
return acc + ` ${key}=${value},\n`;
|
return acc + ` ${key}=${value},\n`;
|
||||||
}, '');
|
}, '');
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user