Complete self_thinking llm process and Agent Memory
This commit is contained in:
+41
-25
@@ -24,21 +24,16 @@ from .llm_do_task import *
|
||||
from .chatsession import *
|
||||
|
||||
from ..environment.workspace_env import WorkspaceEnvironment, TodoListType
|
||||
from ..frame.contact_manager import ContactManager,Contact,FamilyMember
|
||||
from ..frame.compute_kernel import ComputeKernel
|
||||
from ..frame.bus import AIBus
|
||||
from ..environment.environment import *
|
||||
from ..environment.workspace_env import WorkspaceEnvironment
|
||||
from ..storage.storage import AIStorage
|
||||
from ..knowledge import *
|
||||
from ..utils import video_utils, image_utils
|
||||
from ..proto.compute_task import ComputeTaskResult,ComputeTaskResultCode,LLMPrompt,LLMResult
|
||||
from ..proto.compute_task import LLMPrompt,LLMResult
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class AIAgentTemplete:
|
||||
def __init__(self) -> None:
|
||||
self.llm_model_name:str = "gpt-4-0613"
|
||||
self.llm_model_name:str = "gpt-4-turbo-preview"
|
||||
self.max_token_size:int = 0
|
||||
self.template_id:str = None
|
||||
self.introduce:str = None
|
||||
@@ -99,7 +94,8 @@ class AIAgent(BaseAIAgent):
|
||||
}
|
||||
self.todo_prompts = todo_prompts
|
||||
|
||||
self.memory_db = None
|
||||
self.base_dir = None
|
||||
#self.memory_db = None
|
||||
self.unread_msg = Queue() # msg from other agent
|
||||
self.owenr_bus = None
|
||||
|
||||
@@ -109,7 +105,9 @@ class AIAgent(BaseAIAgent):
|
||||
self.behaviors:Dict[str,BaseLLMProcess] = {}
|
||||
|
||||
async def initial(self,params:Dict = None):
|
||||
self.memory = AgentMemory(self.agent_id,self.memory_db)
|
||||
self.base_dir = f"{AIStorage.get_instance().get_myai_dir()}/agent_data/{self.agent_id}"
|
||||
memory_base_dir = f"{self.base_dir}/memory"
|
||||
self.memory = AgentMemory(self.agent_id,memory_base_dir)
|
||||
self.prviate_workspace = AgentWorkspace(self.agent_id)
|
||||
init_params = {}
|
||||
init_params["memory"] = self.memory
|
||||
@@ -241,6 +239,34 @@ class AIAgent(BaseAIAgent):
|
||||
return await self.llm_process_msg(msg)
|
||||
|
||||
|
||||
async def llm_self_think(self):
|
||||
llm_process : BaseLLMProcess = self.behaviors.get("self_thinking")
|
||||
if llm_process:
|
||||
logger.info(f"agent {self.agent_id} self thinking start!")
|
||||
|
||||
context_info = await self._get_context_info()
|
||||
known_session_list = AIChatSession.list_session(self.agent_id,self.memory.memory_db)
|
||||
known_experience_list = await self.memory.list_experience()
|
||||
record_list = await self.memory.load_records(await self.memory.get_last_think_time())
|
||||
|
||||
input_parms = {
|
||||
"record_list":record_list,
|
||||
"known_session_list":known_session_list,
|
||||
"known_experience_list":known_experience_list,
|
||||
"context_info":context_info
|
||||
}
|
||||
|
||||
llm_result : LLMResult = await llm_process.process(input_parms)
|
||||
if llm_result.state == LLMResultStates.ERROR:
|
||||
logger.error(f"llm process self thinking error:{llm_result.compute_error_str}")
|
||||
elif llm_result.state == LLMResultStates.IGNORE:
|
||||
logger.info(f"llm process self thinking ignore!")
|
||||
else:
|
||||
logger.info(f"llm process self thinking ok!,think is:{llm_result.resp}")
|
||||
self.memory.set_last_think_time(time.time())
|
||||
self.agent_energy -= 2
|
||||
return
|
||||
|
||||
async def llm_triage_tasklist(self):
|
||||
llm_process : BaseLLMProcess = self.behaviors.get("triage_tasks")
|
||||
if llm_process:
|
||||
@@ -361,21 +387,8 @@ class AIAgent(BaseAIAgent):
|
||||
self.agent_energy -= 1
|
||||
|
||||
|
||||
async def do_self_think(self):
|
||||
session_id_list = AIChatSession.list_session(self.agent_id,self.memory_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
|
||||
return
|
||||
|
||||
def need_self_think(self) -> bool:
|
||||
return False
|
||||
|
||||
async def _self_imporve(self):
|
||||
if self.need_self_think():
|
||||
await self.do_self_think()
|
||||
await self.llm_self_think()
|
||||
|
||||
def wake_up(self) -> None:
|
||||
if self.agent_task is None:
|
||||
@@ -446,13 +459,16 @@ class AIAgent(BaseAIAgent):
|
||||
|
||||
await self._self_imporve()
|
||||
|
||||
|
||||
|
||||
except Exception as e:
|
||||
tb_str = traceback.format_exc()
|
||||
logger.error(f"agent {self.agent_id} on timer error:{e},{tb_str}")
|
||||
continue
|
||||
|
||||
|
||||
# Because the LLM itself is very slow, the accuracy of the system processing task is in minutes.
|
||||
await asyncio.sleep(30)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+323
-14
@@ -1,12 +1,18 @@
|
||||
# pylint:disable=E0402
|
||||
from datetime import datetime,timedelta
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
from typing import Dict, List
|
||||
import sqlite3
|
||||
|
||||
import aiofiles
|
||||
|
||||
from ..storage.storage import AIStorage
|
||||
from ..frame.compute_kernel import ComputeKernel
|
||||
from ..proto.ai_function import SimpleAIAction
|
||||
from ..frame.contact_manager import ContactManager
|
||||
from ..frame.contact import Contact
|
||||
from ..proto.ai_function import ParameterDefine, SimpleAIAction, SimpleAIFunction
|
||||
from ..proto.agent_msg import AgentMsg, AgentMsgType
|
||||
from ..proto.agent_task import AgentWorkLog
|
||||
|
||||
@@ -17,12 +23,34 @@ import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
#class ObjectSummary:
|
||||
# def __init__(self) -> None:
|
||||
# self.summary : str = None
|
||||
# self.object_name : str = None
|
||||
# self.priority : int = 5
|
||||
# [info_source, info]
|
||||
# self.infos : Dict[str,str] = {}
|
||||
|
||||
|
||||
|
||||
class AgentMemory:
|
||||
def __init__(self,agent_id:str,db_path:str) -> None:
|
||||
def __init__(self,agent_id:str,base_dir:str) -> None:
|
||||
self.agent_memory_base_dir = base_dir
|
||||
self.agent_id:str= agent_id
|
||||
self.memory_db:str = db_path
|
||||
|
||||
AIStorage.get_instance().ensure_directory_exists(self.agent_memory_base_dir)
|
||||
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/experience")
|
||||
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/contacts")
|
||||
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/relations")
|
||||
AIStorage.get_instance().ensure_directory_exists(f"{self.agent_memory_base_dir}/summary")
|
||||
|
||||
self.memory_db:str = f"{self.agent_memory_base_dir}/memory.db"
|
||||
self.model_name:str = "gp4-1106-preview"
|
||||
self.threshold_hours = 72
|
||||
self.last_think_time : float = 0.0
|
||||
|
||||
self.load_memory_meta()
|
||||
|
||||
|
||||
def _get_conn(self):
|
||||
@@ -54,6 +82,15 @@ class AgentMemory:
|
||||
session_topic = msg.get_sender() + "#" + msg.topic
|
||||
chatsession = AIChatSession.get_session(self.agent_id,session_topic,self.memory_db)
|
||||
return chatsession
|
||||
|
||||
# return last record time
|
||||
async def load_records(self,starttime,tokenlimit=8000)->float:
|
||||
# 专用思路:做聊天记录/工作经验的整理
|
||||
# 通用思路:没有具体的目的,让Agent根据提示词自己工作(可能效果很差也可能很好)
|
||||
# 先实现通用思路
|
||||
msg_records = AIChatSession.load_message_records_by_agentid(self.agent_id,starttime,32,self.memory_db)
|
||||
work_records = self.load_worklogs(self.agent_id,token_limit=tokenlimit)
|
||||
pass
|
||||
|
||||
async def load_chatlogs(self,msg:AgentMsg,n:int=6,m:int=64,token_limit=800)->str:
|
||||
chatsession = self.get_session_from_msg(msg)
|
||||
@@ -176,23 +213,295 @@ class AgentMemory:
|
||||
conn.commit()
|
||||
#conn.close()
|
||||
|
||||
def memory_meta_to_dict(self) -> Dict:
|
||||
return {
|
||||
"last_think_time" : self.last_think_time
|
||||
}
|
||||
|
||||
def load_meta(self,Dict):
|
||||
self.last_think_time = Dict.get("last_think_time",0.0)
|
||||
|
||||
def load_memory_meta(self):
|
||||
meta_file_path = f"{self.agent_memory_base_dir}/meta.json"
|
||||
try:
|
||||
with open(meta_file_path, mode='r') as file:
|
||||
meta = json.load(file)
|
||||
self.load_meta(meta)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"load memory meta failed: {e}")
|
||||
self.last_think_time = 0.0
|
||||
|
||||
def save_memory_meta(self):
|
||||
meta_file_path = f"{self.agent_memory_base_dir}/meta.json"
|
||||
try:
|
||||
with open(meta_file_path, mode='w') as file:
|
||||
meta = self.memory_meta_to_dict()
|
||||
json.dump(meta,file)
|
||||
except Exception as e:
|
||||
logger.error(f"save memory meta failed: {e}")
|
||||
|
||||
async def get_last_think_time(self)->float:
|
||||
return self.last_think_time
|
||||
|
||||
async def set_last_think_time(self,last_time:float):
|
||||
self.last_think_time = last_time
|
||||
self.save_memory_meta()
|
||||
|
||||
async def get_contact_summary(self,contact_id:str) -> str:
|
||||
if contact_id is None:
|
||||
return None
|
||||
return "Contact id is None"
|
||||
|
||||
# TODO : fix this by system config.
|
||||
if contact_id == "lzc":
|
||||
return "lzc is your master. Male, 40 years old, Mother tongue is Chinese, senior software engineer."
|
||||
return None
|
||||
result = {}
|
||||
contact_info:Contact = ContactManager.get_instance().find_contact_by_name(contact_id)
|
||||
if contact_info:
|
||||
result["name"] = contact_info.name
|
||||
result["relation"] = contact_info.relationship
|
||||
result["notes"] = contact_info.notes
|
||||
|
||||
summary_path = f"{self.agent_memory_base_dir}/contacts/{contact_id}.summary"
|
||||
try:
|
||||
async with aiofiles.open(summary_path, mode='r') as file:
|
||||
result["summary"] = await file.read()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"read contact summary failed: {e}")
|
||||
|
||||
return json.dumps(result,ensure_ascii=False)
|
||||
|
||||
async def update_contact_summary(self,contact_id:str,summary:str) -> str:
|
||||
return "OK"
|
||||
async def update_contact_summary(self,contact_id:str,summary:str):
|
||||
summary_path = f"{self.agent_memory_base_dir}/contacts/{contact_id}.summary"
|
||||
try:
|
||||
async with aiofiles.open(summary_path, mode='w') as file:
|
||||
await file.write(summary)
|
||||
return "OK"
|
||||
except Exception as e:
|
||||
logger.error(f"write contact summary failed: {e}")
|
||||
return "write contact summary failed: {e}"
|
||||
|
||||
async def get_sth_summary(self,sth_id:str) -> str:
|
||||
return None
|
||||
async def get_summary(self,object_name:str) -> str:
|
||||
summary_path = f"{self.agent_memory_base_dir}/{object_name}.summary"
|
||||
try:
|
||||
async with aiofiles.open(summary_path, mode='r') as file:
|
||||
return await file.read()
|
||||
except Exception as e:
|
||||
logger.error(f"read summary failed: {e}")
|
||||
return f"read summary failed: {e}"
|
||||
|
||||
async def update_summary(self,object_name:str,summary:str) -> str:
|
||||
summary_path = f"{self.agent_memory_base_dir}/{object_name}.summary"
|
||||
try:
|
||||
async with aiofiles.open(summary_path, mode='w') as file:
|
||||
await file.write(summary)
|
||||
return "OK"
|
||||
except Exception as e:
|
||||
logger.error(f"write summary failed: {e}")
|
||||
return f"write summary failed: {e}"
|
||||
|
||||
async def list_summary_object_names(self) -> List[str]:
|
||||
# list dir
|
||||
try:
|
||||
contents = os.listdir(self.agent_memory_base_dir)
|
||||
return [x for x in contents if x.endswith(".summary")]
|
||||
except Exception as e:
|
||||
logger.error(f"list summary object names failed: {e}")
|
||||
return []
|
||||
|
||||
# means object1 feel object2 is ...
|
||||
async def get_relation_summary(self,object_name1:str,object_name2:str) -> str:
|
||||
summary_path = f"{self.agent_memory_base_dir}/relations/{object_name1}.relation.{object_name2}.summary"
|
||||
try:
|
||||
async with aiofiles.open(summary_path, mode='r') as file:
|
||||
await file.read()
|
||||
except FileNotFoundError:
|
||||
return "no summary"
|
||||
except Exception as e:
|
||||
logger.error(f"read relation summary failed: {e}")
|
||||
return f"read relation summary failed: {e}"
|
||||
|
||||
|
||||
async def update_relation_summary(self,object_name1:str,object_name2:str,summary:Dict):
|
||||
summary_path = f"{self.agent_memory_base_dir}/relations/{object_name1}.relation.{object_name2}.summary"
|
||||
try:
|
||||
async with aiofiles.open(summary_path, mode='w') as file:
|
||||
await file.write(json.dumps(summary))
|
||||
return "OK"
|
||||
except Exception as e:
|
||||
logger.error(f"write relation summary failed: {e}")
|
||||
return "write relation summary failed: {e}"
|
||||
|
||||
async def get_experience(self,topic_name:str) -> str:
|
||||
experience_path = f"{self.agent_memory_base_dir}/experience/{topic_name}.experience"
|
||||
try:
|
||||
async with aiofiles.open(experience_path, mode='r') as file:
|
||||
await file.read()
|
||||
except FileNotFoundError:
|
||||
return "no experience"
|
||||
except Exception as e:
|
||||
logger.error(f"read experience failed: {e}")
|
||||
return f"read experience failed: {e}"
|
||||
|
||||
|
||||
async def set_experience(self,topic_name:str,summary:str) -> str:
|
||||
experience_path = f"{self.agent_memory_base_dir}/experience/{topic_name}.experience"
|
||||
try:
|
||||
async with aiofiles.open(experience_path, mode='w') as file:
|
||||
await file.write(summary)
|
||||
return "OK"
|
||||
except Exception as e:
|
||||
logger.error(f"write experience failed: {e}")
|
||||
return "write experience failed: {e}"
|
||||
|
||||
async def list_experience(self) -> List[str]:
|
||||
dir_path = f"{self.agent_memory_base_dir}/experience"
|
||||
try:
|
||||
contents = os.listdir(dir_path)
|
||||
return [x for x in contents if x.endswith(".experience")]
|
||||
except Exception as e:
|
||||
logger.error(f"list experience failed: {e}")
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def register_ai_functions():
|
||||
async def get_contact_summary(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
contact_name = parameters.get("contact_name")
|
||||
return await agent_memory.get_contact_summary(contact_name)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"contact_name": {"type": "string", "description": "contact name"}
|
||||
})
|
||||
get_contact_summary_func = SimpleAIFunction("agent.memory.get_contact_summary",
|
||||
"get contact summary",
|
||||
get_contact_summary,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(get_contact_summary_func)
|
||||
|
||||
async def update_contact_summary(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
contact_name = parameters.get("contact_name")
|
||||
summary = parameters.get("summary")
|
||||
return await agent_memory.update_contact_summary(contact_name,summary)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"contact_name": {"type": "string", "description": "contact name"},
|
||||
"summary": {"type": "string", "description": "new summary"}
|
||||
})
|
||||
update_contact_summary_func = SimpleAIFunction("agent.memory.update_contact_summary",
|
||||
"update contact summary",
|
||||
update_contact_summary,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(update_contact_summary_func)
|
||||
|
||||
async def get_summary(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
object_name = parameters.get("object_name")
|
||||
return await agent_memory.get_summary(object_name)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"object_name": {"type": "string", "description": "object name"}
|
||||
})
|
||||
get_summary_func = SimpleAIFunction("agent.memory.get_summary",
|
||||
"get summary of sth",
|
||||
get_summary,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(get_summary_func)
|
||||
|
||||
async def update_summary(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
object_name = parameters.get("object_name")
|
||||
summary = parameters.get("summary")
|
||||
return await agent_memory.update_summary(object_name,summary)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"object_name": {"type": "string", "description": "object name"},
|
||||
"summary": {"type": "string", "description": "new summary"}
|
||||
})
|
||||
update_summary_func = SimpleAIFunction("agent.memory.update_summary",
|
||||
"update summary of sth",
|
||||
update_summary,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(update_summary_func)
|
||||
|
||||
async def list_summary_object_names(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
return await agent_memory.list_summary_object_names()
|
||||
parameters = ParameterDefine.create_parameters({})
|
||||
list_summary_object_names_func = SimpleAIFunction("agent.memory.list_summary",
|
||||
"list summary object names",
|
||||
list_summary_object_names,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(list_summary_object_names_func)
|
||||
|
||||
async def get_relation_summary(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
object_name1 = parameters.get("object1_name")
|
||||
object_name2 = parameters.get("object2_name")
|
||||
return await agent_memory.get_relation_summary(object_name1,object_name2)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"object1_name": {"type": "string", "description": "object name1"},
|
||||
"object2_name": {"type": "string", "description": "object name2"}
|
||||
})
|
||||
get_relation_summary_func = SimpleAIFunction("agent.memory.get_relation_summary",
|
||||
"object1 feel object2 is ...",
|
||||
get_relation_summary,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(get_relation_summary_func)
|
||||
|
||||
async def update_relation_summary(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
object_name1 = parameters.get("object1_name")
|
||||
object_name2 = parameters.get("object2_name")
|
||||
summary = parameters.get("summary")
|
||||
return await agent_memory.update_relation_summary(object_name1,object_name2,summary)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"object1_name": {"type": "string", "description": "object name1"},
|
||||
"object2_name": {"type": "string", "description": "object name2"},
|
||||
"summary": {"type": "string", "description": "new summary"}
|
||||
})
|
||||
update_relation_summary_func = SimpleAIFunction("agent.memory.update_relation_summary",
|
||||
"object1 feel object2 is ...",
|
||||
update_relation_summary,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(update_relation_summary_func)
|
||||
|
||||
async def get_experience(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
topic_name = parameters.get("topic_name")
|
||||
return await agent_memory.get_experience(topic_name)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"topic_name": {"type": "string", "description": "topic name"}
|
||||
})
|
||||
get_experience_func = SimpleAIFunction("agent.memory.get_experience",
|
||||
"get experience",
|
||||
get_experience,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(get_experience_func)
|
||||
|
||||
async def set_experience(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
topic_name = parameters.get("topic_name")
|
||||
summary = parameters.get("summary")
|
||||
return await agent_memory.set_experience(topic_name,summary)
|
||||
parameters = ParameterDefine.create_parameters({
|
||||
"topic_name": {"type": "string", "description": "topic name"},
|
||||
"summary": {"type": "string", "description": "new summary"}
|
||||
})
|
||||
set_experience_func = SimpleAIFunction("agent.memory.set_experience",
|
||||
"set experience",
|
||||
set_experience,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(set_experience_func)
|
||||
|
||||
async def list_experience(parameters):
|
||||
agent_memory:AgentMemory = parameters.get("_agent_memory")
|
||||
return await agent_memory.list_experience()
|
||||
parameters = ParameterDefine.create_parameters({})
|
||||
list_experience_func = SimpleAIFunction("agent.memory.list_experience",
|
||||
"list exist experience topics",
|
||||
list_experience,
|
||||
parameters)
|
||||
GlobaToolsLibrary.register_tool_function(list_experience_func)
|
||||
|
||||
|
||||
|
||||
|
||||
async def update_sth_summary(self,sth_id:str,summary:str) -> str:
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -211,6 +211,23 @@ class ChatSessionDB:
|
||||
logging.error("Error occurred while getting messages: %s", e)
|
||||
return -1, None # return -1 and None if an error occurs
|
||||
|
||||
def load_message_by_agentid(self,agent_id,limit,start_time="1970-01-01 00:00:00"):
|
||||
try:
|
||||
conn = self._get_conn()
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("""
|
||||
SELECT MessageID, SessionID, MsgType, PrevMsgID, SenderID, ReceiverID, Timestamp, Topic,Mentions,ContentMIME,Content,ActionName,ActionParams,ActionResult,DoneTime,Status FROM Messages
|
||||
WHERE SenderID = ? or ReceiverID =? AND Timestamp > ?
|
||||
ORDER BY Timestamp
|
||||
LIMIT ?
|
||||
""", (agent_id, agent_id, start_time,limit))
|
||||
results = cursor.fetchall()
|
||||
#self.close()
|
||||
return results # return 0 and the result if successful
|
||||
except Error as e:
|
||||
logging.error("Error occurred while getting messages: %s", e)
|
||||
return -1, None
|
||||
|
||||
# read message from now->beign
|
||||
def get_messages(self, session_id, limit, offset):
|
||||
""" retrieve messages of a session with pagination """
|
||||
@@ -287,6 +304,38 @@ class AIChatSession:
|
||||
# cls._dbs[db_path] = db
|
||||
# db.get_chatsession_by_id(session_id)
|
||||
# #result = AIChatSession()
|
||||
@classmethod
|
||||
# start_time is a string like "2021-01-01 00:00:00"
|
||||
def load_message_records_by_agentid(cls,agent_id:str,start_time:str,limit:int,db_path:str)->List[AgentMsg]:
|
||||
db = cls._dbs.get(db_path)
|
||||
if db is None:
|
||||
db = ChatSessionDB(db_path)
|
||||
cls._dbs[db_path] = db
|
||||
msgs = db.load_message_by_agentid(agent_id,start_time,limit)
|
||||
result = []
|
||||
for msg in msgs:
|
||||
agent_msg = AgentMsg()
|
||||
agent_msg.msg_id = msg[0]
|
||||
agent_msg.session_id = msg[1]
|
||||
agent_msg.msg_type = AgentMsgType(msg[2])
|
||||
agent_msg.prev_msg_id = msg[3]
|
||||
agent_msg.sender = msg[4]
|
||||
agent_msg.target = msg[5]
|
||||
agent_msg.create_time = msg[6]
|
||||
agent_msg.topic = msg[7]
|
||||
if msg[8] is not None:
|
||||
agent_msg.mentions = json.loads(msg[8])
|
||||
agent_msg.body_mime = msg[9]
|
||||
agent_msg.body = msg[10]
|
||||
agent_msg.func_name = msg[11]
|
||||
if msg[12] is not None:
|
||||
agent_msg.args = json.loads(msg[12])
|
||||
agent_msg.result_str = msg[13]
|
||||
agent_msg.done_time = msg[14]
|
||||
agent_msg.status = AgentMsgStatus(msg[15])
|
||||
|
||||
result.append(agent_msg)
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def get_session(cls,owner_id:str,session_topic:str,db_path:str,auto_create = True) -> 'AIChatSession':
|
||||
|
||||
+100
-29
@@ -42,6 +42,9 @@ class BaseLLMProcess(ABC):
|
||||
|
||||
self.llm_context:LLMProcessContext = None
|
||||
|
||||
def get_llm_model_name(self) -> str:
|
||||
return self.model_name
|
||||
|
||||
@abstractmethod
|
||||
async def prepare_prompt(self,input:Dict) -> LLMPrompt:
|
||||
pass
|
||||
@@ -123,10 +126,11 @@ class BaseLLMProcess(ABC):
|
||||
else:
|
||||
inner_functions = None
|
||||
|
||||
|
||||
task_result: ComputeTaskResult = await (ComputeKernel.get_instance().do_llm_completion(
|
||||
prompt,
|
||||
resp_mode=resp_mode,
|
||||
mode_name=self.model_name,
|
||||
mode_name=self.get_llm_model_name(),
|
||||
max_token=max_result_token,
|
||||
inner_functions=inner_functions, #NOTICE: inner_function in prompt can be a subset of get_inner_function
|
||||
timeout=self.timeout))
|
||||
@@ -166,7 +170,7 @@ class BaseLLMProcess(ABC):
|
||||
task_result: ComputeTaskResult = await (ComputeKernel.get_instance().do_llm_completion(
|
||||
prompt,
|
||||
resp_mode=resp_mode,
|
||||
mode_name=self.model_name,
|
||||
mode_name=self.get_llm_model_name(),
|
||||
max_token=max_result_token,
|
||||
inner_functions=prompt.inner_functions, #NOTICE: inner_function in prompt can be a subset of get_inner_function
|
||||
timeout=self.timeout))
|
||||
@@ -309,6 +313,9 @@ class LLMAgentBaseProcess(BaseLLMProcess):
|
||||
class AgentMessageProcess(LLMAgentBaseProcess):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self.mutil_model = None
|
||||
self.enable_media2text = False
|
||||
self.is_mutil_model = False
|
||||
|
||||
async def load_default_config(self) -> bool:
|
||||
return True
|
||||
@@ -319,8 +326,18 @@ class AgentMessageProcess(LLMAgentBaseProcess):
|
||||
|
||||
if await super().load_from_config(config) is False:
|
||||
return False
|
||||
|
||||
|
||||
self.enable_media2text = config.get('enable_media2text', 'false').lower() in ('true', '1', 't', 'y', 'yes')
|
||||
|
||||
if config.get("mutil_model"):
|
||||
self.mutil_model = config.get("mutil_model")
|
||||
|
||||
def get_llm_model_name(self) -> str:
|
||||
if self.is_mutil_model:
|
||||
return self.mutil_model
|
||||
else:
|
||||
return self.model_name
|
||||
|
||||
def check_and_to_base64(self, image_path: str) -> str:
|
||||
if image_utils.is_file(image_path):
|
||||
return image_utils.to_base64(image_path, (1024, 1024))
|
||||
@@ -329,14 +346,24 @@ class AgentMessageProcess(LLMAgentBaseProcess):
|
||||
|
||||
async def get_prompt_from_msg(self,msg:AgentMsg) -> LLMPrompt:
|
||||
msg_prompt = LLMPrompt()
|
||||
if msg.is_image_msg():
|
||||
image_prompt, images = msg.get_image_body()
|
||||
if image_prompt is None:
|
||||
msg_prompt.messages = [{"role": "user", "content": [{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images]}]
|
||||
self.is_mutil_model = False
|
||||
if msg.is_image_msg():
|
||||
if self.enable_media2text:
|
||||
logger.error(f"enable_media2text is not supported yet")
|
||||
else:
|
||||
content = [{"type": "text", "text": image_prompt}]
|
||||
content.extend([{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images])
|
||||
msg_prompt.messages = [{"role": "user", "content": content}]
|
||||
image_prompt, images = msg.get_image_body()
|
||||
if image_prompt is None:
|
||||
msg_prompt.messages = [{"role": "user", "content": [{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images]}]
|
||||
else:
|
||||
content = [{"type": "text", "text": image_prompt}]
|
||||
content.extend([{"type": "image_url", "image_url": {"url": self.check_and_to_base64(image)}} for image in images])
|
||||
msg_prompt.messages = [{"role": "user", "content": content}]
|
||||
|
||||
if self.mutil_model:
|
||||
self.is_mutil_model = True
|
||||
else:
|
||||
logger.warning(f"mutil_model is not set!")
|
||||
|
||||
elif msg.is_video_msg():
|
||||
video_prompt, video = msg.get_video_body()
|
||||
frames = video_utils.extract_frames(video, (1024, 1024))
|
||||
@@ -459,25 +486,7 @@ class AgentMessageProcess(LLMAgentBaseProcess):
|
||||
|
||||
return True
|
||||
|
||||
class AgentSelfLearning(BaseLLMProcess):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
async def load_from_config(self, config: dict) -> Coroutine[Any, Any, bool]:
|
||||
if await super().load_from_config(config) is False:
|
||||
return False
|
||||
|
||||
async def prepare_prompt(self) -> LLMPrompt:
|
||||
prompt = LLMPrompt()
|
||||
pass
|
||||
|
||||
async def get_inner_function_for_exec(self,func_name:str) -> AIFunction:
|
||||
pass
|
||||
|
||||
async def post_llm_process(self,actions:List[ActionNode]) -> bool:
|
||||
pass
|
||||
|
||||
class AgentSelfThinking(BaseLLMProcess):
|
||||
class AgentSelfThinking(LLMAgentBaseProcess):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
@@ -553,6 +562,68 @@ class AgentSelfThinking(BaseLLMProcess):
|
||||
chatsession.update_think_progress(next_pos,new_summary)
|
||||
return
|
||||
|
||||
async def prepare_prompt(self,input:Dict) -> LLMPrompt:
|
||||
prompt = LLMPrompt()
|
||||
|
||||
record_list = input.get("record_list")
|
||||
context_info = input.get("context_info")
|
||||
|
||||
if record_list is None:
|
||||
logger.error(f"AgentSelfThinking prepare_prompt failed! input not found")
|
||||
return None
|
||||
|
||||
prompt.append_user_message(json.dumps(record_list,ensure_ascii=False))
|
||||
system_prompt_dict = self.prepare_role_system_prompt(context_info)
|
||||
|
||||
# Known_info is the SESSION summary of the existence, the current task work record summary,
|
||||
known_info = {}
|
||||
have_known_info = False
|
||||
known_session_list = input.get("known_session_list")
|
||||
known_task_list = input.get("known_task_list")
|
||||
known_contact_list = input.get("known_contact_list")
|
||||
known_experience_list = input.get("known_experience_list")
|
||||
if known_session_list:
|
||||
known_info["known_session_list"] = known_session_list
|
||||
have_known_info = True
|
||||
if known_task_list:
|
||||
known_info["known_task_list"] = known_task_list
|
||||
have_known_info = True
|
||||
if known_contact_list:
|
||||
known_info["known_contact_list"] = known_contact_list
|
||||
have_known_info = True
|
||||
if known_experience_list:
|
||||
known_info["known_experience_list"] = known_experience_list
|
||||
have_known_info = True
|
||||
|
||||
if have_known_info:
|
||||
system_prompt_dict["known_info"] = known_info
|
||||
|
||||
prompt.inner_functions =LLMProcessContext.aifunctions_to_inner_functions(self.llm_context.get_all_ai_functions())
|
||||
prompt.append_system_message(json.dumps(system_prompt_dict,ensure_ascii=False))
|
||||
|
||||
async def post_llm_process(self,actions:List[ActionNode],input:Dict,llm_result:LLMResult) -> bool:
|
||||
action_params = {}
|
||||
action_params["_input"] = input
|
||||
action_params["_memory"] = self.memory
|
||||
action_params["_workspace"] = self.workspace
|
||||
action_params["_llm_result"] = llm_result
|
||||
action_params["_agentid"] = self.memory.agent_id
|
||||
action_params["_start_at"] = datetime.now()
|
||||
try:
|
||||
if await self._execute_actions(actions,action_params) is False:
|
||||
result_str = "execute action failed!"
|
||||
except Exception as e:
|
||||
logger.error(f"execute action failed! {e}")
|
||||
result_str = "execute action failed!,error:" + str(e)
|
||||
|
||||
class AgentSelfLearning(BaseLLMProcess):
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
|
||||
async def load_from_config(self, config: dict) -> Coroutine[Any, Any, bool]:
|
||||
if await super().load_from_config(config) is False:
|
||||
return False
|
||||
|
||||
async def prepare_prompt(self) -> LLMPrompt:
|
||||
prompt = LLMPrompt()
|
||||
pass
|
||||
|
||||
@@ -21,7 +21,7 @@ logger = logging.getLogger(__name__)
|
||||
class LocalAgentTaskManger(AgentTaskManager):
|
||||
def __init__(self, owner_id):
|
||||
super().__init__()
|
||||
self.root_path = f"{AIStorage.get_instance().get_myai_dir()}/workspaces/{owner_id}_workspace"
|
||||
self.root_path = f"{AIStorage.get_instance().get_myai_dir()}/agent_data/{owner_id}/workspace/"
|
||||
#self.root_path = os.path.join(workspace, list_type)
|
||||
if not os.path.exists(self.root_path):
|
||||
os.makedirs(self.root_path)
|
||||
|
||||
Reference in New Issue
Block a user