瀏覽代碼

Feat: Display the knowledge graph on the knowledge base page #4543 (#4587)

### 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)
tags/v0.16.0
balibabu 9 月之前
父節點
當前提交
c5c0dd2da0
No account linked to committer's email address
共有 31 個文件被更改,包括 346 次插入133 次删除
  1. 4
    0
      web/src/components/chunk-method-modal/index.tsx
  2. 10
    4
      web/src/components/entity-types-item.tsx
  3. 4
    5
      web/src/components/indented-tree/modal.tsx
  4. 22
    4
      web/src/components/layout-recognize.tsx
  5. 120
    0
      web/src/components/parse-configuration/graph-rag-items.tsx
  6. 21
    0
      web/src/components/use-knowledge-graph-item.tsx
  7. 1
    0
      web/src/constants/knowledge.ts
  8. 0
    20
      web/src/hooks/chunk-hooks.ts
  9. 4
    3
      web/src/hooks/common-hooks.tsx
  10. 19
    0
      web/src/hooks/knowledge-hooks.ts
  11. 9
    0
      web/src/interfaces/database/document.ts
  12. 6
    0
      web/src/interfaces/database/knowledge.ts
  13. 20
    3
      web/src/locales/en.ts
  14. 19
    1
      web/src/locales/zh-traditional.ts
  15. 19
    2
      web/src/locales/zh.ts
  16. 0
    75
      web/src/pages/add-knowledge/components/knowledge-chunk/components/knowledge-graph/modal.tsx
  17. 0
    2
      web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx
  18. 6
    1
      web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx
  19. 0
    0
      web/src/pages/add-knowledge/components/knowledge-graph/constant.ts
  20. 3
    3
      web/src/pages/add-knowledge/components/knowledge-graph/force-graph.tsx
  21. 0
    5
      web/src/pages/add-knowledge/components/knowledge-graph/index.less
  22. 15
    0
      web/src/pages/add-knowledge/components/knowledge-graph/index.tsx
  23. 0
    0
      web/src/pages/add-knowledge/components/knowledge-graph/util.ts
  24. 5
    0
      web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx
  25. 22
    4
      web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx
  26. 2
    0
      web/src/pages/add-knowledge/components/knowledge-testing/testing-control/index.tsx
  27. 4
    0
      web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx
  28. 1
    1
      web/src/pages/knowledge/knowledge-card/index.tsx
  29. 4
    0
      web/src/routes.ts
  30. 4
    0
      web/src/services/knowledge-service.ts
  31. 2
    0
      web/src/utils/api.ts

+ 4
- 0
web/src/components/chunk-method-modal/index.tsx 查看文件

@@ -30,6 +30,9 @@ import LayoutRecognize from '../layout-recognize';
import ParseConfiguration, {
showRaptorParseConfiguration,
} from '../parse-configuration';
import GraphRagItems, {
showGraphRagItems,
} from '../parse-configuration/graph-rag-items';
import styles from './index.less';

interface IProps extends Omit<IModalManagerChildrenProps, 'showModal'> {
@@ -296,6 +299,7 @@ const ChunkMethodModal: React.FC<IProps> = ({
{showRaptorParseConfiguration(selectedTag) && (
<ParseConfiguration></ParseConfiguration>
)}
{showGraphRagItems(selectedTag) && <GraphRagItems></GraphRagItems>}
{showEntityTypes && <EntityTypesItem></EntityTypesItem>}
</Form>
</Modal>

+ 10
- 4
web/src/components/entity-types-item.tsx 查看文件

@@ -5,16 +5,22 @@ import EditTag from './edit-tag';
const initialEntityTypes = [
'organization',
'person',
'location',
'geo',
'event',
'time',
'category',
];

const EntityTypesItem = () => {
type IProps = {
field?: string[];
};

const EntityTypesItem = ({
field = ['parser_config', 'entity_types'],
}: IProps) => {
const { t } = useTranslate('knowledgeConfiguration');
return (
<Form.Item
name={['parser_config', 'entity_types']}
name={field}
label={t('entityTypes')}
rules={[{ required: true }]}
initialValue={initialEntityTypes}

+ 4
- 5
web/src/components/indented-tree/modal.tsx 查看文件

@@ -1,16 +1,15 @@
import { useFetchKnowledgeGraph } from '@/hooks/chunk-hooks';
import { Modal } from 'antd';
import { useTranslation } from 'react-i18next';
import IndentedTree from './indented-tree';

import { useFetchKnowledgeGraph } from '@/hooks/knowledge-hooks';
import { IModalProps } from '@/interfaces/common';
import { Modal } from 'antd';

const IndentedTreeModal = ({
documentId,
visible,
hideModal,
}: IModalProps<any> & { documentId: string }) => {
const { data } = useFetchKnowledgeGraph(documentId);
const { data } = useFetchKnowledgeGraph();
const { t } = useTranslation();

return (
@@ -22,7 +21,7 @@ const IndentedTreeModal = ({
footer={null}
>
<section>
<IndentedTree data={data?.data?.mind_map} show></IndentedTree>
<IndentedTree data={data?.mind_map} show></IndentedTree>
</section>
</Modal>
);

+ 22
- 4
web/src/components/layout-recognize.tsx 查看文件

@@ -1,17 +1,35 @@
import { LlmModelType } from '@/constants/knowledge';
import { useTranslate } from '@/hooks/common-hooks';
import { Form, Switch } from 'antd';
import { useSelectLlmOptionsByModelType } from '@/hooks/llm-hooks';
import { Form, Select } from 'antd';
import { useMemo } from 'react';

const enum DocumentType {
DeepDOC = 'DeepDOC',
PlainText = 'Plain Text',
}

const LayoutRecognize = () => {
const { t } = useTranslate('knowledgeDetails');
const allOptions = useSelectLlmOptionsByModelType();

const options = useMemo(() => {
const list = [DocumentType.DeepDOC, DocumentType.PlainText].map((x) => ({
label: x,
value: x,
}));

return [...list, ...allOptions[LlmModelType.Image2text]];
}, [allOptions]);

return (
<Form.Item
name={['parser_config', 'layout_recognize']}
label={t('layoutRecognize')}
initialValue={true}
valuePropName="checked"
initialValue={DocumentType.DeepDOC}
tooltip={t('layoutRecognizeTip')}
>
<Switch />
<Select options={options} />
</Form.Item>
);
};

+ 120
- 0
web/src/components/parse-configuration/graph-rag-items.tsx 查看文件

@@ -0,0 +1,120 @@
import { useTranslate } from '@/hooks/common-hooks';
import { Divider, Form, Select, Switch } from 'antd';
import { upperFirst } from 'lodash';
import { useCallback, useMemo } from 'react';
import EntityTypesItem from '../entity-types-item';

const excludedTagParseMethods = ['table', 'knowledge_graph', 'tag'];

export const showTagItems = (parserId: string) => {
return !excludedTagParseMethods.includes(parserId);
};

const enum MethodValue {
General = 'general',
Light = 'light',
}

export const excludedParseMethods = [
'table',
'resume',
'picture',
'knowledge_graph',
'qa',
'tag',
];

export const showGraphRagItems = (parserId: string) => {
return !excludedParseMethods.includes(parserId);
};

// The three types "table", "resume" and "one" do not display this configuration.
const GraphRagItems = () => {
const { t } = useTranslate('knowledgeConfiguration');

const methodOptions = useMemo(() => {
return [MethodValue.Light, MethodValue.General].map((x) => ({
value: x,
label: upperFirst(x),
}));
}, []);

const renderWideTooltip = useCallback(
(title: React.ReactNode | string) => {
return {
title: typeof title === 'string' ? t(title) : title,
overlayInnerStyle: { width: '50vw' },
};
},
[t],
);

return (
<>
<Divider></Divider>
<Form.Item
name={['parser_config', 'graphrag', 'use_graphrag']}
label={t('useGraphRag')}
initialValue={false}
valuePropName="checked"
tooltip={renderWideTooltip('useGraphRagTip')}
>
<Switch />
</Form.Item>
<Form.Item
shouldUpdate={(prevValues, curValues) =>
prevValues.parser_config.graphrag.use_graphrag !==
curValues.parser_config.graphrag.use_graphrag
}
>
{({ getFieldValue }) => {
const useRaptor = getFieldValue([
'parser_config',
'graphrag',
'use_graphrag',
]);

return (
useRaptor && (
<>
<EntityTypesItem
field={['parser_config', 'graphrag', 'entity_types']}
></EntityTypesItem>
<Form.Item
name={['parser_config', 'graphrag', 'method']}
label={t('graphRagMethod')}
tooltip={renderWideTooltip(
<div
dangerouslySetInnerHTML={{
__html: t('graphRagMethodTip'),
}}
></div>,
)}
initialValue={MethodValue.Light}
>
<Select options={methodOptions} />
</Form.Item>
<Form.Item
name={['parser_config', 'graphrag', 'resolution']}
label={t('resolution')}
tooltip={renderWideTooltip('resolutionTip')}
>
<Switch />
</Form.Item>
<Form.Item
name={['parser_config', 'graphrag', 'community']}
label={t('community')}
tooltip={renderWideTooltip('communityTip')}
>
<Switch />
</Form.Item>
</>
)
);
}}
</Form.Item>
</>
);
};

export default GraphRagItems;

+ 21
- 0
web/src/components/use-knowledge-graph-item.tsx 查看文件

@@ -0,0 +1,21 @@
import { Form, Switch } from 'antd';
import { useTranslation } from 'react-i18next';

type IProps = {
filedName: string[];
};

export function UseKnowledgeGraphItem({ filedName }: IProps) {
const { t } = useTranslation();

return (
<Form.Item
label={t('chat.useKnowledgeGraph')}
tooltip={t('chat.useKnowledgeGraphTip')}
name={filedName}
initialValue={false}
>
<Switch></Switch>
</Form.Item>
);
}

+ 1
- 0
web/src/constants/knowledge.ts 查看文件

@@ -2,6 +2,7 @@ export enum KnowledgeRouteKey {
Dataset = 'dataset',
Testing = 'testing',
Configuration = 'configuration',
KnowledgeGraph = 'knowledgeGraph',
}

export const DatasetBaseKey = 'dataset';

+ 0
- 20
web/src/hooks/chunk-hooks.ts 查看文件

@@ -206,23 +206,3 @@ export const useFetchChunk = (chunkId?: string): ResponseType<any> => {

return data;
};

export const useFetchKnowledgeGraph = (
documentId: string,
): ResponseType<any> => {
const { data } = useQuery({
queryKey: ['fetchKnowledgeGraph', documentId],
initialData: true,
enabled: !!documentId,
gcTime: 0,
queryFn: async () => {
const data = await kbService.knowledge_graph({
doc_id: documentId,
});

return data;
},
});

return data;
};

+ 4
- 3
web/src/hooks/common-hooks.tsx 查看文件

@@ -1,7 +1,7 @@
import { ExclamationCircleFilled } from '@ant-design/icons';
import { App } from 'antd';
import isEqual from 'lodash/isEqual';
import { useCallback, useEffect, useRef, useState } from 'react';
import { ReactNode, useCallback, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';

export const useSetModalState = () => {
@@ -78,6 +78,7 @@ export function useDynamicSVGImport(

interface IProps {
title?: string;
content?: ReactNode;
onOk?: (...args: any[]) => any;
onCancel?: (...args: any[]) => any;
}
@@ -87,12 +88,12 @@ export const useShowDeleteConfirm = () => {
const { t } = useTranslation();

const showDeleteConfirm = useCallback(
({ title, onOk, onCancel }: IProps): Promise<number> => {
({ title, content, onOk, onCancel }: IProps): Promise<number> => {
return new Promise((resolve, reject) => {
modal.confirm({
title: title ?? t('common.deleteModalTitle'),
icon: <ExclamationCircleFilled />,
// content: 'Some descriptions',
content,
okText: t('common.ok'),
okType: 'danger',
cancelText: t('common.cancel'),

+ 19
- 0
web/src/hooks/knowledge-hooks.ts 查看文件

@@ -1,11 +1,13 @@
import { ResponsePostType } from '@/interfaces/database/base';
import {
IKnowledge,
IKnowledgeGraph,
IRenameTag,
ITestingResult,
} from '@/interfaces/database/knowledge';
import i18n from '@/locales/config';
import kbService, {
getKnowledgeGraph,
listTag,
removeTag,
renameTag,
@@ -373,3 +375,20 @@ export const useFetchTagListByKnowledgeIds = () => {
};

//#endregion

export function useFetchKnowledgeGraph() {
const knowledgeBaseId = useKnowledgeBaseId();

const { data, isFetching: loading } = useQuery<IKnowledgeGraph>({
queryKey: ['fetchKnowledgeGraph', knowledgeBaseId],
initialData: { graph: {}, mind_map: {} } as IKnowledgeGraph,
enabled: !!knowledgeBaseId,
gcTime: 0,
queryFn: async () => {
const { data } = await getKnowledgeGraph(knowledgeBaseId);
return data?.data;
},
});

return { data, loading };
}

+ 9
- 0
web/src/interfaces/database/document.ts 查看文件

@@ -33,8 +33,17 @@ export interface IParserConfig {
layout_recognize?: boolean;
pages: any[];
raptor?: Raptor;
graphrag?: GraphRag;
}

interface Raptor {
use_raptor: boolean;
}

interface GraphRag {
community?: boolean;
entity_types?: string[];
method?: string;
resolution?: boolean;
use_graphrag?: boolean;
}

+ 6
- 0
web/src/interfaces/database/knowledge.ts 查看文件

@@ -1,4 +1,5 @@
import { RunningStatus } from '@/constants/knowledge';
import { TreeData } from '@antv/g6/lib/types';

// knowledge base
export interface IKnowledge {
@@ -136,3 +137,8 @@ export interface ITestingResult {
}

export type IRenameTag = { fromTag: string; toTag: string };

export interface IKnowledgeGraph {
graph: Record<string, any>;
mind_map: TreeData;
}

+ 20
- 3
web/src/locales/en.ts 查看文件

@@ -86,6 +86,7 @@ export default {
testing: 'Retrieval testing',
files: 'files',
configuration: 'Configuration',
knowledgeGraph: 'Knowledge graph',
name: 'Name',
namePlaceholder: 'Please input name!',
doc: 'Docs',
@@ -137,7 +138,7 @@ export default {
fromMessage: 'Missing start page number',
toPlaceholder: 'to',
toMessage: 'Missing end page number (excluded)',
layoutRecognize: 'Layout recognition',
layoutRecognize: 'Layout recognition & OCR',
layoutRecognizeTip:
'Use visual models for layout analysis to better understand the structure of the document and effectively locate document titles, text blocks, images, and tables. If disabled, only the plain text in the PDF will be retrieved.',
taskPageSize: 'Task page size',
@@ -192,6 +193,8 @@ export default {
</ul>
`,
metaData: 'Meta data',
deleteDocumentConfirmContent:
'The document is associated with the knowledge graph. After deletion, the related node and relationship information will be deleted, but the graph will not be updated immediately. The update graph action is performed during the process of parsing the new document that carries the knowledge graph extraction task.',
},
knowledgeConfiguration: {
titleDescription:
@@ -363,6 +366,17 @@ This procedure will improve precision of retrieval by adding more information to
topnTags: 'Top-N Tags',
tags: 'Tags',
addTag: 'Add tag',
useGraphRag: 'Extract knowledge graph',
useGraphRagTip:
'After files being chunked, all the chunks will be used for knowlege graph generation which helps inference of multi-hop and complex problems a lot.',
graphRagMethod: 'Method',
graphRagMethodTip: `Light: the entity and relation extraction prompt is from GitHub - HKUDS/LightRAG: "LightRAG: Simple and Fast Retrieval-Augmented Generation"</br>
General: the entity and relation extraction prompt is from GitHub - microsoft/graphrag: A modular graph-based Retrieval-Augmented Generation (RAG) system`,
resolution: 'Entity resolution',
resolutionTip: `The resolution procedure would merge entities with the same meaning together which allows the graph conciser and more accurate. Entities as following should be merged: President Trump, Donald Trump, Donald J. Trump, Donald John Trump`,
community: 'Community reports generation',
communityTip:
'Chunks are clustered into hierarchical communities with entities and relationships connecting each segment up through higher levels of abstraction. We then use an LLM to generate a summary of each community, known as a community report. More: https://www.microsoft.com/en-us/research/blog/graphrag-improving-global-search-via-dynamic-community-selection/',
},
chunk: {
chunk: 'Chunk',
@@ -503,6 +517,9 @@ This procedure will improve precision of retrieval by adding more information to
'This optimizes user queries using context in a multi-round conversation. When enabled, it will consume additional LLM tokens.',
howUseId: 'How to use chat ID?',
description: 'Description of assistant',
useKnowledgeGraph: 'Use knowledge graph',
useKnowledgeGraphTip:
'It will retrieve descriptions of relevant entities,relations and community reports, which will enhance inference of multi-hop and complex question.',
},
setting: {
profile: 'Profile',
@@ -971,8 +988,8 @@ This procedure will improve precision of retrieval by adding more information to
notEmpty: 'Not empty',
},
switchLogicOperatorOptions: {
and: 'And',
or: 'Or',
and: 'AND',
or: 'OR',
},
operator: 'Operator',
value: 'Value',

+ 19
- 1
web/src/locales/zh-traditional.ts 查看文件

@@ -85,6 +85,7 @@ export default {
dataset: '數據集',
testing: '檢索測試',
configuration: '配置',
knowledgeGraph: '知識圖譜',
files: '文件',
name: '名稱',
namePlaceholder: '請輸入名稱',
@@ -135,7 +136,7 @@ export default {
fromMessage: '缺少起始頁碼',
toPlaceholder: '到',
toMessage: '缺少結束頁碼(不包含)',
layoutRecognize: '佈局識別',
layoutRecognize: '佈局識別和 OCR',
layoutRecognizeTip:
'使用視覺模型進行佈局分析,以更好地識別文檔結構,找到標題、文本塊、圖像和表格的位置。如果沒有此功能,則只能獲取 PDF 的純文本。',
taskPageSize: '任務頁面大小',
@@ -187,6 +188,9 @@ export default {
<li>這是區塊內容....</li>
</ul>
`,
metaData: '元資料',
deleteDocumentConfirmContent:
'該文件與知識圖譜相關聯。刪除後,相關節點和關係資訊將被刪除,但圖不會立即更新。更新圖動作是在解析承載知識圖譜提取任務的新文件的過程中執行的。 ',
},
knowledgeConfiguration: {
titleDescription: '在這裡更新您的知識庫詳細信息,尤其是解析方法。',
@@ -346,6 +350,17 @@ export default {
`,
tags: '標籤',
addTag: '增加標籤',
useGraphRag: '提取知識圖譜',
useGraphRagTip:
'文件分塊後,所有區塊將用於知識圖譜生成,這對多跳和複雜問題的推理有很大幫助。',
graphRagMethod: '方法',
graphRagMethodTip: `Light:實體和關係提取提示來自 GitHub - HKUDS/LightRAG:“LightRAG:簡單快速的檢索增強生成”<br>
一般:實體和關係擷取提示來自 GitHub - microsoft/graphrag:基於模組化圖形的檢索增強生成 (RAG) 系統,`,
resolution: '實體歸一化',
resolutionTip: `解析過程會將具有相同意義的實體合併在一起,使知識圖譜更簡潔、更準確。應合併以下實體:川普總統、唐納德·川普、唐納德·J·川普、唐納德·約翰·川普`,
community: '社群報告生成',
communityTip:
'區塊被聚集成層次化的社區,其中實體和關係透過更高層次的抽象將每個部分連接起來。然後,我們使用 LLM 產生每個社群的摘要,即社群報告。更多資訊:https://www.microsoft.com/en-us/research/blog/graphrag-improving-global-search-via-dynamic-community-selection/',
},
chunk: {
chunk: '解析塊',
@@ -486,6 +501,9 @@ export default {
'在多輪對話的中,對去知識庫查詢的問題進行最佳化。會呼叫大模型額外消耗token。',
howUseId: '如何使用聊天ID?',
description: '助理描述',
useKnowledgeGraph: '使用知識圖譜',
useKnowledgeGraph提示:
'它將檢索相關實體、關係和社區報告的描述,這將增強多跳和複雜問題的推理。',
},
setting: {
profile: '概述',

+ 19
- 2
web/src/locales/zh.ts 查看文件

@@ -85,6 +85,7 @@ export default {
dataset: '数据集',
testing: '检索测试',
configuration: '配置',
knowledgeGraph: '知识图谱',
files: '文件',
name: '名称',
namePlaceholder: '请输入名称',
@@ -135,7 +136,7 @@ export default {
fromMessage: '缺少起始页码',
toPlaceholder: '到',
toMessage: '缺少结束页码(不包含)',
layoutRecognize: '布局识别',
layoutRecognize: '布局识别和 OCR',
layoutRecognizeTip:
'使用视觉模型进行布局分析,以更好地识别文档结构,找到标题、文本块、图像和表格的位置。 如果没有此功能,则只能获取 PDF 的纯文本。',
taskPageSize: '任务页面大小',
@@ -188,7 +189,9 @@ export default {
<li> 这是块内容....</li>
</ul>
`,
metaData: '元資料',
metaData: '元数据',
deleteDocumentConfirmContent:
'该文档与知识图谱相关联。删除后,相关节点和关系信息将被删除,但图不会立即更新。更新图动作是在解析承载知识图谱提取任务的新文档的过程中执行的。',
},
knowledgeConfiguration: {
titleDescription: '在这里更新您的知识库详细信息,尤其是解析方法。',
@@ -364,6 +367,17 @@ export default {
`,
tags: '标签',
addTag: '增加标签',
useGraphRag: '提取知识图谱',
useGraphRagTip:
'文件分块后,所有块将用于知识图谱生成,这对多跳和复杂问题的推理大有帮助。',
graphRagMethod: '方法',
graphRagMethodTip: `Light:实体和关系提取提示来自 GitHub - HKUDS/LightRAG:“LightRAG:简单快速的检索增强生成”<br>
General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于图形的模块化检索增强生成 (RAG) 系统`,
resolution: '实体归一化',
resolutionTip: `解析过程会将具有相同含义的实体合并在一起,从而使知识图谱更简洁、更准确。应合并以下实体:特朗普总统、唐纳德·特朗普、唐纳德·J·特朗普、唐纳德·约翰·特朗普`,
community: '社区报告生成',
communityTip:
'区块被聚集成层次化的社区,实体和关系通过更高抽象层次将每个部分连接起来。然后,我们使用 LLM 生成每个社区的摘要,称为社区报告。更多信息:https://www.microsoft.com/en-us/research/blog/graphrag-improving-global-search-via-dynamic-community-selection/',
},
chunk: {
chunk: '解析块',
@@ -504,6 +518,9 @@ export default {
'在多轮对话的中,对去知识库查询的问题进行优化。会调用大模型额外消耗token。',
howUseId: '如何使用聊天ID?',
description: '助理描述',
useKnowledgeGraph: '使用知识图谱',
useKnowledgeGraphTip:
'它将检索相关实体、关系和社区报告的描述,这将增强多跳和复杂问题的推理。',
},
setting: {
profile: '概要',

+ 0
- 75
web/src/pages/add-knowledge/components/knowledge-chunk/components/knowledge-graph/modal.tsx 查看文件

@@ -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;

+ 0
- 2
web/src/pages/add-knowledge/components/knowledge-chunk/index.tsx 查看文件

@@ -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>
</>
);
};

+ 6
- 1
web/src/pages/add-knowledge/components/knowledge-file/parsing-action-cell/index.tsx 查看文件

@@ -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')
: '',
});
}
};


web/src/pages/add-knowledge/components/knowledge-chunk/components/knowledge-graph/constant.ts → web/src/pages/add-knowledge/components/knowledge-graph/constant.ts 查看文件


web/src/pages/add-knowledge/components/knowledge-chunk/components/knowledge-graph/force-graph.tsx → web/src/pages/add-knowledge/components/knowledge-graph/force-graph.tsx 查看文件

@@ -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',
}}
/>

web/src/pages/add-knowledge/components/knowledge-chunk/components/knowledge-graph/index.less → web/src/pages/add-knowledge/components/knowledge-graph/index.less 查看文件

@@ -3,8 +3,3 @@
border-radius: 10px !important;
}
}

.modalContainer {
width: 100%;
height: 100%;
}

+ 15
- 0
web/src/pages/add-knowledge/components/knowledge-graph/index.tsx 查看文件

@@ -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;

web/src/pages/add-knowledge/components/knowledge-chunk/components/knowledge-graph/util.ts → web/src/pages/add-knowledge/components/knowledge-graph/util.ts 查看文件


+ 5
- 0
web/src/pages/add-knowledge/components/knowledge-setting/configuration.tsx 查看文件

@@ -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>}
</>
);

+ 22
- 4
web/src/pages/add-knowledge/components/knowledge-sidebar/index.tsx 查看文件

@@ -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();

+ 2
- 0
web/src/pages/add-knowledge/components/knowledge-testing/testing-control/index.tsx 查看文件

@@ -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'}

+ 4
- 0
web/src/pages/chat/chat-configuration-modal/prompt-engine.tsx 查看文件

@@ -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">

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

@@ -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',
})}

+ 4
- 0
web/src/routes.ts 查看文件

@@ -66,6 +66,10 @@ const routes = [
path: '/knowledge/testing',
component: '@/pages/add-knowledge/components/knowledge-testing',
},
{
path: '/knowledge/knowledgeGraph',
component: '@/pages/add-knowledge/components/knowledge-graph',
},
],
},
{

+ 4
- 0
web/src/services/knowledge-service.ts 查看文件

@@ -165,4 +165,8 @@ export const renameTag = (
{ fromTag, toTag }: IRenameTag,
) => post(api.renameTag(knowledgeId), { fromTag, toTag });

export function getKnowledgeGraph(knowledgeId: string) {
return request.get(api.getKnowledgeGraph(knowledgeId));
}

export default kbService;

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

@@ -36,6 +36,8 @@ export default {
update_kb: `${api_host}/kb/update`,
rm_kb: `${api_host}/kb/rm`,
get_kb_detail: `${api_host}/kb/detail`,
getKnowledgeGraph: (knowledgeId: string) =>
`${api_host}/kb/${knowledgeId}/knowledge_graph`,

// tags
listTag: (knowledgeId: string) => `${api_host}/kb/${knowledgeId}/tags`,

Loading…
取消
儲存