diff --git a/src/aios_kernel/environment.py b/src/aios_kernel/environment.py index 1e8cdab..cf5e9b3 100644 --- a/src/aios_kernel/environment.py +++ b/src/aios_kernel/environment.py @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) class EnvironmentEvent(ABC): @abstractmethod def display(self) -> str: - pass + pass EnvironmentEventHandler = Callable[[str,EnvironmentEvent],Awaitable[Any]] @@ -21,7 +21,7 @@ class Environment: @classmethod def get_env_by_id(cls,env_id:str): return cls._all_env.get(env_id) - + @classmethod def set_env_by_id(cls,id,env): assert id == env.get_id() @@ -39,7 +39,7 @@ class Environment: def get_id(self) -> str: return self.env_id - + def add_owner_env(self,env) -> None: self.owner_env[env.get_id()] = env @@ -51,11 +51,20 @@ class Environment: def add_ai_function(self,func:AIFunction) -> None: if self.functions.get(func.get_name()) is not None: logger.warn(f"add ai_function {func.get_name()} in env {self.env_id}:function already exist") - + self.functions[func.get_name()] = func def get_ai_function(self,func_name:str) -> AIFunction: - return self.functions.get(func_name) + func = self.functions.get(func_name) + if func is not None: + return func + + for owner_env in self.owner_env.values(): + func = owner_env.get_ai_function(func_name) + if func is not None: + return func + + return None #def enable_ai_function(self,func_name:str) -> None: # pass @@ -64,7 +73,11 @@ class Environment: # pass def get_all_ai_functions(self) -> List[AIFunction]: - return self.functions.values() + func_list = [] + func_list.extend(self.functions.values()) + for owner_env in self.owner_env.values(): + func_list.extend(owner_env.get_all_ai_functions()) + return func_list @abstractmethod def _do_get_value(self,key:str) -> Optional[str]: @@ -93,7 +106,7 @@ class Environment: return logger.warn(f"remove event_handler {event_id} in env {self.env_id}:handler not found") - + async def fire_event(self,event_id:str,event:EnvironmentEvent) -> None: handler_list = self.event_handlers.get(event_id) if handler_list is not None: @@ -102,15 +115,15 @@ class Environment: else: logger.debug(f"fire event {event_id} in env {self.env_id}:handler not found") return - + def __getitem__(self, key): return self.get_value(key) - + def get_value(self,key:str) -> Optional[str]: handler = self.get_handlers.get(key) if handler is not None: return handler() - + s = self.values.get(key) if isinstance(s,str): return s @@ -119,7 +132,7 @@ class Environment: s = self._do_get_value(key) if s is not None: - return s + return s if self.owner_env is not None: for env in self.owner_env.values(): s = env.get_value(key) @@ -128,7 +141,7 @@ class Environment: logger.warn(f"get value {key} in env {self.env_id} failed!,not found") return None - + def set_value(self, key: str, str_value: str,is_storage:bool = True): logger.info(f"set value {key} in env {self.env_id} to {str_value}") self.values[key] = str_value diff --git a/src/aios_kernel/role.py b/src/aios_kernel/role.py index 83d64d6..560d4db 100644 --- a/src/aios_kernel/role.py +++ b/src/aios_kernel/role.py @@ -35,18 +35,18 @@ class AIRole: if self.prompt.load_from_config(prompt_node) is False: logging.error("load prompt failed!") return False - + intro_node = config.get("intro") if intro_node is not None: self.introduce = intro_node history_node = config.get("history_len") - if history_node: + if history_node is not None: self.history_len = int(history_node) if config.get("enable_function") is not None: self.enable_function_list = config["enable_function"] - + def get_role_id(self) -> str: return self.role_id @@ -55,15 +55,15 @@ class AIRole: def get_name(self) -> str: return self.role_name - + def get_prompt(self) -> AgentPrompt: return self.prompt - + class AIRoleGroup: def __init__(self) -> None: self.roles : dict[str,AIRole] = {} self.owner_name : str = None - + def load_from_config(self,config:dict) -> bool: for k,v in config.items(): role = AIRole() @@ -72,10 +72,9 @@ class AIRoleGroup: return False role.role_id = self.owner_name + "." + k self.roles[k] = role - + return True def get(self,role_name:str) -> AIRole: return self.roles.get(role_name) - \ No newline at end of file diff --git a/src/aios_kernel/workflow.py b/src/aios_kernel/workflow.py index a25e202..5dae542 100644 --- a/src/aios_kernel/workflow.py +++ b/src/aios_kernel/workflow.py @@ -196,7 +196,7 @@ class Workflow: targets = self._parse_msg_target(msg.target) if len(targets) > 1: return await self._forword_msg(targets,msg) - + #0 we don't support workflow join a group right now, this cloud be a feture in future if msg.mentions is not None: logger.warn(f"workflow {self.workflow_id} recv a group chat message,not support ignore!") @@ -254,8 +254,8 @@ class Workflow: def check_args(func_item:FunctionItem): match func_name: case "send_msg":# sendmsg($target_id,$msg_content) - if len(func_args) != 1: - logger.error(f"parse sendmsg failed! {func_call}") + if len(func_item.args) != 1: + logger.error(f"parse sendmsg failed! {func_item}") return False new_msg = AgentMsg() target_id = func_item.args[0] @@ -266,8 +266,8 @@ class Workflow: is_need_wait = True case "post_msg":# postmsg($target_id,$msg_content) - if len(func_args) != 1: - logger.error(f"parse postmsg failed! {func_call}") + if len(func_item.args) != 1: + logger.error(f"parse postmsg failed! {func_item}") return False new_msg = AgentMsg() target_id = func_item.args[0] @@ -381,7 +381,7 @@ class Workflow: if the_role.enable_function_list is not None: if len(the_role.enable_function_list) > 0: if func_name not in the_role.enable_function_list: - logger.debug(f"agent {self.agent_id} ignore inner func:{func_name}") + logger.debug(f"agent {the_role.agent.agent_id} ignore inner func:{func_name}") continue else: continue @@ -410,6 +410,7 @@ class Workflow: except Exception as e: result_str = f"execute {func_name} error:{str(e)}" logger.error(f"llm execute inner func:{func_name} error:{e}") + logger.exception(e) inner_functions = self._get_inner_functions(the_role) @@ -442,7 +443,7 @@ class Workflow: prompt = AgentPrompt() - prompt.append(the_role.agent.prompt) + prompt.append(the_role.agent.agent_prompt) prompt.append(self.get_workflow_rule_prompt()) prompt.append(the_role.get_prompt()) # prompt.append(self._get_function_prompt(the_role.get_name())) @@ -465,7 +466,7 @@ class Workflow: logger.error(f"llm compute error:{task_result.error_str}") error_resp = msg.create_error_resp(task_result.error_str) return error_resp - + result_str = task_result.result_str logger.info(f"{the_role.role_id} process {msg.sender}:{msg.body},llm str is :{result_str}") @@ -513,7 +514,7 @@ class Workflow: workflow_chat_session.append(resp_msg) #await self.get_bus().resp_message(resp_msg) return resp_msg - case "waiting": + case "waiting": for sendmsg in result.send_msgs: target = sendmsg.target sendmsg.topic = msg.topic @@ -529,7 +530,7 @@ class Workflow: else: # message will be saved in role.process_message pass - + this_llm_resp_prompt = AgentPrompt() this_llm_resp_prompt.messages = [{"role":"assistant","content":result_str}] prompt.append(this_llm_resp_prompt)