mirror of
https://github.com/Jerryplusy/crystelf-plugin.git
synced 2025-12-05 15:41:56 +00:00
feat:优化提示词
This commit is contained in:
parent
356233263c
commit
1c3ce32678
17
apps/ai.js
17
apps/ai.js
@ -102,7 +102,9 @@ function extractUserMessage(msg, nickname,e) {
|
|||||||
const regex = new RegExp(`^${nickname}\\s*([\\s\\S]*)?$`);
|
const regex = new RegExp(`^${nickname}\\s*([\\s\\S]*)?$`);
|
||||||
const match = msg.match(regex);
|
const match = msg.match(regex);
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
return match[1].trim();
|
let message = match[1].trim();
|
||||||
|
message = `[${e.sender?.nickname},id:${e.user_id}]说:${message}`;
|
||||||
|
return message;
|
||||||
} else {
|
} else {
|
||||||
if(e.message){
|
if(e.message){
|
||||||
let text;
|
let text;
|
||||||
@ -111,7 +113,7 @@ function extractUserMessage(msg, nickname,e) {
|
|||||||
text = message.text;
|
text = message.text;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if(text) return text;
|
if(text) return `[${e.sender?.nickname},id:${e.user_id}]说:${text}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.warn('[crystelf-ai] 字符串匹配失败,使用空字符串操作');
|
logger.warn('[crystelf-ai] 字符串匹配失败,使用空字符串操作');
|
||||||
@ -210,10 +212,11 @@ async function callAiForResponse(userMessage, e, aiConfig) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
//搜索相关记忆
|
//搜索相关记忆
|
||||||
const memories = await MemorySystem.searchMemories([userMessage], 5);
|
const memories = await MemorySystem.searchMemories(e.user_id,[userMessage], 5);
|
||||||
//构建聊天历史
|
//构建聊天历史
|
||||||
const chatHistory = session.chatHistory.slice(-10);
|
const historyLen = aiConfig.chatHistory;
|
||||||
const aiResult = await AiCaller.callAi(userMessage, chatHistory, memories);
|
const chatHistory = session.chatHistory.slice(-historyLen|-10);
|
||||||
|
const aiResult = await AiCaller.callAi(userMessage, chatHistory, memories,e);
|
||||||
if (!aiResult.success) {
|
if (!aiResult.success) {
|
||||||
logger.error(`[crystelf-ai] AI调用失败: ${aiResult.error}`);
|
logger.error(`[crystelf-ai] AI调用失败: ${aiResult.error}`);
|
||||||
return [
|
return [
|
||||||
@ -227,8 +230,10 @@ async function callAiForResponse(userMessage, e, aiConfig) {
|
|||||||
const processedResponse = await ResponseHandler.processResponse(
|
const processedResponse = await ResponseHandler.processResponse(
|
||||||
aiResult.response,
|
aiResult.response,
|
||||||
userMessage,
|
userMessage,
|
||||||
e.group_id
|
e.group_id,
|
||||||
|
e.user_id
|
||||||
);
|
);
|
||||||
|
|
||||||
//更新session
|
//更新session
|
||||||
const newChatHistory = [
|
const newChatHistory = [
|
||||||
...chatHistory,
|
...chatHistory,
|
||||||
|
|||||||
@ -28,6 +28,8 @@
|
|||||||
"timeout": 30,
|
"timeout": 30,
|
||||||
"?maxSessions": "最大同时存在的sessions群聊数量",
|
"?maxSessions": "最大同时存在的sessions群聊数量",
|
||||||
"maxSessions": 10,
|
"maxSessions": 10,
|
||||||
|
"?chatHistory": "聊天上下文最大长度",
|
||||||
|
"chatHistory": 10,
|
||||||
"?keywordCache": "是否缓存关键词到本地",
|
"?keywordCache": "是否缓存关键词到本地",
|
||||||
"keywordCache": true,
|
"keywordCache": true,
|
||||||
"?pinyinMatch": "是否启用拼音匹配",
|
"?pinyinMatch": "是否启用拼音匹配",
|
||||||
|
|||||||
@ -43,9 +43,10 @@ class AiCaller {
|
|||||||
* @param prompt 用户输入
|
* @param prompt 用户输入
|
||||||
* @param chatHistory 聊天历史
|
* @param chatHistory 聊天历史
|
||||||
* @param memories 记忆
|
* @param memories 记忆
|
||||||
|
* @param e
|
||||||
* @returns {Promise<{success: boolean, response: (*|string), rawResponse: (*|string)}|{success: boolean, error: string}|{success: boolean, error}>}
|
* @returns {Promise<{success: boolean, response: (*|string), rawResponse: (*|string)}|{success: boolean, error: string}|{success: boolean, error}>}
|
||||||
*/
|
*/
|
||||||
async callAi(prompt, chatHistory = [], memories = []) {
|
async callAi(prompt, chatHistory = [], memories = [],e) {
|
||||||
if (!this.isInitialized || !this.config) {
|
if (!this.isInitialized || !this.config) {
|
||||||
logger.error('[crystelf-ai] 未初始化或配置无效');
|
logger.error('[crystelf-ai] 未初始化或配置无效');
|
||||||
return { success: false, error: 'AI调用器未初始化' };
|
return { success: false, error: 'AI调用器未初始化' };
|
||||||
@ -59,7 +60,7 @@ class AiCaller {
|
|||||||
chatHistory: chatHistory,
|
chatHistory: chatHistory,
|
||||||
model: this.config.modelType,
|
model: this.config.modelType,
|
||||||
temperature: this.config.temperature,
|
temperature: this.config.temperature,
|
||||||
customPrompt: await this.getSystemPrompt(),
|
customPrompt: await this.getSystemPrompt(e),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
@ -89,9 +90,10 @@ class AiCaller {
|
|||||||
* @param chatHistory 聊天记录
|
* @param chatHistory 聊天记录
|
||||||
* @param memories 记忆
|
* @param memories 记忆
|
||||||
* @param onChunk 流式数据回调函数
|
* @param onChunk 流式数据回调函数
|
||||||
|
* @param e
|
||||||
* @returns {Promise<Object|{success: boolean, error: string}|{success: boolean, error}>}
|
* @returns {Promise<Object|{success: boolean, error: string}|{success: boolean, error}>}
|
||||||
*/
|
*/
|
||||||
async callAiStream(prompt, chatHistory = [], memories = [], onChunk = null) {
|
async callAiStream(prompt, chatHistory = [], memories = [], onChunk = null,e) {
|
||||||
if (!this.isInitialized || !this.config) {
|
if (!this.isInitialized || !this.config) {
|
||||||
logger.error('[crystelf-ai] 未初始化或配置无效');
|
logger.error('[crystelf-ai] 未初始化或配置无效');
|
||||||
return { success: false, error: 'AI调用器未初始化' };
|
return { success: false, error: 'AI调用器未初始化' };
|
||||||
@ -99,7 +101,7 @@ class AiCaller {
|
|||||||
|
|
||||||
if (!this.config.stream) {
|
if (!this.config.stream) {
|
||||||
logger.warn('[crystelf-ai] 流式输出未启用,使用普通调用');
|
logger.warn('[crystelf-ai] 流式输出未启用,使用普通调用');
|
||||||
return await this.callAi(prompt, chatHistory, memories);
|
return await this.callAi(prompt, chatHistory, memories,e);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -137,26 +139,59 @@ class AiCaller {
|
|||||||
*/
|
*/
|
||||||
buildPrompt(prompt, memories = []) {
|
buildPrompt(prompt, memories = []) {
|
||||||
let fullPrompt = '';
|
let fullPrompt = '';
|
||||||
// TODO 加入标准信息
|
|
||||||
if (memories && memories.length > 0) {
|
if (memories && memories.length > 0) {
|
||||||
fullPrompt += '相关记忆:\n';
|
fullPrompt += '你可能会用到的记忆,请按情况使用,如果不合语境请忽略:\n';
|
||||||
memories.forEach((memory, index) => {
|
memories.forEach((memory, index) => {
|
||||||
fullPrompt += `${index + 1}. ${memory.data}\n`;
|
fullPrompt += `${index + 1}. 关键词:${memory.keywords},内容:${memory.data}\n`;
|
||||||
});
|
});
|
||||||
fullPrompt += '\n';
|
fullPrompt += '\n';
|
||||||
}
|
}
|
||||||
fullPrompt += `用户说: ${prompt}\n`;
|
fullPrompt += `以下是用户说的内容,会以[用户昵称,用户qq号]的形式给你,但是请注意,你回复message块的时候不需要带[]以及里面的内容,正常回复你想说的话即可:\n${prompt}\n`;
|
||||||
fullPrompt += '请根据以上信息进行回复:\n';
|
|
||||||
return fullPrompt;
|
return fullPrompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取系统提示词
|
* 获取系统提示词
|
||||||
|
* @param {object} e 上下文事件对象
|
||||||
* @returns {Promise<string>} 系统提示词
|
* @returns {Promise<string>} 系统提示词
|
||||||
*/
|
*/
|
||||||
async getSystemPrompt() {
|
async getSystemPrompt(e) {
|
||||||
return this.config?.stream ? await getStreamSystemPrompt() : await getSystemPrompt();
|
try {
|
||||||
|
const basePrompt = this.config?.stream
|
||||||
|
? await getStreamSystemPrompt()
|
||||||
|
: await getSystemPrompt();
|
||||||
|
const config = await ConfigControl.get();
|
||||||
|
const botInfo = {
|
||||||
|
id: e.bot?.uin || '未知',
|
||||||
|
name: config?.profile?.nickName || '晶灵'
|
||||||
|
};
|
||||||
|
|
||||||
|
const userInfo = {
|
||||||
|
id: e.user_id || e.sender?.user_id || '未知',
|
||||||
|
name: e.sender?.card || e.sender?.nickname || '用户',
|
||||||
|
isMaster: e.isMaster,
|
||||||
|
};
|
||||||
|
const contextIntro = [
|
||||||
|
`以下是当前对话的上下文信息(仅供你理解对话背景,请勿泄露):`,
|
||||||
|
`[你的信息]`,
|
||||||
|
`- 你的昵称:${botInfo.name}`,
|
||||||
|
`- 你的qq号:${botInfo.id}`,
|
||||||
|
``,
|
||||||
|
`[跟你对话的用户的信息]`,
|
||||||
|
`- 他的名字:${userInfo.name}`,
|
||||||
|
`- 他的qq号(id):${userInfo.id}`,
|
||||||
|
`- 他${userInfo.isMaster ? '是':'不是'}你的主人`,
|
||||||
|
``,
|
||||||
|
`请基于以上上下文进行理解,这些信息是当你需要的时候使用的,绝对不能泄露这些信息,也不能主动提起`,
|
||||||
|
``,
|
||||||
|
].join('\n');
|
||||||
|
return `${contextIntro}${basePrompt}`;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(`[crystelf-ai] 生成系统提示词失败: ${error.message}`);
|
||||||
|
return await getSystemPrompt();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将回复分割成多个块用于流式输出
|
* 将回复分割成多个块用于流式输出
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import path from 'path';
|
|||||||
|
|
||||||
class MemorySystem {
|
class MemorySystem {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.memoryFile = path.join(process.cwd(), 'data', 'crystelf', 'ai_memory.json');
|
this.baseDir = path.join(process.cwd(), 'data', 'crystelf', 'memories');
|
||||||
this.memories = new Map(); // 内存中的记忆存储
|
this.memories = new Map(); // 内存中的记忆存储
|
||||||
this.defaultTimeout = 30; // 默认超时时间(天)
|
this.defaultTimeout = 30; // 默认超时时间(天)
|
||||||
}
|
}
|
||||||
@ -13,40 +13,60 @@ class MemorySystem {
|
|||||||
try {
|
try {
|
||||||
const config = await ConfigControl.get('ai');
|
const config = await ConfigControl.get('ai');
|
||||||
this.defaultTimeout = config?.timeout || 30;
|
this.defaultTimeout = config?.timeout || 30;
|
||||||
await this.loadMemories();
|
await this.loadAllMemories();
|
||||||
await this.cleanExpiredMemories();
|
await this.cleanExpiredMemories();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[crystelf-ai] 记忆系统初始化失败: ${error.message}`);
|
logger.error(`[crystelf-ai] 记忆系统初始化失败: ${error.message}`);
|
||||||
}
|
}
|
||||||
} // TODO 群聊id/用户id分组保存
|
}
|
||||||
|
|
||||||
async loadMemories() {
|
async loadAllMemories() {
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(this.memoryFile)) {
|
if (!fs.existsSync(this.baseDir)) {
|
||||||
const data = fs.readFileSync(this.memoryFile, 'utf8');
|
fs.mkdirSync(this.baseDir, { recursive: true });
|
||||||
const memoriesData = JSON.parse(data);
|
}
|
||||||
|
|
||||||
|
const groupDirs = fs.readdirSync(this.baseDir);
|
||||||
|
for (const groupId of groupDirs) {
|
||||||
|
const groupPath = path.join(this.baseDir, groupId);
|
||||||
|
if (!fs.statSync(groupPath).isDirectory()) continue;
|
||||||
|
|
||||||
|
const userFiles = fs.readdirSync(groupPath);
|
||||||
|
for (const file of userFiles) {
|
||||||
|
if (!file.endsWith('.json')) continue;
|
||||||
|
const userId = path.basename(file, '.json');
|
||||||
|
const filePath = path.join(groupPath, file);
|
||||||
|
const data = fs.readFileSync(filePath, 'utf8');
|
||||||
|
const memoriesData = JSON.parse(data || '{}');
|
||||||
for (const [key, memory] of Object.entries(memoriesData)) {
|
for (const [key, memory] of Object.entries(memoriesData)) {
|
||||||
this.memories.set(key, memory);
|
this.memories.set(`${groupId}_${userId}_${key}`, memory);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
logger.info(`[crystelf-ai] 加载了 ${this.memories.size} 条记忆`);
|
logger.info(`[crystelf-ai] 加载了 ${this.memories.size} 条记忆`);
|
||||||
} else {
|
|
||||||
const memoryDir = path.dirname(this.memoryFile);
|
|
||||||
if (!fs.existsSync(memoryDir)) {
|
|
||||||
fs.mkdirSync(memoryDir, { recursive: true });
|
|
||||||
}
|
|
||||||
fs.writeFileSync(this.memoryFile, '{}');
|
|
||||||
logger.info('[crystelf-ai] 创建新的记忆文件');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[crystelf-ai] 加载记忆失败: ${error.message}`);
|
logger.error(`[crystelf-ai] 加载记忆失败: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveMemories() {
|
async saveMemories(groupId, userId) {
|
||||||
try {
|
try {
|
||||||
const memoriesData = Object.fromEntries(this.memories);
|
const groupPath = path.join(this.baseDir, groupId);
|
||||||
fs.writeFileSync(this.memoryFile, JSON.stringify(memoriesData, null, 2));
|
const filePath = path.join(groupPath, `${userId}.json`);
|
||||||
logger.info('[crystelf-ai] 记忆已保存到文件');
|
if (!fs.existsSync(groupPath)) {
|
||||||
|
fs.mkdirSync(groupPath, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const userMemories = {};
|
||||||
|
for (const [key, memory] of this.memories) {
|
||||||
|
if (key.startsWith(`${groupId}_${userId}_`)) {
|
||||||
|
const memoryId = key.split(`${groupId}_${userId}_`)[1];
|
||||||
|
userMemories[memoryId] = memory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(filePath, JSON.stringify(userMemories, null, 2));
|
||||||
|
logger.info(`[crystelf-ai] 记忆已保存到 ${groupId}/${userId}.json`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[crystelf-ai] 保存记忆失败: ${error.message}`);
|
logger.error(`[crystelf-ai] 保存记忆失败: ${error.message}`);
|
||||||
}
|
}
|
||||||
@ -54,12 +74,14 @@ class MemorySystem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加记忆
|
* 添加记忆
|
||||||
|
* @param groupId 群聊id
|
||||||
|
* @param userId 用户id
|
||||||
* @param data 内容
|
* @param data 内容
|
||||||
* @param keywords 关键词
|
* @param keywords 关键词
|
||||||
* @param timeout 超时时间
|
* @param timeout 超时时间
|
||||||
* @returns {Promise<null|string>}
|
* @returns {Promise<null|string>}
|
||||||
*/
|
*/
|
||||||
async addMemory(data, keywords = [], timeout = null) {
|
async addMemory(groupId, userId, data, keywords = [], timeout = null) {
|
||||||
try {
|
try {
|
||||||
const memoryId = this.generateMemoryId();
|
const memoryId = this.generateMemoryId();
|
||||||
const expireTime = timeout || this.defaultTimeout;
|
const expireTime = timeout || this.defaultTimeout;
|
||||||
@ -72,10 +94,10 @@ class MemorySystem {
|
|||||||
accessCount: 0,
|
accessCount: 0,
|
||||||
lastAccessed: Date.now()
|
lastAccessed: Date.now()
|
||||||
};
|
};
|
||||||
this.memories.set(memoryId, memory);
|
this.memories.set(`${groupId}_${userId}_${memoryId}`, memory);
|
||||||
await this.saveMemories();
|
await this.saveMemories(groupId, userId);
|
||||||
|
|
||||||
logger.info(`[crystelf-ai] 添加新记忆: ${memoryId}`);
|
logger.info(`[crystelf-ai] 添加新记忆: ${groupId}/${userId}/${memoryId}`);
|
||||||
return memoryId;
|
return memoryId;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[crystelf-ai] 添加记忆失败: ${error.message}`);
|
logger.error(`[crystelf-ai] 添加记忆失败: ${error.message}`);
|
||||||
@ -85,36 +107,53 @@ class MemorySystem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 搜索记忆
|
* 搜索记忆
|
||||||
|
* @param userId 用户id
|
||||||
* @param keywords 关键词
|
* @param keywords 关键词
|
||||||
* @param limit 数量限制
|
* @param limit 数量限制
|
||||||
* @returns {Promise<*[]>}
|
* @returns {Promise<*[]>}
|
||||||
*/
|
*/
|
||||||
async searchMemories(keywords = [], limit = 10) {
|
async searchMemories(userId, keywords = [], limit = 10) {
|
||||||
try {
|
try {
|
||||||
const results = [];
|
const results = [];
|
||||||
|
const now = Date.now();
|
||||||
for (const [memoryId, memory] of this.memories) {
|
let searchText = '';
|
||||||
if (Date.now() > memory.expireAt) {
|
if (keywords.length === 1 && keywords[0].length > 6) {
|
||||||
continue;
|
searchText = keywords[0].toLowerCase();
|
||||||
|
const words = searchText.match(/[\u4e00-\u9fa5]{1,2}|[a-zA-Z0-9]+/g) || [];
|
||||||
|
keywords = Array.from(new Set(words.filter(w => w.length > 1))); // 去重+过滤过短词
|
||||||
}
|
}
|
||||||
if (keywords.length > 0) {
|
const userMemories = [];
|
||||||
const hasMatch = keywords.some(keyword =>
|
for (const [key, memory] of this.memories) {
|
||||||
memory.keywords.includes(keyword) ||
|
const parts = key.split('_');
|
||||||
memory.data.includes(keyword)
|
if (parts.length < 3) continue;
|
||||||
);
|
const uid = parts[1];
|
||||||
if (!hasMatch) {
|
if (uid !== userId) continue;
|
||||||
continue;
|
if (now > memory.expireAt) continue;
|
||||||
|
userMemories.push(memory);
|
||||||
|
}
|
||||||
|
if (userMemories.length === 0) return [];
|
||||||
|
for (const memory of userMemories) {
|
||||||
|
let matchScore = 0;
|
||||||
|
for (const kw of keywords) {
|
||||||
|
if (memory.keywords.some(k => k.includes(kw) || kw.includes(k))) matchScore += 10;
|
||||||
|
else if (memory.data.includes(kw)) matchScore += 5;
|
||||||
|
}
|
||||||
|
if (searchText) {
|
||||||
|
for (const mk of memory.keywords) {
|
||||||
|
if (searchText.includes(mk)) matchScore += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (matchScore > 0) {
|
||||||
memory.accessCount++;
|
memory.accessCount++;
|
||||||
memory.lastAccessed = Date.now();
|
memory.lastAccessed = now;
|
||||||
results.push({
|
results.push({
|
||||||
id: memory.id,
|
id: memory.id,
|
||||||
data: memory.data,
|
data: memory.data,
|
||||||
keywords: memory.keywords,
|
keywords: memory.keywords,
|
||||||
relevance: this.calculateRelevance(memory, keywords)
|
relevance: matchScore + this.calculateRelevance(memory, keywords)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
results.sort((a, b) => b.relevance - a.relevance);
|
results.sort((a, b) => b.relevance - a.relevance);
|
||||||
return results.slice(0, limit);
|
return results.slice(0, limit);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -123,6 +162,7 @@ class MemorySystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
calculateRelevance(memory, keywords) {
|
calculateRelevance(memory, keywords) {
|
||||||
let score = 0;
|
let score = 0;
|
||||||
for (const keyword of keywords) {
|
for (const keyword of keywords) {
|
||||||
@ -147,14 +187,16 @@ class MemorySystem {
|
|||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
let cleanedCount = 0;
|
let cleanedCount = 0;
|
||||||
|
|
||||||
for (const [memoryId, memory] of this.memories) {
|
for (const [memoryKey, memory] of this.memories) {
|
||||||
if (now > memory.expireAt) {
|
if (now > memory.expireAt) {
|
||||||
this.memories.delete(memoryId);
|
this.memories.delete(memoryKey);
|
||||||
cleanedCount++;
|
cleanedCount++;
|
||||||
|
const [groupId, userId] = memoryKey.split('_');
|
||||||
|
await this.saveMemories(groupId, userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cleanedCount > 0) {
|
if (cleanedCount > 0) {
|
||||||
await this.saveMemories();
|
|
||||||
logger.info(`[crystelf-ai] 清理了 ${cleanedCount} 条过期记忆`);
|
logger.info(`[crystelf-ai] 清理了 ${cleanedCount} 条过期记忆`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -13,10 +13,11 @@ class ResponseHandler {
|
|||||||
* 处理ai响应
|
* 处理ai响应
|
||||||
* @param rawResponse ai原始回复
|
* @param rawResponse ai原始回复
|
||||||
* @param userMessage 用户消息
|
* @param userMessage 用户消息
|
||||||
* @param groupId 群聊ai
|
* @param groupId 群聊id
|
||||||
|
* @param user_id 用户id
|
||||||
* @returns {Promise<[{type: string, data: string, at: boolean, quote: boolean, recall: number}]|Array|*[]>}
|
* @returns {Promise<[{type: string, data: string, at: boolean, quote: boolean, recall: number}]|Array|*[]>}
|
||||||
*/
|
*/
|
||||||
async processResponse(rawResponse, userMessage, groupId) {
|
async processResponse(rawResponse, userMessage, groupId,user_id) {
|
||||||
try {
|
try {
|
||||||
const parsedResponse = this.parseAiResponse(rawResponse);
|
const parsedResponse = this.parseAiResponse(rawResponse);
|
||||||
if (!parsedResponse.success) {
|
if (!parsedResponse.success) {
|
||||||
@ -26,7 +27,7 @@ class ResponseHandler {
|
|||||||
const messages = parsedResponse.messages;
|
const messages = parsedResponse.messages;
|
||||||
const processedMessages = [];
|
const processedMessages = [];
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
const processedMessage = await this.processMessage(message, userMessage, groupId);
|
const processedMessage = await this.processMessage(message, userMessage, groupId,user_id);
|
||||||
if (processedMessage) {
|
if (processedMessage) {
|
||||||
processedMessages.push(processedMessage);
|
processedMessages.push(processedMessage);
|
||||||
}
|
}
|
||||||
@ -73,15 +74,15 @@ class ResponseHandler {
|
|||||||
return cleaned;
|
return cleaned;
|
||||||
}
|
}
|
||||||
|
|
||||||
async processMessage(message, userMessage, groupId) {
|
async processMessage(message, userMessage, groupId,userId) {
|
||||||
try {
|
try {
|
||||||
if (!this.validateMessage(message)) {
|
if (!this.validateMessage(message)) {
|
||||||
logger.warn(`[响应处理器] 无效消息格式: ${JSON.stringify(message)}`);
|
logger.warn(`[crystelf-ai] 无效消息格式: ${JSON.stringify(message)}`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case 'memory':
|
case 'memory':
|
||||||
await this.handleMemoryMessage(message, groupId);
|
await this.handleMemoryMessage(message, groupId,userId);
|
||||||
return null;
|
return null;
|
||||||
case 'recall':
|
case 'recall':
|
||||||
return this.handleRecallMessage(message);
|
return this.handleRecallMessage(message);
|
||||||
@ -137,11 +138,14 @@ class ResponseHandler {
|
|||||||
* 记忆消息
|
* 记忆消息
|
||||||
* @param message 记忆
|
* @param message 记忆
|
||||||
* @param groupId 群聊id
|
* @param groupId 群聊id
|
||||||
|
* @param user_id 用户id
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async handleMemoryMessage(message, groupId) {
|
async handleMemoryMessage(message, groupId,user_id) {
|
||||||
try {
|
try {
|
||||||
const memoryId = await this.memorySystem.addMemory(
|
const memoryId = await this.memorySystem.addMemory(
|
||||||
|
groupId,
|
||||||
|
user_id,
|
||||||
message.data,
|
message.data,
|
||||||
message.key || [],
|
message.key || [],
|
||||||
message.timeout || 30
|
message.timeout || 30
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user