From a2d41f21df3792db90daec1f215715764172f2e0 Mon Sep 17 00:00:00 2001 From: Harry Li <harry.li@ll.mit.edu> Date: Fri, 17 Jan 2025 16:24:08 -0500 Subject: [PATCH] added icons --- src/App.tsx | 23 +++++++++++++-- src/components/Chat/Chat.module.scss | 4 --- src/components/Chat/Chat.tsx | 19 +++++++++++-- src/components/IDTable/IDTable.tsx | 9 +++++- src/components/InfoModal.tsx | 28 +++++++++++++++++++ src/components/LLMWarning.tsx | 23 +++++++++++++++ .../QueryEditor/QueryEditor.module.scss | 9 ++++++ src/components/QueryEditor/QueryEditor.tsx | 15 ++++------ 8 files changed, 111 insertions(+), 19 deletions(-) create mode 100644 src/components/InfoModal.tsx create mode 100644 src/components/LLMWarning.tsx diff --git a/src/App.tsx b/src/App.tsx index 41ba1ae..02bee58 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,6 +7,8 @@ import { Chat } from 'components/Chat/Chat'; import { DemoModeModal } from 'components/DemoModeModal'; import { ErrorMessage } from 'components/ErrorMessage'; import { IDTableContainer } from 'components/IDTable/IDTable'; +import { InfoModal } from 'components/InfoModal'; +import { LLMWarning } from 'components/LLMWarning'; import { QueryEditor } from 'components/QueryEditor/QueryEditor' import { QueryVisualization } from "components/QueryVisualization/QueryVisualization"; import { ResultsTable } from 'components/ResultsTable/ResultsTable'; @@ -67,9 +69,26 @@ function Results() { return ( <> <Title order={4}>Results Summary from LLM</Title> - {results.summary ? <p>{results.summary}</p> : <ErrorMessage>There was an error generating a summary.</ErrorMessage>} + {results.summary ? ( + <div> + <LLMWarning> + <p>This results summary was generated by an LLM that can make mistakes. Refer below to the Results Table from KG for ground-truth data.</p> + <p>Note that the absence of data does not necessairly mean that there is no data. It is possible that the query did not find what that you are looking for.</p> + </LLMWarning> + + <p>{results.summary}</p> + </div> + ) : <ErrorMessage>There was an error generating a summary.</ErrorMessage>} + <hr/> - <Title order={4}>Results Table from KG</Title> + + <Title order={4}> + Results Table from KG + <InfoModal title="Results Table from KG"> + <p>These are ground-truth results retrieved from the KG using the query you executed.</p> + <p>Note that the absence of data does not necessairly mean that there is no data. It is possible that the query did not find what that you are looking for.</p> + </InfoModal> + </Title> <ResultsTable data={results.data}/> </> ) diff --git a/src/components/Chat/Chat.module.scss b/src/components/Chat/Chat.module.scss index 016d4ed..221b1ff 100644 --- a/src/components/Chat/Chat.module.scss +++ b/src/components/Chat/Chat.module.scss @@ -43,10 +43,6 @@ padding: 0.5rem; margin-bottom: 0.5rem; border-radius: 5px; - - button { - margin-top: 0.5rem; - } } &.user { diff --git a/src/components/Chat/Chat.tsx b/src/components/Chat/Chat.tsx index 905e54b..3d6e6cf 100644 --- a/src/components/Chat/Chat.tsx +++ b/src/components/Chat/Chat.tsx @@ -10,6 +10,7 @@ import { useMutation } from "@tanstack/react-query"; import { IconCaretRight, IconSettings, IconZoomCode } from '@tabler/icons-react'; import { ErrorMessage } from 'components/ErrorMessage'; +import { LLMWarning } from 'components/LLMWarning'; import { useMakeChatGPTAPIInstance } from 'hooks/useMakeChatGPTAPIInstance'; import { useRunQuery } from 'hooks/useRunQuery'; @@ -152,6 +153,10 @@ function RenderLLMResponse({ if(parsedQuery) { return ( <div className={styles.chat}> + <LLMWarning> + <p>This was generated by an LLM that can make mistakes.</p> + </LLMWarning> + <RenderSparqlQuery pre={parsedQuery.pre} query={parsedQuery.query.trim()} @@ -163,7 +168,15 @@ function RenderLLMResponse({ ) } - return <pre className={styles.chat}>{text}</pre> + return ( + <div className={styles.chat}> + <LLMWarning> + <p>This was generated by an LLM that can make mistakes.</p> + </LLMWarning> + + <pre>{text}</pre> + </div> + ) } @@ -204,9 +217,9 @@ function RenderSparqlQuery({ </div> <pre>{post}</pre> <br/> - <Button onClick={() => setInputText("You identified the wrong data. I was actually looking for: ")}>You identified the wrong data</Button> + <Button onClick={() => setInputText("You identified the wrong data. I was actually looking for: ")} style={{marginTop:"0.5rem"}}>You identified the wrong data</Button> <br/> - <Button onClick={() => setInputText("You misunderstood my question. I was actually asking about: ")}>You misunderstood my question</Button> + <Button onClick={() => setInputText("You misunderstood my question. I was actually asking about: ")} style={{marginTop:"0.5rem"}}>You misunderstood my question</Button> <br/> <Button onClick={() => setInputText("I want to ask something different: ")}>I want to ask something different</Button> </> diff --git a/src/components/IDTable/IDTable.tsx b/src/components/IDTable/IDTable.tsx index b29ffc2..405e598 100644 --- a/src/components/IDTable/IDTable.tsx +++ b/src/components/IDTable/IDTable.tsx @@ -4,6 +4,8 @@ import { createColumnHelper, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { Table, Title } from "@mantine/core"; +import { InfoModal } from "components/InfoModal"; + import { useAppSelector } from "redux/store"; import { IDTableEntitiesType } from "types/idTable"; @@ -38,7 +40,12 @@ export function IDTableContainer () { return ( <div id={styles["id-table-container"]}> - <Title order={4}>Entity-Relation Table from KG</Title> + <Title order={4}> + Entity-Relation Table from KG + <InfoModal title="Entity-Relation Table from KG"> + <p>This table extracts the IDs from your query and explains what they mean in the KG.</p> + </InfoModal> + </Title> {content} </div> ) diff --git a/src/components/InfoModal.tsx b/src/components/InfoModal.tsx new file mode 100644 index 0000000..5ec1baa --- /dev/null +++ b/src/components/InfoModal.tsx @@ -0,0 +1,28 @@ +import { useDisclosure } from '@mantine/hooks'; +import { Modal, ActionIcon } from '@mantine/core'; +import { IconQuestionMark } from '@tabler/icons-react'; + +export const InfoModal = ({ + children, + title, +}:{ + children: React.ReactNode, + title: string, +}) => { + const [opened, { open, close }] = useDisclosure(false); + + return ( + <> + <Modal opened={opened} onClose={close} title={title}> + {children} + </Modal> + + <ActionIcon size="xs" variant="filled" aria-label={title} color="gray" onClick={open} style={{ + marginLeft: "0.5em", + transform: "translateY(0.1em)", + }}> + <IconQuestionMark/> + </ActionIcon> + </> + ); +} \ No newline at end of file diff --git a/src/components/LLMWarning.tsx b/src/components/LLMWarning.tsx new file mode 100644 index 0000000..e88357a --- /dev/null +++ b/src/components/LLMWarning.tsx @@ -0,0 +1,23 @@ +import { useDisclosure } from '@mantine/hooks'; +import { Modal, ActionIcon } from '@mantine/core'; +import { IconAlertTriangle } from '@tabler/icons-react'; + +export const LLMWarning = ({ + children, +}:{ + children: React.ReactNode, +}) => { + const [opened, { open, close }] = useDisclosure(false); + + return ( + <> + <Modal opened={opened} onClose={close} title="LLM Hallucination Warning"> + {children} + </Modal> + + <ActionIcon size="xs" variant="filled" aria-label="LLM Hallucination Warning" color="yellow" onClick={open} style={{float:"right"}}> + <IconAlertTriangle/> + </ActionIcon> + </> + ); +} \ No newline at end of file diff --git a/src/components/QueryEditor/QueryEditor.module.scss b/src/components/QueryEditor/QueryEditor.module.scss index 1d85fc5..e18f120 100644 --- a/src/components/QueryEditor/QueryEditor.module.scss +++ b/src/components/QueryEditor/QueryEditor.module.scss @@ -6,4 +6,13 @@ background-color: #fff; width: 100%; overflow-x: auto; +} + +.query-history-button { + margin-top: 1em; + + span { + white-space: wrap; + overflow: auto; + } } \ No newline at end of file diff --git a/src/components/QueryEditor/QueryEditor.tsx b/src/components/QueryEditor/QueryEditor.tsx index 72d8bbc..4f10fe9 100644 --- a/src/components/QueryEditor/QueryEditor.tsx +++ b/src/components/QueryEditor/QueryEditor.tsx @@ -52,15 +52,12 @@ export function QueryEditor() { <Divider/> {queryHistory.map((record,i) => { return ( - <div key={i}> - <br/> - <Button key={i} variant='default' onClick={() => { - dispatch(setQueryValue(record.query)) - dispatch(setResults(record.results)) - }}> - {i+1}: {record.name || "There was an error generating a name for this query"} - </Button> - </div> + <Button key={i} className={styles["query-history-button"]} fullWidth variant='default' onClick={() => { + dispatch(setQueryValue(record.query)) + dispatch(setResults(record.results)) + }}> + {i+1}: {record.name || "There was an error generating a name for this query"} + </Button> ) })}