# pylint:disable=E0402 import json import logging import shlex import uuid from enum import Enum import time from typing import Tuple, List logger = logging.getLogger(__name__) class AgentMsgType(Enum): TYPE_MSG = 0 TYPE_GROUPMSG = 1 TYPE_INTERNAL_CALL = 10 TYPE_ACTION = 20 TYPE_EVENT = 30 TYPE_SYSTEM = 40 class AgentMsgStatus(Enum): RESPONSED = 0 INIT = 1 SENDING = 2 PROCESSING = 3 ERROR = 4 RECVED = 5 EXECUTED = 6 # msg is a msg / msg resp # msg body可以有内容类型(MIME标签),text, image, voice, video, file,以及富文本(html) # msg is a inner function call with result # msg is a Action with result # qutoe Msg # forword msg # reply msg # 逻辑上的同一个Message在同一个session中看到的msgid相同 # 在不同的session中看到的msgid不同 class AgentMsg: def __init__(self,msg_type=AgentMsgType.TYPE_MSG) -> None: self.msg_id = "msg#" + uuid.uuid4().hex self.msg_type:AgentMsgType = msg_type self.prev_msg_id:str = None self.quote_msg_id:str = None self.rely_msg_id:str = None # if not none means this is a respone msg self.session_id:str = None #forword info self.create_time = 0 self.done_time = 0 self.topic:str = None # topic is use to find session, not store in db self.sender:str = None # obj_id.sub_objid@tunnel_id self.target:str = None self.mentions:[] = None #use in group chat only #self.title:str = None self.body:str = None self.body_mime:str = "text/plain" #//default is "text/plain",encode is utf8 #type is call / action self.func_name = None self.args = None self.result_str = None #type is event self.event_name = None self.event_args = None self.status = AgentMsgStatus.INIT self.inner_call_chain = [] self.resp_msg = None self.action_list = [] #context info self.context_info:dict= {} @classmethod def from_json(cls,json_obj:dict) -> 'AgentMsg': msg = AgentMsg() return msg @classmethod def create_internal_call_msg(self,func_name:str,args:dict,prev_msg_id:str,caller:str): msg = AgentMsg(AgentMsgType.TYPE_INTERNAL_CALL) msg.create_time = time.time() msg.func_name = func_name msg.args = args msg.prev_msg_id = prev_msg_id msg.sender = caller return msg def create_action_msg(self,action_name:str,args:dict,caller:str): msg = AgentMsg(AgentMsgType.TYPE_ACTION) msg.create_time = time.time() msg.func_name = action_name msg.args = args msg.prev_msg_id = self.msg_id msg.topic = self.topic msg.sender = caller return msg def create_error_resp(self,error_msg:str): resp_msg = AgentMsg(AgentMsgType.TYPE_SYSTEM) resp_msg.create_time = time.time() resp_msg.rely_msg_id = self.msg_id resp_msg.body = error_msg resp_msg.topic = self.topic resp_msg.sender = self.target resp_msg.target = self.sender return resp_msg def create_resp_msg(self,resp_body): resp_msg = AgentMsg() resp_msg.create_time = time.time() resp_msg.rely_msg_id = self.msg_id resp_msg.sender = self.target resp_msg.target = self.sender resp_msg.body = resp_body resp_msg.topic = self.topic return resp_msg def create_group_resp_msg(self,sender_id,resp_body): resp_msg = AgentMsg(AgentMsgType.TYPE_GROUPMSG) resp_msg.create_time = time.time() resp_msg.rely_msg_id = self.msg_id resp_msg.target = self.sender resp_msg.sender = sender_id resp_msg.body = resp_body resp_msg.topic = self.topic return resp_msg def set(self,sender:str,target:str,body:str,topic:str=None,body_mime:str=None) -> None: self.sender = sender self.target = target self.body = body self.body_mime = body_mime self.create_time = time.time() if topic: self.topic = topic @staticmethod def create_image_body(images: [str], prompt: str = None): return json.dumps({"images": images, "prompt": prompt}, ensure_ascii=False) @staticmethod def parse_image_body(image_body: str) -> Tuple[str, List[str]]: body = json.loads(image_body) return body.get("prompt"), body.get("images") @staticmethod def create_video_body(video: str, prompt: str = None): return json.dumps({"video": video, "prompt": prompt}, ensure_ascii=False) @staticmethod def parse_video_body(video_body: str) -> Tuple[str, str]: body = json.loads(video_body) return body.get("prompt"), body.get("video") @staticmethod def create_audio_body(audio: str, prompt: str = None): return json.dumps({"audio": audio, "prompt": prompt}, ensure_ascii=False) @staticmethod def parse_audio_body(audio_body: str) -> Tuple[str, str]: body = json.loads(audio_body) return body.get("prompt"), body.get("audio") def set_image(self, sender: str, target: str, image_format: str, images: [str], prompt: str = None, topic: str = None): self.sender = sender self.target = target self.create_time = time.time() self.body_mime = f"image/{image_format}" self.body = self.create_image_body(images, prompt) if topic: self.topic = topic def is_image_msg(self) -> bool: if self.body_mime is None: return False if self.body_mime.startswith("image/"): return True return False def get_image_body(self) -> Tuple[str, List[str]]: if self.body_mime is None: return None if self.body_mime.startswith("image/"): return self.parse_image_body(self.body) return None def set_video(self, sender: str, target: str, video_format: str, video: str, prompt: str = None, topic: str = None): self.sender = sender self.target = target self.create_time = time.time() self.body_mime = f"video/{video_format}" self.body = self.create_video_body(video, prompt) if topic: self.topic = topic def get_video_body(self) -> Tuple[str, str]: if self.body_mime is None: return None if self.body_mime.startswith("video/"): return self.parse_video_body(self.body) return None def is_video_msg(self) -> bool: if self.body_mime is None: return False if self.body_mime.startswith("video/"): return True return False def set_audio(self, sender: str, target: str, audio_format: str, audio: str, prompt: str = None, topic: str = None): self.sender = sender self.target = target self.create_time = time.time() self.body_mime = f"audio/{audio_format}" self.body = self.create_audio_body(audio, prompt) if topic: self.topic = topic def get_audio_body(self) -> Tuple[str, str]: if self.body_mime is None: return None if self.body_mime.startswith("audio/"): return self.parse_audio_body(self.body) return None def is_audio_msg(self) -> bool: if self.body_mime is None: return False if self.body_mime.startswith("audio/"): return True return False def get_msg_id(self) -> str: return self.msg_id def get_sender(self) -> str: return self.sender def get_target(self) -> str: return self.target def get_prev_msg_id(self) -> str: return self.prev_msg_id def get_quote_msg_id(self) -> str: return self.quote_msg_id