1. Build a more simple workflow:math_school

2. Fix some bug
This commit is contained in:
Liu Zhicong
2023-09-01 12:05:03 -07:00
parent b4990e4c57
commit 25bba0742a
5 changed files with 74 additions and 113 deletions
+5
View File
@@ -0,0 +1,5 @@
instance_id = "math_teacher"
fullname = "the one"
[[prompt]]
role = "system"
content = "你是精通数学的老师"
@@ -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="""你在学校任职,担任教导处主任。
你收到老师发来的信息时,如果是类似 学生名_作业分数 的结果,会在合适的情况下根据学生作业的整体情况,对老师的教学方法进行必要的调整。"""
+12 -97
View File
@@ -1,6 +1,7 @@
import logging import logging
import asyncio import asyncio
import json
from asyncio import Queue from asyncio import Queue
from typing import Optional,Tuple from typing import Optional,Tuple
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
@@ -79,13 +80,12 @@ class Workflow:
self.workflow_id = self.owner_workflow.workflow_id + "." + self.workflow_name self.workflow_id = self.owner_workflow.workflow_id + "." + self.workflow_name
self.db_file = self.owner_workflow.db_file self.db_file = self.owner_workflow.db_file
#if config.get("rule_prompt") is None: if config.get("prompt") is not None:
# logger.error("workflow config must have rule_prompt") self.rule_prompt = AgentPrompt()
# return False if self.rule_prompt.load_from_config(config.get("prompt")) is False:
#self.rule_prompt = AgentPrompt() logger.error("Workflow load prompt failed")
#if self.rule_prompt.load_from_config(config.get("rule_prompt")) is False: return False
# logger.error("Workflow load rule_prompt failed")
# return False
if config.get("roles") is None: if config.get("roles") is None:
logger.error("workflow config must have roles") logger.error("workflow config must have roles")
return False return False
@@ -225,8 +225,8 @@ class Workflow:
logger.error(f"parse postmsg failed! {func_call}") logger.error(f"parse postmsg failed! {func_call}")
continue continue
new_msg = AgentMsg() new_msg = AgentMsg()
target_id = func_args[1] target_id = func_args[0]
msg_content = func_args[2] msg_content = func_args[1]
new_msg.set("_",target_id,msg_content) new_msg.set("_",target_id,msg_content)
r.post_msgs.append(new_msg) r.post_msgs.append(new_msg)
continue continue
@@ -307,9 +307,8 @@ class Workflow:
prompt = AgentPrompt() prompt = AgentPrompt()
prompt.append(the_role.agent.prompt) prompt.append(the_role.agent.prompt)
prompt.append(self.get_workflow_rule_prompt())
prompt.append(the_role.get_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_function_prompt(the_role.get_name()))
# prompt.append(self._get_knowlege_prompt(the_role.get_name())) # prompt.append(self._get_knowlege_prompt(the_role.get_name()))
prompt.append(await self._get_prompt_from_session(chatsession)) prompt.append(await self._get_prompt_from_session(chatsession))
@@ -323,16 +322,14 @@ class Workflow:
#TODO: send msg to agent might be better? #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_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) 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: for postmsg in result.post_msgs:
postmsg.topic = msg.topic 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: for post_call in result.post_calls:
await self.role_post_call(post_call,the_role) await self.role_post_call(post_call,the_role)
result_prompt_str = "" result_prompt_str = ""
match result.state: match result.state:
case "ignore": case "ignore":
@@ -367,82 +364,6 @@ class Workflow:
return await _do_process_msg() 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: async def _get_prompt_from_session(self,chatsession:AIChatSession) -> AgentPrompt:
messages = chatsession.read_history() # read last 10 message messages = chatsession.read_history() # read last 10 message
result_prompt = AgentPrompt() result_prompt = AgentPrompt()
@@ -465,12 +386,6 @@ class Workflow:
def get_workflow_rule_prompt(self) -> AgentPrompt: def get_workflow_rule_prompt(self) -> AgentPrompt:
return self.rule_prompt 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: def _env_event_to_msg(self,env_event:EnvironmentEvent) -> AgentMsg:
pass pass
@@ -52,6 +52,7 @@ class WorkflowManager:
the_workflow = await self._load_workflow_from_media(workflow_media_info) the_workflow = await self._load_workflow_from_media(workflow_media_info)
if the_workflow is None: if the_workflow is None:
logger.warn(f"load workflow {workflow_id} from media failed!") logger.warn(f"load workflow {workflow_id} from media failed!")
return None
if await self._load_workflow_agents(the_workflow) is False: if await self._load_workflow_agents(the_workflow) is False:
return None return None
+6 -16
View File
@@ -107,6 +107,10 @@ class AIOS_Shell:
self.current_topic = topic self.current_topic = topic
show_text = FormattedText([("class:title", f"current session switch to {topic}@{target_id}")]) show_text = FormattedText([("class:title", f"current session switch to {topic}@{target_id}")])
return show_text return show_text
case 'login':
if len(args) >= 1:
self.username = args[0]
return self.username + " login success!"
case 'history': case 'history':
num = 10 num = 10
offset = 0 offset = 0
@@ -157,31 +161,17 @@ def parse_function_call(func_string):
async def main(): async def main():
print("aios shell prepareing...") 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, level=logging.INFO,
format='[%(asctime)s]%(name)s[%(levelname)s]: %(message)s') format='[%(asctime)s]%(name)s[%(levelname)s]: %(message)s')
shell = AIOS_Shell("user") shell = AIOS_Shell("user")
await shell.initial() 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.") print(f"aios shell {shell.get_version()} ready.")
completer = WordCompleter(['send($target,$msg,$topic)', completer = WordCompleter(['send($target,$msg,$topic)',
'open($target,$topic)', 'open($target,$topic)',
'history($num,$offset)', 'history($num,$offset)',
'login($username)'
'show()', 'show()',
'exit()', 'exit()',
'help()'], ignore_case=True) 'help()'], ignore_case=True)