From 0a2f837fb2f5364ebcf37a3d34a1d76c1c545aaf Mon Sep 17 00:00:00 2001 From: Timothy Carambat Date: Thu, 27 Jul 2023 22:33:27 -0700 Subject: [PATCH] improve citations to show all text chunks referred and expand the citation to view full referenced text (#161) * improve citations to show all text chunks referred and expand the citation to view full referenced text chunk text of same document together * remove debug --- frontend/src/components/Sidebar/index.jsx | 4 +- .../ChatHistory/Citation/index.jsx | 99 +++++++++++++++++++ .../ChatHistory/HistoricalMessage/index.jsx | 49 +-------- .../ChatHistory/PromptReply/index.jsx | 47 +-------- .../ChatContainer/PromptInput/index.jsx | 24 +++-- frontend/src/index.css | 20 ++++ frontend/tailwind.config.js | 2 +- server/utils/helpers/index.js | 10 +- server/utils/vectorDbProviders/lance/index.js | 11 +-- 9 files changed, 146 insertions(+), 120 deletions(-) create mode 100644 frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx diff --git a/frontend/src/components/Sidebar/index.jsx b/frontend/src/components/Sidebar/index.jsx index b1287282..3b67abf3 100644 --- a/frontend/src/components/Sidebar/index.jsx +++ b/frontend/src/components/Sidebar/index.jsx @@ -129,7 +129,7 @@ export default function Sidebar() { @MintplexLabs @@ -295,7 +295,7 @@ export function SidebarMobileHeader() { @MintplexLabs diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx new file mode 100644 index 00000000..9ffe9713 --- /dev/null +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/Citation/index.jsx @@ -0,0 +1,99 @@ +import { memo, useState } from "react"; +import { Maximize2, Minimize2 } from "react-feather"; +import { v4 } from "uuid"; +import { decode as HTMLDecode } from "he"; + +function combineLikeSources(sources) { + const combined = {}; + sources.forEach((source) => { + const { id, title, text } = source; + if (combined.hasOwnProperty(title)) { + combined[title].text += `\n\n ---- Chunk ${id || ""} ---- \n\n${text}`; + combined[title].references += 1; + } else { + combined[title] = { title, text, references: 1 }; + } + }); + return Object.values(combined); +} + +export default function Citations({ sources = [] }) { + if (sources.length === 0) return null; + + return ( +
+
+
+ {combineLikeSources(sources).map((source) => ( + + ))} +
+
+

+ *citations may not be relevant to end result. +

+
+ ); +} + +const Citation = memo(({ source, id }) => { + const [maximized, setMaximized] = useState(false); + const { references = 0, title, text } = source; + if (title?.length === 0 || text?.length === 0) return null; + const handleMinMax = () => { + setMaximized(!maximized); + Array.from( + document?.querySelectorAll( + `div[data-citation]:not([data-citation="${id}"])` + ) + ).forEach((el) => { + const func = maximized ? "remove" : "add"; + el.classList[func]("hidden"); + }); + }; + + return ( +
+
+

+ {title} +

+ +
+
+

+ {references > 1 && ( +

+ referenced {references} times. +

+ )} + {HTMLDecode(text)} +

+
+
+
+ ); +}); diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx index ee5af67e..4acda9b8 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/HistoricalMessage/index.jsx @@ -1,10 +1,9 @@ -import { useEffect, useRef, memo, useState } from "react"; +import { useEffect, useRef, memo } from "react"; import { AlertTriangle } from "react-feather"; import Jazzicon from "../../../../UserIcon"; -import { v4 } from "uuid"; -import { decode as HTMLDecode } from "he"; import renderMarkdown from "../../../../../utils/chat/markdown"; import { userFromStorage } from "../../../../../utils/request"; +import Citations from "../Citation"; function HistoricalMessage({ message, @@ -55,7 +54,7 @@ function HistoricalMessage({
@@ -64,46 +63,4 @@ function HistoricalMessage({ ); } -const Citations = ({ sources = [] }) => { - const [show, setShow] = useState(false); - if (sources.length === 0) return null; - - return ( -
- - {show && ( - <> -
- {sources.map((source) => { - const { id = null, title, url } = source; - const handleClick = () => { - if (!url) return false; - window.open(url, "_blank"); - }; - return ( - - ); - })} -
-

- *citation may not be relevant to end result. -

- - )} -
- ); -}; - export default memo(HistoricalMessage); diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx index a0bf02bc..a82c25a4 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/ChatHistory/PromptReply/index.jsx @@ -1,9 +1,8 @@ -import { memo, useEffect, useRef, useState } from "react"; +import { memo, useEffect, useRef } from "react"; import { AlertTriangle } from "react-feather"; import Jazzicon from "../../../../UserIcon"; -import { v4 } from "uuid"; -import { decode as HTMLDecode } from "he"; import renderMarkdown from "../../../../../utils/chat/markdown"; +import Citations from "../Citation"; function PromptReply({ uuid, @@ -69,46 +68,4 @@ function PromptReply({ ); } -const Citations = ({ sources = [] }) => { - const [show, setShow] = useState(false); - if (sources.length === 0) return null; - - return ( -
- - {show && ( - <> -
- {sources.map((source) => { - const { id = null, title, url } = source; - const handleClick = () => { - if (!url) return false; - window.open(url, "_blank"); - }; - return ( - - ); - })} -
-

- *citation may not be relevant to end result. -

- - )} -
- ); -}; - export default memo(PromptReply); diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx index 0ecf3238..b0e1e7a8 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/index.jsx @@ -65,7 +65,7 @@ export default function PromptInput({ @@ -93,14 +93,14 @@ export default function PromptInput({ ref={formRef} type="submit" disabled={buttonDisabled} - className="inline-flex justify-center p-0 md:p-2 rounded-full cursor-pointer text-black-900 dark:text-slate-200 hover:bg-gray-600 dark:hover:bg-stone-500" + className="inline-flex justify-center p-0 md:p-2 rounded-full cursor-pointer text-black-900 dark:text-slate-200 hover:bg-gray-200 dark:hover:bg-stone-500 group" > {buttonDisabled ? ( ) : (
-

+

Chat mode: {chatMode}

@@ -164,13 +164,13 @@ function CommandMenu({ workspace, show, handleClick, hide }) { ]; return ( -

+
-

Available Commands

+

Available Commands

@@ -188,10 +188,14 @@ function CommandMenu({ workspace, show, handleClick, hide }) { handleClick(cmd); hide(); }} - className="w-full px-4 py-2 flex items-center rounded-lg hover:bg-slate-500 gap-x-1 disabled:cursor-not-allowed" + className="w-full px-4 py-2 flex items-center rounded-lg hover:bg-gray-300 hover:dark:bg-slate-500 gap-x-1 disabled:cursor-not-allowed" > -

{cmd}

-

{description}

+

+ {cmd} +

+

+ {description} +

); diff --git a/frontend/src/index.css b/frontend/src/index.css index 225a8d45..a0294126 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -133,6 +133,26 @@ a { } } +@media (prefers-color-scheme: light) { + .fade-up-border { + background: linear-gradient( + to bottom, + rgba(220, 221, 223, 10%), + rgb(220, 221, 223) 89% + ); + } +} + +@media (prefers-color-scheme: dark) { + .fade-up-border { + background: linear-gradient( + to bottom, + rgba(41, 37, 36, 50%), + rgb(41 37 36) 90% + ); + } +} + /** * ============================================== * Dot Falling diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index cad2efe7..e0d23bb3 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -5,7 +5,7 @@ export default { extend: { colors: { 'black-900': '#141414', - } + }, }, }, plugins: [], diff --git a/server/utils/helpers/index.js b/server/utils/helpers/index.js index 745fd061..672bddea 100644 --- a/server/utils/helpers/index.js +++ b/server/utils/helpers/index.js @@ -23,7 +23,6 @@ function toChunks(arr, size) { } function curateSources(sources = []) { - const knownDocs = []; const documents = []; // Sometimes the source may or may not have a metadata property @@ -32,17 +31,12 @@ function curateSources(sources = []) { for (const source of sources) { if (source.hasOwnProperty("metadata")) { const { metadata = {} } = source; - if ( - Object.keys(metadata).length > 0 && - !knownDocs.includes(metadata.title) - ) { + if (Object.keys(metadata).length > 0) { documents.push({ ...metadata }); - knownDocs.push(metadata.title); } } else { - if (Object.keys(source).length > 0 && !knownDocs.includes(source.title)) { + if (Object.keys(source).length > 0) { documents.push({ ...source }); - knownDocs.push(source.title); } } } diff --git a/server/utils/vectorDbProviders/lance/index.js b/server/utils/vectorDbProviders/lance/index.js index ddc18469..bf29d17f 100644 --- a/server/utils/vectorDbProviders/lance/index.js +++ b/server/utils/vectorDbProviders/lance/index.js @@ -10,16 +10,11 @@ const { chatPrompt } = require("../../chats"); // Since we roll our own results for prompting we // have to manually curate sources as well. function curateLanceSources(sources = []) { - const knownDocs = []; const documents = []; for (const source of sources) { - const { text: _t, vector: _v, score: _s, ...metadata } = source; - if ( - Object.keys(metadata).length > 0 && - !knownDocs.includes(metadata.title) - ) { - documents.push({ ...metadata }); - knownDocs.push(metadata.title); + const { text, vector: _v, score: _s, ...metadata } = source; + if (Object.keys(metadata).length > 0) { + documents.push({ ...metadata, text }); } }