Files
school-developer/src/views/knowledge/aiChat/ts/message.ts
吴红兵 b997b3ba48 fix
2026-03-07 12:35:45 +08:00

161 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import type { ChatMessage, Dataset, PrologueItem } from './index';
import { useUserInfo } from '/@/stores/userInfo';
import { Session } from '/@/utils/storage';
import { getObj } from '/@/api/knowledge/aiMcpConfig';
import { getObj as getDataObj } from '/@/api/knowledge/aiData';
/**
* Process a message to extract any thought content enclosed in <think> tags
* and update the message object accordingly
*/
export function withMessageThought(message: ChatMessage, startTime?: number) {
const content = message.content;
// If message already has reasoning_content, calculate thinking time
if (message.reasoning_content) {
const thinkingTime = startTime ? ((Date.now() - startTime) / 1000).toFixed(1) : '0.5';
message.thinking_time = thinkingTime;
// @ts-ignore - Add isThinking flag
message.isThinking = false;
return message;
}
const thinkPattern = /<think>(.*?)<\/think>/s;
const matches = content.match(thinkPattern);
if (matches) {
const reasoning_content = matches[1].trim();
const remainingContent = content.replace(thinkPattern, '').trim();
message.content = remainingContent;
if (reasoning_content) {
// Calculate thinking time
const thinkingTime = startTime ? ((Date.now() - startTime) / 1000).toFixed(1) : '0.5';
// @ts-ignore - Add reasoning properties
message.reasoning_content = reasoning_content;
message.thinking_time = thinkingTime;
// @ts-ignore - Add isThinking flag
message.isThinking = true;
return message;
}
}
return message;
}
/**
* 检查字符串是否为 Markdown 数组格式(以 '- ' 开头)
* @param {string} val - 要检查的字符串
* @returns {boolean} 是否为 Markdown 数组格式
*/
export const isMdArray = (val: string): boolean => {
return Boolean(val.match(/^-\s.*/m));
};
/**
* 解析欢迎消息字符串为 PrologueItem 数组
* @param {string} welcomeMsg - 欢迎消息字符串
* @returns {PrologueItem[]} 解析后的 PrologueItem 数组
*/
export const parseWelcomeMessage = (welcomeMsg?: string): PrologueItem[] => {
const lines = welcomeMsg?.split('\n');
if (!lines) return [];
return lines
.reduce((pre_array: PrologueItem[], current: string, index: number) => {
const currentObj = isMdArray(current)
? {
type: 'question' as const,
str: current.replace(/^-\s+/, ''),
index: index,
}
: {
type: 'md' as const,
str: current,
index: index,
};
if (pre_array.length > 0) {
const pre = pre_array[pre_array.length - 1];
if (!isMdArray(current) && pre.type === 'md') {
pre.str = [pre.str, current].join('\n');
pre.index = index;
return pre_array;
} else {
pre_array.push(currentObj);
}
} else {
pre_array.push(currentObj);
}
return pre_array;
}, [])
.sort((pre, next) => pre.index - next.index);
};
/**
* 处理 prologue items包括从 MCP 获取元数据的逻辑
* @param {Dataset} selectedKnowledge - 选中的知识库
* @param {PrologueItem[]} initialPrologueList - 初始的 prologue 列表
* @returns {Promise<PrologueItem[]>} 处理后的 prologue items
*/
export const processPrologueItems = async (selectedKnowledge: Dataset, initialPrologueList: PrologueItem[]): Promise<PrologueItem[]> => {
// 如果存在 mcpId从后端获取 MCP 元数据
if (selectedKnowledge?.mcpId) {
const { data } = await getObj(selectedKnowledge.mcpId);
if (data && data.description) {
// 使用 parseWelcomeMessage 解析 MCP 的描述信息
return parseWelcomeMessage(data.description);
}
}
// 如果存在 dataId从后端获取数据集元数据
if (selectedKnowledge?.dataId) {
const { data } = await getDataObj(selectedKnowledge.dataId);
if (data && data.description) {
// 使用 parseWelcomeMessage 解析数据集的描述信息
return parseWelcomeMessage(data.description);
}
}
// 如果没有 mcpId 和 dataId 或获取失败,返回初始列表
return initialPrologueList;
};
/**
* 从会话存储中获取访问令牌
* @returns {string} 访问令牌
*/
const token = computed(() => {
return Session.getToken();
});
/**
* 生成会话存储的key
* @param {string} knowledgeId - 知识库ID
* @param {boolean} notime - 是否不包含时间戳
* @param {string} mcpId - MCP服务ID可选
* @param {string} dataId - 数据ID可选
* @returns {string} 会话存储key
*/
export const generateConversationKey = (knowledgeId: string, notime?: boolean, mcpId?: string, dataId?: string) => {
// 构建基础key
let key = `chat-${knowledgeId}-${useUserInfo().userInfos.user.userId}-${token.value}`;
// 如果有mcpId添加到key中
if (mcpId) {
key += `-mcp-${mcpId}`;
}
// 如果有dataId添加到key中
if (dataId) {
key += `-data-${dataId}`;
}
// 如果需要时间戳添加到key末尾
if (!notime) {
key += `-${Date.now()}`;
}
return key;
};