feat: add models compare
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { createFromIconfontCN } from '@ant-design/icons';
|
import { createFromIconfontCN } from '@ant-design/icons';
|
||||||
|
|
||||||
const IconFont = createFromIconfontCN({
|
const IconFont = createFromIconfontCN({
|
||||||
scriptUrl: '//at.alicdn.com/t/c/font_4613488_xpmv3m9655d.js'
|
scriptUrl: '//at.alicdn.com/t/c/font_4613488_fcpq8y25444.js'
|
||||||
});
|
});
|
||||||
|
|
||||||
export default IconFont;
|
export default IconFont;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
:local(.wrapper-box) {
|
:local(.wrapper-box) {
|
||||||
@borderRadius: 8px;
|
@borderRadius: var(--border-radius-base);
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -5,13 +5,16 @@ import {
|
|||||||
ClearOutlined,
|
ClearOutlined,
|
||||||
ControlOutlined,
|
ControlOutlined,
|
||||||
PictureOutlined,
|
PictureOutlined,
|
||||||
SendOutlined
|
SendOutlined,
|
||||||
|
SwapOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Input, Select } from 'antd';
|
import { Button, Divider, Input, Select } from 'antd';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
import { Roles } from '../config';
|
||||||
import '../style/message-input.less';
|
import '../style/message-input.less';
|
||||||
|
import PromptModal from './prompt-modal';
|
||||||
|
|
||||||
const layoutOptions = [
|
const layoutOptions = [
|
||||||
{
|
{
|
||||||
@@ -36,7 +39,7 @@ const layoutOptions = [
|
|||||||
label: '4 columns',
|
label: '4 columns',
|
||||||
icon: 'icon-cols_4',
|
icon: 'icon-cols_4',
|
||||||
value: {
|
value: {
|
||||||
span: 6,
|
span: 12,
|
||||||
count: 4
|
count: 4
|
||||||
},
|
},
|
||||||
tips: 'four models compare'
|
tips: 'four models compare'
|
||||||
@@ -54,31 +57,47 @@ const layoutOptions = [
|
|||||||
|
|
||||||
interface MessageInputProps {
|
interface MessageInputProps {
|
||||||
modelList: Global.BaseOption<string>[];
|
modelList: Global.BaseOption<string>[];
|
||||||
handleSubmit: (value: string) => void;
|
handleSubmit: (params: { role: string; content: string }) => void;
|
||||||
handleAbortFetch: () => void;
|
handleAbortFetch: () => void;
|
||||||
setParamsSettings: (value: Record<string, any>) => void;
|
|
||||||
setSpans: (value: { span: number; count: number }) => void;
|
setSpans: (value: { span: number; count: number }) => void;
|
||||||
|
clearAll: () => void;
|
||||||
|
setModelSelections: (modelList: Global.BaseOption<string>[]) => void;
|
||||||
|
presetPrompt: (list: { role: string; content: string }[]) => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MessageInput: React.FC<MessageInputProps> = ({
|
const MessageInput: React.FC<MessageInputProps> = ({
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
handleAbortFetch,
|
handleAbortFetch,
|
||||||
setParamsSettings,
|
setModelSelections,
|
||||||
|
presetPrompt,
|
||||||
loading,
|
loading,
|
||||||
modelList,
|
modelList,
|
||||||
|
clearAll,
|
||||||
setSpans
|
setSpans
|
||||||
}) => {
|
}) => {
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const platform = platformCall();
|
const platform = platformCall();
|
||||||
const [disabled, setDisabled] = useState(false);
|
const [disabled, setDisabled] = useState(false);
|
||||||
const [message, setMessage] = useState('');
|
const [open, setOpen] = useState(false);
|
||||||
|
const [message, setMessage] = useState<{ role: string; content: string }>({
|
||||||
|
role: Roles.User,
|
||||||
|
content: ''
|
||||||
|
});
|
||||||
const handleInputChange = (value: string) => {
|
const handleInputChange = (value: string) => {
|
||||||
setMessage(value);
|
console.log('input change:', value);
|
||||||
|
setMessage({
|
||||||
|
...message,
|
||||||
|
content: value
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const handleSendMessage = () => {
|
const handleSendMessage = () => {
|
||||||
handleSubmit(message);
|
handleSubmit({ ...message });
|
||||||
|
setMessage({
|
||||||
|
...message,
|
||||||
|
content: ''
|
||||||
|
});
|
||||||
};
|
};
|
||||||
const onStop = () => {
|
const onStop = () => {
|
||||||
setDisabled(false);
|
setDisabled(false);
|
||||||
@@ -88,6 +107,33 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
|||||||
console.log('layout change:', value);
|
console.log('layout change:', value);
|
||||||
setSpans(value);
|
setSpans(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleToggleRole = () => {
|
||||||
|
setMessage({
|
||||||
|
...message,
|
||||||
|
role: message.role === Roles.User ? Roles.Assistant : Roles.User
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearAll = (e: any) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
clearAll();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdateModelSelections = (value: string[]) => {
|
||||||
|
console.log('update model selections:', value);
|
||||||
|
const list = value?.map?.((val) => {
|
||||||
|
return {
|
||||||
|
value: val,
|
||||||
|
label: val
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setModelSelections(list);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenPrompt = () => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
HotKeys.SUBMIT.join(','),
|
HotKeys.SUBMIT.join(','),
|
||||||
() => {
|
() => {
|
||||||
@@ -99,10 +145,29 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
|||||||
<div className="messageInput">
|
<div className="messageInput">
|
||||||
<div className="tool-bar">
|
<div className="tool-bar">
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
size="middle"
|
||||||
|
onClick={handleToggleRole}
|
||||||
|
icon={<SwapOutlined rotate={90} />}
|
||||||
|
>
|
||||||
|
{intl.formatMessage({ id: `playground.${message.role}` })}
|
||||||
|
</Button>
|
||||||
|
<Divider type="vertical" style={{ margin: 0 }} />
|
||||||
<Button type="text" icon={<PictureOutlined />} size="middle"></Button>
|
<Button type="text" icon={<PictureOutlined />} size="middle"></Button>
|
||||||
<Button type="text" icon={<ClearOutlined />} size="middle"></Button>
|
<Button
|
||||||
<Button type="text" icon={<ControlOutlined />} size="middle"></Button>
|
type="text"
|
||||||
|
icon={<ClearOutlined />}
|
||||||
|
size="middle"
|
||||||
|
onClick={handleClearAll}
|
||||||
|
></Button>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
icon={<ControlOutlined />}
|
||||||
|
size="middle"
|
||||||
|
onClick={handleOpenPrompt}
|
||||||
|
></Button>
|
||||||
|
<Divider type="vertical" style={{ margin: 0 }} />
|
||||||
{layoutOptions.map((option) => (
|
{layoutOptions.map((option) => (
|
||||||
<Button
|
<Button
|
||||||
key={option.icon}
|
key={option.icon}
|
||||||
@@ -123,13 +188,20 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
|||||||
maxCount={6}
|
maxCount={6}
|
||||||
maxTagCount={0}
|
maxTagCount={0}
|
||||||
maxTagTextLength={15}
|
maxTagTextLength={15}
|
||||||
|
onChange={handleUpdateModelSelections}
|
||||||
></Select>
|
></Select>
|
||||||
{!loading ? (
|
{!loading ? (
|
||||||
<Button type="primary" onClick={handleSendMessage} size="middle">
|
<Button
|
||||||
|
style={{ width: 44 }}
|
||||||
|
type="primary"
|
||||||
|
onClick={handleSendMessage}
|
||||||
|
size="middle"
|
||||||
|
>
|
||||||
<SendOutlined />
|
<SendOutlined />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<Button
|
<Button
|
||||||
|
style={{ width: 44 }}
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={onStop}
|
onClick={onStop}
|
||||||
size="middle"
|
size="middle"
|
||||||
@@ -139,13 +211,18 @@ const MessageInput: React.FC<MessageInputProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<TextArea
|
<TextArea
|
||||||
placeholder="Send your message"
|
placeholder="Type your message here"
|
||||||
autoSize={{ minRows: 3, maxRows: 3 }}
|
autoSize={{ minRows: 3, maxRows: 3 }}
|
||||||
onChange={(e) => handleInputChange(e.target.value)}
|
onChange={(e) => handleInputChange(e.target.value)}
|
||||||
value={message}
|
value={message.content}
|
||||||
size="large"
|
size="large"
|
||||||
variant="borderless"
|
variant="borderless"
|
||||||
></TextArea>
|
></TextArea>
|
||||||
|
<PromptModal
|
||||||
|
open={open}
|
||||||
|
onCancel={() => setOpen(false)}
|
||||||
|
onSelect={presetPrompt}
|
||||||
|
></PromptModal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { Col, Row } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import ModelItem from './model-item';
|
||||||
|
|
||||||
|
interface ActiveModelsProps {
|
||||||
|
spans: {
|
||||||
|
span: number;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
modelSelections: Global.BaseOption<string>[];
|
||||||
|
setModelRefs: (modelname: string, value: React.MutableRefObject<any>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ActiveModels: React.FC<ActiveModelsProps> = (props) => {
|
||||||
|
const { spans, modelSelections, setModelRefs } = props;
|
||||||
|
return (
|
||||||
|
<Row gutter={[16, 16]} style={{ height: '100%' }}>
|
||||||
|
{modelSelections.map((model, index) => (
|
||||||
|
<Col span={spans.span} key={model.value}>
|
||||||
|
<ModelItem
|
||||||
|
key={model.value}
|
||||||
|
ref={(el: React.MutableRefObject<any>) =>
|
||||||
|
setModelRefs(model.value, el)
|
||||||
|
}
|
||||||
|
modelList={modelSelections}
|
||||||
|
model={model.value}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(ActiveModels);
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import IconFont from '@/components/icon-font';
|
||||||
|
import { UserOutlined } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { Roles } from '../../config';
|
||||||
|
import '../../style/content-item.less';
|
||||||
|
|
||||||
const ContentItem: React.FC<{ data: { role: string; content: string } }> = ({
|
const ContentItem: React.FC<{ data: { role: string; content: string } }> = ({
|
||||||
data
|
data
|
||||||
@@ -8,7 +12,13 @@ const ContentItem: React.FC<{ data: { role: string; content: string } }> = ({
|
|||||||
return (
|
return (
|
||||||
<div className="content-item">
|
<div className="content-item">
|
||||||
<div className="content-item-role">
|
<div className="content-item-role">
|
||||||
{' '}
|
<span className="m-r-5">
|
||||||
|
{Roles.User === data.role ? (
|
||||||
|
<UserOutlined></UserOutlined>
|
||||||
|
) : (
|
||||||
|
<IconFont type="icon-AIzhineng"></IconFont>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
{intl.formatMessage({ id: `playground.${data.role}` })}
|
{intl.formatMessage({ id: `playground.${data.role}` })}
|
||||||
</div>
|
</div>
|
||||||
<div className="content-item-content">{data.content}</div>
|
<div className="content-item-content">{data.content}</div>
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
import { Col, Row } from 'antd';
|
import _ from 'lodash';
|
||||||
import { memo, useEffect, useMemo, useRef, useState } from 'react';
|
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import CompareContext from '../../config/compare-context';
|
||||||
import '../../style/multiple-chat.less';
|
import '../../style/multiple-chat.less';
|
||||||
import MessageInput from '../message-input';
|
import MessageInput from '../message-input';
|
||||||
import ModelItem from './model-item';
|
import ActiveModels from './active-models';
|
||||||
|
|
||||||
interface MultiCompareProps {
|
interface MultiCompareProps {
|
||||||
modelList: Global.BaseOption<string>[];
|
modelList: Global.BaseOption<string>[];
|
||||||
parmasSettings?: Record<string, any>;
|
|
||||||
spans?: number;
|
spans?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
|
const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
|
||||||
const [loadingStatus, setLoadingStatus] = useState<boolean[]>([]);
|
const [loadingStatus, setLoadingStatus] = useState<Record<string, boolean>>(
|
||||||
const [parmasSettings, setParamsSettings] = useState<Record<string, any>>({});
|
{}
|
||||||
const [systemMessage, setSystemMessage] = useState<string>('');
|
);
|
||||||
const [currentMessage, setCurrentMessage] = useState<
|
const [modelSelections, setModelSelections] = useState<
|
||||||
{
|
Global.BaseOption<string>[]
|
||||||
role: 'user' | 'assistant';
|
|
||||||
content: string;
|
|
||||||
}[]
|
|
||||||
>([]);
|
>([]);
|
||||||
const [globalParams, setGlobalParams] = useState<Record<string, any>>({
|
const [globalParams, setGlobalParams] = useState<Record<string, any>>({
|
||||||
seed: null,
|
seed: null,
|
||||||
@@ -34,88 +31,127 @@ const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
|
|||||||
span: 12,
|
span: 12,
|
||||||
count: 2
|
count: 2
|
||||||
});
|
});
|
||||||
const modelRefs = useRef<any[]>([]);
|
const modelRefs = useRef<any>({});
|
||||||
|
const boxHeight = 'calc(100vh - 72px)';
|
||||||
|
|
||||||
const isLoading = useMemo(() => {
|
const isLoading = useMemo(() => {
|
||||||
return loadingStatus.some((status) => status);
|
console.log('loadingStatus========2', loadingStatus);
|
||||||
|
return _.keys(loadingStatus).some(
|
||||||
|
(modelname: string) => loadingStatus[modelname]
|
||||||
|
);
|
||||||
}, [loadingStatus]);
|
}, [loadingStatus]);
|
||||||
|
|
||||||
const modelSelections = useMemo(() => {
|
useEffect(() => {
|
||||||
const list = modelList.slice?.(0, spans.count);
|
const list = modelList.slice?.(0, spans.count);
|
||||||
return list;
|
setModelSelections(list);
|
||||||
}, [modelList, spans.count]);
|
}, [modelList, spans.count]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
modelRefs.current = modelSelections.map(() => {
|
modelRefs.current = {};
|
||||||
return {};
|
modelSelections.forEach((item) => {
|
||||||
|
modelRefs.current[item.value] = null;
|
||||||
});
|
});
|
||||||
}, [modelSelections]);
|
}, [modelSelections]);
|
||||||
|
|
||||||
const handleSubmit = (message: string) => {
|
const handleSubmit = (currentMessage: { role: string; content: string }) => {
|
||||||
let msg: any[] = [];
|
const modelRefList = _.keys(modelRefs.current);
|
||||||
if (message) {
|
modelRefList.forEach(async (modelname: any, index: number) => {
|
||||||
msg = [
|
const ref = modelRefs.current[modelname];
|
||||||
{
|
ref?.submit(currentMessage);
|
||||||
role: 'user',
|
|
||||||
content: message
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
modelRefs.current.forEach(async (ref, index) => {
|
|
||||||
ref?.setMessageList((preList: any) => {
|
|
||||||
return [...preList, ...msg];
|
|
||||||
});
|
|
||||||
setLoadingStatus((preStatus) => {
|
|
||||||
const newState = [...preStatus];
|
|
||||||
newState[index] = true;
|
|
||||||
return newState;
|
|
||||||
});
|
|
||||||
await ref?.submit();
|
|
||||||
setLoadingStatus((preStatus) => {
|
|
||||||
const newState = [...preStatus];
|
|
||||||
newState[index] = false;
|
|
||||||
return newState;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAbortFetch = () => {
|
const handleAbortFetch = () => {
|
||||||
modelRefs.current.forEach((ref) => {
|
_.keys(modelRefs.current).forEach((modelname: string) => {
|
||||||
|
const ref = modelRefs.current[modelname];
|
||||||
ref?.abortFetch();
|
ref?.abortFetch();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const setModelRefs = (index: number, ref: any) => {
|
const setModelRefs = useCallback(
|
||||||
modelRefs.current[index] = ref;
|
(modelname: string, el: React.MutableRefObject<any>) => {
|
||||||
|
modelRefs.current[modelname] = el;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSetLoadingStatus = (modeName: string, status: boolean) => {
|
||||||
|
setLoadingStatus((preStatus) => {
|
||||||
|
const newState = { ...preStatus };
|
||||||
|
newState[modeName] = status;
|
||||||
|
return newState;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearAll = () => {
|
||||||
|
_.keys(modelRefs.current).forEach((modelname: string) => {
|
||||||
|
const ref = modelRefs.current[modelname];
|
||||||
|
ref?.clear();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteModel = (modelname: string) => {
|
||||||
|
const newModelList = modelSelections.filter(
|
||||||
|
(model) => model.value !== modelname
|
||||||
|
);
|
||||||
|
const span = Math.floor(24 / (24 / spans.span - 1));
|
||||||
|
setSpans({
|
||||||
|
span,
|
||||||
|
count: spans.count
|
||||||
|
});
|
||||||
|
setModelSelections(newModelList);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleUpdateModelSelections = (list: Global.BaseOption<string>[]) => {
|
||||||
|
// set spans.span
|
||||||
|
const span = Math.floor(24 / list.length);
|
||||||
|
setSpans({
|
||||||
|
span: span < 8 ? 8 : span,
|
||||||
|
count: spans.count
|
||||||
|
});
|
||||||
|
setModelSelections(list);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePresetPrompt = (list: { role: string; content: string }[]) => {
|
||||||
|
const sysMsg = list.filter((item) => item.role === 'system');
|
||||||
|
const userMsg = list.filter((item) => item.role === 'user');
|
||||||
|
const modelRefList = _.keys(modelRefs.current);
|
||||||
|
modelRefList.forEach(async (modelname: any) => {
|
||||||
|
const ref = modelRefs.current[modelname];
|
||||||
|
ref?.presetPrompt(userMsg);
|
||||||
|
ref?.setSystemMessage(_.get(sysMsg, '0.content', ''));
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="multiple-chat">
|
<div className="multiple-chat" style={{ height: boxHeight }}>
|
||||||
<div className="chat-list">
|
<div className="chat-list">
|
||||||
<Row gutter={[16, 16]} style={{ height: '100%' }}>
|
<CompareContext.Provider
|
||||||
{modelSelections.map((model, index) => (
|
value={{
|
||||||
<Col span={spans.span} key={model.value}>
|
spans,
|
||||||
<ModelItem
|
globalParams,
|
||||||
ref={(el: any) => setModelRefs(index, el)}
|
loadingStatus,
|
||||||
modelList={modelSelections}
|
setGlobalParams,
|
||||||
globalParams={{
|
setLoadingStatus: handleSetLoadingStatus,
|
||||||
...globalParams,
|
handleDeleteModel: handleDeleteModel
|
||||||
model: model.value
|
}}
|
||||||
}}
|
>
|
||||||
systemMessage={systemMessage}
|
<ActiveModels
|
||||||
setGlobalParams={setGlobalParams}
|
spans={spans}
|
||||||
/>
|
modelSelections={modelSelections}
|
||||||
</Col>
|
setModelRefs={setModelRefs}
|
||||||
))}
|
></ActiveModels>
|
||||||
</Row>
|
</CompareContext.Provider>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<MessageInput
|
<MessageInput
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
handleAbortFetch={handleAbortFetch}
|
handleAbortFetch={handleAbortFetch}
|
||||||
setParamsSettings={setParamsSettings}
|
clearAll={handleClearAll}
|
||||||
setSpans={setSpans}
|
setSpans={setSpans}
|
||||||
|
setModelSelections={handleUpdateModelSelections}
|
||||||
|
presetPrompt={handlePresetPrompt}
|
||||||
modelList={modelList}
|
modelList={modelList}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,49 @@
|
|||||||
import React from 'react';
|
import { Spin } from 'antd';
|
||||||
|
import React, { useMemo } from 'react';
|
||||||
|
import SimpleBar from 'simplebar-react';
|
||||||
|
import 'simplebar-react/dist/simplebar.min.css';
|
||||||
import ContentItem from './content-item';
|
import ContentItem from './content-item';
|
||||||
|
|
||||||
interface MessageContentProps {
|
interface MessageContentProps {
|
||||||
|
loading: boolean;
|
||||||
|
spans: {
|
||||||
|
span: number;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
messageList: {
|
messageList: {
|
||||||
role: string;
|
role: string;
|
||||||
uid?: string;
|
uid?: any;
|
||||||
content: string;
|
content: string;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MessageContent: React.FC<MessageContentProps> = ({ messageList }) => {
|
const MessageContent: React.FC<MessageContentProps> = ({
|
||||||
|
messageList,
|
||||||
|
spans,
|
||||||
|
loading
|
||||||
|
}) => {
|
||||||
|
const maxHeight = useMemo(() => {
|
||||||
|
const total = 72 + 110 + 46 + 16 + 32;
|
||||||
|
if (spans.span < 4) {
|
||||||
|
return `calc(100vh - ${total}px)`;
|
||||||
|
}
|
||||||
|
return `calc(100vh - ${total * 2 + 16}px)`;
|
||||||
|
}, [spans.span]);
|
||||||
return (
|
return (
|
||||||
<div>
|
<>
|
||||||
{messageList.map((item, index) => (
|
{messageList.length ? (
|
||||||
<ContentItem key={index} data={item} />
|
<SimpleBar style={{ maxHeight: 'calc(100% - 46px)' }}>
|
||||||
))}
|
<div className="message-content-list">
|
||||||
</div>
|
{messageList.map((item, index) => (
|
||||||
|
<ContentItem key={index} data={item} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</SimpleBar>
|
||||||
|
) : (
|
||||||
|
<span>{loading}</span>
|
||||||
|
)}
|
||||||
|
<Spin spinning={!!loading} size="small" style={{ width: '100%' }} />
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import IconFont from '@/components/icon-font';
|
import IconFont from '@/components/icon-font';
|
||||||
|
import { fetchChunkedData, readStreamData } from '@/utils/fetch-chunk-data';
|
||||||
import {
|
import {
|
||||||
ClearOutlined,
|
ClearOutlined,
|
||||||
CloseOutlined,
|
CloseOutlined,
|
||||||
@@ -6,71 +7,200 @@ import {
|
|||||||
SettingOutlined
|
SettingOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Checkbox, Dropdown, Popover, Select } from 'antd';
|
import {
|
||||||
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Divider,
|
||||||
|
Dropdown,
|
||||||
|
Input,
|
||||||
|
Popover,
|
||||||
|
Select
|
||||||
|
} from 'antd';
|
||||||
|
import _ from 'lodash';
|
||||||
import React, {
|
import React, {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
|
useCallback,
|
||||||
|
useContext,
|
||||||
useEffect,
|
useEffect,
|
||||||
useImperativeHandle,
|
useImperativeHandle,
|
||||||
useRef,
|
useRef,
|
||||||
useState
|
useState
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import SimpleBar from 'simplebar-react';
|
|
||||||
import 'simplebar-react/dist/simplebar.min.css';
|
import 'simplebar-react/dist/simplebar.min.css';
|
||||||
import useChatCompletion from '../../hooks/use-chat-completion';
|
import { CHAT_API } from '../../apis';
|
||||||
|
import { Roles } from '../../config';
|
||||||
|
import CompareContext from '../../config/compare-context';
|
||||||
import '../../style/model-item.less';
|
import '../../style/model-item.less';
|
||||||
import ParamsSettings from '../params-settings';
|
import ParamsSettings from '../params-settings';
|
||||||
|
import ReferenceParams from '../reference-params';
|
||||||
|
import ViewCodeModal from '../view-code-modal';
|
||||||
import MessageContent from './message-content';
|
import MessageContent from './message-content';
|
||||||
|
|
||||||
interface ModelItemProps {
|
interface ModelItemProps {
|
||||||
model?: string;
|
model: string;
|
||||||
globalParams: Record<string, any>;
|
|
||||||
setGlobalParams: (value: Record<string, any>) => void;
|
|
||||||
modelList: Global.BaseOption<string>[];
|
modelList: Global.BaseOption<string>[];
|
||||||
systemMessage: string;
|
|
||||||
ref: any;
|
ref: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MessageItemProps {
|
||||||
|
role: string;
|
||||||
|
content: string;
|
||||||
|
uid: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
||||||
({ model, systemMessage, modelList, globalParams, setGlobalParams }, ref) => {
|
({ model, modelList }, ref) => {
|
||||||
|
const {
|
||||||
|
spans,
|
||||||
|
globalParams,
|
||||||
|
setGlobalParams,
|
||||||
|
setLoadingStatus,
|
||||||
|
handleDeleteModel,
|
||||||
|
loadingStatus
|
||||||
|
} = useContext(CompareContext);
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const isApplyToAllModels = useRef(false);
|
const isApplyToAllModels = useRef(false);
|
||||||
|
const [autoSize, setAutoSize] = useState<{
|
||||||
|
minRows: number;
|
||||||
|
maxRows: number;
|
||||||
|
}>({ minRows: 1, maxRows: 1 });
|
||||||
|
const [systemMessage, setSystemMessage] = useState<string>('');
|
||||||
const [params, setParams] = useState<Record<string, any>>({});
|
const [params, setParams] = useState<Record<string, any>>({});
|
||||||
// const [messageList, setMessageList] = useState<
|
const [loading, setLoading] = useState(false);
|
||||||
// {
|
const messageId = useRef<number>(0);
|
||||||
// role: 'user' | 'assistant';
|
const [messageList, setMessageList] = useState<MessageItemProps[]>([]);
|
||||||
// content: string;
|
const [tokenResult, setTokenResult] = useState<any>(null);
|
||||||
// }[]
|
const [show, setShow] = useState(false);
|
||||||
// >([]);
|
const contentRef = useRef<any>('');
|
||||||
const { messageList, submitMessage, abortFetch, setMessageList, loading } =
|
const controllerRef = useRef<any>(null);
|
||||||
useChatCompletion(systemMessage, params);
|
const currentMessageRef = useRef<MessageItemProps>({} as MessageItemProps);
|
||||||
|
|
||||||
useImperativeHandle(ref, () => {
|
const setMessageId = () => {
|
||||||
return {
|
messageId.current = messageId.current + 1;
|
||||||
submit: submitMessage,
|
};
|
||||||
abortFetch,
|
|
||||||
setMessageList,
|
|
||||||
loading
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const actions = [
|
const abortFetch = () => {
|
||||||
{
|
controllerRef.current?.abort?.();
|
||||||
label: intl.formatMessage({ id: 'common.button.clear' }),
|
setLoadingStatus(params.model, false);
|
||||||
key: 'clear',
|
};
|
||||||
icon: <ClearOutlined />
|
|
||||||
},
|
const joinMessage = (chunk: any) => {
|
||||||
{
|
if (!chunk) {
|
||||||
label: intl.formatMessage({ id: 'playground.viewcode' }),
|
return;
|
||||||
key: 'viewcode',
|
|
||||||
icon: <IconFont type="icon-code" />
|
|
||||||
}
|
}
|
||||||
];
|
if (_.get(chunk, 'choices.0.finish_reason')) {
|
||||||
|
setTokenResult({
|
||||||
|
...chunk?.usage
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
contentRef.current =
|
||||||
|
contentRef.current + _.get(chunk, 'choices.0.delta.content', '');
|
||||||
|
console.log('currentMessage==========5', messageList);
|
||||||
|
setMessageList([
|
||||||
|
...messageList,
|
||||||
|
{
|
||||||
|
...currentMessageRef.current
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: Roles.Assistant,
|
||||||
|
content: contentRef.current,
|
||||||
|
uid: messageId.current
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
const handleModelChange = (value: string) => {
|
const submitMessage = async (currentParams: {
|
||||||
setParams({
|
parameters: Record<string, any>;
|
||||||
...params,
|
currentMessage: { role: string; content: string };
|
||||||
model: value
|
}) => {
|
||||||
});
|
console.log('currentMessage==========3', currentParams);
|
||||||
|
const { parameters, currentMessage } = currentParams;
|
||||||
|
if (!parameters.model) return;
|
||||||
|
try {
|
||||||
|
setLoadingStatus(parameters.model, true);
|
||||||
|
setMessageId();
|
||||||
|
|
||||||
|
controllerRef.current?.abort?.();
|
||||||
|
controllerRef.current = new AbortController();
|
||||||
|
const signal = controllerRef.current.signal;
|
||||||
|
currentMessageRef.current = {
|
||||||
|
...currentMessage,
|
||||||
|
uid: messageId.current
|
||||||
|
};
|
||||||
|
setMessageList((preList) => {
|
||||||
|
return [
|
||||||
|
...preList,
|
||||||
|
{
|
||||||
|
...currentMessageRef.current
|
||||||
|
}
|
||||||
|
];
|
||||||
|
});
|
||||||
|
console.log('currentMessage==========4', messageList);
|
||||||
|
const messages = _.map(
|
||||||
|
[
|
||||||
|
...messageList,
|
||||||
|
{
|
||||||
|
...currentMessageRef.current
|
||||||
|
}
|
||||||
|
],
|
||||||
|
(item: MessageItemProps) => {
|
||||||
|
return {
|
||||||
|
role: item.role,
|
||||||
|
content: item.content
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
contentRef.current = '';
|
||||||
|
const chatParams = {
|
||||||
|
messages: systemMessage
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
role: Roles.System,
|
||||||
|
content: systemMessage
|
||||||
|
},
|
||||||
|
...messages
|
||||||
|
]
|
||||||
|
: [...messages],
|
||||||
|
...parameters,
|
||||||
|
stream: true
|
||||||
|
};
|
||||||
|
const result = await fetchChunkedData({
|
||||||
|
data: chatParams,
|
||||||
|
url: CHAT_API,
|
||||||
|
signal
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { reader, decoder } = result;
|
||||||
|
await readStreamData(reader, decoder, (chunk: any) => {
|
||||||
|
joinMessage(chunk);
|
||||||
|
});
|
||||||
|
setLoadingStatus(params.model, false);
|
||||||
|
} catch (error) {
|
||||||
|
console.log('error=====', error);
|
||||||
|
setLoadingStatus(params.model, false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleDropdownAction = useCallback(({ key }: { key: string }) => {
|
||||||
|
console.log('key:', key);
|
||||||
|
if (key === 'clear') {
|
||||||
|
setMessageList([]);
|
||||||
|
}
|
||||||
|
if (key === 'viewCode') {
|
||||||
|
setShow(true);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSubmit = (currentMessage: {
|
||||||
|
role: string;
|
||||||
|
content: string;
|
||||||
|
}) => {
|
||||||
|
console.log('currentMessage==========2', currentMessage);
|
||||||
|
submitMessage({ parameters: params, currentMessage });
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleApplyToAllModels = (e: any) => {
|
const handleApplyToAllModels = (e: any) => {
|
||||||
@@ -104,17 +234,67 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDropdownAction = ({ key }: { key: string }) => {
|
const handleClearMessage = () => {
|
||||||
console.log('key:', key);
|
setMessageList([]);
|
||||||
|
setTokenResult(null);
|
||||||
|
setSystemMessage('');
|
||||||
|
currentMessageRef.current = {} as MessageItemProps;
|
||||||
|
};
|
||||||
|
const handleCloseViewCode = () => {
|
||||||
|
setShow(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleModelChange = (value: string) => {
|
||||||
|
setParams({
|
||||||
|
...params,
|
||||||
|
model: value
|
||||||
|
});
|
||||||
|
handleClearMessage();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePresetMessageList = (list: MessageItemProps[]) => {
|
||||||
|
currentMessageRef.current = {} as MessageItemProps;
|
||||||
|
const messages = _.map(
|
||||||
|
list,
|
||||||
|
(item: { role: string; content: string }) => {
|
||||||
|
setMessageId();
|
||||||
|
return {
|
||||||
|
role: item.role,
|
||||||
|
content: item.content,
|
||||||
|
uid: messageId.current
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
setTokenResult(null);
|
||||||
|
setMessageList(messages);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
handleDeleteModel(params.model);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFocus = () => {
|
||||||
|
setAutoSize({
|
||||||
|
minRows: 4,
|
||||||
|
maxRows: 4
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBlur = () => {
|
||||||
|
setAutoSize({
|
||||||
|
minRows: 1,
|
||||||
|
maxRows: 1
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('globalParams:', globalParams.model, globalParams);
|
console.log('globalParams:', globalParams.model, globalParams);
|
||||||
setParams({
|
setParams({
|
||||||
...params,
|
...params,
|
||||||
|
model: model,
|
||||||
...globalParams
|
...globalParams
|
||||||
});
|
});
|
||||||
}, [globalParams]);
|
}, [globalParams, model]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@@ -122,6 +302,18 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => {
|
||||||
|
return {
|
||||||
|
submit: handleSubmit,
|
||||||
|
abortFetch,
|
||||||
|
setMessageList,
|
||||||
|
clear: handleClearMessage,
|
||||||
|
presetPrompt: handlePresetMessageList,
|
||||||
|
setSystemMessage,
|
||||||
|
loading
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="model-item">
|
<div className="model-item">
|
||||||
<div className="header">
|
<div className="header">
|
||||||
@@ -133,9 +325,29 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
|||||||
value={params.model}
|
value={params.model}
|
||||||
></Select>
|
></Select>
|
||||||
</span>
|
</span>
|
||||||
|
<ReferenceParams usage={tokenResult}></ReferenceParams>
|
||||||
<span className="action">
|
<span className="action">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
menu={{ items: actions, onSelect: handleDropdownAction }}
|
menu={{
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({ id: 'common.button.clear' }),
|
||||||
|
key: 'clear',
|
||||||
|
icon: <ClearOutlined />,
|
||||||
|
onClick: () => {
|
||||||
|
handleDropdownAction({ key: 'clear' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({ id: 'playground.viewcode' }),
|
||||||
|
key: 'viewcode',
|
||||||
|
icon: <IconFont type="icon-code" />,
|
||||||
|
onClick: () => {
|
||||||
|
handleDropdownAction({ key: 'viewCode' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}}
|
||||||
placement="bottomRight"
|
placement="bottomRight"
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
@@ -170,14 +382,43 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
|
|||||||
size="small"
|
size="small"
|
||||||
></Button>
|
></Button>
|
||||||
</Popover>
|
</Popover>
|
||||||
<Button type="text" icon={<CloseOutlined />} size="small"></Button>
|
<Button
|
||||||
|
type="text"
|
||||||
|
icon={<CloseOutlined />}
|
||||||
|
size="small"
|
||||||
|
onClick={handleDelete}
|
||||||
|
></Button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<SimpleBar style={{ height: 'calc(100% - 46px)' }}>
|
<div>
|
||||||
<div className="content">
|
<Input.TextArea
|
||||||
<MessageContent messageList={messageList} />
|
variant="filled"
|
||||||
</div>
|
placeholder="Type system message here"
|
||||||
</SimpleBar>
|
style={{ borderRadius: '0', border: 'none' }}
|
||||||
|
value={systemMessage}
|
||||||
|
autoSize={autoSize}
|
||||||
|
onFocus={handleFocus}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
allowClear={false}
|
||||||
|
onChange={(e) => setSystemMessage(e.target.value)}
|
||||||
|
></Input.TextArea>
|
||||||
|
<Divider style={{ margin: '0' }}></Divider>
|
||||||
|
</div>
|
||||||
|
<div className="content">
|
||||||
|
<MessageContent
|
||||||
|
spans={spans}
|
||||||
|
messageList={messageList}
|
||||||
|
loading={loadingStatus[params.model]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ViewCodeModal
|
||||||
|
open={show}
|
||||||
|
systemMessage={systemMessage}
|
||||||
|
messageList={messageList}
|
||||||
|
parameters={params}
|
||||||
|
onCancel={handleCloseViewCode}
|
||||||
|
title={intl.formatMessage({ id: 'playground.viewcode' })}
|
||||||
|
></ViewCodeModal>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { useIntl } from '@umijs/max';
|
||||||
|
import { Button, Modal, Typography } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import promptList from '../config/prompt';
|
||||||
|
import '../style/prompt-modal.less';
|
||||||
|
|
||||||
|
type ViewModalProps = {
|
||||||
|
open: boolean;
|
||||||
|
onCancel: () => void;
|
||||||
|
onSelect: (list: { role: string; content: string }[]) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AddWorker: React.FC<ViewModalProps> = (props) => {
|
||||||
|
const { open, onCancel } = props || {};
|
||||||
|
const intl = useIntl();
|
||||||
|
const handleSelect = (item: {
|
||||||
|
title: string;
|
||||||
|
data: { role: string; content: string }[];
|
||||||
|
}) => {
|
||||||
|
props.onSelect(item.data);
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title="Prompts"
|
||||||
|
open={open}
|
||||||
|
centered={true}
|
||||||
|
onCancel={onCancel}
|
||||||
|
destroyOnClose={true}
|
||||||
|
closeIcon={true}
|
||||||
|
maskClosable={false}
|
||||||
|
keyboard={false}
|
||||||
|
width={660}
|
||||||
|
styles={{
|
||||||
|
body: {
|
||||||
|
maxHeight: '550px',
|
||||||
|
overflow: 'auto'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
footer={null}
|
||||||
|
>
|
||||||
|
<div className="prompt-wrapper">
|
||||||
|
{promptList.map((item, index) => {
|
||||||
|
return (
|
||||||
|
<div key={index} className="prompt-item">
|
||||||
|
<h3 className="title">
|
||||||
|
<span className="text">{item.title}</span>
|
||||||
|
<Button
|
||||||
|
size="middle"
|
||||||
|
type="default"
|
||||||
|
onClick={() => handleSelect(item)}
|
||||||
|
>
|
||||||
|
Use
|
||||||
|
</Button>
|
||||||
|
</h3>
|
||||||
|
{item.data.map((data, i) => {
|
||||||
|
return (
|
||||||
|
<div key={i} className="data-item">
|
||||||
|
<span className="role">{data.role}</span>
|
||||||
|
<span className="prompt">
|
||||||
|
<Typography.Paragraph
|
||||||
|
style={{ margin: 0 }}
|
||||||
|
ellipsis={{ rows: 2, expandable: true, symbol: 'more' }}
|
||||||
|
>
|
||||||
|
{data.content}
|
||||||
|
</Typography.Paragraph>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(AddWorker);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
interface CompareContextProps {
|
||||||
|
spans: {
|
||||||
|
span: number;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
systemMessage?: string;
|
||||||
|
globalParams: Record<string, any>;
|
||||||
|
loadingStatus: Record<string, boolean>;
|
||||||
|
handleDeleteModel: (modelname: string) => void;
|
||||||
|
setSystemMessage?: (message: string) => void;
|
||||||
|
setGlobalParams: (value: Record<string, any>) => void;
|
||||||
|
setLoadingStatus: (modeName: string, status: boolean) => void;
|
||||||
|
}
|
||||||
|
const CompareContext = React.createContext<CompareContextProps>(
|
||||||
|
{} as CompareContextProps
|
||||||
|
);
|
||||||
|
|
||||||
|
export default CompareContext;
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import { Roles } from '.';
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
title: 'Grammar correction',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
role: Roles.System,
|
||||||
|
content:
|
||||||
|
'You will be provided with statements, and your task is to convert them to standard English.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: Roles.User,
|
||||||
|
content: 'She no went to the market.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Summarize for a 2nd grader',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
role: Roles.System,
|
||||||
|
content:
|
||||||
|
'Summarize content you are provided with for a second-grade student.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: Roles.User,
|
||||||
|
content:
|
||||||
|
'Jupiter is the fifth planet from the Sun and the largest in the Solar System. It is a gas giant with a mass one-thousandth that of the Sun, but two-and-a-half times that of all the other planets in the Solar System combined. Jupiter is one of the brightest objects visible to the naked eye in the night sky, and has been known to ancient civilizations since before recorded history. It is named after the Roman god Jupiter.[19] When viewed from Earth, Jupiter can be bright enough for its reflected light to cast visible shadows,[20] and is on average the third-brightest natural object in the night sky after the Moon and Venus.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Keywords',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
role: Roles.System,
|
||||||
|
content:
|
||||||
|
'You will be provided with a block of text, and your task is to extract a list of keywords from it.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: Roles.User,
|
||||||
|
content:
|
||||||
|
"Black-on-black ware is a 20th- and 21st-century pottery tradition developed by the Puebloan Native American ceramic artists in Northern New Mexico. Traditional reduction-fired blackware has been made for centuries by pueblo artists. Black-on-black ware of the past century is produced with a smooth surface, with the designs applied through selective burnishing or the application of refractory slip. Another style involves carving or incising designs and selectively polishing the raised areas. For generations several families from Kha'po Owingeh and P'ohwhóge Owingeh pueblos have been making black-on-black ware with the techniques passed down from matriarch potters. Artists from other pueblos have also produced black-on-black ware. Several contemporary artists have created works honoring the pottery of their ancestors."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Spreadsheet creator',
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
role: Roles.User,
|
||||||
|
content:
|
||||||
|
'Create a two-column CSV of top science fiction movies along with the year of release.'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
@@ -10,19 +10,10 @@ interface MessageItemProps {
|
|||||||
uid: number;
|
uid: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useChatCompletion = (
|
const useChatCompletion = () => {
|
||||||
systemMessage: string,
|
|
||||||
parameters: Record<string, any>
|
|
||||||
) => {
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const messageId = useRef<number>(0);
|
const messageId = useRef<number>(0);
|
||||||
const [messageList, setMessageList] = useState<MessageItemProps[]>([
|
const [messageList, setMessageList] = useState<MessageItemProps[]>([]);
|
||||||
{
|
|
||||||
role: 'user',
|
|
||||||
content: '',
|
|
||||||
uid: messageId.current
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
const contentRef = useRef<any>('');
|
const contentRef = useRef<any>('');
|
||||||
const controllerRef = useRef<any>(null);
|
const controllerRef = useRef<any>(null);
|
||||||
|
|
||||||
@@ -53,12 +44,16 @@ const useChatCompletion = (
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitMessage = async () => {
|
const submitMessage = async (pramas: {
|
||||||
|
parameters: Record<string, any>;
|
||||||
|
systemMessage: string;
|
||||||
|
}) => {
|
||||||
|
const { parameters, systemMessage } = pramas;
|
||||||
if (!parameters.model) return;
|
if (!parameters.model) return;
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
setMessageId();
|
setMessageId();
|
||||||
|
console.log('messagelist=========2=', messageList);
|
||||||
controllerRef.current?.abort?.();
|
controllerRef.current?.abort?.();
|
||||||
controllerRef.current = new AbortController();
|
controllerRef.current = new AbortController();
|
||||||
const signal = controllerRef.current.signal;
|
const signal = controllerRef.current.signal;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
.content-item {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
&-role {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
word-break: break-word;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: var(--border-radius-mini);
|
||||||
|
background-color: var(--ant-color-fill-tertiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: calc(100vh - 72px);
|
|
||||||
|
|
||||||
.chat-list {
|
.chat-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
.prompt-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt-item {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
border: 1px solid var(--ant-color-border);
|
||||||
|
border-radius: var(--border-radius-base);
|
||||||
|
min-height: 150px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.data-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.role {
|
||||||
|
display: flex;
|
||||||
|
width: 60px;
|
||||||
|
flex-basis: 60px;
|
||||||
|
font-weight: var(--font-weight-bold);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.prompt {
|
||||||
|
flex: 1;
|
||||||
|
padding: 8px;
|
||||||
|
border-radius: var(--border-radius-mini);
|
||||||
|
background-color: var(--ant-color-fill-tertiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user