Skip to content

Commit

Permalink
fix bugs.
Browse files Browse the repository at this point in the history
  • Loading branch information
waterflier committed Jan 6, 2024
1 parent b6395c2 commit 3663f14
Show file tree
Hide file tree
Showing 17 changed files with 161 additions and 123 deletions.
1 change: 1 addition & 0 deletions doc/promps/Review Task.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,4 @@ The result of my planned execution must be directly parsed by `python json.loads


## RetryTask 对未成功的任务进行再次处理
注意RetryTask和RetryTodo的区别
2 changes: 2 additions & 0 deletions doc/promps/self-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
self learn通常是根据既定目标,对KB进行学习,或则主动扩展KB的行为。
self learn的结果是可以被组织(workflow)共享
11 changes: 5 additions & 6 deletions rootfs/agents/Jarvis/agent.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ owner_prompt = "I am your master{name}"
contact_prompt = "I am your master's friend{name}"

role_desc = """
Your name is Jarvis, the super personal assistant to the master.
Your name is Jarvis, the super personal assistant to the master, The focus of work is the support of the schedule management and schedule affairs.
"""

[behavior.on_message]
type="LLMAgentMessageProcess"

process_description="""
1. Based on your role, combined with existing information, make a brief and efficient reply.
2. Be mindful of the identity of the person you are chatting with and provide services accordingly based on their status.
3. Understand the intention of the dialogue, while using the necessary reply, use the appropriate, supported ACTION.
4. If you feel that there is a potential Task in the dialogue, you can create these tasks through appropriate ACTION. Be careful to query whether there are the same task before creating.Using the query interface is a high -cost behavior.
4. If you feel that there is a potential Task in the dialogue, you can create these tasks through appropriate ACTION. Be careful to query whether there are the same task before creating. Using the query interface is a high-cost behavior.
5. You are proficient in the languages of various countries and try to communicate with each other's mother tongue.
"""

Expand All @@ -44,6 +45,8 @@ known_info_tips = """

tools_tips = """
"""
llm_context.actions.enable = ["agent.workspace.create_task"]
llm_context.functions.enable = ["agent.workspace.list_task"]

[behavior.review_task]
type="ReviewTaskProcess"
Expand Down Expand Up @@ -82,11 +85,7 @@ known_info_tips = """
tools_tips = """
"""
[llm_context.actions]
enable = ["agent.memory.append_chatlog"]

[llm_context.functions]
enable = []

[behavior.do] # do TODO
type="DoTodoProcess"
Expand Down
1 change: 1 addition & 0 deletions src/aios/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .agent.role import AIRole,AIRoleGroup
from .agent.workflow import Workflow
from .agent.agent_memory import AgentMemory
from .agent.workspace import AgentWorkspace
from .agent.llm_context import LLMProcessContext,GlobaToolsLibrary,SimpleLLMContext

from .frame.compute_kernel import ComputeKernel,ComputeTask,ComputeTaskResult,ComputeTaskState,ComputeTaskType
Expand Down
83 changes: 43 additions & 40 deletions src/aios/agent/llm_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ def __init__(self) -> None:
def function2action(ai_func:AIFunction) -> AIAction:
async def exec_func(params:Dict) -> str:
return await ai_func.execute(params)
return SimpleAIAction(ai_func.get_name(),ai_func.get_detail_description(),exec_func)
return SimpleAIAction(ai_func.get_id(),ai_func.get_detail_description(),exec_func)


@staticmethod
def aifunction_to_inner_function(self,all_inner_function:List[AIFunction]) -> List[Dict]:
def aifunctions_to_inner_functions(all_inner_function:List[AIFunction]) -> List[Dict]:
result_func = []
result_len = 0
for inner_func in all_inner_function:
Expand All @@ -34,6 +34,7 @@ def aifunction_to_inner_function(self,all_inner_function:List[AIFunction]) -> Li
result_func.append(this_func)
return result_func


@abstractmethod
def get_ai_function(self,func_name:str) -> AIFunction:
pass
Expand Down Expand Up @@ -63,13 +64,14 @@ def __getitem__(self, key):
def get_value(self,key:str) -> Optional[str]:
pass

def list_actions(self,path:str) -> List[AIAction]:
return "No more actions!"
#def list_actions(self,path:str) -> List[AIAction]:
# return "No more actions!"

def list_functions(self,path:str) -> List[AIFunction]:
return "No more tool functions!"
#def list_functions(self,path:str) -> List[AIFunction]:
# return "No more tool functions!"

class GlobaToolsLibrary:
_instance = None
@classmethod
def get_instance(cls) -> 'GlobaToolsLibrary':
if cls._instance is None:
Expand All @@ -89,10 +91,10 @@ def get_preset_context(self,preset_id:str):
return self.all_preset_context.get(preset_id)

def register_tool_function(self,function:AIFunction) -> None:
if self.all_tool_functions.get(function.get_name()):
logger.warning(f"Tool function {function.get_name()} already exists! will be replaced!")
if self.all_tool_functions.get(function.get_id()):
logger.warning(f"Tool function {function.get_id()} already exists! will be replaced!")

self.all_tool_functions[function.get_name()] = function
self.all_tool_functions[function.get_id()] = function

def get_tool_function(self,function_name:str) -> AIFunction:
return self.all_tool_functions.get(function_name)
Expand Down Expand Up @@ -139,18 +141,19 @@ def load_action_set_from_config(self,preset,config:Dict[str,str]) -> bool:
return None

disable_actions = config.get("disable")
for disable_action in disable_actions:
if result.get(disable_action):
result.pop(disable_action)
else:
func_set = GlobaToolsLibrary.get_instance().get_function_set(action_id)
if func_set:
for _func_id in func_set:
if result.get(_func_id):
result.pop(_func_id)
if disable_actions:
for disable_action in disable_actions:
if result.get(disable_action):
result.pop(disable_action)
else:
logger.error(f"load_action_set_from_config failed! disable action id {action_id} not found!")
return None
func_set = GlobaToolsLibrary.get_instance().get_function_set(action_id)
if func_set:
for _func_id in func_set:
if result.get(_func_id):
result.pop(_func_id)
else:
logger.error(f"load_action_set_from_config failed! disable action id {action_id} not found!")
return None

return result

Expand Down Expand Up @@ -182,18 +185,19 @@ def load_function_set_from_config(self,preset,config:Dict) -> Dict[str,AIFunctio


disable_functions = config.get("disable")
for disable_function in disable_functions:
if result.get(disable_function):
result.pop(disable_function)
else:
func_set = GlobaToolsLibrary.get_instance().get_function_set(func_id)
if func_set:
for func_id in func_set:
if result.get(func_id):
result.pop(func_id)
if disable_functions:
for disable_function in disable_functions:
if result.get(disable_function):
result.pop(disable_function)
else:
logger.error(f"load_function_set_from_config failed! disable function id {disable_function} not found!")
return None
func_set = GlobaToolsLibrary.get_instance().get_function_set(func_id)
if func_set:
for func_id in func_set:
if result.get(func_id):
result.pop(func_id)
else:
logger.error(f"load_function_set_from_config failed! disable function id {disable_function} not found!")
return None

return result

Expand Down Expand Up @@ -268,15 +272,14 @@ def set_value_callback(self,key:str,callback:Callable[[],str]) -> None:
def set_value(self,key:str,value:str):
self.values[key] = value

#def get_ai_function(self,func_name:str) -> AIFunction:
# func = self.functions.get(func_name)
# if func is not None:
# return func

# for set_name in self.func_sets.keys():
# func = self.func_sets[set_name].get(func_name)
# if func is not None:
# return func
def get_ai_function(self,func_name:str) -> AIFunction:
for func in self.functions.values():
if func.get_name() == func_name:
return func
#for set_name in self.func_sets.keys():
# func = self.func_sets[set_name].get(func_name)
# if func is not None:
# return func

def get_function_set(self,set_name:str = None) -> List[AIFunction]:
if set_name is None:
Expand Down
37 changes: 32 additions & 5 deletions src/aios/agent/llm_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ async def initial(self,params:Dict = None) -> bool:
def _format_content_by_env_value(self,content:str,env)->str:
return content.format_map(env)

def prepare_inner_function_context_for_exec(self,inner_func_name:str,parameters:Dict):
return

async def _execute_inner_func(self,inner_func_call_node:Dict,prompt: LLMPrompt,stack_limit = 1) -> ComputeTaskResult:
arguments = None
stack_limit = stack_limit - 1
Expand All @@ -92,7 +95,8 @@ async def _execute_inner_func(self,inner_func_call_node:Dict,prompt: LLMPrompt,s
if func_node is None:
result_str:str = f"execute {func_name} error,function not found"
else:
result_str:str = await func_node.execute(**arguments)
self.prepare_inner_function_context_for_exec(func_name,arguments)
result_str:str = await func_node.execute(arguments)
except Exception as e:
result_str = f"execute {func_name} error:{str(e)}"
logger.error(f"LLMProcess execute inner func:{func_name} error:\n\t{e}")
Expand Down Expand Up @@ -440,9 +444,8 @@ async def prepare_prompt(self,input:Dict) -> LLMPrompt:
## 可以使用的tools(inner function)的解释,注意不定义该tips,则不会导入任何workspace中的tools
if self.tools_tips:
system_prompt_dict["tools_tips"] = self.tools_tips
#prompt.append_system_message(self.tools_tips)
#self.llm_context.

prompt.inner_functions =LLMProcessContext.aifunctions_to_inner_functions(self.llm_context.get_all_ai_functions())
if self.workspace:
#TODO eanble workspace functions?
logger.info(f"workspace is not none,enable workspace functions")
Expand All @@ -458,6 +461,8 @@ async def prepare_prompt(self,input:Dict) -> LLMPrompt:

return prompt

def prepare_inner_function_context_for_exec(self,inner_func_name:str,parameters:Dict):
parameters["_workspace"] = self.workspace

async def get_inner_function_for_exec(self,func_name:str) -> AIFunction:
return self.llm_context.get_ai_function(func_name)
Expand Down Expand Up @@ -518,9 +523,30 @@ async def initial(self,params:Dict = None) -> bool:


return True
async def load_from_config(self, config: dict):

async def load_from_config(self, config: dict,is_load_default=True) -> Coroutine[Any, Any, bool]:


if await super().load_from_config(config) is False:
return False

self.role_description = config.get("role_desc")
if self.role_description is None:
logger.error(f"role_description not found in config")
return False

if config.get("process_description"):
self.process_description = config.get("process_description")

if config.get("reply_format"):
self.reply_format = config.get("reply_format")

if config.get("context"):
self.context = config.get("context")

self.llm_context = SimpleLLMContext()
if config.get("llm_context"):
self.llm_context.load_from_config(config.get("llm_context"))

async def prepare_prompt(self,input:Dict) -> LLMPrompt:
agent_task = input.get("task")
Expand All @@ -529,7 +555,8 @@ async def prepare_prompt(self,input:Dict) -> LLMPrompt:
system_prompt_dict["role_description"] = self.role_description
system_prompt_dict["process_rule"] = self.process_description
system_prompt_dict["reply_format"] = self.reply_format

prompt.append_system_message(json.dumps(system_prompt_dict))
prompt.append_user_message(json.dumps(agent_task.to_dict()))
return prompt


Expand Down
2 changes: 1 addition & 1 deletion src/aios/agent/workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ def _get_inner_functions(self,the_role:AIRole) -> dict:

result_func = []
for inner_func in all_inner_function:
func_name = inner_func.get_name()
func_name = inner_func.get_id()
if the_role.enable_function_list is not None:
if len(the_role.enable_function_list) > 0:
if func_name not in the_role.enable_function_list:
Expand Down
Loading

0 comments on commit 3663f14

Please sign in to comment.