From d32d1c6079eee666ed6bc3096abc7c25b935da6d Mon Sep 17 00:00:00 2001 From: pablodanswer Date: Thu, 23 Jan 2025 12:13:44 -0800 Subject: [PATCH] update- reorg --- web/src/app/chat/input/ChatInputBar.tsx | 2 +- web/src/app/chat/message/AgenticMessage.tsx | 71 ++------ web/src/app/chat/message/SourcesDisplay.tsx | 29 ++-- web/src/app/chat/message/StreamingMessages.ts | 74 --------- .../app/chat/message/SubQuestionsDisplay.tsx | 17 +- web/src/app/chat/refinmentBadge.tsx | 152 ++++++++++++++++++ .../chat_search/sources/SourceCard.tsx | 48 +++--- 7 files changed, 211 insertions(+), 182 deletions(-) create mode 100644 web/src/app/chat/refinmentBadge.tsx diff --git a/web/src/app/chat/input/ChatInputBar.tsx b/web/src/app/chat/input/ChatInputBar.tsx index 73cc84647..686209bb0 100644 --- a/web/src/app/chat/input/ChatInputBar.tsx +++ b/web/src/app/chat/input/ChatInputBar.tsx @@ -826,7 +826,7 @@ export function ChatInputBar({ chatState == "toolBuilding" || chatState == "loading" ? ( ) : ( diff --git a/web/src/app/chat/message/AgenticMessage.tsx b/web/src/app/chat/message/AgenticMessage.tsx index 82005e765..a448198f4 100644 --- a/web/src/app/chat/message/AgenticMessage.tsx +++ b/web/src/app/chat/message/AgenticMessage.tsx @@ -76,9 +76,9 @@ import { StreamingPhase, StreamingPhaseText, useStreamingMessages, - useOrderedPhases, } from "./StreamingMessages"; import { Badge } from "@/components/ui/badge"; +import RefinemenetBadge from "../refinmentBadge"; export const AgenticMessage = ({ secondLevelAssistantMessage, @@ -294,8 +294,8 @@ export const AgenticMessage = ({ ? docs : agenticDocs : agenticDocs && agenticDocs.length > 0 - ? agenticDocs - : docs + ? agenticDocs + : docs } subQuestions={ isViewingInitialAnswer @@ -374,22 +374,6 @@ export const AgenticMessage = ({ ); }, [streamedContent, markdownComponents]); - const currentState = secondLevelSubquestions?.[0] - ? secondLevelSubquestions[0].answer - ? secondLevelSubquestions[0].is_complete - ? StreamingPhase.COMPLETE - : StreamingPhase.ANSWER - : secondLevelSubquestions[0].context_docs - ? StreamingPhase.CONTEXT_DOCS - : secondLevelSubquestions[0].sub_queries - ? StreamingPhase.SUB_QUERIES - : secondLevelSubquestions[0].question - ? StreamingPhase.WAITING - : StreamingPhase.WAITING - : StreamingPhase.WAITING; - - const message = useOrderedPhases(currentState); - const includeMessageSwitcher = currentMessageInd !== undefined && onMessageSelection && @@ -495,45 +479,16 @@ export const AgenticMessage = ({ Answer - {secondLevelSubquestions && - secondLevelSubquestions.length > 0 && - secondLevelGenerating ? ( - - -
- Refining answer... - -
-
- -
-

- {message} -

-

- The answer is being refined based on - additional context and analysis. -

- -
-
-
+ {true ? ( + { + setIsViewingInitialAnswer( + !isViewingInitialAnswer + ); + }} + isViewingInitialAnswer={isViewingInitialAnswer} + /> ) : ( secondLevelAssistantMessage && ( = ({ ))} {hasMoreDocuments && ( - + doc.source_type)) + ) as ValidSources[] + } + webSourceDomains={documents.map((doc) => doc.link)} + /> )} diff --git a/web/src/app/chat/message/StreamingMessages.ts b/web/src/app/chat/message/StreamingMessages.ts index 620112b50..ad8478cca 100644 --- a/web/src/app/chat/message/StreamingMessages.ts +++ b/web/src/app/chat/message/StreamingMessages.ts @@ -31,86 +31,12 @@ interface SubQuestionProgress { answerCharIndex: number; } -const PHASES_ORDER: StreamingPhase[] = [ - StreamingPhase.WAITING, - StreamingPhase.SUB_QUERIES, - StreamingPhase.CONTEXT_DOCS, - StreamingPhase.ANSWER, - StreamingPhase.COMPLETE, -]; - export const PHASE_MIN_MS = 800; // Minimum phase duration in ms function canTransition(p: SubQuestionProgress) { return Date.now() - p.phaseStartTime >= PHASE_MIN_MS; } -export function useOrderedPhases(externalPhase: StreamingPhase) { - const [phaseQueue, setPhaseQueue] = useState([]); - const [displayedPhase, setDisplayedPhase] = useState( - StreamingPhase.WAITING - ); - const lastDisplayTimestampRef = useRef(Date.now()); - - const getPhaseIndex = (phase: StreamingPhase) => { - return PHASES_ORDER.indexOf(phase); - }; - - useEffect(() => { - setPhaseQueue((prevQueue) => { - const lastQueuedPhase = - prevQueue.length > 0 ? prevQueue[prevQueue.length - 1] : displayedPhase; - - const lastQueuedIndex = getPhaseIndex(lastQueuedPhase); - const externalIndex = getPhaseIndex(externalPhase); - - if (externalIndex <= lastQueuedIndex) { - return prevQueue; - } - - const missingPhases: StreamingPhase[] = []; - for (let i = lastQueuedIndex + 1; i <= externalIndex; i++) { - missingPhases.push(PHASES_ORDER[i]); - } - return [...prevQueue, ...missingPhases]; - }); - }, [externalPhase, displayedPhase]); - - useEffect(() => { - if (phaseQueue.length === 0) return; - let rafId: number; - - const processQueue = () => { - const now = Date.now(); - const elapsed = now - lastDisplayTimestampRef.current; - - // Keep this at 1000ms from the original example (unchanged), - // but you can adjust if you want a different visible time in *this* component. - if (elapsed >= 1000) { - setPhaseQueue((prevQueue) => { - if (prevQueue.length > 0) { - const [next, ...rest] = prevQueue; - setDisplayedPhase(next); - lastDisplayTimestampRef.current = Date.now(); - return rest; - } - return prevQueue; - }); - } - rafId = requestAnimationFrame(processQueue); - }; - - rafId = requestAnimationFrame(processQueue); - return () => { - if (rafId) { - cancelAnimationFrame(rafId); - } - }; - }, [phaseQueue]); - - return StreamingPhaseText[displayedPhase]; -} - const DOC_DELAY_MS = 100; export const useStreamingMessages = ( diff --git a/web/src/app/chat/message/SubQuestionsDisplay.tsx b/web/src/app/chat/message/SubQuestionsDisplay.tsx index 28a28aad0..e216e330f 100644 --- a/web/src/app/chat/message/SubQuestionsDisplay.tsx +++ b/web/src/app/chat/message/SubQuestionsDisplay.tsx @@ -308,8 +308,8 @@ const SubQuestionDisplay: React.FC<{ status === ToggleState.Todo ? "!border-4 border border-background-900 bg-background" : false - ? "bg-background border-3 border border-background-900 rotating-border" - : "bg-background-900 flex items-center justify-center" + ? "bg-background border-3 border border-background-900 rotating-border" + : "bg-background-900 flex items-center justify-center" } `} > @@ -506,9 +506,12 @@ const SubQuestionsDisplay: React.FC = ({ useEffect(() => { if (documents && documents.length > 0) { - setTimeout(() => { - setShownDocuments(documents); - }, 1500); + setTimeout( + () => { + setShownDocuments(documents); + }, + overallAnswerGenerating ? 1500 : 0 + ); } }, [documents]); @@ -639,7 +642,7 @@ const SubQuestionsDisplay: React.FC = ({ documents={documents} isLast={ !showSummarizing && - memoizedSubQuestions.length > index + 1 && + memoizedSubQuestions.length == index + 1 && !( showSecondLevel && memoizedSecondLevelQuestions && @@ -689,7 +692,7 @@ const SubQuestionsDisplay: React.FC = ({ documents={documents} isLast={ !showSummarizing && - memoizedSecondLevelQuestions.length > index + 1 + memoizedSecondLevelQuestions.length == index + 1 } isFirst={false} setPresentingDocument={setPresentingDocument} diff --git a/web/src/app/chat/refinmentBadge.tsx b/web/src/app/chat/refinmentBadge.tsx new file mode 100644 index 000000000..ccc2586a8 --- /dev/null +++ b/web/src/app/chat/refinmentBadge.tsx @@ -0,0 +1,152 @@ +"use client"; +import { + Tooltip, + TooltipTrigger, + TooltipProvider, + TooltipContent, +} from "@/components/ui/tooltip"; +import { Button } from "@/components/ui/button"; +import { FiChevronRight, FiGlobe } from "react-icons/fi"; +import { + StreamingPhase, + StreamingPhaseText, +} from "./message/StreamingMessages"; +import { SubQuestionDetail } from "./interfaces"; +import { useEffect, useRef, useState } from "react"; + +const PHASES_ORDER: StreamingPhase[] = [ + StreamingPhase.WAITING, + StreamingPhase.SUB_QUERIES, + StreamingPhase.CONTEXT_DOCS, + StreamingPhase.ANSWER, + StreamingPhase.COMPLETE, +]; + +export function useOrderedPhases(externalPhase: StreamingPhase) { + const [phaseQueue, setPhaseQueue] = useState([]); + const [displayedPhase, setDisplayedPhase] = useState( + StreamingPhase.WAITING + ); + const lastDisplayTimestampRef = useRef(Date.now()); + + const getPhaseIndex = (phase: StreamingPhase) => { + return PHASES_ORDER.indexOf(phase); + }; + + useEffect(() => { + setPhaseQueue((prevQueue) => { + const lastQueuedPhase = + prevQueue.length > 0 ? prevQueue[prevQueue.length - 1] : displayedPhase; + + const lastQueuedIndex = getPhaseIndex(lastQueuedPhase); + const externalIndex = getPhaseIndex(externalPhase); + + if (externalIndex <= lastQueuedIndex) { + return prevQueue; + } + + const missingPhases: StreamingPhase[] = []; + for (let i = lastQueuedIndex + 1; i <= externalIndex; i++) { + missingPhases.push(PHASES_ORDER[i]); + } + return [...prevQueue, ...missingPhases]; + }); + }, [externalPhase, displayedPhase]); + + useEffect(() => { + if (phaseQueue.length === 0) return; + let rafId: number; + + const processQueue = () => { + const now = Date.now(); + const elapsed = now - lastDisplayTimestampRef.current; + + // Keep this at 1000ms from the original example (unchanged), + // but you can adjust if you want a different visible time in *this* component. + if (elapsed >= 1000) { + setPhaseQueue((prevQueue) => { + if (prevQueue.length > 0) { + const [next, ...rest] = prevQueue; + setDisplayedPhase(next); + lastDisplayTimestampRef.current = Date.now(); + return rest; + } + return prevQueue; + }); + } + rafId = requestAnimationFrame(processQueue); + }; + + rafId = requestAnimationFrame(processQueue); + return () => { + if (rafId) { + cancelAnimationFrame(rafId); + } + }; + }, [phaseQueue]); + + return StreamingPhaseText[displayedPhase]; +} + +export default function RefinemenetBadge({ + secondLevelSubquestions, + toggleInitialAnswerVieinwg, + isViewingInitialAnswer, +}: { + secondLevelSubquestions?: SubQuestionDetail[] | null; + toggleInitialAnswerVieinwg: () => void; + isViewingInitialAnswer: boolean; +}) { + const currentState = secondLevelSubquestions?.[0] + ? secondLevelSubquestions[0].answer + ? secondLevelSubquestions[0].is_complete + ? StreamingPhase.COMPLETE + : StreamingPhase.ANSWER + : secondLevelSubquestions[0].context_docs + ? StreamingPhase.CONTEXT_DOCS + : secondLevelSubquestions[0].sub_queries + ? StreamingPhase.SUB_QUERIES + : secondLevelSubquestions[0].question + ? StreamingPhase.WAITING + : StreamingPhase.WAITING + : StreamingPhase.WAITING; + + const message = useOrderedPhases(currentState); + + return ( + + + +
+ Refining answer... + +
+
+ +
+

+ {message} +

+

+ The answer is being refined based on additional context and + analysis. +

+ +
+
+
+
+ ); +} diff --git a/web/src/components/chat_search/sources/SourceCard.tsx b/web/src/components/chat_search/sources/SourceCard.tsx index f48f2eb8d..12988d4f3 100644 --- a/web/src/components/chat_search/sources/SourceCard.tsx +++ b/web/src/components/chat_search/sources/SourceCard.tsx @@ -71,37 +71,29 @@ export function SeeMoreBlock({ ); const numOfWebSourcesToDisplay = 3 - filteredUniqueSources.length; return ( -
-
-

- {toggled ? "Hide Results" : "Show Sources"} -

-
- {filteredUniqueSources.slice(0, 3).map((source, index) => ( - +
+ {filteredUniqueSources.slice(0, 3).map((source, index) => ( + + ))} + {webSourceDomains + .slice(0, numOfWebSourcesToDisplay) + .map((domain, index) => ( + ))} - {/* {webSourceDomains - .slice(0, numOfWebSourcesToDisplay) - .map((domain, ind) => ( - - ))} - - ))} */} - {uniqueSources.length > 3 && ( - - +{uniqueSources.length - 3} - - )} -
+ {uniqueSources.length > 3 && ( + + +{uniqueSources.length - 3} + + )}
-
+ +
+ {toggled ? "Hide Results" : "Show All"} +
+ ); }