feat: add models compare

This commit is contained in:
jialin
2024-09-22 14:55:23 +08:00
parent 2e5f0d9210
commit 4f4f00f0c8
15 changed files with 794 additions and 154 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
import { createFromIconfontCN } from '@ant-design/icons';
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;
@@ -1,5 +1,5 @@
:local(.wrapper-box) {
@borderRadius: 8px;
@borderRadius: var(--border-radius-base);
position: relative;
display: flex;
@@ -5,13 +5,16 @@ import {
ClearOutlined,
ControlOutlined,
PictureOutlined,
SendOutlined
SendOutlined,
SwapOutlined
} from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Button, Input, Select } from 'antd';
import { Button, Divider, Input, Select } from 'antd';
import { useState } from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
import { Roles } from '../config';
import '../style/message-input.less';
import PromptModal from './prompt-modal';
const layoutOptions = [
{
@@ -36,7 +39,7 @@ const layoutOptions = [
label: '4 columns',
icon: 'icon-cols_4',
value: {
span: 6,
span: 12,
count: 4
},
tips: 'four models compare'
@@ -54,31 +57,47 @@ const layoutOptions = [
interface MessageInputProps {
modelList: Global.BaseOption<string>[];
handleSubmit: (value: string) => void;
handleSubmit: (params: { role: string; content: string }) => void;
handleAbortFetch: () => void;
setParamsSettings: (value: Record<string, any>) => 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;
}
const MessageInput: React.FC<MessageInputProps> = ({
handleSubmit,
handleAbortFetch,
setParamsSettings,
setModelSelections,
presetPrompt,
loading,
modelList,
clearAll,
setSpans
}) => {
const { TextArea } = Input;
const intl = useIntl();
const platform = platformCall();
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) => {
setMessage(value);
console.log('input change:', value);
setMessage({
...message,
content: value
});
};
const handleSendMessage = () => {
handleSubmit(message);
handleSubmit({ ...message });
setMessage({
...message,
content: ''
});
};
const onStop = () => {
setDisabled(false);
@@ -88,6 +107,33 @@ const MessageInput: React.FC<MessageInputProps> = ({
console.log('layout change:', 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(
HotKeys.SUBMIT.join(','),
() => {
@@ -99,10 +145,29 @@ const MessageInput: React.FC<MessageInputProps> = ({
<div className="messageInput">
<div className="tool-bar">
<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={<ClearOutlined />} size="middle"></Button>
<Button type="text" icon={<ControlOutlined />} size="middle"></Button>
<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) => (
<Button
key={option.icon}
@@ -123,13 +188,20 @@ const MessageInput: React.FC<MessageInputProps> = ({
maxCount={6}
maxTagCount={0}
maxTagTextLength={15}
onChange={handleUpdateModelSelections}
></Select>
{!loading ? (
<Button type="primary" onClick={handleSendMessage} size="middle">
<Button
style={{ width: 44 }}
type="primary"
onClick={handleSendMessage}
size="middle"
>
<SendOutlined />
</Button>
) : (
<Button
style={{ width: 44 }}
type="primary"
onClick={onStop}
size="middle"
@@ -139,13 +211,18 @@ const MessageInput: React.FC<MessageInputProps> = ({
</div>
</div>
<TextArea
placeholder="Send your message"
placeholder="Type your message here"
autoSize={{ minRows: 3, maxRows: 3 }}
onChange={(e) => handleInputChange(e.target.value)}
value={message}
value={message.content}
size="large"
variant="borderless"
></TextArea>
<PromptModal
open={open}
onCancel={() => setOpen(false)}
onSelect={presetPrompt}
></PromptModal>
</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 React from 'react';
import { Roles } from '../../config';
import '../../style/content-item.less';
const ContentItem: React.FC<{ data: { role: string; content: string } }> = ({
data
@@ -8,7 +12,13 @@ const ContentItem: React.FC<{ data: { role: string; content: string } }> = ({
return (
<div className="content-item">
<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}` })}
</div>
<div className="content-item-content">{data.content}</div>
@@ -1,24 +1,21 @@
import { Col, Row } from 'antd';
import { memo, useEffect, useMemo, useRef, useState } from 'react';
import _ from 'lodash';
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import CompareContext from '../../config/compare-context';
import '../../style/multiple-chat.less';
import MessageInput from '../message-input';
import ModelItem from './model-item';
import ActiveModels from './active-models';
interface MultiCompareProps {
modelList: Global.BaseOption<string>[];
parmasSettings?: Record<string, any>;
spans?: number;
}
const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
const [loadingStatus, setLoadingStatus] = useState<boolean[]>([]);
const [parmasSettings, setParamsSettings] = useState<Record<string, any>>({});
const [systemMessage, setSystemMessage] = useState<string>('');
const [currentMessage, setCurrentMessage] = useState<
{
role: 'user' | 'assistant';
content: string;
}[]
const [loadingStatus, setLoadingStatus] = useState<Record<string, boolean>>(
{}
);
const [modelSelections, setModelSelections] = useState<
Global.BaseOption<string>[]
>([]);
const [globalParams, setGlobalParams] = useState<Record<string, any>>({
seed: null,
@@ -34,88 +31,127 @@ const MultiCompare: React.FC<MultiCompareProps> = ({ modelList }) => {
span: 12,
count: 2
});
const modelRefs = useRef<any[]>([]);
const modelRefs = useRef<any>({});
const boxHeight = 'calc(100vh - 72px)';
const isLoading = useMemo(() => {
return loadingStatus.some((status) => status);
console.log('loadingStatus========2', loadingStatus);
return _.keys(loadingStatus).some(
(modelname: string) => loadingStatus[modelname]
);
}, [loadingStatus]);
const modelSelections = useMemo(() => {
useEffect(() => {
const list = modelList.slice?.(0, spans.count);
return list;
setModelSelections(list);
}, [modelList, spans.count]);
useEffect(() => {
modelRefs.current = modelSelections.map(() => {
return {};
modelRefs.current = {};
modelSelections.forEach((item) => {
modelRefs.current[item.value] = null;
});
}, [modelSelections]);
const handleSubmit = (message: string) => {
let msg: any[] = [];
if (message) {
msg = [
{
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 handleSubmit = (currentMessage: { role: string; content: string }) => {
const modelRefList = _.keys(modelRefs.current);
modelRefList.forEach(async (modelname: any, index: number) => {
const ref = modelRefs.current[modelname];
ref?.submit(currentMessage);
});
};
const handleAbortFetch = () => {
modelRefs.current.forEach((ref) => {
_.keys(modelRefs.current).forEach((modelname: string) => {
const ref = modelRefs.current[modelname];
ref?.abortFetch();
});
};
const setModelRefs = (index: number, ref: any) => {
modelRefs.current[index] = ref;
const setModelRefs = useCallback(
(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 (
<div className="multiple-chat">
<div className="multiple-chat" style={{ height: boxHeight }}>
<div className="chat-list">
<Row gutter={[16, 16]} style={{ height: '100%' }}>
{modelSelections.map((model, index) => (
<Col span={spans.span} key={model.value}>
<ModelItem
ref={(el: any) => setModelRefs(index, el)}
modelList={modelSelections}
globalParams={{
...globalParams,
model: model.value
}}
systemMessage={systemMessage}
setGlobalParams={setGlobalParams}
/>
</Col>
))}
</Row>
<CompareContext.Provider
value={{
spans,
globalParams,
loadingStatus,
setGlobalParams,
setLoadingStatus: handleSetLoadingStatus,
handleDeleteModel: handleDeleteModel
}}
>
<ActiveModels
spans={spans}
modelSelections={modelSelections}
setModelRefs={setModelRefs}
></ActiveModels>
</CompareContext.Provider>
</div>
<div>
<MessageInput
loading={isLoading}
handleSubmit={handleSubmit}
handleAbortFetch={handleAbortFetch}
setParamsSettings={setParamsSettings}
clearAll={handleClearAll}
setSpans={setSpans}
setModelSelections={handleUpdateModelSelections}
presetPrompt={handlePresetPrompt}
modelList={modelList}
/>
</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';
interface MessageContentProps {
loading: boolean;
spans: {
span: number;
count: number;
};
messageList: {
role: string;
uid?: string;
uid?: any;
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 (
<div>
{messageList.map((item, index) => (
<ContentItem key={index} data={item} />
))}
</div>
<>
{messageList.length ? (
<SimpleBar style={{ maxHeight: 'calc(100% - 46px)' }}>
<div className="message-content-list">
{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 { fetchChunkedData, readStreamData } from '@/utils/fetch-chunk-data';
import {
ClearOutlined,
CloseOutlined,
@@ -6,71 +7,200 @@ import {
SettingOutlined
} from '@ant-design/icons';
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, {
forwardRef,
useCallback,
useContext,
useEffect,
useImperativeHandle,
useRef,
useState
} from 'react';
import SimpleBar from 'simplebar-react';
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 ParamsSettings from '../params-settings';
import ReferenceParams from '../reference-params';
import ViewCodeModal from '../view-code-modal';
import MessageContent from './message-content';
interface ModelItemProps {
model?: string;
globalParams: Record<string, any>;
setGlobalParams: (value: Record<string, any>) => void;
model: string;
modelList: Global.BaseOption<string>[];
systemMessage: string;
ref: any;
}
interface MessageItemProps {
role: string;
content: string;
uid: string | number;
}
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 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 [messageList, setMessageList] = useState<
// {
// role: 'user' | 'assistant';
// content: string;
// }[]
// >([]);
const { messageList, submitMessage, abortFetch, setMessageList, loading } =
useChatCompletion(systemMessage, params);
const [loading, setLoading] = useState(false);
const messageId = useRef<number>(0);
const [messageList, setMessageList] = useState<MessageItemProps[]>([]);
const [tokenResult, setTokenResult] = useState<any>(null);
const [show, setShow] = useState(false);
const contentRef = useRef<any>('');
const controllerRef = useRef<any>(null);
const currentMessageRef = useRef<MessageItemProps>({} as MessageItemProps);
useImperativeHandle(ref, () => {
return {
submit: submitMessage,
abortFetch,
setMessageList,
loading
};
});
const setMessageId = () => {
messageId.current = messageId.current + 1;
};
const actions = [
{
label: intl.formatMessage({ id: 'common.button.clear' }),
key: 'clear',
icon: <ClearOutlined />
},
{
label: intl.formatMessage({ id: 'playground.viewcode' }),
key: 'viewcode',
icon: <IconFont type="icon-code" />
const abortFetch = () => {
controllerRef.current?.abort?.();
setLoadingStatus(params.model, false);
};
const joinMessage = (chunk: any) => {
if (!chunk) {
return;
}
];
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) => {
setParams({
...params,
model: value
});
const submitMessage = async (currentParams: {
parameters: Record<string, any>;
currentMessage: { role: string; content: string };
}) => {
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) => {
@@ -104,17 +234,67 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
}
};
const handleDropdownAction = ({ key }: { key: string }) => {
console.log('key:', key);
const handleClearMessage = () => {
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(() => {
console.log('globalParams:', globalParams.model, globalParams);
setParams({
...params,
model: model,
...globalParams
});
}, [globalParams]);
}, [globalParams, model]);
useEffect(() => {
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 (
<div className="model-item">
<div className="header">
@@ -133,9 +325,29 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
value={params.model}
></Select>
</span>
<ReferenceParams usage={tokenResult}></ReferenceParams>
<span className="action">
<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"
>
<Button
@@ -170,14 +382,43 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
size="small"
></Button>
</Popover>
<Button type="text" icon={<CloseOutlined />} size="small"></Button>
<Button
type="text"
icon={<CloseOutlined />}
size="small"
onClick={handleDelete}
></Button>
</span>
</div>
<SimpleBar style={{ height: 'calc(100% - 46px)' }}>
<div className="content">
<MessageContent messageList={messageList} />
</div>
</SimpleBar>
<div>
<Input.TextArea
variant="filled"
placeholder="Type system message here"
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>
);
}
@@ -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;
+57
View File
@@ -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;
}
const useChatCompletion = (
systemMessage: string,
parameters: Record<string, any>
) => {
const useChatCompletion = () => {
const [loading, setLoading] = useState(false);
const messageId = useRef<number>(0);
const [messageList, setMessageList] = useState<MessageItemProps[]>([
{
role: 'user',
content: '',
uid: messageId.current
}
]);
const [messageList, setMessageList] = useState<MessageItemProps[]>([]);
const contentRef = useRef<any>('');
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;
try {
setLoading(true);
setMessageId();
console.log('messagelist=========2=', messageList);
controllerRef.current?.abort?.();
controllerRef.current = new AbortController();
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;
flex-direction: column;
justify-content: space-between;
height: calc(100vh - 72px);
.chat-list {
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);
}
}
}