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 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
@@ -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
+6 -16
View File
@@ -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)