mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-20 02:10:15 +01:00
🐳 feat: Deepseek Reasoning UI (#5440)
This commit is contained in:
parent
b8b7f40e98
commit
7818ae5c60
4 changed files with 55 additions and 1 deletions
|
|
@ -1292,6 +1292,12 @@ ${convo}
|
||||||
let reasoningCompleted = false;
|
let reasoningCompleted = false;
|
||||||
for await (const chunk of stream) {
|
for await (const chunk of stream) {
|
||||||
if (chunk?.choices?.[0]?.delta?.reasoning_content) {
|
if (chunk?.choices?.[0]?.delta?.reasoning_content) {
|
||||||
|
if (reasoningTokens.length === 0) {
|
||||||
|
const thinkingDirective = ':::thinking\n';
|
||||||
|
intermediateReply.push(thinkingDirective);
|
||||||
|
reasoningTokens.push(thinkingDirective);
|
||||||
|
onProgress(thinkingDirective);
|
||||||
|
}
|
||||||
const reasoning_content = chunk?.choices?.[0]?.delta?.reasoning_content || '';
|
const reasoning_content = chunk?.choices?.[0]?.delta?.reasoning_content || '';
|
||||||
intermediateReply.push(reasoning_content);
|
intermediateReply.push(reasoning_content);
|
||||||
reasoningTokens.push(reasoning_content);
|
reasoningTokens.push(reasoning_content);
|
||||||
|
|
@ -1301,7 +1307,7 @@ ${convo}
|
||||||
const token = chunk?.choices?.[0]?.delta?.content || '';
|
const token = chunk?.choices?.[0]?.delta?.content || '';
|
||||||
if (!reasoningCompleted && reasoningTokens.length > 0 && token) {
|
if (!reasoningCompleted && reasoningTokens.length > 0 && token) {
|
||||||
reasoningCompleted = true;
|
reasoningCompleted = true;
|
||||||
const separatorTokens = '\n\n---\n';
|
const separatorTokens = '\n:::\n';
|
||||||
reasoningTokens.push(separatorTokens);
|
reasoningTokens.push(separatorTokens);
|
||||||
onProgress(separatorTokens);
|
onProgress(separatorTokens);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
45
client/src/components/Artifacts/Thinking.tsx
Normal file
45
client/src/components/Artifacts/Thinking.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Atom, ChevronDown } from 'lucide-react';
|
||||||
|
import type { MouseEvent } from 'react';
|
||||||
|
import useLocalize from '~/hooks/useLocalize';
|
||||||
|
|
||||||
|
interface ThinkingProps {
|
||||||
|
children: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Thinking = ({ children }: ThinkingProps) => {
|
||||||
|
const localize = useLocalize();
|
||||||
|
const [isExpanded, setIsExpanded] = useState(true);
|
||||||
|
|
||||||
|
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsExpanded(!isExpanded);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="mb-3">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleClick}
|
||||||
|
className="group mb-3 flex w-fit items-center justify-center rounded-xl bg-surface-tertiary px-3.5 py-2 text-xs leading-[18px] text-text-primary transition-colors hover:bg-surface-secondary"
|
||||||
|
>
|
||||||
|
<Atom size={14} className="mr-1.5 text-text-secondary" />
|
||||||
|
{localize('com_ui_thoughts')}
|
||||||
|
<ChevronDown
|
||||||
|
className="icon-sm ml-1.5 text-text-primary transition-transform duration-200"
|
||||||
|
style={{
|
||||||
|
transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
{isExpanded && (
|
||||||
|
<div className="relative pl-3 text-text-secondary">
|
||||||
|
<div className="absolute left-0 top-[5px] h-[calc(100%-10px)] border-l-2 border-border-medium dark:border-border-heavy" />
|
||||||
|
<p className="my-4 whitespace-pre-wrap leading-[26px]">{children}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Thinking;
|
||||||
|
|
@ -17,6 +17,7 @@ import {
|
||||||
import { Artifact, artifactPlugin } from '~/components/Artifacts/Artifact';
|
import { Artifact, artifactPlugin } from '~/components/Artifacts/Artifact';
|
||||||
import { langSubset, preprocessLaTeX, handleDoubleClick } from '~/utils';
|
import { langSubset, preprocessLaTeX, handleDoubleClick } from '~/utils';
|
||||||
import CodeBlock from '~/components/Messages/Content/CodeBlock';
|
import CodeBlock from '~/components/Messages/Content/CodeBlock';
|
||||||
|
import Thinking from '~/components/Artifacts/Thinking';
|
||||||
import { useFileDownload } from '~/data-provider';
|
import { useFileDownload } from '~/data-provider';
|
||||||
import useLocalize from '~/hooks/useLocalize';
|
import useLocalize from '~/hooks/useLocalize';
|
||||||
import store from '~/store';
|
import store from '~/store';
|
||||||
|
|
@ -213,6 +214,7 @@ const Markdown = memo(({ content = '', showCursor, isLatestMessage }: TContentPr
|
||||||
a,
|
a,
|
||||||
p,
|
p,
|
||||||
artifact: Artifact,
|
artifact: Artifact,
|
||||||
|
thinking: Thinking,
|
||||||
} as {
|
} as {
|
||||||
[nodeType: string]: React.ElementType;
|
[nodeType: string]: React.ElementType;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,7 @@ export default {
|
||||||
com_ui_more_options: 'More',
|
com_ui_more_options: 'More',
|
||||||
com_ui_more_info: 'More info',
|
com_ui_more_info: 'More info',
|
||||||
com_ui_preview: 'Preview',
|
com_ui_preview: 'Preview',
|
||||||
|
com_ui_thoughts: 'Thoughts',
|
||||||
com_ui_upload: 'Upload',
|
com_ui_upload: 'Upload',
|
||||||
com_ui_connect: 'Connect',
|
com_ui_connect: 'Connect',
|
||||||
com_ui_locked: 'Locked',
|
com_ui_locked: 'Locked',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue