Fix story maker bug
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
instance_id = "fairy_tale_writer"
|
instance_id = "fairy_tale_writer"
|
||||||
fullname = "tracy wang"
|
fullname = "tracy wang"
|
||||||
llm_model_name = "gpt-3.5-turbo-16k-0613"
|
llm_model_name = "gpt-3.5-turbo-16k-0613"
|
||||||
|
enable_function = []
|
||||||
|
|
||||||
[[prompt]]
|
[[prompt]]
|
||||||
role = "system"
|
role = "system"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
instance_id = "agent:xxxxxxabcde"
|
instance_id = "agent:xxxxxxabcde"
|
||||||
fullname = "musk"
|
fullname = "musk"
|
||||||
|
enable_function = []
|
||||||
|
|
||||||
[[prompt]]
|
[[prompt]]
|
||||||
role = "system"
|
role = "system"
|
||||||
content = "你有丰富的管理技能,擅长将复杂工作拆解成简单的任务,让团队成员高效协作。"
|
content = "你有丰富的管理技能,擅长将复杂工作拆解成简单的任务,让团队成员高效协作。"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
instance_id = "studio_director"
|
instance_id = "studio_director"
|
||||||
fullname = "tracy wang"
|
fullname = "tracy wang"
|
||||||
llm_model_name = "gpt-3.5-turbo-16k-0613"
|
enable_function = ["text_to_speech"]
|
||||||
|
|
||||||
[[prompt]]
|
[[prompt]]
|
||||||
role = "system"
|
role = "system"
|
||||||
content = "你是一个演播导演,请将下面故事改编成朗读剧本,提取旁白和角色台词,每个角色需要有性别、年龄、以及每句台词的语气。并调用text_to_speech function生成音频数据。"
|
content = "你是一个故事播音员,请将下面故事改编成播音剧本,提取旁白和角色台词,以及每个角色需要有性别、年龄、以及每句台词的语气,最后生成音频文件。"
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ name = "story_maker"
|
|||||||
name = "manager"
|
name = "manager"
|
||||||
fullname = "总导演"
|
fullname = "总导演"
|
||||||
agent="manager"
|
agent="manager"
|
||||||
|
enable_function = []
|
||||||
|
|
||||||
[[roles.manager.prompt]]
|
[[roles.manager.prompt]]
|
||||||
role="system"
|
role="system"
|
||||||
content="""
|
content="""
|
||||||
你是一个语音故事制作总导演,与客户对接并向团队下达指令。你的团队分为下面几个成员:writer,studio_director。一个故事制作分成两个阶段:让writer写出故事,再交由studio_director演播故事。你的基本工作模式是:
|
你是一个语音故事制作总导演,与客户对接并向团队下达指令。你的团队分为下面几个成员:writer,studio_director。一个故事制作分成两个阶段:让writer写出故事,再交由studio_director演播故事生成音频文件。你的基本工作模式是:
|
||||||
1. 收到客户的明确的指令后,让writer写出故事
|
1. 收到客户的明确的指令后,让writer写出故事
|
||||||
2. 将writer写出的故事交给studio_director演播
|
2. 将writer写出的故事交给studio_director演播
|
||||||
3. 当你决定要和成员通信时,请使用下面形式输出需要通信的消息
|
3. 当你决定要和成员通信时,请使用下面形式输出需要通信的消息
|
||||||
@@ -25,6 +27,7 @@ content="""
|
|||||||
name = "writer"
|
name = "writer"
|
||||||
agent = "fairy_tale_writer"
|
agent = "fairy_tale_writer"
|
||||||
fullname = "作家"
|
fullname = "作家"
|
||||||
|
enable_function = []
|
||||||
[[roles.writer.prompt]]
|
[[roles.writer.prompt]]
|
||||||
role="system"
|
role="system"
|
||||||
content=""
|
content=""
|
||||||
@@ -32,6 +35,7 @@ content=""
|
|||||||
[roles.studio_director]
|
[roles.studio_director]
|
||||||
name = "studio_director"
|
name = "studio_director"
|
||||||
agent = "studio_director"
|
agent = "studio_director"
|
||||||
|
enable_function = ["text_to_speech"]
|
||||||
[[roles.studio_director.prompt]]
|
[[roles.studio_director.prompt]]
|
||||||
role="system"
|
role="system"
|
||||||
content=""
|
content=""
|
||||||
|
|||||||
+40
-38
@@ -26,7 +26,7 @@ class AgentPrompt:
|
|||||||
self.system_message = None
|
self.system_message = None
|
||||||
|
|
||||||
def as_str(self)->str:
|
def as_str(self)->str:
|
||||||
result_str = ""
|
result_str = ""
|
||||||
if self.system_message:
|
if self.system_message:
|
||||||
result_str += self.system_message.get("role") + ":" + self.system_message.get("content") + "\n"
|
result_str += self.system_message.get("role") + ":" + self.system_message.get("content") + "\n"
|
||||||
if self.messages:
|
if self.messages:
|
||||||
@@ -34,18 +34,18 @@ class AgentPrompt:
|
|||||||
result_str += msg.get("role") + ":" + msg.get("content") + "\n"
|
result_str += msg.get("role") + ":" + msg.get("content") + "\n"
|
||||||
|
|
||||||
return result_str
|
return result_str
|
||||||
|
|
||||||
def to_message_list(self):
|
def to_message_list(self):
|
||||||
result = []
|
result = []
|
||||||
if self.system_message:
|
if self.system_message:
|
||||||
result.append(self.system_message)
|
result.append(self.system_message)
|
||||||
result.extend(self.messages)
|
result.extend(self.messages)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def append(self,prompt):
|
def append(self,prompt):
|
||||||
if prompt is None:
|
if prompt is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if prompt.system_message is not None:
|
if prompt.system_message is not None:
|
||||||
if self.system_message is None:
|
if self.system_message is None:
|
||||||
self.system_message = prompt.system_message
|
self.system_message = prompt.system_message
|
||||||
@@ -99,9 +99,9 @@ class AIAgentTemplete:
|
|||||||
logger.error("load prompt from config failed!")
|
logger.error("load prompt from config failed!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class AIAgent:
|
class AIAgent:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
@@ -111,7 +111,7 @@ class AIAgent:
|
|||||||
self.agent_id:str = None
|
self.agent_id:str = None
|
||||||
self.template_id:str = None
|
self.template_id:str = None
|
||||||
self.fullname:str = None
|
self.fullname:str = None
|
||||||
self.powerby = None
|
self.powerby = None
|
||||||
self.enable = True
|
self.enable = True
|
||||||
self.enable_kb = False
|
self.enable_kb = False
|
||||||
self.enable_timestamp = False
|
self.enable_timestamp = False
|
||||||
@@ -124,7 +124,7 @@ class AIAgent:
|
|||||||
self.owner_env : Environment = None
|
self.owner_env : Environment = None
|
||||||
self.owenr_bus = None
|
self.owenr_bus = None
|
||||||
self.enable_function_list = []
|
self.enable_function_list = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create_from_templete(cls,templete:AIAgentTemplete, fullname:str):
|
def create_from_templete(cls,templete:AIAgentTemplete, fullname:str):
|
||||||
# Agent just inherit from templete on craete,if template changed,agent will not change
|
# Agent just inherit from templete on craete,if template changed,agent will not change
|
||||||
@@ -137,7 +137,7 @@ class AIAgent:
|
|||||||
result_agent.powerby = templete.author
|
result_agent.powerby = templete.author
|
||||||
result_agent.prompt = templete.prompt
|
result_agent.prompt = templete.prompt
|
||||||
return result_agent
|
return result_agent
|
||||||
|
|
||||||
def load_from_config(self,config:dict) -> bool:
|
def load_from_config(self,config:dict) -> bool:
|
||||||
if config.get("instance_id") is None:
|
if config.get("instance_id") is None:
|
||||||
logger.error("agent instance_id is None!")
|
logger.error("agent instance_id is None!")
|
||||||
@@ -188,7 +188,7 @@ class AIAgent:
|
|||||||
if llm_result_str == "ignore":
|
if llm_result_str == "ignore":
|
||||||
r.state = "ignore"
|
r.state = "ignore"
|
||||||
return r
|
return r
|
||||||
|
|
||||||
lines = llm_result_str.splitlines()
|
lines = llm_result_str.splitlines()
|
||||||
is_need_wait = False
|
is_need_wait = False
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@ class AIAgent:
|
|||||||
|
|
||||||
r.send_msgs.append(new_msg)
|
r.send_msgs.append(new_msg)
|
||||||
is_need_wait = True
|
is_need_wait = True
|
||||||
|
|
||||||
case "post_msg":# postmsg($target_id,$msg_content)
|
case "post_msg":# postmsg($target_id,$msg_content)
|
||||||
if len(func_args) != 1:
|
if len(func_args) != 1:
|
||||||
logger.error(f"parse postmsg failed! {func_call}")
|
logger.error(f"parse postmsg failed! {func_call}")
|
||||||
@@ -215,22 +215,22 @@ class AIAgent:
|
|||||||
msg_content = func_item.body
|
msg_content = func_item.body
|
||||||
new_msg.set(self.agent_id,target_id,msg_content)
|
new_msg.set(self.agent_id,target_id,msg_content)
|
||||||
r.post_msgs.append(new_msg)
|
r.post_msgs.append(new_msg)
|
||||||
|
|
||||||
case "call":# call($func_name,$args_str)
|
case "call":# call($func_name,$args_str)
|
||||||
r.calls.append(func_item)
|
r.calls.append(func_item)
|
||||||
is_need_wait = True
|
is_need_wait = True
|
||||||
return True
|
return True
|
||||||
case "post_call": # post_call($func_name,$args_str)
|
case "post_call": # post_call($func_name,$args_str)
|
||||||
r.post_calls.append(func_item)
|
r.post_calls.append(func_item)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
current_func : FunctionItem = None
|
current_func : FunctionItem = None
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if line.startswith("##/"):
|
if line.startswith("##/"):
|
||||||
if current_func:
|
if current_func:
|
||||||
if check_args(current_func) is False:
|
if check_args(current_func) is False:
|
||||||
r.resp += current_func.dumps()
|
r.resp += current_func.dumps()
|
||||||
|
|
||||||
func_name,func_args = AgentMsg.parse_function_call(line[3:])
|
func_name,func_args = AgentMsg.parse_function_call(line[3:])
|
||||||
current_func = FunctionItem(func_name,func_args)
|
current_func = FunctionItem(func_name,func_args)
|
||||||
else:
|
else:
|
||||||
@@ -238,11 +238,11 @@ class AIAgent:
|
|||||||
current_func.append_body(line + "\n")
|
current_func.append_body(line + "\n")
|
||||||
else:
|
else:
|
||||||
r.resp += line + "\n"
|
r.resp += line + "\n"
|
||||||
|
|
||||||
if current_func:
|
if current_func:
|
||||||
if check_args(current_func) is False:
|
if check_args(current_func) is False:
|
||||||
r.resp += current_func.dumps()
|
r.resp += current_func.dumps()
|
||||||
|
|
||||||
if len(r.send_msgs) > 0 or len(r.calls) > 0:
|
if len(r.send_msgs) > 0 or len(r.calls) > 0:
|
||||||
r.state = "waiting"
|
r.state = "waiting"
|
||||||
else:
|
else:
|
||||||
@@ -279,21 +279,22 @@ class AIAgent:
|
|||||||
def _get_inner_functions(self) -> dict:
|
def _get_inner_functions(self) -> dict:
|
||||||
if self.owner_env is None:
|
if self.owner_env is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
all_inner_function = self.owner_env.get_all_ai_functions()
|
all_inner_function = self.owner_env.get_all_ai_functions()
|
||||||
if all_inner_function is None:
|
if all_inner_function is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result_func = []
|
result_func = []
|
||||||
result_len = 0
|
result_len = 0
|
||||||
for inner_func in all_inner_function:
|
for inner_func in all_inner_function:
|
||||||
func_name = inner_func.get_name()
|
func_name = inner_func.get_name()
|
||||||
if self.enable_function_list:
|
if self.enable_function_list is not None:
|
||||||
if len(self.enable_function_list) > 0:
|
if len(self.enable_function_list) > 0:
|
||||||
if func_name not in self.enable_function_list:
|
if func_name not in self.enable_function_list:
|
||||||
logger.debug(f"ageint {self.agent_id} ignore inner func:{func_name}")
|
logger.debug(f"ageint {self.agent_id} ignore inner func:{func_name}")
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
|
continue
|
||||||
this_func = {}
|
this_func = {}
|
||||||
this_func["name"] = func_name
|
this_func["name"] = func_name
|
||||||
this_func["description"] = inner_func.get_description()
|
this_func["description"] = inner_func.get_description()
|
||||||
@@ -313,28 +314,29 @@ class AIAgent:
|
|||||||
func_node : AIFunction = self.owner_env.get_ai_function(func_name)
|
func_node : AIFunction = self.owner_env.get_ai_function(func_name)
|
||||||
if func_node is None:
|
if func_node is None:
|
||||||
return "execute failed,function not found"
|
return "execute failed,function not found"
|
||||||
|
|
||||||
ineternal_call_record = AgentMsg.create_internal_call_msg(func_name,arguments,org_msg.get_msg_id(),org_msg.target)
|
ineternal_call_record = AgentMsg.create_internal_call_msg(func_name,arguments,org_msg.get_msg_id(),org_msg.target)
|
||||||
try:
|
try:
|
||||||
result_str:str = await func_node.execute(**arguments)
|
result_str:str = await func_node.execute(**arguments)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
result_str = "call error:" + str(e)
|
result_str = "call error:" + str(e)
|
||||||
logger.error(f"llm execute inner func:{func_name} error:{e}")
|
logger.error(f"llm execute inner func:{func_name} error:{e}")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
logger.info("llm execute inner func result:" + result_str)
|
||||||
inner_functions,inner_function_len = self._get_inner_functions()
|
inner_functions,inner_function_len = self._get_inner_functions()
|
||||||
prompt.messages.append({"role":"function","content":result_str,"name":func_name})
|
prompt.messages.append({"role":"function","content":result_str,"name":func_name})
|
||||||
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions)
|
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,self.llm_model_name,self.max_token_size,inner_functions)
|
||||||
|
|
||||||
ineternal_call_record.result_str = task_result.result_str
|
ineternal_call_record.result_str = task_result.result_str
|
||||||
ineternal_call_record.done_time = time.time()
|
ineternal_call_record.done_time = time.time()
|
||||||
org_msg.inner_call_chain.append(ineternal_call_record)
|
org_msg.inner_call_chain.append(ineternal_call_record)
|
||||||
|
|
||||||
if stack_limit > 0:
|
if stack_limit > 0:
|
||||||
inner_func_call_node = task_result.result_message.get("function_call")
|
inner_func_call_node = task_result.result_message.get("function_call")
|
||||||
|
|
||||||
if inner_func_call_node:
|
if inner_func_call_node:
|
||||||
return await self._execute_func(inner_func_call_node,prompt,org_msg,stack_limit-1)
|
return await self._execute_func(inner_func_call_node,prompt,org_msg,stack_limit-1)
|
||||||
else:
|
else:
|
||||||
return task_result.result_str
|
return task_result.result_str
|
||||||
|
|
||||||
@@ -344,7 +346,7 @@ class AIAgent:
|
|||||||
def _format_msg_by_env_value(self,prompt:AgentPrompt):
|
def _format_msg_by_env_value(self,prompt:AgentPrompt):
|
||||||
if self.owner_env is None:
|
if self.owner_env is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
for msg in prompt.messages:
|
for msg in prompt.messages:
|
||||||
old_content = msg.get("content")
|
old_content = msg.get("content")
|
||||||
msg["content"] = old_content.format_map(self.owner_env)
|
msg["content"] = old_content.format_map(self.owner_env)
|
||||||
@@ -380,7 +382,7 @@ class AIAgent:
|
|||||||
|
|
||||||
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(chatsession,system_prompt_len + function_token_len,input_len)
|
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
|
prompt.append(history_prmpt) # chat context
|
||||||
|
|
||||||
@@ -397,7 +399,7 @@ class AIAgent:
|
|||||||
if inner_func_call_node:
|
if inner_func_call_node:
|
||||||
#TODO to save more token ,can i use msg_prompt?
|
#TODO to save more token ,can i use msg_prompt?
|
||||||
final_result = await self._execute_func(inner_func_call_node,prompt,msg)
|
final_result = await self._execute_func(inner_func_call_node,prompt,msg)
|
||||||
|
|
||||||
llm_result : LLMResult = self._get_llm_result_type(final_result)
|
llm_result : LLMResult = self._get_llm_result_type(final_result)
|
||||||
is_ignore = False
|
is_ignore = False
|
||||||
result_prompt_str = ""
|
result_prompt_str = ""
|
||||||
@@ -415,21 +417,21 @@ class AIAgent:
|
|||||||
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_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
|
||||||
|
|
||||||
def get_id(self) -> str:
|
def get_id(self) -> str:
|
||||||
return self.agent_id
|
return self.agent_id
|
||||||
|
|
||||||
def get_fullname(self) -> str:
|
def get_fullname(self) -> str:
|
||||||
return self.fullname
|
return self.fullname
|
||||||
|
|
||||||
@@ -438,14 +440,14 @@ class AIAgent:
|
|||||||
|
|
||||||
def get_llm_model_name(self) -> str:
|
def get_llm_model_name(self) -> str:
|
||||||
return self.llm_model_name
|
return self.llm_model_name
|
||||||
|
|
||||||
def get_max_token_size(self) -> int:
|
def get_max_token_size(self) -> int:
|
||||||
return self.max_token_size
|
return self.max_token_size
|
||||||
|
|
||||||
async def _get_prompt_from_session(self,chatsession:AIChatSession,system_token_len,input_token_len,is_groupchat=False) -> AgentPrompt:
|
async def _get_prompt_from_session(self,chatsession:AIChatSession,system_token_len,input_token_len,is_groupchat=False) -> 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
|
||||||
messages = chatsession.read_history() # read
|
messages = chatsession.read_history() # read
|
||||||
result_token_len = 0
|
result_token_len = 0
|
||||||
result_prompt = AgentPrompt()
|
result_prompt = AgentPrompt()
|
||||||
read_history_msg = 0
|
read_history_msg = 0
|
||||||
|
|||||||
+23
-21
@@ -19,14 +19,14 @@ class AIBusHandler:
|
|||||||
async def handle_message(self,msg:AgentMsg) -> Any:
|
async def handle_message(self,msg:AgentMsg) -> Any:
|
||||||
if self.handler is None:
|
if self.handler is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
resp_msg = await self.handler(msg)
|
resp_msg = await self.handler(msg)
|
||||||
if self.enable_defualt_proc:
|
if self.enable_defualt_proc:
|
||||||
if resp_msg is not None:
|
if resp_msg is not None:
|
||||||
await self.owner_bus.post_message(resp_msg,False)
|
await self.owner_bus.post_message(resp_msg,False)
|
||||||
|
|
||||||
return resp_msg
|
return resp_msg
|
||||||
|
|
||||||
class AIBus:
|
class AIBus:
|
||||||
_instance = None
|
_instance = None
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -48,16 +48,16 @@ class AIBus:
|
|||||||
if msg.rely_msg_id is not None:
|
if msg.rely_msg_id is not None:
|
||||||
handler.results[msg.rely_msg_id] = msg
|
handler.results[msg.rely_msg_id] = msg
|
||||||
return None
|
return None
|
||||||
|
|
||||||
handler.queue.put_nowait(msg)
|
handler.queue.put_nowait(msg)
|
||||||
self.start_process(target_id)
|
self.start_process(target_id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if use_unhandle:
|
if use_unhandle:
|
||||||
if self.unhandle_handler is not None:
|
if self.unhandle_handler is not None:
|
||||||
if await self.unhandle_handler(self,msg):
|
if await self.unhandle_handler(self,msg):
|
||||||
return await self.post_message(msg,False)
|
return await self.post_message(msg,False)
|
||||||
|
|
||||||
logger.warn(f"post message to {msg.target} failed!,target not found")
|
logger.warn(f"post message to {msg.target} failed!,target not found")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ class AIBus:
|
|||||||
if sender_handler is None:
|
if sender_handler is None:
|
||||||
logger.warn(f"sender {sender_id} not register on AI_BUS!")
|
logger.warn(f"sender {sender_id} not register on AI_BUS!")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
post_result = await self.post_message(msg)
|
post_result = await self.post_message(msg)
|
||||||
if post_result is False:
|
if post_result is False:
|
||||||
return None
|
return None
|
||||||
@@ -84,37 +84,39 @@ class AIBus:
|
|||||||
msg.status = AgentMsgStatus.RESPONSED
|
msg.status = AgentMsgStatus.RESPONSED
|
||||||
del sender_handler.results[msg.msg_id]
|
del sender_handler.results[msg.msg_id]
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
await asyncio.sleep(0.2)
|
await asyncio.sleep(0.2)
|
||||||
retry_times += 1
|
retry_times += 1
|
||||||
if retry_times > 5*120: # default timeout is 120 sec
|
if retry_times > 5*240: # default timeout is 240 sec
|
||||||
msg.status = AgentMsgStatus.ERROR
|
msg.status = AgentMsgStatus.ERROR
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def register_unhandle_message_handler(self,handler:Any) -> Queue:
|
def register_unhandle_message_handler(self,handler:Any) -> Queue:
|
||||||
self.unhandle_handler = handler
|
self.unhandle_handler = handler
|
||||||
|
|
||||||
# means sub
|
# means sub
|
||||||
def register_message_handler(self,handler_name:str,handler:Any) -> Queue:
|
def register_message_handler(self,handler_name:str,handler:Any) -> Queue:
|
||||||
handler_node = AIBusHandler(handler,self)
|
handler_node = AIBusHandler(handler,self)
|
||||||
self.handlers[handler_name] = handler_node
|
self.handlers[handler_name] = handler_node
|
||||||
return handler_node.queue
|
return handler_node.queue
|
||||||
|
|
||||||
async def process_queue(self, handler:AIBusHandler):
|
async def process_queue(self, handler:AIBusHandler):
|
||||||
while True:
|
while True:
|
||||||
# Wait for a message
|
# Wait for a message
|
||||||
message = await handler.queue.get()
|
message = await handler.queue.get()
|
||||||
|
|
||||||
#try:
|
try:
|
||||||
# Try to handle the message
|
# Try to handle the message
|
||||||
await handler.handle_message(message)
|
await handler.handle_message(message)
|
||||||
#except Exception as e:
|
except Exception as e:
|
||||||
# If an error occurs, put the message back into the queue
|
# If an error occurs, put the message back into the queue
|
||||||
# logger.error(f"handle message {message.msg_id} failed! {e}")
|
logger.error(f"handle message {message.msg_id} failed! {e}")
|
||||||
|
logger.exception(e)
|
||||||
|
raise e
|
||||||
#self.queues[name].put_nowait(message)
|
#self.queues[name].put_nowait(message)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def start_process(self,target_name):
|
def start_process(self,target_name):
|
||||||
@@ -122,12 +124,12 @@ class AIBus:
|
|||||||
if handler is None:
|
if handler is None:
|
||||||
logger.error(f"handler {target_name} not found!")
|
logger.error(f"handler {target_name} not found!")
|
||||||
return
|
return
|
||||||
|
|
||||||
if handler.handler is None:
|
if handler.handler is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
if handler.working_task is not None:
|
if handler.working_task is not None:
|
||||||
logger.warn(f"handler {target_name} is already working!")
|
logger.warn(f"handler {target_name} is already working!")
|
||||||
return
|
return
|
||||||
|
|
||||||
handler.working_task = asyncio.create_task(self.process_queue(handler))
|
handler.working_task = asyncio.create_task(self.process_queue(handler))
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ class ComputeKernel:
|
|||||||
if task_req.state == ComputeTaskState.ERROR:
|
if task_req.state == ComputeTaskState.ERROR:
|
||||||
break
|
break
|
||||||
|
|
||||||
if check_times >= 20:
|
if check_times >= 120:
|
||||||
task_req.state = ComputeTaskState.ERROR
|
task_req.state = ComputeTaskState.ERROR
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ class ComputeKernel:
|
|||||||
if task_req.state == ComputeTaskState.DONE:
|
if task_req.state == ComputeTaskState.DONE:
|
||||||
return task_req.result
|
return task_req.result
|
||||||
|
|
||||||
return "error!"
|
raise Exception("error!")
|
||||||
|
|
||||||
|
|
||||||
def text_embedding(self,input:str,model_name:Optional[str] = None):
|
def text_embedding(self,input:str,model_name:Optional[str] = None):
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
if cls._instance is None:
|
if cls._instance is None:
|
||||||
cls._instance = OpenAI_ComputeNode()
|
cls._instance = OpenAI_ComputeNode()
|
||||||
return cls._instance
|
return cls._instance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def declare_user_config(cls):
|
def declare_user_config(cls):
|
||||||
if os.getenv("OPENAI_API_KEY_") is None:
|
if os.getenv("OPENAI_API_KEY_") is None:
|
||||||
@@ -46,7 +46,7 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
if self.openai_api_key is None:
|
if self.openai_api_key is None:
|
||||||
logger.error("openai_api_key is None!")
|
logger.error("openai_api_key is None!")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
openai.api_key = self.openai_api_key
|
openai.api_key = self.openai_api_key
|
||||||
self.start()
|
self.start()
|
||||||
return True
|
return True
|
||||||
@@ -68,7 +68,7 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
|
|
||||||
resp = openai.Embedding.create(model=model_name,
|
resp = openai.Embedding.create(model=model_name,
|
||||||
input=input)
|
input=input)
|
||||||
|
|
||||||
# resp = {
|
# resp = {
|
||||||
# "object": "list",
|
# "object": "list",
|
||||||
# "data": [
|
# "data": [
|
||||||
@@ -86,7 +86,7 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
|
|
||||||
logger.info(f"openai response: {resp}")
|
logger.info(f"openai response: {resp}")
|
||||||
|
|
||||||
result = ComputeTaskResult()
|
result = ComputeTaskResult()
|
||||||
result.set_from_task(task)
|
result.set_from_task(task)
|
||||||
result.worker_id = self.node_id
|
result.worker_id = self.node_id
|
||||||
result.result = resp["data"][0]["embedding"]
|
result.result = resp["data"][0]["embedding"]
|
||||||
@@ -100,23 +100,23 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
if max_token_size is None:
|
if max_token_size is None:
|
||||||
max_token_size = 4000
|
max_token_size = 4000
|
||||||
|
|
||||||
result_token = int(max_token_size * 0.4)
|
result_token = max_token_size
|
||||||
|
|
||||||
logger.info(f"call openai {mode_name} prompts: {prompts}")
|
|
||||||
|
|
||||||
if llm_inner_functions is None:
|
if llm_inner_functions is None:
|
||||||
|
logger.info(f"call openai {mode_name} prompts: {prompts}")
|
||||||
resp = openai.ChatCompletion.create(model=mode_name,
|
resp = openai.ChatCompletion.create(model=mode_name,
|
||||||
messages=prompts,
|
messages=prompts,
|
||||||
max_tokens=result_token,
|
max_tokens=result_token,
|
||||||
temperature=0.7)
|
temperature=0.7)
|
||||||
else:
|
else:
|
||||||
|
logger.info(f"call openai {mode_name} prompts: {prompts} functions: {json.dumps(llm_inner_functions)}")
|
||||||
resp = openai.ChatCompletion.create(model=mode_name,
|
resp = openai.ChatCompletion.create(model=mode_name,
|
||||||
messages=prompts,
|
messages=prompts,
|
||||||
functions=llm_inner_functions,
|
functions=llm_inner_functions,
|
||||||
max_tokens=result_token,
|
max_tokens=result_token,
|
||||||
temperature=0.7) # TODO: add temperature to task params?
|
temperature=0.7) # TODO: add temperature to task params?
|
||||||
|
|
||||||
|
|
||||||
logger.info(f"openai response: {json.dumps(resp, indent=4)}")
|
logger.info(f"openai response: {json.dumps(resp, indent=4)}")
|
||||||
|
|
||||||
result = ComputeTaskResult()
|
result = ComputeTaskResult()
|
||||||
@@ -139,6 +139,7 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
result.result_message = resp["choices"][0]["message"]
|
result.result_message = resp["choices"][0]["message"]
|
||||||
if token_usage:
|
if token_usage:
|
||||||
result.result_refers["token_usage"] = token_usage
|
result.result_refers["token_usage"] = token_usage
|
||||||
|
logger.info(f"openai success response: {result.result_str}")
|
||||||
return result
|
return result
|
||||||
case _:
|
case _:
|
||||||
task.state = ComputeTaskState.ERROR
|
task.state = ComputeTaskState.ERROR
|
||||||
@@ -148,7 +149,7 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
if self.is_start is True:
|
if self.is_start is True:
|
||||||
return
|
return
|
||||||
self.is_start = True
|
self.is_start = True
|
||||||
|
|
||||||
async def _run_task_loop():
|
async def _run_task_loop():
|
||||||
while True:
|
while True:
|
||||||
task = await self.task_queue.get()
|
task = await self.task_queue.get()
|
||||||
@@ -171,13 +172,13 @@ class OpenAI_ComputeNode(ComputeNode):
|
|||||||
|
|
||||||
|
|
||||||
def is_support(self, task: ComputeTask) -> bool:
|
def is_support(self, task: ComputeTask) -> bool:
|
||||||
if task.task_type == ComputeTaskType.LLM_COMPLETION:
|
if task.task_type == ComputeTaskType.LLM_COMPLETION:
|
||||||
if not task.params["model_name"]:
|
if not task.params["model_name"]:
|
||||||
return True
|
return True
|
||||||
model_name : str = task.params["model_name"]
|
model_name : str = task.params["model_name"]
|
||||||
if model_name.startswith("gpt-"):
|
if model_name.startswith("gpt-"):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if task.task_type == ComputeTaskType.TEXT_EMBEDDING:
|
if task.task_type == ComputeTaskType.TEXT_EMBEDDING:
|
||||||
if task.params["model_name"] == "text-embedding-ada-002":
|
if task.params["model_name"] == "text-embedding-ada-002":
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ class TextToSpeechFunction(AIFunction):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if audio is not None:
|
if audio is not None:
|
||||||
path = os.path.join(os.curdir, "{}.mp3".format(random.sample('zyxwvutsrqponmlkjihgfedcba', 10)))
|
path = os.path.join(os.path.realpath(os.curdir), "{}.mp3".format(''.join(random.sample('zyxwvutsrqponmlkjihgfedcba', 10))))
|
||||||
audio.export(path, format="mp3")
|
audio.export(path, format="mp3")
|
||||||
return "complete.file path:{}".format(path)
|
return "已经生成音频文件, 文件路径为{}".format(path)
|
||||||
else:
|
else:
|
||||||
return "failed"
|
return "failed"
|
||||||
|
|
||||||
|
|||||||
+58
-56
@@ -2,7 +2,7 @@ import logging
|
|||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from asyncio import Queue
|
from asyncio import Queue
|
||||||
from typing import Optional,Tuple,List
|
from typing import Optional,Tuple,List
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
@@ -32,7 +32,7 @@ class MessageFilter:
|
|||||||
|
|
||||||
# TODO: add more filter
|
# TODO: add more filter
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def load_from_config(self,config:dict) -> bool:
|
def load_from_config(self,config:dict) -> bool:
|
||||||
self.filters = config
|
self.filters = config
|
||||||
return True
|
return True
|
||||||
@@ -68,8 +68,8 @@ class Workflow:
|
|||||||
def load_from_config(self,config:dict) -> bool:
|
def load_from_config(self,config:dict) -> bool:
|
||||||
if config is None:
|
if config is None:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if config.get("name") is None:
|
if config.get("name") is None:
|
||||||
logger.error("workflow config must have name")
|
logger.error("workflow config must have name")
|
||||||
return False
|
return False
|
||||||
self.workflow_name = config.get("name")
|
self.workflow_name = config.get("name")
|
||||||
@@ -84,7 +84,7 @@ class Workflow:
|
|||||||
if self.rule_prompt.load_from_config(config.get("prompt")) is False:
|
if self.rule_prompt.load_from_config(config.get("prompt")) is False:
|
||||||
logger.error("Workflow load prompt failed")
|
logger.error("Workflow load prompt failed")
|
||||||
return False
|
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
|
||||||
@@ -106,13 +106,13 @@ class Workflow:
|
|||||||
self.env_db_file = self.owner_workflow.env_db_file
|
self.env_db_file = self.owner_workflow.env_db_file
|
||||||
self.workflow_env = WorkflowEnvironment(self.workflow_id,self.env_db_file)
|
self.workflow_env = WorkflowEnvironment(self.workflow_id,self.env_db_file)
|
||||||
|
|
||||||
env_ndoe = config.get("enviroment")
|
env_ndoe = config.get("enviroment")
|
||||||
if env_ndoe is not None:
|
if env_ndoe is not None:
|
||||||
if self._load_env_from_config(env_ndoe) is False:
|
if self._load_env_from_config(env_ndoe) is False:
|
||||||
logger.error("Workflow load env failed")
|
logger.error("Workflow load env failed")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
connected_env_ndoe = config.get("connected_env")
|
connected_env_ndoe = config.get("connected_env")
|
||||||
if connected_env_ndoe is not None:
|
if connected_env_ndoe is not None:
|
||||||
for _node in connected_env_ndoe:
|
for _node in connected_env_ndoe:
|
||||||
env_id = _node.get("env_id")
|
env_id = _node.get("env_id")
|
||||||
@@ -124,13 +124,13 @@ class Workflow:
|
|||||||
logger.error(f"Workflow load connected_env failed, env {env_id} not found!")
|
logger.error(f"Workflow load connected_env failed, env {env_id} not found!")
|
||||||
return False
|
return False
|
||||||
self.connect_to_environment(remote_env,_node.get("event2msg"))
|
self.connect_to_environment(remote_env,_node.get("event2msg"))
|
||||||
|
|
||||||
sub_workflows = config.get("sub_workflows")
|
sub_workflows = config.get("sub_workflows")
|
||||||
if sub_workflows is not None:
|
if sub_workflows is not None:
|
||||||
if self._load_sub_workflows(sub_workflows) is False:
|
if self._load_sub_workflows(sub_workflows) is False:
|
||||||
logger.error("Workflow load sub workflows failed")
|
logger.error("Workflow load sub workflows failed")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _load_env_from_config(self,config:dict) -> bool:
|
def _load_env_from_config(self,config:dict) -> bool:
|
||||||
@@ -147,7 +147,7 @@ class Workflow:
|
|||||||
return False
|
return False
|
||||||
self.sub_workflows[k] = sub_workflow
|
self.sub_workflows[k] = sub_workflow
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _parse_msg_target(self,s:str)->list[str]:
|
def _parse_msg_target(self,s:str)->list[str]:
|
||||||
return s.split(".")
|
return s.split(".")
|
||||||
|
|
||||||
@@ -170,12 +170,12 @@ class Workflow:
|
|||||||
if current_workflow is None:
|
if current_workflow is None:
|
||||||
logger.error(f"sub workflow {inner_obj_id[i]} not found!")
|
logger.error(f"sub workflow {inner_obj_id[i]} not found!")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
logger.error(f"{msg.target} not found! forword message failed!")
|
logger.error(f"{msg.target} not found! forword message failed!")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get_workflow_id_from_target(self,target:str) -> str:
|
def get_workflow_id_from_target(self,target:str) -> str:
|
||||||
target_list = target.split(".")
|
target_list = target.split(".")
|
||||||
if len(target_list) == 0:
|
if len(target_list) == 0:
|
||||||
@@ -203,11 +203,11 @@ class Workflow:
|
|||||||
|
|
||||||
#1. workflow start process message
|
#1. workflow start process message
|
||||||
final_result = None
|
final_result = None
|
||||||
|
|
||||||
# this is workflow's group_chat session
|
# this is workflow's group_chat session
|
||||||
session_topic = msg.sender + "#" + msg.topic
|
session_topic = msg.sender + "#" + msg.topic
|
||||||
chatsesssion = AIChatSession.get_session(self.workflow_id,session_topic,self.db_file)
|
chatsesssion = AIChatSession.get_session(self.workflow_id,session_topic,self.db_file)
|
||||||
|
|
||||||
#2. find role by msg.mentions or workflow's selector logic
|
#2. find role by msg.mentions or workflow's selector logic
|
||||||
if msg.mentions is not None:
|
if msg.mentions is not None:
|
||||||
if not self.workflow_id in msg.mentions:
|
if not self.workflow_id in msg.mentions:
|
||||||
@@ -219,20 +219,20 @@ class Workflow:
|
|||||||
this_role = self.role_group.get(mention)
|
this_role = self.role_group.get(mention)
|
||||||
if this_role is not None:
|
if this_role is not None:
|
||||||
return await self.role_process_msg(msg,this_role,chatsesssion)
|
return await self.role_process_msg(msg,this_role,chatsesssion)
|
||||||
|
|
||||||
if self.input_filter is not None:
|
if self.input_filter is not None:
|
||||||
select_role_id = self.input_filter.select(msg)
|
select_role_id = self.input_filter.select(msg)
|
||||||
if select_role_id is not None:
|
if select_role_id is not None:
|
||||||
select_role = self.role_group.get(select_role_id)
|
select_role = self.role_group.get(select_role_id)
|
||||||
if select_role is None:
|
if select_role is None:
|
||||||
logger.error(f"input_filter return invalid role id:{select_role_id}, role not found in role_group")
|
logger.error(f"input_filter return invalid role id:{select_role_id}, role not found in role_group")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return await self.role_process_msg(msg,select_role,chatsesssion)
|
return await self.role_process_msg(msg,select_role,chatsesssion)
|
||||||
else:
|
else:
|
||||||
logger.error(f"input_filter return None for :{msg.body}")
|
logger.error(f"input_filter return None for :{msg.body}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
logger.error(f"{self.workflow_id}:no role can process this msg:{msg.body}")
|
logger.error(f"{self.workflow_id}:no role can process this msg:{msg.body}")
|
||||||
return final_result
|
return final_result
|
||||||
|
|
||||||
@@ -245,7 +245,7 @@ class Workflow:
|
|||||||
if llm_result_str == "ignore":
|
if llm_result_str == "ignore":
|
||||||
r.state = "ignore"
|
r.state = "ignore"
|
||||||
return r
|
return r
|
||||||
|
|
||||||
lines = llm_result_str.splitlines()
|
lines = llm_result_str.splitlines()
|
||||||
is_need_wait = False
|
is_need_wait = False
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ class Workflow:
|
|||||||
|
|
||||||
r.send_msgs.append(new_msg)
|
r.send_msgs.append(new_msg)
|
||||||
is_need_wait = True
|
is_need_wait = True
|
||||||
|
|
||||||
case "post_msg":# postmsg($target_id,$msg_content)
|
case "post_msg":# postmsg($target_id,$msg_content)
|
||||||
if len(func_args) != 1:
|
if len(func_args) != 1:
|
||||||
logger.error(f"parse postmsg failed! {func_call}")
|
logger.error(f"parse postmsg failed! {func_call}")
|
||||||
@@ -272,22 +272,22 @@ class Workflow:
|
|||||||
msg_content = func_item.body
|
msg_content = func_item.body
|
||||||
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)
|
||||||
|
|
||||||
case "call":# call($func_name,$args_str)
|
case "call":# call($func_name,$args_str)
|
||||||
r.calls.append(func_item)
|
r.calls.append(func_item)
|
||||||
is_need_wait = True
|
is_need_wait = True
|
||||||
return True
|
return True
|
||||||
case "post_call": # post_call($func_name,$args_str)
|
case "post_call": # post_call($func_name,$args_str)
|
||||||
r.post_calls.append(func_item)
|
r.post_calls.append(func_item)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
current_func : FunctionItem = None
|
current_func : FunctionItem = None
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if line.startswith("##/"):
|
if line.startswith("##/"):
|
||||||
if current_func:
|
if current_func:
|
||||||
if check_args(current_func) is False:
|
if check_args(current_func) is False:
|
||||||
r.resp += current_func.dumps()
|
r.resp += current_func.dumps()
|
||||||
|
|
||||||
func_name,func_args = AgentMsg.parse_function_call(line[3:])
|
func_name,func_args = AgentMsg.parse_function_call(line[3:])
|
||||||
current_func = FunctionItem(func_name,func_args)
|
current_func = FunctionItem(func_name,func_args)
|
||||||
else:
|
else:
|
||||||
@@ -295,7 +295,7 @@ class Workflow:
|
|||||||
current_func.append_body(line + "\n")
|
current_func.append_body(line + "\n")
|
||||||
else:
|
else:
|
||||||
r.resp += line + "\n"
|
r.resp += line + "\n"
|
||||||
|
|
||||||
if current_func:
|
if current_func:
|
||||||
if check_args(current_func) is False:
|
if check_args(current_func) is False:
|
||||||
r.resp += current_func.dumps()
|
r.resp += current_func.dumps()
|
||||||
@@ -309,14 +309,14 @@ class Workflow:
|
|||||||
|
|
||||||
async def role_post_msg(self,msg:AgentMsg,the_role:AIRole,workflow_chat_session:AIChatSession):
|
async def role_post_msg(self,msg:AgentMsg,the_role:AIRole,workflow_chat_session:AIChatSession):
|
||||||
msg.sender = the_role.get_role_id()
|
msg.sender = the_role.get_role_id()
|
||||||
|
|
||||||
target_role = self.role_group.get(msg.target)
|
target_role = self.role_group.get(msg.target)
|
||||||
if target_role:
|
if target_role:
|
||||||
msg.target = target_role.get_role_id()
|
msg.target = target_role.get_role_id()
|
||||||
logger.info(f"{msg.sender} post message {msg.msg_id} to inner role: {msg.target}")
|
logger.info(f"{msg.sender} post message {msg.msg_id} to inner role: {msg.target}")
|
||||||
asyncio.create_task(self.role_process_msg(msg,target_role,workflow_chat_session))
|
asyncio.create_task(self.role_process_msg(msg,target_role,workflow_chat_session))
|
||||||
return
|
return
|
||||||
|
|
||||||
target_workflow = self.sub_workflows.get(msg.target)
|
target_workflow = self.sub_workflows.get(msg.target)
|
||||||
if target_workflow:
|
if target_workflow:
|
||||||
msg.target = target_workflow.workflow_id
|
msg.target = target_workflow.workflow_id
|
||||||
@@ -341,7 +341,7 @@ class Workflow:
|
|||||||
# msg.target = target_workflow.workflow_id
|
# msg.target = target_workflow.workflow_id
|
||||||
logger.info(f"{msg.sender} send message {msg.msg_id} to sub workflow: {msg.target}")
|
logger.info(f"{msg.sender} send message {msg.msg_id} to sub workflow: {msg.target}")
|
||||||
return await target_workflow._process_msg(msg)
|
return await target_workflow._process_msg(msg)
|
||||||
|
|
||||||
logger.info(f"{msg.sender} post message {msg.msg_id} to AIBus: {msg.target}")
|
logger.info(f"{msg.sender} post message {msg.msg_id} to AIBus: {msg.target}")
|
||||||
return await self.get_bus().send_message(msg)
|
return await self.get_bus().send_message(msg)
|
||||||
|
|
||||||
@@ -352,8 +352,8 @@ class Workflow:
|
|||||||
func_node : AIFunction = self.workflow_env.get_ai_function(func_item.name)
|
func_node : AIFunction = self.workflow_env.get_ai_function(func_item.name)
|
||||||
if func_node is None:
|
if func_node is None:
|
||||||
return "execute failed,function not found"
|
return "execute failed,function not found"
|
||||||
|
|
||||||
result_str:str = await func_node.execute(**arguments)
|
result_str:str = await func_node.execute(**arguments)
|
||||||
return result_str
|
return result_str
|
||||||
|
|
||||||
async def role_post_call(self,func_item:FunctionItem,the_role:AIRole):
|
async def role_post_call(self,func_item:FunctionItem,the_role:AIRole):
|
||||||
@@ -363,7 +363,7 @@ class Workflow:
|
|||||||
def _format_msg_by_env_value(self,prompt:AgentPrompt):
|
def _format_msg_by_env_value(self,prompt:AgentPrompt):
|
||||||
if self.workflow_env is None:
|
if self.workflow_env is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
for msg in prompt.messages:
|
for msg in prompt.messages:
|
||||||
old_content = msg.get("content")
|
old_content = msg.get("content")
|
||||||
msg["content"] = old_content.format_map(self.workflow_env)
|
msg["content"] = old_content.format_map(self.workflow_env)
|
||||||
@@ -372,15 +372,17 @@ class Workflow:
|
|||||||
all_inner_function = self.workflow_env.get_all_ai_functions()
|
all_inner_function = self.workflow_env.get_all_ai_functions()
|
||||||
if all_inner_function is None:
|
if all_inner_function is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result_func = []
|
result_func = []
|
||||||
for inner_func in all_inner_function:
|
for inner_func in all_inner_function:
|
||||||
func_name = inner_func.get_name()
|
func_name = inner_func.get_name()
|
||||||
if the_role.enable_function_list:
|
if the_role.enable_function_list is not None:
|
||||||
if len(the_role.enable_function_list) > 0:
|
if len(the_role.enable_function_list) > 0:
|
||||||
if func_name not in the_role.enable_function_list:
|
if func_name not in the_role.enable_function_list:
|
||||||
logger.debug(f"ageint {self.agent_id} ignore inner func:{func_name}")
|
logger.debug(f"agent {self.agent_id} ignore inner func:{func_name}")
|
||||||
continue
|
continue
|
||||||
|
else:
|
||||||
|
continue
|
||||||
this_func = {}
|
this_func = {}
|
||||||
this_func["name"] = func_name
|
this_func["name"] = func_name
|
||||||
this_func["description"] = inner_func.get_description()
|
this_func["description"] = inner_func.get_description()
|
||||||
@@ -399,17 +401,17 @@ class Workflow:
|
|||||||
func_node : AIFunction = self.workflow_env.get_ai_function(func_name)
|
func_node : AIFunction = self.workflow_env.get_ai_function(func_name)
|
||||||
if func_node is None:
|
if func_node is None:
|
||||||
return "execute failed,function not found"
|
return "execute failed,function not found"
|
||||||
|
|
||||||
ineternal_call_record = AgentMsg.create_internal_call_msg(func_name,arguments,org_msg.get_msg_id(),org_msg.target)
|
ineternal_call_record = AgentMsg.create_internal_call_msg(func_name,arguments,org_msg.get_msg_id(),org_msg.target)
|
||||||
|
|
||||||
result_str:str = await func_node.execute(**arguments)
|
result_str:str = await func_node.execute(**arguments)
|
||||||
|
|
||||||
inner_functions = self._get_inner_functions()
|
inner_functions = self._get_inner_functions(the_role)
|
||||||
prompt.messages.append({"role":"function","content":result_str,"name":func_name})
|
prompt.messages.append({"role":"function","content":result_str,"name":func_name})
|
||||||
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,
|
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,
|
||||||
the_role.agent.llm_model_name,the_role.agent.max_token_size,
|
the_role.agent.llm_model_name,the_role.agent.max_token_size,
|
||||||
inner_functions)
|
inner_functions)
|
||||||
|
|
||||||
ineternal_call_record.result_str = task_result.result_str
|
ineternal_call_record.result_str = task_result.result_str
|
||||||
ineternal_call_record.done_time = time.time()
|
ineternal_call_record.done_time = time.time()
|
||||||
org_msg.inner_call_chain.append(ineternal_call_record)
|
org_msg.inner_call_chain.append(ineternal_call_record)
|
||||||
@@ -419,13 +421,13 @@ class Workflow:
|
|||||||
return await self._role_execute_func(the_role,inner_func_call_node,prompt,org_msg,stack_limit-1)
|
return await self._role_execute_func(the_role,inner_func_call_node,prompt,org_msg,stack_limit-1)
|
||||||
else:
|
else:
|
||||||
return task_result.result_str
|
return task_result.result_str
|
||||||
|
|
||||||
def _is_in_same_workflow(self,msg) -> bool:
|
def _is_in_same_workflow(self,msg) -> bool:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def role_process_msg(self,msg:AgentMsg,the_role:AIRole,workflow_chat_session:AIChatSession):
|
async def role_process_msg(self,msg:AgentMsg,the_role:AIRole,workflow_chat_session:AIChatSession):
|
||||||
msg.target = the_role.get_role_id()
|
msg.target = the_role.get_role_id()
|
||||||
|
|
||||||
|
|
||||||
prompt = AgentPrompt()
|
prompt = AgentPrompt()
|
||||||
prompt.append(the_role.agent.prompt)
|
prompt.append(the_role.agent.prompt)
|
||||||
@@ -433,7 +435,7 @@ class Workflow:
|
|||||||
prompt.append(the_role.get_prompt())
|
prompt.append(the_role.get_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()))
|
||||||
|
|
||||||
#support group chat, user content include sender name!
|
#support group chat, user content include sender name!
|
||||||
prompt.append(await self._get_prompt_from_session(workflow_chat_session))
|
prompt.append(await self._get_prompt_from_session(workflow_chat_session))
|
||||||
|
|
||||||
@@ -443,15 +445,15 @@ class Workflow:
|
|||||||
|
|
||||||
self._format_msg_by_env_value(prompt)
|
self._format_msg_by_env_value(prompt)
|
||||||
inner_functions = self._get_inner_functions(the_role)
|
inner_functions = self._get_inner_functions(the_role)
|
||||||
|
|
||||||
async def _do_process_msg():
|
async def _do_process_msg():
|
||||||
#TODO: send msg to agent might be better?
|
#TODO: send msg to agent might be better?
|
||||||
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,the_role.agent.get_llm_model_name(),the_role.agent.get_max_token_size(),inner_functions)
|
task_result:ComputeTaskResult = await ComputeKernel.get_instance().do_llm_completion(prompt,the_role.agent.get_llm_model_name(),the_role.agent.get_max_token_size(),inner_functions)
|
||||||
result_str = task_result.result_str
|
result_str = task_result.result_str
|
||||||
logger.info(f"{the_role.role_id} process {msg.sender}:{msg.body},llm str is :{result_str}")
|
logger.info(f"{the_role.role_id} process {msg.sender}:{msg.body},llm str is :{result_str}")
|
||||||
|
|
||||||
inner_func_call_node = task_result.result_message.get("function_call")
|
inner_func_call_node = task_result.result_message.get("function_call")
|
||||||
|
|
||||||
if inner_func_call_node:
|
if inner_func_call_node:
|
||||||
#TODO to save more token ,can i use msg_prompt?
|
#TODO to save more token ,can i use msg_prompt?
|
||||||
result_str = await self._role_execute_func(the_role,inner_func_call_node,prompt,msg)
|
result_str = await self._role_execute_func(the_role,inner_func_call_node,prompt,msg)
|
||||||
@@ -461,7 +463,7 @@ class Workflow:
|
|||||||
postmsg.prev_msg_id = msg.get_msg_id()
|
postmsg.prev_msg_id = msg.get_msg_id()
|
||||||
# might be craete a new msg.topic for this postmsg
|
# might be craete a new msg.topic for this postmsg
|
||||||
postmsg.topic = msg.topic
|
postmsg.topic = msg.topic
|
||||||
|
|
||||||
await self.role_post_msg(postmsg,the_role,workflow_chat_session)
|
await self.role_post_msg(postmsg,the_role,workflow_chat_session)
|
||||||
if not self._is_in_same_workflow(postmsg):
|
if not self._is_in_same_workflow(postmsg):
|
||||||
role_sesion = AIChatSession.get_session(the_role.get_role_id(),f"{postmsg.target}#{msg.topic}",self.db_file)
|
role_sesion = AIChatSession.get_session(the_role.get_role_id(),f"{postmsg.target}#{msg.topic}",self.db_file)
|
||||||
@@ -469,14 +471,14 @@ class Workflow:
|
|||||||
else:
|
else:
|
||||||
# message will be saved in role.process_message
|
# message will be saved in role.process_message
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
for post_call in result.post_calls:
|
for post_call in result.post_calls:
|
||||||
action_msg = msg.create_action_msg(post_call[0],post_call[1],the_role.get_role_id())
|
action_msg = msg.create_action_msg(post_call[0],post_call[1],the_role.get_role_id())
|
||||||
workflow_chat_session.append(action_msg)
|
workflow_chat_session.append(action_msg)
|
||||||
await self.role_post_call(post_call,the_role)
|
await self.role_post_call(post_call,the_role)
|
||||||
#save post_call
|
#save post_call
|
||||||
|
|
||||||
result_prompt_str = ""
|
result_prompt_str = ""
|
||||||
match result.state:
|
match result.state:
|
||||||
case "ignore":
|
case "ignore":
|
||||||
@@ -506,11 +508,11 @@ class Workflow:
|
|||||||
else:
|
else:
|
||||||
# message will be saved in role.process_message
|
# message will be saved in role.process_message
|
||||||
pass
|
pass
|
||||||
|
|
||||||
for call in result.calls:
|
for call in result.calls:
|
||||||
action_msg = msg.create_action_msg(call[0],call[1],call_result,the_role.get_role_id)
|
action_msg = msg.create_action_msg(call[0],call[1],call_result,the_role.get_role_id)
|
||||||
call_result = await self.role_call(call,the_role)
|
call_result = await self.role_call(call,the_role)
|
||||||
|
|
||||||
if call_result is not None:
|
if call_result is not None:
|
||||||
result_prompt_str += f"\ncall {call[0]} result is :{call_result}"
|
result_prompt_str += f"\ncall {call[0]} result is :{call_result}"
|
||||||
#save action
|
#save action
|
||||||
@@ -522,7 +524,7 @@ class Workflow:
|
|||||||
prompt.append(result_prompt)
|
prompt.append(result_prompt)
|
||||||
r = await _do_process_msg()
|
r = await _do_process_msg()
|
||||||
return r
|
return r
|
||||||
|
|
||||||
return await _do_process_msg()
|
return await _do_process_msg()
|
||||||
|
|
||||||
async def _get_prompt_from_session(self,chatsession:AIChatSession) -> AgentPrompt:
|
async def _get_prompt_from_session(self,chatsession:AIChatSession) -> AgentPrompt:
|
||||||
@@ -533,9 +535,9 @@ class Workflow:
|
|||||||
result_prompt.messages.append({"role":"assistant","content":msg.body})
|
result_prompt.messages.append({"role":"assistant","content":msg.body})
|
||||||
else:
|
else:
|
||||||
result_prompt.messages.append({"role":"user","content":f"{msg.body}"})
|
result_prompt.messages.append({"role":"user","content":f"{msg.body}"})
|
||||||
|
|
||||||
return result_prompt
|
return result_prompt
|
||||||
|
|
||||||
def _get_knowlege_prompt(self,role_name:str) -> AgentPrompt:
|
def _get_knowlege_prompt(self,role_name:str) -> AgentPrompt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -557,7 +559,7 @@ class Workflow:
|
|||||||
# if k == "role":
|
# if k == "role":
|
||||||
# continue
|
# continue
|
||||||
# else:
|
# else:
|
||||||
#
|
#
|
||||||
# def _env_msg_handler(env_event:EnvironmentEvent) -> None:
|
# def _env_msg_handler(env_event:EnvironmentEvent) -> None:
|
||||||
# the_msg:AgentMsg= self._env_event_to_msg(env_event)
|
# the_msg:AgentMsg= self._env_event_to_msg(env_event)
|
||||||
# self.role_post_msg
|
# self.role_post_msg
|
||||||
|
|||||||
Reference in New Issue
Block a user