Revert "🔖chore: Remove the handling of the MarkdownRender component and the <think> tag"

This reverts commit 96f338c964.
This commit is contained in:
Apple\Apple
2025-05-30 01:31:38 +08:00
parent bbf7fe2d1d
commit faa7abcc7f

View File

@@ -17,6 +17,7 @@ import {
TextArea,
Typography,
Button,
MarkdownRender,
Tag,
Tabs,
TabPane,
@@ -312,6 +313,33 @@ const Playground = () => {
let content = choice.message?.content || '';
let reasoningContent = choice.message?.reasoning_content || '';
if (content.includes('<think>')) {
const thinkTagRegex = /<think>([\s\S]*?)<\/think>/g;
let thoughts = [];
let replyParts = [];
let lastIndex = 0;
let match;
thinkTagRegex.lastIndex = 0;
while ((match = thinkTagRegex.exec(content)) !== null) {
replyParts.push(content.substring(lastIndex, match.index));
thoughts.push(match[1]);
lastIndex = match.index + match[0].length;
}
replyParts.push(content.substring(lastIndex));
content = replyParts.join('');
if (thoughts.length > 0) {
if (reasoningContent) {
reasoningContent += '\n\n---\n\n' + thoughts.join('\n\n---\n\n');
} else {
reasoningContent = thoughts.join('\n\n---\n\n');
}
}
}
content = content.replace(/<\/?think>/g, '').trim();
setMessage((prevMessage) => {
const newMessages = [...prevMessage];
const lastMessage = newMessages[newMessages.length - 1];
@@ -605,13 +633,23 @@ const Playground = () => {
status: 'incomplete',
};
} else if (type === 'content') {
const shouldCollapseReasoning = !lastMessage.content && lastMessage.reasoningContent;
const newContent = (lastMessage.content || '') + textChunk;
let shouldCollapseFromThinkTag = false;
if (lastMessage.isReasoningExpanded && newContent.includes('</think>')) {
const thinkMatches = newContent.match(/<think>/g);
const thinkCloseMatches = newContent.match(/<\/think>/g);
if (thinkMatches && thinkCloseMatches && thinkCloseMatches.length >= thinkMatches.length) {
shouldCollapseFromThinkTag = true;
}
}
newMessage = {
...newMessage,
content: newContent,
status: 'incomplete',
isReasoningExpanded: lastMessage.isReasoningExpanded,
isReasoningExpanded: (shouldCollapseReasoning || shouldCollapseFromThinkTag) ? false : lastMessage.isReasoningExpanded,
};
}
}
@@ -763,9 +801,57 @@ const Playground = () => {
setMessage((prevMessage) => {
const lastMessage = prevMessage[prevMessage.length - 1];
if (lastMessage.status === 'loading' || lastMessage.status === 'incomplete') {
let currentContent = lastMessage.content || '';
let currentReasoningContent = lastMessage.reasoningContent || '';
if (currentContent.includes('<think>')) {
const thinkTagRegex = /<think>([\s\S]*?)<\/think>/g;
let match;
let thoughtsFromPairedTags = [];
let replyParts = [];
let lastIndex = 0;
while ((match = thinkTagRegex.exec(currentContent)) !== null) {
replyParts.push(currentContent.substring(lastIndex, match.index));
thoughtsFromPairedTags.push(match[1]);
lastIndex = match.index + match[0].length;
}
replyParts.push(currentContent.substring(lastIndex));
if (thoughtsFromPairedTags.length > 0) {
const pairedThoughtsStr = thoughtsFromPairedTags.join('\n\n---\n\n');
if (currentReasoningContent) {
currentReasoningContent += '\n\n---\n\n' + pairedThoughtsStr;
} else {
currentReasoningContent = pairedThoughtsStr;
}
}
currentContent = replyParts.join('');
}
const lastOpenThinkIndex = currentContent.lastIndexOf('<think>');
if (lastOpenThinkIndex !== -1) {
const fragmentAfterLastOpen = currentContent.substring(lastOpenThinkIndex);
if (!fragmentAfterLastOpen.includes('</think>')) {
const unclosedThought = fragmentAfterLastOpen.substring('<think>'.length).trim();
if (unclosedThought) {
if (currentReasoningContent) {
currentReasoningContent += '\n\n---\n\n' + unclosedThought;
} else {
currentReasoningContent = unclosedThought;
}
}
currentContent = currentContent.substring(0, lastOpenThinkIndex);
}
}
currentContent = currentContent.replace(/<\/?think>/g, '').trim();
return [...prevMessage.slice(0, -1), {
...lastMessage,
status: 'complete',
reasoningContent: currentReasoningContent || null,
content: currentContent,
isReasoningExpanded: false
}];
}
@@ -922,13 +1008,65 @@ const Playground = () => {
const isThinkingStatus = message.status === 'loading' || message.status === 'incomplete';
let currentExtractedThinkingContent = null;
let currentDisplayableFinalContent = message.content || "";
let thinkingSource = null;
if (message.role === 'assistant') {
let baseContentForDisplay = message.content || "";
let combinedThinkingContent = "";
if (message.reasoningContent) {
currentExtractedThinkingContent = message.reasoningContent;
combinedThinkingContent = message.reasoningContent;
thinkingSource = 'reasoningContent';
}
currentDisplayableFinalContent = message.content || "";
if (baseContentForDisplay.includes('<think>')) {
const thinkTagRegex = /<think>([\s\S]*?)<\/think>/g;
let match;
let thoughtsFromPairedTags = [];
let replyParts = [];
let lastIndex = 0;
while ((match = thinkTagRegex.exec(baseContentForDisplay)) !== null) {
replyParts.push(baseContentForDisplay.substring(lastIndex, match.index));
thoughtsFromPairedTags.push(match[1]);
lastIndex = match.index + match[0].length;
}
replyParts.push(baseContentForDisplay.substring(lastIndex));
if (thoughtsFromPairedTags.length > 0) {
const pairedThoughtsStr = thoughtsFromPairedTags.join('\n\n---\n\n');
if (combinedThinkingContent) {
combinedThinkingContent += '\n\n---\n\n' + pairedThoughtsStr;
} else {
combinedThinkingContent = pairedThoughtsStr;
}
thinkingSource = thinkingSource ? thinkingSource + ' & <think> tags' : '<think> tags';
}
baseContentForDisplay = replyParts.join('');
}
if (isThinkingStatus) {
const lastOpenThinkIndex = baseContentForDisplay.lastIndexOf('<think>');
if (lastOpenThinkIndex !== -1) {
const fragmentAfterLastOpen = baseContentForDisplay.substring(lastOpenThinkIndex);
if (!fragmentAfterLastOpen.includes('</think>')) {
const unclosedThought = fragmentAfterLastOpen.substring('<think>'.length).trim();
if (unclosedThought) {
if (combinedThinkingContent) {
combinedThinkingContent += '\n\n---\n\n' + unclosedThought;
} else {
combinedThinkingContent = unclosedThought;
}
thinkingSource = thinkingSource ? thinkingSource + ' + streaming <think>' : 'streaming <think>';
}
baseContentForDisplay = baseContentForDisplay.substring(0, lastOpenThinkIndex);
}
}
}
currentExtractedThinkingContent = combinedThinkingContent || null;
currentDisplayableFinalContent = baseContentForDisplay.replace(/<\/?think>/g, '').trim();
}
const headerText = isThinkingStatus ? t('思考中...') : t('思考过程');
@@ -972,9 +1110,11 @@ const Playground = () => {
<Typography.Text strong className="text-gray-800 text-base">
{headerText}
</Typography.Text>
<Typography.Text className="text-gray-500 text-xs mt-0.5">
来源: reasoning_content
</Typography.Text>
{thinkingSource && (
<Typography.Text className="text-gray-500 text-xs mt-0.5">
来源: {thinkingSource}
</Typography.Text>
)}
</div>
</div>
<div className="flex items-center gap-3">
@@ -1004,9 +1144,7 @@ const Playground = () => {
<div className="p-5 pt-4">
<div className="bg-white/70 backdrop-blur-sm rounded-xl p-4 shadow-inner overflow-x-auto max-h-50 overflow-y-auto">
<div className="prose prose-sm prose-purple max-w-none">
<Typography.Paragraph className="whitespace-pre-wrap">
{finalExtractedThinkingContent}
</Typography.Paragraph>
<MarkdownRender raw={finalExtractedThinkingContent} />
</div>
</div>
</div>
@@ -1017,9 +1155,7 @@ const Playground = () => {
{(finalDisplayableFinalContent && finalDisplayableFinalContent.trim() !== '') && (
<div className="prose prose-sm prose-gray max-w-none overflow-x-auto">
<Typography.Paragraph className="whitespace-pre-wrap">
{finalDisplayableFinalContent}
</Typography.Paragraph>
<MarkdownRender raw={finalDisplayableFinalContent} />
</div>
)}
</div>