mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Display the knowledge graph on the knowledge base page #4543 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,75 +0,0 @@
|
||||
import IndentedTree from '@/components/indented-tree/indented-tree';
|
||||
import { useFetchKnowledgeGraph } from '@/hooks/chunk-hooks';
|
||||
import { useGetKnowledgeSearchParams } from '@/hooks/route-hook';
|
||||
import { Flex, Modal, Segmented } from 'antd';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ForceGraph from './force-graph';
|
||||
import styles from './index.less';
|
||||
import { isDataExist } from './util';
|
||||
|
||||
enum SegmentedValue {
|
||||
Graph = 'Graph',
|
||||
Mind = 'Mind',
|
||||
}
|
||||
|
||||
const KnowledgeGraphModal: React.FC = () => {
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const { documentId } = useGetKnowledgeSearchParams();
|
||||
const { data } = useFetchKnowledgeGraph(documentId);
|
||||
const [value, setValue] = useState<SegmentedValue>(SegmentedValue.Graph);
|
||||
const { t } = useTranslation();
|
||||
|
||||
const options = useMemo(() => {
|
||||
return [
|
||||
{ value: SegmentedValue.Graph, label: t('chunk.graph') },
|
||||
{ value: SegmentedValue.Mind, label: t('chunk.mind') },
|
||||
];
|
||||
}, [t]);
|
||||
|
||||
const handleOk = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isDataExist(data)) {
|
||||
setIsModalOpen(true);
|
||||
}
|
||||
}, [setIsModalOpen, data]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={t('chunk.graph')}
|
||||
open={isModalOpen}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
width={'90vw'}
|
||||
footer={null}
|
||||
>
|
||||
<section className={styles.modalContainer}>
|
||||
<Flex justify="end">
|
||||
<Segmented
|
||||
size="large"
|
||||
options={options}
|
||||
value={value}
|
||||
onChange={(v) => setValue(v as SegmentedValue)}
|
||||
/>
|
||||
</Flex>
|
||||
<ForceGraph
|
||||
data={data?.data?.graph}
|
||||
show={value === SegmentedValue.Graph}
|
||||
></ForceGraph>
|
||||
<IndentedTree
|
||||
data={data?.data?.mind_map}
|
||||
show={value === SegmentedValue.Mind}
|
||||
></IndentedTree>
|
||||
</section>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default KnowledgeGraphModal;
|
||||
@ -8,7 +8,6 @@ import ChunkCard from './components/chunk-card';
|
||||
import CreatingModal from './components/chunk-creating-modal';
|
||||
import ChunkToolBar from './components/chunk-toolbar';
|
||||
import DocumentPreview from './components/document-preview/preview';
|
||||
import KnowledgeGraphModal from './components/knowledge-graph/modal';
|
||||
import {
|
||||
useChangeChunkTextMode,
|
||||
useDeleteChunkByIds,
|
||||
@ -196,7 +195,6 @@ const Chunk = () => {
|
||||
parserId={documentInfo.parser_id}
|
||||
/>
|
||||
)}
|
||||
<KnowledgeGraphModal></KnowledgeGraphModal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -39,7 +39,12 @@ const ParsingActionCell = ({
|
||||
|
||||
const onRmDocument = () => {
|
||||
if (!isRunning) {
|
||||
showDeleteConfirm({ onOk: () => removeDocument([documentId]) });
|
||||
showDeleteConfirm({
|
||||
onOk: () => removeDocument([documentId]),
|
||||
content: record?.parser_config?.graphrag?.use_graphrag
|
||||
? t('deleteDocumentConfirmContent')
|
||||
: '',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ const ForceGraph = ({ data, show }: IProps) => {
|
||||
if (!isEmpty(data)) {
|
||||
const graphData = data;
|
||||
const mi = buildNodesAndCombos(graphData.nodes);
|
||||
return { edges: graphData.links, ...mi };
|
||||
return { edges: graphData.edges, ...mi };
|
||||
}
|
||||
return { nodes: [], edges: [] };
|
||||
}, [data]);
|
||||
@ -130,8 +130,8 @@ const ForceGraph = ({ data, show }: IProps) => {
|
||||
ref={containerRef}
|
||||
className={styles.forceContainer}
|
||||
style={{
|
||||
width: '90vw',
|
||||
height: '80vh',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: show ? 'block' : 'none',
|
||||
}}
|
||||
/>
|
||||
@ -3,8 +3,3 @@
|
||||
border-radius: 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.modalContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
import { useFetchKnowledgeGraph } from '@/hooks/knowledge-hooks';
|
||||
import React from 'react';
|
||||
import ForceGraph from './force-graph';
|
||||
|
||||
const KnowledgeGraphModal: React.FC = () => {
|
||||
const { data } = useFetchKnowledgeGraph();
|
||||
|
||||
return (
|
||||
<section className={'w-full h-full'}>
|
||||
<ForceGraph data={data?.graph} show></ForceGraph>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default KnowledgeGraphModal;
|
||||
@ -13,6 +13,9 @@ import ParseConfiguration, {
|
||||
showRaptorParseConfiguration,
|
||||
showTagItems,
|
||||
} from '@/components/parse-configuration';
|
||||
import GraphRagItems, {
|
||||
showGraphRagItems,
|
||||
} from '@/components/parse-configuration/graph-rag-items';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { useHandleChunkMethodSelectChange } from '@/hooks/logic-hooks';
|
||||
import { normFile } from '@/utils/file-util';
|
||||
@ -149,6 +152,8 @@ const ConfigurationForm = ({ form }: { form: FormInstance }) => {
|
||||
<ParseConfiguration></ParseConfiguration>
|
||||
)}
|
||||
|
||||
{showGraphRagItems(parserId) && <GraphRagItems></GraphRagItems>}
|
||||
|
||||
{showTagItems(parserId) && <TagItems></TagItems>}
|
||||
</>
|
||||
);
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { ReactComponent as ConfigurationIcon } from '@/assets/svg/knowledge-configration.svg';
|
||||
import { ReactComponent as DatasetIcon } from '@/assets/svg/knowledge-dataset.svg';
|
||||
import { ReactComponent as TestingIcon } from '@/assets/svg/knowledge-testing.svg';
|
||||
import { useFetchKnowledgeBaseConfiguration } from '@/hooks/knowledge-hooks';
|
||||
import {
|
||||
useFetchKnowledgeBaseConfiguration,
|
||||
useFetchKnowledgeGraph,
|
||||
} from '@/hooks/knowledge-hooks';
|
||||
import {
|
||||
useGetKnowledgeSearchParams,
|
||||
useSecondPathName,
|
||||
@ -14,6 +17,8 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'umi';
|
||||
import { KnowledgeRouteKey } from '../../constant';
|
||||
|
||||
import { isEmpty } from 'lodash';
|
||||
import { GitGraph } from 'lucide-react';
|
||||
import styles from './index.less';
|
||||
|
||||
const KnowledgeSidebar = () => {
|
||||
@ -30,6 +35,8 @@ const KnowledgeSidebar = () => {
|
||||
navigate(`/knowledge/${e.key}?id=${knowledgeId}`);
|
||||
};
|
||||
|
||||
const { data } = useFetchKnowledgeGraph();
|
||||
|
||||
type MenuItem = Required<MenuProps>['items'][number];
|
||||
|
||||
const getItem = useCallback(
|
||||
@ -54,7 +61,7 @@ const KnowledgeSidebar = () => {
|
||||
);
|
||||
|
||||
const items: MenuItem[] = useMemo(() => {
|
||||
return [
|
||||
const list = [
|
||||
getItem(
|
||||
KnowledgeRouteKey.Dataset, // TODO: Change icon color when selected
|
||||
KnowledgeRouteKey.Dataset,
|
||||
@ -71,7 +78,19 @@ const KnowledgeSidebar = () => {
|
||||
<ConfigurationIcon />,
|
||||
),
|
||||
];
|
||||
}, [getItem]);
|
||||
|
||||
if (!isEmpty(data.graph)) {
|
||||
list.push(
|
||||
getItem(
|
||||
KnowledgeRouteKey.KnowledgeGraph,
|
||||
KnowledgeRouteKey.KnowledgeGraph,
|
||||
<GitGraph />,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return list;
|
||||
}, [data, getItem]);
|
||||
|
||||
useEffect(() => {
|
||||
if (windowWidth.width > 957) {
|
||||
@ -81,7 +100,6 @@ const KnowledgeSidebar = () => {
|
||||
}
|
||||
}, [windowWidth.width]);
|
||||
|
||||
// 标记一下
|
||||
useEffect(() => {
|
||||
const widthSize = () => {
|
||||
const width = getWidth();
|
||||
|
||||
@ -6,6 +6,7 @@ import { Button, Card, Divider, Flex, Form, Input } from 'antd';
|
||||
import { FormInstance } from 'antd/lib';
|
||||
import { LabelWordCloud } from './label-word-cloud';
|
||||
|
||||
import { UseKnowledgeGraphItem } from '@/components/use-knowledge-graph-item';
|
||||
import styles from './index.less';
|
||||
|
||||
type FieldType = {
|
||||
@ -38,6 +39,7 @@ const TestingControl = ({ form, handleTesting }: IProps) => {
|
||||
<Form name="testing" layout="vertical" form={form}>
|
||||
<SimilaritySlider isTooltipShown></SimilaritySlider>
|
||||
<Rerank></Rerank>
|
||||
<UseKnowledgeGraphItem filedName={['use_kg']}></UseKnowledgeGraphItem>
|
||||
<Card size="small" title={t('testText')}>
|
||||
<Form.Item<FieldType>
|
||||
name={'question'}
|
||||
|
||||
@ -30,6 +30,7 @@ import { EditableCell, EditableRow } from './editable-cell';
|
||||
|
||||
import Rerank from '@/components/rerank';
|
||||
import TopNItem from '@/components/top-n-item';
|
||||
import { UseKnowledgeGraphItem } from '@/components/use-knowledge-graph-item';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { useSelectPromptConfigParameters } from '../hooks';
|
||||
import styles from './index.less';
|
||||
@ -168,6 +169,9 @@ const PromptEngine = (
|
||||
>
|
||||
<Switch></Switch>
|
||||
</Form.Item>
|
||||
<UseKnowledgeGraphItem
|
||||
filedName={['prompt_config', 'use_kg']}
|
||||
></UseKnowledgeGraphItem>
|
||||
<Rerank></Rerank>
|
||||
<section className={classNames(styles.variableContainer)}>
|
||||
<Row align={'middle'} justify="end">
|
||||
|
||||
@ -41,7 +41,7 @@ const KnowledgeCard = ({ item }: IProps) => {
|
||||
return (
|
||||
<Badge.Ribbon
|
||||
text={item?.nickname}
|
||||
color={userInfo.nickname === item.nickname ? '#1677ff' : 'pink'}
|
||||
color={userInfo?.nickname === item?.nickname ? '#1677ff' : 'pink'}
|
||||
className={classNames(styles.ribbon, {
|
||||
[styles.hideRibbon]: item.permission !== 'team',
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user