Skip to content

Commit bc09b86

Browse files
Added Description to chat mode menu (#743)
* added tooltips to chat mode menu * addition of description to menu * 741-tooltips-to-selectOptions * menu changes * acommunities name change * close changes * name changes * format fixes
1 parent 8f0a706 commit bc09b86

File tree

9 files changed

+150
-76
lines changed

9 files changed

+150
-76
lines changed

frontend/src/App.css

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@
121121
height: 55px;
122122
object-fit: contain;
123123
}
124-
.webImg{
124+
125+
.webImg {
125126
width: 80px;
126127
height: 80px;
127128
}
@@ -240,9 +241,11 @@
240241
.ndl-widget-content>div {
241242
overflow-wrap: break-word
242243
}
243-
.word-break{
244+
245+
.word-break {
244246
word-break: break-word;
245247
}
248+
246249
.cellClass {
247250
width: 100%;
248251
height: 100%;
@@ -345,22 +348,28 @@
345348
margin-bottom: 0 !important;
346349
}
347350

348-
.node_label__value-container--has-value ,.relationship_label__value-container--has-value{
351+
.node_label__value-container--has-value,
352+
.relationship_label__value-container--has-value {
349353
max-height: 215px;
350354
overflow-y: scroll !important;
351355
scrollbar-width: thin;
352356
}
353-
.entity_extraction_Tab_node_label__value-container--has-value,.entity_extraction_Tab_relationship_label__value-container--has-value{
357+
358+
.entity_extraction_Tab_node_label__value-container--has-value,
359+
.entity_extraction_Tab_relationship_label__value-container--has-value {
354360
max-height: 100px;
355361
overflow-y: scroll !important;
356362
scrollbar-width: thin;
357363
}
358-
.tablet_entity_extraction_Tab_node_label__value-container--has-value,.tablet_entity_extraction_Tab_relationship_label__value-container--has-value{
364+
365+
.tablet_entity_extraction_Tab_node_label__value-container--has-value,
366+
.tablet_entity_extraction_Tab_relationship_label__value-container--has-value {
359367
max-height: 80px;
360368
overflow-y: scroll !important;
361369
scrollbar-width: thin;
362370
}
363-
.widthunset{
371+
372+
.widthunset {
364373
width: initial !important;
365374
height: initial !important;
366375
}
@@ -372,4 +381,9 @@
372381

373382
.text-input-container.search-initiated {
374383
width: 60dvh;
384+
}
385+
386+
.custom-menu {
387+
min-width: 250px;
388+
max-width: 300px;
375389
}
Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { StatusIndicator } from '@neo4j-ndl/react';
1+
import { StatusIndicator, Typography } from '@neo4j-ndl/react';
22
import { useMemo } from 'react';
33
import { useFileContext } from '../../context/UsersFiles';
44
import CustomMenu from '../UI/Menu';
@@ -22,55 +22,47 @@ export default function ChatModeToggle({
2222
const { setchatMode, chatMode, postProcessingTasks } = useFileContext();
2323
const isCommunityAllowed = postProcessingTasks.includes('create_communities');
2424
const { isGdsActive } = useCredentials();
25+
const memoizedChatModes = useMemo(() => {
26+
return isGdsActive && isCommunityAllowed
27+
? chatModes
28+
: chatModes?.filter((m) => !m.mode.includes('entity search+vector'));
29+
}, [isGdsActive, isCommunityAllowed]);
30+
const menuItems = useMemo(() => {
31+
return memoizedChatModes?.map((m) => ({
32+
title: (
33+
<div>
34+
<Typography variant='subheading-small'>
35+
{m.mode.includes('+') ? capitalizeWithPlus(m.mode) : capitalize(m.mode)}
36+
</Typography>
37+
<div>
38+
<Typography variant='body-small'>{m.description}</Typography>
39+
</div>
40+
</div>
41+
),
42+
onClick: () => {
43+
setchatMode(m.mode);
44+
closeHandler(); // Close the menu after setting the chat mode
45+
},
46+
disabledCondition: false,
47+
description: (
48+
<span>
49+
{chatMode === m.mode && (
50+
<>
51+
<StatusIndicator type='success' /> Selected
52+
</>
53+
)}
54+
</span>
55+
),
56+
}));
57+
}, [chatMode, memoizedChatModes, setchatMode, closeHandler]);
2558
return (
2659
<CustomMenu
2760
closeHandler={closeHandler}
2861
open={open}
2962
MenuAnchor={menuAnchor}
3063
anchorPortal={anchorPortal}
3164
disableBackdrop={disableBackdrop}
32-
items={useMemo(() => {
33-
if (isGdsActive && isCommunityAllowed) {
34-
return chatModes?.map((m) => {
35-
return {
36-
title: m.includes('+') ? capitalizeWithPlus(m) : capitalize(m),
37-
onClick: () => {
38-
setchatMode(m);
39-
},
40-
disabledCondition: false,
41-
description: (
42-
<span>
43-
{chatMode === m && (
44-
<>
45-
<StatusIndicator type={`${chatMode === m ? 'success' : 'unknown'}`} /> Selected
46-
</>
47-
)}
48-
</span>
49-
),
50-
};
51-
});
52-
}
53-
return chatModes
54-
?.filter((s) => !s.includes('community'))
55-
?.map((m) => {
56-
return {
57-
title: m.includes('+') ? capitalizeWithPlus(m) : capitalize(m),
58-
onClick: () => {
59-
setchatMode(m);
60-
},
61-
disabledCondition: false,
62-
description: (
63-
<span>
64-
{chatMode === m && (
65-
<>
66-
<StatusIndicator type={`${chatMode === m ? 'success' : 'unknown'}`} /> Selected
67-
</>
68-
)}
69-
</span>
70-
),
71-
};
72-
});
73-
}, [chatMode, chatModes, isCommunityAllowed, isGdsActive])}
65+
items={menuItems}
7466
/>
7567
);
7668
}
Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { LegendChipProps } from '../../types';
2+
import { graphLabels } from '../../utils/Constants';
23
import Legend from '../UI/Legend';
34

45
export const LegendsChip: React.FunctionComponent<LegendChipProps> = ({ scheme, label, type, count, onClick }) => {
5-
return <Legend title={label} count={count} bgColor={scheme[label]} type={type} onClick={onClick} />;
6+
return (
7+
<Legend
8+
title={label === '__Community__' ? graphLabels.community : label}
9+
count={count}
10+
bgColor={scheme[label]}
11+
type={type}
12+
onClick={onClick}
13+
/>
14+
);
615
};

frontend/src/components/Layout/SideNav.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ const SideNav: React.FC<SideNavProps> = ({
203203
</Tip>
204204
{!isChatModalOpen && (
205205
<SideNavigation.Item
206+
selected={showChatMode}
206207
onClick={(e) => {
207208
setchatModeAnchor(e.currentTarget);
208209
setshowChatMode(true);
@@ -217,6 +218,7 @@ const SideNav: React.FC<SideNavProps> = ({
217218
closeHandler={() => setshowChatMode(false)}
218219
menuAnchor={chatModeAnchor}
219220
disableBackdrop={true}
221+
anchorPortal={true}
220222
></ChatModeToggle>
221223
</>
222224
}

frontend/src/components/Popups/GraphEnhancementDialog/Deduplication/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,12 @@ export default function DeduplicationTab() {
8080
const onRemove = (nodeid: string, similarNodeId: string) => {
8181
setDuplicateNodes((prev) => {
8282
return prev.map((d) =>
83-
(d.e.elementId === nodeid
83+
d.e.elementId === nodeid
8484
? {
8585
...d,
8686
similar: d.similar.filter((n) => n.elementId != similarNodeId),
8787
}
88-
: d)
88+
: d
8989
);
9090
});
9191
};

frontend/src/components/UI/Menu.tsx

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Menu } from '@neo4j-ndl/react';
22
import { Menuitems, Origin } from '../../types';
3-
43
export default function CustomMenu({
54
open,
65
closeHandler,
@@ -23,25 +22,29 @@ export default function CustomMenu({
2322
return (
2423
<Menu
2524
open={open}
26-
onClose={closeHandler}
25+
onClose={() => {
26+
closeHandler();
27+
}}
2728
anchorOrigin={anchorOrigin}
2829
transformOrigin={transformOrigin}
2930
anchorPortal={anchorPortal}
3031
anchorEl={MenuAnchor}
3132
disableBackdrop={disableBackdrop}
33+
className='custom-menu'
3234
>
33-
{items?.map((i, idx) => {
34-
return (
35-
<Menu.Item
36-
key={`${idx}${i.title}`}
37-
title={i.title}
38-
onClick={i.onClick}
39-
disabled={i.disabledCondition}
40-
className={i.isSelected ? i.selectedClassName : ''}
41-
description={i.description}
42-
/>
43-
);
44-
})}
35+
{items?.map((i, idx) => (
36+
<Menu.Item
37+
key={`${idx}${i.title}`}
38+
title={i.title}
39+
onClick={() => {
40+
i.onClick();
41+
closeHandler();
42+
}}
43+
disabled={i.disabledCondition}
44+
className={i.isSelected ? i.selectedClassName : ''}
45+
description={i.description}
46+
/>
47+
))}
4548
</Menu>
4649
);
4750
}

frontend/src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ export interface SettingsModalProps {
534534
onClear?: () => void;
535535
}
536536
export interface Menuitems {
537-
title: string;
537+
title: string | JSX.Element;
538538
onClick: () => void;
539539
disabledCondition: boolean;
540540
description?: string | React.ReactNode;

frontend/src/utils/Constants.ts

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NvlOptions } from '@neo4j-nvl/base';
22
import { GraphType, OptionType } from '../types';
3+
import { getDescriptionForChatMode } from './Utils';
34

45
export const document = `+ [docs]`;
56

@@ -28,10 +29,12 @@ export const docChunkEntities = `+[chunks]
2829
+ collect { MATCH p=(c)-[:SIMILAR]-() RETURN p } // similar-chunks
2930
//chunks with entities
3031
+ collect { OPTIONAL MATCH p=(c:Chunk)-[:HAS_ENTITY]->(e)-[*0..1]-(:!Chunk) RETURN p }`;
32+
3133
export const APP_SOURCES =
3234
process.env.VITE_REACT_APP_SOURCES !== ''
3335
? (process.env.VITE_REACT_APP_SOURCES?.split(',') as string[])
3436
: ['gcs', 's3', 'local', 'wiki', 'youtube', 'web'];
37+
3538
export const llms =
3639
process.env?.VITE_LLM_MODELS?.trim() != ''
3740
? (process.env.VITE_LLM_MODELS?.split(',') as string[])
@@ -56,18 +59,50 @@ export const defaultLLM = llms?.includes('openai-gpt-4o')
5659
: llms?.includes('gemini-1.0-pro')
5760
? 'gemini-1.0-pro'
5861
: 'diffbot';
62+
63+
// export const chatModes =
64+
// process.env?.VITE_CHAT_MODES?.trim() != ''
65+
// ? process.env.VITE_CHAT_MODES?.split(',')
66+
// : ['vector', 'graph', 'graph+vector', 'fulltext', 'graph+vector+fulltext', 'local community', 'global community'];
67+
5968
export const chatModes =
6069
process.env?.VITE_CHAT_MODES?.trim() != ''
61-
? process.env.VITE_CHAT_MODES?.split(',')
70+
? process.env.VITE_CHAT_MODES?.split(',').map((mode) => ({
71+
mode: mode.trim(),
72+
description: getDescriptionForChatMode(mode.trim()),
73+
}))
6274
: [
63-
'vector',
64-
'graph',
65-
'graph+vector',
66-
'fulltext',
67-
'graph+vector+fulltext',
68-
'entity search+vector',
69-
'global community',
75+
{
76+
mode: 'vector',
77+
description: 'Utilizes vector indexing on text chunks to enable semantic similarity search.',
78+
},
79+
{
80+
mode: 'graph',
81+
description:
82+
'Leverages text-to-cypher translation to query a database and retrieve relevant data, ensuring a highly targeted and contextually accurate response.',
83+
},
84+
{
85+
mode: 'graph+vector',
86+
description:
87+
'Combines vector indexing on text chunks with graph connections, enhancing search results with contextual relevance by considering relationships between concepts.',
88+
},
89+
{
90+
mode: 'fulltext',
91+
description:
92+
'Employs a fulltext index on text chunks for rapid keyword-based search, efficiently identifying documents containing specific words or phrases.',
93+
},
94+
{
95+
mode: 'graph+vector+fulltext',
96+
description:
97+
'Merges vector indexing, graph connections, and fulltext indexing for a comprehensive search approach, combining semantic similarity, contextual relevance, and keyword-based search for optimal results.',
98+
},
99+
{
100+
mode: 'entity search+vector',
101+
description:
102+
'Combines entity node vector indexing with graph connections for accurate entity-based search, providing the most relevant response.',
103+
},
70104
];
105+
71106
export const chunkSize = process.env.VITE_CHUNK_SIZE ? parseInt(process.env.VITE_CHUNK_SIZE) : 1 * 1024 * 1024;
72107
export const timeperpage = process.env.VITE_TIME_PER_PAGE ? parseInt(process.env.VITE_TIME_PER_PAGE) : 50;
73108
export const timePerByte = 0.2;

frontend/src/utils/Utils.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ export const isFileCompleted = (waitingFile: CustomFile, item: SourceNode) =>
392392
waitingFile && item.status === 'Completed';
393393

394394
export const calculateProcessedCount = (prev: number, batchSize: number) =>
395-
(prev === batchSize ? batchSize - 1 : prev + 1);
395+
prev === batchSize ? batchSize - 1 : prev + 1;
396396

397397
export const isProcessingFileValid = (item: SourceNode, userCredentials: UserCredentials) => {
398398
return item.status === 'Processing' && item.fileName != undefined && userCredentials && userCredentials.database;
@@ -409,6 +409,25 @@ export const capitalizeWithPlus = (s: string) => {
409409
.map((s) => capitalize(s))
410410
.join('+');
411411
};
412+
413+
export const getDescriptionForChatMode = (mode: string): string => {
414+
switch (mode.toLowerCase()) {
415+
case 'vector':
416+
return 'Utilizes vector indexing on text chunks to enable semantic similarity search.';
417+
case 'graph':
418+
return 'Leverages text-to-cypher translation to query a database and retrieve relevant data, ensuring a highly targeted and contextually accurate response.';
419+
case 'graph+vector':
420+
return 'Combines vector indexing on text chunks with graph connections, enhancing search results with contextual relevance by considering relationships between concepts.';
421+
case 'fulltext':
422+
return 'Employs a fulltext index on text chunks for rapid keyword-based search, efficiently identifying documents containing specific words or phrases.';
423+
case 'graph+vector+fulltext':
424+
return 'Merges vector indexing, graph connections, and fulltext indexing for a comprehensive search approach, combining semantic similarity, contextual relevance, and keyword-based search for optimal results.';
425+
case 'entity search+vector':
426+
return 'Combines entity node vector indexing with graph connections for accurate entity-based search, providing the most relevant response.';
427+
default:
428+
return 'Chat mode description not available'; // Fallback description
429+
}
430+
};
412431
export const getLogo = (mode: string): Record<string, string> => {
413432
if (mode === 'light') {
414433
return {

0 commit comments

Comments
 (0)