From ab4d0093d9787cdab0389f789c80771702b689e5 Mon Sep 17 00:00:00 2001 From: xlj <543978819@qq.com> Date: Mon, 11 Aug 2025 14:49:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=81=8A=E5=A4=A9=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E6=9C=AC=E5=9C=B0=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/Scripts/test/ChatAIService.ts | 58 ++++- assets/Scripts/test/ChatHistoryManager.ts | 212 ++++++++++++++++++ .../Scripts/test/ChatHistoryManager.ts.meta | 9 + 3 files changed, 270 insertions(+), 9 deletions(-) create mode 100644 assets/Scripts/test/ChatHistoryManager.ts create mode 100644 assets/Scripts/test/ChatHistoryManager.ts.meta diff --git a/assets/Scripts/test/ChatAIService.ts b/assets/Scripts/test/ChatAIService.ts index 66e920fb..a6caf896 100644 --- a/assets/Scripts/test/ChatAIService.ts +++ b/assets/Scripts/test/ChatAIService.ts @@ -1,5 +1,6 @@ import { GoogleGenAI } from "@google/genai"; import { RoleConfig } from "./RoleConfig"; +import { ChatHistoryManager } from "./ChatHistoryManager"; // API配置 const API_CONFIG = { @@ -39,15 +40,37 @@ export class ChatAIService { private createOrGetChat(roleId: number): any { if (!this.chatInstances.has(roleId)) { const systemInstruction = RoleConfig.getRoleInstruction(roleId); - const chat = this.ai.chats.create({ - model: API_CONFIG.model, - config: { - temperature: API_CONFIG.temperature, - systemInstruction: systemInstruction - }, - }); + + // 从本地加载历史记录 + const savedHistory = ChatHistoryManager.Instance.loadHistory(roleId); + let chat; + if(savedHistory && savedHistory.length > 0) { + chat = this.ai.chats.create({ + model: API_CONFIG.model, + config: { + temperature: API_CONFIG.temperature, + systemInstruction: systemInstruction + }, + history: savedHistory + }); + }else{ + chat = this.ai.chats.create({ + model: API_CONFIG.model, + config: { + temperature: API_CONFIG.temperature, + systemInstruction: systemInstruction + } + }); + } + + this.chatInstances.set(roleId, chat); - console.log(`Created new chat instance for role ${roleId}`); + + if (savedHistory.length > 0) { + console.log(`Loaded ${savedHistory.length} history messages for role ${roleId}`); + } else { + console.log(`Created new chat instance for role ${roleId}`); + } } return this.chatInstances.get(roleId); } @@ -83,6 +106,19 @@ export class ChatAIService { if (response && response.text) { console.log(`Response from role ${roleId}:`, response.text); + + // 保存用户消息 + ChatHistoryManager.Instance.appendMessage(roleId, { + role: "user", + parts: [{ text: message }] + }); + + // 保存AI回复 + ChatHistoryManager.Instance.appendMessage(roleId, { + role: "model", + parts: [{ text: response.text }] + }); + return response.text; } else { console.warn(`Empty response from role ${roleId}`); @@ -101,8 +137,10 @@ export class ChatAIService { public clearChatHistory(roleId: number): void { if (this.chatInstances.has(roleId)) { this.chatInstances.delete(roleId); - console.log(`Cleared chat history for role ${roleId}`); } + // 清除本地存储的历史 + ChatHistoryManager.Instance.clearHistory(roleId); + console.log(`Cleared chat history for role ${roleId}`); } /** @@ -110,6 +148,8 @@ export class ChatAIService { */ public clearAllChatHistory(): void { this.chatInstances.clear(); + // 清除本地存储的所有历史 + ChatHistoryManager.Instance.clearAllHistory(); console.log("Cleared all chat histories"); } diff --git a/assets/Scripts/test/ChatHistoryManager.ts b/assets/Scripts/test/ChatHistoryManager.ts new file mode 100644 index 00000000..69a7fed4 --- /dev/null +++ b/assets/Scripts/test/ChatHistoryManager.ts @@ -0,0 +1,212 @@ +import { sys } from "cc"; + +export interface ChatMessage { + role: "user" | "model"; + parts: { text: string }[]; + timestamp?: number; +} + +export interface ChatHistory { + roleId: number; + messages: ChatMessage[]; + createdAt: number; + updatedAt: number; +} + +/** + * 聊天历史管理器 + * 负责聊天记录的本地存储、加载和管理 + */ +export class ChatHistoryManager { + private static _instance: ChatHistoryManager; + + public static get Instance(): ChatHistoryManager { + if (!this._instance) { + this._instance = new ChatHistoryManager(); + } + return this._instance; + } + + private constructor() {} + + /** + * 保存聊天历史到本地 + * @param roleId 角色ID + * @param messages 消息列表 + */ + public saveHistory(roleId: number, messages: ChatMessage[]): void { + const key = `chat_history_${roleId}`; + try { + const history: ChatHistory = { + roleId: roleId, + messages: messages, + createdAt: Date.now(), + updatedAt: Date.now() + }; + + sys.localStorage.setItem(key, JSON.stringify(history)); + console.log(`Saved chat history for role ${roleId}, ${messages.length} messages`); + } catch (error) { + console.error(`Failed to save chat history for role ${roleId}:`, error); + } + } + + /** + * 从本地加载聊天历史 + * @param roleId 角色ID + * @returns 消息列表,如果没有历史记录则返回空数组 + */ + public loadHistory(roleId: number): ChatMessage[] { + const key = `chat_history_${roleId}`; + try { + const data = sys.localStorage.getItem(key); + if (data) { + const history: ChatHistory = JSON.parse(data); + console.log(`Loaded chat history for role ${roleId}: ${history.messages.length} messages`); + return history.messages; + } + } catch (error) { + console.error(`Failed to load chat history for role ${roleId}:`, error); + // 如果数据损坏,清除错误的数据 + this.clearHistory(roleId); + } + return []; + } + + /** + * 清除指定角色的聊天历史 + * @param roleId 角色ID + */ + public clearHistory(roleId: number): void { + const key = `chat_history_${roleId}`; + sys.localStorage.removeItem(key); + console.log(`Cleared chat history for role ${roleId}`); + } + + /** + * 追加消息到历史记录 + * @param roleId 角色ID + * @param message 消息对象 + */ + public appendMessage(roleId: number, message: ChatMessage): void { + const history = this.loadHistory(roleId); + + // 添加时间戳 + message.timestamp = Date.now(); + history.push(message); + + // 限制历史长度,保留最近100条消息 + if (history.length > 100) { + history.splice(0, history.length - 100); + console.log(`Trimmed chat history for role ${roleId} to 100 messages`); + } + + this.saveHistory(roleId, history); + } + + /** + * 获取指定角色的消息数量 + * @param roleId 角色ID + * @returns 消息数量 + */ + public getMessageCount(roleId: number): number { + const history = this.loadHistory(roleId); + return history.length; + } + + /** + * 获取最近的N条消息 + * @param roleId 角色ID + * @param count 消息数量 + * @returns 最近的消息列表 + */ + public getRecentMessages(roleId: number, count: number = 10): ChatMessage[] { + const history = this.loadHistory(roleId); + return history.slice(-count); + } + + /** + * 清除所有聊天历史 + */ + public clearAllHistory(): void { + // 查找所有chat_history_开头的key + const keysToRemove: string[] = []; + for (let i = 0; i < sys.localStorage.length; i++) { + const key = sys.localStorage.key(i); + if (key && key.startsWith('chat_history_')) { + keysToRemove.push(key); + } + } + + // 删除找到的所有聊天历史 + keysToRemove.forEach(key => { + sys.localStorage.removeItem(key); + }); + + console.log(`Cleared all chat histories, ${keysToRemove.length} records removed`); + } + + /** + * 获取所有有历史记录的角色ID列表 + * @returns 角色ID数组 + */ + public getAllHistoryRoleIds(): number[] { + const roleIds: number[] = []; + for (let i = 0; i < sys.localStorage.length; i++) { + const key = sys.localStorage.key(i); + if (key && key.startsWith('chat_history_')) { + const roleId = parseInt(key.replace('chat_history_', '')); + if (!isNaN(roleId)) { + roleIds.push(roleId); + } + } + } + return roleIds; + } + + /** + * 准备上传到远程服务器(预留接口) + * @param roleId 角色ID + */ + public async syncToRemote(roleId: number): Promise { + const history = this.loadHistory(roleId); + if (history.length === 0) { + console.log(`No history to sync for role ${roleId}`); + return; + } + + try { + // TODO: 调用 HttpUnit.ins.api 上传到服务器 + // await HttpUnit.ins.api("chat/save_history", { + // role_id: roleId, + // messages: history + // }, "POST"); + + console.log(`Ready to sync ${history.length} messages for role ${roleId} to remote server`); + } catch (error) { + console.error(`Failed to sync history for role ${roleId}:`, error); + } + } + + /** + * 从远程服务器下载历史(预留接口) + * @param roleId 角色ID + */ + public async syncFromRemote(roleId: number): Promise { + try { + // TODO: 调用 HttpUnit.ins.api 从服务器获取历史 + // const response = await HttpUnit.ins.api("chat/get_history", { + // role_id: roleId + // }, "GET"); + + // if (response && response.messages) { + // this.saveHistory(roleId, response.messages); + // console.log(`Synced ${response.messages.length} messages from remote for role ${roleId}`); + // } + + console.log(`Ready to sync history from remote server for role ${roleId}`); + } catch (error) { + console.error(`Failed to sync from remote for role ${roleId}:`, error); + } + } +} \ No newline at end of file diff --git a/assets/Scripts/test/ChatHistoryManager.ts.meta b/assets/Scripts/test/ChatHistoryManager.ts.meta new file mode 100644 index 00000000..8007b5e8 --- /dev/null +++ b/assets/Scripts/test/ChatHistoryManager.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "9228a7c4-2443-45bb-b869-dd0f90361e1f", + "files": [], + "subMetas": {}, + "userData": {} +}