diff --git a/api/app/clients/OpenAIClient.js b/api/app/clients/OpenAIClient.js index 8827a901a96..034547c38c5 100644 --- a/api/app/clients/OpenAIClient.js +++ b/api/app/clients/OpenAIClient.js @@ -1292,6 +1292,12 @@ ${convo} let reasoningCompleted = false; for await (const chunk of stream) { 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 || ''; intermediateReply.push(reasoning_content); reasoningTokens.push(reasoning_content); @@ -1301,7 +1307,7 @@ ${convo} const token = chunk?.choices?.[0]?.delta?.content || ''; if (!reasoningCompleted && reasoningTokens.length > 0 && token) { reasoningCompleted = true; - const separatorTokens = '\n\n---\n'; + const separatorTokens = '\n:::\n'; reasoningTokens.push(separatorTokens); onProgress(separatorTokens); } diff --git a/client/src/components/Artifacts/Thinking.tsx b/client/src/components/Artifacts/Thinking.tsx new file mode 100644 index 00000000000..53bafba627f --- /dev/null +++ b/client/src/components/Artifacts/Thinking.tsx @@ -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) => { + e.preventDefault(); + setIsExpanded(!isExpanded); + }; + + return ( +
+ + {isExpanded && ( +
+
+

{children}

+
+ )} +
+ ); +}; + +export default Thinking; diff --git a/client/src/components/Chat/Messages/Content/Markdown.tsx b/client/src/components/Chat/Messages/Content/Markdown.tsx index 176cc90191e..3489a92005c 100644 --- a/client/src/components/Chat/Messages/Content/Markdown.tsx +++ b/client/src/components/Chat/Messages/Content/Markdown.tsx @@ -17,6 +17,7 @@ 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'; @@ -213,6 +214,7 @@ const Markdown = memo(({ content = '', showCursor, isLatestMessage }: TContentPr a, p, artifact: Artifact, + thinking: Thinking, } as { [nodeType: string]: React.ElementType; } diff --git a/client/src/localization/languages/Eng.ts b/client/src/localization/languages/Eng.ts index 2975e83ff86..664b46d712d 100644 --- a/client/src/localization/languages/Eng.ts +++ b/client/src/localization/languages/Eng.ts @@ -409,6 +409,7 @@ export default { com_ui_more_options: 'More', com_ui_more_info: 'More info', com_ui_preview: 'Preview', + com_ui_thoughts: 'Thoughts', com_ui_upload: 'Upload', com_ui_connect: 'Connect', com_ui_locked: 'Locked',