Skip to content

Commit

Permalink
📜 refactor: Optimize Longer Message Thread Performance (danny-avila#3610
Browse files Browse the repository at this point in the history
)
  • Loading branch information
danny-avila authored Aug 11, 2024
1 parent 9abb36a commit d414051
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 280 deletions.
41 changes: 18 additions & 23 deletions client/src/components/Chat/Messages/Content/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import supersub from 'remark-supersub';
import rehypeKatex from 'rehype-katex';
import { useRecoilValue } from 'recoil';
import ReactMarkdown from 'react-markdown';
import rehypeHighlight from 'rehype-highlight';
import type { TMessage } from 'librechat-data-provider';
import type { PluggableList } from 'unified';
import rehypeHighlight from 'rehype-highlight';
import { cn, langSubset, validateIframe, processLaTeX } from '~/utils';
import CodeBlock from '~/components/Messages/Content/CodeBlock';
import { useChatContext, useToastContext } from '~/Providers';
import { useFileDownload } from '~/data-provider';
import useLocalize from '~/hooks/useLocalize';
import { useToastContext } from '~/Providers';
import store from '~/store';

type TCodeProps = {
Expand All @@ -22,20 +21,14 @@ type TCodeProps = {
children: React.ReactNode;
};

type TContentProps = {
content: string;
message: TMessage;
showCursor?: boolean;
};

export const code = memo(({ inline, className, children }: TCodeProps) => {
const match = /language-(\w+)/.exec(className || '');
const match = /language-(\w+)/.exec(className ?? '');
const lang = match && match[1];

if (inline) {
return <code className={className}>{children}</code>;
} else {
return <CodeBlock lang={lang || 'text'} codeChildren={children} />;
return <CodeBlock lang={lang ?? 'text'} codeChildren={children} />;
}
});

Expand Down Expand Up @@ -110,18 +103,22 @@ export const p = memo(({ children }: { children: React.ReactNode }) => {
});

const cursor = ' ';
const Markdown = memo(({ content, message, showCursor }: TContentProps) => {
const { isSubmitting, latestMessage } = useChatContext();

type TContentProps = {
content: string;
isEdited?: boolean;
showCursor?: boolean;
isLatestMessage: boolean;
};

const Markdown = memo(({ content = '', isEdited, showCursor, isLatestMessage }: TContentProps) => {
const LaTeXParsing = useRecoilValue<boolean>(store.LaTeXParsing);

const isInitializing = content === '';

const { isEdited, messageId } = message ?? {};
const isLatestMessage = messageId === latestMessage?.messageId;

let currentContent = content;
if (!isInitializing) {
currentContent = currentContent?.replace('z-index: 1;', '') ?? '';
currentContent = currentContent.replace('z-index: 1;', '') || '';
currentContent = LaTeXParsing ? processLaTeX(currentContent) : currentContent;
}

Expand All @@ -143,18 +140,18 @@ const Markdown = memo(({ content, message, showCursor }: TContentProps) => {
return (
<div className="absolute">
<p className="relative">
<span className={cn(isSubmitting ? 'result-thinking' : '')} />
<span className={cn(showCursor === true ? 'result-thinking' : '')} />
</p>
</div>
);
}

let isValidIframe: string | boolean | null = false;
if (!isEdited) {
if (isEdited !== true) {
isValidIframe = validateIframe(currentContent);
}

if (isEdited || ((!isInitializing || !isLatestMessage) && !isValidIframe)) {
if (isEdited === true || (!isLatestMessage && !isValidIframe)) {
rehypePlugins.pop();
}

Expand All @@ -173,9 +170,7 @@ const Markdown = memo(({ content, message, showCursor }: TContentProps) => {
}
}
>
{isLatestMessage && isSubmitting && !isInitializing && showCursor
? currentContent + cursor
: currentContent}
{isLatestMessage && showCursor === true ? currentContent + cursor : currentContent}
</ReactMarkdown>
);
});
Expand Down
21 changes: 18 additions & 3 deletions client/src/components/Chat/Messages/Content/MessageContent.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Fragment, Suspense } from 'react';
import { Fragment, Suspense, useMemo } from 'react';
import type { TMessage, TResPlugin } from 'librechat-data-provider';
import type { TMessageContentProps, TDisplayProps } from '~/common';
import Plugin from '~/components/Messages/Content/Plugin';
import Error from '~/components/Messages/Content/Error';
import { DelayedRender } from '~/components/ui';
import { useChatContext } from '~/Providers';
import EditMessage from './EditMessage';
import { useLocalize } from '~/hooks';
import Container from './Container';
Expand Down Expand Up @@ -63,17 +64,31 @@ export const ErrorMessage = ({

// Display Message Component
const DisplayMessage = ({ text, isCreatedByUser, message, showCursor }: TDisplayProps) => {
const { isSubmitting, latestMessage } = useChatContext();
const showCursorState = useMemo(
() => showCursor === true && isSubmitting,
[showCursor, isSubmitting],
);
const isLatestMessage = useMemo(
() => message.messageId === latestMessage?.messageId,
[message.messageId, latestMessage?.messageId],
);
return (
<Container message={message}>
<div
className={cn(
showCursor && !!text.length ? 'result-streaming' : '',
showCursorState && !!text.length ? 'result-streaming' : '',
'markdown prose message-content dark:prose-invert light w-full break-words',
isCreatedByUser ? 'whitespace-pre-wrap dark:text-gray-20' : 'dark:text-gray-100',
)}
>
{!isCreatedByUser ? (
<Markdown content={text} message={message} showCursor={showCursor} />
<Markdown
content={text}
isEdited={message.isEdited}
showCursor={showCursorState}
isLatestMessage={isLatestMessage}
/>
) : (
<>{text}</>
)}
Expand Down
20 changes: 18 additions & 2 deletions client/src/components/Chat/Messages/Content/Part.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import {
imageGenTools,
isImageVisionTool,
} from 'librechat-data-provider';
import { useMemo } from 'react';
import type { TMessageContentParts, TMessage } from 'librechat-data-provider';
import type { TDisplayProps } from '~/common';
import { ErrorMessage } from './MessageContent';
import { useChatContext } from '~/Providers';
import RetrievalCall from './RetrievalCall';
import CodeAnalyze from './CodeAnalyze';
import Container from './Container';
Expand All @@ -20,16 +22,30 @@ import { cn } from '~/utils';

// Display Message Component
const DisplayMessage = ({ text, isCreatedByUser = false, message, showCursor }: TDisplayProps) => {
const { isSubmitting, latestMessage } = useChatContext();
const showCursorState = useMemo(
() => showCursor === true && isSubmitting,
[showCursor, isSubmitting],
);
const isLatestMessage = useMemo(
() => message.messageId === latestMessage?.messageId,
[message.messageId, latestMessage?.messageId],
);
return (
<div
className={cn(
showCursor && !!text.length ? 'result-streaming' : '',
showCursorState && !!text.length ? 'result-streaming' : '',
'markdown prose message-content dark:prose-invert light w-full break-words',
isCreatedByUser ? 'whitespace-pre-wrap dark:text-gray-20' : 'dark:text-gray-70',
)}
>
{!isCreatedByUser ? (
<Markdown content={text} message={message} showCursor={showCursor} />
<Markdown
content={text}
isEdited={message.isEdited}
showCursor={showCursorState}
isLatestMessage={isLatestMessage}
/>
) : (
<>{text}</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const SearchContent = ({ message }: { message: TMessage }) => {
)}
dir="auto"
>
<MarkdownLite content={message.text ?? ''} />
<MarkdownLite content={message.text || ''} />
</div>
);
};
Expand Down
122 changes: 0 additions & 122 deletions client/src/components/Messages/Content/Markdown.tsx

This file was deleted.

Loading

0 comments on commit d414051

Please sign in to comment.