[feature](weaapp) add agent

This commit is contained in:
williamhliu
2023-08-20 18:17:00 +08:00
parent c93e60ced7
commit aa218898ff
40 changed files with 1928 additions and 316 deletions

View File

@@ -8,24 +8,26 @@ import type { ForwardRefRenderFunction } from 'react';
import { searchRecommend } from 'supersonic-chat-sdk';
import { SemanticTypeEnum, SEMANTIC_TYPE_MAP } from '../constants';
import styles from './style.less';
import { PLACE_HOLDER } from '../constants';
import { DefaultEntityType, ModelType } from '../type';
import { DefaultEntityType, AgentType, ModelType } from '../type';
import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons';
type Props = {
inputMsg: string;
chatId?: number;
currentModel?: ModelType;
currentAgent?: AgentType;
defaultEntity?: DefaultEntityType;
isCopilotMode?: boolean;
copilotFullscreen?: boolean;
models: ModelType[];
agentList: AgentType[];
collapsed: boolean;
onToggleCollapseBtn: () => void;
onInputMsgChange: (value: string) => void;
onSendMsg: (msg: string, modelId?: number) => void;
onAddConversation: () => void;
onCancelDefaultFilter: () => void;
onSelectAgent: (agent: AgentType) => void;
};
const { OptGroup, Option } = Select;
@@ -45,8 +47,10 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
inputMsg,
chatId,
currentModel,
currentAgent,
defaultEntity,
models,
agentList,
collapsed,
isCopilotMode,
copilotFullscreen,
@@ -55,10 +59,11 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
onSendMsg,
onAddConversation,
onCancelDefaultFilter,
onSelectAgent,
},
ref,
) => {
const [modelOptions, setModelOptions] = useState<ModelType[]>([]);
const [modelOptions, setModelOptions] = useState<(ModelType | AgentType)[]>([]);
const [stepOptions, setStepOptions] = useState<Record<string, any[]>>({});
const [open, setOpen] = useState(false);
const [focused, setFocused] = useState(false);
@@ -121,6 +126,9 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
const model = models.find((item) => msg.includes(`@${item.name}`));
msgValue = model ? msg.replace(`@${model.name}`, '') : msg;
modelId = model?.id;
} else if (msg?.[0] === '/') {
const agent = agentList.find((item) => msg.includes(`/${item.name}`));
msgValue = agent ? msg.replace(`/${agent.name}`, '') : msg;
}
return { msgValue, modelId };
};
@@ -163,9 +171,9 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
const [debounceGetWords] = useState<any>(debounceGetWordsFunc);
useEffect(() => {
if (inputMsg.length === 1 && inputMsg[0] === '@') {
if (inputMsg.length === 1 && (inputMsg[0] === '@' || inputMsg[0] === '/')) {
setOpen(true);
setModelOptions(models);
setModelOptions(inputMsg[0] === '/' ? agentList : models);
setStepOptions({});
return;
} else {
@@ -173,10 +181,10 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
if (modelOptions.length > 0) {
setTimeout(() => {
setModelOptions([]);
}, 500);
}, 50);
}
}
if (!isSelect) {
if (!isSelect && currentAgent?.name !== '问知识') {
debounceGetWords(inputMsg, models, chatId, currentModel);
} else {
isSelect = false;
@@ -237,6 +245,12 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
isSelect = true;
if (modelOptions.length === 0) {
sendMsg(value);
} else {
const agent = agentList.find((item) => value.includes(item.name));
if (agent) {
onSelectAgent(agent);
onInputMsgChange('');
}
}
setOpen(false);
setTimeout(() => {
@@ -249,12 +263,98 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
[styles.defaultCopilotMode]: isCopilotMode && !copilotFullscreen,
});
const restrictNode = currentModel && !isMobile && (
<div className={styles.currentModel}>
<div className={styles.currentModelName}>
<span className={styles.quoteText}>
{!defaultEntity && <>{currentModel.name}</>}
{defaultEntity && (
<>
<span>{`${currentModel.name.slice(0, currentModel.name.length - 1)}`}</span>
<span className={styles.entityName} title={defaultEntity.entityName}>
{defaultEntity.entityName}
</span>
<span></span>
</>
)}
</span>
</div>
<div className={styles.cancelModel} onClick={onCancelDefaultFilter}>
</div>
</div>
);
const modelOptionNodes = modelOptions.map((model) => {
return (
<Option
key={model.id}
value={inputMsg[0] === '/' ? `/${model.name} ` : `@${model.name} `}
className={styles.searchOption}
>
{model.name}
</Option>
);
});
const associateOptionNodes = Object.keys(stepOptions).map((key) => {
return (
<OptGroup key={key} label={key}>
{stepOptions[key].map((option) => {
let optionValue =
Object.keys(stepOptions).length === 1
? option.recommend
: `${option.modelName || ''}${option.recommend}`;
if (inputMsg[0] === '@') {
const model = models.find((item) => inputMsg.includes(item.name));
optionValue = model ? `@${model.name} ${option.recommend}` : optionValue;
} else if (inputMsg[0] === '/') {
const agent = agentList.find((item) => inputMsg.includes(item.name));
optionValue = agent ? `/${agent.name} ${option.recommend}` : optionValue;
}
return (
<Option
key={`${option.recommend}${option.modelName ? `_${option.modelName}` : ''}`}
value={optionValue}
className={styles.searchOption}
>
<div className={styles.optionContent}>
{option.schemaElementType && (
<Tag
className={styles.semanticType}
color={
option.schemaElementType === SemanticTypeEnum.DIMENSION ||
option.schemaElementType === SemanticTypeEnum.MODEL
? 'blue'
: option.schemaElementType === SemanticTypeEnum.VALUE
? 'geekblue'
: 'cyan'
}
>
{SEMANTIC_TYPE_MAP[option.schemaElementType] ||
option.schemaElementType ||
'维度'}
</Tag>
)}
{option.subRecommend}
</div>
</Option>
);
})}
</OptGroup>
);
});
return (
<div className={chatFooterClass}>
<div className={styles.composer}>
<div className={styles.collapseBtn} onClick={onToggleCollapseBtn}>
{collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
</div>
{!isMobile && (
<div className={styles.collapseBtn} onClick={onToggleCollapseBtn}>
{collapsed ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />}
</div>
)}
<Tooltip title="新建对话">
<IconFont
type="icon-icon-add-conversation-line"
@@ -263,36 +363,14 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
/>
</Tooltip>
<div className={styles.composerInputWrapper}>
{currentModel && (
<div className={styles.currentModel}>
<div className={styles.currentModelName}>
<span className={styles.quoteText}>
{currentModel.name}
{defaultEntity && (
<>
<span></span>
<span>{`${currentModel.name.slice(0, currentModel.name.length - 1)}`}</span>
<span className={styles.entityName} title={defaultEntity.entityName}>
{defaultEntity.entityName}
</span>
<span></span>
</>
)}
</span>
</div>
<div className={styles.cancelModel} onClick={onCancelDefaultFilter}>
</div>
</div>
)}
{/* {restrictNode}
{currentAgentNode} */}
<AutoComplete
className={styles.composerInput}
placeholder={
currentModel
? `请输入${currentModel.name}主题的问题,可使用@切换到其他主题`
: PLACE_HOLDER
currentAgent?.name
? `智能助理${currentAgent?.name}将与您对话,可输入“/”切换助理`
: '请输入您的问题'
}
value={inputMsg}
onChange={onInputMsgChange}
@@ -302,10 +380,20 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
ref={inputRef}
id="chatInput"
onKeyDown={(e) => {
if ((e.code === 'Enter' || e.code === 'NumpadEnter') && !isSelect) {
const chatInputEl: any = document.getElementById('chatInput');
sendMsg(chatInputEl.value);
setOpen(false);
if (e.code === 'Enter' || e.code === 'NumpadEnter') {
{
const chatInputEl: any = document.getElementById('chatInput');
if (!isSelect) {
sendMsg(chatInputEl.value);
setOpen(false);
} else {
const agent = agentList.find((item) => chatInputEl.value.includes(item.name));
if (agent) {
onSelectAgent(agent);
onInputMsgChange('');
}
}
}
}
}}
onFocus={() => {
@@ -320,64 +408,7 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
open={open}
getPopupContainer={(triggerNode) => triggerNode.parentNode}
>
{modelOptions.length > 0
? modelOptions.map((model) => {
return (
<Option
key={model.id}
value={`@${model.name} `}
className={styles.searchOption}
>
{model.name}
</Option>
);
})
: Object.keys(stepOptions).map((key) => {
return (
<OptGroup key={key} label={key}>
{stepOptions[key].map((option) => {
let optionValue =
Object.keys(stepOptions).length === 1
? option.recommend
: `${option.modelName || ''}${option.recommend}`;
if (inputMsg[0] === '@') {
const model = models.find((item) => inputMsg.includes(item.name));
optionValue = model ? `@${model.name} ${option.recommend}` : optionValue;
}
return (
<Option
key={`${option.recommend}${
option.modelName ? `_${option.modelName}` : ''
}`}
value={optionValue}
className={styles.searchOption}
>
<div className={styles.optionContent}>
{option.schemaElementType && (
<Tag
className={styles.semanticType}
color={
option.schemaElementType === SemanticTypeEnum.DIMENSION ||
option.schemaElementType === SemanticTypeEnum.MODEL
? 'blue'
: option.schemaElementType === SemanticTypeEnum.VALUE
? 'geekblue'
: 'cyan'
}
>
{SEMANTIC_TYPE_MAP[option.schemaElementType] ||
option.schemaElementType ||
'维度'}
</Tag>
)}
{option.subRecommend}
</div>
</Option>
);
})}
</OptGroup>
);
})}
{modelOptions.length > 0 ? modelOptionNodes : associateOptionNodes}
</AutoComplete>
<div
className={classNames(styles.sendBtn, {

View File

@@ -90,7 +90,12 @@ const Conversation: ForwardRefRenderFunction<any, Props> = (
defaultEntityFilter?.entityName && window.location.pathname.includes('detail')
? defaultEntityFilter.entityName
: defaultModelName;
onAddConversation({ name: conversationName, type: 'CUSTOMIZE' });
onAddConversation({
name: conversationName,
type: 'CUSTOMIZE',
modelId: defaultEntityFilter?.modelId,
entityId: defaultEntityFilter?.entityId,
});
onNewConversationTriggered?.();
}
}, [triggerNewConversation]);

View File

@@ -3,10 +3,13 @@ import { memo, useCallback, useEffect, useState } from 'react';
import { isEqual } from 'lodash';
import { ChatItem } from 'supersonic-chat-sdk';
import type { MsgDataType } from 'supersonic-chat-sdk';
import { MessageItem, MessageTypeEnum } from './type';
import { AgentType, MessageItem, MessageTypeEnum } from './type';
import Plugin from './components/Plugin';
import { updateMessageContainerScroll } from '@/utils/utils';
import styles from './style.less';
import { MODEL_MODEL_ENTITY_ID_FILTER_MAP } from './constants';
import AgentList from './components/AgentList';
import RecommendQuestions from './components/RecommendQuestions';
type Props = {
id: string;
@@ -15,6 +18,7 @@ type Props = {
isMobileMode?: boolean;
conversationCollapsed: boolean;
copilotFullscreen?: boolean;
agentList: AgentType[];
onClickMessageContainer: () => void;
onMsgDataLoaded: (
data: MsgDataType,
@@ -24,6 +28,8 @@ type Props = {
) => void;
onCheckMore: (data: MsgDataType) => void;
onApplyAuth: (model: string) => void;
onSendMsg: (value: string) => void;
onSelectAgent: (agent: AgentType) => void;
};
const MessageContainer: React.FC<Props> = ({
@@ -33,10 +39,12 @@ const MessageContainer: React.FC<Props> = ({
isMobileMode,
conversationCollapsed,
copilotFullscreen,
agentList,
onClickMessageContainer,
onMsgDataLoaded,
onCheckMore,
onApplyAuth,
onSendMsg,
onSelectAgent,
}) => {
const [triggerResize, setTriggerResize] = useState(false);
@@ -97,6 +105,7 @@ const MessageContainer: React.FC<Props> = ({
}
return [
{
...MODEL_MODEL_ENTITY_ID_FILTER_MAP[modelId],
value: entityId,
},
];
@@ -109,6 +118,7 @@ const MessageContainer: React.FC<Props> = ({
const {
id: msgId,
modelId,
agentId,
entityId,
type,
msg,
@@ -125,6 +135,17 @@ const MessageContainer: React.FC<Props> = ({
return (
<div key={msgId} id={`${msgId}`} className={styles.messageItem}>
{type === MessageTypeEnum.TEXT && <Text position="left" data={msg} />}
{type === MessageTypeEnum.RECOMMEND_QUESTIONS && (
<RecommendQuestions onSelectQuestion={onSendMsg} />
)}
{type === MessageTypeEnum.AGENT_LIST && (
<AgentList
currentAgentName={msg!}
data={agentList}
copilotFullscreen={copilotFullscreen}
onSelectAgent={onSelectAgent}
/>
)}
{type === MessageTypeEnum.QUESTION && (
<>
<Text position="right" data={msg} />
@@ -134,6 +155,7 @@ const MessageContainer: React.FC<Props> = ({
msgData={msgData}
conversationId={chatId}
modelId={modelId}
agentId={agentId}
filter={getFilters(modelId, entityId)}
isLastMessage={index === messageList.length - 1}
isMobileMode={isMobileMode}
@@ -150,6 +172,7 @@ const MessageContainer: React.FC<Props> = ({
msg={msgValue || msg || ''}
conversationId={chatId}
modelId={modelId}
agentId={agentId}
filter={getFilters(modelId, entityId)}
isLastMessage={index === messageList.length - 1}
isMobileMode={isMobileMode}
@@ -192,7 +215,8 @@ function areEqual(prevProps: Props, nextProps: Props) {
prevProps.id === nextProps.id &&
isEqual(prevProps.messageList, nextProps.messageList) &&
prevProps.conversationCollapsed === nextProps.conversationCollapsed &&
prevProps.copilotFullscreen === nextProps.copilotFullscreen
prevProps.copilotFullscreen === nextProps.copilotFullscreen &&
prevProps.agentList === nextProps.agentList
) {
return true;
}

View File

@@ -0,0 +1,63 @@
import LeftAvatar from '../CopilotAvatar';
import Message from '../Message';
import styles from './style.less';
import { AgentType } from '../../type';
import classNames from 'classnames';
type Props = {
currentAgentName: string;
data: AgentType[];
copilotFullscreen?: boolean;
onSelectAgent: (agent: AgentType) => void;
};
const AgentList: React.FC<Props> = ({
currentAgentName,
data,
copilotFullscreen,
onSelectAgent,
}) => {
const agentClass = classNames(styles.agent, {
[styles.fullscreen]: copilotFullscreen,
});
return (
<div className={styles.agentList}>
<LeftAvatar />
<Message position="left" bubbleClassName={styles.agentListMsg}>
<div className={styles.title}>
{currentAgentName}
/
</div>
<div className={styles.content}>
{data.map((agent) => (
<div
key={agent.id}
className={agentClass}
onClick={() => {
onSelectAgent(agent);
}}
>
<div className={styles.topBar}>
<div className={styles.agentName}>{agent.name}</div>
<div className={styles.tip}></div>
</div>
<div className={styles.examples}>
{agent.examples?.length > 0 ? (
agent.examples.map((example) => (
<div key={example} className={styles.example}>
{example}
</div>
))
) : (
<div className={styles.example}>{agent.description}</div>
)}
</div>
</div>
))}
</div>
</Message>
</div>
);
};
export default AgentList;

View File

@@ -0,0 +1,63 @@
.agentList {
display: flex;
margin-top: 12px;
.agentListMsg {
padding: 12px 20px 20px !important;
.title {
margin-bottom: 12px;
font-weight: 500;
font-size: 14px;
}
.content {
display: flex;
flex-wrap: wrap;
margin-top: 20px;
column-gap: 14px;
row-gap: 14px;
.agent {
flex: 0 0 calc(50% - 7px);
padding: 10px 14px 20px;
color: var(--text-color);
font-size: 14px;
background-color: #f4f4f4;
border-radius: 17px;
cursor: pointer;
.topBar {
.agentName {
font-weight: 700;
}
.tip {
margin-top: 2px;
font-size: 13px;
font-style: italic;
}
}
.examples {
display: flex;
flex-direction: column;
margin-top: 12px;
font-size: 13px;
row-gap: 8px;
.example {
padding: 4px 12px;
background-color: #ededed;
border-radius: 15px;
}
}
&.fullscreen {
flex: none;
width: 280px;
}
}
}
}
}

View File

@@ -9,8 +9,9 @@ import {
ModelType,
MessageItem,
MessageTypeEnum,
AgentType,
} from './type';
import { getModelList } from './service';
import { getModelList, queryAgentList } from './service';
import { useThrottleFn } from 'ahooks';
import Conversation from './Conversation';
import ChatFooter from './ChatFooter';
@@ -64,6 +65,8 @@ const Chat: React.FC<Props> = ({
const [applyAuthVisible, setApplyAuthVisible] = useState(false);
const [applyAuthModel, setApplyAuthModel] = useState('');
const [initialModelName, setInitialModelName] = useState('');
const [agentList, setAgentList] = useState<AgentType[]>([]);
const [currentAgent, setCurrentAgent] = useState<AgentType>();
const location = useLocation();
const dispatch = useDispatch();
const { modelName } = (location as any).query;
@@ -71,9 +74,19 @@ const Chat: React.FC<Props> = ({
const conversationRef = useRef<any>();
const chatFooterRef = useRef<any>();
const initAgentList = async () => {
const res = await queryAgentList();
const agentListValue = (res.data || []).filter((item) => item.status === 1);
setAgentList(agentListValue);
if (agentListValue.length > 0) {
setCurrentAgent(agentListValue[0]);
}
};
useEffect(() => {
setChatSdkToken(localStorage.getItem(AUTH_TOKEN_KEY) || '');
initModels();
initAgentList();
}, []);
useEffect(() => {
@@ -102,7 +115,13 @@ const Chat: React.FC<Props> = ({
if (initMsg) {
inputFocus();
if (initMsg === 'CUSTOMIZE' && copilotSendMsg) {
onSendMsg(copilotSendMsg, [], modelId, entityId);
onSendMsg(
copilotSendMsg,
[],
modelId,
entityId,
agentList.find((item) => item.name === '做分析'),
);
dispatch({
type: 'globalState/setCopilotSendMsg',
payload: '',
@@ -143,16 +162,9 @@ const Chat: React.FC<Props> = ({
setMessageList([
{
id: uuid(),
type: MessageTypeEnum.TEXT,
msg: defaultModelName
? `您好,请输入关于${
defaultEntityFilter?.entityName
? `${defaultModelName?.slice(0, defaultModelName?.length - 1)}${
defaultEntityFilter?.entityName
}`
: `${defaultModelName}`
}的问题`
: '您好,请问有什么我能帮您吗?',
type: MessageTypeEnum.RECOMMEND_QUESTIONS,
// type: MessageTypeEnum.AGENT_LIST,
// msg: currentAgent?.name || '查信息',
},
]);
};
@@ -161,7 +173,6 @@ const Chat: React.FC<Props> = ({
return list.map((item: HistoryMsgItemType) => ({
id: item.questionId,
type:
item.queryResult?.queryMode === MessageTypeEnum.PLUGIN ||
item.queryResult?.queryMode === MessageTypeEnum.WEB_PAGE
? MessageTypeEnum.PLUGIN
: MessageTypeEnum.QUESTION,
@@ -212,6 +223,10 @@ const Chat: React.FC<Props> = ({
}
};
const changeAgent = (agent?: AgentType) => {
setCurrentAgent(agent);
};
const initModels = async () => {
const res = await getModelList();
const modelList = getLeafList(res.data);
@@ -236,6 +251,7 @@ const Chat: React.FC<Props> = ({
list?: MessageItem[],
modelId?: number,
entityId?: string,
agent?: AgentType,
) => {
const currentMsg = msg || inputMsg;
if (currentMsg.trim() === '') {
@@ -252,13 +268,26 @@ const Chat: React.FC<Props> = ({
modelChanged = currentModel?.id !== toModel?.id;
}
const modelIdValue = modelId || msgModel?.id || currentModel?.id;
const msgAgent = agentList.find((item) => currentMsg.indexOf(item.name) === 1);
const certainAgent = currentMsg[0] === '/' && msgAgent;
const agentIdValue = certainAgent ? msgAgent.id : undefined;
if (agent || certainAgent) {
changeAgent(agent || msgAgent);
}
const msgs = [
...(list || messageList),
{
id: uuid(),
msg: currentMsg,
msgValue: certainModel ? currentMsg.replace(`@${msgModel.name}`, '').trim() : currentMsg,
msgValue: certainModel
? currentMsg.replace(`@${msgModel.name}`, '').trim()
: certainAgent
? currentMsg.replace(`/${certainAgent.name}`, '').trim()
: currentMsg,
modelId: modelIdValue === -1 ? undefined : modelIdValue,
agentId: agent?.id || agentIdValue || currentAgent?.id,
entityId: entityId || (modelChanged ? undefined : defaultEntity?.entityId),
identityMsg: certainModel ? getIdentityMsgText(msgModel) : undefined,
type: MessageTypeEnum.QUESTION,
@@ -398,8 +427,22 @@ const Chat: React.FC<Props> = ({
inputFocus();
};
const onSelectAgent = (agent: AgentType) => {
setCurrentAgent(agent);
setMessageList([
...messageList,
{
id: uuid(),
type: MessageTypeEnum.TEXT,
msg: `您好,智能助理【${agent.name}】将与您对话,可输入“/”切换助理`,
},
]);
updateMessageContainerScroll();
};
const chatClass = classNames(styles.chat, {
[styles.mobile]: isMobileMode,
[styles.mobileMode]: isMobileMode,
[styles.mobile]: isMobile,
[styles.copilotFullscreen]: copilotFullscreen,
[styles.conversationCollapsed]: conversationCollapsed,
});
@@ -431,16 +474,21 @@ const Chat: React.FC<Props> = ({
isMobileMode={isMobileMode}
conversationCollapsed={conversationCollapsed}
copilotFullscreen={copilotFullscreen}
agentList={agentList}
onClickMessageContainer={inputFocus}
onMsgDataLoaded={onMsgDataLoaded}
onCheckMore={onCheckMore}
onApplyAuth={onApplyAuth}
onSendMsg={onSendMsg}
onSelectAgent={onSelectAgent}
/>
<ChatFooter
inputMsg={inputMsg}
chatId={currentConversation?.chatId}
models={models}
agentList={agentList}
currentModel={currentModel}
currentAgent={currentAgent}
defaultEntity={defaultEntity}
collapsed={conversationCollapsed}
isCopilotMode={isCopilotMode}
@@ -461,6 +509,7 @@ const Chat: React.FC<Props> = ({
onCancelCopilotFilter();
}
}}
onSelectAgent={onSelectAgent}
ref={chatFooterRef}
/>
</div>

View File

@@ -1,5 +1,5 @@
import { request } from 'umi';
import { ModelType } from './type';
import { AgentType, ModelType } from './type';
const prefix = '/api';
@@ -66,3 +66,9 @@ export function queryRecommendQuestions() {
method: 'GET',
});
}
export function queryAgentList() {
return request<Result<AgentType[]>>(`${prefix}/chat/agent/getAgentList`, {
method: 'GET',
});
}

View File

@@ -101,12 +101,12 @@
display: flex;
flex-direction: column;
padding: 20px 20px 60px 4px;
row-gap: 10px;
row-gap: 16px;
.messageItem {
display: flex;
flex-direction: column;
row-gap: 10px;
row-gap: 20px;
:global {
.ant-table-small {
@@ -240,9 +240,8 @@
}
}
&.mobile {
&.mobileMode {
height: 100% !important;
.chatSection {
width: 100% !important;
height: 100% !important;
@@ -276,6 +275,10 @@
}
}
}
&.mobile {
height: 100vh !important;
}
}
.conversation {
@@ -444,10 +447,6 @@
color: var(--primary-color);
}
// .messageItem {
// margin-top: 12px;
// }
.messageTime {
display: flex;
align-items: center;

View File

@@ -11,6 +11,7 @@ export enum MessageTypeEnum {
WEB_PAGE = 'WEB_PAGE', // 插件
RECOMMEND_QUESTIONS = 'recommend_questions', // 推荐问题
PARSE_OPTIONS = 'parse_options', // 解析选项
AGENT_LIST = 'agent_list', // 专家列表
}
export type MessageItem = {
@@ -20,6 +21,7 @@ export type MessageItem = {
msgValue?: string;
identityMsg?: string;
modelId?: number;
agentId?: number;
entityId?: string;
msgData?: MsgDataType;
quote?: string;
@@ -47,7 +49,6 @@ export enum MessageModeEnum {
export type ModelType = {
id: number;
parentId: number;
name: string;
bizName: string;
};
@@ -69,6 +70,7 @@ export type DefaultEntityType = {
entityId: string;
entityName: string;
modelName?: string;
modelId?: number;
};
export type SuggestionItemType = {
@@ -82,3 +84,11 @@ export type SuggestionType = {
dimensions: SuggestionItemType[];
metrics: SuggestionItemType[];
};
export type AgentType = {
id: number;
name: string;
description: string;
examples: string[];
status: 0 | 1;
};