mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-12 12:37:55 +00:00
(feature)(webapp) add show case and support multiple selection and deletion of filter conditions (#251)
This commit is contained in:
@@ -21,6 +21,7 @@ type Props = {
|
|||||||
onSendMsg: (msg: string, modelId?: number) => void;
|
onSendMsg: (msg: string, modelId?: number) => void;
|
||||||
onAddConversation: (agent?: AgentType) => void;
|
onAddConversation: (agent?: AgentType) => void;
|
||||||
onSelectAgent: (agent: AgentType) => void;
|
onSelectAgent: (agent: AgentType) => void;
|
||||||
|
onOpenShowcase: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const { OptGroup, Option } = Select;
|
const { OptGroup, Option } = Select;
|
||||||
@@ -47,6 +48,7 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
|
|||||||
onSendMsg,
|
onSendMsg,
|
||||||
onAddConversation,
|
onAddConversation,
|
||||||
onSelectAgent,
|
onSelectAgent,
|
||||||
|
onOpenShowcase,
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
@@ -313,14 +315,24 @@ const ChatFooter: ForwardRefRenderFunction<any, Props> = (
|
|||||||
<IconFont type="icon-zhinengzhuli" className={styles.toolIcon} />
|
<IconFont type="icon-zhinengzhuli" className={styles.toolIcon} />
|
||||||
<div>智能助理</div>
|
<div>智能助理</div>
|
||||||
</div>
|
</div>
|
||||||
|
{!isMobile && (
|
||||||
|
<div className={styles.toolItem} onClick={onOpenShowcase}>
|
||||||
|
<IconFont type="icon-showcase" className={styles.toolIcon} />
|
||||||
|
<div>showcase</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.composer}>
|
<div className={styles.composer}>
|
||||||
<div className={styles.composerInputWrapper}>
|
<div className={styles.composerInputWrapper}>
|
||||||
<AutoComplete
|
<AutoComplete
|
||||||
className={styles.composerInput}
|
className={styles.composerInput}
|
||||||
placeholder={`智能助理${
|
placeholder={
|
||||||
|
currentAgent
|
||||||
|
? `智能助理${
|
||||||
isMobile ? `[${currentAgent?.name}]` : `【${currentAgent?.name}】`
|
isMobile ? `[${currentAgent?.name}]` : `【${currentAgent?.name}】`
|
||||||
}将与您对话,输入“/”可切换助理`}
|
}将与您对话,输入“/”可切换助理`
|
||||||
|
: '请输入您的问题'
|
||||||
|
}
|
||||||
value={inputMsg}
|
value={inputMsg}
|
||||||
onChange={(value: string) => {
|
onChange={(value: string) => {
|
||||||
onInputMsgChange(value);
|
onInputMsgChange(value);
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ type Props = {
|
|||||||
data: MsgDataType,
|
data: MsgDataType,
|
||||||
questionId: string | number,
|
questionId: string | number,
|
||||||
question: string,
|
question: string,
|
||||||
valid: boolean
|
valid: boolean,
|
||||||
|
isRefresh?: boolean
|
||||||
) => void;
|
) => void;
|
||||||
onSendMsg: (value: string) => void;
|
onSendMsg: (value: string) => void;
|
||||||
};
|
};
|
||||||
@@ -72,6 +73,7 @@ const MessageContainer: React.FC<Props> = ({
|
|||||||
type,
|
type,
|
||||||
msg,
|
msg,
|
||||||
msgValue,
|
msgValue,
|
||||||
|
score,
|
||||||
identityMsg,
|
identityMsg,
|
||||||
msgData,
|
msgData,
|
||||||
filters,
|
filters,
|
||||||
@@ -93,13 +95,14 @@ const MessageContainer: React.FC<Props> = ({
|
|||||||
conversationId={chatId}
|
conversationId={chatId}
|
||||||
modelId={modelId}
|
modelId={modelId}
|
||||||
agentId={agentId}
|
agentId={agentId}
|
||||||
|
score={score}
|
||||||
filter={filters}
|
filter={filters}
|
||||||
isLastMessage={index === messageList.length - 1}
|
isLastMessage={index === messageList.length - 1}
|
||||||
triggerResize={triggerResize}
|
triggerResize={triggerResize}
|
||||||
isDeveloper={isDeveloper}
|
isDeveloper={isDeveloper}
|
||||||
integrateSystem={integrateSystem}
|
integrateSystem={integrateSystem}
|
||||||
onMsgDataLoaded={(data: MsgDataType, valid: boolean) => {
|
onMsgDataLoaded={(data: MsgDataType, valid: boolean, isRefresh) => {
|
||||||
onMsgDataLoaded(data, msgId, msgValue || msg || '', valid);
|
onMsgDataLoaded(data, msgId, msgValue || msg || '', valid, isRefresh);
|
||||||
}}
|
}}
|
||||||
onUpdateMessageScroll={updateMessageContainerScroll}
|
onUpdateMessageScroll={updateMessageContainerScroll}
|
||||||
onSendMsg={onSendMsg}
|
onSendMsg={onSendMsg}
|
||||||
|
|||||||
@@ -5,14 +5,16 @@ import LeftAvatar from './CopilotAvatar';
|
|||||||
import Message from './Message';
|
import Message from './Message';
|
||||||
import styles from './style.module.less';
|
import styles from './style.module.less';
|
||||||
import { userAvatarUrl } from '../../common/env';
|
import { userAvatarUrl } from '../../common/env';
|
||||||
|
import IconFont from '../../components/IconFont';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
position: 'left' | 'right';
|
position: 'left' | 'right';
|
||||||
data: any;
|
data: any;
|
||||||
quote?: string;
|
quote?: string;
|
||||||
|
anonymousUser?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Text: React.FC<Props> = ({ position, data, quote }) => {
|
const Text: React.FC<Props> = ({ position, data, quote, anonymousUser }) => {
|
||||||
const textWrapperClass = classNames(styles.textWrapper, {
|
const textWrapperClass = classNames(styles.textWrapper, {
|
||||||
[styles.rightTextWrapper]: position === 'right',
|
[styles.rightTextWrapper]: position === 'right',
|
||||||
});
|
});
|
||||||
@@ -25,7 +27,13 @@ const Text: React.FC<Props> = ({ position, data, quote }) => {
|
|||||||
<div className={styles.text}>{data}</div>
|
<div className={styles.text}>{data}</div>
|
||||||
</Message>
|
</Message>
|
||||||
{!isMobile && position === 'right' && rightAvatarUrl && (
|
{!isMobile && position === 'right' && rightAvatarUrl && (
|
||||||
<Avatar shape="circle" size={40} src={rightAvatarUrl} className={styles.rightAvatar} />
|
<Avatar
|
||||||
|
shape="circle"
|
||||||
|
size={40}
|
||||||
|
src={anonymousUser ? undefined : rightAvatarUrl}
|
||||||
|
icon={<IconFont type="icon-geren" />}
|
||||||
|
className={styles.rightAvatar}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import AgentList from './AgentList';
|
|||||||
import MobileAgents from './MobileAgents';
|
import MobileAgents from './MobileAgents';
|
||||||
import { HistoryMsgItemType, MsgDataType, SendMsgParamsType } from '../common/type';
|
import { HistoryMsgItemType, MsgDataType, SendMsgParamsType } from '../common/type';
|
||||||
import { getHistoryMsg } from '../service';
|
import { getHistoryMsg } from '../service';
|
||||||
|
import ShowCase from '../ShowCase';
|
||||||
|
import { Modal } from 'antd';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
token?: string;
|
token?: string;
|
||||||
@@ -30,7 +32,6 @@ type Props = {
|
|||||||
isDeveloper?: boolean;
|
isDeveloper?: boolean;
|
||||||
integrateSystem?: string;
|
integrateSystem?: string;
|
||||||
isCopilot?: boolean;
|
isCopilot?: boolean;
|
||||||
apiUrl?: string;
|
|
||||||
onCurrentAgentChange?: (agent?: AgentType) => void;
|
onCurrentAgentChange?: (agent?: AgentType) => void;
|
||||||
onReportMsgEvent?: (msg: string, valid: boolean) => void;
|
onReportMsgEvent?: (msg: string, valid: boolean) => void;
|
||||||
};
|
};
|
||||||
@@ -45,7 +46,6 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
isDeveloper,
|
isDeveloper,
|
||||||
integrateSystem,
|
integrateSystem,
|
||||||
isCopilot,
|
isCopilot,
|
||||||
apiUrl,
|
|
||||||
onCurrentAgentChange,
|
onCurrentAgentChange,
|
||||||
onReportMsgEvent,
|
onReportMsgEvent,
|
||||||
},
|
},
|
||||||
@@ -64,6 +64,7 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
const [currentAgent, setCurrentAgent] = useState<AgentType>();
|
const [currentAgent, setCurrentAgent] = useState<AgentType>();
|
||||||
const [mobileAgentsVisible, setMobileAgentsVisible] = useState(false);
|
const [mobileAgentsVisible, setMobileAgentsVisible] = useState(false);
|
||||||
const [agentListVisible, setAgentListVisible] = useState(true);
|
const [agentListVisible, setAgentListVisible] = useState(true);
|
||||||
|
const [showCaseVisible, setShowCaseVisible] = useState(false);
|
||||||
|
|
||||||
const conversationRef = useRef<any>();
|
const conversationRef = useRef<any>();
|
||||||
const chatFooterRef = useRef<any>();
|
const chatFooterRef = useRef<any>();
|
||||||
@@ -120,12 +121,6 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
}
|
}
|
||||||
}, [token]);
|
}, [token]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (apiUrl) {
|
|
||||||
localStorage.setItem('SUPERSONIC_CHAT_API_URL', apiUrl);
|
|
||||||
}
|
|
||||||
}, [apiUrl]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (chatVisible) {
|
if (chatVisible) {
|
||||||
inputFocus();
|
inputFocus();
|
||||||
@@ -300,7 +295,8 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
data: MsgDataType,
|
data: MsgDataType,
|
||||||
questionId: string | number,
|
questionId: string | number,
|
||||||
question: string,
|
question: string,
|
||||||
valid: boolean
|
valid: boolean,
|
||||||
|
isRefresh?: boolean
|
||||||
) => {
|
) => {
|
||||||
onReportMsgEvent?.(question, valid);
|
onReportMsgEvent?.(question, valid);
|
||||||
if (!isMobile) {
|
if (!isMobile) {
|
||||||
@@ -315,7 +311,9 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
msg.msgData = data;
|
msg.msgData = data;
|
||||||
setMessageList(msgs);
|
setMessageList(msgs);
|
||||||
}
|
}
|
||||||
|
if (!isRefresh) {
|
||||||
updateMessageContainerScroll(`${questionId}`);
|
updateMessageContainerScroll(`${questionId}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onToggleHistoryVisible = () => {
|
const onToggleHistoryVisible = () => {
|
||||||
@@ -404,6 +402,9 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
setAgentListVisible(!agentListVisible);
|
setAgentListVisible(!agentListVisible);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
onOpenShowcase={() => {
|
||||||
|
setShowCaseVisible(!showCaseVisible);
|
||||||
|
}}
|
||||||
ref={chatFooterRef}
|
ref={chatFooterRef}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -419,6 +420,23 @@ const Chat: ForwardRefRenderFunction<any, Props> = (
|
|||||||
onCloseConversation={onCloseConversation}
|
onCloseConversation={onCloseConversation}
|
||||||
ref={conversationRef}
|
ref={conversationRef}
|
||||||
/>
|
/>
|
||||||
|
{currentAgent && (
|
||||||
|
<Modal
|
||||||
|
title="showcase"
|
||||||
|
width="98%"
|
||||||
|
open={showCaseVisible}
|
||||||
|
centered
|
||||||
|
footer={null}
|
||||||
|
wrapClassName={styles.showCaseModal}
|
||||||
|
onCancel={() => {
|
||||||
|
setShowCaseVisible(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={styles.showCase}>
|
||||||
|
<ShowCase agentId={currentAgent.id} onSendMsg={onSendMsg} />
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<MobileAgents
|
<MobileAgents
|
||||||
open={mobileAgentsVisible}
|
open={mobileAgentsVisible}
|
||||||
|
|||||||
@@ -77,6 +77,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.showCaseModal {
|
||||||
|
:global {
|
||||||
|
.ant-modal-body {
|
||||||
|
padding: 20px 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.showCase {
|
||||||
|
height: calc(100vh - 140px);
|
||||||
|
padding: 0 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
:global {
|
:global {
|
||||||
.ss-chat-recommend-options {
|
.ss-chat-recommend-options {
|
||||||
.ant-table-thead .ant-table-cell {
|
.ant-table-thead .ant-table-cell {
|
||||||
|
|||||||
71
webapp/packages/chat-sdk/src/ShowCase/index.tsx
Normal file
71
webapp/packages/chat-sdk/src/ShowCase/index.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import styles from './style.module.less';
|
||||||
|
import { ShowCaseMapType } from './type';
|
||||||
|
import { queryShowCase } from './service';
|
||||||
|
import Text from '../Chat/components/Text';
|
||||||
|
import ChatItem from '../components/ChatItem';
|
||||||
|
import { HistoryMsgItemType } from '../common/type';
|
||||||
|
import { Spin } from 'antd';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
agentId: number;
|
||||||
|
onSendMsg?: (msg: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ShowCase: React.FC<Props> = ({ agentId, onSendMsg }) => {
|
||||||
|
const [showCaseMap, setShowCaseMap] = useState<ShowCaseMapType>({});
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const updateData = async (pageNo: number) => {
|
||||||
|
if (pageNo === 1) {
|
||||||
|
setLoading(true);
|
||||||
|
}
|
||||||
|
const res = await queryShowCase(agentId, pageNo, 20);
|
||||||
|
if (pageNo === 1) {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
setShowCaseMap(
|
||||||
|
pageNo === 1 ? res.data.showCaseMap : { ...showCaseMap, ...res.data.showCaseMap }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (agentId) {
|
||||||
|
updateData(1);
|
||||||
|
}
|
||||||
|
}, [agentId]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Spin spinning={loading} size="large">
|
||||||
|
<div className={styles.showCase}>
|
||||||
|
{Object.keys(showCaseMap || {}).map(key => {
|
||||||
|
const showCaseItem = showCaseMap?.[key] || [];
|
||||||
|
return (
|
||||||
|
<div key={key} className={styles.showCaseItem}>
|
||||||
|
{showCaseItem
|
||||||
|
.filter((chatItem: HistoryMsgItemType) => !!chatItem.queryResult)
|
||||||
|
.slice(0, 10)
|
||||||
|
.map((chatItem: HistoryMsgItemType) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.showCaseChatItem} key={chatItem.questionId}>
|
||||||
|
<Text position="right" data={chatItem.queryText} anonymousUser />
|
||||||
|
<ChatItem
|
||||||
|
msg={chatItem.queryText}
|
||||||
|
msgData={chatItem.queryResult}
|
||||||
|
conversationId={chatItem.chatId}
|
||||||
|
agentId={agentId}
|
||||||
|
integrateSystem="showcase"
|
||||||
|
onSendMsg={onSendMsg}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ShowCase;
|
||||||
12
webapp/packages/chat-sdk/src/ShowCase/service.ts
Normal file
12
webapp/packages/chat-sdk/src/ShowCase/service.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import axios from '../service/axiosInstance';
|
||||||
|
import { isMobile } from '../utils/utils';
|
||||||
|
import { ShowCaseType } from './type';
|
||||||
|
|
||||||
|
const prefix = isMobile ? '/openapi' : '/api';
|
||||||
|
|
||||||
|
export function queryShowCase(agentId: number, current: number, pageSize: number) {
|
||||||
|
return axios.post<ShowCaseType>(
|
||||||
|
`${prefix}/chat/manage/queryShowCase?agentId=${agentId}`,
|
||||||
|
{ current, pageSize }
|
||||||
|
);
|
||||||
|
}
|
||||||
27
webapp/packages/chat-sdk/src/ShowCase/style.module.less
Normal file
27
webapp/packages/chat-sdk/src/ShowCase/style.module.less
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
.showCase {
|
||||||
|
column-count: 2;
|
||||||
|
column-gap: 20px;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
.showCaseItem {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
max-height: 800px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.14), 0 0 2px rgba(0, 0, 0, 0.12);
|
||||||
|
background: linear-gradient(180deg, rgba(23, 74, 228, 0) 29.44%, rgba(23, 74, 228, 0.06) 100%),
|
||||||
|
linear-gradient(90deg, #f3f3f7 0%, #f3f3f7 20%, #ebf0f9 60%, #f3f3f7 80%, #f3f3f7 100%);
|
||||||
|
|
||||||
|
.showCaseChatItem {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
row-gap: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
webapp/packages/chat-sdk/src/ShowCase/type.ts
Normal file
9
webapp/packages/chat-sdk/src/ShowCase/type.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { HistoryMsgItemType } from "../common/type";
|
||||||
|
|
||||||
|
export type ShowCaseMapType = Record<number, HistoryMsgItemType[]>;
|
||||||
|
|
||||||
|
export type ShowCaseType = {
|
||||||
|
showCaseMap: ShowCaseMapType,
|
||||||
|
current: number,
|
||||||
|
pageSize: number,
|
||||||
|
}
|
||||||
@@ -71,7 +71,7 @@ export type EntityDimensionType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type SqlInfoType = {
|
export type SqlInfoType = {
|
||||||
llmParseSql: string;
|
s2QL: string;
|
||||||
logicSql: string;
|
logicSql: string;
|
||||||
querySql: string;
|
querySql: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ type Props = {
|
|||||||
chatContext: ChatContextType;
|
chatContext: ChatContextType;
|
||||||
agentId?: number;
|
agentId?: number;
|
||||||
entityAlias?: string;
|
entityAlias?: string;
|
||||||
|
integrateSystem?: string;
|
||||||
onFiltersChange: (filters: FilterItemType[]) => void;
|
onFiltersChange: (filters: FilterItemType[]) => void;
|
||||||
onSwitchEntity: (entityId: string) => void;
|
onSwitchEntity: (entityId: string) => void;
|
||||||
};
|
};
|
||||||
@@ -24,6 +25,7 @@ const FilterItem: React.FC<Props> = ({
|
|||||||
chatContext,
|
chatContext,
|
||||||
agentId,
|
agentId,
|
||||||
entityAlias,
|
entityAlias,
|
||||||
|
integrateSystem,
|
||||||
onFiltersChange,
|
onFiltersChange,
|
||||||
onSwitchEntity,
|
onSwitchEntity,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -50,7 +52,11 @@ const FilterItem: React.FC<Props> = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if ((typeof filter.value === 'string' || isArray(filter.value)) && options.length === 0) {
|
if (
|
||||||
|
(typeof filter.value === 'string' || isArray(filter.value)) &&
|
||||||
|
options.length === 0 &&
|
||||||
|
integrateSystem !== 'showcase'
|
||||||
|
) {
|
||||||
initData();
|
initData();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
@@ -148,17 +154,24 @@ const FilterItem: React.FC<Props> = ({
|
|||||||
onSearch={debounceFetcher}
|
onSearch={debounceFetcher}
|
||||||
notFoundContent={loading ? <Spin size="small" /> : null}
|
notFoundContent={loading ? <Spin size="small" /> : null}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
mode={isArray(filter.value) ? 'multiple' : undefined}
|
mode="multiple"
|
||||||
showSearch
|
showSearch
|
||||||
|
allowClear
|
||||||
/>
|
/>
|
||||||
) : entityAlias &&
|
) : entityAlias &&
|
||||||
['歌曲', '艺人'].includes(entityAlias) &&
|
['歌曲', '艺人'].includes(entityAlias) &&
|
||||||
filter.bizName?.includes('_id') ? (
|
filter.bizName?.includes('_id') ? (
|
||||||
|
<>
|
||||||
<SwicthEntity
|
<SwicthEntity
|
||||||
entityName={filter.value}
|
entityName={filter.value}
|
||||||
chatContext={chatContext}
|
chatContext={chatContext}
|
||||||
onSwitchEntity={onSwitchEntity}
|
onSwitchEntity={onSwitchEntity}
|
||||||
/>
|
/>
|
||||||
|
<span className={`${prefixCls}-switch-entity-tip`}>
|
||||||
|
(如未匹配到相关{entityAlias},可点击{entityAlias === '艺人' ? '歌手' : entityAlias}
|
||||||
|
ID切换)
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<span className={`${prefixCls}-filter-value`}>{filter.value}</span>
|
<span className={`${prefixCls}-filter-value`}>{filter.value}</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ type Props = {
|
|||||||
dimensionFilters: FilterItemType[];
|
dimensionFilters: FilterItemType[];
|
||||||
dateInfo: DateInfoType;
|
dateInfo: DateInfoType;
|
||||||
entityInfo: EntityInfoType;
|
entityInfo: EntityInfoType;
|
||||||
|
integrateSystem?: string;
|
||||||
onSelectParseInfo: (parseInfo: ChatContextType) => void;
|
onSelectParseInfo: (parseInfo: ChatContextType) => void;
|
||||||
onSwitchEntity: (entityId: string) => void;
|
onSwitchEntity: (entityId: string) => void;
|
||||||
onFiltersChange: (filters: FilterItemType[]) => void;
|
onFiltersChange: (filters: FilterItemType[]) => void;
|
||||||
@@ -35,6 +36,7 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
dimensionFilters,
|
dimensionFilters,
|
||||||
dateInfo,
|
dateInfo,
|
||||||
entityInfo,
|
entityInfo,
|
||||||
|
integrateSystem,
|
||||||
onSelectParseInfo,
|
onSelectParseInfo,
|
||||||
onSwitchEntity,
|
onSwitchEntity,
|
||||||
onFiltersChange,
|
onFiltersChange,
|
||||||
@@ -115,14 +117,14 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${prefixCls}-tip-content`}>
|
<div className={`${prefixCls}-tip-content`}>
|
||||||
{!!agentType && queryMode !== 'DSL' ? (
|
{!!agentType && queryMode !== 'LLM_S2QL' ? (
|
||||||
<div className={`${prefixCls}-tip-item`}>
|
<div className={`${prefixCls}-tip-item`}>
|
||||||
将由{agentType === 'plugin' ? '插件' : '内置'}工具
|
将由{agentType === 'plugin' ? '插件' : '内置'}工具
|
||||||
<span className={itemValueClass}>{agentName}</span>来解答
|
<span className={itemValueClass}>{agentName}</span>来解答
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{(queryMode?.includes('ENTITY') || queryMode === 'DSL') &&
|
{(queryMode?.includes('ENTITY') || queryMode === 'LLM_S2QL') &&
|
||||||
typeof entityId === 'string' &&
|
typeof entityId === 'string' &&
|
||||||
!!entityAlias &&
|
!!entityAlias &&
|
||||||
!!entityName ? (
|
!!entityName ? (
|
||||||
@@ -144,12 +146,14 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
<div className={itemValueClass}>{metric.name}</div>
|
<div className={itemValueClass}>{metric.name}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{['METRIC_GROUPBY', 'METRIC_ORDERBY', 'ENTITY_DETAIL', 'DSL'].includes(queryMode!) &&
|
{['METRIC_GROUPBY', 'METRIC_ORDERBY', 'ENTITY_DETAIL', 'LLM_S2QL'].includes(
|
||||||
|
queryMode!
|
||||||
|
) &&
|
||||||
fields &&
|
fields &&
|
||||||
fields.length > 0 && (
|
fields.length > 0 && (
|
||||||
<div className={`${prefixCls}-tip-item`}>
|
<div className={`${prefixCls}-tip-item`}>
|
||||||
<div className={`${prefixCls}-tip-item-name`}>
|
<div className={`${prefixCls}-tip-item-name`}>
|
||||||
{queryMode === 'DSL'
|
{queryMode === 'LLM_S2QL'
|
||||||
? nativeQuery
|
? nativeQuery
|
||||||
? '查询字段'
|
? '查询字段'
|
||||||
: '下钻维度'
|
: '下钻维度'
|
||||||
@@ -178,7 +182,9 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
<div className={itemValueClass}>{dimension.value}</div>
|
<div className={itemValueClass}>{dimension.value}</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{queryMode === 'METRIC_ORDERBY' && aggType && aggType !== 'NONE' && (
|
{(queryMode === 'METRIC_ORDERBY' || queryMode === 'METRIC_MODEL') &&
|
||||||
|
aggType &&
|
||||||
|
aggType !== 'NONE' && (
|
||||||
<div className={`${prefixCls}-tip-item`}>
|
<div className={`${prefixCls}-tip-item`}>
|
||||||
<div className={`${prefixCls}-tip-item-name`}>聚合方式:</div>
|
<div className={`${prefixCls}-tip-item-name`}>聚合方式:</div>
|
||||||
<div className={itemValueClass}>{AGG_TYPE_MAP[aggType]}</div>
|
<div className={itemValueClass}>{AGG_TYPE_MAP[aggType]}</div>
|
||||||
@@ -218,6 +224,7 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
chatContext={currentParseInfo!}
|
chatContext={currentParseInfo!}
|
||||||
entityAlias={entityAlias}
|
entityAlias={entityAlias}
|
||||||
agentId={agentId}
|
agentId={agentId}
|
||||||
|
integrateSystem={integrateSystem}
|
||||||
onFiltersChange={onFiltersChange}
|
onFiltersChange={onFiltersChange}
|
||||||
onSwitchEntity={onSwitchEntity}
|
onSwitchEntity={onSwitchEntity}
|
||||||
key={filter.name}
|
key={filter.name}
|
||||||
@@ -240,11 +247,6 @@ const ParseTip: React.FC<Props> = ({
|
|||||||
<div className={`${prefixCls}-tip`}>
|
<div className={`${prefixCls}-tip`}>
|
||||||
{getTipNode()}
|
{getTipNode()}
|
||||||
{getFiltersNode()}
|
{getFiltersNode()}
|
||||||
{(!type || queryMode === 'DSL') && entityAlias && entityAlias !== '厂牌' && entityName && (
|
|
||||||
<div className={`${prefixCls}-switch-entity-tip`}>
|
|
||||||
(如未匹配到相关{entityAlias},可点击{entityAlias === '艺人' ? '歌手' : entityAlias}ID切换)
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
|||||||
setSqlType('');
|
setSqlType('');
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!sqlInfo.llmParseSql && !sqlInfo.logicSql && !sqlInfo.querySql) {
|
if (!sqlInfo.s2QL && !sqlInfo.logicSql && !sqlInfo.querySql) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,13 +44,13 @@ const SqlItem: React.FC<Props> = ({ integrateSystem, sqlInfo }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className={`${tipPrefixCls}-content-options`}>
|
<div className={`${tipPrefixCls}-content-options`}>
|
||||||
{sqlInfo.llmParseSql && (
|
{sqlInfo.s2QL && (
|
||||||
<div
|
<div
|
||||||
className={`${tipPrefixCls}-content-option ${
|
className={`${tipPrefixCls}-content-option ${
|
||||||
sqlType === 'llmParseSql' ? `${tipPrefixCls}-content-option-active` : ''
|
sqlType === 's2QL' ? `${tipPrefixCls}-content-option-active` : ''
|
||||||
}`}
|
}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSqlType(sqlType === 'llmParseSql' ? '' : 'llmParseSql');
|
setSqlType(sqlType === 's2QL' ? '' : 's2QL');
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
LLM解析SQL
|
LLM解析SQL
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ type Props = {
|
|||||||
conversationId?: number;
|
conversationId?: number;
|
||||||
modelId?: number;
|
modelId?: number;
|
||||||
agentId?: number;
|
agentId?: number;
|
||||||
|
score?: number;
|
||||||
filter?: any[];
|
filter?: any[];
|
||||||
isLastMessage?: boolean;
|
isLastMessage?: boolean;
|
||||||
msgData?: MsgDataType;
|
msgData?: MsgDataType;
|
||||||
@@ -33,7 +34,7 @@ type Props = {
|
|||||||
integrateSystem?: string;
|
integrateSystem?: string;
|
||||||
executeItemNode?: React.ReactNode;
|
executeItemNode?: React.ReactNode;
|
||||||
renderCustomExecuteNode?: boolean;
|
renderCustomExecuteNode?: boolean;
|
||||||
onMsgDataLoaded?: (data: MsgDataType, valid: boolean) => void;
|
onMsgDataLoaded?: (data: MsgDataType, valid: boolean, isRefresh?: boolean) => void;
|
||||||
onUpdateMessageScroll?: () => void;
|
onUpdateMessageScroll?: () => void;
|
||||||
onSendMsg?: (msg: string) => void;
|
onSendMsg?: (msg: string) => void;
|
||||||
};
|
};
|
||||||
@@ -43,6 +44,7 @@ const ChatItem: React.FC<Props> = ({
|
|||||||
conversationId,
|
conversationId,
|
||||||
modelId,
|
modelId,
|
||||||
agentId,
|
agentId,
|
||||||
|
score,
|
||||||
filter,
|
filter,
|
||||||
isLastMessage,
|
isLastMessage,
|
||||||
triggerResize,
|
triggerResize,
|
||||||
@@ -68,8 +70,6 @@ const ChatItem: React.FC<Props> = ({
|
|||||||
const [dateInfo, setDateInfo] = useState<DateInfoType>({} as DateInfoType);
|
const [dateInfo, setDateInfo] = useState<DateInfoType>({} as DateInfoType);
|
||||||
const [entityInfo, setEntityInfo] = useState<EntityInfoType>({} as EntityInfoType);
|
const [entityInfo, setEntityInfo] = useState<EntityInfoType>({} as EntityInfoType);
|
||||||
|
|
||||||
// const [chartIndex, setChartIndex] = useState(0);
|
|
||||||
|
|
||||||
const prefixCls = `${PREFIX_CLS}-item`;
|
const prefixCls = `${PREFIX_CLS}-item`;
|
||||||
|
|
||||||
const updateData = (res: Result<MsgDataType>) => {
|
const updateData = (res: Result<MsgDataType>) => {
|
||||||
@@ -208,9 +208,7 @@ const ChatItem: React.FC<Props> = ({
|
|||||||
const resChatContext = res.data?.chatContext;
|
const resChatContext = res.data?.chatContext;
|
||||||
const contextValue = { ...(resChatContext || chatContextValue), queryId };
|
const contextValue = { ...(resChatContext || chatContextValue), queryId };
|
||||||
const dataValue = { ...res.data, chatContext: contextValue };
|
const dataValue = { ...res.data, chatContext: contextValue };
|
||||||
if (onMsgDataLoaded) {
|
onMsgDataLoaded?.(dataValue, true, true);
|
||||||
onMsgDataLoaded(dataValue, true);
|
|
||||||
}
|
|
||||||
setData(dataValue);
|
setData(dataValue);
|
||||||
setParseInfo(contextValue);
|
setParseInfo(contextValue);
|
||||||
}
|
}
|
||||||
@@ -230,7 +228,6 @@ const ChatItem: React.FC<Props> = ({
|
|||||||
} else {
|
} else {
|
||||||
getEntityInfo(parseInfoValue);
|
getEntityInfo(parseInfoValue);
|
||||||
}
|
}
|
||||||
onUpdateMessageScroll?.();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSelectQuestion = (question: SimilarQuestionType) => {
|
const onSelectQuestion = (question: SimilarQuestionType) => {
|
||||||
@@ -261,6 +258,7 @@ const ChatItem: React.FC<Props> = ({
|
|||||||
dimensionFilters={dimensionFilters}
|
dimensionFilters={dimensionFilters}
|
||||||
dateInfo={dateInfo}
|
dateInfo={dateInfo}
|
||||||
entityInfo={entityInfo}
|
entityInfo={entityInfo}
|
||||||
|
integrateSystem={integrateSystem}
|
||||||
onSelectParseInfo={onSelectParseInfo}
|
onSelectParseInfo={onSelectParseInfo}
|
||||||
onSwitchEntity={onSwitchEntity}
|
onSwitchEntity={onSwitchEntity}
|
||||||
onFiltersChange={onFiltersChange}
|
onFiltersChange={onFiltersChange}
|
||||||
@@ -294,11 +292,11 @@ const ChatItem: React.FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!isMetricCard && data && (
|
{integrateSystem !== 'showcase' && (
|
||||||
<Tools
|
<Tools
|
||||||
queryId={parseInfo?.queryId || 0}
|
queryId={parseInfo?.queryId || 0}
|
||||||
scoreValue={undefined}
|
scoreValue={score}
|
||||||
isLastMessage={isLastMessage}
|
// isLastMessage={isLastMessage}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -164,15 +164,6 @@
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-switch-entity-tip {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
column-gap: 6px;
|
|
||||||
color: var(--text-color-fourth);
|
|
||||||
font-size: 13px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-switch-entity {
|
&-switch-entity {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
@@ -372,6 +363,16 @@
|
|||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-switch-entity-tip {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
column-gap: 6px;
|
||||||
|
margin-left: 4px;
|
||||||
|
color: var(--text-color-fourth);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
.ant-select-selector, .ant-input-number-input {
|
.ant-select-selector, .ant-input-number-input {
|
||||||
background-color: #f5f8fb !important;
|
background-color: #f5f8fb !important;
|
||||||
border-color: #ececec !important;
|
border-color: #ececec !important;
|
||||||
|
|||||||
@@ -28,11 +28,7 @@ const MetricCard: React.FC<Props> = ({ data, loading, onApplyAuth }) => {
|
|||||||
const prefixCls = `${PREFIX_CLS}-metric-card`;
|
const prefixCls = `${PREFIX_CLS}-metric-card`;
|
||||||
|
|
||||||
const matricCardClass = classNames(prefixCls, {
|
const matricCardClass = classNames(prefixCls, {
|
||||||
[`${PREFIX_CLS}-metric-card-dsl`]: queryMode === 'DSL',
|
[`${PREFIX_CLS}-metric-card-dsl`]: queryMode === 'LLM_S2QL',
|
||||||
});
|
|
||||||
|
|
||||||
const indicatorClass = classNames(`${prefixCls}-indicator`, {
|
|
||||||
[`${prefixCls}-indicator-period-compare`]: metricInfos?.length > 0,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isNumber, setIsNumber] = useState(false);
|
const [isNumber, setIsNumber] = useState(false);
|
||||||
@@ -50,7 +46,7 @@ const MetricCard: React.FC<Props> = ({ data, loading, onApplyAuth }) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Spin spinning={loading}>
|
<Spin spinning={loading}>
|
||||||
<div className={indicatorClass}>
|
<div className={`${prefixCls}-indicator`}>
|
||||||
{indicatorColumn && !indicatorColumn?.authorized ? (
|
{indicatorColumn && !indicatorColumn?.authorized ? (
|
||||||
<ApplyAuth model={entityInfo?.modelInfo.name || ''} onApplyAuth={onApplyAuth} />
|
<ApplyAuth model={entityInfo?.modelInfo.name || ''} onApplyAuth={onApplyAuth} />
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -55,12 +55,8 @@
|
|||||||
&-indicator {
|
&-indicator {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
&-indicator-period-compare {
|
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-date-range {
|
&-date-range {
|
||||||
@@ -90,6 +86,7 @@
|
|||||||
column-gap: 40px;
|
column-gap: 40px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-period-compare-item {
|
&-period-compare-item {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import moment from 'moment';
|
|||||||
import { ColumnType } from '../../../common/type';
|
import { ColumnType } from '../../../common/type';
|
||||||
import NoPermissionChart from '../NoPermissionChart';
|
import NoPermissionChart from '../NoPermissionChart';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { isArray } from 'lodash';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
model?: string;
|
model?: string;
|
||||||
@@ -83,7 +84,9 @@ const MetricTrendChart: React.FC<Props> = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const xData = groupData[sortedGroupKeys[0]]?.map((item: any) => {
|
const xData = groupData[sortedGroupKeys[0]]?.map((item: any) => {
|
||||||
const date = `${item[dateColumnName]}`;
|
const date = isArray(item[dateColumnName])
|
||||||
|
? item[dateColumnName].join('-')
|
||||||
|
: `${item[dateColumnName]}`;
|
||||||
return date.length === 10 ? moment(date).format('MM-DD') : date;
|
return date.length === 10 ? moment(date).format('MM-DD') : date;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
import { CHART_SECONDARY_COLOR, CLS_PREFIX, THEME_COLOR_LIST } from '../../../common/constants';
|
||||||
|
import { getFormattedValue } from '../../../utils/utils';
|
||||||
|
import type { ECharts } from 'echarts';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { ColumnType } from '../../../common/type';
|
||||||
|
import { isArray } from 'lodash';
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
dateColumnName: string;
|
||||||
|
metricFields: ColumnType[];
|
||||||
|
resultList: any[];
|
||||||
|
triggerResize?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const MultiMetricsTrendChart: React.FC<Props> = ({
|
||||||
|
dateColumnName,
|
||||||
|
metricFields,
|
||||||
|
resultList,
|
||||||
|
triggerResize,
|
||||||
|
}) => {
|
||||||
|
const chartRef = useRef<any>();
|
||||||
|
const [instance, setInstance] = useState<ECharts>();
|
||||||
|
|
||||||
|
const renderChart = () => {
|
||||||
|
let instanceObj: any;
|
||||||
|
if (!instance) {
|
||||||
|
instanceObj = echarts.init(chartRef.current);
|
||||||
|
setInstance(instanceObj);
|
||||||
|
} else {
|
||||||
|
instanceObj = instance;
|
||||||
|
instanceObj.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const xData = resultList?.map((item: any) => {
|
||||||
|
const date = isArray(item[dateColumnName])
|
||||||
|
? item[dateColumnName].join('-')
|
||||||
|
: `${item[dateColumnName]}`;
|
||||||
|
return date.length === 10 ? moment(date).format('MM-DD') : date;
|
||||||
|
});
|
||||||
|
|
||||||
|
instanceObj.setOption({
|
||||||
|
legend: {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
icon: 'rect',
|
||||||
|
itemWidth: 15,
|
||||||
|
itemHeight: 5,
|
||||||
|
type: 'scroll',
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: CHART_SECONDARY_COLOR,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: CHART_SECONDARY_COLOR,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
showMaxLabel: true,
|
||||||
|
color: '#999',
|
||||||
|
},
|
||||||
|
data: xData,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
opacity: 0.3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
formatter: function (value: any) {
|
||||||
|
return value === 0 ? 0 : getFormattedValue(value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
formatter: function (params: any[]) {
|
||||||
|
const param = params[0];
|
||||||
|
const valueLabels = params
|
||||||
|
.sort((a, b) => b.value - a.value)
|
||||||
|
.map(
|
||||||
|
(item: any) =>
|
||||||
|
`<div style="margin-top: 3px;">${
|
||||||
|
item.marker
|
||||||
|
} <span style="display: inline-block; width: 70px; margin-right: 12px;">${
|
||||||
|
item.seriesName
|
||||||
|
}</span><span style="display: inline-block; width: 90px; text-align: right; font-weight: 500;">${
|
||||||
|
item.value === '' ? '-' : getFormattedValue(item.value)
|
||||||
|
}</span></div>`
|
||||||
|
)
|
||||||
|
.join('');
|
||||||
|
return `${param.name}<br />${valueLabels}`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '1%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
top: 45,
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
series: metricFields.map((metricField, index) => {
|
||||||
|
return {
|
||||||
|
type: 'line',
|
||||||
|
name: metricField.name,
|
||||||
|
symbol: 'circle',
|
||||||
|
showSymbol: resultList.length === 1,
|
||||||
|
smooth: true,
|
||||||
|
data: resultList.map((item: any) => {
|
||||||
|
const value = item[metricField.nameEn];
|
||||||
|
return (metricField.dataFormatType === 'percent' ||
|
||||||
|
metricField.dataFormatType === 'decimal') &&
|
||||||
|
metricField.dataFormat?.needMultiply100
|
||||||
|
? value * 100
|
||||||
|
: value;
|
||||||
|
}),
|
||||||
|
color: THEME_COLOR_LIST[index],
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
instanceObj.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
renderChart();
|
||||||
|
}, [resultList]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (triggerResize && instance) {
|
||||||
|
instance.resize();
|
||||||
|
}
|
||||||
|
}, [triggerResize]);
|
||||||
|
|
||||||
|
const prefixCls = `${CLS_PREFIX}-metric-trend`;
|
||||||
|
|
||||||
|
return <div className={`${prefixCls}-flow-trend-chart`} ref={chartRef} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MultiMetricsTrendChart;
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
import { CLS_PREFIX } from '../../../common/constants';
|
import { CLS_PREFIX } from '../../../common/constants';
|
||||||
import { FieldType, MsgDataType } from '../../../common/type';
|
import { DrillDownDimensionType, FieldType, MsgDataType } from '../../../common/type';
|
||||||
import { isMobile } from '../../../utils/utils';
|
import { isMobile } from '../../../utils/utils';
|
||||||
import MetricTrendChart from './MetricTrendChart';
|
import MetricTrendChart from './MetricTrendChart';
|
||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
import Table from '../Table';
|
import Table from '../Table';
|
||||||
import MetricInfo from './MetricInfo';
|
import MetricInfo from './MetricInfo';
|
||||||
import DateOptions from '../DateOptions';
|
import DateOptions from '../DateOptions';
|
||||||
|
import MultiMetricsTrendChart from './MultiMetricsTrendChart';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
data: MsgDataType;
|
data: MsgDataType;
|
||||||
@@ -13,6 +14,7 @@ type Props = {
|
|||||||
triggerResize?: boolean;
|
triggerResize?: boolean;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
activeMetricField?: FieldType;
|
activeMetricField?: FieldType;
|
||||||
|
drillDownDimension?: DrillDownDimensionType;
|
||||||
currentDateOption?: number;
|
currentDateOption?: number;
|
||||||
onApplyAuth?: (model: string) => void;
|
onApplyAuth?: (model: string) => void;
|
||||||
onSelectDateOption: (value: number) => void;
|
onSelectDateOption: (value: number) => void;
|
||||||
@@ -24,6 +26,7 @@ const MetricTrend: React.FC<Props> = ({
|
|||||||
triggerResize,
|
triggerResize,
|
||||||
loading,
|
loading,
|
||||||
activeMetricField,
|
activeMetricField,
|
||||||
|
drillDownDimension,
|
||||||
currentDateOption,
|
currentDateOption,
|
||||||
onApplyAuth,
|
onApplyAuth,
|
||||||
onSelectDateOption,
|
onSelectDateOption,
|
||||||
@@ -36,6 +39,7 @@ const MetricTrend: React.FC<Props> = ({
|
|||||||
const dateColumnName = dateField?.nameEn || '';
|
const dateColumnName = dateField?.nameEn || '';
|
||||||
const categoryColumnName =
|
const categoryColumnName =
|
||||||
queryColumns?.find((column: any) => column.showType === 'CATEGORY')?.nameEn || '';
|
queryColumns?.find((column: any) => column.showType === 'CATEGORY')?.nameEn || '';
|
||||||
|
const metricFields = queryColumns?.filter((column: any) => column.showType === 'NUMBER');
|
||||||
|
|
||||||
const currentMetricField = queryColumns?.find((column: any) => column.showType === 'NUMBER');
|
const currentMetricField = queryColumns?.find((column: any) => column.showType === 'NUMBER');
|
||||||
|
|
||||||
@@ -48,6 +52,7 @@ const MetricTrend: React.FC<Props> = ({
|
|||||||
return (
|
return (
|
||||||
<div className={prefixCls}>
|
<div className={prefixCls}>
|
||||||
<div className={`${prefixCls}-charts`}>
|
<div className={`${prefixCls}-charts`}>
|
||||||
|
{metricFields?.length === 1 && (
|
||||||
<div className={`${prefixCls}-top-bar`}>
|
<div className={`${prefixCls}-top-bar`}>
|
||||||
<div
|
<div
|
||||||
className={`${prefixCls}-metric-fields ${prefixCls}-metric-field-single`}
|
className={`${prefixCls}-metric-fields ${prefixCls}-metric-field-single`}
|
||||||
@@ -56,9 +61,12 @@ const MetricTrend: React.FC<Props> = ({
|
|||||||
{activeMetricField?.name}
|
{activeMetricField?.name}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
<Spin spinning={loading}>
|
<Spin spinning={loading}>
|
||||||
<div className={`${prefixCls}-content`}>
|
<div className={`${prefixCls}-content`}>
|
||||||
{!isMobile && aggregateInfo?.metricInfos?.length > 0 && (
|
{!isMobile &&
|
||||||
|
aggregateInfo?.metricInfos?.length > 0 &&
|
||||||
|
drillDownDimension === undefined && (
|
||||||
<MetricInfo aggregateInfo={aggregateInfo} currentMetricField={currentMetricField} />
|
<MetricInfo aggregateInfo={aggregateInfo} currentMetricField={currentMetricField} />
|
||||||
)}
|
)}
|
||||||
<DateOptions
|
<DateOptions
|
||||||
@@ -68,6 +76,13 @@ const MetricTrend: React.FC<Props> = ({
|
|||||||
/>
|
/>
|
||||||
{queryResults?.length === 1 || chartIndex % 2 === 1 ? (
|
{queryResults?.length === 1 || chartIndex % 2 === 1 ? (
|
||||||
<Table data={{ ...data, queryResults }} onApplyAuth={onApplyAuth} />
|
<Table data={{ ...data, queryResults }} onApplyAuth={onApplyAuth} />
|
||||||
|
) : metricFields.length > 1 ? (
|
||||||
|
<MultiMetricsTrendChart
|
||||||
|
dateColumnName={dateColumnName}
|
||||||
|
metricFields={metricFields}
|
||||||
|
resultList={queryResults}
|
||||||
|
triggerResize={triggerResize}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<MetricTrendChart
|
<MetricTrendChart
|
||||||
model={entityInfo?.modelInfo.name}
|
model={entityInfo?.modelInfo.name}
|
||||||
|
|||||||
@@ -59,11 +59,9 @@ const ChatMsg: React.FC<Props> = ({ queryId, data, chartIndex, triggerResize })
|
|||||||
const metricFields = columns.filter(item => item.showType === 'NUMBER');
|
const metricFields = columns.filter(item => item.showType === 'NUMBER');
|
||||||
|
|
||||||
const isDslMetricCard =
|
const isDslMetricCard =
|
||||||
queryMode === 'DSL' && singleData && metricFields.length === 1 && columns.length === 1;
|
queryMode === 'LLM_S2QL' && singleData && metricFields.length === 1 && columns.length === 1;
|
||||||
|
|
||||||
const isMetricCard =
|
const isMetricCard = (queryMode.includes('METRIC') || isDslMetricCard) && singleData;
|
||||||
(queryMode.includes('METRIC') || isDslMetricCard) &&
|
|
||||||
(singleData || chatContext?.dateInfo?.startDate === chatContext?.dateInfo?.endDate);
|
|
||||||
|
|
||||||
const isText =
|
const isText =
|
||||||
columns.length === 1 &&
|
columns.length === 1 &&
|
||||||
@@ -95,8 +93,11 @@ const ChatMsg: React.FC<Props> = ({ queryId, data, chartIndex, triggerResize })
|
|||||||
if (isTable) {
|
if (isTable) {
|
||||||
return <Table data={{ ...data, queryColumns: columns, queryResults: dataSource }} />;
|
return <Table data={{ ...data, queryColumns: columns, queryResults: dataSource }} />;
|
||||||
}
|
}
|
||||||
if (dateField && metricFields.length > 0) {
|
if (
|
||||||
if (!dataSource.every(item => item[dateField.nameEn] === dataSource[0][dateField.nameEn])) {
|
dateField &&
|
||||||
|
metricFields.length > 0 &&
|
||||||
|
!dataSource.every(item => item[dateField.nameEn] === dataSource[0][dateField.nameEn])
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<MetricTrend
|
<MetricTrend
|
||||||
data={{
|
data={{
|
||||||
@@ -108,12 +109,12 @@ const ChatMsg: React.FC<Props> = ({ queryId, data, chartIndex, triggerResize })
|
|||||||
chartIndex={chartIndex}
|
chartIndex={chartIndex}
|
||||||
triggerResize={triggerResize}
|
triggerResize={triggerResize}
|
||||||
activeMetricField={activeMetricField}
|
activeMetricField={activeMetricField}
|
||||||
|
drillDownDimension={drillDownDimension}
|
||||||
currentDateOption={currentDateOption}
|
currentDateOption={currentDateOption}
|
||||||
onSelectDateOption={selectDateOption}
|
onSelectDateOption={selectDateOption}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (categoryField?.length > 0 && metricFields?.length > 0) {
|
if (categoryField?.length > 0 && metricFields?.length > 0) {
|
||||||
return (
|
return (
|
||||||
<Bar
|
<Bar
|
||||||
@@ -209,7 +210,11 @@ const ChatMsg: React.FC<Props> = ({ queryId, data, chartIndex, triggerResize })
|
|||||||
<div>
|
<div>
|
||||||
{getMsgContent()}
|
{getMsgContent()}
|
||||||
{(isMultipleMetric || existDrillDownDimension) && (
|
{(isMultipleMetric || existDrillDownDimension) && (
|
||||||
<div className={`${prefixCls}-bottom-tools`}>
|
<div
|
||||||
|
className={`${prefixCls}-bottom-tools ${
|
||||||
|
isMetricCard ? `${prefixCls}-metric-card-tools` : ''
|
||||||
|
}`}
|
||||||
|
>
|
||||||
{isMultipleMetric && (
|
{isMultipleMetric && (
|
||||||
<MetricOptions
|
<MetricOptions
|
||||||
metrics={chatContext.metrics}
|
metrics={chatContext.metrics}
|
||||||
@@ -221,6 +226,7 @@ const ChatMsg: React.FC<Props> = ({ queryId, data, chartIndex, triggerResize })
|
|||||||
{existDrillDownDimension && (
|
{existDrillDownDimension && (
|
||||||
<DrillDownDimensions
|
<DrillDownDimensions
|
||||||
modelId={chatContext.modelId}
|
modelId={chatContext.modelId}
|
||||||
|
metricId={activeMetricField?.id || defaultMetricField?.id}
|
||||||
drillDownDimension={drillDownDimension}
|
drillDownDimension={drillDownDimension}
|
||||||
originDimensions={chatContext.dimensions}
|
originDimensions={chatContext.dimensions}
|
||||||
dimensionFilters={chatContext.dimensionFilters}
|
dimensionFilters={chatContext.dimensionFilters}
|
||||||
|
|||||||
@@ -14,5 +14,10 @@
|
|||||||
column-gap: 20px;
|
column-gap: 20px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-metric-card-tools {
|
||||||
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ import classNames from 'classnames';
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
modelId: number;
|
modelId: number;
|
||||||
|
metricId?: number;
|
||||||
drillDownDimension?: DrillDownDimensionType;
|
drillDownDimension?: DrillDownDimensionType;
|
||||||
isMetricCard?: boolean;
|
isMetricCard?: boolean;
|
||||||
originDimensions?: DrillDownDimensionType[];
|
originDimensions?: DrillDownDimensionType[];
|
||||||
@@ -17,8 +18,11 @@ type Props = {
|
|||||||
|
|
||||||
const MAX_DIMENSION_COUNT = 20;
|
const MAX_DIMENSION_COUNT = 20;
|
||||||
|
|
||||||
|
const DEFAULT_DIMENSION_COUNT = 5;
|
||||||
|
|
||||||
const DrillDownDimensions: React.FC<Props> = ({
|
const DrillDownDimensions: React.FC<Props> = ({
|
||||||
modelId,
|
modelId,
|
||||||
|
metricId,
|
||||||
drillDownDimension,
|
drillDownDimension,
|
||||||
isMetricCard,
|
isMetricCard,
|
||||||
originDimensions,
|
originDimensions,
|
||||||
@@ -27,12 +31,10 @@ const DrillDownDimensions: React.FC<Props> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const [dimensions, setDimensions] = useState<DrillDownDimensionType[]>([]);
|
const [dimensions, setDimensions] = useState<DrillDownDimensionType[]>([]);
|
||||||
|
|
||||||
const DEFAULT_DIMENSION_COUNT = isMetricCard ? 3 : 5;
|
|
||||||
|
|
||||||
const prefixCls = `${CLS_PREFIX}-drill-down-dimensions`;
|
const prefixCls = `${CLS_PREFIX}-drill-down-dimensions`;
|
||||||
|
|
||||||
const initData = async () => {
|
const initData = async () => {
|
||||||
const res = await queryDrillDownDimensions(modelId);
|
const res = await queryDrillDownDimensions(modelId, metricId);
|
||||||
setDimensions(
|
setDimensions(
|
||||||
res.data.dimensions
|
res.data.dimensions
|
||||||
.filter(
|
.filter(
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
.@{drill-down-dimensions-prefix-cls} {
|
.@{drill-down-dimensions-prefix-cls} {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-top: 2px;
|
|
||||||
|
|
||||||
&-section {
|
&-section {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -13,7 +12,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
column-gap: 6px;
|
column-gap: 6px;
|
||||||
margin-top: 6px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-metric-card {
|
&-metric-card {
|
||||||
|
|||||||
@@ -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_4120566_46xw04fpzii.js',
|
scriptUrl: '//at.alicdn.com/t/c/font_4120566_2vn019wsui6.js',
|
||||||
});
|
});
|
||||||
|
|
||||||
export default IconFont;
|
export default IconFont;
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
column-gap: 6px;
|
column-gap: 6px;
|
||||||
margin-top: 8px;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&-metric-card {
|
&-metric-card {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const Tools: React.FC<Props> = ({ queryId, scoreValue, isLastMessage }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={prefixCls}>
|
<div className={prefixCls}>
|
||||||
{!isMobile && isLastMessage && (
|
{!isMobile && (
|
||||||
<div className={`${prefixCls}-feedback`}>
|
<div className={`${prefixCls}-feedback`}>
|
||||||
<div>这个回答正确吗?</div>
|
<div>这个回答正确吗?</div>
|
||||||
<LikeOutlined className={likeClass} onClick={like} />
|
<LikeOutlined className={likeClass} onClick={like} />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import './styles/index.less';
|
|||||||
// import ChatDemo from './demo/ChatDemo';
|
// import ChatDemo from './demo/ChatDemo';
|
||||||
// import CopilotDemo from './demo/CopilotDemo';
|
// import CopilotDemo from './demo/CopilotDemo';
|
||||||
// const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
// const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
||||||
// root.render(<Chat />);
|
// root.render(<ChatDemo />);
|
||||||
|
|
||||||
export { default as Chat } from './Chat';
|
export { default as Chat } from './Chat';
|
||||||
|
|
||||||
@@ -15,6 +15,8 @@ export { default as ChatMsg } from './components/ChatMsg';
|
|||||||
|
|
||||||
export { default as ChatItem } from './components/ChatItem';
|
export { default as ChatItem } from './components/ChatItem';
|
||||||
|
|
||||||
|
export { default as ShowCase } from './ShowCase';
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
SearchRecommendItem,
|
SearchRecommendItem,
|
||||||
FieldType,
|
FieldType,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { getToken } from '../utils/utils';
|
|||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const axiosInstance: AxiosInstance = axios.create({
|
const axiosInstance: AxiosInstance = axios.create({
|
||||||
// 设置基本URL,所有请求都会使用这个URL作为前缀
|
// 设置基本URL,所有请求都会使用这个URL作为前缀
|
||||||
baseURL: localStorage.getItem('SUPERSONIC_CHAT_API_URL') || '',
|
baseURL: '',
|
||||||
// 设置请求超时时间(毫秒)
|
// 设置请求超时时间(毫秒)
|
||||||
timeout: 120000,
|
timeout: 120000,
|
||||||
// 设置请求头
|
// 设置请求头
|
||||||
@@ -19,7 +19,6 @@ axiosInstance.interceptors.request.use(
|
|||||||
(config: any) => {
|
(config: any) => {
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
if (token && config?.headers) {
|
if (token && config?.headers) {
|
||||||
// config.headers.Auth = `Bearer ${token}`;
|
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
config.headers.Authorization = `Bearer ${token}`;
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ export function updateQAFeedback(questionId: number, score: number) {
|
|||||||
return axios.post<any>(`${prefix}/chat/manage/updateQAFeedback?id=${questionId}&score=${score}&feedback=`);
|
return axios.post<any>(`${prefix}/chat/manage/updateQAFeedback?id=${questionId}&score=${score}&feedback=`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryDrillDownDimensions(modelId: number) {
|
export function queryDrillDownDimensions(modelId: number, metricId?: number) {
|
||||||
return axios.get<{ dimensions: DrillDownDimensionType[] }>(`${prefix}/chat/recommend/metric/${modelId}`);
|
return axios.get<{ dimensions: DrillDownDimensionType[] }>(`${prefix}/chat/recommend/metric/${modelId}${metricId ? `?metricId=${metricId}` : ''}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryDimensionValues(modelId: number, bizName: string, agentId: number, elementID: number, value: string) {
|
export function queryDimensionValues(modelId: number, bizName: string, agentId: number, elementID: number, value: string) {
|
||||||
@@ -86,7 +86,7 @@ export function queryDimensionValues(modelId: number, bizName: string, agentId:
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function querySimilarQuestions(queryText: string, agentId?: number) {
|
export function querySimilarQuestions(queryText: string, agentId?: number) {
|
||||||
return axios.get<any>(`${prefix}/chat/manage/getSolvedQuery?queryText=${queryText}&agentId=${agentId}`);
|
return axios.get<any>(`${prefix}/chat/manage/getSolvedQuery?queryText=${queryText}&agentId=${agentId || 0}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryEntityInfo(queryId: number, parseId: number) {
|
export function queryEntityInfo(queryId: number, parseId: number) {
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
|||||||
<FormItem name="name" label="名称">
|
<FormItem name="name" label="名称">
|
||||||
<Input placeholder="请输入工具名称" />
|
<Input placeholder="请输入工具名称" />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
{(toolType === AgentToolTypeEnum.RULE || toolType === AgentToolTypeEnum.DSL) && (
|
{(toolType === AgentToolTypeEnum.RULE || toolType === AgentToolTypeEnum.LLM_S2QL) && (
|
||||||
<FormItem name="modelIds" label="主题域">
|
<FormItem name="modelIds" label="主题域">
|
||||||
<Select
|
<Select
|
||||||
options={modelList.map((model) => ({ label: model.name, value: model.id }))}
|
options={modelList.map((model) => ({ label: model.name, value: model.id }))}
|
||||||
@@ -122,7 +122,7 @@ const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
|||||||
/>
|
/>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
{toolType === AgentToolTypeEnum.DSL && (
|
{toolType === AgentToolTypeEnum.LLM_S2QL && (
|
||||||
<FormItem name="exampleQuestions" label="示例问题">
|
<FormItem name="exampleQuestions" label="示例问题">
|
||||||
<div className={styles.paramsSection}>
|
<div className={styles.paramsSection}>
|
||||||
{examples.map((example) => {
|
{examples.map((example) => {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export type MetricOptionType = {
|
|||||||
|
|
||||||
export enum AgentToolTypeEnum {
|
export enum AgentToolTypeEnum {
|
||||||
RULE = 'RULE',
|
RULE = 'RULE',
|
||||||
DSL = 'DSL',
|
LLM_S2QL = 'LLM_S2QL',
|
||||||
PLUGIN = 'PLUGIN',
|
PLUGIN = 'PLUGIN',
|
||||||
INTERPRET = 'INTERPRET'
|
INTERPRET = 'INTERPRET'
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ export const AGENT_TOOL_TYPE_LIST = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '大模型语义解析',
|
label: '大模型语义解析',
|
||||||
value: AgentToolTypeEnum.DSL
|
value: AgentToolTypeEnum.LLM_S2QL
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '大模型指标解读',
|
label: '大模型指标解读',
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
|||||||
}))}
|
}))}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
setPluginType(value);
|
setPluginType(value);
|
||||||
if (value === PluginTypeEnum.DSL) {
|
if (value === PluginTypeEnum.LLM_S2QL) {
|
||||||
form.setFieldsValue({ parseMode: ParseModeEnum.FUNCTION_CALL });
|
form.setFieldsValue({ parseMode: ParseModeEnum.FUNCTION_CALL });
|
||||||
setFunctionParams([
|
setFunctionParams([
|
||||||
{
|
{
|
||||||
@@ -243,7 +243,7 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
|||||||
<FormItem name="pattern" label="函数描述">
|
<FormItem name="pattern" label="函数描述">
|
||||||
<TextArea placeholder="请输入函数描述,多个描述换行分隔" allowClear />
|
<TextArea placeholder="请输入函数描述,多个描述换行分隔" allowClear />
|
||||||
</FormItem>
|
</FormItem>
|
||||||
{/* <FormItem name="params" label="函数参数" hidden={pluginType === PluginTypeEnum.DSL}>
|
{/* <FormItem name="params" label="函数参数" hidden={pluginType === PluginTypeEnum.LLM_S2QL}>
|
||||||
<div className={styles.paramsSection}>
|
<div className={styles.paramsSection}>
|
||||||
{functionParams.map((functionParam: FunctionParamFormItemType) => {
|
{functionParams.map((functionParam: FunctionParamFormItemType) => {
|
||||||
const { id, name, type, description } = functionParam;
|
const { id, name, type, description } = functionParam;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export const PLUGIN_TYPE_MAP = {
|
export const PLUGIN_TYPE_MAP = {
|
||||||
WEB_PAGE: 'Web页面',
|
WEB_PAGE: 'Web页面',
|
||||||
WEB_SERVICE: 'Web服务',
|
WEB_SERVICE: 'Web服务',
|
||||||
// DSL: 'LLM语义解析',
|
// LLM_S2QL: 'LLM语义解析',
|
||||||
// CONTENT_INTERPRET: '内容解读',
|
// CONTENT_INTERPRET: '内容解读',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export type PluginConfigType = {
|
|||||||
export enum PluginTypeEnum {
|
export enum PluginTypeEnum {
|
||||||
WEB_PAGE = 'WEB_PAGE',
|
WEB_PAGE = 'WEB_PAGE',
|
||||||
WEB_SERVICE = 'WEB_SERVICE',
|
WEB_SERVICE = 'WEB_SERVICE',
|
||||||
DSL = 'DSL'
|
LLM_S2QL = 'LLM_S2QL'
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ParseModeEnum {
|
export enum ParseModeEnum {
|
||||||
|
|||||||
2
webapp/pnpm-lock.yaml
generated
2
webapp/pnpm-lock.yaml
generated
@@ -430,7 +430,7 @@ importers:
|
|||||||
specifier: '3.5'
|
specifier: '3.5'
|
||||||
version: 3.5.41(react-router@5.3.4)
|
version: 3.5.41(react-router@5.3.4)
|
||||||
umi-request:
|
umi-request:
|
||||||
specifier: ^1.0.8
|
specifier: ^1.4.0
|
||||||
version: 1.4.0
|
version: 1.4.0
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@ant-design/pro-cli':
|
'@ant-design/pro-cli':
|
||||||
|
|||||||
Reference in New Issue
Block a user