From e6d7b2b00933a8eb2c507af6ddab4928d1146a8b Mon Sep 17 00:00:00 2001 From: Liu Zhicong Date: Tue, 19 Sep 2023 21:36:56 -0700 Subject: [PATCH] Improve defualt agent Jarvis, fix some bug. --- rootfs/agents/David/agent.toml | 6 ++ rootfs/agents/Jarvis/agent.toml | 2 +- .../agents/{Tracy Wang => Tracy}/agent.toml | 6 +- src/aios_kernel/agent.py | 96 +++++++++++++++++-- src/aios_kernel/agent_message.py | 10 ++ src/aios_kernel/bus.py | 11 +-- src/aios_kernel/open_ai_node.py | 3 +- src/aios_kernel/workflow.py | 13 +-- 8 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 rootfs/agents/David/agent.toml rename rootfs/agents/{Tracy Wang => Tracy}/agent.toml (84%) diff --git a/rootfs/agents/David/agent.toml b/rootfs/agents/David/agent.toml new file mode 100644 index 0000000..3462da9 --- /dev/null +++ b/rootfs/agents/David/agent.toml @@ -0,0 +1,6 @@ +instance_id = "David" +fullname = "David" + +[[prompt]] +role = "system" +content = "你的名字是David,是一个擅长各种风格的画家。你在收到任何绘画请求时,会尝试产生一组英文单词来说明你想画的画" diff --git a/rootfs/agents/Jarvis/agent.toml b/rootfs/agents/Jarvis/agent.toml index 20cd7c0..7e3fd71 100644 --- a/rootfs/agents/Jarvis/agent.toml +++ b/rootfs/agents/Jarvis/agent.toml @@ -6,7 +6,7 @@ role = "system" content = """ 你叫Jarvis,是我的超级私人助理。 你领导一个团队为我服务,团队的成员有: -Tracy Wang,私人英语老师 +Tracy,私人英语老师 David,私人画家 *** diff --git a/rootfs/agents/Tracy Wang/agent.toml b/rootfs/agents/Tracy/agent.toml similarity index 84% rename from rootfs/agents/Tracy Wang/agent.toml rename to rootfs/agents/Tracy/agent.toml index c815314..a4a3462 100644 --- a/rootfs/agents/Tracy Wang/agent.toml +++ b/rootfs/agents/Tracy/agent.toml @@ -1,10 +1,10 @@ -instance_id = "Tracy Wang" -fullname = "Tracy Wang" +instance_id = "Tracy" +fullname = "Tracy" [[prompt]] role = "system" content = """ -Your name is Tracy Wang, and you are my advanced private English tutor. +Your name is Tracy, and you are my advanced private English tutor. ## You will assess my English proficiency based on all available information, using a 5-point scale. ## While interacting with me normally, you will adjust my input into more idiomatic American sentences. ## Depending on my level of English, you will annotate potentially incorrect words with phonetic symbols or provide expanded explanations for certain words and phrases. diff --git a/src/aios_kernel/agent.py b/src/aios_kernel/agent.py index 25c7a4a..5bb3027 100644 --- a/src/aios_kernel/agent.py +++ b/src/aios_kernel/agent.py @@ -8,7 +8,7 @@ import time import json import shlex -from .agent_message import AgentMsg, AgentMsgStatus, AgentMsgType +from .agent_message import AgentMsg, AgentMsgStatus, AgentMsgType,FunctionItem,LLMResult from .chatsession import AIChatSession from .compute_task import ComputeTaskResult from .ai_function import AIFunction @@ -124,16 +124,82 @@ class AIAgent: return True - def _get_llm_result_type(self,result:str) -> str: - if result == "ignore": - return "ignore" + def _get_llm_result_type(self,llm_result_str:str) -> LLMResult: + r = LLMResult() + if llm_result_str is None: + r.state = "ignore" + return r + if llm_result_str == "ignore": + r.state = "ignore" + return r - return "text" + lines = llm_result_str.splitlines() + is_need_wait = False + + 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}") + return False + new_msg = AgentMsg() + target_id = func_item.args[0] + msg_content = func_item.body + new_msg.set(self.agent_id,target_id,msg_content) + + r.send_msgs.append(new_msg) + 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}") + return False + new_msg = AgentMsg() + target_id = func_item.args[0] + msg_content = func_item.body + new_msg.set(self.agent_id,target_id,msg_content) + r.post_msgs.append(new_msg) + + case "call":# call($func_name,$args_str) + r.calls.append(func_item) + is_need_wait = True + return True + case "post_call": # post_call($func_name,$args_str) + r.post_calls.append(func_item) + return True + + current_func : FunctionItem = None + for line in lines: + if line.startswith("##/"): + if current_func: + if check_args(current_func) is False: + r.resp += current_func.dumps() + + func_name,func_args = AgentMsg.parse_function_call(line[3:]) + current_func = FunctionItem(func_name,func_args) + else: + if current_func: + current_func.append_body(line + "\n") + else: + r.resp += line + "\n" + + if current_func: + if check_args(current_func) is False: + r.resp += current_func.dumps() + + if len(r.send_msgs) > 0 or len(r.calls) > 0: + r.state = "waiting" + else: + r.state = "reponsed" + + return r def _get_inner_functions(self) -> dict: if self.owner_env is None: return None + return None + all_inner_function = self.owner_env.get_all_ai_functions() if all_inner_function is None: return None @@ -178,6 +244,7 @@ class AIAgent: async def _process_msg(self,msg:AgentMsg) -> AgentMsg: from .compute_kernel import ComputeKernel + from .bus import AIBus session_topic = msg.get_sender() + "#" + msg.topic chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.chat_db) @@ -206,13 +273,26 @@ class AIAgent: #TODO to save more token ,can i use msg_prompt? final_result = await self._execute_func(inner_func_call_node,prompt,msg) - result_type : str = self._get_llm_result_type(final_result) + llm_result : LLMResult = self._get_llm_result_type(final_result) is_ignore = False - - match result_type: + result_prompt_str = "" + match llm_result.state: case "ignore": is_ignore = True + case "waiting": + for sendmsg in llm_result.send_msgs: + target = sendmsg.target + sendmsg.topic = msg.topic + sendmsg.prev_msg_id = msg.get_msg_id() + send_resp = await AIBus.get_default_bus().send_message(sendmsg) + if send_resp is not None: + result_prompt_str += f"\n{target} response is :{send_resp.body}" + agent_sesion = AIChatSession.get_session(self.agent_id,f"{sendmsg.target}#{sendmsg.topic}",self.chat_db) + agent_sesion.append(sendmsg) + agent_sesion.append(send_resp) + final_result = llm_result.resp + result_prompt_str + if is_ignore is not True: resp_msg = msg.create_resp_msg(final_result) chatsession.append(msg) diff --git a/src/aios_kernel/agent_message.py b/src/aios_kernel/agent_message.py index 07227e9..4c19a7a 100644 --- a/src/aios_kernel/agent_message.py +++ b/src/aios_kernel/agent_message.py @@ -3,6 +3,8 @@ import uuid import time import re import shlex +from typing import List +from .ai_function import FunctionItem class AgentMsgType(Enum): TYPE_MSG = 0 @@ -129,3 +131,11 @@ class AgentMsg: params = str_list[1:] return func_name, params +class LLMResult: + def __init__(self) -> None: + self.state : str = "ignore" + self.resp : str = "" + self.post_msgs : List[AgentMsg] = [] + self.send_msgs : List[AgentMsg] = [] + self.calls : List[FunctionItem] = [] + self.post_calls : List[FunctionItem] = [] \ No newline at end of file diff --git a/src/aios_kernel/bus.py b/src/aios_kernel/bus.py index 1e97733..29fc186 100644 --- a/src/aios_kernel/bus.py +++ b/src/aios_kernel/bus.py @@ -20,13 +20,6 @@ class AIBusHandler: if self.handler is None: return None - if self.enable_defualt_proc: - # do default process - if msg.rely_msg_id is not None: - self.results[msg.rely_msg_id] = msg - return None - - resp_msg = await self.handler(msg) if self.enable_defualt_proc: if resp_msg is not None: @@ -52,6 +45,10 @@ class AIBus: handler = self.handlers.get(target_id) if handler: + if msg.rely_msg_id is not None: + handler.results[msg.rely_msg_id] = msg + return None + handler.queue.put_nowait(msg) self.start_process(target_id) return True diff --git a/src/aios_kernel/open_ai_node.py b/src/aios_kernel/open_ai_node.py index 8362a5a..c30fc87 100644 --- a/src/aios_kernel/open_ai_node.py +++ b/src/aios_kernel/open_ai_node.py @@ -4,6 +4,7 @@ import os import asyncio from asyncio import Queue import logging +import json from .compute_task import ComputeTask, ComputeTaskResult, ComputeTaskState, ComputeTaskType from .compute_node import ComputeNode @@ -114,7 +115,7 @@ class OpenAI_ComputeNode(ComputeNode): temperature=0.7) # TODO: add temperature to task params? - logger.info(f"openai response: {resp}") + logger.info(f"openai response: {json.dumps(resp, indent=4)}") result = ComputeTaskResult() result.set_from_task(task) diff --git a/src/aios_kernel/workflow.py b/src/aios_kernel/workflow.py index 3d98dce..48e8a4b 100644 --- a/src/aios_kernel/workflow.py +++ b/src/aios_kernel/workflow.py @@ -8,7 +8,7 @@ from typing import Optional,Tuple,List from abc import ABC, abstractmethod from .environment import Environment,EnvironmentEvent -from .agent_message import AgentMsg,AgentMsgStatus +from .agent_message import AgentMsg,AgentMsgStatus,FunctionItem,LLMResult from .agent import AgentPrompt,AgentMsg from .chatsession import AIChatSession from .role import AIRole,AIRoleGroup @@ -38,14 +38,7 @@ class MessageFilter: return True -class LLMResult: - def __init__(self) -> None: - self.state : str = "ignore" - self.resp : str = "" - self.post_msgs : List[AgentMsg] = [] - self.send_msgs : List[AgentMsg] = [] - self.calls : List[FunctionItem] = [] - self.post_calls : List[FunctionItem] = [] + class Workflow: @@ -306,7 +299,7 @@ class Workflow: if current_func: if check_args(current_func) is False: r.resp += current_func.dumps() - + if len(r.send_msgs) > 0 or len(r.calls) > 0: r.state = "waiting" else: