init
This commit is contained in:
163
src/views/knowledge/aiChat/ts/message.ts
Normal file
163
src/views/knowledge/aiChat/ts/message.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
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;
|
||||
};
|
||||
Reference in New Issue
Block a user