diff --git a/pkg/database/manager.py b/pkg/database/manager.py index 2fde0fbb..fb3fbe6f 100644 --- a/pkg/database/manager.py +++ b/pkg/database/manager.py @@ -118,6 +118,89 @@ class DatabaseManager: return sessions + # 获取此session_name前一个session的数据 + def last_session(self, session_name: str, cursor_timestamp: int): + + self.cursor.execute(""" + select `name`, `type`, `number`, `create_timestamp`, `last_interact_timestamp`, `prompt`, `status` + from `sessions` where `name` = '{}' and `last_interact_timestamp` < {} order by `last_interact_timestamp` desc + limit 1 + """.format(session_name, cursor_timestamp)) + results = self.cursor.fetchall() + if len(results) == 0: + return None + result = results[0] + + session_name = result[0] + subject_type = result[1] + subject_number = result[2] + create_timestamp = result[3] + last_interact_timestamp = result[4] + prompt = result[5] + status = result[6] + + return { + 'subject_type': subject_type, + 'subject_number': subject_number, + 'create_timestamp': create_timestamp, + 'last_interact_timestamp': last_interact_timestamp, + 'prompt': prompt + } + + # 获取此session_name后一个session的数据 + def next_session(self, session_name: str, cursor_timestamp: int): + + self.cursor.execute(""" + select `name`, `type`, `number`, `create_timestamp`, `last_interact_timestamp`, `prompt`, `status` + from `sessions` where `name` = '{}' and `last_interact_timestamp` > {} order by `last_interact_timestamp` asc + limit 1 + """.format(session_name, cursor_timestamp)) + results = self.cursor.fetchall() + if len(results) == 0: + return None + result = results[0] + + session_name = result[0] + subject_type = result[1] + subject_number = result[2] + create_timestamp = result[3] + last_interact_timestamp = result[4] + prompt = result[5] + status = result[6] + + return { + 'subject_type': subject_type, + 'subject_number': subject_number, + 'create_timestamp': create_timestamp, + 'last_interact_timestamp': last_interact_timestamp, + 'prompt': prompt + } + + def list_history(self, session_name: str, capacity: int, page: int): + self.cursor.execute(""" + select `name`, `type`, `number`, `create_timestamp`, `last_interact_timestamp`, `prompt`, `status` + from `sessions` where `name` = '{}' order by `last_interact_timestamp` desc limit {} offset {} + """.format(session_name, capacity, capacity * page)) + results = self.cursor.fetchall() + sessions = [] + for result in results: + session_name = result[0] + subject_type = result[1] + subject_number = result[2] + create_timestamp = result[3] + last_interact_timestamp = result[4] + prompt = result[5] + status = result[6] + + sessions.append({ + 'subject_type': subject_type, + 'subject_number': subject_number, + 'create_timestamp': create_timestamp, + 'last_interact_timestamp': last_interact_timestamp, + 'prompt': prompt + }) + + return sessions def get_inst() -> DatabaseManager: global inst diff --git a/pkg/openai/session.py b/pkg/openai/session.py index b271f509..194b8c0c 100644 --- a/pkg/openai/session.py +++ b/pkg/openai/session.py @@ -59,6 +59,7 @@ class Session: def __init__(self, name: str): self.name = name self.create_timestamp = int(time.time()) + self.last_interact_timestamp = int(time.time()) # 请求回复 # 这个函数是阻塞的 @@ -84,6 +85,9 @@ class Session: return res_ans def persistence(self): + if self.prompt == '': + return + db_inst = pkg.database.manager.get_inst() name_spt = self.name.split('_') @@ -101,10 +105,32 @@ class Session: pkg.database.manager.get_inst().explicit_close_session(self.name, self.create_timestamp) self.prompt = '' self.create_timestamp = int(time.time()) - self.last_interact_timestamp = 0 + self.last_interact_timestamp = int(time.time()) + # 切换到上一个session def last_session(self): - pass + last_one = pkg.database.manager.get_inst().last_session(self.name, self.last_interact_timestamp) + if last_one is None: + return None + else: + self.persistence() + + self.create_timestamp = last_one['create_timestamp'] + self.last_interact_timestamp = last_one['last_interact_timestamp'] + self.prompt = last_one['prompt'] + return self def next_session(self): - pass + next_one = pkg.database.manager.get_inst().next_session(self.name, self.last_interact_timestamp) + if next_one is None: + return None + else: + self.persistence() + + self.create_timestamp = next_one['create_timestamp'] + self.last_interact_timestamp = next_one['last_interact_timestamp'] + self.prompt = next_one['prompt'] + return self + + def list_history(self, capacity: int = 10, page: int = 0): + return pkg.database.manager.get_inst().list_history(self.name, capacity, page) diff --git a/pkg/qqbot/manager.py b/pkg/qqbot/manager.py index 2172f4fe..8b698b4d 100644 --- a/pkg/qqbot/manager.py +++ b/pkg/qqbot/manager.py @@ -1,13 +1,15 @@ from mirai import At, GroupMessage, MessageEvent, Mirai, Plain, StrangerMessage, WebSocketAdapter, FriendMessage, Image import pkg.openai.session from func_timeout import func_set_timeout, FunctionTimedOut +import datetime help_text = """帮助信息: !help - 显示帮助 !reset - 重置会话 !last - 切换到上一次的对话 !next - 切换到下一次的对话 -""" +!prompt - 显示当前对话所有内容 +!list - 列出所有历史会话""" inst = None @@ -58,17 +60,62 @@ class QQBotManager: session_name = "{}_{}".format(launcher_type, launcher_id) if text_message.startswith('!') or text_message.startswith("!"): # 指令 - cmd = text_message[1:].strip() + cmd = text_message[1:].strip().split(' ')[0] + params = text_message[1:].strip().split(' ')[1:] if cmd == 'help': reply = "[bot]" + help_text elif cmd == 'reset': pkg.openai.session.get_session(session_name).reset(explicit=True) reply = "[bot]会话已重置" elif cmd == 'last': - pass + result = pkg.openai.session.get_session(session_name).last_session() + if result is None: + reply = "[bot]没有上一次的对话" + else: + datetime_str = datetime.datetime.fromtimestamp(result.create_timestamp).strftime('%Y-%m-%d %H:%M:%S') + reply = "[bot]已切换到上一次的对话:\n创建时间:{}\n".format(datetime_str) + result.prompt[:min(100, len(result.prompt))] + \ + ("..." if len(result.prompt) > 100 else "#END#") elif cmd == 'next': - pass + result = pkg.openai.session.get_session(session_name).next_session() + if result is None: + reply = "[bot]没有下一次的对话" + else: + datetime_str = datetime.datetime.fromtimestamp(result.create_timestamp).strftime('%Y-%m-%d %H:%M:%S') + reply = "[bot]已切换到下一次的对话:\n创建时间:{}\n".format(datetime_str) + result.prompt[:min(100, len(result.prompt))] + \ + ("..." if len(result.prompt) > 100 else "#END#") + elif cmd == 'prompt': + reply = "[bot]当前对话所有内容:\n" + pkg.openai.session.get_session(session_name).prompt + elif cmd == 'list': + pkg.openai.session.get_session(session_name).persistence() + page = 0 + + if len(params) > 0: + try: + page = int(params[0]) + except ValueError: + pass + + results = pkg.openai.session.get_session(session_name).list_history(page=page) + if len(results) == 0: + reply = "[bot]第{}页没有历史会话".format(page) + else: + reply = "[bot]历史会话 第{}页:\n".format(page) + current = -1 + for i in range(len(results)): + # 时间(使用create_timestamp转换) 序号 部分内容 + datetime_obj = datetime.datetime.fromtimestamp(results[i]['create_timestamp']) + reply += "#{} 创建:{} {}\n".format(i + page * 10, datetime_obj.strftime("%Y-%m-%d %H:%M:%S"), + results[i]['prompt'][:min(20, len(results[i]['prompt']))]) + if results[i]['create_timestamp'] == pkg.openai.session.get_session(session_name).create_timestamp: + current = i + page * 10 + + reply += "以上信息倒序排列" + if current != -1: + reply += ",当前会话是 #{}\n".format(current) + else: + reply += ",当前处于全新会话" + else: # 消息 session = pkg.openai.session.get_session(session_name) reply = "[GPT]" + session.append(text_message)