mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-23 20:00:15 +01:00
🚀 feat: o1 Tool Calling & reasoning_effort (#5553)
* fix: Update @librechat/agents to version 1.9.98 * feat: o1 tool calling * fix: Improve error logging in RouteErrorBoundary * refactor: Move extractContent function to utils and clean up Artifact component * refactor: optimize reasoning UI post-streaming and deprecate plugins rendering * feat: reasoning_effort support * fix: update request content type handling in openapiToFunction to remove default 'application/x-www-form-urlencoded' * chore: bump v0.7.696 data-provider
This commit is contained in:
parent
591a019766
commit
587d46a20b
17 changed files with 752 additions and 685 deletions
|
|
@ -17,7 +17,6 @@ import {
|
|||
import { Artifact, artifactPlugin } from '~/components/Artifacts/Artifact';
|
||||
import { langSubset, preprocessLaTeX, handleDoubleClick } from '~/utils';
|
||||
import CodeBlock from '~/components/Messages/Content/CodeBlock';
|
||||
import Thinking from '~/components/Artifacts/Thinking';
|
||||
import { useFileDownload } from '~/data-provider';
|
||||
import useLocalize from '~/hooks/useLocalize';
|
||||
import store from '~/store';
|
||||
|
|
@ -223,7 +222,6 @@ const Markdown = memo(({ content = '', showCursor, isLatestMessage }: TContentPr
|
|||
a,
|
||||
p,
|
||||
artifact: Artifact,
|
||||
thinking: Thinking,
|
||||
} as {
|
||||
[nodeType: string]: React.ElementType;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { Fragment, Suspense, useMemo } from 'react';
|
||||
import { memo, Suspense, useMemo } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import type { TMessage, TResPlugin } from 'librechat-data-provider';
|
||||
import type { TMessage } 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 Thinking from '~/components/Artifacts/Thinking';
|
||||
import { DelayedRender } from '~/components/ui';
|
||||
import { useChatContext } from '~/Providers';
|
||||
import MarkdownLite from './MarkdownLite';
|
||||
|
|
@ -117,7 +117,6 @@ export const UnfinishedMessage = ({ message }: { message: TMessage }) => (
|
|||
/>
|
||||
);
|
||||
|
||||
// Content Component
|
||||
const MessageContent = ({
|
||||
text,
|
||||
edit,
|
||||
|
|
@ -127,72 +126,49 @@ const MessageContent = ({
|
|||
isLast,
|
||||
...props
|
||||
}: TMessageContentProps) => {
|
||||
const { message } = props;
|
||||
const { messageId } = message;
|
||||
|
||||
const { thinkingContent, regularContent } = useMemo(() => {
|
||||
const thinkingMatch = text.match(/:::thinking([\s\S]*?):::/);
|
||||
return {
|
||||
thinkingContent: thinkingMatch ? thinkingMatch[1].trim() : '',
|
||||
regularContent: thinkingMatch ? text.replace(/:::thinking[\s\S]*?:::/, '').trim() : text,
|
||||
};
|
||||
}, [text]);
|
||||
|
||||
const showRegularCursor = useMemo(() => isLast && isSubmitting, [isLast, isSubmitting]);
|
||||
|
||||
const unfinishedMessage = useMemo(
|
||||
() =>
|
||||
!isSubmitting && unfinished ? (
|
||||
<Suspense>
|
||||
<DelayedRender delay={250}>
|
||||
<UnfinishedMessage message={message} />
|
||||
</DelayedRender>
|
||||
</Suspense>
|
||||
) : null,
|
||||
[isSubmitting, unfinished, message],
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return <ErrorMessage message={props.message} text={text} />;
|
||||
} else if (edit) {
|
||||
return <EditMessage text={text} isSubmitting={isSubmitting} {...props} />;
|
||||
} else {
|
||||
const marker = ':::plugin:::\n';
|
||||
const splitText = text.split(marker);
|
||||
const { message } = props;
|
||||
const { plugins, messageId } = message;
|
||||
const displayedIndices = new Set<number>();
|
||||
// Function to get the next non-empty text index
|
||||
const getNextNonEmptyTextIndex = (currentIndex: number) => {
|
||||
for (let i = currentIndex + 1; i < splitText.length; i++) {
|
||||
// Allow the last index to be last in case it has text
|
||||
// this may need to change if I add back streaming
|
||||
if (i === splitText.length - 1) {
|
||||
return currentIndex;
|
||||
}
|
||||
|
||||
if (splitText[i].trim() !== '' && !displayedIndices.has(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return currentIndex; // If no non-empty text is found, return the current index
|
||||
};
|
||||
|
||||
return splitText.map((text, idx) => {
|
||||
let currentText = text.trim();
|
||||
let plugin: TResPlugin | null = null;
|
||||
|
||||
if (plugins) {
|
||||
plugin = plugins[idx];
|
||||
}
|
||||
|
||||
// If the current text is empty, get the next non-empty text index
|
||||
const displayTextIndex = currentText === '' ? getNextNonEmptyTextIndex(idx) : idx;
|
||||
currentText = splitText[displayTextIndex];
|
||||
const isLastIndex = displayTextIndex === splitText.length - 1;
|
||||
const isEmpty = currentText.trim() === '';
|
||||
const showText =
|
||||
(currentText && !isEmpty && !displayedIndices.has(displayTextIndex)) ||
|
||||
(isEmpty && isLastIndex);
|
||||
displayedIndices.add(displayTextIndex);
|
||||
|
||||
return (
|
||||
<Fragment key={idx}>
|
||||
{plugin && <Plugin key={`plugin-${messageId}-${idx}`} plugin={plugin} />}
|
||||
{showText ? (
|
||||
<DisplayMessage
|
||||
key={`display-${messageId}-${idx}`}
|
||||
showCursor={isLastIndex && isLast && isSubmitting}
|
||||
text={currentText}
|
||||
{...props}
|
||||
/>
|
||||
) : null}
|
||||
{!isSubmitting && unfinished && (
|
||||
<Suspense>
|
||||
<DelayedRender delay={250}>
|
||||
<UnfinishedMessage message={message} key={`unfinished-${messageId}-${idx}`} />
|
||||
</DelayedRender>
|
||||
</Suspense>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{thinkingContent && <Thinking key={`thinking-${messageId}`}>{thinkingContent}</Thinking>}
|
||||
<DisplayMessage
|
||||
key={`display-${messageId}`}
|
||||
showCursor={showRegularCursor}
|
||||
text={regularContent}
|
||||
{...props}
|
||||
/>
|
||||
{unfinishedMessage}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MessageContent;
|
||||
export default memo(MessageContent);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const Reasoning = memo(({ reasoning }: ReasoningProps) => {
|
|||
<div
|
||||
className={cn(
|
||||
'grid transition-all duration-300 ease-out',
|
||||
nextType !== ContentTypes.THINK && isExpanded && 'mb-10',
|
||||
nextType !== ContentTypes.THINK && isExpanded && 'mb-8',
|
||||
)}
|
||||
style={{
|
||||
gridTemplateRows: isExpanded ? '1fr' : '0fr',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue