1) FixBug

2) Add Documents abount TASK/TODO Refactor
This commit is contained in:
Liu Zhicong
2024-01-06 13:08:41 -08:00
parent 3663f140fc
commit c975ba2053
22 changed files with 398 additions and 109 deletions
+4 -4
View File
@@ -115,22 +115,22 @@ class ChatSessionDB:
action_result = None
mentions = None
if msg.mentions:
mentions = json.dumps(msg.mentions)
mentions = json.dumps(msg.mentions,ensure_ascii=False)
match msg.msg_type:
case AgentMsgType.TYPE_MSG:
pass
case AgentMsgType.TYPE_ACTION:# THIS Action is not AIAction
action_name = msg.func_name
action_params = json.dumps(msg.args)
action_params = json.dumps(msg.args,ensure_ascii=False)
action_result = msg.result_str
case AgentMsgType.TYPE_INTERNAL_CALL:
action_name = msg.func_name
action_params = json.dumps(msg.args)
action_params = json.dumps(msg.args,ensure_ascii=False)
action_result = msg.result_str
case AgentMsgType.TYPE_EVENT:
action_name = msg.event_name
action_params = json.dumps(msg.event_args)
action_params = json.dumps(msg.event_args,ensure_ascii=False)
if tags is None:
tags = []
+41 -47
View File
@@ -4,7 +4,7 @@ import json
import logging
from typing import Optional,Set,List,Dict,Callable
from ..proto.ai_function import AIFunction,AIAction,SimpleAIAction
from ..proto.ai_function import AIFunction,AIAction, AIFunction2Action,SimpleAIAction
logger = logging.getLogger(__name__)
@@ -15,10 +15,7 @@ class LLMProcessContext:
@staticmethod
def function2action(ai_func:AIFunction) -> AIAction:
async def exec_func(params:Dict) -> str:
return await ai_func.execute(params)
return SimpleAIAction(ai_func.get_id(),ai_func.get_detail_description(),exec_func)
return AIFunction2Action(ai_func)
@staticmethod
def aifunctions_to_inner_functions(all_inner_function:List[AIFunction]) -> List[Dict]:
@@ -30,7 +27,7 @@ class LLMProcessContext:
this_func["name"] = func_name
this_func["description"] = inner_func.get_description()
this_func["parameters"] = inner_func.get_openai_parameters()
result_len += len(json.dumps(this_func)) / 4
result_len += len(json.dumps(this_func,ensure_ascii=False)) / 4
result_func.append(this_func)
return result_func
@@ -117,7 +114,7 @@ class SimpleLLMContext(LLMProcessContext):
self.actions: Dict[str,AIAction] = {}
self.action_sets : Dict[str,Dict[str,AIAction]] = {}
def load_action_set_from_config(self,preset,config:Dict[str,str]) -> bool:
def load_action_set_from_config(self,preset,config:Dict[str,str]) -> Dict:
if preset is None:
result = {}
else:
@@ -217,43 +214,42 @@ class SimpleLLMContext(LLMProcessContext):
self.func_sets = self.parent.func_sets
action_def:Dict= config.get("actions")
if action_def is None:
logger.error(f"load_from_config failed! actions not found!")
return False
self.actions = self.load_action_set_from_config(self.actions,action_def)
if self.actions is None:
logger.error(f"load_from_config failed! load_action_set_from_config failed!")
return False
for set_name in action_def.keys():
if set_name == "enable":
continue
if set_name == "disable":
continue
sub_set = config.get(set_name)
self.action_sets[set_name] = self.load_action_set_from_config(None,sub_set)
if self.action_sets[set_name] is None:
if action_def:
self.actions = self.load_action_set_from_config(self.actions,action_def)
if self.actions is None:
logger.error(f"load_from_config failed! load_action_set_from_config failed!")
return False
function_def:Dict = config.get("functions")
self.functions = self.load_function_set_from_config(self.functions,function_def)
if self.functions is None:
logger.error(f"load_from_config failed! load_function_set_from_config failed!")
return False
for set_name in function_def.keys():
if set_name == "enable":
continue
if set_name == "disable":
continue
for set_name in action_def.keys():
if set_name == "enable":
continue
if set_name == "disable":
continue
sub_set = config.get(set_name)
self.func_sets[set_name] = self.load_function_set_from_config(None,sub_set)
if self.func_sets[set_name] is None:
sub_set = config.get(set_name)
self.action_sets[set_name] = self.load_action_set_from_config(None,sub_set)
if self.action_sets[set_name] is None:
logger.error(f"load_from_config failed! load_action_set_from_config failed!")
return False
function_def:Dict = config.get("functions")
if function_def:
self.functions = self.load_function_set_from_config(self.functions,function_def)
if self.functions is None:
logger.error(f"load_from_config failed! load_function_set_from_config failed!")
return False
for set_name in function_def.keys():
if set_name == "enable":
continue
if set_name == "disable":
continue
sub_set = config.get(set_name)
self.func_sets[set_name] = self.load_function_set_from_config(None,sub_set)
if self.func_sets[set_name] is None:
logger.error(f"load_from_config failed! load_function_set_from_config failed!")
return False
#values_def = config.get("values")
#if values_def:
@@ -280,6 +276,7 @@ class SimpleLLMContext(LLMProcessContext):
# func = self.func_sets[set_name].get(func_name)
# if func is not None:
# return func
return None
def get_function_set(self,set_name:str = None) -> List[AIFunction]:
if set_name is None:
@@ -291,15 +288,12 @@ class SimpleLLMContext(LLMProcessContext):
return None
# def get_ai_action(self,op_name:str) -> AIOperation:
# op = self.actions.get(op_name)
# if op is not None:
# return op
# for set_name in self.action_sets.keys():
# op = self.action_sets[set_name].get(op_name)
# if op is not None:
# return op
# return None
def get_ai_action(self,op_name:str) -> AIAction:
for action in self.actions.values():
if action.get_name() == op_name:
return action
return None
def get_action_set(self,set_name:str = None) -> List[AIFunction]:
if set_name is None:
+6 -6
View File
@@ -46,9 +46,9 @@ class BaseLLMProcess(ABC):
async def prepare_prompt(self,input:Dict) -> LLMPrompt:
pass
@abstractmethod
async def get_inner_function_for_exec(self,func_name:str) -> AIFunction:
return GlobaToolsLibrary.get_instance().get_tool_function(func_name)
pass
@abstractmethod
async def post_llm_process(self,actions:List[ActionNode],input:Dict,llm_result:LLMResult) -> bool:
@@ -89,7 +89,7 @@ class BaseLLMProcess(ABC):
try:
func_name = inner_func_call_node.get("name")
arguments = json.loads(inner_func_call_node.get("arguments"))
logger.info(f"LLMProcess execute inner func:{func_name} :\n\t {json.dumps(arguments)}")
logger.info(f"LLMProcess execute inner func:{func_name} :\n\t {json.dumps(arguments,ensure_ascii=False)}")
func_node : AIFunction = await self.get_inner_function_for_exec(func_name)
if func_node is None:
@@ -455,7 +455,7 @@ class LLMAgentMessageProcess(BaseLLMProcess):
logger.info(f"enable kb")
prompt.append_system_message(json.dumps(system_prompt_dict))
prompt.append_system_message(json.dumps(system_prompt_dict,ensure_ascii=False))
## 扩展已知信息 (这可能是一个LLM过程)
prompt.append_system_message(await self.get_extend_known_info(msg,prompt))
@@ -555,8 +555,8 @@ class ReviewTaskProcess(BaseLLMProcess):
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()))
prompt.append_system_message(json.dumps(system_prompt_dict,ensure_ascii=False))
prompt.append_user_message(json.dumps(agent_task.to_dict(),ensure_ascii=False))
return prompt
+12 -10
View File
@@ -76,7 +76,7 @@ class LocalAgentTaskManger(AgentTaskManager):
self._save_obj_path(task.task_id,task_path)
logger.info("create_task at %s",detail_path)
async with aiofiles.open(detail_path, mode='w', encoding="utf-8") as f:
await f.write(json.dumps(task.to_dict()))
await f.write(json.dumps(task.to_dict(),ensure_ascii=False))
return "create task ok"
except Exception as e:
logger.error("create_task failed:%s",e)
@@ -97,7 +97,7 @@ class LocalAgentTaskManger(AgentTaskManager):
todo_path = f"{self.root_path}/{owner_task_path}/#{step_order} {todo.title}.todo"
self._save_obj_path(todo.todo_id,todo_path)
async with aiofiles.open(todo_path, mode='w', encoding="utf-8") as f:
await f.write(json.dumps(todo.to_dict()))
await f.write(json.dumps(todo.to_dict(),ensure_ascii=False))
logger.info("create_todos at %s OK!",todo_path)
step_order += 1
except Exception as e:
@@ -121,7 +121,7 @@ class LocalAgentTaskManger(AgentTaskManager):
logs = []
logs.append(log.to_dict())
json_obj["logs"] = logs
await f.write(json.dumps(json_obj))
await f.write(json.dumps(json_obj,ensure_ascii=False))
async def get_worklog(self,obj_id:str)->List[AgentWorkLog]:
@@ -263,7 +263,7 @@ class LocalAgentTaskManger(AgentTaskManager):
detail_path = f"{self.root_path}/{task.task_path}/detail"
try:
async with aiofiles.open(detail_path, mode='w', encoding="utf-8") as f:
await f.write(json.dumps(task.to_dict()))
await f.write(json.dumps(task.to_dict(),ensure_ascii=False))
except Exception as e:
logger.error("update_task failed:%s",e)
return str(e)
@@ -277,7 +277,7 @@ class LocalAgentTaskManger(AgentTaskManager):
try:
async with aiofiles.open(todo_path, mode='w', encoding="utf-8") as f:
await f.write(json.dumps(todo.to_dict()))
await f.write(json.dumps(todo.to_dict(),ensure_ascii=False))
except Exception as e:
logger.error("update_todo failed:%s",e)
return str(e)
@@ -311,18 +311,20 @@ class LocalAgentTaskManger(AgentTaskManager):
class AgentWorkspace:
def __init__(self,owner_agent_id:str) -> None:
self.agent_id : str = owner_agent_id
self.task_mgr : AgentTaskManager = LocalAgentTaskManger(owner_agent_id)
def __init__(self,owner_id:str) -> None:
self.owner_id : str = owner_id
self.task_mgr : AgentTaskManager = LocalAgentTaskManger(owner_id)
@staticmethod
def register_ai_functions():
async def create_task(params):
_workspace = params.get("_workspace")
_agent_id = params.get("_agentid")
if _workspace is None:
return "_workspace not found"
if params.get("creator") is None:
params["creator"] = _agent_id
taskObj = AgentTask.create_by_dict(params)
parent_id = params.get("parent")
return await _workspace.task_mgr.create_task(taskObj,parent_id)
@@ -371,7 +373,7 @@ class AgentWorkspace:
return "_workspace not found"
all_task = await _workspace.task_mgr.list_task(None)
if all_task:
return json.dumps([task.to_dict() for task in all_task])
return json.dumps([task.to_dict() for task in all_task],ensure_ascii=False)
else :
return "no task"
list_task_ai_function = SimpleAIFunction("agent.workspace.list_task",
@@ -44,7 +44,7 @@ class DuckDuckGoTextSearchFunction(AIFunction):
max_results=self.max_results
)]
return json.dumps(results)
return json.dumps(results,,ensure_ascii=False)
def is_local(self) -> bool:
return True
+2 -2
View File
@@ -87,7 +87,7 @@ class SimpleEnvironment(BaseEnvironment):
return func_list
def add_ai_operation(self,op:AIAction) -> None:
self.operations[op.get_name()] = op
self.operations[op.get_id()] = op
def get_ai_operation(self,op_name:str) -> AIAction:
op = self.operations.get(op_name)
@@ -114,7 +114,7 @@ class CompositeEnvironment(SimpleEnvironment):
self.functions[func.get_id()] = func
operations = env.get_all_ai_operations()
for op in operations:
self.operations[op.get_name()] = op
self.operations[op.get_id()] = op
def get_value(self,key:str) -> Optional[str]:
for env in self.envs:
+1 -1
View File
@@ -214,7 +214,7 @@ class SimpleKnowledgeDB:
def query_docs_by_tag(self, tag: str) -> List[str]:
conn = self._get_conn()
cursor = conn.cursor()
tag_json = json.dumps(tag) # 将标签转换为 JSON 字符串
tag_json = json.dumps(tag,ensure_ascii=False) # 将标签转换为 JSON 字符串
cursor.execute('''
SELECT documents.doc_path
FROM documents
+3 -3
View File
@@ -126,7 +126,7 @@ class CalenderEnvironment(SimpleEnvironment):
_event["location"] = row[5]
_event["details"] = row[6]
result[row[0]] = _event
return json.dumps(result, indent=4, sort_keys=True)
return json.dumps(result, indent=4, sort_keys=True,ensure_ascii=False)
async def _get_events_by_time_range(self,start_time, end_time):
async with aiosqlite.connect(self.db_file) as db:
@@ -152,7 +152,7 @@ class CalenderEnvironment(SimpleEnvironment):
if not have_result:
return "No event."
return json.dumps(result, indent=4, sort_keys=True)
return json.dumps(result, indent=4, sort_keys=True,ensure_ascii=False)
async def _update_event(self,event_id, new_title=None, new_participants=None, new_location=None, new_details=None ,start_time=None, end_time=None):
fields_to_update = []
@@ -214,7 +214,7 @@ class CalenderEnvironment(SimpleEnvironment):
cm = ContactManager.get_instance()
contact : Contact = cm.find_contact_by_name(name)
if contact:
s = json.dumps(contact.to_dict())
s = json.dumps(contact.to_dict(),ensure_ascii=False)
return f"Execute get_contact OK , contact {name} is {s}"
else:
return f"Execute get_contact OK , contact {name} not found!"
+3 -3
View File
@@ -205,7 +205,7 @@ class TodoListEnvironment(SimpleEnvironment):
self._save_todo_path(todo.todo_id,todo_path)
logger.info("create_todo %s",detail_path)
async with aiofiles.open(detail_path, mode='w', encoding="utf-8") as f:
await f.write(json.dumps(todo.to_dict()))
await f.write(json.dumps(todo.to_dict(),ensure_ascii=False))
except Exception as e:
logger.error("create_todo failed:%s",e)
return str(e)
@@ -221,7 +221,7 @@ class TodoListEnvironment(SimpleEnvironment):
todo.state = new_stat
detail_path = f"{full_path}/detail"
async with aiofiles.open(detail_path, mode='w', encoding="utf-8") as f:
await f.write(json.dumps(todo.to_dict()))
await f.write(json.dumps(todo.to_dict()),ensure_ascii=False)
return None
else:
return "todo not found."
@@ -270,7 +270,7 @@ class TodoListEnvironment(SimpleEnvironment):
logs = []
logs.append(result.to_dict())
json_obj["logs"] = logs
await f.write(json.dumps(json_obj))
await f.write(json.dumps(json_obj),ensure_ascii=False)
class WorkspaceEnvironment(CompositeEnvironment):
+1
View File
@@ -63,6 +63,7 @@ class KnowledgeObject(ABC):
# Convert the object_type and desc to string and compute the SHA256 hash
data = json.dumps(
{"object_type": self.object_type, "desc": self.desc},
ensure_ascii=False,
cls=ObjectEnhancedJSONEncoder,
)
sha256 = hashlib.sha256()
+3 -3
View File
@@ -154,7 +154,7 @@ class AgentMsg:
@staticmethod
def create_image_body(images: [str], prompt: str = None):
return json.dumps({"images": images, "prompt": prompt})
return json.dumps({"images": images, "prompt": prompt}, ensure_ascii=False)
@staticmethod
def parse_image_body(image_body: str) -> Tuple[str, List[str]]:
@@ -163,7 +163,7 @@ class AgentMsg:
@staticmethod
def create_video_body(video: str, prompt: str = None):
return json.dumps({"video": video, "prompt": prompt})
return json.dumps({"video": video, "prompt": prompt}, ensure_ascii=False)
@staticmethod
def parse_video_body(video_body: str) -> Tuple[str, str]:
@@ -172,7 +172,7 @@ class AgentMsg:
@staticmethod
def create_audio_body(audio: str, prompt: str = None):
return json.dumps({"audio": audio, "prompt": prompt})
return json.dumps({"audio": audio, "prompt": prompt}, ensure_ascii=False)
@staticmethod
def parse_audio_body(audio_body: str) -> Tuple[str, str]:
+12 -11
View File
@@ -60,7 +60,7 @@ class AIFunction:
else:
parameters_str += f"{k} (Optional): {v.description},"
if len(parameters_str) > 0:
return f"{self.get_description} Parameters: {parameters_str}"
return f"{self.get_description()} Parameters: {parameters_str}"
return f"f{self.get_description()}, no parameters"
@abstractmethod
@@ -246,12 +246,16 @@ class SimpleAIFunction(AIFunction):
class AIAction:
@abstractmethod
def get_name(self) -> str:
def get_id(self) -> str:
"""
return the name of the operation (should be snake case)
"""
pass
def get_name(self)->str:
return self.get_id().split('.')[-1].strip()
@abstractmethod
def get_description(self) -> str:
"""
@@ -274,7 +278,7 @@ class SimpleAIAction(AIAction):
self.description = description
self.func_handler = func_handler
def get_name(self) -> str:
def get_id(self) -> str:
return self.op
def get_description(self) -> str:
@@ -289,17 +293,14 @@ class SimpleAIAction(AIAction):
class AIFunction2Action(AIAction):
def __init__(self, func: AIFunction) -> None:
self.func = func
super().__init__()
self.ai_func = func
@abstractmethod
def get_name(self) -> str:
return self.func.get_id()
def get_id(self) -> str:
return self.ai_func.get_id()
@abstractmethod
def get_description(self) -> str:
return self.func.get_detail_description()
return self.ai_func.get_detail_description()
@abstractmethod
async def execute(self, params: dict) -> str:
self.func.execute(**params)
return await self.ai_func.execute(params)
+3 -3
View File
@@ -95,11 +95,11 @@ class LLMPrompt:
def as_str(self)->str:
result_str = ""
if self.system_message:
result_str = json.dumps(self.system_message)
result_str = json.dumps(self.system_message,ensure_ascii=False)
if self.messages:
result_str += json.dumps(self.messages)
result_str += json.dumps(self.messages,ensure_ascii=False)
if self.inner_functions:
result_str += json.dumps(self.inner_functions)
result_str += json.dumps(self.inner_functions,ensure_ascii=False)
return result_str
+1 -1
View File
@@ -92,7 +92,7 @@ class UserConfig:
os.makedirs(directory)
async with aiofiles.open(self.user_config_path,"w") as f:
toml_str = toml.dumps(will_save_config)
toml_str = toml.dumps(will_save_config,ensure_ascii=False)
await f.write(toml_str)
except Exception as e:
logger.error(f"save user config to {self.user_config_path} failed!")