balibabu commited on
Commit
a432686
·
1 Parent(s): be98b1d

Feat: Modify the data structure of the chunk in the conversation #3909 (#3955)

Browse files

### What problem does this PR solve?

Feat: Modify the data structure of the chunk in the conversation #3909

### Type of change


- [x] New Feature (non-breaking change which adds functionality)

web/src/components/api-service/chat-api-key-modal/index.tsx CHANGED
@@ -63,7 +63,7 @@ const ChatApiKeyModal = ({
63
  <Button
64
  onClick={createToken}
65
  loading={creatingLoading}
66
- disabled={tokenList.length > 0}
67
  >
68
  {t('createNewKey')}
69
  </Button>
 
63
  <Button
64
  onClick={createToken}
65
  loading={creatingLoading}
66
+ disabled={tokenList?.length > 0}
67
  >
68
  {t('createNewKey')}
69
  </Button>
web/src/components/api-service/chat-overview-modal/api-content.tsx CHANGED
@@ -3,8 +3,7 @@ import apiDoc from '@parent/docs/references/http_api_reference.md';
3
  import MarkdownPreview from '@uiw/react-markdown-preview';
4
  import { Button, Card, Flex, Space } from 'antd';
5
  import ChatApiKeyModal from '../chat-api-key-modal';
6
- import EmbedModal from '../embed-modal';
7
- import { usePreviewChat, useShowEmbedModal } from '../hooks';
8
  import BackendServiceApi from './backend-service-api';
9
 
10
  const ApiContent = ({
@@ -22,10 +21,10 @@ const ApiContent = ({
22
  hideModal: hideApiKeyModal,
23
  showModal: showApiKeyModal,
24
  } = useSetModalState();
25
- const { embedVisible, hideEmbedModal, showEmbedModal, embedToken } =
26
- useShowEmbedModal(idKey, id);
27
 
28
- const { handlePreview } = usePreviewChat(idKey, id);
29
 
30
  return (
31
  <div>
@@ -36,7 +35,9 @@ const ApiContent = ({
36
  <Flex gap={8} vertical>
37
  <Space size={'middle'}>
38
  <Button onClick={handlePreview}>{t('preview')}</Button>
39
- <Button onClick={showEmbedModal}>{t('embedded')}</Button>
 
 
40
  </Space>
41
  </Flex>
42
  </Card>
@@ -50,13 +51,13 @@ const ApiContent = ({
50
  idKey={idKey}
51
  ></ChatApiKeyModal>
52
  )}
53
- {embedVisible && (
54
  <EmbedModal
55
  token={embedToken}
56
  visible={embedVisible}
57
  hideModal={hideEmbedModal}
58
  ></EmbedModal>
59
- )}
60
  </div>
61
  );
62
  };
 
3
  import MarkdownPreview from '@uiw/react-markdown-preview';
4
  import { Button, Card, Flex, Space } from 'antd';
5
  import ChatApiKeyModal from '../chat-api-key-modal';
6
+ import { usePreviewChat } from '../hooks';
 
7
  import BackendServiceApi from './backend-service-api';
8
 
9
  const ApiContent = ({
 
21
  hideModal: hideApiKeyModal,
22
  showModal: showApiKeyModal,
23
  } = useSetModalState();
24
+ // const { embedVisible, hideEmbedModal, showEmbedModal, embedToken } =
25
+ // useShowEmbedModal(idKey);
26
 
27
+ const { handlePreview } = usePreviewChat(idKey);
28
 
29
  return (
30
  <div>
 
35
  <Flex gap={8} vertical>
36
  <Space size={'middle'}>
37
  <Button onClick={handlePreview}>{t('preview')}</Button>
38
+ {/* <Button onClick={() => showEmbedModal(id)}>
39
+ {t('embedded')}
40
+ </Button> */}
41
  </Space>
42
  </Flex>
43
  </Card>
 
51
  idKey={idKey}
52
  ></ChatApiKeyModal>
53
  )}
54
+ {/* {embedVisible && (
55
  <EmbedModal
56
  token={embedToken}
57
  visible={embedVisible}
58
  hideModal={hideEmbedModal}
59
  ></EmbedModal>
60
+ )} */}
61
  </div>
62
  );
63
  };
web/src/components/api-service/embed-modal/index.less CHANGED
@@ -6,3 +6,7 @@
6
  padding: 10px;
7
  background-color: #ffffff09;
8
  }
 
 
 
 
 
6
  padding: 10px;
7
  background-color: #ffffff09;
8
  }
9
+
10
+ .id {
11
+ .linkText();
12
+ }
web/src/components/api-service/embed-modal/index.tsx CHANGED
@@ -1,21 +1,33 @@
1
  import CopyToClipboard from '@/components/copy-to-clipboard';
2
  import HightLightMarkdown from '@/components/highlight-markdown';
 
3
  import { useTranslate } from '@/hooks/common-hooks';
4
  import { IModalProps } from '@/interfaces/common';
5
- import { Card, Modal, Tabs, TabsProps } from 'antd';
 
6
  import styles from './index.less';
7
 
 
 
8
  const EmbedModal = ({
9
  visible,
10
  hideModal,
11
  token = '',
12
- }: IModalProps<any> & { token: string }) => {
 
 
 
 
 
 
 
 
13
  const { t } = useTranslate('chat');
14
 
15
  const text = `
16
  ~~~ html
17
  <iframe
18
- src="${location.origin}/chat/share?shared_id=${token}"
19
  style="width: 100%; height: 100%; min-height: 600px"
20
  frameborder="0"
21
  >
@@ -63,6 +75,23 @@ const EmbedModal = ({
63
  onCancel={hideModal}
64
  >
65
  <Tabs defaultActiveKey="1" items={items} onChange={onChange} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  </Modal>
67
  );
68
  };
 
1
  import CopyToClipboard from '@/components/copy-to-clipboard';
2
  import HightLightMarkdown from '@/components/highlight-markdown';
3
+ import { SharedFrom } from '@/constants/chat';
4
  import { useTranslate } from '@/hooks/common-hooks';
5
  import { IModalProps } from '@/interfaces/common';
6
+ import { Card, Modal, Tabs, TabsProps, Typography } from 'antd';
7
+
8
  import styles from './index.less';
9
 
10
+ const { Paragraph, Link } = Typography;
11
+
12
  const EmbedModal = ({
13
  visible,
14
  hideModal,
15
  token = '',
16
+ form,
17
+ beta = '',
18
+ isAgent,
19
+ }: IModalProps<any> & {
20
+ token: string;
21
+ form: SharedFrom;
22
+ beta: string;
23
+ isAgent: boolean;
24
+ }) => {
25
  const { t } = useTranslate('chat');
26
 
27
  const text = `
28
  ~~~ html
29
  <iframe
30
+ src="${location.origin}/chat/share?shared_id=${token}&from=${form}&auth=${beta}"
31
  style="width: 100%; height: 100%; min-height: 600px"
32
  frameborder="0"
33
  >
 
75
  onCancel={hideModal}
76
  >
77
  <Tabs defaultActiveKey="1" items={items} onChange={onChange} />
78
+ <div className="text-base font-medium mt-4 mb-1">
79
+ {t(isAgent ? 'flow' : 'chat', { keyPrefix: 'header' })}
80
+ <span className="ml-1 inline-block">ID</span>
81
+ </div>
82
+ <Paragraph copyable={{ text: token }} className={styles.id}>
83
+ {token}
84
+ </Paragraph>
85
+ <Link
86
+ href={
87
+ isAgent
88
+ ? 'https://ragflow.io/docs/dev/http_api_reference#create-session-with-an-agent'
89
+ : 'https://ragflow.io/docs/dev/http_api_reference#create-session-with-chat-assistant'
90
+ }
91
+ target="_blank"
92
+ >
93
+ {t('howUseId')}
94
+ </Link>
95
  </Modal>
96
  );
97
  };
web/src/components/api-service/hooks.ts CHANGED
@@ -6,6 +6,7 @@ import {
6
  } from '@/hooks/common-hooks';
7
  import {
8
  useCreateSystemToken,
 
9
  useFetchSystemTokenList,
10
  useRemoveSystemToken,
11
  } from '@/hooks/user-setting-hooks';
@@ -17,9 +18,7 @@ import { useCallback } from 'react';
17
  export const useOperateApiKey = (idKey: string, dialogId?: string) => {
18
  const { removeToken } = useRemoveSystemToken();
19
  const { createToken, loading: creatingLoading } = useCreateSystemToken();
20
- const { data: tokenList, loading: listLoading } = useFetchSystemTokenList({
21
- [idKey]: dialogId,
22
- });
23
 
24
  const showDeleteConfirm = useShowDeleteConfirm();
25
 
@@ -72,49 +71,68 @@ export const useShowTokenEmptyError = () => {
72
  return { showTokenEmptyError };
73
  };
74
 
 
 
 
 
 
 
 
 
 
75
  const getUrlWithToken = (token: string, from: string = 'chat') => {
76
  const { protocol, host } = window.location;
77
  return `${protocol}//${host}/chat/share?shared_id=${token}&from=${from}`;
78
  };
79
 
80
- const useFetchTokenListBeforeOtherStep = (idKey: string, dialogId?: string) => {
81
  const { showTokenEmptyError } = useShowTokenEmptyError();
 
 
 
 
82
 
83
- const { data: tokenList, refetch } = useFetchSystemTokenList({
84
- [idKey]: dialogId,
85
- });
86
 
87
- const token =
 
 
 
 
 
88
  Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
89
 
90
  const handleOperate = useCallback(async () => {
91
- const ret = await refetch();
92
- const list = ret.data;
93
  if (Array.isArray(list) && list.length > 0) {
 
 
 
 
94
  return list[0]?.token;
95
  } else {
96
  showTokenEmptyError();
97
  return false;
98
  }
99
- }, [showTokenEmptyError, refetch]);
100
 
101
  return {
102
  token,
 
103
  handleOperate,
104
  };
105
  };
106
 
107
- export const useShowEmbedModal = (idKey: string, dialogId?: string) => {
108
  const {
109
  visible: embedVisible,
110
  hideModal: hideEmbedModal,
111
  showModal: showEmbedModal,
112
  } = useSetModalState();
113
 
114
- const { handleOperate, token } = useFetchTokenListBeforeOtherStep(
115
- idKey,
116
- dialogId,
117
- );
118
 
119
  const handleShowEmbedModal = useCallback(async () => {
120
  const succeed = await handleOperate();
@@ -128,11 +146,12 @@ export const useShowEmbedModal = (idKey: string, dialogId?: string) => {
128
  hideEmbedModal,
129
  embedVisible,
130
  embedToken: token,
 
131
  };
132
  };
133
 
134
- export const usePreviewChat = (idKey: string, dialogId?: string) => {
135
- const { handleOperate } = useFetchTokenListBeforeOtherStep(idKey, dialogId);
136
 
137
  const open = useCallback(
138
  (t: string) => {
 
6
  } from '@/hooks/common-hooks';
7
  import {
8
  useCreateSystemToken,
9
+ useFetchManualSystemTokenList,
10
  useFetchSystemTokenList,
11
  useRemoveSystemToken,
12
  } from '@/hooks/user-setting-hooks';
 
18
  export const useOperateApiKey = (idKey: string, dialogId?: string) => {
19
  const { removeToken } = useRemoveSystemToken();
20
  const { createToken, loading: creatingLoading } = useCreateSystemToken();
21
+ const { data: tokenList, loading: listLoading } = useFetchSystemTokenList();
 
 
22
 
23
  const showDeleteConfirm = useShowDeleteConfirm();
24
 
 
71
  return { showTokenEmptyError };
72
  };
73
 
74
+ export const useShowBetaEmptyError = () => {
75
+ const { t } = useTranslate('chat');
76
+
77
+ const showBetaEmptyError = useCallback(() => {
78
+ message.error(t('betaError'));
79
+ }, [t]);
80
+ return { showBetaEmptyError };
81
+ };
82
+
83
  const getUrlWithToken = (token: string, from: string = 'chat') => {
84
  const { protocol, host } = window.location;
85
  return `${protocol}//${host}/chat/share?shared_id=${token}&from=${from}`;
86
  };
87
 
88
+ const useFetchTokenListBeforeOtherStep = () => {
89
  const { showTokenEmptyError } = useShowTokenEmptyError();
90
+ const { showBetaEmptyError } = useShowBetaEmptyError();
91
+
92
+ const { data: tokenList, fetchSystemTokenList } =
93
+ useFetchManualSystemTokenList();
94
 
95
+ let token = '',
96
+ beta = '';
 
97
 
98
+ if (Array.isArray(tokenList) && tokenList.length > 0) {
99
+ token = tokenList[0].token;
100
+ beta = tokenList[0].beta;
101
+ }
102
+
103
+ token =
104
  Array.isArray(tokenList) && tokenList.length > 0 ? tokenList[0].token : '';
105
 
106
  const handleOperate = useCallback(async () => {
107
+ const ret = await fetchSystemTokenList();
108
+ const list = ret;
109
  if (Array.isArray(list) && list.length > 0) {
110
+ if (!list[0].beta) {
111
+ showBetaEmptyError();
112
+ return false;
113
+ }
114
  return list[0]?.token;
115
  } else {
116
  showTokenEmptyError();
117
  return false;
118
  }
119
+ }, [fetchSystemTokenList, showBetaEmptyError, showTokenEmptyError]);
120
 
121
  return {
122
  token,
123
+ beta,
124
  handleOperate,
125
  };
126
  };
127
 
128
+ export const useShowEmbedModal = () => {
129
  const {
130
  visible: embedVisible,
131
  hideModal: hideEmbedModal,
132
  showModal: showEmbedModal,
133
  } = useSetModalState();
134
 
135
+ const { handleOperate, token, beta } = useFetchTokenListBeforeOtherStep();
 
 
 
136
 
137
  const handleShowEmbedModal = useCallback(async () => {
138
  const succeed = await handleOperate();
 
146
  hideEmbedModal,
147
  embedVisible,
148
  embedToken: token,
149
+ beta,
150
  };
151
  };
152
 
153
+ export const usePreviewChat = (idKey: string) => {
154
+ const { handleOperate } = useFetchTokenListBeforeOtherStep();
155
 
156
  const open = useCallback(
157
  (t: string) => {
web/src/components/message-item/index.tsx CHANGED
@@ -1,8 +1,7 @@
1
  import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg';
2
  import { MessageType } from '@/constants/chat';
3
  import { useSetModalState } from '@/hooks/common-hooks';
4
- import { IReference } from '@/interfaces/database/chat';
5
- import { IChunk } from '@/interfaces/database/knowledge';
6
  import classNames from 'classnames';
7
  import { memo, useCallback, useEffect, useMemo, useState } from 'react';
8
 
@@ -31,7 +30,7 @@ interface IProps extends Partial<IRemoveMessageById>, IRegenerateMessage {
31
  sendLoading?: boolean;
32
  nickname?: string;
33
  avatar?: string;
34
- clickDocumentButton?: (documentId: string, chunk: IChunk) => void;
35
  index: number;
36
  showLikeButton?: boolean;
37
  }
 
1
  import { ReactComponent as AssistantIcon } from '@/assets/svg/assistant.svg';
2
  import { MessageType } from '@/constants/chat';
3
  import { useSetModalState } from '@/hooks/common-hooks';
4
+ import { IReference, IReferenceChunk } from '@/interfaces/database/chat';
 
5
  import classNames from 'classnames';
6
  import { memo, useCallback, useEffect, useMemo, useState } from 'react';
7
 
 
30
  sendLoading?: boolean;
31
  nickname?: string;
32
  avatar?: string;
33
+ clickDocumentButton?: (documentId: string, chunk: IReferenceChunk) => void;
34
  index: number;
35
  showLikeButton?: boolean;
36
  }
web/src/components/pdf-drawer/hooks.ts CHANGED
@@ -1,14 +1,16 @@
1
  import { useSetModalState } from '@/hooks/common-hooks';
2
- import { IChunk } from '@/interfaces/database/knowledge';
3
  import { useCallback, useState } from 'react';
4
 
5
  export const useClickDrawer = () => {
6
  const { visible, showModal, hideModal } = useSetModalState();
7
- const [selectedChunk, setSelectedChunk] = useState<IChunk>({} as IChunk);
 
 
8
  const [documentId, setDocumentId] = useState<string>('');
9
 
10
  const clickDocumentButton = useCallback(
11
- (documentId: string, chunk: IChunk) => {
12
  showModal();
13
  setSelectedChunk(chunk);
14
  setDocumentId(documentId);
 
1
  import { useSetModalState } from '@/hooks/common-hooks';
2
+ import { IReferenceChunk } from '@/interfaces/database/chat';
3
  import { useCallback, useState } from 'react';
4
 
5
  export const useClickDrawer = () => {
6
  const { visible, showModal, hideModal } = useSetModalState();
7
+ const [selectedChunk, setSelectedChunk] = useState<IReferenceChunk>(
8
+ {} as IReferenceChunk,
9
+ );
10
  const [documentId, setDocumentId] = useState<string>('');
11
 
12
  const clickDocumentButton = useCallback(
13
+ (documentId: string, chunk: IReferenceChunk) => {
14
  showModal();
15
  setSelectedChunk(chunk);
16
  setDocumentId(documentId);
web/src/components/pdf-drawer/index.tsx CHANGED
@@ -1,11 +1,12 @@
1
  import { IModalProps } from '@/interfaces/common';
 
2
  import { IChunk } from '@/interfaces/database/knowledge';
3
  import { Drawer } from 'antd';
4
  import DocumentPreviewer from '../pdf-previewer';
5
 
6
  interface IProps extends IModalProps<any> {
7
  documentId: string;
8
- chunk: IChunk;
9
  }
10
 
11
  export const PdfDrawer = ({
 
1
  import { IModalProps } from '@/interfaces/common';
2
+ import { IReferenceChunk } from '@/interfaces/database/chat';
3
  import { IChunk } from '@/interfaces/database/knowledge';
4
  import { Drawer } from 'antd';
5
  import DocumentPreviewer from '../pdf-previewer';
6
 
7
  interface IProps extends IModalProps<any> {
8
  documentId: string;
9
+ chunk: IChunk | IReferenceChunk;
10
  }
11
 
12
  export const PdfDrawer = ({
web/src/components/pdf-previewer/index.tsx CHANGED
@@ -2,7 +2,9 @@ import {
2
  useGetChunkHighlights,
3
  useGetDocumentUrl,
4
  } from '@/hooks/document-hooks';
 
5
  import { IChunk } from '@/interfaces/database/knowledge';
 
6
  import { Skeleton } from 'antd';
7
  import { useEffect, useRef, useState } from 'react';
8
  import {
@@ -13,13 +15,12 @@ import {
13
  PdfLoader,
14
  Popup,
15
  } from 'react-pdf-highlighter';
16
-
17
- import FileError from '@/pages/document-viewer/file-error';
18
  import { useCatchDocumentError } from './hooks';
 
19
  import styles from './index.less';
20
 
21
  interface IProps {
22
- chunk: IChunk;
23
  documentId: string;
24
  visible: boolean;
25
  }
 
2
  useGetChunkHighlights,
3
  useGetDocumentUrl,
4
  } from '@/hooks/document-hooks';
5
+ import { IReferenceChunk } from '@/interfaces/database/chat';
6
  import { IChunk } from '@/interfaces/database/knowledge';
7
+ import FileError from '@/pages/document-viewer/file-error';
8
  import { Skeleton } from 'antd';
9
  import { useEffect, useRef, useState } from 'react';
10
  import {
 
15
  PdfLoader,
16
  Popup,
17
  } from 'react-pdf-highlighter';
 
 
18
  import { useCatchDocumentError } from './hooks';
19
+
20
  import styles from './index.less';
21
 
22
  interface IProps {
23
+ chunk: IChunk | IReferenceChunk;
24
  documentId: string;
25
  visible: boolean;
26
  }
web/src/hooks/chat-hooks.ts CHANGED
@@ -504,11 +504,17 @@ export const useCreateNextSharedConversation = () => {
504
  return { data, loading, createSharedConversation: mutateAsync };
505
  };
506
 
507
- export const useFetchNextSharedConversation = (conversationId: string) => {
 
 
 
508
  const { data, isPending: loading } = useQuery({
509
  queryKey: ['fetchSharedConversation'],
510
  enabled: !!conversationId,
511
  queryFn: async () => {
 
 
 
512
  const { data } = await chatService.getExternalConversation(
513
  null,
514
  conversationId,
 
504
  return { data, loading, createSharedConversation: mutateAsync };
505
  };
506
 
507
+ // deprecated
508
+ export const useFetchNextSharedConversation = (
509
+ conversationId?: string | null,
510
+ ) => {
511
  const { data, isPending: loading } = useQuery({
512
  queryKey: ['fetchSharedConversation'],
513
  enabled: !!conversationId,
514
  queryFn: async () => {
515
+ if (!conversationId) {
516
+ return {};
517
+ }
518
  const { data } = await chatService.getExternalConversation(
519
  null,
520
  conversationId,
web/src/hooks/document-hooks.ts CHANGED
@@ -1,3 +1,4 @@
 
1
  import { IDocumentInfo } from '@/interfaces/database/document';
2
  import { IChunk } from '@/interfaces/database/knowledge';
3
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
@@ -32,7 +33,9 @@ export const useGetDocumentUrl = (documentId?: string) => {
32
  return getDocumentUrl;
33
  };
34
 
35
- export const useGetChunkHighlights = (selectedChunk: IChunk) => {
 
 
36
  const [size, setSize] = useState({ width: 849, height: 1200 });
37
 
38
  const highlights: IHighlight[] = useMemo(() => {
 
1
+ import { IReferenceChunk } from '@/interfaces/database/chat';
2
  import { IDocumentInfo } from '@/interfaces/database/document';
3
  import { IChunk } from '@/interfaces/database/knowledge';
4
  import { IChangeParserConfigRequestBody } from '@/interfaces/request/document';
 
33
  return getDocumentUrl;
34
  };
35
 
36
+ export const useGetChunkHighlights = (
37
+ selectedChunk: IChunk | IReferenceChunk,
38
+ ) => {
39
  const [size, setSize] = useState({ width: 849, height: 1200 });
40
 
41
  const highlights: IHighlight[] = useMemo(() => {
web/src/hooks/logic-hooks.ts CHANGED
@@ -12,6 +12,7 @@ import { PaginationProps, message } from 'antd';
12
  import { FormInstance } from 'antd/lib';
13
  import axios from 'axios';
14
  import { EventSourceParserStream } from 'eventsource-parser/stream';
 
15
  import {
16
  ChangeEventHandler,
17
  useCallback,
@@ -336,6 +337,7 @@ export const useSelectDerivedMessages = () => {
336
  }),
337
  prompt: answer.prompt,
338
  audio_binary: answer.audio_binary,
 
339
  },
340
  ];
341
  });
 
12
  import { FormInstance } from 'antd/lib';
13
  import axios from 'axios';
14
  import { EventSourceParserStream } from 'eventsource-parser/stream';
15
+ import { omit } from 'lodash';
16
  import {
17
  ChangeEventHandler,
18
  useCallback,
 
337
  }),
338
  prompt: answer.prompt,
339
  audio_binary: answer.audio_binary,
340
+ ...omit(answer, 'reference'),
341
  },
342
  ];
343
  });
web/src/hooks/user-setting-hooks.tsx CHANGED
@@ -169,17 +169,34 @@ export const useFetchSystemStatus = () => {
169
  };
170
  };
171
 
172
- export const useFetchSystemTokenList = (params: Record<string, any>) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  const {
174
  data,
175
  isFetching: loading,
176
  refetch,
177
  } = useQuery<IToken[]>({
178
- queryKey: ['fetchSystemTokenList', params],
179
  initialData: [],
180
  gcTime: 0,
181
  queryFn: async () => {
182
- const { data } = await userService.listToken(params);
183
 
184
  return data?.data ?? [];
185
  },
@@ -213,6 +230,7 @@ export const useRemoveSystemToken = () => {
213
 
214
  export const useCreateSystemToken = () => {
215
  const queryClient = useQueryClient();
 
216
  const {
217
  data,
218
  isPending: loading,
 
169
  };
170
  };
171
 
172
+ export const useFetchManualSystemTokenList = () => {
173
+ const {
174
+ data,
175
+ isPending: loading,
176
+ mutateAsync,
177
+ } = useMutation({
178
+ mutationKey: ['fetchManualSystemTokenList'],
179
+ mutationFn: async () => {
180
+ const { data } = await userService.listToken();
181
+
182
+ return data?.data ?? [];
183
+ },
184
+ });
185
+
186
+ return { data, loading, fetchSystemTokenList: mutateAsync };
187
+ };
188
+
189
+ export const useFetchSystemTokenList = () => {
190
  const {
191
  data,
192
  isFetching: loading,
193
  refetch,
194
  } = useQuery<IToken[]>({
195
+ queryKey: ['fetchSystemTokenList'],
196
  initialData: [],
197
  gcTime: 0,
198
  queryFn: async () => {
199
+ const { data } = await userService.listToken();
200
 
201
  return data?.data ?? [];
202
  },
 
230
 
231
  export const useCreateSystemToken = () => {
232
  const queryClient = useQueryClient();
233
+
234
  const {
235
  data,
236
  isPending: loading,
web/src/interfaces/database/chat.ts CHANGED
@@ -1,5 +1,4 @@
1
  import { MessageType } from '@/constants/chat';
2
- import { IChunk } from './knowledge';
3
 
4
  export interface PromptConfig {
5
  empty_response: string;
@@ -35,7 +34,7 @@ export interface IDialog {
35
  description: string;
36
  icon: string;
37
  id: string;
38
- dialog_id?: string;
39
  kb_ids: string[];
40
  kb_names: string[];
41
  language: string;
@@ -75,8 +74,21 @@ export interface Message {
75
  audio_binary?: string;
76
  }
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  export interface IReference {
79
- chunks: IChunk[];
80
  doc_aggs: Docagg[];
81
  total: number;
82
  }
@@ -117,6 +129,7 @@ export interface IToken {
117
  token: string;
118
  update_date?: any;
119
  update_time?: any;
 
120
  }
121
 
122
  export interface IStats {
 
1
  import { MessageType } from '@/constants/chat';
 
2
 
3
  export interface PromptConfig {
4
  empty_response: string;
 
34
  description: string;
35
  icon: string;
36
  id: string;
37
+ dialog_id: string;
38
  kb_ids: string[];
39
  kb_names: string[];
40
  language: string;
 
74
  audio_binary?: string;
75
  }
76
 
77
+ export interface IReferenceChunk {
78
+ id: string;
79
+ content: null;
80
+ document_id: string;
81
+ document_name: string;
82
+ dataset_id: string;
83
+ image_id: string;
84
+ similarity: number;
85
+ vector_similarity: number;
86
+ term_similarity: number;
87
+ positions: number[];
88
+ }
89
+
90
  export interface IReference {
91
+ chunks: IReferenceChunk[];
92
  doc_aggs: Docagg[];
93
  total: number;
94
  }
 
129
  token: string;
130
  update_date?: any;
131
  update_time?: any;
132
+ beta: string;
133
  }
134
 
135
  export interface IStats {
web/src/locales/config.ts CHANGED
@@ -2,11 +2,11 @@ import i18n from 'i18next';
2
  import LanguageDetector from 'i18next-browser-languagedetector';
3
  import { initReactI18next } from 'react-i18next';
4
 
5
- import { createTranslationTable, flattenObject } from './until';
6
  import translation_en from './en';
7
  import translation_es from './es';
8
  import translation_id from './id';
9
  import translation_ja from './ja';
 
10
  import translation_vi from './vi';
11
  import translation_zh from './zh';
12
  import translation_zh_traditional from './zh-traditional';
 
2
  import LanguageDetector from 'i18next-browser-languagedetector';
3
  import { initReactI18next } from 'react-i18next';
4
 
 
5
  import translation_en from './en';
6
  import translation_es from './es';
7
  import translation_id from './id';
8
  import translation_ja from './ja';
9
+ import { createTranslationTable, flattenObject } from './until';
10
  import translation_vi from './vi';
11
  import translation_zh from './zh';
12
  import translation_zh_traditional from './zh-traditional';
web/src/locales/en.ts CHANGED
@@ -432,6 +432,7 @@ The above is the content you need to summarize.`,
432
  partialTitle: 'Partial Embed',
433
  extensionTitle: 'Chrome Extension',
434
  tokenError: 'Please create API Token first!',
 
435
  searching: 'searching...',
436
  parsing: 'Parsing',
437
  uploading: 'Uploading',
 
432
  partialTitle: 'Partial Embed',
433
  extensionTitle: 'Chrome Extension',
434
  tokenError: 'Please create API Token first!',
435
+ betaError: 'The beta field of the API Token cannot be empty!',
436
  searching: 'searching...',
437
  parsing: 'Parsing',
438
  uploading: 'Uploading',
web/src/locales/ja.ts CHANGED
@@ -33,6 +33,7 @@ export default {
33
  pleaseSelect: '選択してください',
34
  pleaseInput: '入力してください',
35
  submit: '送信',
 
36
  },
37
  login: {
38
  login: 'ログイン',
@@ -85,8 +86,7 @@ export default {
85
  name: '名前',
86
  namePlaceholder: '名前を入力してください',
87
  doc: 'ドキュメント',
88
- datasetDescription:
89
- '😉 パースが成功すると、質問と回答が可能になります。',
90
  addFile: 'ファイルを追加',
91
  searchFiles: 'ファイルを検索',
92
  localFiles: 'ローカルファイル',
@@ -157,8 +157,7 @@ export default {
157
  topK: 'トップK',
158
  topKTip: `Kチャンクがリランキングモデルに供給されます。`,
159
  delimiter: `区切り文字`,
160
- delimiterTip:
161
- '複数文字の区切り文字をサポートしています。',
162
  html4excel: 'ExcelをHTMLに変換',
163
  html4excelTip: `有効にすると、スプレッドシートはHTMLテーブルとして解析されます。それ以外の場合、キーと値のペアとして解析されます。`,
164
  autoKeywords: '自動キーワード',
@@ -182,7 +181,7 @@ export default {
182
  embeddingModelTip:
183
  'チャンクを埋め込みに変換するモデルです。一度チャンクが作成されると変更できません。',
184
  permissionsTip:
185
- "「チーム」に設定すると、全てのチームメンバーがナレッジベースを管理できます。",
186
  chunkTokenNumberTip:
187
  'チャンクのトークンしきい値を設定します。このしきい値を下回る段落は、次の段落と結合され、しきい値を超えた時点でチャンクが作成されます。',
188
  chunkMethod: 'チャンク方法',
@@ -201,8 +200,7 @@ export default {
201
  methodExamplesDescription:
202
  '以下のスクリーンショットは明確な説明のために提供されています。',
203
  dialogueExamplesTitle: '会話の例',
204
- methodEmpty:
205
- 'ナレッジベースカテゴリの視覚的説明がここに表示されます',
206
  book: `<p>対応ファイル形式は<b>DOCX</b>, <b>PDF</b>, <b>TXT</b>です。</p><p>
207
  PDF形式の書籍では、解析時間を短縮するため、<i>ページ範囲</i>を設定してください。</p>`,
208
  laws: `<p>対応ファイル形式は<b>DOCX</b>, <b>PDF</b>, <b>TXT</b>です。</p><p>
@@ -305,7 +303,7 @@ export default {
305
  entityTypes: 'エンティティタイプ',
306
  pageRank: 'ページランク',
307
  pageRankTip: `これは関連性スコアを高めるために使用されます。すべての取得されたチャンクの関連性スコアにこの数値が加算されます。
308
- 特定のナレッジベースを最初に検索したい場合は、他のものよりも高いページランクスコアを設定してください。`
309
  },
310
  chunk: {
311
  chunk: 'チャンク',
@@ -360,8 +358,7 @@ export default {
360
  {knowledge}
361
  上記がナレッジベースです。`,
362
  systemMessage: '入力してください!',
363
- systemTip:
364
- 'LLMが質問に答える際に従う指示を設定します。',
365
  topN: 'トップN',
366
  topNTip: `類似度スコアがしきい値を超えるチャンクのうち、上位N件のみがLLMに供給されます。`,
367
  variable: '変数',
@@ -406,7 +403,8 @@ export default {
406
  quote: '引用を表示',
407
  quoteTip: '元のテキストの出典を表示しますか?',
408
  selfRag: 'Self-RAG',
409
- selfRagTip: '詳細は次を参照してください:https://huggingface.co/papers/2310.11511',
 
410
  overview: 'チャットID',
411
  pv: 'メッセージ数',
412
  uv: 'アクティブユーザー数',
@@ -486,7 +484,7 @@ export default {
486
  newPassword: '新しいパスワード',
487
  newPasswordMessage: 'パスワードを入力してください!',
488
  newPasswordDescription:
489
- '新しいパスワードは8文字以上でなければなりません。',
490
  confirmPassword: '新しいパスワードの確認',
491
  confirmPasswordMessage: 'パスワードを確認してください!',
492
  confirmPasswordNonMatchMessage:
@@ -568,7 +566,7 @@ export default {
568
  SparkModelNameMessage: 'Sparkモデルを選択してください',
569
  addSparkAPIPassword: 'Spark APIパスワード',
570
  SparkAPIPasswordMessage: 'APIパスワードを入力してください',
571
- addSparkAPPID: 'Spark APPID',
572
  SparkAPPIDMessage: 'APPIDを入力してください',
573
  addSparkAPISecret: 'Spark APIシークレット',
574
  SparkAPISecretMessage: 'APIシークレットを入力してください',
@@ -579,8 +577,7 @@ export default {
579
  yiyanAKMessage: 'APIキーを入力してください',
580
  addyiyanSK: 'yiyanシークレットキー',
581
  yiyanSKMessage: 'シークレットキーを入力してください',
582
- FishAudioModelNameMessage:
583
- '音声合成モデルに名前を付けてください',
584
  addFishAudioAK: 'Fish Audio APIキー',
585
  addFishAudioAKMessage: 'APIキーを入力してください',
586
  addFishAudioRefID: 'FishAudio参照ID',
@@ -700,7 +697,7 @@ export default {
700
  relevantDescription: `LLMを使用して、上流の出力がユーザーの最新のクエリに関連しているかどうかを評価するコンポーネント。各判定結果に対して次のコンポーネントを指定してください。`,
701
  rewriteQuestionDescription: `ナレッジベースから関連情報を取得できなかった場合にユーザーのクエリを修正するコンポーネント。定義されたループの上限に達するまでこのプロセスを繰り返します。上流が「Relevant」、下流が「Retrieval」であることを確認してください。`,
702
  messageDescription:
703
- "静的メッセージを送信するコンポーネント。複数のメッセージが提供されている場合は、その中からランダムに1つを選択して送信します。下流がインターフェースコンポーネント「Answer」であることを確認してください。",
704
  keywordDescription: `ユーザーの入力からトップNの検索結果を取得するコンポーネント。使用前にTopNの値が適切に設定されていることを確認してください。`,
705
  switchDescription: `前のコンポーネントの出力に基づいて条件を評価し、それに応じて実行の流れを指示するコンポーネント。ケースを定義し、各ケースのアクションまたは条件が満たされない場合のデフォルトアクションを指定することで、複雑な分岐ロジックを可能にします。`,
706
  wikipediaDescription: `wikipedia.orgから検索を行うコンポーネントで、TopNを使用して検索結果の数を指定します。既存のナレッジベースを補完します。`,
@@ -800,7 +797,7 @@ export default {
800
  news: 'ニュースと情報',
801
  law: '法律と規制',
802
  contract: '契約',
803
- },
804
  baiduSourceLangOptions: {
805
  auto: '自動検出',
806
  zh: '中国語',
@@ -1089,4 +1086,4 @@ export default {
1089
  chat: 'チャット',
1090
  },
1091
  },
1092
- };
 
33
  pleaseSelect: '選択してください',
34
  pleaseInput: '入力してください',
35
  submit: '送信',
36
+ japanese: '日本語',
37
  },
38
  login: {
39
  login: 'ログイン',
 
86
  name: '名前',
87
  namePlaceholder: '名前を入力してください',
88
  doc: 'ドキュメント',
89
+ datasetDescription: '😉 パースが成功すると、質問と回答が可能になります。',
 
90
  addFile: 'ファイルを追加',
91
  searchFiles: 'ファイルを検索',
92
  localFiles: 'ローカルファイル',
 
157
  topK: 'トップK',
158
  topKTip: `Kチャンクがリランキングモデルに供給されます。`,
159
  delimiter: `区切り文字`,
160
+ delimiterTip: '複数文字の区切り文字をサポートしています。',
 
161
  html4excel: 'ExcelをHTMLに変換',
162
  html4excelTip: `有効にすると、スプレッドシートはHTMLテーブルとして解析されます。それ以外の場合、キーと値のペアとして解析されます。`,
163
  autoKeywords: '自動キーワード',
 
181
  embeddingModelTip:
182
  'チャンクを埋め込みに変換するモデルです。一度チャンクが作成されると変更できません。',
183
  permissionsTip:
184
+ '「チーム」に設定すると、全てのチームメンバーがナレッジベースを管理できます。',
185
  chunkTokenNumberTip:
186
  'チャンクのトークンしきい値を設定します。このしきい値を下回る段落は、次の段落と結合され、しきい値を超えた時点でチャンクが作成されます。',
187
  chunkMethod: 'チャンク方法',
 
200
  methodExamplesDescription:
201
  '以下のスクリーンショットは明確な説明のために提供されています。',
202
  dialogueExamplesTitle: '会話の例',
203
+ methodEmpty: 'ナレッジベースカテゴリの視覚的説明がここに表示されます',
 
204
  book: `<p>対応ファイル形式は<b>DOCX</b>, <b>PDF</b>, <b>TXT</b>です。</p><p>
205
  PDF形式の書籍では、解析時間を短縮するため、<i>ページ範囲</i>を設定してください。</p>`,
206
  laws: `<p>対応ファイル形式は<b>DOCX</b>, <b>PDF</b>, <b>TXT</b>です。</p><p>
 
303
  entityTypes: 'エンティティタイプ',
304
  pageRank: 'ページランク',
305
  pageRankTip: `これは関連性スコアを高めるために使用されます。すべての取得されたチャンクの関連性スコアにこの数値が加算されます。
306
+ 特定のナレッジベースを最初に検索したい場合は、他のものよりも高いページランクスコアを設定してください。`,
307
  },
308
  chunk: {
309
  chunk: 'チャンク',
 
358
  {knowledge}
359
  上記がナレッジベースです。`,
360
  systemMessage: '入力してください!',
361
+ systemTip: 'LLMが質問に答える際に従う指示を設定します。',
 
362
  topN: 'トップN',
363
  topNTip: `類似度スコアがしきい値を超えるチャンクのうち、上位N件のみがLLMに供給されます。`,
364
  variable: '変数',
 
403
  quote: '引用を表示',
404
  quoteTip: '元のテキストの出典を表示しますか?',
405
  selfRag: 'Self-RAG',
406
+ selfRagTip:
407
+ '詳細は次を参照してください:https://huggingface.co/papers/2310.11511',
408
  overview: 'チャットID',
409
  pv: 'メッセージ数',
410
  uv: 'アクティブユーザー数',
 
484
  newPassword: '新しいパスワード',
485
  newPasswordMessage: 'パスワードを入力してください!',
486
  newPasswordDescription:
487
+ '新しいパスワードは8文字以上でなければなりません。',
488
  confirmPassword: '新しいパスワードの確認',
489
  confirmPasswordMessage: 'パスワードを確認してください!',
490
  confirmPasswordNonMatchMessage:
 
566
  SparkModelNameMessage: 'Sparkモデルを選択してください',
567
  addSparkAPIPassword: 'Spark APIパスワード',
568
  SparkAPIPasswordMessage: 'APIパスワードを入力してください',
569
+ addSparkAPPID: 'Spark APPID',
570
  SparkAPPIDMessage: 'APPIDを入力してください',
571
  addSparkAPISecret: 'Spark APIシークレット',
572
  SparkAPISecretMessage: 'APIシークレットを入力してください',
 
577
  yiyanAKMessage: 'APIキーを入力してください',
578
  addyiyanSK: 'yiyanシークレットキー',
579
  yiyanSKMessage: 'シークレットキーを入力してください',
580
+ FishAudioModelNameMessage: '音声合成モデルに名前を付けてください',
 
581
  addFishAudioAK: 'Fish Audio APIキー',
582
  addFishAudioAKMessage: 'APIキーを入力してください',
583
  addFishAudioRefID: 'FishAudio参照ID',
 
697
  relevantDescription: `LLMを使用して、上流の出力がユーザーの最新のクエリに関連しているかどうかを評価するコンポーネント。各判定結果に対して次のコンポーネントを指定してください。`,
698
  rewriteQuestionDescription: `ナレッジベースから関連情報を取得できなかった場合にユーザーのクエリを修正するコンポーネント。定義されたループの上限に達するまでこのプロセスを繰り返します。上流が「Relevant」、下流が「Retrieval」であることを確認してください。`,
699
  messageDescription:
700
+ '静的メッセージを送信するコンポーネント。複数のメッセージが提供されている場合は、その中からランダムに1つを選択して送信します。下流がインターフェースコンポーネント「Answer」であることを確認してください。',
701
  keywordDescription: `ユーザーの入力からトップNの検索結果を取得するコンポーネント。使用前にTopNの値が適切に設定されていることを確認してください。`,
702
  switchDescription: `前のコンポーネントの出力に基づいて条件を評価し、それに応じて実行の流れを指示するコンポーネント。ケースを定義し、各ケースのアクションまたは条件が満たされない場合のデフォルトアクションを指定することで、複雑な分岐ロジックを可能にします。`,
703
  wikipediaDescription: `wikipedia.orgから検索を行うコンポーネントで、TopNを使用して検索結果の数を指定します。既存のナレッジベースを補完します。`,
 
797
  news: 'ニュースと情報',
798
  law: '法律と規制',
799
  contract: '契約',
800
+ },
801
  baiduSourceLangOptions: {
802
  auto: '自動検出',
803
  zh: '中国語',
 
1086
  chat: 'チャット',
1087
  },
1088
  },
1089
+ };
web/src/locales/zh-traditional.ts CHANGED
@@ -414,6 +414,7 @@ export default {
414
  partialTitle: '部分嵌入',
415
  extensionTitle: 'Chrome 插件',
416
  tokenError: '請先創建 API Token!',
 
417
  searching: '搜索中',
418
  parsing: '解析中',
419
  uploading: '上傳中',
 
414
  partialTitle: '部分嵌入',
415
  extensionTitle: 'Chrome 插件',
416
  tokenError: '請先創建 API Token!',
417
+ betaError: 'API Token的beta欄位不可以為空!',
418
  searching: '搜索中',
419
  parsing: '解析中',
420
  uploading: '上傳中',
web/src/locales/zh.ts CHANGED
@@ -431,6 +431,7 @@ export default {
431
  partialTitle: '部分嵌入',
432
  extensionTitle: 'Chrome 插件',
433
  tokenError: '请先创建 API Token!',
 
434
  searching: '搜索中',
435
  parsing: '解析中',
436
  uploading: '上传中',
 
431
  partialTitle: '部分嵌入',
432
  extensionTitle: 'Chrome 插件',
433
  tokenError: '请先创建 API Token!',
434
+ betaError: 'API Token的beta字段不可以为空!',
435
  searching: '搜索中',
436
  parsing: '解析中',
437
  uploading: '上传中',
web/src/pages/chat/index.tsx CHANGED
@@ -29,18 +29,20 @@ import {
29
  useSelectDerivedConversationList,
30
  } from './hooks';
31
 
 
 
32
  import SvgIcon from '@/components/svg-icon';
33
  import { useTheme } from '@/components/theme-provider';
 
34
  import {
35
  useClickConversationCard,
36
  useClickDialogCard,
37
  useFetchNextDialogList,
38
  useGetChatSearchParams,
39
  } from '@/hooks/chat-hooks';
40
- import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
41
  import { useSetSelectedRecord } from '@/hooks/logic-hooks';
42
  import { IDialog } from '@/interfaces/database/chat';
43
- import ChatIdModal from './chat-id-modal';
44
  import styles from './index.less';
45
 
46
  const { Text } = Typography;
@@ -82,13 +84,10 @@ const Chat = () => {
82
  showDialogEditModal,
83
  } = useEditDialog();
84
  const { t } = useTranslate('chat');
85
- const {
86
- visible: overviewVisible,
87
- hideModal: hideOverviewModal,
88
- showModal: showOverviewModal,
89
- } = useSetModalState();
90
  const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>();
91
  const [controller, setController] = useState(new AbortController());
 
 
92
 
93
  const handleAppCardEnter = (id: string) => () => {
94
  handleItemEnter(id);
@@ -120,7 +119,7 @@ const Chat = () => {
120
  info?.domEvent?.preventDefault();
121
  info?.domEvent?.stopPropagation();
122
  setRecord(dialog);
123
- showOverviewModal();
124
  };
125
 
126
  const handleRemoveConversation =
@@ -193,7 +192,7 @@ const Chat = () => {
193
  label: (
194
  <Space>
195
  <KeyOutlined />
196
- {t('overview')}
197
  </Space>
198
  ),
199
  },
@@ -374,14 +373,16 @@ const Chat = () => {
374
  initialName={initialConversationName}
375
  loading={conversationRenameLoading}
376
  ></RenameModal>
377
- {overviewVisible && (
378
- <ChatIdModal
379
- visible={overviewVisible}
380
- hideModal={hideOverviewModal}
381
- id={currentRecord.id}
382
- name={currentRecord.name}
383
- idKey="dialogId"
384
- ></ChatIdModal>
 
 
385
  )}
386
  </Flex>
387
  );
 
29
  useSelectDerivedConversationList,
30
  } from './hooks';
31
 
32
+ import EmbedModal from '@/components/api-service/embed-modal';
33
+ import { useShowEmbedModal } from '@/components/api-service/hooks';
34
  import SvgIcon from '@/components/svg-icon';
35
  import { useTheme } from '@/components/theme-provider';
36
+ import { SharedFrom } from '@/constants/chat';
37
  import {
38
  useClickConversationCard,
39
  useClickDialogCard,
40
  useFetchNextDialogList,
41
  useGetChatSearchParams,
42
  } from '@/hooks/chat-hooks';
43
+ import { useTranslate } from '@/hooks/common-hooks';
44
  import { useSetSelectedRecord } from '@/hooks/logic-hooks';
45
  import { IDialog } from '@/interfaces/database/chat';
 
46
  import styles from './index.less';
47
 
48
  const { Text } = Typography;
 
84
  showDialogEditModal,
85
  } = useEditDialog();
86
  const { t } = useTranslate('chat');
 
 
 
 
 
87
  const { currentRecord, setRecord } = useSetSelectedRecord<IDialog>();
88
  const [controller, setController] = useState(new AbortController());
89
+ const { showEmbedModal, hideEmbedModal, embedVisible, beta } =
90
+ useShowEmbedModal();
91
 
92
  const handleAppCardEnter = (id: string) => () => {
93
  handleItemEnter(id);
 
119
  info?.domEvent?.preventDefault();
120
  info?.domEvent?.stopPropagation();
121
  setRecord(dialog);
122
+ showEmbedModal();
123
  };
124
 
125
  const handleRemoveConversation =
 
192
  label: (
193
  <Space>
194
  <KeyOutlined />
195
+ {t('publish', { keyPrefix: 'flow' })}
196
  </Space>
197
  ),
198
  },
 
373
  initialName={initialConversationName}
374
  loading={conversationRenameLoading}
375
  ></RenameModal>
376
+
377
+ {embedVisible && (
378
+ <EmbedModal
379
+ visible={embedVisible}
380
+ hideModal={hideEmbedModal}
381
+ token={currentRecord.id}
382
+ form={SharedFrom.Chat}
383
+ beta={beta}
384
+ isAgent={false}
385
+ ></EmbedModal>
386
  )}
387
  </Flex>
388
  );
web/src/pages/chat/markdown-content/index.tsx CHANGED
@@ -1,7 +1,6 @@
1
  import Image from '@/components/image';
2
  import SvgIcon from '@/components/svg-icon';
3
- import { IReference } from '@/interfaces/database/chat';
4
- import { IChunk } from '@/interfaces/database/knowledge';
5
  import { getExtension } from '@/utils/document-util';
6
  import { InfoCircleOutlined } from '@ant-design/icons';
7
  import { Button, Flex, Popover, Space } from 'antd';
@@ -11,6 +10,7 @@ import Markdown from 'react-markdown';
11
  import reactStringReplace from 'react-string-replace';
12
  import SyntaxHighlighter from 'react-syntax-highlighter';
13
  import rehypeKatex from 'rehype-katex';
 
14
  import remarkGfm from 'remark-gfm';
15
  import remarkMath from 'remark-math';
16
  import { visitParents } from 'unist-util-visit-parents';
@@ -36,7 +36,7 @@ const MarkdownContent = ({
36
  content: string;
37
  loading: boolean;
38
  reference: IReference;
39
- clickDocumentButton?: (documentId: string, chunk: IChunk) => void;
40
  }) => {
41
  const { t } = useTranslation();
42
  const { setDocumentIds, data: fileThumbnails } =
@@ -54,7 +54,7 @@ const MarkdownContent = ({
54
  }, [reference, setDocumentIds]);
55
 
56
  const handleDocumentButtonClick = useCallback(
57
- (documentId: string, chunk: IChunk, isPdf: boolean) => () => {
58
  if (!isPdf) {
59
  return;
60
  }
@@ -85,15 +85,15 @@ const MarkdownContent = ({
85
  const chunks = reference?.chunks ?? [];
86
  const chunkItem = chunks[chunkIndex];
87
  const document = reference?.doc_aggs?.find(
88
- (x) => x?.doc_id === chunkItem?.doc_id,
89
  );
90
  const documentId = document?.doc_id;
91
  const fileThumbnail = documentId ? fileThumbnails[documentId] : '';
92
  const fileExtension = documentId ? getExtension(document?.doc_name) : '';
93
- const imageId = chunkItem?.img_id;
94
  return (
95
  <Flex
96
- key={chunkItem?.chunk_id}
97
  gap={10}
98
  className={styles.referencePopoverWrapper}
99
  >
@@ -116,7 +116,7 @@ const MarkdownContent = ({
116
  <Space direction={'vertical'}>
117
  <div
118
  dangerouslySetInnerHTML={{
119
- __html: DOMPurify.sanitize(chunkItem?.content_with_weight),
120
  }}
121
  className={styles.chunkContentText}
122
  ></div>
@@ -176,7 +176,7 @@ const MarkdownContent = ({
176
 
177
  return (
178
  <Markdown
179
- rehypePlugins={[rehypeWrapReference, rehypeKatex]}
180
  remarkPlugins={[remarkGfm, remarkMath]}
181
  components={
182
  {
 
1
  import Image from '@/components/image';
2
  import SvgIcon from '@/components/svg-icon';
3
+ import { IReference, IReferenceChunk } from '@/interfaces/database/chat';
 
4
  import { getExtension } from '@/utils/document-util';
5
  import { InfoCircleOutlined } from '@ant-design/icons';
6
  import { Button, Flex, Popover, Space } from 'antd';
 
10
  import reactStringReplace from 'react-string-replace';
11
  import SyntaxHighlighter from 'react-syntax-highlighter';
12
  import rehypeKatex from 'rehype-katex';
13
+ import rehypeRaw from 'rehype-raw';
14
  import remarkGfm from 'remark-gfm';
15
  import remarkMath from 'remark-math';
16
  import { visitParents } from 'unist-util-visit-parents';
 
36
  content: string;
37
  loading: boolean;
38
  reference: IReference;
39
+ clickDocumentButton?: (documentId: string, chunk: IReferenceChunk) => void;
40
  }) => {
41
  const { t } = useTranslation();
42
  const { setDocumentIds, data: fileThumbnails } =
 
54
  }, [reference, setDocumentIds]);
55
 
56
  const handleDocumentButtonClick = useCallback(
57
+ (documentId: string, chunk: IReferenceChunk, isPdf: boolean) => () => {
58
  if (!isPdf) {
59
  return;
60
  }
 
85
  const chunks = reference?.chunks ?? [];
86
  const chunkItem = chunks[chunkIndex];
87
  const document = reference?.doc_aggs?.find(
88
+ (x) => x?.doc_id === chunkItem?.document_id,
89
  );
90
  const documentId = document?.doc_id;
91
  const fileThumbnail = documentId ? fileThumbnails[documentId] : '';
92
  const fileExtension = documentId ? getExtension(document?.doc_name) : '';
93
+ const imageId = chunkItem?.image_id;
94
  return (
95
  <Flex
96
+ key={chunkItem?.id}
97
  gap={10}
98
  className={styles.referencePopoverWrapper}
99
  >
 
116
  <Space direction={'vertical'}>
117
  <div
118
  dangerouslySetInnerHTML={{
119
+ __html: DOMPurify.sanitize(chunkItem?.content ?? ''),
120
  }}
121
  className={styles.chunkContentText}
122
  ></div>
 
176
 
177
  return (
178
  <Markdown
179
+ rehypePlugins={[rehypeWrapReference, rehypeKatex, rehypeRaw]}
180
  remarkPlugins={[remarkGfm, remarkMath]}
181
  components={
182
  {
web/src/pages/chat/share/large.tsx CHANGED
@@ -1,21 +1,23 @@
1
  import MessageInput from '@/components/message-input';
2
  import MessageItem from '@/components/message-item';
 
3
  import { MessageType, SharedFrom } from '@/constants/chat';
4
- import { useFetchNextSharedConversation } from '@/hooks/chat-hooks';
5
  import { useSendButtonDisabled } from '@/pages/chat/hooks';
6
  import { Flex, Spin } from 'antd';
7
  import { forwardRef } from 'react';
8
  import {
9
- useCreateSharedConversationOnMount,
10
  useGetSharedChatSearchParams,
11
  useSendSharedMessage,
12
  } from '../shared-hooks';
13
  import { buildMessageItemReference } from '../utils';
 
 
14
  import styles from './index.less';
15
 
16
  const ChatContainer = () => {
17
- const { conversationId } = useCreateSharedConversationOnMount();
18
- const { data } = useFetchNextSharedConversation(conversationId);
 
19
 
20
  const {
21
  handlePressEnter,
@@ -25,9 +27,13 @@ const ChatContainer = () => {
25
  loading,
26
  ref,
27
  derivedMessages,
28
- } = useSendSharedMessage(conversationId);
 
29
  const sendDisabled = useSendButtonDisabled(value);
30
- const { from } = useGetSharedChatSearchParams();
 
 
 
31
 
32
  return (
33
  <>
@@ -44,7 +50,7 @@ const ChatContainer = () => {
44
  reference={buildMessageItemReference(
45
  {
46
  message: derivedMessages,
47
- reference: data?.data?.reference,
48
  },
49
  message,
50
  )}
@@ -54,6 +60,7 @@ const ChatContainer = () => {
54
  derivedMessages?.length - 1 === i
55
  }
56
  index={i}
 
57
  ></MessageItem>
58
  );
59
  })}
@@ -65,7 +72,7 @@ const ChatContainer = () => {
65
  <MessageInput
66
  isShared
67
  value={value}
68
- disabled={false}
69
  sendDisabled={sendDisabled}
70
  conversationId={conversationId}
71
  onInputChange={handleInputChange}
@@ -75,6 +82,14 @@ const ChatContainer = () => {
75
  showUploadIcon={from === SharedFrom.Chat}
76
  ></MessageInput>
77
  </Flex>
 
 
 
 
 
 
 
 
78
  </>
79
  );
80
  };
 
1
  import MessageInput from '@/components/message-input';
2
  import MessageItem from '@/components/message-item';
3
+ import { useClickDrawer } from '@/components/pdf-drawer/hooks';
4
  import { MessageType, SharedFrom } from '@/constants/chat';
 
5
  import { useSendButtonDisabled } from '@/pages/chat/hooks';
6
  import { Flex, Spin } from 'antd';
7
  import { forwardRef } from 'react';
8
  import {
 
9
  useGetSharedChatSearchParams,
10
  useSendSharedMessage,
11
  } from '../shared-hooks';
12
  import { buildMessageItemReference } from '../utils';
13
+
14
+ import PdfDrawer from '@/components/pdf-drawer';
15
  import styles from './index.less';
16
 
17
  const ChatContainer = () => {
18
+ const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
19
+ const { visible, hideModal, documentId, selectedChunk, clickDocumentButton } =
20
+ useClickDrawer();
21
 
22
  const {
23
  handlePressEnter,
 
27
  loading,
28
  ref,
29
  derivedMessages,
30
+ hasError,
31
+ } = useSendSharedMessage();
32
  const sendDisabled = useSendButtonDisabled(value);
33
+
34
+ if (!conversationId) {
35
+ return <div>empty</div>;
36
+ }
37
 
38
  return (
39
  <>
 
50
  reference={buildMessageItemReference(
51
  {
52
  message: derivedMessages,
53
+ reference: [],
54
  },
55
  message,
56
  )}
 
60
  derivedMessages?.length - 1 === i
61
  }
62
  index={i}
63
+ clickDocumentButton={clickDocumentButton}
64
  ></MessageItem>
65
  );
66
  })}
 
72
  <MessageInput
73
  isShared
74
  value={value}
75
+ disabled={hasError}
76
  sendDisabled={sendDisabled}
77
  conversationId={conversationId}
78
  onInputChange={handleInputChange}
 
82
  showUploadIcon={from === SharedFrom.Chat}
83
  ></MessageInput>
84
  </Flex>
85
+ {visible && (
86
+ <PdfDrawer
87
+ visible={visible}
88
+ hideModal={hideModal}
89
+ documentId={documentId}
90
+ chunk={selectedChunk}
91
+ ></PdfDrawer>
92
+ )}
93
  </>
94
  );
95
  };
web/src/pages/chat/shared-hooks.ts CHANGED
@@ -1,83 +1,41 @@
1
  import { MessageType, SharedFrom } from '@/constants/chat';
2
- import {
3
- useCreateNextSharedConversation,
4
- useFetchNextSharedConversation,
5
- } from '@/hooks/chat-hooks';
6
  import {
7
  useSelectDerivedMessages,
8
  useSendMessageWithSse,
9
  } from '@/hooks/logic-hooks';
10
  import { Message } from '@/interfaces/database/chat';
11
- import api from '@/utils/api';
 
12
  import trim from 'lodash/trim';
13
  import { useCallback, useEffect, useState } from 'react';
14
  import { useSearchParams } from 'umi';
15
  import { v4 as uuid } from 'uuid';
16
  import { useHandleMessageInputChange } from './hooks';
17
 
18
- export const useCreateSharedConversationOnMount = () => {
19
- const [currentQueryParameters] = useSearchParams();
20
- const [conversationId, setConversationId] = useState('');
21
-
22
- const { createSharedConversation: createConversation } =
23
- useCreateNextSharedConversation();
24
- const sharedId = currentQueryParameters.get('shared_id');
25
- const userId = currentQueryParameters.get('user_id');
26
-
27
- const setConversation = useCallback(async () => {
28
- if (sharedId) {
29
- const data = await createConversation(userId ?? undefined);
30
- const id = data.data?.id;
31
- if (id) {
32
- setConversationId(id);
33
- }
34
- }
35
- }, [createConversation, sharedId, userId]);
36
-
37
- useEffect(() => {
38
- setConversation();
39
- }, [setConversation]);
40
 
41
- return { conversationId };
 
42
  };
43
 
44
- export const useSelectNextSharedMessages = (conversationId: string) => {
45
- const { data, loading } = useFetchNextSharedConversation(conversationId);
46
-
47
- const {
48
- derivedMessages,
49
- ref,
50
- setDerivedMessages,
51
- addNewestAnswer,
52
- addNewestQuestion,
53
- removeLatestMessage,
54
- } = useSelectDerivedMessages();
55
-
56
- useEffect(() => {
57
- setDerivedMessages(data?.data?.message);
58
- }, [setDerivedMessages, data]);
59
 
60
  return {
61
- derivedMessages,
62
- addNewestAnswer,
63
- addNewestQuestion,
64
- removeLatestMessage,
65
- loading,
66
- ref,
67
- setDerivedMessages,
68
  };
69
  };
70
 
71
- export const useSendButtonDisabled = (value: string) => {
72
- return trim(value) === '';
73
- };
74
-
75
- export const useSendSharedMessage = (conversationId: string) => {
76
  const { createSharedConversation: setConversation } =
77
  useCreateNextSharedConversation();
78
  const { handleInputChange, value, setValue } = useHandleMessageInputChange();
79
  const { send, answer, done } = useSendMessageWithSse(
80
- api.completeExternalConversation,
81
  );
82
  const {
83
  derivedMessages,
@@ -85,24 +43,25 @@ export const useSendSharedMessage = (conversationId: string) => {
85
  removeLatestMessage,
86
  addNewestAnswer,
87
  addNewestQuestion,
88
- loading,
89
- } = useSelectNextSharedMessages(conversationId);
90
 
91
  const sendMessage = useCallback(
92
  async (message: Message, id?: string) => {
93
  const res = await send({
94
  conversation_id: id ?? conversationId,
95
- quote: false,
96
- messages: [...(derivedMessages ?? []), message],
 
97
  });
98
 
99
- if (res && (res?.response.status !== 200 || res?.data?.code !== 0)) {
100
  // cancel loading
101
  setValue(message.content);
102
  removeLatestMessage();
103
  }
104
  },
105
- [conversationId, derivedMessages, removeLatestMessage, setValue, send],
106
  );
107
 
108
  const handleSendMessage = useCallback(
@@ -120,6 +79,18 @@ export const useSendSharedMessage = (conversationId: string) => {
120
  [conversationId, setConversation, sendMessage],
121
  );
122
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  useEffect(() => {
124
  if (answer.answer) {
125
  addNewestAnswer(answer);
@@ -154,16 +125,8 @@ export const useSendSharedMessage = (conversationId: string) => {
154
  value,
155
  sendLoading: !done,
156
  ref,
157
- loading,
158
  derivedMessages,
159
- };
160
- };
161
-
162
- export const useGetSharedChatSearchParams = () => {
163
- const [searchParams] = useSearchParams();
164
-
165
- return {
166
- from: searchParams.get('from') as SharedFrom,
167
- sharedId: searchParams.get('shared_id'),
168
  };
169
  };
 
1
  import { MessageType, SharedFrom } from '@/constants/chat';
2
+ import { useCreateNextSharedConversation } from '@/hooks/chat-hooks';
 
 
 
3
  import {
4
  useSelectDerivedMessages,
5
  useSendMessageWithSse,
6
  } from '@/hooks/logic-hooks';
7
  import { Message } from '@/interfaces/database/chat';
8
+ import { message } from 'antd';
9
+ import { get } from 'lodash';
10
  import trim from 'lodash/trim';
11
  import { useCallback, useEffect, useState } from 'react';
12
  import { useSearchParams } from 'umi';
13
  import { v4 as uuid } from 'uuid';
14
  import { useHandleMessageInputChange } from './hooks';
15
 
16
+ const isCompletionError = (res: any) =>
17
+ res && (res?.response.status !== 200 || res?.data?.code !== 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ export const useSendButtonDisabled = (value: string) => {
20
+ return trim(value) === '';
21
  };
22
 
23
+ export const useGetSharedChatSearchParams = () => {
24
+ const [searchParams] = useSearchParams();
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  return {
27
+ from: searchParams.get('from') as SharedFrom,
28
+ sharedId: searchParams.get('shared_id'),
 
 
 
 
 
29
  };
30
  };
31
 
32
+ export const useSendSharedMessage = () => {
33
+ const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
 
 
 
34
  const { createSharedConversation: setConversation } =
35
  useCreateNextSharedConversation();
36
  const { handleInputChange, value, setValue } = useHandleMessageInputChange();
37
  const { send, answer, done } = useSendMessageWithSse(
38
+ `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`,
39
  );
40
  const {
41
  derivedMessages,
 
43
  removeLatestMessage,
44
  addNewestAnswer,
45
  addNewestQuestion,
46
+ } = useSelectDerivedMessages();
47
+ const [hasError, setHasError] = useState(false);
48
 
49
  const sendMessage = useCallback(
50
  async (message: Message, id?: string) => {
51
  const res = await send({
52
  conversation_id: id ?? conversationId,
53
+ quote: true,
54
+ question: message.content,
55
+ session_id: get(derivedMessages, '0.session_id'),
56
  });
57
 
58
+ if (isCompletionError(res)) {
59
  // cancel loading
60
  setValue(message.content);
61
  removeLatestMessage();
62
  }
63
  },
64
+ [send, conversationId, derivedMessages, setValue, removeLatestMessage],
65
  );
66
 
67
  const handleSendMessage = useCallback(
 
79
  [conversationId, setConversation, sendMessage],
80
  );
81
 
82
+ const fetchSessionId = useCallback(async () => {
83
+ const ret = await send({ question: '' });
84
+ if (isCompletionError(ret)) {
85
+ message.error(ret?.data.message);
86
+ setHasError(true);
87
+ }
88
+ }, [send]);
89
+
90
+ useEffect(() => {
91
+ fetchSessionId();
92
+ }, [fetchSessionId, send]);
93
+
94
  useEffect(() => {
95
  if (answer.answer) {
96
  addNewestAnswer(answer);
 
125
  value,
126
  sendLoading: !done,
127
  ref,
128
+ loading: false,
129
  derivedMessages,
130
+ hasError,
 
 
 
 
 
 
 
 
131
  };
132
  };
web/src/pages/flow/header/index.tsx CHANGED
@@ -1,13 +1,15 @@
1
- import ChatOverviewModal from '@/components/api-service/chat-overview-modal';
2
- import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
 
 
3
  import { useFetchFlow } from '@/hooks/flow-hooks';
4
  import { ArrowLeftOutlined } from '@ant-design/icons';
5
  import { Button, Flex, Space } from 'antd';
6
  import { useCallback } from 'react';
7
  import { Link, useParams } from 'umi';
8
- import FlowIdModal from '../flow-id-modal';
9
  import {
10
  useGetBeginNodeDataQuery,
 
11
  useSaveGraph,
12
  useSaveGraphBeforeOpeningDebugDrawer,
13
  useWatchAgentChange,
@@ -25,15 +27,16 @@ const FlowHeader = ({ showChatDrawer, chatDrawerVisible }: IProps) => {
25
  const { handleRun } = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer);
26
  const { data } = useFetchFlow();
27
  const { t } = useTranslate('flow');
28
- const {
29
- visible: overviewVisible,
30
- hideModal: hideOverviewModal,
31
- // showModal: showOverviewModal,
32
- } = useSetModalState();
33
- const { visible, hideModal, showModal } = useSetModalState();
34
  const { id } = useParams();
35
  const time = useWatchAgentChange(chatDrawerVisible);
36
  const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
 
 
 
 
 
 
 
37
 
38
  const handleRunAgent = useCallback(() => {
39
  const query: BeginQuery[] = getBeginNodeDataQuery();
@@ -70,23 +73,25 @@ const FlowHeader = ({ showChatDrawer, chatDrawerVisible }: IProps) => {
70
  <Button type="primary" onClick={() => saveGraph()}>
71
  <b>{t('save')}</b>
72
  </Button>
73
- {/* <Button type="primary" onClick={showOverviewModal} disabled>
 
 
 
 
74
  <b>{t('publish')}</b>
75
- </Button> */}
76
- <Button type="primary" onClick={showModal}>
77
- <b>Agent ID</b>
78
  </Button>
79
  </Space>
80
  </Flex>
81
- {overviewVisible && (
82
- <ChatOverviewModal
83
- visible={overviewVisible}
84
- hideModal={hideOverviewModal}
85
- id={id!}
86
- idKey="canvasId"
87
- ></ChatOverviewModal>
 
 
88
  )}
89
- {visible && <FlowIdModal hideModal={hideModal}></FlowIdModal>}
90
  </>
91
  );
92
  };
 
1
+ import EmbedModal from '@/components/api-service/embed-modal';
2
+ import { useShowEmbedModal } from '@/components/api-service/hooks';
3
+ import { SharedFrom } from '@/constants/chat';
4
+ import { useTranslate } from '@/hooks/common-hooks';
5
  import { useFetchFlow } from '@/hooks/flow-hooks';
6
  import { ArrowLeftOutlined } from '@ant-design/icons';
7
  import { Button, Flex, Space } from 'antd';
8
  import { useCallback } from 'react';
9
  import { Link, useParams } from 'umi';
 
10
  import {
11
  useGetBeginNodeDataQuery,
12
+ useGetBeginNodeDataQueryIsEmpty,
13
  useSaveGraph,
14
  useSaveGraphBeforeOpeningDebugDrawer,
15
  useWatchAgentChange,
 
27
  const { handleRun } = useSaveGraphBeforeOpeningDebugDrawer(showChatDrawer);
28
  const { data } = useFetchFlow();
29
  const { t } = useTranslate('flow');
 
 
 
 
 
 
30
  const { id } = useParams();
31
  const time = useWatchAgentChange(chatDrawerVisible);
32
  const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
33
+ const { showEmbedModal, hideEmbedModal, embedVisible, beta } =
34
+ useShowEmbedModal();
35
+ const isBeginNodeDataQueryEmpty = useGetBeginNodeDataQueryIsEmpty();
36
+
37
+ const handleShowEmbedModal = useCallback(() => {
38
+ showEmbedModal();
39
+ }, [showEmbedModal]);
40
 
41
  const handleRunAgent = useCallback(() => {
42
  const query: BeginQuery[] = getBeginNodeDataQuery();
 
73
  <Button type="primary" onClick={() => saveGraph()}>
74
  <b>{t('save')}</b>
75
  </Button>
76
+ <Button
77
+ type="primary"
78
+ onClick={handleShowEmbedModal}
79
+ disabled={!isBeginNodeDataQueryEmpty}
80
+ >
81
  <b>{t('publish')}</b>
 
 
 
82
  </Button>
83
  </Space>
84
  </Flex>
85
+ {embedVisible && (
86
+ <EmbedModal
87
+ visible={embedVisible}
88
+ hideModal={hideEmbedModal}
89
+ token={id!}
90
+ form={SharedFrom.Agent}
91
+ beta={beta}
92
+ isAgent
93
+ ></EmbedModal>
94
  )}
 
95
  </>
96
  );
97
  };
web/src/pages/flow/hooks.tsx CHANGED
@@ -474,6 +474,20 @@ export const useGetBeginNodeDataQuery = () => {
474
  return getBeginNodeDataQuery;
475
  };
476
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
  export const useSaveGraphBeforeOpeningDebugDrawer = (show: () => void) => {
478
  const { saveGraph, loading } = useSaveGraph();
479
  const { resetFlow } = useResetFlow();
 
474
  return getBeginNodeDataQuery;
475
  };
476
 
477
+ export const useGetBeginNodeDataQueryIsEmpty = () => {
478
+ const [isBeginNodeDataQueryEmpty, setIsBeginNodeDataQueryEmpty] =
479
+ useState(false);
480
+ const getBeginNodeDataQuery = useGetBeginNodeDataQuery();
481
+ const nodes = useGraphStore((state) => state.nodes);
482
+
483
+ useEffect(() => {
484
+ const query: BeginQuery[] = getBeginNodeDataQuery();
485
+ setIsBeginNodeDataQueryEmpty(query.length === 0);
486
+ }, [getBeginNodeDataQuery, nodes]);
487
+
488
+ return isBeginNodeDataQueryEmpty;
489
+ };
490
+
491
  export const useSaveGraphBeforeOpeningDebugDrawer = (show: () => void) => {
492
  const { saveGraph, loading } = useSaveGraph();
493
  const { resetFlow } = useResetFlow();
web/src/utils/authorization-util.ts CHANGED
@@ -47,9 +47,9 @@ const storage = {
47
  };
48
 
49
  export const getAuthorization = () => {
50
- const sharedId = getSearchValue('shared_id');
51
- const authorization = sharedId
52
- ? 'Bearer ' + sharedId
53
  : storage.getAuthorization() || '';
54
 
55
  return authorization;
 
47
  };
48
 
49
  export const getAuthorization = () => {
50
+ const auth = getSearchValue('auth');
51
+ const authorization = auth
52
+ ? 'Bearer ' + auth
53
  : storage.getAuthorization() || '';
54
 
55
  return authorization;
web/src/utils/document-util.ts CHANGED
@@ -1,10 +1,12 @@
1
  import { Images, SupportedPreviewDocumentTypes } from '@/constants/common';
 
2
  import { IChunk } from '@/interfaces/database/knowledge';
3
  import { UploadFile } from 'antd';
 
4
  import { v4 as uuid } from 'uuid';
5
 
6
  export const buildChunkHighlights = (
7
- selectedChunk: IChunk,
8
  size: { width: number; height: number },
9
  ) => {
10
  return Array.isArray(selectedChunk?.positions) &&
@@ -24,7 +26,11 @@ export const buildChunkHighlights = (
24
  text: '',
25
  emoji: '',
26
  },
27
- content: { text: selectedChunk.content_with_weight },
 
 
 
 
28
  position: {
29
  boundingRect: boundingRect,
30
  rects: [boundingRect],
 
1
  import { Images, SupportedPreviewDocumentTypes } from '@/constants/common';
2
+ import { IReferenceChunk } from '@/interfaces/database/chat';
3
  import { IChunk } from '@/interfaces/database/knowledge';
4
  import { UploadFile } from 'antd';
5
+ import { get } from 'lodash';
6
  import { v4 as uuid } from 'uuid';
7
 
8
  export const buildChunkHighlights = (
9
+ selectedChunk: IChunk | IReferenceChunk,
10
  size: { width: number; height: number },
11
  ) => {
12
  return Array.isArray(selectedChunk?.positions) &&
 
26
  text: '',
27
  emoji: '',
28
  },
29
+ content: {
30
+ text:
31
+ get(selectedChunk, 'content_with_weight') ||
32
+ get(selectedChunk, 'content', ''),
33
+ },
34
  position: {
35
  boundingRect: boundingRect,
36
  rects: [boundingRect],