Skip to content

Added Description to chat mode menu #743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Sep 16, 2024
Merged
26 changes: 20 additions & 6 deletions frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@
height: 55px;
object-fit: contain;
}
.webImg{

.webImg {
width: 80px;
height: 80px;
}
Expand Down Expand Up @@ -240,9 +241,11 @@
.ndl-widget-content>div {
overflow-wrap: break-word
}
.word-break{

.word-break {
word-break: break-word;
}

.cellClass {
width: 100%;
height: 100%;
Expand Down Expand Up @@ -345,22 +348,28 @@
margin-bottom: 0 !important;
}

.node_label__value-container--has-value ,.relationship_label__value-container--has-value{
.node_label__value-container--has-value,
.relationship_label__value-container--has-value {
max-height: 215px;
overflow-y: scroll !important;
scrollbar-width: thin;
}
.entity_extraction_Tab_node_label__value-container--has-value,.entity_extraction_Tab_relationship_label__value-container--has-value{

.entity_extraction_Tab_node_label__value-container--has-value,
.entity_extraction_Tab_relationship_label__value-container--has-value {
max-height: 100px;
overflow-y: scroll !important;
scrollbar-width: thin;
}
.tablet_entity_extraction_Tab_node_label__value-container--has-value,.tablet_entity_extraction_Tab_relationship_label__value-container--has-value{

.tablet_entity_extraction_Tab_node_label__value-container--has-value,
.tablet_entity_extraction_Tab_relationship_label__value-container--has-value {
max-height: 80px;
overflow-y: scroll !important;
scrollbar-width: thin;
}
.widthunset{

.widthunset {
width: initial !important;
height: initial !important;
}
Expand All @@ -372,4 +381,9 @@

.text-input-container.search-initiated {
width: 60dvh;
}

.custom-menu {
min-width: 250px;
max-width: 300px;
}
78 changes: 35 additions & 43 deletions frontend/src/components/ChatBot/ChatModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { StatusIndicator } from '@neo4j-ndl/react';
import { StatusIndicator, Typography } from '@neo4j-ndl/react';
import { useMemo } from 'react';
import { useFileContext } from '../../context/UsersFiles';
import CustomMenu from '../UI/Menu';
Expand All @@ -22,55 +22,47 @@ export default function ChatModeToggle({
const { setchatMode, chatMode, postProcessingTasks } = useFileContext();
const isCommunityAllowed = postProcessingTasks.includes('create_communities');
const { isGdsActive } = useCredentials();
const memoizedChatModes = useMemo(() => {
return isGdsActive && isCommunityAllowed
? chatModes
: chatModes?.filter((m) => !m.mode.includes('entity search+vector'));
}, [isGdsActive, isCommunityAllowed]);
const menuItems = useMemo(() => {
return memoizedChatModes?.map((m) => ({
title: (
<div>
<Typography variant='subheading-small'>
{m.mode.includes('+') ? capitalizeWithPlus(m.mode) : capitalize(m.mode)}
</Typography>
<div>
<Typography variant='body-small'>{m.description}</Typography>
</div>
</div>
),
onClick: () => {
setchatMode(m.mode);
closeHandler(); // Close the menu after setting the chat mode
},
disabledCondition: false,
description: (
<span>
{chatMode === m.mode && (
<>
<StatusIndicator type='success' /> Selected
</>
)}
</span>
),
}));
}, [chatMode, memoizedChatModes, setchatMode, closeHandler]);
return (
<CustomMenu
closeHandler={closeHandler}
open={open}
MenuAnchor={menuAnchor}
anchorPortal={anchorPortal}
disableBackdrop={disableBackdrop}
items={useMemo(() => {
if (isGdsActive && isCommunityAllowed) {
return chatModes?.map((m) => {
return {
title: m.includes('+') ? capitalizeWithPlus(m) : capitalize(m),
onClick: () => {
setchatMode(m);
},
disabledCondition: false,
description: (
<span>
{chatMode === m && (
<>
<StatusIndicator type={`${chatMode === m ? 'success' : 'unknown'}`} /> Selected
</>
)}
</span>
),
};
});
}
return chatModes
?.filter((s) => !s.includes('community'))
?.map((m) => {
return {
title: m.includes('+') ? capitalizeWithPlus(m) : capitalize(m),
onClick: () => {
setchatMode(m);
},
disabledCondition: false,
description: (
<span>
{chatMode === m && (
<>
<StatusIndicator type={`${chatMode === m ? 'success' : 'unknown'}`} /> Selected
</>
)}
</span>
),
};
});
}, [chatMode, chatModes, isCommunityAllowed, isGdsActive])}
items={menuItems}
/>
);
}
11 changes: 10 additions & 1 deletion frontend/src/components/Graph/LegendsChip.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
import { LegendChipProps } from '../../types';
import { graphLabels } from '../../utils/Constants';
import Legend from '../UI/Legend';

export const LegendsChip: React.FunctionComponent<LegendChipProps> = ({ scheme, label, type, count, onClick }) => {
return <Legend title={label} count={count} bgColor={scheme[label]} type={type} onClick={onClick} />;
return (
<Legend
title={label === '__Community__' ? graphLabels.community : label}
count={count}
bgColor={scheme[label]}
type={type}
onClick={onClick}
/>
);
};
2 changes: 2 additions & 0 deletions frontend/src/components/Layout/SideNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ const SideNav: React.FC<SideNavProps> = ({
</Tip>
{!isChatModalOpen && (
<SideNavigation.Item
selected={showChatMode}
onClick={(e) => {
setchatModeAnchor(e.currentTarget);
setshowChatMode(true);
Expand All @@ -217,6 +218,7 @@ const SideNav: React.FC<SideNavProps> = ({
closeHandler={() => setshowChatMode(false)}
menuAnchor={chatModeAnchor}
disableBackdrop={true}
anchorPortal={true}
></ChatModeToggle>
</>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ export default function DeduplicationTab() {
const onRemove = (nodeid: string, similarNodeId: string) => {
setDuplicateNodes((prev) => {
return prev.map((d) =>
(d.e.elementId === nodeid
d.e.elementId === nodeid
? {
...d,
similar: d.similar.filter((n) => n.elementId != similarNodeId),
}
: d)
: d
);
});
};
Expand Down
31 changes: 17 additions & 14 deletions frontend/src/components/UI/Menu.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Menu } from '@neo4j-ndl/react';
import { Menuitems, Origin } from '../../types';

export default function CustomMenu({
open,
closeHandler,
Expand All @@ -23,25 +22,29 @@ export default function CustomMenu({
return (
<Menu
open={open}
onClose={closeHandler}
onClose={() => {
closeHandler();
}}
anchorOrigin={anchorOrigin}
transformOrigin={transformOrigin}
anchorPortal={anchorPortal}
anchorEl={MenuAnchor}
disableBackdrop={disableBackdrop}
className='custom-menu'
>
{items?.map((i, idx) => {
return (
<Menu.Item
key={`${idx}${i.title}`}
title={i.title}
onClick={i.onClick}
disabled={i.disabledCondition}
className={i.isSelected ? i.selectedClassName : ''}
description={i.description}
/>
);
})}
{items?.map((i, idx) => (
<Menu.Item
key={`${idx}${i.title}`}
title={i.title}
onClick={() => {
i.onClick();
closeHandler();
}}
disabled={i.disabledCondition}
className={i.isSelected ? i.selectedClassName : ''}
description={i.description}
/>
))}
</Menu>
);
}
2 changes: 1 addition & 1 deletion frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ export interface SettingsModalProps {
onClear?: () => void;
}
export interface Menuitems {
title: string;
title: string | JSX.Element;
onClick: () => void;
disabledCondition: boolean;
description?: string | React.ReactNode;
Expand Down
51 changes: 43 additions & 8 deletions frontend/src/utils/Constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NvlOptions } from '@neo4j-nvl/base';
import { GraphType, OptionType } from '../types';
import { getDescriptionForChatMode } from './Utils';

export const document = `+ [docs]`;

Expand Down Expand Up @@ -28,10 +29,12 @@ export const docChunkEntities = `+[chunks]
+ collect { MATCH p=(c)-[:SIMILAR]-() RETURN p } // similar-chunks
//chunks with entities
+ collect { OPTIONAL MATCH p=(c:Chunk)-[:HAS_ENTITY]->(e)-[*0..1]-(:!Chunk) RETURN p }`;

export const APP_SOURCES =
process.env.VITE_REACT_APP_SOURCES !== ''
? (process.env.VITE_REACT_APP_SOURCES?.split(',') as string[])
: ['gcs', 's3', 'local', 'wiki', 'youtube', 'web'];

export const llms =
process.env?.VITE_LLM_MODELS?.trim() != ''
? (process.env.VITE_LLM_MODELS?.split(',') as string[])
Expand All @@ -56,18 +59,50 @@ export const defaultLLM = llms?.includes('openai-gpt-4o')
: llms?.includes('gemini-1.0-pro')
? 'gemini-1.0-pro'
: 'diffbot';

// export const chatModes =
// process.env?.VITE_CHAT_MODES?.trim() != ''
// ? process.env.VITE_CHAT_MODES?.split(',')
// : ['vector', 'graph', 'graph+vector', 'fulltext', 'graph+vector+fulltext', 'local community', 'global community'];

export const chatModes =
process.env?.VITE_CHAT_MODES?.trim() != ''
? process.env.VITE_CHAT_MODES?.split(',')
? process.env.VITE_CHAT_MODES?.split(',').map((mode) => ({
mode: mode.trim(),
description: getDescriptionForChatMode(mode.trim()),
}))
: [
'vector',
'graph',
'graph+vector',
'fulltext',
'graph+vector+fulltext',
'entity search+vector',
'global community',
{
mode: 'vector',
description: 'Utilizes vector indexing on text chunks to enable semantic similarity search.',
},
{
mode: 'graph',
description:
'Leverages text-to-cypher translation to query a database and retrieve relevant data, ensuring a highly targeted and contextually accurate response.',
},
{
mode: 'graph+vector',
description:
'Combines vector indexing on text chunks with graph connections, enhancing search results with contextual relevance by considering relationships between concepts.',
},
{
mode: 'fulltext',
description:
'Employs a fulltext index on text chunks for rapid keyword-based search, efficiently identifying documents containing specific words or phrases.',
},
{
mode: 'graph+vector+fulltext',
description:
'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.',
},
{
mode: 'entity search+vector',
description:
'Combines entity node vector indexing with graph connections for accurate entity-based search, providing the most relevant response.',
},
];

export const chunkSize = process.env.VITE_CHUNK_SIZE ? parseInt(process.env.VITE_CHUNK_SIZE) : 1 * 1024 * 1024;
export const timeperpage = process.env.VITE_TIME_PER_PAGE ? parseInt(process.env.VITE_TIME_PER_PAGE) : 50;
export const timePerByte = 0.2;
Expand Down
21 changes: 20 additions & 1 deletion frontend/src/utils/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ export const isFileCompleted = (waitingFile: CustomFile, item: SourceNode) =>
waitingFile && item.status === 'Completed';

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

export const isProcessingFileValid = (item: SourceNode, userCredentials: UserCredentials) => {
return item.status === 'Processing' && item.fileName != undefined && userCredentials && userCredentials.database;
Expand All @@ -409,6 +409,25 @@ export const capitalizeWithPlus = (s: string) => {
.map((s) => capitalize(s))
.join('+');
};

export const getDescriptionForChatMode = (mode: string): string => {
switch (mode.toLowerCase()) {
case 'vector':
return 'Utilizes vector indexing on text chunks to enable semantic similarity search.';
case 'graph':
return 'Leverages text-to-cypher translation to query a database and retrieve relevant data, ensuring a highly targeted and contextually accurate response.';
case 'graph+vector':
return 'Combines vector indexing on text chunks with graph connections, enhancing search results with contextual relevance by considering relationships between concepts.';
case 'fulltext':
return 'Employs a fulltext index on text chunks for rapid keyword-based search, efficiently identifying documents containing specific words or phrases.';
case 'graph+vector+fulltext':
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.';
case 'entity search+vector':
return 'Combines entity node vector indexing with graph connections for accurate entity-based search, providing the most relevant response.';
default:
return 'Chat mode description not available'; // Fallback description
}
};
export const getLogo = (mode: string): Record<string, string> => {
if (mode === 'light') {
return {
Expand Down