Commit 7d91f005 authored by 水玉婷's avatar 水玉婷
Browse files

feat:增加思考过程

parent 091c7fb9
...@@ -53,9 +53,9 @@ ...@@ -53,9 +53,9 @@
<div v-else v-html="item.content" class="message-inner-box"></div> <div v-else v-html="item.content" class="message-inner-box"></div>
<!-- 思考过程框 --> <!-- 思考过程框 -->
<div v-if="item.hasThinkBox" class="think-box-wrapper"> <div v-if="item.hasThinkBox" class="think-box-wrapper">
<div class="think-box-toggle" @click="toggleThinkBox(index, i)">{{ <div class="think-box-toggle" @click="toggleThinkBox(index, i)">{{
item.thinkBoxExpanded ? '▲ 收起思考过程' : '▼ 展开思考过程' item.thinkBoxExpanded ? '▲ ' : '▼ '
}}</div> }}<span v-if="item.thinkingTimeText" class="thinking-text">{{ item.thinkingTimeText }}</span></div>
<div v-if="item.thinkBoxExpanded" class="think-box-content" <div v-if="item.thinkBoxExpanded" class="think-box-content"
v-html="templateService.generateThinkingTemplate(item.thinkContent || '')"></div> v-html="templateService.generateThinkingTemplate(item.thinkContent || '')"></div>
</div> </div>
......
...@@ -312,15 +312,6 @@ li { ...@@ -312,15 +312,6 @@ li {
} }
// 思考框样式 // 思考框样式
.think-box-wrapper {
margin: 12px 0;
padding: 10px 15px;
background-color: #f5f8f7;
border-radius: 12px;
border: 1px solid #e3ecea;
transition: all 0.3s ease;
}
:deep(.think-box-toggle) { :deep(.think-box-toggle) {
color: @primary-color; color: @primary-color;
cursor: pointer; cursor: pointer;
...@@ -328,33 +319,23 @@ li { ...@@ -328,33 +319,23 @@ li {
text-decoration: none; text-decoration: none;
align-items: center; align-items: center;
gap: 4px; gap: 4px;
font-weight: 500;
padding: 4px 8px; padding: 4px 8px;
border-radius: 4px; border-radius: 4px;
transition: all 0.2s ease; transition: all 0.2s ease;
.thinking-text {
margin-left: 6px;
color: @gray-7;
font-size: 13px;
}
} }
:deep(.think-box-content) { :deep(.think-box-content) {
margin-top: 8px; margin-top: 8px;
background-color: @white;
padding: 12px 16px;
border-radius: 8px;
border: 1px solid #e9ecef;
font-size: 0px;
color: #495057;
white-space: pre-wrap;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
animation: fadeIn 0.3s ease-in-out;
.think-content { .think-content {
font-size: 0; font-size: 14px;
color: @gray-5;
.think-line {
font-size: 13px;
color: @gray-7;
font-style: italic;
}
} }
} }
......
...@@ -25,6 +25,8 @@ export interface MessageBlock { ...@@ -25,6 +25,8 @@ export interface MessageBlock {
src: string; src: string;
durationTime: string; durationTime: string;
}; };
thinkingTime?: number;
thinkingTimeText?: string;
} }
// 消息类型定义 // 消息类型定义
...@@ -59,6 +61,49 @@ export interface TemplateProcessResult { ...@@ -59,6 +61,49 @@ export interface TemplateProcessResult {
newDialogSessionId: string; newDialogSessionId: string;
} }
// 检查最后一个块是否是普通文本块
function isLastBlockText(blocks: MessageBlock[]): boolean {
if (blocks.length === 0) return false;
const lastBlock = blocks[blocks.length - 1];
// 普通文本块的条件:有content且没有其他特殊类型数据
return !!lastBlock.content &&
!lastBlock.audioData &&
!lastBlock.chartData &&
!lastBlock.thinkContent;
}
// 获取最后一个普通文本块的索引
function getLastTextBlockIndex(blocks: MessageBlock[]): number {
for (let i = blocks.length - 1; i >= 0; i--) {
const block = blocks[i];
if (!!block.content &&
!block.audioData &&
!block.chartData &&
!block.thinkContent) {
return i;
}
}
return -1;
}
// 合并普通文本内容
function mergeTextContent(existingContent: string, newContent: string): string {
// 从现有内容中提取纯文本(去掉HTML标签)
const existingText = existingContent.replace(/<[^>]*>/g, '').trim();
const newText = newContent.trim();
// 如果现有内容为空,直接返回新内容的模板
if (!existingText) {
return `<div class=\"message-text\">${newText}</div>`;
}
// 合并文本内容
const mergedText = existingText + '\n' + newText;
// 返回合并后的HTML模板
return `<div class=\"message-text\">${mergedText}</div>`;
}
// 内容模板服务类 // 内容模板服务类
export class ContentTemplateService { export class ContentTemplateService {
private templates: ContentTemplates; private templates: ContentTemplates;
...@@ -79,11 +124,7 @@ export class ContentTemplateService { ...@@ -79,11 +124,7 @@ export class ContentTemplateService {
// 思考过程 // 思考过程
thinking: (content: string) => { thinking: (content: string) => {
const formattedContent = content return `<div class="think-content">${content}</div>`;
.split('\n')
.map((line) => `<div class="think-line">${line}</div>`)
.join('');
return `<div class="think-content">${formattedContent}</div>`;
}, },
// 错误信息 // 错误信息
...@@ -207,55 +248,12 @@ export class ContentTemplateService { ...@@ -207,55 +248,12 @@ export class ContentTemplateService {
let completionTokens = 0; let completionTokens = 0;
let totalTokens = 0; let totalTokens = 0;
let newDialogSessionId = ''; let newDialogSessionId = '';
// 删除局部变量 thinkingStartTime,使用类的实例变量
// 根据是否为历史数据设置默认展开状态 // 根据是否为历史数据设置默认展开状态
const defaultThinkBoxExpanded = !isHistoryData; const defaultThinkBoxExpanded = !isHistoryData;
// 检查是否是"正在思考中....."消息(仅当状态为0且类型为0时)
const isThinkingMessage = contentStatus === 0 && contentType === 0 &&
typeof messageContent === 'string' &&
messageContent.includes('正在思考中.....');
// 跟踪思考状态的变量
let isCurrentlyThinking = updatedResponse && updatedResponse.contentBlocks.length > 0 &&
updatedResponse.contentBlocks.some(block => block.content.includes('think-message'));
// 处理思考开始时间(基于"正在思考中....."文本的出现)
if (isThinkingMessage && !this.thinkingStartTime) {
// 思考开始,记录开始时间
this.thinkingStartTime = Date.now();
}
// 检查是否是思考完成的消息("正在思考中....."文本消失)
const isThinkingComplete = contentStatus === 0 && contentType === 0 && !isThinkingMessage && this.thinkingStartTime;
// 处理思考完成状态(在所有状态分支之前处理)
if (isThinkingComplete) {
// 如果思考完成,更新所有包含"正在思考中....."的消息
if (updatedResponse && updatedResponse.contentBlocks.length > 0) {
let thinkingTimeText = '';
// 计算思考用时
if (this.thinkingStartTime) {
const thinkingEndTime = Date.now();
const thinkingTimeSeconds = Math.round((thinkingEndTime - this.thinkingStartTime) / 1000);
thinkingTimeText = `(用时:${thinkingTimeSeconds}s)`;
// 重置思考开始时间
this.thinkingStartTime = null;
}
updatedResponse.contentBlocks.forEach(block => {
// 只在包含"正在思考中....."文本的块中添加用时信息
if (block.content && block.content.includes('正在思考中.....')) {
block.content = block.content.replace('正在思考中.....', `已完成思考${thinkingTimeText}`);
}
if (block.thinkContent && block.thinkContent.includes('正在思考中.....')) {
block.thinkContent = block.thinkContent.replace('正在思考中.....', `已完成思考${thinkingTimeText}`);
}
});
}
}
switch (contentStatus) { switch (contentStatus) {
case -1: // 错误信息 case -1: // 错误信息
if (updatedResponse) { if (updatedResponse) {
...@@ -306,50 +304,12 @@ export class ContentTemplateService { ...@@ -306,50 +304,12 @@ export class ContentTemplateService {
thinkBoxExpanded: false, thinkBoxExpanded: false,
}); });
} else { } else {
// 走选项
updatedResponse.contentBlocks.push({ updatedResponse.contentBlocks.push({
content: this.templates.option(messageContent), content: this.templates.option({
hasThinkBox: false, tips,
thinkContent: '', options,
thinkBoxExpanded: false, }),
});
}
}
break;
case 4: // MD格式
if (updatedResponse) {
// 对于SSE流式数据,使用流式处理
const markdownContent = templateTools?.markdownTemplate ?
templateTools.markdownTemplate(messageContent || '', true) :
this.templates.markdown(messageContent || '', true);
// 检查最后一个块是否是markdown块
const isLastMarkdown = templateTools?.isLastBlockMarkdown ?
templateTools.isLastBlockMarkdown(updatedResponse.contentBlocks) :
isLastBlockMarkdown(updatedResponse.contentBlocks);
if (isLastMarkdown) {
// 合并到现有的markdown块
const lastMarkdownIndex = templateTools?.getLastMarkdownBlockIndex ?
templateTools.getLastMarkdownBlockIndex(updatedResponse.contentBlocks) :
getLastMarkdownBlockIndex(updatedResponse.contentBlocks);
if (lastMarkdownIndex !== -1) {
updatedResponse.contentBlocks[lastMarkdownIndex].content =
templateTools?.mergeMarkdownContent ?
templateTools.mergeMarkdownContent(
updatedResponse.contentBlocks[lastMarkdownIndex].content,
markdownContent
) :
mergeMarkdownContent(
updatedResponse.contentBlocks[lastMarkdownIndex].content,
markdownContent
);
}
} else {
// 创建新的markdown块
updatedResponse.contentBlocks.push({
content: markdownContent,
hasThinkBox: false, hasThinkBox: false,
thinkContent: '', thinkContent: '',
thinkBoxExpanded: false, thinkBoxExpanded: false,
...@@ -357,28 +317,24 @@ export class ContentTemplateService { ...@@ -357,28 +317,24 @@ export class ContentTemplateService {
} }
} }
break; break;
default: // 默认处理
updatedResponse.contentBlocks.push({
content: this.templates.text(messageContent || ''),
hasThinkBox: false,
thinkContent: '',
thinkBoxExpanded: false,
});
break;
} }
} }
break; break;
case 10: // 思考开始 case 10: // 思考开始
updatedIsThinking = true; updatedIsThinking = true;
// 记录思考开始时间
this.thinkingStartTime = Date.now();
if (updatedBlockIndex === -1 && updatedResponse) { if (updatedBlockIndex === -1 && updatedResponse) {
updatedBlockIndex = updatedResponse.contentBlocks.length; updatedBlockIndex = updatedResponse.contentBlocks.length;
updatedResponse.contentBlocks.push({ updatedResponse.contentBlocks.push({
content: '', content: '',
thinkContent: `${messageContent}`, thinkContent: `${messageContent}`,
hasThinkBox: true, hasThinkBox: true,
thinkBoxExpanded: defaultThinkBoxExpanded, thinkBoxExpanded: false,
thinkingTime: 0,
thinkingTimeText: '正在思考中……',
}); });
} else if (updatedResponse && updatedResponse.contentBlocks[updatedBlockIndex]) { } else if (updatedResponse && updatedResponse.contentBlocks[updatedBlockIndex]) {
updatedResponse.contentBlocks[updatedBlockIndex].thinkContent += ``; updatedResponse.contentBlocks[updatedBlockIndex].thinkContent += ``;
...@@ -389,41 +345,27 @@ export class ContentTemplateService { ...@@ -389,41 +345,27 @@ export class ContentTemplateService {
case 11: // 思考结束 case 11: // 思考结束
if (updatedResponse && updatedBlockIndex !== -1 && updatedResponse.contentBlocks[updatedBlockIndex]) { if (updatedResponse && updatedBlockIndex !== -1 && updatedResponse.contentBlocks[updatedBlockIndex]) {
updatedResponse.contentBlocks[updatedBlockIndex].thinkContent += ``; const currentThinkContent = updatedResponse.contentBlocks[updatedBlockIndex].thinkContent;
// 计算思考用时
const thinkingTime = this.thinkingStartTime ? Math.round((Date.now() - this.thinkingStartTime) / 1000) : 0;
const thinkingTimeText = thinkingTime > 0 ? `已完成思考 (用时:${thinkingTime}s)` : '';
updatedResponse.contentBlocks[updatedBlockIndex].thinkContent = currentThinkContent;
// 添加思考时长信息到内容块中,供前端模板使用
updatedResponse.contentBlocks[updatedBlockIndex].thinkingTime = thinkingTime;
updatedResponse.contentBlocks[updatedBlockIndex].thinkingTimeText = thinkingTimeText;
updatedResponse.contentBlocks[updatedBlockIndex].hasThinkBox = true; updatedResponse.contentBlocks[updatedBlockIndex].hasThinkBox = true;
updatedResponse.contentBlocks[updatedBlockIndex].thinkBoxExpanded = defaultThinkBoxExpanded; // 思考结束后保持展开状态
updatedResponse.contentBlocks[updatedBlockIndex].thinkBoxExpanded = true;
// 重置思考开始时间
this.thinkingStartTime = null;
} }
updatedIsThinking = false; updatedIsThinking = false;
break; break;
case 0: // 普通内容状态
if (isThinkingMessage || isCurrentlyThinking) {
// 如果是思考中消息或当前处于思考状态,添加think类别
if (updatedResponse) {
updatedResponse.contentBlocks.push({
content: `<div class="message-text think-message">${messageContent}</div>`,
hasThinkBox: false,
thinkContent: '',
thinkBoxExpanded: false,
});
// 标记为当前处于思考状态
isCurrentlyThinking = true;
}
} else {
// 普通消息处理
if (updatedResponse) {
updatedResponse.contentBlocks.push({
content: this.templates.text(messageContent),
hasThinkBox: false,
thinkContent: '',
thinkBoxExpanded: false,
});
// 普通消息结束思考状态
isCurrentlyThinking = false;
}
}
break;
case 20: // 初始连接回传信息 case 20: // 初始连接回传信息
if (updatedResponse) { if (updatedResponse) {
updatedResponse.contentBlocks.push({ updatedResponse.contentBlocks.push({
...@@ -446,35 +388,59 @@ export class ContentTemplateService { ...@@ -446,35 +388,59 @@ export class ContentTemplateService {
completionTokens = messageContent?.completionTokens || 0; completionTokens = messageContent?.completionTokens || 0;
totalTokens = messageContent?.totalTokens || 0; totalTokens = messageContent?.totalTokens || 0;
// 只有实时对话才在29时折叠思考框,历史数据不受影响 // 只有实时对话才在29时折叠思考框,历史数据不受影响
if (!isHistoryData && updatedResponse && updatedResponse.contentBlocks.length > 0) { // 修改:不再自动折叠思考框,保持用户当前的展开状态
updatedResponse.contentBlocks.forEach((block) => { // if (!isHistoryData && updatedResponse && updatedResponse.contentBlocks.length > 0) {
if (block.hasThinkBox) { // updatedResponse.contentBlocks.forEach((block) => {
block.thinkBoxExpanded = false; // if (block.hasThinkBox) {
} // block.thinkBoxExpanded = false;
}); // }
} // });
// }
updatedIsThinking = false; updatedIsThinking = false;
updatedBlockIndex = -1; updatedBlockIndex = -1;
// 会话结束时重置思考开始时间
this.thinkingStartTime = null;
break; break;
default: // 普通内容 default: // 普通内容
if (updatedIsThinking && updatedResponse) { if (updatedIsThinking && updatedResponse) {
if (updatedBlockIndex !== -1 && updatedResponse.contentBlocks[updatedBlockIndex]) { if (updatedBlockIndex !== -1 && updatedResponse.contentBlocks[updatedBlockIndex]) {
updatedResponse.contentBlocks[updatedBlockIndex].thinkContent += `\n${messageContent}`; // 获取当前思考内容
const currentThinkContent = updatedResponse.contentBlocks[updatedBlockIndex].thinkContent;
// 如果思考内容为空,直接设置新内容
if (!currentThinkContent) {
updatedResponse.contentBlocks[updatedBlockIndex].thinkContent = messageContent;
} else {
// 否则追加新内容(用换行符分隔)
updatedResponse.contentBlocks[updatedBlockIndex].thinkContent = currentThinkContent + messageContent;
}
updatedResponse.contentBlocks[updatedBlockIndex].hasThinkBox = true; updatedResponse.contentBlocks[updatedBlockIndex].hasThinkBox = true;
updatedResponse.contentBlocks[updatedBlockIndex].thinkBoxExpanded = defaultThinkBoxExpanded; updatedResponse.contentBlocks[updatedBlockIndex].thinkBoxExpanded = defaultThinkBoxExpanded;
} }
} else if (updatedResponse) { } else if (updatedResponse) {
updatedBlockIndex = updatedResponse.contentBlocks.length; // 检查最后一个块是否是普通文本块,如果是则合并,否则创建新块
updatedResponse.contentBlocks.push({ const isLastText = isLastBlockText(updatedResponse.contentBlocks);
content: this.templates.text(messageContent),
hasThinkBox: false, if (isLastText) {
thinkContent: '', // 合并到现有的普通文本块
thinkBoxExpanded: false, const lastTextIndex = getLastTextBlockIndex(updatedResponse.contentBlocks);
});
if (lastTextIndex !== -1) {
updatedResponse.contentBlocks[lastTextIndex].content =
mergeTextContent(
updatedResponse.contentBlocks[lastTextIndex].content,
messageContent
);
}
} else {
// 创建新的内容块
updatedBlockIndex = updatedResponse.contentBlocks.length;
updatedResponse.contentBlocks.push({
content: this.templates.text(messageContent),
hasThinkBox: false,
thinkContent: '',
thinkBoxExpanded: false,
});
}
} }
break; break;
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment