balibabu
commited on
Commit
·
f9e19e4
1
Parent(s):
22978e1
feat: Fetch mind map in search page #2247 (#2292)
Browse files### What problem does this PR solve?
feat: Fetch mind map in search page #2247
### Type of change
- [x] New Feature (non-breaking change which adds functionality)
- web/src/components/indented-tree/indented-tree.tsx +4 -2
- web/src/hooks/chat-hooks.ts +20 -1
- web/src/hooks/flow-hooks.ts +1 -1
- web/src/interfaces/request/chat.ts +1 -1
- web/src/layouts/components/header/index.tsx +3 -3
- web/src/locales/en.ts +2 -1
- web/src/locales/zh-traditional.ts +1 -0
- web/src/locales/zh.ts +1 -0
- web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx +2 -2
- web/src/pages/flow/message-form/index.tsx +1 -1
- web/src/pages/force-graph/index.tsx +0 -109
- web/src/pages/search/hooks.ts +23 -2
- web/src/pages/search/index.less +5 -1
- web/src/pages/search/index.tsx +32 -3
- web/src/pages/search/sidebar.tsx +9 -6
- web/src/services/chat-service.ts +5 -0
- web/src/utils/api.ts +1 -0
web/src/components/indented-tree/indented-tree.tsx
CHANGED
@@ -16,7 +16,7 @@ import {
|
|
16 |
} from '@antv/g6';
|
17 |
import { TreeData } from '@antv/g6/lib/types';
|
18 |
import isEmpty from 'lodash/isEmpty';
|
19 |
-
import { useCallback, useEffect, useRef } from 'react';
|
20 |
|
21 |
const rootId = 'root';
|
22 |
|
@@ -294,9 +294,10 @@ register(
|
|
294 |
interface IProps {
|
295 |
data: TreeData;
|
296 |
show: boolean;
|
|
|
297 |
}
|
298 |
|
299 |
-
const IndentedTree = ({ data, show }: IProps) => {
|
300 |
const containerRef = useRef<HTMLDivElement>(null);
|
301 |
const graphRef = useRef<Graph | null>(null);
|
302 |
|
@@ -388,6 +389,7 @@ const IndentedTree = ({ data, show }: IProps) => {
|
|
388 |
width: '90vw',
|
389 |
height: '80vh',
|
390 |
display: show ? 'block' : 'none',
|
|
|
391 |
}}
|
392 |
/>
|
393 |
);
|
|
|
16 |
} from '@antv/g6';
|
17 |
import { TreeData } from '@antv/g6/lib/types';
|
18 |
import isEmpty from 'lodash/isEmpty';
|
19 |
+
import React, { useCallback, useEffect, useRef } from 'react';
|
20 |
|
21 |
const rootId = 'root';
|
22 |
|
|
|
294 |
interface IProps {
|
295 |
data: TreeData;
|
296 |
show: boolean;
|
297 |
+
style?: React.CSSProperties;
|
298 |
}
|
299 |
|
300 |
+
const IndentedTree = ({ data, show, style = {} }: IProps) => {
|
301 |
const containerRef = useRef<HTMLDivElement>(null);
|
302 |
const graphRef = useRef<Graph | null>(null);
|
303 |
|
|
|
389 |
width: '90vw',
|
390 |
height: '80vh',
|
391 |
display: show ? 'block' : 'none',
|
392 |
+
...style,
|
393 |
}}
|
394 |
/>
|
395 |
);
|
web/src/hooks/chat-hooks.ts
CHANGED
@@ -490,13 +490,32 @@ export const useFetchMindMap = () => {
|
|
490 |
mutateAsync,
|
491 |
} = useMutation({
|
492 |
mutationKey: ['fetchMindMap'],
|
|
|
493 |
mutationFn: async (params: IAskRequestBody) => {
|
494 |
const { data } = await chatService.getMindMap(params);
|
495 |
|
496 |
-
return data;
|
497 |
},
|
498 |
});
|
499 |
|
500 |
return { data, loading, fetchMindMap: mutateAsync };
|
501 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
502 |
//#endregion
|
|
|
490 |
mutateAsync,
|
491 |
} = useMutation({
|
492 |
mutationKey: ['fetchMindMap'],
|
493 |
+
gcTime: 0,
|
494 |
mutationFn: async (params: IAskRequestBody) => {
|
495 |
const { data } = await chatService.getMindMap(params);
|
496 |
|
497 |
+
return data?.data ?? [];
|
498 |
},
|
499 |
});
|
500 |
|
501 |
return { data, loading, fetchMindMap: mutateAsync };
|
502 |
};
|
503 |
+
|
504 |
+
export const useFetchRelatedQuestions = () => {
|
505 |
+
const {
|
506 |
+
data,
|
507 |
+
isPending: loading,
|
508 |
+
mutateAsync,
|
509 |
+
} = useMutation({
|
510 |
+
mutationKey: ['fetchRelatedQuestions'],
|
511 |
+
gcTime: 0,
|
512 |
+
mutationFn: async (question: string): Promise<string[]> => {
|
513 |
+
const { data } = await chatService.getRelatedQuestions({ question });
|
514 |
+
|
515 |
+
return data?.data ?? [];
|
516 |
+
},
|
517 |
+
});
|
518 |
+
|
519 |
+
return { data, loading, fetchRelatedQuestions: mutateAsync };
|
520 |
+
};
|
521 |
//#endregion
|
web/src/hooks/flow-hooks.ts
CHANGED
@@ -57,7 +57,7 @@ export const useFetchFlowTemplates = (): ResponseType<IFlowTemplate[]> => {
|
|
57 |
data.data.unshift({
|
58 |
id: uuid(),
|
59 |
title: 'Blank',
|
60 |
-
description: 'Create from
|
61 |
dsl: EmptyDsl,
|
62 |
});
|
63 |
}
|
|
|
57 |
data.data.unshift({
|
58 |
id: uuid(),
|
59 |
title: 'Blank',
|
60 |
+
description: 'Create your agent from scratch',
|
61 |
dsl: EmptyDsl,
|
62 |
});
|
63 |
}
|
web/src/interfaces/request/chat.ts
CHANGED
@@ -5,6 +5,6 @@ export interface IFeedbackRequestBody {
|
|
5 |
}
|
6 |
|
7 |
export interface IAskRequestBody {
|
8 |
-
|
9 |
kb_ids: string[];
|
10 |
}
|
|
|
5 |
}
|
6 |
|
7 |
export interface IAskRequestBody {
|
8 |
+
question: string;
|
9 |
kb_ids: string[];
|
10 |
}
|
web/src/layouts/components/header/index.tsx
CHANGED
@@ -9,7 +9,7 @@ import { useLocation } from 'umi';
|
|
9 |
import Toolbar from '../right-toolbar';
|
10 |
|
11 |
import { useFetchAppConf } from '@/hooks/logic-hooks';
|
12 |
-
import {
|
13 |
import styles from './index.less';
|
14 |
|
15 |
const { Header } = Layout;
|
@@ -26,8 +26,8 @@ const RagHeader = () => {
|
|
26 |
const tagsData = useMemo(
|
27 |
() => [
|
28 |
{ path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon },
|
29 |
-
{ path: '/chat', name: t('chat'), icon: MessageOutlined },
|
30 |
-
|
31 |
{ path: '/flow', name: t('flow'), icon: GraphIcon },
|
32 |
{ path: '/file', name: t('fileManager'), icon: FileIcon },
|
33 |
],
|
|
|
9 |
import Toolbar from '../right-toolbar';
|
10 |
|
11 |
import { useFetchAppConf } from '@/hooks/logic-hooks';
|
12 |
+
import { SearchOutlined } from '@ant-design/icons';
|
13 |
import styles from './index.less';
|
14 |
|
15 |
const { Header } = Layout;
|
|
|
26 |
const tagsData = useMemo(
|
27 |
() => [
|
28 |
{ path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon },
|
29 |
+
// { path: '/chat', name: t('chat'), icon: MessageOutlined },
|
30 |
+
{ path: '/search', name: t('search'), icon: SearchOutlined },
|
31 |
{ path: '/flow', name: t('flow'), icon: GraphIcon },
|
32 |
{ path: '/file', name: t('fileManager'), icon: FileIcon },
|
33 |
],
|
web/src/locales/en.ts
CHANGED
@@ -634,6 +634,7 @@ The above is the content you need to summarize.`,
|
|
634 |
messagePlaceholder: 'message',
|
635 |
messageMsg: 'Please input message or delete this field.',
|
636 |
addField: 'Add field',
|
|
|
637 |
loop: 'Loop',
|
638 |
loopTip:
|
639 |
'Loop is the upper limit of the number of loops of the current component, when the number of loops exceeds the value of loop, it means that the component can not complete the current task, please re-optimize agent',
|
@@ -672,7 +673,7 @@ The above is the content you need to summarize.`,
|
|
672 |
begin: 'Begin',
|
673 |
message: 'Message',
|
674 |
blank: 'Blank',
|
675 |
-
createFromNothing: 'Create from
|
676 |
addItem: 'Add Item',
|
677 |
addSubItem: 'Add Sub Item',
|
678 |
nameRequiredMsg: 'Name is required',
|
|
|
634 |
messagePlaceholder: 'message',
|
635 |
messageMsg: 'Please input message or delete this field.',
|
636 |
addField: 'Add field',
|
637 |
+
addMessage: 'Add message',
|
638 |
loop: 'Loop',
|
639 |
loopTip:
|
640 |
'Loop is the upper limit of the number of loops of the current component, when the number of loops exceeds the value of loop, it means that the component can not complete the current task, please re-optimize agent',
|
|
|
673 |
begin: 'Begin',
|
674 |
message: 'Message',
|
675 |
blank: 'Blank',
|
676 |
+
createFromNothing: 'Create your agent from scratch',
|
677 |
addItem: 'Add Item',
|
678 |
addSubItem: 'Add Sub Item',
|
679 |
nameRequiredMsg: 'Name is required',
|
web/src/locales/zh-traditional.ts
CHANGED
@@ -590,6 +590,7 @@ export default {
|
|
590 |
messagePlaceholder: '訊息',
|
591 |
messageMsg: '請輸入訊息或刪除此欄位。',
|
592 |
addField: '新增字段',
|
|
|
593 |
loop: '循環上限',
|
594 |
loopTip:
|
595 |
'loop為目前元件循環次數上限,當循環次數超過loop的值時,表示元件無法完成目前任務,請重新最佳化agent',
|
|
|
590 |
messagePlaceholder: '訊息',
|
591 |
messageMsg: '請輸入訊息或刪除此欄位。',
|
592 |
addField: '新增字段',
|
593 |
+
addMessage: '新增訊息',
|
594 |
loop: '循環上限',
|
595 |
loopTip:
|
596 |
'loop為目前元件循環次數上限,當循環次數超過loop的值時,表示元件無法完成目前任務,請重新最佳化agent',
|
web/src/locales/zh.ts
CHANGED
@@ -609,6 +609,7 @@ export default {
|
|
609 |
messagePlaceholder: '消息',
|
610 |
messageMsg: '请输入消息或删除此字段。',
|
611 |
addField: '新增字段',
|
|
|
612 |
loop: '循环上限',
|
613 |
loopTip:
|
614 |
'loop为当前组件循环次数上限,当循环次数超过loop的值时,说明组件不能完成当前任务,请重新优化agent',
|
|
|
609 |
messagePlaceholder: '消息',
|
610 |
messageMsg: '请输入消息或删除此字段。',
|
611 |
addField: '新增字段',
|
612 |
+
addMessage: '新增消息',
|
613 |
loop: '循环上限',
|
614 |
loopTip:
|
615 |
'loop为当前组件循环次数上限,当循环次数超过loop的值时,说明组件不能完成当前任务,请重新优化agent',
|
web/src/pages/chat/chat-configuration-modal/assistant-setting.tsx
CHANGED
@@ -90,7 +90,7 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
|
90 |
>
|
91 |
<Switch />
|
92 |
</Form.Item>
|
93 |
-
<Form.Item
|
94 |
label={t('selfRag')}
|
95 |
valuePropName="checked"
|
96 |
name={['prompt_config', 'self_rag']}
|
@@ -98,7 +98,7 @@ const AssistantSetting = ({ show }: ISegmentedContentProps) => {
|
|
98 |
initialValue={false}
|
99 |
>
|
100 |
<Switch />
|
101 |
-
</Form.Item>
|
102 |
{/* <Form.Item
|
103 |
label={t('tts')}
|
104 |
valuePropName="checked"
|
|
|
90 |
>
|
91 |
<Switch />
|
92 |
</Form.Item>
|
93 |
+
{/* <Form.Item
|
94 |
label={t('selfRag')}
|
95 |
valuePropName="checked"
|
96 |
name={['prompt_config', 'self_rag']}
|
|
|
98 |
initialValue={false}
|
99 |
>
|
100 |
<Switch />
|
101 |
+
</Form.Item> */}
|
102 |
{/* <Form.Item
|
103 |
label={t('tts')}
|
104 |
valuePropName="checked"
|
web/src/pages/flow/message-form/index.tsx
CHANGED
@@ -74,7 +74,7 @@ const MessageForm = ({ onValuesChange, form }: IOperatorForm) => {
|
|
74 |
style={{ width: '80%' }}
|
75 |
icon={<PlusOutlined />}
|
76 |
>
|
77 |
-
{t('
|
78 |
</Button>
|
79 |
</Form.Item>
|
80 |
</>
|
|
|
74 |
style={{ width: '80%' }}
|
75 |
icon={<PlusOutlined />}
|
76 |
>
|
77 |
+
{t('addMessage')}
|
78 |
</Button>
|
79 |
</Form.Item>
|
80 |
</>
|
web/src/pages/force-graph/index.tsx
CHANGED
@@ -1,112 +1,3 @@
|
|
1 |
-
import { Graph } from '@antv/g6';
|
2 |
-
import { useSize } from 'ahooks';
|
3 |
-
import { useEffect, useRef } from 'react';
|
4 |
-
import { graphData } from './constant';
|
5 |
import InputWithUpload from './input-upload';
|
6 |
|
7 |
-
import styles from './index.less';
|
8 |
-
import { Converter } from './util';
|
9 |
-
|
10 |
-
const converter = new Converter();
|
11 |
-
|
12 |
-
const nextData = converter.buildNodesAndCombos(
|
13 |
-
graphData.nodes,
|
14 |
-
graphData.edges,
|
15 |
-
);
|
16 |
-
console.log('🚀 ~ nextData:', nextData);
|
17 |
-
|
18 |
-
const finalData = { ...graphData, ...nextData };
|
19 |
-
|
20 |
-
const ForceGraph = () => {
|
21 |
-
const containerRef = useRef<HTMLDivElement>(null);
|
22 |
-
const size = useSize(containerRef);
|
23 |
-
let graph: Graph;
|
24 |
-
|
25 |
-
const render = () => {
|
26 |
-
graph = new Graph({
|
27 |
-
container: containerRef.current!,
|
28 |
-
autoFit: 'view',
|
29 |
-
behaviors: [
|
30 |
-
'drag-element',
|
31 |
-
'drag-canvas',
|
32 |
-
'zoom-canvas',
|
33 |
-
'collapse-expand',
|
34 |
-
{
|
35 |
-
type: 'hover-activate',
|
36 |
-
degree: 1, // 👈🏻 Activate relations.
|
37 |
-
},
|
38 |
-
],
|
39 |
-
plugins: [
|
40 |
-
{
|
41 |
-
type: 'tooltip',
|
42 |
-
getContent: (e, items) => {
|
43 |
-
if (items.every((x) => x?.description)) {
|
44 |
-
let result = ``;
|
45 |
-
items.forEach((item) => {
|
46 |
-
if (item?.description) {
|
47 |
-
result += `<p>${item?.description}</p>`;
|
48 |
-
}
|
49 |
-
});
|
50 |
-
return result;
|
51 |
-
}
|
52 |
-
return undefined;
|
53 |
-
},
|
54 |
-
},
|
55 |
-
],
|
56 |
-
layout: {
|
57 |
-
type: 'combo-combined',
|
58 |
-
preventOverlap: true,
|
59 |
-
comboPadding: 1,
|
60 |
-
spacing: 20,
|
61 |
-
},
|
62 |
-
node: {
|
63 |
-
style: {
|
64 |
-
size: 20,
|
65 |
-
labelText: (d) => d.id,
|
66 |
-
labelPadding: 30,
|
67 |
-
// labelOffsetX: 20,
|
68 |
-
// labelOffsetY: 5,
|
69 |
-
labelPlacement: 'center',
|
70 |
-
labelWordWrap: true,
|
71 |
-
},
|
72 |
-
palette: {
|
73 |
-
type: 'group',
|
74 |
-
field: (d) => d.combo,
|
75 |
-
},
|
76 |
-
// state: {
|
77 |
-
// highlight: {
|
78 |
-
// fill: '#D580FF',
|
79 |
-
// halo: true,
|
80 |
-
// lineWidth: 0,
|
81 |
-
// },
|
82 |
-
// dim: {
|
83 |
-
// fill: '#99ADD1',
|
84 |
-
// },
|
85 |
-
// },
|
86 |
-
},
|
87 |
-
edge: {
|
88 |
-
style: (model) => {
|
89 |
-
const { size, color } = model.data;
|
90 |
-
return {
|
91 |
-
stroke: color || '#99ADD1',
|
92 |
-
lineWidth: size || 1,
|
93 |
-
};
|
94 |
-
},
|
95 |
-
},
|
96 |
-
// data: graphData,
|
97 |
-
});
|
98 |
-
|
99 |
-
graph.setData(finalData);
|
100 |
-
|
101 |
-
graph.render();
|
102 |
-
};
|
103 |
-
|
104 |
-
useEffect(() => {
|
105 |
-
console.info('rendered');
|
106 |
-
render();
|
107 |
-
}, []);
|
108 |
-
|
109 |
-
return <div ref={containerRef} className={styles.container} />;
|
110 |
-
};
|
111 |
-
|
112 |
export default InputWithUpload;
|
|
|
|
|
|
|
|
|
|
|
1 |
import InputWithUpload from './input-upload';
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
export default InputWithUpload;
|
web/src/pages/search/hooks.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
|
|
1 |
import { useTestChunkRetrieval } from '@/hooks/knowledge-hooks';
|
2 |
import { useSendMessageWithSse } from '@/hooks/logic-hooks';
|
3 |
import { IAnswer } from '@/interfaces/database/chat';
|
@@ -10,6 +11,13 @@ export const useSendQuestion = (kbIds: string[]) => {
|
|
10 |
const { testChunk, loading } = useTestChunkRetrieval();
|
11 |
const [sendingLoading, setSendingLoading] = useState(false);
|
12 |
const [currentAnswer, setCurrentAnswer] = useState({} as IAnswer);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13 |
|
14 |
const sendQuestion = useCallback(
|
15 |
(question: string) => {
|
@@ -17,8 +25,13 @@ export const useSendQuestion = (kbIds: string[]) => {
|
|
17 |
setSendingLoading(true);
|
18 |
send({ kb_ids: kbIds, question });
|
19 |
testChunk({ kb_id: kbIds, highlight: true, question });
|
|
|
|
|
|
|
|
|
|
|
20 |
},
|
21 |
-
[send, testChunk, kbIds],
|
22 |
);
|
23 |
|
24 |
useEffect(() => {
|
@@ -33,5 +46,13 @@ export const useSendQuestion = (kbIds: string[]) => {
|
|
33 |
}
|
34 |
}, [done]);
|
35 |
|
36 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
};
|
|
|
1 |
+
import { useFetchMindMap, useFetchRelatedQuestions } from '@/hooks/chat-hooks';
|
2 |
import { useTestChunkRetrieval } from '@/hooks/knowledge-hooks';
|
3 |
import { useSendMessageWithSse } from '@/hooks/logic-hooks';
|
4 |
import { IAnswer } from '@/interfaces/database/chat';
|
|
|
11 |
const { testChunk, loading } = useTestChunkRetrieval();
|
12 |
const [sendingLoading, setSendingLoading] = useState(false);
|
13 |
const [currentAnswer, setCurrentAnswer] = useState({} as IAnswer);
|
14 |
+
const { fetchRelatedQuestions, data: relatedQuestions } =
|
15 |
+
useFetchRelatedQuestions();
|
16 |
+
const {
|
17 |
+
fetchMindMap,
|
18 |
+
data: mindMap,
|
19 |
+
loading: mindMapLoading,
|
20 |
+
} = useFetchMindMap();
|
21 |
|
22 |
const sendQuestion = useCallback(
|
23 |
(question: string) => {
|
|
|
25 |
setSendingLoading(true);
|
26 |
send({ kb_ids: kbIds, question });
|
27 |
testChunk({ kb_id: kbIds, highlight: true, question });
|
28 |
+
fetchMindMap({
|
29 |
+
question,
|
30 |
+
kb_ids: kbIds,
|
31 |
+
});
|
32 |
+
fetchRelatedQuestions(question);
|
33 |
},
|
34 |
+
[send, testChunk, kbIds, fetchRelatedQuestions, fetchMindMap],
|
35 |
);
|
36 |
|
37 |
useEffect(() => {
|
|
|
46 |
}
|
47 |
}, [done]);
|
48 |
|
49 |
+
return {
|
50 |
+
sendQuestion,
|
51 |
+
loading,
|
52 |
+
sendingLoading,
|
53 |
+
answer: currentAnswer,
|
54 |
+
relatedQuestions: relatedQuestions?.slice(0, 5) ?? [],
|
55 |
+
mindMap,
|
56 |
+
mindMapLoading,
|
57 |
+
};
|
58 |
};
|
web/src/pages/search/index.less
CHANGED
@@ -2,6 +2,10 @@
|
|
2 |
.card {
|
3 |
width: 100%;
|
4 |
}
|
|
|
|
|
|
|
|
|
5 |
}
|
6 |
|
7 |
.searchSide {
|
@@ -49,6 +53,6 @@
|
|
49 |
|
50 |
.graph {
|
51 |
width: 40%;
|
52 |
-
|
53 |
}
|
54 |
}
|
|
|
2 |
.card {
|
3 |
width: 100%;
|
4 |
}
|
5 |
+
.tag {
|
6 |
+
padding: 4px 8px;
|
7 |
+
font-size: 14px;
|
8 |
+
}
|
9 |
}
|
10 |
|
11 |
.searchSide {
|
|
|
53 |
|
54 |
.graph {
|
55 |
width: 40%;
|
56 |
+
padding-right: 10px;
|
57 |
}
|
58 |
}
|
web/src/pages/search/index.tsx
CHANGED
@@ -2,12 +2,13 @@ import HightLightMarkdown from '@/components/highlight-markdown';
|
|
2 |
import { ImageWithPopover } from '@/components/image';
|
3 |
import { useSelectTestingResult } from '@/hooks/knowledge-hooks';
|
4 |
import { IReference } from '@/interfaces/database/chat';
|
5 |
-
import { Card, Flex, Input, Layout, List, Space } from 'antd';
|
6 |
import { useState } from 'react';
|
7 |
import MarkdownContent from '../chat/markdown-content';
|
8 |
import { useSendQuestion } from './hooks';
|
9 |
import SearchSidebar from './sidebar';
|
10 |
|
|
|
11 |
import styles from './index.less';
|
12 |
|
13 |
const { Content } = Layout;
|
@@ -16,7 +17,14 @@ const { Search } = Input;
|
|
16 |
const SearchPage = () => {
|
17 |
const [checkedList, setCheckedList] = useState<string[]>([]);
|
18 |
const list = useSelectTestingResult();
|
19 |
-
const {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
|
21 |
return (
|
22 |
<Layout className={styles.searchPage}>
|
@@ -56,8 +64,29 @@ const SearchPage = () => {
|
|
56 |
</List.Item>
|
57 |
)}
|
58 |
/>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
</section>
|
60 |
-
<section className={styles.graph}></section>
|
61 |
</Flex>
|
62 |
</Content>
|
63 |
</Layout>
|
|
|
2 |
import { ImageWithPopover } from '@/components/image';
|
3 |
import { useSelectTestingResult } from '@/hooks/knowledge-hooks';
|
4 |
import { IReference } from '@/interfaces/database/chat';
|
5 |
+
import { Card, Flex, Input, Layout, List, Skeleton, Space, Tag } from 'antd';
|
6 |
import { useState } from 'react';
|
7 |
import MarkdownContent from '../chat/markdown-content';
|
8 |
import { useSendQuestion } from './hooks';
|
9 |
import SearchSidebar from './sidebar';
|
10 |
|
11 |
+
import IndentedTree from '@/components/indented-tree/indented-tree';
|
12 |
import styles from './index.less';
|
13 |
|
14 |
const { Content } = Layout;
|
|
|
17 |
const SearchPage = () => {
|
18 |
const [checkedList, setCheckedList] = useState<string[]>([]);
|
19 |
const list = useSelectTestingResult();
|
20 |
+
const {
|
21 |
+
sendQuestion,
|
22 |
+
answer,
|
23 |
+
sendingLoading,
|
24 |
+
relatedQuestions,
|
25 |
+
mindMap,
|
26 |
+
mindMapLoading,
|
27 |
+
} = useSendQuestion(checkedList);
|
28 |
|
29 |
return (
|
30 |
<Layout className={styles.searchPage}>
|
|
|
64 |
</List.Item>
|
65 |
)}
|
66 |
/>
|
67 |
+
{relatedQuestions?.length > 0 && (
|
68 |
+
<Card>
|
69 |
+
<Flex wrap="wrap" gap={'10px 0'}>
|
70 |
+
{relatedQuestions?.map((x, idx) => (
|
71 |
+
<Tag key={idx} className={styles.tag}>
|
72 |
+
{x}
|
73 |
+
</Tag>
|
74 |
+
))}
|
75 |
+
</Flex>
|
76 |
+
</Card>
|
77 |
+
)}
|
78 |
+
</section>
|
79 |
+
<section className={styles.graph}>
|
80 |
+
{mindMapLoading ? (
|
81 |
+
<Skeleton active />
|
82 |
+
) : (
|
83 |
+
<IndentedTree
|
84 |
+
data={mindMap}
|
85 |
+
show
|
86 |
+
style={{ width: '100%', height: '100%' }}
|
87 |
+
></IndentedTree>
|
88 |
+
)}
|
89 |
</section>
|
|
|
90 |
</Flex>
|
91 |
</Content>
|
92 |
</Layout>
|
web/src/pages/search/sidebar.tsx
CHANGED
@@ -30,20 +30,23 @@ const SearchSidebar = ({ checkedList, setCheckedList }: IProps) => {
|
|
30 |
const indeterminate =
|
31 |
checkedList.length > 0 && checkedList.length < list.length;
|
32 |
|
33 |
-
const onChange = useCallback(
|
34 |
-
|
35 |
-
|
|
|
|
|
|
|
36 |
|
37 |
const onCheckAllChange: CheckboxProps['onChange'] = useCallback(
|
38 |
(e: CheckboxChangeEvent) => {
|
39 |
setCheckedList(e.target.checked ? ids : []);
|
40 |
},
|
41 |
-
[ids],
|
42 |
);
|
43 |
|
44 |
useEffect(() => {
|
45 |
setCheckedList(ids);
|
46 |
-
}, [ids]);
|
47 |
|
48 |
return (
|
49 |
<Sider className={styles.searchSide} theme={'light'} width={240}>
|
@@ -53,7 +56,7 @@ const SearchSidebar = ({ checkedList, setCheckedList }: IProps) => {
|
|
53 |
onChange={onCheckAllChange}
|
54 |
checked={checkAll}
|
55 |
>
|
56 |
-
|
57 |
</Checkbox>
|
58 |
<Checkbox.Group
|
59 |
className={styles.checkGroup}
|
|
|
30 |
const indeterminate =
|
31 |
checkedList.length > 0 && checkedList.length < list.length;
|
32 |
|
33 |
+
const onChange = useCallback(
|
34 |
+
(list: CheckboxValueType[]) => {
|
35 |
+
setCheckedList(list as string[]);
|
36 |
+
},
|
37 |
+
[setCheckedList],
|
38 |
+
);
|
39 |
|
40 |
const onCheckAllChange: CheckboxProps['onChange'] = useCallback(
|
41 |
(e: CheckboxChangeEvent) => {
|
42 |
setCheckedList(e.target.checked ? ids : []);
|
43 |
},
|
44 |
+
[ids, setCheckedList],
|
45 |
);
|
46 |
|
47 |
useEffect(() => {
|
48 |
setCheckedList(ids);
|
49 |
+
}, [ids, setCheckedList]);
|
50 |
|
51 |
return (
|
52 |
<Sider className={styles.searchSide} theme={'light'} width={240}>
|
|
|
56 |
onChange={onCheckAllChange}
|
57 |
checked={checkAll}
|
58 |
>
|
59 |
+
All
|
60 |
</Checkbox>
|
61 |
<Checkbox.Group
|
62 |
className={styles.checkGroup}
|
web/src/services/chat-service.ts
CHANGED
@@ -25,6 +25,7 @@ const {
|
|
25 |
tts,
|
26 |
ask,
|
27 |
mindmap,
|
|
|
28 |
} = api;
|
29 |
|
30 |
const methods = {
|
@@ -116,6 +117,10 @@ const methods = {
|
|
116 |
url: mindmap,
|
117 |
method: 'post',
|
118 |
},
|
|
|
|
|
|
|
|
|
119 |
} as const;
|
120 |
|
121 |
const chatService = registerServer<keyof typeof methods>(methods, request);
|
|
|
25 |
tts,
|
26 |
ask,
|
27 |
mindmap,
|
28 |
+
getRelatedQuestions,
|
29 |
} = api;
|
30 |
|
31 |
const methods = {
|
|
|
117 |
url: mindmap,
|
118 |
method: 'post',
|
119 |
},
|
120 |
+
getRelatedQuestions: {
|
121 |
+
url: getRelatedQuestions,
|
122 |
+
method: 'post',
|
123 |
+
},
|
124 |
} as const;
|
125 |
|
126 |
const chatService = registerServer<keyof typeof methods>(methods, request);
|
web/src/utils/api.ts
CHANGED
@@ -68,6 +68,7 @@ export default {
|
|
68 |
tts: `${api_host}/conversation/tts`,
|
69 |
ask: `${api_host}/conversation/ask`,
|
70 |
mindmap: `${api_host}/conversation/mindmap`,
|
|
|
71 |
// chat for external
|
72 |
createToken: `${api_host}/api/new_token`,
|
73 |
listToken: `${api_host}/api/token_list`,
|
|
|
68 |
tts: `${api_host}/conversation/tts`,
|
69 |
ask: `${api_host}/conversation/ask`,
|
70 |
mindmap: `${api_host}/conversation/mindmap`,
|
71 |
+
getRelatedQuestions: `${api_host}/conversation/related_questions`,
|
72 |
// chat for external
|
73 |
createToken: `${api_host}/api/new_token`,
|
74 |
listToken: `${api_host}/api/token_list`,
|