🐳 feat: Deepseek Reasoning UI (#5440)

This commit is contained in:
Danny Avila 2025-01-24 10:52:08 -05:00 committed by GitHub
parent b8b7f40e98
commit 7818ae5c60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 55 additions and 1 deletions

View file

@ -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);
} }

View 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;

View file

@ -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;
} }

View file

@ -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',