浏览代码

feat: add OperateDropdown and send debug message #918 (#1095)

### What problem does this PR solve?
feat: add OperateDropdown
feat: send debug message #918 

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
tags/v0.8.0
balibabu 1年前
父节点
当前提交
706985c188
没有帐户链接到提交者的电子邮件

+ 3
- 0
web/src/components/operate-dropdown/index.less 查看文件

@@ -0,0 +1,3 @@
.delete {
height: 24px;
}

+ 61
- 0
web/src/components/operate-dropdown/index.tsx 查看文件

@@ -0,0 +1,61 @@
import { ReactComponent as MoreIcon } from '@/assets/svg/more.svg';
import { useShowDeleteConfirm } from '@/hooks/commonHooks';
import { DeleteOutlined } from '@ant-design/icons';
import { Dropdown, MenuProps, Space } from 'antd';
import { useTranslation } from 'react-i18next';

import React from 'react';
import styles from './index.less';

interface IProps {
deleteItem: () => Promise<any>;
}

const OperateDropdown = ({
deleteItem,
children,
}: React.PropsWithChildren<IProps>) => {
const { t } = useTranslation();
const showDeleteConfirm = useShowDeleteConfirm();

const handleDelete = () => {
showDeleteConfirm({ onOk: deleteItem });
};

const handleDropdownMenuClick: MenuProps['onClick'] = ({ domEvent, key }) => {
domEvent.preventDefault();
domEvent.stopPropagation();
if (key === '1') {
handleDelete();
}
};

const items: MenuProps['items'] = [
{
key: '1',
label: (
<Space>
{t('common.delete')}
<DeleteOutlined />
</Space>
),
},
];

return (
<Dropdown
menu={{
items,
onClick: handleDropdownMenuClick,
}}
>
{children || (
<span className={styles.delete}>
<MoreIcon />
</span>
)}
</Dropdown>
);
};

export default OperateDropdown;

+ 1
- 1
web/src/hooks/flow-hooks.ts 查看文件

@@ -64,7 +64,7 @@ export const useSetFlow = () => {
);
queryClient.invalidateQueries({ queryKey: ['fetchFlowList'] });
}
return data?.retcode;
return data;
},
});


+ 3
- 3
web/src/hooks/logicHooks.ts 查看文件

@@ -206,14 +206,14 @@ export const useSendMessageWithSse = (

//#region chat hooks

export const useScrollToBottom = (id?: string) => {
export const useScrollToBottom = (messages?: unknown) => {
const ref = useRef<HTMLDivElement>(null);

const scrollToBottom = useCallback(() => {
if (id) {
if (messages) {
ref.current?.scrollIntoView({ behavior: 'instant' });
}
}, [id]);
}, [messages]); // If the message changes, scroll to the bottom

useEffect(() => {
scrollToBottom();

+ 4
- 7
web/src/interfaces/database/flow.ts 查看文件

@@ -1,4 +1,5 @@
import { Edge, Node } from 'reactflow';
import { IReference, Message } from './chat';

export type DSLComponents = Record<string, IOperator>;

@@ -8,6 +9,8 @@ export interface DSL {
path?: string[];
answer?: any[];
graph?: IGraph;
messages: Message[];
reference: IReference[];
}

export interface IOperator {
@@ -32,13 +35,7 @@ export interface IFlow {
create_date: string;
create_time: number;
description: null;
dsl: {
answer: any[];
components: DSLComponents;
graph: IGraph;
history: any[];
path: string[];
};
dsl: DSL;
id: string;
title: string;
update_date: string;

+ 2
- 2
web/src/pages/chat/utils.ts 查看文件

@@ -1,7 +1,7 @@
import { MessageType } from '@/constants/chat';
import { IConversation, IReference } from '@/interfaces/database/chat';
import { EmptyConversationId } from './constants';
import { IClientConversation, IMessage } from './interface';
import { IMessage } from './interface';

export const isConversationIdExist = (conversationId: string) => {
return conversationId !== EmptyConversationId && conversationId !== '';
@@ -25,7 +25,7 @@ export const getDocumentIdsFromConversionReference = (data: IConversation) => {
};

export const buildMessageItemReference = (
conversation: IClientConversation,
conversation: { message: IMessage[]; reference: IReference[] },
message: IMessage,
) => {
const assistantMessages = conversation.message

+ 17
- 25
web/src/pages/flow/chat/box.tsx 查看文件

@@ -2,43 +2,34 @@ import MessageItem from '@/components/message-item';
import DocumentPreviewer from '@/components/pdf-previewer';
import { MessageType } from '@/constants/chat';
import { useTranslate } from '@/hooks/commonHooks';
import {
useClickDrawer,
useFetchConversationOnMount,
useGetFileIcon,
useGetSendButtonDisabled,
useSelectConversationLoading,
useSendMessage,
} from '@/pages/chat/hooks';
import { useClickDrawer, useGetFileIcon } from '@/pages/chat/hooks';
import { buildMessageItemReference } from '@/pages/chat/utils';
import { Button, Drawer, Flex, Input, Spin } from 'antd';

import { useSelectCurrentMessages, useSendMessage } from './hooks';

import styles from './index.less';

const FlowChatBox = () => {
const {
ref,
currentConversation: conversation,
addNewestConversation,
removeLatestMessage,
currentMessages,
reference,
addNewestAnswer,
} = useFetchConversationOnMount();
addNewestQuestion,
removeLatestMessage,
loading,
} = useSelectCurrentMessages();

const {
handleInputChange,
handlePressEnter,
value,
loading: sendLoading,
} = useSendMessage(
conversation,
addNewestConversation,
removeLatestMessage,
addNewestAnswer,
);
} = useSendMessage(addNewestQuestion, removeLatestMessage, addNewestAnswer);
const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
useClickDrawer();
const disabled = useGetSendButtonDisabled();
useGetFileIcon();
const loading = useSelectConversationLoading();
const { t } = useTranslate('chat');

return (
@@ -47,17 +38,20 @@ const FlowChatBox = () => {
<Flex flex={1} vertical className={styles.messageContainer}>
<div>
<Spin spinning={loading}>
{conversation?.message?.map((message, i) => {
{currentMessages?.map((message, i) => {
return (
<MessageItem
loading={
message.role === MessageType.Assistant &&
sendLoading &&
conversation?.message.length - 1 === i
currentMessages.length - 1 === i
}
key={message.id}
item={message}
reference={buildMessageItemReference(conversation, message)}
reference={buildMessageItemReference(
{ message: currentMessages, reference },
message,
)}
clickDocumentButton={clickDocumentButton}
></MessageItem>
);
@@ -70,13 +64,11 @@ const FlowChatBox = () => {
size="large"
placeholder={t('sendPlaceholder')}
value={value}
disabled={disabled}
suffix={
<Button
type="primary"
onClick={handlePressEnter}
loading={sendLoading}
disabled={disabled}
>
{t('send')}
</Button>

+ 21
- 0
web/src/pages/flow/chat/drawer.tsx 查看文件

@@ -0,0 +1,21 @@
import { IModalProps } from '@/interfaces/common';
import { Drawer } from 'antd';
import FlowChatBox from './box';

const ChatDrawer = ({ visible, hideModal }: IModalProps<any>) => {
return (
<Drawer
title="Debug"
placement="right"
onClose={hideModal}
open={visible}
getContainer={false}
width={470}
zIndex={10000}
>
<FlowChatBox></FlowChatBox>
</Drawer>
);
};

export default ChatDrawer;

+ 50
- 101
web/src/pages/flow/chat/hooks.ts 查看文件

@@ -2,27 +2,25 @@ import { MessageType } from '@/constants/chat';
import { useFetchFlow } from '@/hooks/flow-hooks';
import {
useHandleMessageInputChange,
// useScrollToBottom,
useScrollToBottom,
useSendMessageWithSse,
} from '@/hooks/logicHooks';
import { IAnswer } from '@/interfaces/database/chat';
import { IMessage } from '@/pages/chat/interface';
import omit from 'lodash/omit';
import api from '@/utils/api';
import { useCallback, useEffect, useState } from 'react';
import { useParams } from 'umi';
import { v4 as uuid } from 'uuid';
import { Operator } from '../constant';
import useGraphStore from '../store';

export const useSelectCurrentConversation = () => {
export const useSelectCurrentMessages = () => {
const { id: id } = useParams();
const findNodeByName = useGraphStore((state) => state.findNodeByName);
const [currentMessages, setCurrentMessages] = useState<IMessage[]>([]);

const { data: flowDetail } = useFetchFlow();
const messages = flowDetail.dsl.history;
const { data: flowDetail, loading } = useFetchFlow();
const messages = flowDetail.dsl.messages;
const reference = flowDetail.dsl.reference;

const prologue = findNodeByName(Operator.Begin)?.data?.form?.prologue;
const ref = useScrollToBottom(currentMessages);

const addNewestQuestion = useCallback(
(message: string, answer: string = '') => {
@@ -45,121 +43,71 @@ export const useSelectCurrentConversation = () => {
[],
);

const addNewestAnswer = useCallback(
(answer: IAnswer) => {
setCurrentMessages((pre) => {
const latestMessage = currentMessages?.at(-1);

if (latestMessage) {
return [
...pre.slice(0, -1),
{
...latestMessage,
content: answer.answer,
reference: answer.reference,
},
];
}
return pre;
});
},
[currentMessages],
);
const addNewestAnswer = useCallback((answer: IAnswer) => {
setCurrentMessages((pre) => {
const latestMessage = pre?.at(-1);

if (latestMessage) {
return [
...pre.slice(0, -1),
{
...latestMessage,
content: answer.answer,
reference: answer.reference,
},
];
}
return pre;
});
}, []);

const removeLatestMessage = useCallback(() => {
setCurrentMessages((pre) => {
const nextMessages = pre?.slice(0, -2) ?? [];
return nextMessages;
return [...pre, ...nextMessages];
});
}, []);

const addPrologue = useCallback(() => {
if (id === '') {
const nextMessage = {
role: MessageType.Assistant,
content: prologue,
id: uuid(),
} as IMessage;

setCurrentMessages({
id: '',
reference: [],
message: [nextMessage],
} as any);
}
}, [id, prologue]);

useEffect(() => {
addPrologue();
}, [addPrologue]);

useEffect(() => {
if (id) {
setCurrentMessages(messages);
const nextMessages = messages.map((x) => ({ ...x, id: uuid() }));
setCurrentMessages(nextMessages);
}
}, [messages, id]);

return {
currentConversation: currentMessages,
currentMessages,
reference,
addNewestQuestion,
removeLatestMessage,
addNewestAnswer,
ref,
loading,
};
};

// export const useFetchConversationOnMount = () => {
// const { conversationId } = useGetChatSearchParams();
// const fetchConversation = useFetchConversation();
// const {
// currentConversation,
// addNewestQuestion,
// removeLatestMessage,
// addNewestAnswer,
// } = useSelectCurrentConversation();
// const ref = useScrollToBottom(currentConversation);

// const fetchConversationOnMount = useCallback(() => {
// if (isConversationIdExist(conversationId)) {
// fetchConversation(conversationId);
// }
// }, [fetchConversation, conversationId]);

// useEffect(() => {
// fetchConversationOnMount();
// }, [fetchConversationOnMount]);

// return {
// currentConversation,
// addNewestQuestion,
// ref,
// removeLatestMessage,
// addNewestAnswer,
// };
// };

export const useSendMessage = (
conversation: any,
addNewestQuestion: (message: string, answer?: string) => void,
removeLatestMessage: () => void,
addNewestAnswer: (answer: IAnswer) => void,
) => {
const { id: conversationId } = useParams();
const { id: flowId } = useParams();
const { handleInputChange, value, setValue } = useHandleMessageInputChange();
const { data: flowDetail } = useFetchFlow();
const messages = flowDetail.dsl.messages;

const { send, answer, done } = useSendMessageWithSse();
const { send, answer, done } = useSendMessageWithSse(api.runCanvas);

const sendMessage = useCallback(
async (message: string, id?: string) => {
const res: Response | undefined = await send({
conversation_id: id ?? conversationId,
messages: [
...(conversation?.message ?? []).map((x: IMessage) => omit(x, 'id')),
{
role: MessageType.User,
content: message,
},
],
});
const params: Record<string, unknown> = {
id: flowId,
};
if (message) {
params.message = message;
}
const res: Response | undefined = await send(params);

if (res?.status !== 200) {
// cancel loading
@@ -167,13 +115,7 @@ export const useSendMessage = (
removeLatestMessage();
}
},
[
conversation?.message,
conversationId,
removeLatestMessage,
setValue,
send,
],
[flowId, removeLatestMessage, setValue, send],
);

const handleSendMessage = useCallback(
@@ -189,6 +131,13 @@ export const useSendMessage = (
}
}, [answer, addNewestAnswer]);

useEffect(() => {
// fetch prologue
if (messages.length === 0) {
sendMessage('');
}
}, [sendMessage, messages]);

const handlePressEnter = useCallback(() => {
if (done) {
setValue('');

+ 2
- 1
web/src/pages/flow/chat/index.less 查看文件

@@ -1,5 +1,6 @@
.chatContainer {
padding: 0 0 24px 24px;
padding: 0;
height: 100%;
.messageContainer {
overflow-y: auto;
padding-right: 24px;

+ 1
- 1
web/src/pages/flow/header/index.less 查看文件

@@ -1,3 +1,3 @@
.flowHeader {
padding: 20px;
padding: 0 20px;
}

+ 39
- 14
web/src/pages/flow/header/index.tsx 查看文件

@@ -1,26 +1,51 @@
import { Button, Flex } from 'antd';
import { Button, Flex, Space } from 'antd';

import { useSetModalState } from '@/hooks/commonHooks';
import { useFetchFlow } from '@/hooks/flow-hooks';
import { ArrowLeftOutlined } from '@ant-design/icons';
import { Link } from 'umi';
import ChatDrawer from '../chat/drawer';
import { useRunGraph, useSaveGraph } from '../hooks';
import styles from './index.less';

const FlowHeader = () => {
const { saveGraph } = useSaveGraph();
const { runGraph } = useRunGraph();
const {
visible: chatDrawerVisible,
hideModal: hideChatDrawer,
showModal: showChatDrawer,
} = useSetModalState();
const { data } = useFetchFlow();

return (
<Flex
align="center"
justify="end"
gap={'large'}
className={styles.flowHeader}
>
<Button onClick={runGraph}>
<b>Debug</b>
</Button>
<Button type="primary" onClick={saveGraph}>
<b>Save</b>
</Button>
</Flex>
<>
<Flex
align="center"
justify={'space-between'}
gap={'large'}
className={styles.flowHeader}
>
<Space size={'large'}>
<Link to={`/flow`}>
<ArrowLeftOutlined />
</Link>
<h3>{data.title}</h3>
</Space>
<Space size={'large'}>
<Button onClick={showChatDrawer}>
<b>Debug</b>
</Button>
<Button type="primary" onClick={saveGraph}>
<b>Save</b>
</Button>
</Space>
</Flex>
<ChatDrawer
visible={chatDrawerVisible}
hideModal={hideChatDrawer}
></ChatDrawer>
</>
);
};


+ 2
- 2
web/src/pages/flow/hooks.ts 查看文件

@@ -187,7 +187,7 @@ const useSetGraphInfo = () => {
const { setEdges, setNodes } = useGraphStore((state) => state);
const setGraphInfo = useCallback(
({ nodes = [], edges = [] }: IGraph) => {
if (nodes.length && edges.length) {
if (nodes.length || edges.length) {
setNodes(nodes);
setEdges(edges);
}
@@ -202,7 +202,7 @@ export const useFetchDataOnMount = () => {
const setGraphInfo = useSetGraphInfo();

useEffect(() => {
setGraphInfo(data?.dsl?.graph ?? {});
setGraphInfo(data?.dsl?.graph ?? ({} as IGraph));
}, [setGraphInfo, data?.dsl?.graph]);

useWatchGraphChange();

+ 7
- 47
web/src/pages/flow/list/flow-card/index.tsx 查看文件

@@ -1,17 +1,12 @@
import { ReactComponent as MoreIcon } from '@/assets/svg/more.svg';
import { useShowDeleteConfirm } from '@/hooks/commonHooks';
import { formatDate } from '@/utils/date';
import {
CalendarOutlined,
DeleteOutlined,
UserOutlined,
} from '@ant-design/icons';
import { Avatar, Card, Dropdown, MenuProps, Space } from 'antd';
import { useTranslation } from 'react-i18next';
import { CalendarOutlined, UserOutlined } from '@ant-design/icons';
import { Avatar, Card } from 'antd';
import { useNavigate } from 'umi';

import OperateDropdown from '@/components/operate-dropdown';
import { useDeleteFlow } from '@/hooks/flow-hooks';
import { IFlow } from '@/interfaces/database/flow';
import { useCallback } from 'react';
import styles from './index.less';

interface IProps {
@@ -20,37 +15,11 @@ interface IProps {

const FlowCard = ({ item }: IProps) => {
const navigate = useNavigate();
const showDeleteConfirm = useShowDeleteConfirm();
const { t } = useTranslation();
const { deleteFlow } = useDeleteFlow();

const removeKnowledge = () => {
const removeFlow = useCallback(() => {
return deleteFlow([item.id]);
};

const handleDelete = () => {
showDeleteConfirm({ onOk: removeKnowledge });
};

const items: MenuProps['items'] = [
{
key: '1',
label: (
<Space>
{t('common.delete')}
<DeleteOutlined />
</Space>
),
},
];

const handleDropdownMenuClick: MenuProps['onClick'] = ({ domEvent, key }) => {
domEvent.preventDefault();
domEvent.stopPropagation();
if (key === '1') {
handleDelete();
}
};
}, [deleteFlow, item]);

const handleCardClick = () => {
navigate(`/flow/${item.id}`);
@@ -61,16 +30,7 @@ const FlowCard = ({ item }: IProps) => {
<div className={styles.container}>
<div className={styles.content}>
<Avatar size={34} icon={<UserOutlined />} src={item.avatar} />
<Dropdown
menu={{
items,
onClick: handleDropdownMenuClick,
}}
>
<span className={styles.delete}>
<MoreIcon />
</span>
</Dropdown>
<OperateDropdown deleteItem={removeFlow}></OperateDropdown>
</div>
<div className={styles.titleWrapper}>
<span className={styles.title}>{item.title}</span>

+ 5
- 2
web/src/pages/flow/list/hooks.ts 查看文件

@@ -1,6 +1,7 @@
import { useSetModalState } from '@/hooks/commonHooks';
import { useFetchFlowList, useSetFlow } from '@/hooks/flow-hooks';
import { useCallback, useState } from 'react';
import { useNavigate } from 'umi';
import { dsl } from '../mock';

export const useFetchDataOnMount = () => {
@@ -17,16 +18,18 @@ export const useSaveFlow = () => {
showModal: showFileRenameModal,
} = useSetModalState();
const { loading, setFlow } = useSetFlow();
const navigate = useNavigate();

const onFlowOk = useCallback(
async (title: string) => {
const ret = await setFlow({ title, dsl });

if (ret === 0) {
if (ret?.retcode === 0) {
hideFlowSettingModal();
navigate(`/flow/${ret.data.id}`);
}
},
[setFlow, hideFlowSettingModal],
[setFlow, hideFlowSettingModal, navigate],
);

const handleShowFlowSettingModal = useCallback(

+ 113
- 111
web/src/pages/flow/mock.tsx 查看文件

@@ -49,83 +49,83 @@ export const dsl = {
sourcePosition: 'left',
targetPosition: 'right',
},
{
id: 'Answer:China',
type: 'textUpdater',
position: {
x: 150,
y: 200,
},
data: {
label: 'Answer',
},
sourcePosition: 'left',
targetPosition: 'right',
},
{
id: 'Retrieval:China',
type: 'textUpdater',
position: {
x: 250,
y: 200,
},
data: {
label: 'Retrieval',
},
sourcePosition: 'left',
targetPosition: 'right',
},
{
id: 'Generate:China',
type: 'textUpdater',
position: {
x: 100,
y: 100,
},
data: {
label: 'Generate',
},
sourcePosition: 'left',
targetPosition: 'right',
},
// {
// id: 'Answer:China',
// type: 'textUpdater',
// position: {
// x: 150,
// y: 200,
// },
// data: {
// label: 'Answer',
// },
// sourcePosition: 'left',
// targetPosition: 'right',
// },
// {
// id: 'Retrieval:China',
// type: 'textUpdater',
// position: {
// x: 250,
// y: 200,
// },
// data: {
// label: 'Retrieval',
// },
// sourcePosition: 'left',
// targetPosition: 'right',
// },
// {
// id: 'Generate:China',
// type: 'textUpdater',
// position: {
// x: 100,
// y: 100,
// },
// data: {
// label: 'Generate',
// },
// sourcePosition: 'left',
// targetPosition: 'right',
// },
],
edges: [
{
id: '7facb53d-65c9-43b3-ac55-339c445d3891',
label: '',
source: 'begin',
target: 'Answer:China',
markerEnd: {
type: 'arrow',
},
},
{
id: '7ac83631-502d-410f-a6e7-bec6866a5e99',
label: '',
source: 'Generate:China',
target: 'Answer:China',
markerEnd: {
type: 'arrow',
},
},
{
id: '0aaab297-5779-43ed-9281-2c4d3741566f',
label: '',
source: 'Answer:China',
target: 'Retrieval:China',
markerEnd: {
type: 'arrow',
},
},
{
id: '3477f9f3-0a7d-400e-af96-a11ea7673183',
label: '',
source: 'Retrieval:China',
target: 'Generate:China',
markerEnd: {
type: 'arrow',
},
},
// {
// id: '7facb53d-65c9-43b3-ac55-339c445d3891',
// label: '',
// source: 'begin',
// target: 'Answer:China',
// markerEnd: {
// type: 'arrow',
// },
// },
// {
// id: '7ac83631-502d-410f-a6e7-bec6866a5e99',
// label: '',
// source: 'Generate:China',
// target: 'Answer:China',
// markerEnd: {
// type: 'arrow',
// },
// },
// {
// id: '0aaab297-5779-43ed-9281-2c4d3741566f',
// label: '',
// source: 'Answer:China',
// target: 'Retrieval:China',
// markerEnd: {
// type: 'arrow',
// },
// },
// {
// id: '3477f9f3-0a7d-400e-af96-a11ea7673183',
// label: '',
// source: 'Retrieval:China',
// target: 'Generate:China',
// markerEnd: {
// type: 'arrow',
// },
// },
],
},
components: {
@@ -137,43 +137,45 @@ export const dsl = {
downstream: ['Answer:China'], // other edge target is downstream, edge source is current node id
upstream: [], // edge source is upstream, edge target is current node id
},
'Answer:China': {
obj: {
component_name: 'Answer',
params: {},
},
downstream: ['Retrieval:China'],
upstream: ['begin', 'Generate:China'],
},
'Retrieval:China': {
obj: {
component_name: 'Retrieval',
params: {
similarity_threshold: 0.2,
keywords_similarity_weight: 0.3,
top_n: 6,
top_k: 1024,
rerank_id: 'BAAI/bge-reranker-v2-m3',
kb_ids: ['568aa82603b611efa9d9fa163e197198'],
},
},
downstream: ['Generate:China'],
upstream: ['Answer:China'],
},
'Generate:China': {
obj: {
component_name: 'Generate',
params: {
llm_id: 'deepseek-chat',
prompt:
'You are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence "The answer you are looking for is not found in the knowledge base!" Answers need to consider chat history.\n Here is the knowledge base:\n {input}\n The above is the knowledge base.',
temperature: 0.2,
},
},
downstream: ['Answer:China'],
upstream: ['Retrieval:China'],
},
// 'Answer:China': {
// obj: {
// component_name: 'Answer',
// params: {},
// },
// downstream: ['Retrieval:China'],
// upstream: ['begin', 'Generate:China'],
// },
// 'Retrieval:China': {
// obj: {
// component_name: 'Retrieval',
// params: {
// similarity_threshold: 0.2,
// keywords_similarity_weight: 0.3,
// top_n: 6,
// top_k: 1024,
// rerank_id: 'BAAI/bge-reranker-v2-m3',
// kb_ids: ['568aa82603b611efa9d9fa163e197198'],
// },
// },
// downstream: ['Generate:China'],
// upstream: ['Answer:China'],
// },
// 'Generate:China': {
// obj: {
// component_name: 'Generate',
// params: {
// llm_id: 'deepseek-chat',
// prompt:
// 'You are an intelligent assistant. Please summarize the content of the knowledge base to answer the question. Please list the data in the knowledge base and answer in detail. When all knowledge base content is irrelevant to the question, your answer must include the sentence "The answer you are looking for is not found in the knowledge base!" Answers need to consider chat history.\n Here is the knowledge base:\n {input}\n The above is the knowledge base.',
// temperature: 0.2,
// },
// },
// downstream: ['Answer:China'],
// upstream: ['Retrieval:China'],
// },
},
messages: [],
reference: [],
history: [],
path: [],
answer: [],

+ 0
- 5
web/src/pages/flow/utils.ts 查看文件

@@ -147,11 +147,6 @@ export const buildDslComponentsByGraph = (
components[id] = {
obj: {
component_name: operatorName,
// params:
// removeUselessDataInTheOperator(
// operatorName,
// x.data.form as Record<string, unknown>,
// ) ?? {},
params:
buildOperatorParams(operatorName)(
x.data.form as Record<string, unknown>,

+ 4
- 40
web/src/pages/knowledge/knowledge-card/index.tsx 查看文件

@@ -1,18 +1,16 @@
import { ReactComponent as MoreIcon } from '@/assets/svg/more.svg';
import { KnowledgeRouteKey } from '@/constants/knowledge';
import { useShowDeleteConfirm } from '@/hooks/commonHooks';
import { IKnowledge } from '@/interfaces/database/knowledge';
import { formatDate } from '@/utils/date';
import {
CalendarOutlined,
DeleteOutlined,
FileTextOutlined,
UserOutlined,
} from '@ant-design/icons';
import { Avatar, Card, Dropdown, MenuProps, Space } from 'antd';
import { Avatar, Card, Space } from 'antd';
import { useTranslation } from 'react-i18next';
import { useDispatch, useNavigate } from 'umi';

import OperateDropdown from '@/components/operate-dropdown';
import styles from './index.less';

interface IProps {
@@ -22,10 +20,9 @@ interface IProps {
const KnowledgeCard = ({ item }: IProps) => {
const navigate = useNavigate();
const dispatch = useDispatch();
const showDeleteConfirm = useShowDeleteConfirm();
const { t } = useTranslation();

const removeKnowledge = () => {
const removeKnowledge = async () => {
return dispatch({
type: 'knowledgeModel/rmKb',
payload: {
@@ -34,30 +31,6 @@ const KnowledgeCard = ({ item }: IProps) => {
});
};

const handleDelete = () => {
showDeleteConfirm({ onOk: removeKnowledge });
};

const items: MenuProps['items'] = [
{
key: '1',
label: (
<Space>
{t('common.delete')}
<DeleteOutlined />
</Space>
),
},
];

const handleDropdownMenuClick: MenuProps['onClick'] = ({ domEvent, key }) => {
domEvent.preventDefault();
domEvent.stopPropagation();
if (key === '1') {
handleDelete();
}
};

const handleCardClick = () => {
navigate(`/knowledge/${KnowledgeRouteKey.Dataset}?id=${item.id}`, {
state: { from: 'list' },
@@ -69,16 +42,7 @@ const KnowledgeCard = ({ item }: IProps) => {
<div className={styles.container}>
<div className={styles.content}>
<Avatar size={34} icon={<UserOutlined />} src={item.avatar} />
<Dropdown
menu={{
items,
onClick: handleDropdownMenuClick,
}}
>
<span className={styles.delete}>
<MoreIcon />
</span>
</Dropdown>
<OperateDropdown deleteItem={removeKnowledge}></OperateDropdown>
</div>
<div className={styles.titleWrapper}>
<span className={styles.title}>{item.name}</span>

+ 1
- 1
web/src/utils/api.ts 查看文件

@@ -89,5 +89,5 @@ export default {
removeCanvas: `${api_host}/canvas/rm`,
setCanvas: `${api_host}/canvas/set`,
resetCanvas: `${api_host}/canvas/reset`,
runCanvas: `${api_host}/canvas/run`,
runCanvas: `${api_host}/canvas/completion`,
};

正在加载...
取消
保存