feat: vllm support
This commit is contained in:
@@ -99,7 +99,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
if (!chunk) {
|
||||
return;
|
||||
}
|
||||
if (_.get(chunk, 'choices.0.finish_reason')) {
|
||||
if (!_.get(chunk, 'choices', []).length) {
|
||||
setTokenResult({
|
||||
...chunk?.usage
|
||||
});
|
||||
@@ -142,6 +142,9 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
: [];
|
||||
|
||||
contentRef.current = '';
|
||||
setMessageList((pre) => {
|
||||
return [...pre, ...currentMessageRef.current];
|
||||
});
|
||||
const formatMessages = _.map(
|
||||
[...messageList, ...currentMessageRef.current],
|
||||
(item: MessageItem) => {
|
||||
@@ -217,9 +220,10 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
setTokenResult(null);
|
||||
};
|
||||
|
||||
const handleSendMessage = (message: { role: string; content: string }) => {
|
||||
const handleSendMessage = (message: Omit<MessageItem, 'uid'>) => {
|
||||
console.log('message:', message);
|
||||
const currentMessage = message.content ? message : undefined;
|
||||
const currentMessage =
|
||||
message.content || message.imgs?.length ? message : undefined;
|
||||
submitMessage(currentMessage);
|
||||
};
|
||||
|
||||
|
||||
@@ -110,7 +110,9 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
||||
const inputRef = useRef<any>(null);
|
||||
|
||||
const isDisabled = useMemo(() => {
|
||||
return disabled ? true : !message.content && isEmpty;
|
||||
return disabled
|
||||
? true
|
||||
: !message.content && isEmpty && !message.imgs?.length;
|
||||
}, [disabled, message.content, isEmpty]);
|
||||
|
||||
const resetMessage = () => {
|
||||
@@ -214,9 +216,6 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
||||
dataUrl: img
|
||||
};
|
||||
});
|
||||
// setImgList((pre) => {
|
||||
// return [...pre, ...list];
|
||||
// });
|
||||
setMessage({
|
||||
...message,
|
||||
imgs: [...(message.imgs || []), ...list]
|
||||
@@ -253,7 +252,7 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
||||
if (text) {
|
||||
setMessage?.({
|
||||
...message,
|
||||
content: text
|
||||
content: message.content + text
|
||||
});
|
||||
} else {
|
||||
getPasteContent(e);
|
||||
@@ -446,7 +445,7 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
||||
<div className="input-box">
|
||||
<TextArea
|
||||
ref={inputRef}
|
||||
autoSize={{ minRows: 3, maxRows: 3 }}
|
||||
autoSize={{ minRows: 3, maxRows: 8 }}
|
||||
onChange={(e) => handleInputChange(e.target.value)}
|
||||
value={message.content}
|
||||
size="large"
|
||||
|
||||
@@ -83,7 +83,7 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
||||
if (!chunk) {
|
||||
return;
|
||||
}
|
||||
if (_.get(chunk, 'choices.0.finish_reason')) {
|
||||
if (!_.get(chunk, 'choices', [].length)) {
|
||||
setTokenResult({
|
||||
...chunk?.usage
|
||||
});
|
||||
@@ -120,6 +120,9 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
||||
}
|
||||
]
|
||||
: [];
|
||||
setMessageList((preList) => {
|
||||
return [...preList, ...currentMessageRef.current];
|
||||
});
|
||||
console.log('currentMessageRef.current 1:', currentMessageRef.current);
|
||||
console.log('currentMessage==========4', messageList);
|
||||
const messages = _.map(
|
||||
@@ -208,12 +211,11 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleSubmit = (currentMessage: {
|
||||
role: string;
|
||||
content: string;
|
||||
}) => {
|
||||
console.log('currentMessage==========2', currentMessage);
|
||||
const currentMsg = currentMessage.content ? currentMessage : undefined;
|
||||
const handleSubmit = (currentMessage: Omit<MessageItem, 'uid'>) => {
|
||||
const currentMsg =
|
||||
currentMessage.content || currentMessage.imgs?.length
|
||||
? currentMessage
|
||||
: undefined;
|
||||
submitMessage(currentMsg);
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ const ReferenceParams = (props: ReferenceParamsProps) => {
|
||||
if (!usage) {
|
||||
return null;
|
||||
}
|
||||
console.log('ReferenceParams usage:', usage);
|
||||
return (
|
||||
<div className="reference-params">
|
||||
<span className="usage">
|
||||
@@ -48,14 +49,18 @@ const ReferenceParams = (props: ReferenceParamsProps) => {
|
||||
<Tooltip
|
||||
title={
|
||||
<Space>
|
||||
<span>TPOT: {_.round(usage.time_per_output_token_ms, 2)} ms</span>
|
||||
<span>TTFT: {_.round(usage.time_to_first_token_ms, 2)} ms</span>
|
||||
<span>
|
||||
TPOT: {_.round(usage.time_per_output_token_ms, 2) || 0} ms
|
||||
</span>
|
||||
<span>
|
||||
TTFT: {_.round(usage.time_to_first_token_ms, 2) || 0} ms
|
||||
</span>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{intl.formatMessage({ id: 'playground.tokenoutput' })}:{' '}
|
||||
{_.round(usage.tokens_per_second, 2)} Tokens/s
|
||||
{_.round(usage.tokens_per_second, 2) || 0} Tokens/s
|
||||
</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import EditorWrap from '@/components/editor-wrap';
|
||||
import HighlightCode from '@/components/highlight-code';
|
||||
import { BulbOutlined } from '@ant-design/icons';
|
||||
import Editor from '@monaco-editor/react';
|
||||
import { useIntl } from '@umijs/max';
|
||||
import { Button, Modal } from 'antd';
|
||||
import _ from 'lodash';
|
||||
@@ -16,6 +16,18 @@ type ViewModalProps = {
|
||||
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,
|
||||
@@ -31,7 +43,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
const editorRef = useRef(null);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [codeValue, setCodeValue] = useState('');
|
||||
const [lang, setLang] = useState('shell');
|
||||
const [lang, setLang] = useState(langMap.shell);
|
||||
|
||||
const BaseURL = `${window.location.origin}/v1-openai`;
|
||||
const ClientType = apiType === 'chat' ? 'chat.completions' : 'embeddings';
|
||||
@@ -39,24 +51,6 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
const logcommand =
|
||||
apiType === 'chat' ? 'choices[0].message.content' : 'data[0].embedding';
|
||||
|
||||
const langOptions = [
|
||||
{ label: 'Curl', value: 'shell' },
|
||||
{ label: 'Python', value: 'python' },
|
||||
{ label: 'Nodejs', value: 'javascript' }
|
||||
];
|
||||
|
||||
const formatCode = () => {
|
||||
if (editorRef.current) {
|
||||
setTimeout(() => {
|
||||
editorRef.current
|
||||
?.getAction?.('editor.action.formatDocument')
|
||||
?.run()
|
||||
.then(() => {
|
||||
console.log('format success');
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
};
|
||||
const generateCode = () => {
|
||||
const systemList = systemMessage
|
||||
? [
|
||||
@@ -91,7 +85,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
]
|
||||
};
|
||||
});
|
||||
if (lang === 'shell') {
|
||||
if (lang === langMap.shell) {
|
||||
const messages = [...systemList, ...formatMessageList];
|
||||
const code = `curl ${window.location.origin}/v1-openai/${api} \\\n-H "Content-Type: application/json" \\\n-H "Authorization: Bearer $\{YOUR_GPUSTACK_API_KEY}" \\\n-d '${JSON.stringify(
|
||||
{
|
||||
@@ -102,7 +96,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
2
|
||||
)}'`;
|
||||
setCodeValue(code);
|
||||
} else if (lang === 'javascript') {
|
||||
} else if (lang === langMap.javascript) {
|
||||
const messages = [...systemList, ...formatMessageList];
|
||||
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(
|
||||
{
|
||||
@@ -113,7 +107,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
4
|
||||
)};\nconst response = await openai.${ClientType}.create(params);\n console.log(response.${logcommand});\n}\nmain();`;
|
||||
setCodeValue(code);
|
||||
} else if (lang === 'python') {
|
||||
} else if (lang === langMap.python) {
|
||||
const formattedParams = _.keys(parameters).reduce(
|
||||
(acc: string, key: string) => {
|
||||
if (parameters[key] === null) {
|
||||
@@ -138,20 +132,6 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
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}.create(\n${formattedParams} ${messages})\nprint(response.${logcommand})`;
|
||||
setCodeValue(code);
|
||||
}
|
||||
formatCode();
|
||||
};
|
||||
const handleEditorDidMount = (editor: any, monaco: any) => {
|
||||
editorRef.current = editor;
|
||||
setLoaded(true);
|
||||
console.log('loaded====', editor, monaco);
|
||||
};
|
||||
|
||||
const handleBeforeMount = (monaco: any) => {
|
||||
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
|
||||
noSemanticValidation: false,
|
||||
noSyntaxValidation: false,
|
||||
diagnosticCodesToIgnore: [80001]
|
||||
});
|
||||
};
|
||||
|
||||
const handleOnChangeLang = (value: string) => {
|
||||
@@ -159,7 +139,7 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
setLang('shell');
|
||||
setLang(langMap.shell);
|
||||
onCancel();
|
||||
};
|
||||
const editorConfig = {
|
||||
@@ -203,21 +183,22 @@ const ViewCodeModal: React.FC<ViewModalProps> = (props) => {
|
||||
<EditorWrap
|
||||
copyText={codeValue}
|
||||
langOptions={langOptions}
|
||||
defaultValue="shell"
|
||||
showHeader={loaded}
|
||||
defaultValue={langMap.shell}
|
||||
showHeader={true}
|
||||
onChangeLang={handleOnChangeLang}
|
||||
styles={{
|
||||
wrapper: {
|
||||
backgroundColor: 'var(--color-editor-dark)'
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Editor
|
||||
<HighlightCode
|
||||
height={380}
|
||||
theme="vs-dark"
|
||||
className="monaco-editor"
|
||||
defaultLanguage="shell"
|
||||
language={lang}
|
||||
value={codeValue}
|
||||
options={editorConfig}
|
||||
beforeMount={handleBeforeMount}
|
||||
onMount={handleEditorDidMount}
|
||||
/>
|
||||
theme="dark"
|
||||
code={codeValue}
|
||||
lang={lang}
|
||||
copyable={false}
|
||||
></HighlightCode>
|
||||
</EditorWrap>
|
||||
<div
|
||||
style={{ marginTop: 10, display: 'flex', alignItems: 'baseline' }}
|
||||
|
||||
Reference in New Issue
Block a user