diff --git a/src/components/seal-table/components/table-row.tsx b/src/components/seal-table/components/table-row.tsx index 144fbf60..63f57d03 100644 --- a/src/components/seal-table/components/table-row.tsx +++ b/src/components/seal-table/components/table-row.tsx @@ -27,7 +27,7 @@ const TableRow: React.FC< rowIndex, expandable, rowSelection, - expandedRowKeys, + expandedRowKeys = [], rowKey, childParentKey, columns, @@ -80,6 +80,12 @@ const TableRow: React.FC< return rowSelection?.selectedRowKeys?.includes(record[rowKey]); }, [rowSelection?.selectedRowKeys, record, rowKey]); + useEffect(() => { + if (expandedRowKeys?.length === 0) { + setCurrentExpand(false); + } + }, [expandedRowKeys.length]); + const renderChildrenData = () => { if (childrenData.length === 0) { // return ( diff --git a/src/pages/playground/components/ground-left.tsx b/src/pages/playground/components/ground-left.tsx index a7478ce5..180e7984 100644 --- a/src/pages/playground/components/ground-left.tsx +++ b/src/pages/playground/components/ground-left.tsx @@ -9,11 +9,8 @@ import React, { useRef, useState } from 'react'; -import { - OpenAIViewCode, - Roles, - generateMessagesByListContent -} from '../config'; +import { CHAT_API } from '../apis'; +import { Roles, generateMessagesByListContent } from '../config'; import { ChatParamsConfig } from '../config/params-config'; import { MessageItem, MessageItemAction } from '../config/types'; 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 '../style/ground-left.less'; import '../style/system-message-wrap.less'; +import { generateLLMCode } from '../view-code/llm'; import DynamicParams from './dynamic-params'; import MessageInput from './message-input'; import MessageContent from './multiple-chat/message-content'; import SystemMessage from './multiple-chat/system-message'; import ReferenceParams from './reference-params'; -import ViewCodeModal from './view-code-modal'; +import ViewCommonCode from './view-common-code'; interface MessageProps { modelList: Global.BaseOption[]; @@ -89,13 +87,19 @@ const GroundLeft: React.FC = forwardRef((props, ref) => { }; }); - const viewCodeMessage = useMemo(() => { + const viewCodeContent = useMemo(() => { const resultList = systemMessage ? [{ role: Roles.System, content: systemMessage }] : []; const list = generateMessagesByListContent([...messageList]); - return [...resultList, ...list]; - }, [messageList, systemMessage]); + return generateLLMCode({ + api: CHAT_API, + parameters: { + ...parameters, + messages: [...resultList, ...list] + } + }); + }, [messageList, systemMessage, parameters]); const handleSendMessage = (message: Omit) => { const currentMessage = @@ -189,17 +193,11 @@ const GroundLeft: React.FC = forwardRef((props, ref) => { /> - - + > ); }); diff --git a/src/pages/playground/components/multiple-chat/model-item.tsx b/src/pages/playground/components/multiple-chat/model-item.tsx index de447f97..49fd357e 100644 --- a/src/pages/playground/components/multiple-chat/model-item.tsx +++ b/src/pages/playground/components/multiple-chat/model-item.tsx @@ -22,11 +22,8 @@ import React, { useState } from 'react'; import 'simplebar-react/dist/simplebar.min.css'; -import { - OpenAIViewCode, - Roles, - generateMessagesByListContent -} from '../../config'; +import { CHAT_API } from '../../apis'; +import { Roles, generateMessagesByListContent } from '../../config'; import CompareContext from '../../config/compare-context'; import { ChatParamsConfig } from '../../config/params-config'; 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 { useInitLLmMeta } from '../../hooks/use-init-meta'; import '../../style/model-item.less'; +import { generateLLMCode } from '../../view-code/llm'; import DynamicParams from '../dynamic-params'; import ReferenceParams from '../reference-params'; -import ViewCodeModal from '../view-code-modal'; +import ViewCommonCode from '../view-common-code'; import MessageContent from './message-content'; import SystemMessage from './system-message'; @@ -92,13 +90,20 @@ const ModelItem: React.FC = forwardRef((props, ref) => { loading } = useChatCompletion(scroller); - const viewCodeMessage = useMemo(() => { + const viewCodeContent = useMemo(() => { const resultList = systemMessage ? [{ role: Roles.System, content: systemMessage }] : []; const list = generateMessagesByListContent([...messageList]); - return [...resultList, ...list]; - }, [messageList, systemMessage]); + + return generateLLMCode({ + api: CHAT_API, + parameters: { + ...parameters, + messages: [...resultList, ...list] + } + }); + }, [messageList, systemMessage, parameters]); const abortFetch = () => { handleStopConversation(); @@ -338,16 +343,11 @@ const ModelItem: React.FC = forwardRef((props, ref) => { - + > ); }); diff --git a/src/pages/playground/components/view-code-modal.tsx b/src/pages/playground/components/view-code-modal.tsx deleted file mode 100644 index 8972f71e..00000000 --- a/src/pages/playground/components/view-code-modal.tsx +++ /dev/null @@ -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; - 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 = (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 ( - <> - -
- {intl.formatMessage({ id: 'playground.viewcode.info' })} -
-
- - - -
- - - {intl.formatMessage( - { id: 'playground.viewcode.tips' }, - { - here: ( - - ) - } - )} - -
-
-
- - ); -}; - -export default React.memo(ViewCodeModal); diff --git a/src/pages/playground/components/view-common-code.tsx b/src/pages/playground/components/view-common-code.tsx index e1de03e6..58a479f7 100644 --- a/src/pages/playground/components/view-common-code.tsx +++ b/src/pages/playground/components/view-common-code.tsx @@ -6,7 +6,7 @@ import { Button, Modal } from 'antd'; import React, { useMemo, useState } from 'react'; type ViewModalProps = { - title: string; + title?: string; open: boolean; viewCodeContent: { curlCode: string; @@ -59,7 +59,7 @@ const ViewCodeModal: React.FC = (props) => { return ( <> ) => { + 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 + }; +}; diff --git a/src/pages/playground/view-code/utils.ts b/src/pages/playground/view-code/utils.ts index b990a7b1..aace8adb 100644 --- a/src/pages/playground/view-code/utils.ts +++ b/src/pages/playground/view-code/utils.ts @@ -22,10 +22,14 @@ export const formatPyParams = (parameters: Record) => { if (parameters[key] === null || parameters[key] === undefined) { return acc; } + const vauleType = typeof parameters[key]; const value = - typeof parameters[key] === 'object' + vauleType === 'object' ? JSON.stringify(parameters[key], null, 2) - : `"${parameters[key]}"`; + : vauleType === 'string' + ? `"${parameters[key]}"` + : parameters[key]; + return acc + ` ${key}=${value},\n`; }, ''); };