1.workflow has reached a state of basic functionality.

2. implemented AI message bus infrastructure,
This commit is contained in:
Liu Zhicong
2023-08-30 12:30:41 -07:00
parent ccbef2104b
commit 05d2e4a9cf
21 changed files with 1146 additions and 297 deletions
+31 -106
View File
@@ -1,51 +1,17 @@
from typing import Optional
from enum import Enum
from asyncio import Queue
import asyncio
import logging
import uuid
import time
from .agent_message import AgentMsg
from .chatsession import AIChatSession
logger = logging.getLogger(__name__)
class AgentMsgState(Enum):
RESPONSED = 0
INIT = 1
SENDING = 2
PROCESSING = 3
ERROR = 4
class AgentMsg:
def __init__(self) -> None:
self.create_time = 0
self.sender:str = None
self.target:str = None
self.body:str = None
self.state = AgentMsgState.INIT
self.resp_msg = None
def set(self,sender:str,target:str,body:str) -> None:
self.sender = sender
self.target = target
self.body = body
self.create_time = time.time()
def get_msg_id(self) -> str:
pass
def get_sender(self) -> str:
return self.sender
def get_target(self) -> str:
return self.target
# return workflow_name, role_name, session_id
def parser_target(self,target:str) -> None:
pass
class AgentPrompt:
def __init__(self) -> None:
self.messages = []
@@ -59,6 +25,9 @@ class AgentPrompt:
return result_str
def append(self,prompt):
if prompt is None:
return
self.messages.extend(prompt.messages)
def load_from_config(self,config:list) -> bool:
@@ -69,28 +38,6 @@ class AgentPrompt:
self.messages = config
return True
# chat session store the chat history between owner and agent
# chat session might be large, so can read / write at stream mode.
class AIChatSession:
def __init__(self,owner_id) -> None:
self.owner_id = owner_id
def get_owner_id(self) -> str:
return self.owner_id
def append_post(self,msg:AgentMsg) -> None:
"""append msg to session, msg is post from session (owner => msg.target)"""
pass
def append_recv(self,msg:AgentMsg) -> None:
"""append msg to session, msg is recv from msg'sender (msg.sender => owner)"""
pass
def attach_event_handler(self,handler) -> None:
"""chat session changed event handler"""
pass
#TODO : add iterator interface for read chat history
class AIAgentTemplete:
def __init__(self) -> None:
@@ -121,14 +68,14 @@ class AIAgent:
def __init__(self) -> None:
self.prompt:AgentPrompt = None
self.llm_model_name:str = None
self.max_token_size:int = 0
self.max_token_size:int = 3600
self.instance_id:str = None
self.template_id:str = None
self.fullname:str = None
self.powerby = None
self.enable = True
self.chat_sessions = {}
self.chat_db = None
self.unread_msg = Queue() # msg from other agent
@classmethod
@@ -170,27 +117,6 @@ class AIAgent:
return True
def post_msg(self,msg:AgentMsg) -> None:
# TODO: drop same msg already processed
msg.state = AgentMsgState.SENDING
self.unread_msg.put_nowait(msg)
def start(self) -> None:
async def _process_msg_loop():
while True:
msg = await self.unread_msg.get()
if msg is None:
continue
msg.state = AgentMsgState.PROCESSING
resp_msg = await self._process_msg(msg)
if resp_msg is None:
msg.state = AgentMsgState.ERROR
continue
else:
msg.state = AgentMsgState.RESPONSED
msg.resp_msg = resp_msg
asyncio.create_task(_process_msg_loop())
def _get_llm_result_type(self,result:str) -> str:
if result == "ignore":
@@ -200,16 +126,19 @@ class AIAgent:
async def _process_msg(self,msg:AgentMsg) -> AgentMsg:
from .compute_kernel import ComputeKernel
session_topic = msg.get_sender() + "#" + msg.topic
chatsession = AIChatSession.get_session(self.instance_id,session_topic,self.chat_db)
prompt = AgentPrompt()
prompt.append(self.prompt)
msg_prompt = AgentPrompt()
msg_prompt.messages = [{"role":msg.sender,"content":msg.body}]
prompt.append(msg_prompt)
# prompt.append(self._get_function_prompt(the_role.get_name()))
# prompt.append(self._get_knowlege_prompt(the_role.get_name()))
# prompt.append(await self._get_prompt_from_session(chatsession,the_role.get_name())) # chat context
prompt.append(await self._get_prompt_from_session(chatsession)) # chat context
msg_prompt = AgentPrompt()
msg_prompt.messages = [{"role":"user","content":msg.body}]
prompt.append(msg_prompt)
result = await ComputeKernel().do_llm_completion(prompt,self.llm_model_name,self.max_token_size)
final_result = result
result_type : str = self._get_llm_result_type(result)
@@ -257,12 +186,13 @@ class AIAgent:
if is_ignore is not True:
# TODO : how to get inner chat session?
chatsession = self.get_chat_session(msg.sender)
resp_msg = AgentMsg()
resp_msg.set(self.instance_id,msg.sender,final_result)
resp_msg.topic = msg.topic
if chatsession is not None:
chatsession.append_recv(msg)
chatsession.append_post(final_result)
chatsession.append_post(resp_msg)
return resp_msg
@@ -277,25 +207,20 @@ class AIAgent:
def get_template_id(self) -> str:
return self.template_id
def get_chat_session_for_msg(self,msg:AgentMsg) -> AIChatSession:
pass
def get_chat_session(self,remote:str,topic_name:str=None) -> AIChatSession:
if topic_name is None:
topic_name = "_"
result_session = self.chat_sessions.get(topic_name + "@" + remote)
if result_session is not None:
return result_session
result_session = AIChatSession(self)
self.chat_sessions[topic_name + "@" + remote] = result_session
return result_session
def get_llm_model_name(self) -> str:
return self.llm_model_name
def get_max_token_size(self) -> int:
return self.max_token_size
async def _get_prompt_from_session(self,chatsession:AIChatSession) -> AgentPrompt:
messages = chatsession.read_history() # read last 10 message
result_prompt = AgentPrompt()
for msg in reversed(messages):
if msg.target == chatsession.owner_id:
result_prompt.messages.append({"role":"user","content":f"{msg.sender}:{msg.body}"})
if msg.sender == chatsession.owner_id:
result_prompt.messages.append({"role":"assistant","content":msg.body})
return result_prompt