diff --git a/rootfs/agents/math_teacher/agent.toml b/rootfs/agents/math_teacher/agent.toml new file mode 100644 index 0000000..e24792c --- /dev/null +++ b/rootfs/agents/math_teacher/agent.toml @@ -0,0 +1,5 @@ +instance_id = "math_teacher" +fullname = "the one" +[[prompt]] +role = "system" +content = "你是精通数学的老师" diff --git a/rootfs/workflows/math_school/workflow.toml b/rootfs/workflows/math_school/workflow.toml new file mode 100644 index 0000000..9f5af27 --- /dev/null +++ b/rootfs/workflows/math_school/workflow.toml @@ -0,0 +1,50 @@ +name = "math_school" + +[filter] +"*" = "小学老师" + +[roles."小学老师"] +name = "小学老师" +fullname = "Ada Zhang" +agent="math_teacher" +[[roles."小学老师".prompt]] +role="system" +content="""你在学校任职,担任小学老师。学校由 小学老师、初中老师、高中老师、教导处主任 组成。 +当你发现学生的水平不是小学生时,应使用 sendmsg(老师名称,问题) 的方法,把学生的问题转发给学校里合适的老师 +当学生发来作业时,进行批改(满分5分),并把批改结果以 postmsg(教导处主任,学生名_作业结果) 的方法,将一次作业情况汇报给教导处主任。 +你会根据教导处主任的指示,定期调整教学方法""" + + +[roles."初中老师"] +name = "初中老师" +fullname = "Mark Wang" +agent="math_teacher" +[[roles."初中老师".prompt]] +role="system" +content="""你在学校任职,担任初中老师。 +当你发现学生的水平不是初中生时,应使用 sendmsg(老师名称,问题) 的方法,把学生的问题转发给学校里合适的老师 +当学生发来作业时,进行批改(满分5分),并把批改结果以 postmsg(教导处主任,学生名_作业结果) 的方法,将一次作业情况汇报给教导处主任。 +你会根据教导处主任的指示,定期调整教学方法""" + +[roles."高中老师"] +name = "高中老师" +fullname = "Hong Sun" +agent="math_teacher" + +[[roles."高中老师".prompt]] +role="system" +content="""你在学校任职,担任高中老师。 +当你发现学生的水平不是高中生时,应使用 sendmsg(老师名称,问题) 的方法,把学生的问题转发给学校里合适的老师 +当学生发来作业时,进行批改(满分5分),并把批改结果以 postmsg(教导处主任,学生名_作业结果) 的方法,将一次作业情况汇报给教导处主任。 +你会根据教导处主任的指示,定期调整教学方法""" + +[roles."教导处主任"] +name = "教导处主任" +fullname = "Green King" +agent="math_teacher" + +[[roles."教导处主任".prompt]] +role="system" +content="""你在学校任职,担任教导处主任。 +你收到老师发来的信息时,如果是类似 学生名_作业分数 的结果,会在合适的情况下根据学生作业的整体情况,对老师的教学方法进行必要的调整。""" + diff --git a/src/aios_kernel/workflow.py b/src/aios_kernel/workflow.py index 9c90056..f7c13e8 100644 --- a/src/aios_kernel/workflow.py +++ b/src/aios_kernel/workflow.py @@ -1,6 +1,7 @@ import logging import asyncio +import json from asyncio import Queue from typing import Optional,Tuple from abc import ABC, abstractmethod @@ -79,13 +80,12 @@ class Workflow: self.workflow_id = self.owner_workflow.workflow_id + "." + self.workflow_name self.db_file = self.owner_workflow.db_file - #if config.get("rule_prompt") is None: - # logger.error("workflow config must have rule_prompt") - # return False - #self.rule_prompt = AgentPrompt() - #if self.rule_prompt.load_from_config(config.get("rule_prompt")) is False: - # logger.error("Workflow load rule_prompt failed") - # return False + if config.get("prompt") is not None: + self.rule_prompt = AgentPrompt() + if self.rule_prompt.load_from_config(config.get("prompt")) is False: + logger.error("Workflow load prompt failed") + return False + if config.get("roles") is None: logger.error("workflow config must have roles") return False @@ -225,8 +225,8 @@ class Workflow: logger.error(f"parse postmsg failed! {func_call}") continue new_msg = AgentMsg() - target_id = func_args[1] - msg_content = func_args[2] + target_id = func_args[0] + msg_content = func_args[1] new_msg.set("_",target_id,msg_content) r.post_msgs.append(new_msg) continue @@ -307,9 +307,8 @@ class Workflow: prompt = AgentPrompt() prompt.append(the_role.agent.prompt) + prompt.append(self.get_workflow_rule_prompt()) prompt.append(the_role.get_prompt()) - - # prompt.append(self.get_workflow_rule_prompt()) # prompt.append(self._get_function_prompt(the_role.get_name())) # prompt.append(self._get_knowlege_prompt(the_role.get_name())) prompt.append(await self._get_prompt_from_session(chatsession)) @@ -323,16 +322,14 @@ class Workflow: #TODO: send msg to agent might be better? result_str = await ComputeKernel().do_llm_completion(prompt,the_role.agent.get_llm_model_name(),the_role.agent.get_max_token_size()) result = Workflow.prase_llm_result(result_str) - - + logger.info(f"{the_role.role_id} process {msg.sender}:{msg.body},llm str is :{result_str}") for postmsg in result.post_msgs: postmsg.topic = msg.topic - await self.role_post_msg(the_role,postmsg) + await self.role_post_msg(postmsg,the_role) for post_call in result.post_calls: await self.role_post_call(post_call,the_role) - result_prompt_str = "" match result.state: case "ignore": @@ -367,82 +364,6 @@ class Workflow: return await _do_process_msg() - - #obsolete - async def _role_process_msg(self,msg:AgentMsg,the_role:AIRole) -> None: - # TODO : we just record role's chatsession, but in future, we would record workflow's chatsession(like a groupo chat) - session_topic = f"{the_role.get_name()}#{msg.sender}#{msg.topic}" - chatsession = AIChatSession.get_session(self.workflow_name,session_topic,self.db_file) - if chatsession is None: - logger.error(f"get session {session_topic}@{self.workflow_name} failed!") - return None - - # prompt generat progress is most important part of workflow(app) develope - prompt = AgentPrompt() - prompt.append(the_role.agent.prompt) - prompt.append(the_role.get_prompt()) - - # prompt.append(self.get_workflow_rule_prompt()) - # prompt.append(self._get_function_prompt(the_role.get_name())) - # prompt.append(self._get_knowlege_prompt(the_role.get_name())) - - prompt.append(await self._get_prompt_from_session(chatsession)) - - msg_prompt = AgentPrompt() - msg_prompt.messages = [{"role":"user","content":msg.body}] - prompt.append(msg_prompt) - - result = await ComputeKernel().do_llm_completion(prompt,the_role.agent.get_llm_model_name(),the_role.agent.get_max_token_size()) - chatsession.append_recv(msg) - final_result = result - - result_type : str = self._get_llm_result_type(result) - is_ignore = False - match result_type: - case "function": - callchain:CallChain = self._parse_function_call_chain(result) - resp = await callchain.exec() - if callchain.have_result(): - # generator proc resp prompt with WAITING state - proc_resp_prompt:AgentPrompt = self._get_resp_prompt(resp,msg,the_role,prompt,chatsession) - final_result = await ComputeKernel().do_llm_completion(proc_resp_prompt,the_role.agent.get_llm_model_name(),the_role.agent.get_max_token_size()) - return final_result - - - case "send_message": - # send message to other / sub workflow - next_msg:AgentMsg = self._parse_to_msg(result) - if next_msg is not None: - next_msg.sender = self.workflow_name - logger.info(f"W#{self.workflow_name} send message to {next_msg.get_target()}") - resp_msg = await self.get_bus().send_message(next_msg.get_target(),next_msg) - if resp_msg is not None: - msg_prompt = AgentPrompt() - msg_prompt.messages = [{"role":"assistant","content":result},{"role":"user","content":f"{next_msg.get_target()}:{resp_msg.body}"}] - - final_result = await ComputeKernel().do_llm_completion(proc_resp_prompt,the_role.agent.get_llm_model_name(),the_role.agent.get_max_token_size()) - - - case "post_message": - # post message to other / sub workflow - next_msg:AgentMsg = self._parse_to_msg(result) - if next_msg is not None: - next_msg.sender = self.workflow_name - logger.info(f"W#{self.workflow_name} post message to {next_msg.get_target()}") - self.get_bus().post_message(next_msg.get_target(),next_msg) - - case "ignore": - is_ignore = True - - if is_ignore: - return None - - resp_msg = AgentMsg() - resp_msg.set(self.workflow_name,msg.sender,final_result) - chatsession.append_post(resp_msg) - return resp_msg - - async def _get_prompt_from_session(self,chatsession:AIChatSession) -> AgentPrompt: messages = chatsession.read_history() # read last 10 message result_prompt = AgentPrompt() @@ -465,12 +386,6 @@ class Workflow: def get_workflow_rule_prompt(self) -> AgentPrompt: return self.rule_prompt - - def get_workflow(self,workflow_name:str): - """get workflow from known workflow list or sub workflow list""" - pass - - def _env_event_to_msg(self,env_event:EnvironmentEvent) -> AgentMsg: pass diff --git a/src/component/workflow_manager/workflow_manager.py b/src/component/workflow_manager/workflow_manager.py index adb844a..5603745 100644 --- a/src/component/workflow_manager/workflow_manager.py +++ b/src/component/workflow_manager/workflow_manager.py @@ -52,6 +52,7 @@ class WorkflowManager: the_workflow = await self._load_workflow_from_media(workflow_media_info) if the_workflow is None: logger.warn(f"load workflow {workflow_id} from media failed!") + return None if await self._load_workflow_agents(the_workflow) is False: return None diff --git a/src/service/aios_shell/aios_shell.py b/src/service/aios_shell/aios_shell.py index 3789957..5236e7e 100644 --- a/src/service/aios_shell/aios_shell.py +++ b/src/service/aios_shell/aios_shell.py @@ -107,6 +107,10 @@ class AIOS_Shell: self.current_topic = topic show_text = FormattedText([("class:title", f"current session switch to {topic}@{target_id}")]) return show_text + case 'login': + if len(args) >= 1: + self.username = args[0] + return self.username + " login success!" case 'history': num = 10 offset = 0 @@ -157,31 +161,17 @@ def parse_function_call(func_string): async def main(): print("aios shell prepareing...") - logging.basicConfig(filename="aios_shell.log",filemode="w",encoding='utf-8', + logging.basicConfig(filename="aios_shell.log",filemode="w",encoding='utf-8',force=True, level=logging.INFO, format='[%(asctime)s]%(name)s[%(levelname)s]: %(message)s') shell = AIOS_Shell("user") await shell.initial() - - s = """了解。首先,我们需要进行方案讨论,定出一致的活动策略。我将任务分解如下: -财务组: 分析可见的预算,提供一份合理并被执行的财务方案。 -行程预订组: 硅谷自然迷人的地方众多,寻找适合11人秋游的地点,以及一个可行的周末日期。策划一个一天或两天的安排,包括选择有南瓜园的地方,采摘苹果,参观当地的酗酒作坊等秋游活动。 -嘉宾对接组: 把个人的食品饮料或过敏食物的需求事先了解并计入行程内。 -酒店预订组:根据行程预订组的日期安排,活动时间在1天还是2天,在这个之内找一个合适的住宿,试着保持让住宿在预算边界以内。 -活动摄像组: 准备活动拍摄与剪辑方案。\n\n然后,我将把这些拆分后的任务发来小组。 -sendmsg(财务组,分析预算并提供一份财务方案.) -sendmsg(行程预订组,找出适合秋游的地方和日期.) -sendmsg(嘉宾对接组,了解个人的饮食需求.) -sendmsg(酒店预订组,查询并预订住宿.) -sendmsg(活动摄像组,提供活动拍摄方案.) -经过一两天的准备,一切就绪之后,我将向工作人员发送最后的行程计划, - """ - r = Workflow.prase_llm_result(s) print(f"aios shell {shell.get_version()} ready.") completer = WordCompleter(['send($target,$msg,$topic)', 'open($target,$topic)', 'history($num,$offset)', + 'login($username)' 'show()', 'exit()', 'help()'], ignore_case=True)