commit Agent Work Cycle frame codes
This commit is contained in:
@@ -18,7 +18,7 @@ from .email_tunnel import EmailTunnel
|
|||||||
from .storage import ResourceLocation,AIStorage,UserConfig,UserConfigItem
|
from .storage import ResourceLocation,AIStorage,UserConfig,UserConfigItem
|
||||||
from .contact_manager import ContactManager,Contact,FamilyMember
|
from .contact_manager import ContactManager,Contact,FamilyMember
|
||||||
from .text_to_speech_function import TextToSpeechFunction
|
from .text_to_speech_function import TextToSpeechFunction
|
||||||
from .workspace_env import WorkspaceEnvironment
|
from .workspace_env import ShellEnvironment
|
||||||
from .local_stability_node import Local_Stability_ComputeNode
|
from .local_stability_node import Local_Stability_ComputeNode
|
||||||
from .stability_node import Stability_ComputeNode
|
from .stability_node import Stability_ComputeNode
|
||||||
from .local_st_compute_node import LocalSentenceTransformer_Text_ComputeNode,LocalSentenceTransformer_Image_ComputeNode
|
from .local_st_compute_node import LocalSentenceTransformer_Text_ComputeNode,LocalSentenceTransformer_Image_ComputeNode
|
||||||
|
|||||||
+533
-170
@@ -10,7 +10,7 @@ import shlex
|
|||||||
import datetime
|
import datetime
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
from .agent_base import AgentMsg, AgentMsgStatus, AgentMsgType,FunctionItem,LLMResult,AgentPrompt
|
from .agent_base import AgentMsg, AgentMsgStatus, AgentMsgType,FunctionItem,LLMResult,AgentPrompt,AgentReport,AgentTodo,AgentGoal,AgentTodoResult,AgentWorkLog
|
||||||
from .chatsession import AIChatSession
|
from .chatsession import AIChatSession
|
||||||
from .compute_task import ComputeTaskResult,ComputeTaskResultCode
|
from .compute_task import ComputeTaskResult,ComputeTaskResultCode
|
||||||
from .ai_function import AIFunction
|
from .ai_function import AIFunction
|
||||||
@@ -18,12 +18,50 @@ from .environment import Environment
|
|||||||
from .contact_manager import ContactManager,Contact,FamilyMember
|
from .contact_manager import ContactManager,Contact,FamilyMember
|
||||||
from .compute_kernel import ComputeKernel
|
from .compute_kernel import ComputeKernel
|
||||||
from .bus import AIBus
|
from .bus import AIBus
|
||||||
|
from .workspace_env import WorkspaceEnvironment
|
||||||
|
|
||||||
from knowledge import *
|
from knowledge import *
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_AGENT_READ_REPORT_PROMPT = """
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEFAULT_AGENT_DO_PROMPT = """
|
||||||
|
You are a helpful AI assistant.
|
||||||
|
Solve tasks using your coding and language skills.
|
||||||
|
In the following cases, suggest python code (in a python coding block) for the user to execute.
|
||||||
|
1. When you need to collect info, use the code to output the info you need, for example, browse or search the web, download/read a file, print the content of a webpage or a file, get the current date/time, check the operating system. After sufficient info is printed and the task is ready to be solved based on your language skill, you can solve the task by yourself.
|
||||||
|
2. When you need to perform some task with code, use the code to perform the task and output the result. Finish the task smartly.
|
||||||
|
Solve the task step by step if you need to. If a plan is not provided, explain your plan first. Be clear which step uses code, and which step uses your language skill.
|
||||||
|
When using code, you must indicate the script type in the code block. The user cannot provide any other feedback or perform any other action beyond executing the code you suggest. The user can't modify your code. So do not suggest incomplete code which requires users to modify. Don't use a code block if it's not intended to be executed by the user.
|
||||||
|
If you want the user to save the code in a file before executing it, put # filename: <filename> inside the code block as the first line. Don't include multiple code blocks in one response. Do not ask users to copy and paste the result. Instead, use 'print' function for the output when relevant. Check the execution result returned by the user.
|
||||||
|
If the result indicates there is an error, fix the error and output the code again. Suggest the full code instead of partial code or code changes. If the error can't be fixed or if the task is not solved even after the code is executed successfully, analyze the problem, revisit your assumption, collect additional info you need, and think of a different approach to try.
|
||||||
|
When you find an answer, verify the answer carefully. Include verifiable evidence in your response if possible.
|
||||||
|
Reply "TERMINATE" in the end when everything is done.
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEFAULT_AGENT_SELF_CHECK_PROMPT = """
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEFAULT_AGENT_GOAL_TO_TODO_PROMPT = """
|
||||||
|
我会给你一个目标,你需要结合自己的角色思考如何将其拆解成多个TODO。请直接返回json来表达这些TODO
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEFAULT_AGENT_LEARN_PROMPT = """
|
||||||
|
你拥有非常优秀的资料整理技能。我给你一段内容,你会尝试对其进行摘要,并在已有的资料库中找到合适的位置存放该文章。
|
||||||
|
1. 结合你的角色和组织的工作目标构建摘要,尽量精简,长度不要超过256个字
|
||||||
|
2. 资料库以文件系统的形式组织,浏览知识库是成本高昂的操作,应尝试从根目录往子目录深入来找到最合适的信息。必要的情况下,你可以在合适的位置创建新的目录。为了方便浏览,每一层目录的文件夹数不超过32个,名称长度不超过16个字符,目录深度不超过6层
|
||||||
|
3. 你可以从不同的角度给出最多3个合适的位置
|
||||||
|
4. 返回一个json来保存摘要和建议保存位置信息
|
||||||
|
"""
|
||||||
|
|
||||||
|
DEFAULT_AGENT_LEARN_LONG_CONENT_PROMPT = """
|
||||||
|
我给你一段内容,尝试为期建立目录。目录的标题不能超过16个字,
|
||||||
|
目录要指向正文的位置(用字符偏移即可),整个目录的文本长度不能超过256个字节。并用json表达这个目录
|
||||||
|
"""
|
||||||
class AIAgentTemplete:
|
class AIAgentTemplete:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.llm_model_name:str = "gpt-4-0613"
|
self.llm_model_name:str = "gpt-4-0613"
|
||||||
@@ -57,6 +95,9 @@ class AIAgent:
|
|||||||
self.agent_think_prompt:AgentPrompt = None
|
self.agent_think_prompt:AgentPrompt = None
|
||||||
self.llm_model_name:str = None
|
self.llm_model_name:str = None
|
||||||
self.max_token_size:int = 3600
|
self.max_token_size:int = 3600
|
||||||
|
self.agent_energy = 15
|
||||||
|
self.agent_task = None
|
||||||
|
self.last_recover_time = time.time()
|
||||||
|
|
||||||
|
|
||||||
self.agent_id:str = None
|
self.agent_id:str = None
|
||||||
@@ -71,8 +112,17 @@ class AIAgent:
|
|||||||
self.contact_prompt_str = None
|
self.contact_prompt_str = None
|
||||||
self.history_len = 10
|
self.history_len = 10
|
||||||
|
|
||||||
|
self.review_todo_prompt = None
|
||||||
|
|
||||||
|
self.read_report_prompt = AgentPrompt(DEFAULT_AGENT_READ_REPORT_PROMPT)
|
||||||
|
|
||||||
|
self.do_prompt = AgentPrompt(DEFAULT_AGENT_DO_PROMPT)
|
||||||
|
self.self_check_prompt = AgentPrompt(DEFAULT_AGENT_SELF_CHECK_PROMPT)
|
||||||
|
|
||||||
|
self.goal_to_todo_prompt = AgentPrompt(DEFAULT_AGENT_GOAL_TO_TODO_PROMPT)
|
||||||
|
|
||||||
self.learn_token_limit = 500
|
self.learn_token_limit = 500
|
||||||
self.learn_prompt = None
|
self.learn_prompt = AgentPrompt(DEFAULT_AGENT_LEARN_PROMPT)
|
||||||
|
|
||||||
self.chat_db = None
|
self.chat_db = None
|
||||||
self.unread_msg = Queue() # msg from other agent
|
self.unread_msg = Queue() # msg from other agent
|
||||||
@@ -264,7 +314,7 @@ class AIAgent:
|
|||||||
else:
|
else:
|
||||||
return task_result
|
return task_result
|
||||||
|
|
||||||
async def _get_agent_prompt(self) -> AgentPrompt:
|
def get_agent_prompt(self) -> AgentPrompt:
|
||||||
return self.agent_prompt
|
return self.agent_prompt
|
||||||
|
|
||||||
async def _get_agent_think_prompt(self) -> AgentPrompt:
|
async def _get_agent_think_prompt(self) -> AgentPrompt:
|
||||||
@@ -280,183 +330,189 @@ class AIAgent:
|
|||||||
|
|
||||||
async def _handle_event(self,event):
|
async def _handle_event(self,event):
|
||||||
if event.type == "AgentThink":
|
if event.type == "AgentThink":
|
||||||
return await self._do_think()
|
return await self.do_self_think()
|
||||||
|
|
||||||
|
|
||||||
async def _do_think(self):
|
|
||||||
#1) load all sessions
|
|
||||||
session_id_list = AIChatSession.list_session(self.agent_id,self.chat_db)
|
|
||||||
#2) get history from session in token limit
|
|
||||||
for session_id in session_id_list:
|
|
||||||
await self.think_chatsession(session_id)
|
|
||||||
|
|
||||||
#4) advanced: reload all chatrecord,and think the topic of message.
|
|
||||||
#5) some topic could be end(not be thinked in futured )
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
async def think_chatsession(self,session_id):
|
|
||||||
if self.agent_think_prompt is None:
|
|
||||||
return
|
|
||||||
logger.info(f"agent {self.agent_id} think session {session_id}")
|
|
||||||
chatsession = AIChatSession.get_session_by_id(session_id,self.chat_db)
|
|
||||||
|
|
||||||
while True:
|
# async def _process_group_chat_msg(self,msg:AgentMsg) -> AgentMsg:
|
||||||
cur_pos = chatsession.summarize_pos
|
# session_topic = msg.target + "#" + msg.topic
|
||||||
summary = chatsession.summary
|
# chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.chat_db)
|
||||||
prompt:AgentPrompt = AgentPrompt()
|
# workspace = self.get_current_workspace()
|
||||||
#prompt.append(self._get_agent_prompt())
|
# need_process = False
|
||||||
prompt.append(await self._get_agent_think_prompt())
|
# if msg.mentions is not None:
|
||||||
system_prompt_len = prompt.get_prompt_token_len()
|
# if self.agent_id in msg.mentions:
|
||||||
#think env?
|
# need_process = True
|
||||||
history_prompt,next_pos = await self._get_history_prompt_for_think(chatsession,summary,system_prompt_len,cur_pos)
|
# logger.info(f"agent {self.agent_id} recv a group chat message from {msg.sender},but is not mentioned,ignore!")
|
||||||
prompt.append(history_prompt)
|
|
||||||
is_finish = next_pos - cur_pos < 2
|
|
||||||
if is_finish:
|
|
||||||
logger.info(f"agent {self.agent_id} think session {session_id} is finished!,no more history")
|
|
||||||
break
|
|
||||||
#3) llm summarize chat history
|
|
||||||
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,None)
|
|
||||||
if task_result.result_code != ComputeTaskResultCode.OK:
|
|
||||||
logger.error(f"llm compute error:{task_result.error_str}")
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
new_summary= task_result.result_str
|
|
||||||
logger.info(f"agent {self.agent_id} think session {session_id} from {cur_pos} to {next_pos} summary:{new_summary}")
|
|
||||||
chatsession.update_think_progress(next_pos,new_summary)
|
|
||||||
|
|
||||||
|
|
||||||
|
# if need_process is not True:
|
||||||
return
|
# chatsession.append(msg)
|
||||||
|
# resp_msg = msg.create_group_resp_msg(self.agent_id,"")
|
||||||
|
# return resp_msg
|
||||||
|
# else:
|
||||||
|
# msg_prompt = AgentPrompt()
|
||||||
|
# msg_prompt.messages = [{"role":"user","content":f"{msg.sender}:{msg.body}"}]
|
||||||
|
|
||||||
async def _process_group_chat_msg(self,msg:AgentMsg) -> AgentMsg:
|
# prompt = AgentPrompt()
|
||||||
session_topic = msg.target + "#" + msg.topic
|
# prompt.append(self.get_agent_prompt())
|
||||||
chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.chat_db)
|
|
||||||
need_process = False
|
|
||||||
if msg.mentions is not None:
|
|
||||||
if self.agent_id in msg.mentions:
|
|
||||||
need_process = True
|
|
||||||
logger.info(f"agent {self.agent_id} recv a group chat message from {msg.sender},but is not mentioned,ignore!")
|
|
||||||
|
|
||||||
if need_process is not True:
|
# if workspace:
|
||||||
chatsession.append(msg)
|
# prompt.append(workspace.get_prompt())
|
||||||
resp_msg = msg.create_group_resp_msg(self.agent_id,"")
|
# prompt.append(workspace.get_role_prompt(self.agent_id))
|
||||||
return resp_msg
|
|
||||||
else:
|
|
||||||
msg_prompt = AgentPrompt()
|
|
||||||
msg_prompt.messages = [{"role":"user","content":f"{msg.sender}:{msg.body}"}]
|
|
||||||
|
|
||||||
prompt = AgentPrompt()
|
# if self.need_session_summmary(msg,chatsession):
|
||||||
prompt.append(await self._get_agent_prompt())
|
# # get relate session(todos) summary
|
||||||
self._format_msg_by_env_value(prompt)
|
# summary = self.llm_select_session_summary(msg,chatsession)
|
||||||
inner_functions,function_token_len = self._get_inner_functions()
|
# prompt.append(AgentPrompt(summary))
|
||||||
|
|
||||||
|
# self._format_msg_by_env_value(prompt)
|
||||||
|
# inner_functions,function_token_len = self._get_inner_functions()
|
||||||
|
|
||||||
system_prompt_len = prompt.get_prompt_token_len()
|
# system_prompt_len = prompt.get_prompt_token_len()
|
||||||
input_len = len(msg.body)
|
# input_len = len(msg.body)
|
||||||
|
|
||||||
history_prmpt,history_token_len = await self._get_prompt_from_session_for_groupchat(chatsession,system_prompt_len + function_token_len,input_len)
|
# history_prmpt,history_token_len = await self._get_prompt_from_session_for_groupchat(chatsession,system_prompt_len + function_token_len,input_len)
|
||||||
prompt.append(history_prmpt) # chat context
|
# prompt.append(history_prmpt) # chat context
|
||||||
prompt.append(msg_prompt)
|
# prompt.append(msg_prompt)
|
||||||
|
|
||||||
logger.debug(f"Agent {self.agent_id} do llm token static system:{system_prompt_len},function:{function_token_len},history:{history_token_len},input:{input_len}, totoal prompt:{system_prompt_len + function_token_len + history_token_len} ")
|
# logger.debug(f"Agent {self.agent_id} do llm token static system:{system_prompt_len},function:{function_token_len},history:{history_token_len},input:{input_len}, totoal prompt:{system_prompt_len + function_token_len + history_token_len} ")
|
||||||
task_result = await self._do_llm_complection(prompt,inner_functions,msg)
|
# task_result = await self._do_llm_complection(prompt,inner_functions,msg)
|
||||||
if task_result.result_code != ComputeTaskResultCode.OK:
|
# if task_result.result_code != ComputeTaskResultCode.OK:
|
||||||
error_resp = msg.create_error_resp(task_result.error_str)
|
# error_resp = msg.create_error_resp(task_result.error_str)
|
||||||
return error_resp
|
# return error_resp
|
||||||
|
|
||||||
final_result = task_result.result_str
|
# final_result = task_result.result_str
|
||||||
llm_result : LLMResult = LLMResult.from_str(final_result)
|
# llm_result : LLMResult = LLMResult.from_str(final_result)
|
||||||
is_ignore = False
|
# is_ignore = False
|
||||||
result_prompt_str = ""
|
# result_prompt_str = ""
|
||||||
match llm_result.state:
|
# match llm_result.state:
|
||||||
case "ignore":
|
# case "ignore":
|
||||||
is_ignore = True
|
# is_ignore = True
|
||||||
case "waiting":
|
# case "waiting":
|
||||||
for sendmsg in llm_result.send_msgs:
|
# for sendmsg in llm_result.send_msgs:
|
||||||
target = sendmsg.target
|
# target = sendmsg.target
|
||||||
sendmsg.sender = self.agent_id
|
# sendmsg.sender = self.agent_id
|
||||||
sendmsg.topic = msg.topic
|
# sendmsg.topic = msg.topic
|
||||||
sendmsg.prev_msg_id = msg.get_msg_id()
|
# sendmsg.prev_msg_id = msg.get_msg_id()
|
||||||
send_resp = await AIBus.get_default_bus().send_message(sendmsg)
|
# send_resp = await AIBus.get_default_bus().send_message(sendmsg)
|
||||||
if send_resp is not None:
|
# if send_resp is not None:
|
||||||
result_prompt_str += f"\n{target} response is :{send_resp.body}"
|
# 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 = AIChatSession.get_session(self.agent_id,f"{sendmsg.target}#{sendmsg.topic}",self.chat_db)
|
||||||
agent_sesion.append(sendmsg)
|
# agent_sesion.append(sendmsg)
|
||||||
agent_sesion.append(send_resp)
|
# agent_sesion.append(send_resp)
|
||||||
|
|
||||||
final_result = llm_result.resp + result_prompt_str
|
# final_result = llm_result.resp + result_prompt_str
|
||||||
|
|
||||||
if is_ignore is not True:
|
# if is_ignore is not True:
|
||||||
resp_msg = msg.create_group_resp_msg(self.agent_id,final_result)
|
# resp_msg = msg.create_group_resp_msg(self.agent_id,final_result)
|
||||||
|
# chatsession.append(msg)
|
||||||
|
# chatsession.append(resp_msg)
|
||||||
|
|
||||||
|
# return resp_msg
|
||||||
|
|
||||||
|
# return None
|
||||||
|
def get_workspace_by_msg(self,msg:AgentMsg) -> WorkspaceEnvironment:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def need_session_summmary(self,msg:AgentMsg,session:AIChatSession) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def _process_msg(self,msg:AgentMsg,workspace = None) -> AgentMsg:
|
||||||
|
msg_prompt = AgentPrompt()
|
||||||
|
if msg.msg_type == AgentMsgType.TYPE_GROUPMSG:
|
||||||
|
need_process = False
|
||||||
|
msg_prompt.messages = [{"role":"user","content":f"{msg.sender}:{msg.body}"}]
|
||||||
|
session_topic = msg.target + "#" + msg.topic
|
||||||
|
chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.chat_db)
|
||||||
|
|
||||||
|
if msg.mentions is not None:
|
||||||
|
if self.agent_id in msg.mentions:
|
||||||
|
need_process = True
|
||||||
|
logger.info(f"agent {self.agent_id} recv a group chat message from {msg.sender},but is not mentioned,ignore!")
|
||||||
|
|
||||||
|
if need_process is not True:
|
||||||
chatsession.append(msg)
|
chatsession.append(msg)
|
||||||
chatsession.append(resp_msg)
|
resp_msg = msg.create_group_resp_msg(self.agent_id,"")
|
||||||
|
|
||||||
return resp_msg
|
return resp_msg
|
||||||
|
else:
|
||||||
return None
|
msg_prompt.messages = [{"role":"user","content":msg.body}]
|
||||||
|
|
||||||
async def _process_msg(self,msg:AgentMsg) -> AgentMsg:
|
|
||||||
if msg.msg_type == AgentMsgType.TYPE_GROUPMSG:
|
|
||||||
return await self._process_group_chat_msg(msg)
|
|
||||||
|
|
||||||
session_topic = msg.get_sender() + "#" + msg.topic
|
session_topic = msg.get_sender() + "#" + msg.topic
|
||||||
chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.chat_db)
|
chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.chat_db)
|
||||||
|
|
||||||
msg_prompt = AgentPrompt()
|
workspace = self.get_workspace_by_msg(msg)
|
||||||
msg_prompt.messages = [{"role":"user","content":msg.body}]
|
|
||||||
|
|
||||||
prompt = AgentPrompt()
|
prompt = AgentPrompt()
|
||||||
prompt.append(await self._get_agent_prompt())
|
if workspace:
|
||||||
self._format_msg_by_env_value(prompt)
|
prompt.append(workspace.get_prompt())
|
||||||
prompt.append(self._get_remote_user_prompt(msg.sender))
|
prompt.append(workspace.get_role_prompt(self.agent_id))
|
||||||
|
|
||||||
inner_functions,function_token_len = self._get_inner_functions()
|
prompt.append(self.get_agent_prompt())
|
||||||
|
prompt.append(self._get_remote_user_prompt(msg.sender))
|
||||||
system_prompt_len = prompt.get_prompt_token_len()
|
self._format_msg_by_env_value(prompt)
|
||||||
input_len = len(msg.body)
|
|
||||||
|
if self.need_session_summmary(msg,chatsession):
|
||||||
|
# get relate session(todos) summary
|
||||||
|
summary = self.llm_select_session_summary(msg,chatsession)
|
||||||
|
prompt.append(AgentPrompt(summary))
|
||||||
|
|
||||||
|
inner_functions,function_token_len = self._get_inner_functions()
|
||||||
|
system_prompt_len = prompt.get_prompt_token_len()
|
||||||
|
input_len = len(msg.body)
|
||||||
|
if msg.msg_type == AgentMsgType.TYPE_GROUPMSG:
|
||||||
|
history_prmpt,history_token_len = await self._get_prompt_from_session_for_groupchat(chatsession,system_prompt_len + function_token_len,input_len)
|
||||||
|
else:
|
||||||
|
history_prmpt,history_token_len = await self.get_prompt_from_session(chatsession,system_prompt_len + function_token_len,input_len)
|
||||||
|
prompt.append(history_prmpt) # chat context
|
||||||
|
|
||||||
history_prmpt,history_token_len = await self._get_prompt_from_session(chatsession,system_prompt_len + function_token_len,input_len)
|
prompt.append(msg_prompt)
|
||||||
prompt.append(history_prmpt) # chat context
|
|
||||||
prompt.append(msg_prompt)
|
|
||||||
|
|
||||||
logger.debug(f"Agent {self.agent_id} do llm token static system:{system_prompt_len},function:{function_token_len},history:{history_token_len},input:{input_len}, totoal prompt:{system_prompt_len + function_token_len + history_token_len} ")
|
|
||||||
#task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions)
|
logger.debug(f"Agent {self.agent_id} do llm token static system:{system_prompt_len},function:{function_token_len},history:{history_token_len},input:{input_len}, totoal prompt:{system_prompt_len + function_token_len + history_token_len} ")
|
||||||
task_result = await self._do_llm_complection(prompt,inner_functions,msg)
|
#task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions)
|
||||||
if task_result.result_code != ComputeTaskResultCode.OK:
|
task_result = await self._do_llm_complection(prompt,inner_functions,msg)
|
||||||
error_resp = msg.create_error_resp(task_result.error_str)
|
if task_result.result_code != ComputeTaskResultCode.OK:
|
||||||
return error_resp
|
error_resp = msg.create_error_resp(task_result.error_str)
|
||||||
|
return error_resp
|
||||||
final_result = task_result.result_str
|
|
||||||
|
final_result = task_result.result_str
|
||||||
|
|
||||||
llm_result : LLMResult = LLMResult.from_str(final_result)
|
llm_result : LLMResult = LLMResult.from_str(final_result)
|
||||||
is_ignore = False
|
|
||||||
result_prompt_str = ""
|
# extra_info include the operation about workspace
|
||||||
match llm_result.state:
|
if llm_result.extra_info is not None:
|
||||||
case "ignore":
|
await workspace.update_state_by_msg(msg,llm_result.extra_info)
|
||||||
is_ignore = True
|
|
||||||
case "waiting":
|
|
||||||
for sendmsg in llm_result.send_msgs:
|
|
||||||
sendmsg.sender = self.agent_id
|
|
||||||
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
|
is_ignore = False
|
||||||
|
result_prompt_str = ""
|
||||||
|
match llm_result.state:
|
||||||
|
case "ignore":
|
||||||
|
is_ignore = True
|
||||||
|
case "waiting": # like inner call
|
||||||
|
for sendmsg in llm_result.send_msgs:
|
||||||
|
sendmsg.sender = self.agent_id
|
||||||
|
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)
|
||||||
|
|
||||||
if is_ignore is not True:
|
final_result = llm_result.resp + result_prompt_str
|
||||||
|
|
||||||
|
if is_ignore is not True:
|
||||||
|
if msg.msg_type == AgentMsgType.TYPE_GROUPMSG:
|
||||||
|
resp_msg = msg.create_group_resp_msg(self.agent_id,final_result)
|
||||||
|
else:
|
||||||
resp_msg = msg.create_resp_msg(final_result)
|
resp_msg = msg.create_resp_msg(final_result)
|
||||||
chatsession.append(msg)
|
chatsession.append(msg)
|
||||||
chatsession.append(resp_msg)
|
chatsession.append(resp_msg)
|
||||||
|
|
||||||
return resp_msg
|
return resp_msg
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -527,27 +583,219 @@ class AIAgent:
|
|||||||
|
|
||||||
return result_prompt,result_token_len
|
return result_prompt,result_token_len
|
||||||
|
|
||||||
async def _do_llm_complection(self,prompt:AgentPrompt,inner_functions:dict,org_msg:AgentMsg=None) -> ComputeTaskResult:
|
|
||||||
from .compute_kernel import ComputeKernel
|
|
||||||
#logger.debug(f"Agent {self.agent_id} do llm token static system:{system_prompt_len},function:{function_token_len},history:{history_token_len},input:{input_len}, totoal prompt:{system_prompt_len + function_token_len + history_token_len} ")
|
|
||||||
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions)
|
|
||||||
if task_result.result_code != ComputeTaskResultCode.OK:
|
|
||||||
logger.error(f"llm compute error:{task_result.error_str}")
|
|
||||||
#error_resp = msg.create_error_resp(task_result.error_str)
|
|
||||||
return task_result
|
|
||||||
|
|
||||||
result_message = task_result.result.get("message")
|
|
||||||
inner_func_call_node = None
|
|
||||||
if result_message:
|
|
||||||
inner_func_call_node = result_message.get("function_call")
|
|
||||||
|
|
||||||
if inner_func_call_node:
|
async def _llm_summary_work(self,workspace:WorkspaceEnvironment):
|
||||||
call_prompt : AgentPrompt = copy.deepcopy(prompt)
|
# read report ,and update work summary of
|
||||||
task_result = await self._execute_func(inner_func_call_node,call_prompt,inner_functions,org_msg)
|
# build todo list from work summary and goals
|
||||||
|
#
|
||||||
|
report_list = self.get_unread_reports()
|
||||||
|
|
||||||
|
for report in report_list:
|
||||||
|
if self.agent_energy <= 0:
|
||||||
|
break
|
||||||
|
# merge report to work summary
|
||||||
|
await self._llm_read_report(report,workspace)
|
||||||
|
self.agent_energy -= 1
|
||||||
|
|
||||||
|
if workspace.is_mgr(self.agent_id):
|
||||||
|
# manager can do more work
|
||||||
|
await self._llm_review_team(workspace)
|
||||||
|
self.agent_energy -= 5
|
||||||
|
await self._llm_review_unassigned_todos(workspace)
|
||||||
|
self.agent_energy -= 5
|
||||||
|
|
||||||
|
|
||||||
|
async def _llm_review_team(self,workspace:WorkspaceEnvironment):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def _llm_review_unassigned_todos(self,workspace:WorkspaceEnvironment):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def _llm_read_report(self,report:AgentReport,worksapce:WorkspaceEnvironment):
|
||||||
|
work_summary = worksapce.get_work_summary(self.agent_id)
|
||||||
|
prompt : AgentPrompt = AgentPrompt()
|
||||||
|
prompt.append(self.agent_prompt)
|
||||||
|
prompt.append(worksapce.get_role_prompt(self.agent_id))
|
||||||
|
prompt.append(self.read_report_prompt)
|
||||||
|
# report is a message from other agent(human) about work
|
||||||
|
prompt.append(AgentPrompt(work_summary))
|
||||||
|
prompt.append(AgentPrompt(report.content))
|
||||||
|
|
||||||
|
task_result:ComputeTaskResult = await self._do_llm_complection(prompt)
|
||||||
|
|
||||||
|
if task_result.error_str is not None:
|
||||||
|
logger.error(f"_llm_read_report compute error:{task_result.error_str}")
|
||||||
|
return
|
||||||
|
|
||||||
|
worksapce.set_work_summary(self.agent_id,task_result.result_str)
|
||||||
|
|
||||||
|
|
||||||
|
# 尝试完成自己的TOOD (不依赖任何其他Agnet)
|
||||||
|
async def do_my_work(self) -> None:
|
||||||
|
workspace = self.get_current_workspace()
|
||||||
|
|
||||||
|
# review todo能更整体的思考一次todo的优先级
|
||||||
|
if await self.need_review_todos():
|
||||||
|
await self._llm_review_todos(workspace)
|
||||||
|
|
||||||
|
todo_list = workspace.get_todo_list(self.agent_id)
|
||||||
|
|
||||||
|
for todo in todo_list:
|
||||||
|
if self.agent_energy <= 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
if await self.can_do(todo,workspace) is False:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if todo.try_count() < 2:
|
||||||
|
need_think_todo_from_goal = False
|
||||||
|
do_result : AgentTodoResult = await self._llm_do(todo,workspace)
|
||||||
|
self.agent_energy -= 1
|
||||||
|
if do_result.result_state == "done":
|
||||||
|
await self._llm_check_todo(todo,workspace)
|
||||||
|
self.agent_energy -= 1
|
||||||
|
|
||||||
|
def get_review_todo_prompt(self) -> AgentPrompt:
|
||||||
|
return self.review_todo_prompt
|
||||||
|
|
||||||
|
async def need_review_todos(self) -> bool:
|
||||||
|
if self.get_review_todo_prompt() is None:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def _llm_review_todos(self,workspace:WorkspaceEnvironment):
|
||||||
|
prompt = AgentPrompt()
|
||||||
|
|
||||||
|
prompt.append(workspace.get_prompt())
|
||||||
|
prompt.append(workspace.get_role_prompt(self.agent_id))
|
||||||
|
prompt.append(self.get_review_todo_prompt())
|
||||||
|
|
||||||
|
todo_tree = workspace.get_todo_tree("/")
|
||||||
|
prompt.append(AgentPrompt(todo_tree))
|
||||||
|
inner_functions,function_token_len = self._get_inner_functions()
|
||||||
|
|
||||||
|
task_result:ComputeTaskResult = await self._do_llm_complection(prompt,inner_functions)
|
||||||
|
if task_result.result_code != ComputeTaskResultCode.OK:
|
||||||
|
logger.error(f"_llm_review_todos compute error:{task_result.error_str}")
|
||||||
|
return
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def get_do_prompt(self,todo_type:str) -> AgentPrompt:
|
||||||
|
return self.do_prompt
|
||||||
|
|
||||||
|
async def can_do(self,todo:AgentTodo,workspace:WorkspaceEnvironment) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def _llm_do(self,todo:AgentTodo,workspace:WorkspaceEnvironment) -> AgentTodoResult:
|
||||||
|
prompt : AgentPrompt = AgentPrompt()
|
||||||
|
prompt.append(self.agent_prompt)
|
||||||
|
prompt.append(workspace.get_role_prompt(self.agent_id))
|
||||||
|
|
||||||
|
do_prompt = workspace.get_do_prompt(todo.type)
|
||||||
|
if do_prompt is None:
|
||||||
|
do_prompt = self.get_do_prompt(todo.type)
|
||||||
|
|
||||||
|
prompt.append(do_prompt)
|
||||||
|
|
||||||
|
# 有通用的todo执行方法,也有定制的,针对特定类型TODO更高效的执行方法
|
||||||
|
# 根据经验,Agent可以自主掌握/整理更多类型的TODO的执行方法
|
||||||
|
|
||||||
|
#prompt.append(do_log_prompt)
|
||||||
|
prompt.append(self.get_prompt_from_todo(todo))
|
||||||
|
|
||||||
|
task_result:ComputeTaskResult = await self._do_llm_complection(prompt,workspace.get_inner_functions(todo.type))
|
||||||
|
|
||||||
|
if task_result.error_str is not None:
|
||||||
|
logger.error(f"_llm_do compute error:{task_result.error_str}")
|
||||||
|
|
||||||
|
llm_result = LLMResult.from_str(task_result.result_str)
|
||||||
|
todo.append_do_result(self.agent_id,llm_result)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return task_result
|
return task_result
|
||||||
|
|
||||||
def parser_learn_llm_result(self,llm_result:str):
|
async def _llm_check_todo(self, todo:AgentTodo,workspace:WorkspaceEnvironment) -> bool:
|
||||||
|
if self.get_check_prompt(todo) is None:
|
||||||
|
return True
|
||||||
|
|
||||||
|
prompt : AgentPrompt = AgentPrompt()
|
||||||
|
prompt.append(self.agent_prompt)
|
||||||
|
prompt.append(workspace.get_role_prompt(self.agent_id))
|
||||||
|
prompt.append(self.get_check_prompt(todo))
|
||||||
|
if todo.last_check_result:
|
||||||
|
prompt.append(AgentPrompt(todo.last_check_result))
|
||||||
|
|
||||||
|
prompt.append(todo.detail)
|
||||||
|
prompt.append(todo.result)
|
||||||
|
|
||||||
|
task_result:ComputeTaskResult = await self._do_llm_complection(prompt,workspace.get_inner_functions())
|
||||||
|
|
||||||
|
if task_result.result_code != ComputeTaskResultCode.OK:
|
||||||
|
logger.error(f"_llm_check_todo compute error:{task_result.error_str}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if task_result.result_str == "OK":
|
||||||
|
return True
|
||||||
|
todo.last_check_result = task_result.result_str
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 尝试自我学习,会主动获取、读取资料并进行整理
|
||||||
|
# LLM的本质能力是处理海量知识,应该让LLM能基于知识把自己的工作处理的更好
|
||||||
|
def do_self_learn(self) -> None:
|
||||||
|
# 不同的workspace是否应该有不同的学习方法?
|
||||||
|
learn_power = self.get_learn_power()
|
||||||
|
kb = self.get_knowledge_base()
|
||||||
|
for item in kb.un_learn_items():
|
||||||
|
if learn_power <= 0:
|
||||||
|
break
|
||||||
|
match item.type():
|
||||||
|
case "book":
|
||||||
|
self.llm_read_book(kb,item)
|
||||||
|
learn_power -= 1
|
||||||
|
case "article":
|
||||||
|
# 可以用vdb 对不同目录的名字进行选择后,先进行一次快速的插入。有时间再慢慢用LLM整理
|
||||||
|
self.llm_read_article(kb,item)
|
||||||
|
learn_power -= 1
|
||||||
|
case "video":
|
||||||
|
self.llm_watch_video(kb,item)
|
||||||
|
learn_power -= 1
|
||||||
|
case "audio":
|
||||||
|
self.llm_listen_audio(kb,item)
|
||||||
|
learn_power -= 1
|
||||||
|
case "code_project":
|
||||||
|
self.llm_read_code_project(kb,item)
|
||||||
|
learn_power -= 1
|
||||||
|
case "image":
|
||||||
|
self.llm_view_image(kb,item)
|
||||||
|
learn_power -= 1
|
||||||
|
case "other":
|
||||||
|
self.llm_read_other(kb,item)
|
||||||
|
learn_power -= 1
|
||||||
|
case _:
|
||||||
|
self.llm_learn_any(kb,item)
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 整理自己的知识库(让分类更平衡,更由于自己以后的工作),并尝试更新学习目标
|
||||||
|
current_path = "/"
|
||||||
|
current_list = kb.get_list(current_path)
|
||||||
|
self_assessment_with_goal = self.get_self_assessment_with_goal()
|
||||||
|
learn_goal = {}
|
||||||
|
|
||||||
|
|
||||||
|
llm_blance_knowledge_base(current_path,current_list,self_assessment_with_goal,learn_goal,learn_power)
|
||||||
|
|
||||||
|
# 主动学习
|
||||||
|
# 方法目前只有使用搜索引擎一种?
|
||||||
|
for goal in learn_goal.items():
|
||||||
|
self.llm_learn_with_search_engine(kb,goal,learn_power)
|
||||||
|
if learn_power <= 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def parser_learn_llm_result(self,llm_result:LLMResult):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _llm_read_article(self,item:KnowledgeObject) -> ComputeTaskResult:
|
async def _llm_read_article(self,item:KnowledgeObject) -> ComputeTaskResult:
|
||||||
@@ -568,7 +816,8 @@ class AIAgent:
|
|||||||
task_result:ComputeTaskResult = await self._do_llm_complection(prompt,env_functions)
|
task_result:ComputeTaskResult = await self._do_llm_complection(prompt,env_functions)
|
||||||
if task_result.result_code != ComputeTaskResultCode.OK:
|
if task_result.result_code != ComputeTaskResultCode.OK:
|
||||||
return task_result
|
return task_result
|
||||||
path_list,summary = self.parser_learn_llm_result(task_result.result_str)
|
llm_result = LLMResult.from_str(task_result.result_str)
|
||||||
|
path_list,summary = self.parser_learn_llm_result(llm_result)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# 用传统方法对文章进行一些处理,目的是尽可能减少LLM调用的次数
|
# 用传统方法对文章进行一些处理,目的是尽可能减少LLM调用的次数
|
||||||
@@ -592,9 +841,59 @@ class AIAgent:
|
|||||||
|
|
||||||
kb.insert_item(path_list,item,catelog,summary)
|
kb.insert_item(path_list,item,catelog,summary)
|
||||||
|
|
||||||
|
async def do_self_think(self):
|
||||||
|
session_id_list = AIChatSession.list_session(self.agent_id,self.chat_db)
|
||||||
|
for session_id in session_id_list:
|
||||||
|
if self.agent_energy <= 0:
|
||||||
|
break
|
||||||
|
used_energy = await self.think_chatsession(session_id)
|
||||||
|
self.agent_energy -= used_energy
|
||||||
|
|
||||||
|
todo_logs = await self.get_todo_logs()
|
||||||
|
for todo_log in todo_logs:
|
||||||
|
if self.agent_energy <= 0:
|
||||||
|
break
|
||||||
|
used_energy = await self.think_todo_log(todo_log)
|
||||||
|
self.agent_energy -= used_energy
|
||||||
|
|
||||||
async def _get_prompt_from_session(self,chatsession:AIChatSession,system_token_len,input_token_len) -> AgentPrompt:
|
return
|
||||||
|
|
||||||
|
|
||||||
|
async def think_todo_log(self,todo_log:AgentWorkLog):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def think_chatsession(self,session_id):
|
||||||
|
if self.agent_think_prompt is None:
|
||||||
|
return
|
||||||
|
logger.info(f"agent {self.agent_id} think session {session_id}")
|
||||||
|
chatsession = AIChatSession.get_session_by_id(session_id,self.chat_db)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
cur_pos = chatsession.summarize_pos
|
||||||
|
summary = chatsession.summary
|
||||||
|
prompt:AgentPrompt = AgentPrompt()
|
||||||
|
#prompt.append(self._get_agent_prompt())
|
||||||
|
prompt.append(await self._get_agent_think_prompt())
|
||||||
|
system_prompt_len = prompt.get_prompt_token_len()
|
||||||
|
#think env?
|
||||||
|
history_prompt,next_pos = await self._get_history_prompt_for_think(chatsession,summary,system_prompt_len,cur_pos)
|
||||||
|
prompt.append(history_prompt)
|
||||||
|
is_finish = next_pos - cur_pos < 2
|
||||||
|
if is_finish:
|
||||||
|
logger.info(f"agent {self.agent_id} think session {session_id} is finished!,no more history")
|
||||||
|
break
|
||||||
|
#3) llm summarize chat history
|
||||||
|
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,None)
|
||||||
|
if task_result.result_code != ComputeTaskResultCode.OK:
|
||||||
|
logger.error(f"llm compute error:{task_result.error_str}")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
new_summary= task_result.result_str
|
||||||
|
logger.info(f"agent {self.agent_id} think session {session_id} from {cur_pos} to {next_pos} summary:{new_summary}")
|
||||||
|
chatsession.update_think_progress(next_pos,new_summary)
|
||||||
|
return
|
||||||
|
|
||||||
|
async def get_prompt_from_session(self,chatsession:AIChatSession,system_token_len,input_token_len) -> AgentPrompt:
|
||||||
# TODO: get prompt from group chat is different from single chat
|
# TODO: get prompt from group chat is different from single chat
|
||||||
|
|
||||||
history_len = (self.max_token_size * 0.7) - system_token_len - input_token_len
|
history_len = (self.max_token_size * 0.7) - system_token_len - input_token_len
|
||||||
@@ -614,7 +913,6 @@ class AIAgent:
|
|||||||
formatted_time = dt.strftime('%y-%m-%d %H:%M:%S')
|
formatted_time = dt.strftime('%y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
if msg.sender == self.agent_id:
|
if msg.sender == self.agent_id:
|
||||||
|
|
||||||
if self.enable_timestamp:
|
if self.enable_timestamp:
|
||||||
result_prompt.messages.append({"role":"assistant","content":f"(create on {formatted_time}) {msg.body} "})
|
result_prompt.messages.append({"role":"assistant","content":f"(create on {formatted_time}) {msg.body} "})
|
||||||
else:
|
else:
|
||||||
@@ -633,4 +931,69 @@ class AIAgent:
|
|||||||
break
|
break
|
||||||
|
|
||||||
return result_prompt,result_token_len
|
return result_prompt,result_token_len
|
||||||
|
|
||||||
|
async def _do_llm_complection(self,prompt:AgentPrompt,inner_functions:dict=None,org_msg:AgentMsg=None) -> ComputeTaskResult:
|
||||||
|
from .compute_kernel import ComputeKernel
|
||||||
|
#logger.debug(f"Agent {self.agent_id} do llm token static system:{system_prompt_len},function:{function_token_len},history:{history_token_len},input:{input_len}, totoal prompt:{system_prompt_len + function_token_len + history_token_len} ")
|
||||||
|
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions)
|
||||||
|
if task_result.result_code != ComputeTaskResultCode.OK:
|
||||||
|
logger.error(f"llm compute error:{task_result.error_str}")
|
||||||
|
#error_resp = msg.create_error_resp(task_result.error_str)
|
||||||
|
return task_result
|
||||||
|
|
||||||
|
result_message = task_result.result.get("message")
|
||||||
|
inner_func_call_node = None
|
||||||
|
if result_message:
|
||||||
|
inner_func_call_node = result_message.get("function_call")
|
||||||
|
|
||||||
|
if inner_func_call_node:
|
||||||
|
call_prompt : AgentPrompt = copy.deepcopy(prompt)
|
||||||
|
task_result = await self._execute_func(inner_func_call_node,call_prompt,inner_functions,org_msg)
|
||||||
|
|
||||||
|
return task_result
|
||||||
|
|
||||||
|
def need_work(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def need_self_think(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def need_self_learn(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def wake_up(self) -> None:
|
||||||
|
if self.agent_task is None:
|
||||||
|
self.agent_task = asyncio.create_task(self._on_timer)
|
||||||
|
else:
|
||||||
|
logger.warning(f"agent {self.agent_id} is already wake up!")
|
||||||
|
|
||||||
|
# agent loop
|
||||||
|
async def _on_timer(self):
|
||||||
|
while True:
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
now = time.time()
|
||||||
|
if now - self.last_recover_time > 60:
|
||||||
|
self.agent_energy += (now - self.last_recover_time) / 60
|
||||||
|
self.last_recover_time = now
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
# complete todo
|
||||||
|
if self.need_work():
|
||||||
|
await self.do_my_work()
|
||||||
|
|
||||||
|
# review other's todo
|
||||||
|
# self.review_other_works()
|
||||||
|
|
||||||
|
# do work summary
|
||||||
|
if self.need_self_think():
|
||||||
|
await self.do_self_think()
|
||||||
|
|
||||||
|
#
|
||||||
|
if self.need_self_learn():
|
||||||
|
await self.do_self_learn()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import re
|
|||||||
import shlex
|
import shlex
|
||||||
from typing import List
|
from typing import List
|
||||||
from .ai_function import FunctionItem
|
from .ai_function import FunctionItem
|
||||||
|
from .compute_task import ComputeTaskResult
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -230,6 +231,7 @@ class LLMResult:
|
|||||||
self.send_msgs : List[AgentMsg] = []
|
self.send_msgs : List[AgentMsg] = []
|
||||||
self.calls : List[FunctionItem] = []
|
self.calls : List[FunctionItem] = []
|
||||||
self.post_calls : List[FunctionItem] = []
|
self.post_calls : List[FunctionItem] = []
|
||||||
|
self.extra_info = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_str(self,llm_result_str:str,valid_func:List[str]=None) -> 'LLMResult':
|
def from_str(self,llm_result_str:str,valid_func:List[str]=None) -> 'LLMResult':
|
||||||
@@ -310,7 +312,49 @@ class LLMResult:
|
|||||||
else:
|
else:
|
||||||
r.state = "reponsed"
|
r.state = "reponsed"
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
class AgentGoal:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.description = None
|
||||||
|
|
||||||
|
|
||||||
|
class AgentReport:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class AgentTodoResult:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.result_state = "error"
|
||||||
|
|
||||||
|
class AgentTodo:
|
||||||
|
def __init__(self):
|
||||||
|
self.todo_id = "todo#" + uuid.uuid4().hex
|
||||||
|
self.title = None
|
||||||
|
self.detail = None
|
||||||
|
self.todo_path = None # get parent todo,sub todo by path
|
||||||
|
|
||||||
|
self.depend_todo_ids = []
|
||||||
|
|
||||||
|
self.need_check = True
|
||||||
|
self.result : ComputeTaskResult = None
|
||||||
|
self.last_check_result = None
|
||||||
|
|
||||||
|
self.worker = None
|
||||||
|
self.checker = None
|
||||||
|
self.createor = None
|
||||||
|
|
||||||
|
self.retry_count = 0
|
||||||
|
|
||||||
|
def can_do(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def save(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class AgentWorkLog:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
class BaseAIAgent:
|
class BaseAIAgent:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
|
|||||||
@@ -151,3 +151,8 @@ class ContactManager:
|
|||||||
|
|
||||||
def list_family_members(self):
|
def list_family_members(self):
|
||||||
return self.family_members
|
return self.family_members
|
||||||
|
|
||||||
|
|
||||||
|
#async def process_msg(self,msg:AgentMsg):
|
||||||
|
# # forword message to contact
|
||||||
|
# pass
|
||||||
|
|||||||
@@ -141,3 +141,4 @@ class EmailTunnel(AgentTunnel):
|
|||||||
|
|
||||||
async def _process_message(self, msg: AgentMsg) -> None:
|
async def _process_message(self, msg: AgentMsg) -> None:
|
||||||
logger.warn(f"process message {msg.msg_id} from {msg.sender} to {msg.target}")
|
logger.warn(f"process message {msg.msg_id} from {msg.sender} to {msg.target}")
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import logging
|
||||||
import tempfile
|
import tempfile
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
@@ -11,12 +12,124 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from typing import Any,List
|
||||||
import aiofiles.os
|
import aiofiles.os
|
||||||
import chardet
|
import chardet
|
||||||
|
|
||||||
|
from .agent_base import AgentMsg,AgentTodo
|
||||||
from .environment import Environment,EnvironmentEvent
|
from .environment import Environment,EnvironmentEvent
|
||||||
from .ai_function import AIFunction,SimpleAIFunction
|
from .ai_function import AIFunction,SimpleAIFunction
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class WorkspaceEnvironment(Environment):
|
||||||
|
def __init__(self, env_id: str) -> None:
|
||||||
|
super().__init__(env_id)
|
||||||
|
self.root_path = f"./workspace/{env_id}"
|
||||||
|
|
||||||
|
def set_root_path(self,path:str):
|
||||||
|
self.root_path = path
|
||||||
|
|
||||||
|
def get_knowledge_base(self) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def exec_op_list(self,oplist:List)->None:
|
||||||
|
for op in oplist:
|
||||||
|
if op["op"] == "create":
|
||||||
|
self.create(op["path"],op["content"])
|
||||||
|
elif op["op"] == "write":
|
||||||
|
self.write(op["path"],op["content"],op["mode"])
|
||||||
|
elif op["op"] == "delete":
|
||||||
|
self.delete(op["path"])
|
||||||
|
elif op["op"] == "rename":
|
||||||
|
self.rename(op["path"],op["new_name"])
|
||||||
|
|
||||||
|
else:
|
||||||
|
logger.error(f"execute op list failed: unknown op:{op['op']}")
|
||||||
|
|
||||||
|
async def list(self,path:str,only_dir:bool=False) -> str:
|
||||||
|
directory_path = self.root_path + path
|
||||||
|
items = []
|
||||||
|
|
||||||
|
with await aiofiles.os.scandir(directory_path) as entries:
|
||||||
|
async for entry in entries:
|
||||||
|
is_dir = entry.is_dir()
|
||||||
|
if only_dir and not is_dir:
|
||||||
|
continue
|
||||||
|
item_type = "directory" if is_dir else "file"
|
||||||
|
items.append({"name": entry.name, "type": item_type})
|
||||||
|
|
||||||
|
return json.dumps(items)
|
||||||
|
|
||||||
|
async def read(self,path:str) -> str:
|
||||||
|
file_path = self.root_path + path
|
||||||
|
cur_encode = "utf-8"
|
||||||
|
async with aiofiles.open(file_path,'rb') as f:
|
||||||
|
cur_encode = chardet.detect(await f.read())['encoding']
|
||||||
|
|
||||||
|
async with aiofiles.open(file_path, mode='r', encoding=cur_encode) as f:
|
||||||
|
content = await f.read(2048)
|
||||||
|
return content
|
||||||
|
|
||||||
|
async def write(self,path:str,content:str,is_append:bool=False) -> str:
|
||||||
|
file_path = self.root_path + path
|
||||||
|
if is_append:
|
||||||
|
async with aiofiles.open(file_path, mode='a', encoding="utf-8") as f:
|
||||||
|
await f.write(content)
|
||||||
|
else:
|
||||||
|
async with aiofiles.open(file_path, mode='w', encoding="utf-8") as f:
|
||||||
|
await f.write(content)
|
||||||
|
return "success"
|
||||||
|
|
||||||
|
async def create(self,path:str,content:str=None) -> bool:
|
||||||
|
if content is None:
|
||||||
|
# create dir
|
||||||
|
dir_path = self.root_path + path
|
||||||
|
os.makedirs(dir_path)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
file_path = self.root_path + path
|
||||||
|
async with aiofiles.open(file_path, mode='w', encoding="utf-8") as f:
|
||||||
|
await f.write(content)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def delete(self,path:str) -> bool:
|
||||||
|
file_path = self.root_path + path
|
||||||
|
os.remove(file_path)
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def rename(self,path:str,new_name:str) -> bool:
|
||||||
|
file_path = self.root_path + path
|
||||||
|
new_path = self.root_path + new_name
|
||||||
|
os.rename(file_path,new_path)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
#easy use functions
|
||||||
|
async def update_state_by_msg(self, msg: AgentMsg,extra_info:dict) -> None:
|
||||||
|
# add todo
|
||||||
|
# update todo status
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def update_todos(self,oplist:list) -> None:
|
||||||
|
# add todo
|
||||||
|
# update todo status
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def get_todo_tree(self,path:str,deep:int = 4) -> str:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def get_todo_by_path(self,path:str) -> AgentTodo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def get_todo(self,id:str) -> AgentTodo:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def save_new_todo(self,path:str,todo:AgentTodo) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def update_todo(self,path:str,todo:AgentTodo)->None:
|
||||||
|
pass
|
||||||
|
|
||||||
class CodeInterpreter:
|
class CodeInterpreter:
|
||||||
def __init__(self, language, debug_mode):
|
def __init__(self, language, debug_mode):
|
||||||
@@ -138,7 +251,7 @@ class CodeInterpreter:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceEnvironment(Environment):
|
class ShellEnvironment(Environment):
|
||||||
def __init__(self, env_id: str) -> None:
|
def __init__(self, env_id: str) -> None:
|
||||||
super().__init__(env_id)
|
super().__init__(env_id)
|
||||||
|
|
||||||
@@ -176,7 +289,7 @@ class WorkspaceEnvironment(Environment):
|
|||||||
return interpreter.run(pycode)
|
return interpreter.run(pycode)
|
||||||
|
|
||||||
|
|
||||||
|
# merge to standard workspace env, **ABANDON this!**
|
||||||
class KnowledgeBaseFileSystemEnvironment(Environment):
|
class KnowledgeBaseFileSystemEnvironment(Environment):
|
||||||
def __init__(self, env_id: str) -> None:
|
def __init__(self, env_id: str) -> None:
|
||||||
super().__init__(env_id)
|
super().__init__(env_id)
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class AIOS_Shell:
|
|||||||
await cal_env.start()
|
await cal_env.start()
|
||||||
Environment.set_env_by_id("calender",cal_env)
|
Environment.set_env_by_id("calender",cal_env)
|
||||||
|
|
||||||
workspace_env = WorkspaceEnvironment("bash")
|
workspace_env = ShellEnvironment("bash")
|
||||||
Environment.set_env_by_id("bash",workspace_env)
|
Environment.set_env_by_id("bash",workspace_env)
|
||||||
|
|
||||||
paint_env = PaintEnvironment("paint")
|
paint_env = PaintEnvironment("paint")
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import asyncio
|
|||||||
|
|
||||||
directory = os.path.dirname(__file__)
|
directory = os.path.dirname(__file__)
|
||||||
sys.path.append(directory + '/../src')
|
sys.path.append(directory + '/../src')
|
||||||
from aios_kernel import WorkspaceEnvironment
|
from aios_kernel import ShellEnvironment
|
||||||
|
|
||||||
async def test_workflow():
|
async def test_workflow():
|
||||||
env = WorkspaceEnvironment("test")
|
env = ShellEnvironment("test")
|
||||||
|
|
||||||
test_code ="""
|
test_code ="""
|
||||||
import toml
|
import toml
|
||||||
|
|||||||
Reference in New Issue
Block a user