韩宇
init
1b7e88c
import json
import time
from omagent_core.clients.devices.Aaas.schemas import (ConversationEvent, MessageType)
from omagent_core.clients.input_base import InputBase
from omagent_core.engine.http.models.workflow_status import running_status
from omagent_core.engine.orkes.orkes_workflow_client import (
workflow_client)
from omagent_core.services.connectors.redis import RedisConnector
from omagent_core.utils.logger import logging
from omagent_core.utils.registry import registry
@registry.register_component()
class AaasInput(InputBase):
redis_stream_client: RedisConnector
def read_input(self, workflow_instance_id: str, input_prompt=""):
result = self._parse_workflow_instance_id(workflow_instance_id)
workflow_instance_id = result.get('workflow_instance_id', '')
agent_id = result.get('agent_id', '')
conversation_id = result.get('conversation_id', '')
chat_id = result.get('chat_id', '')
stream_name = f"agent_os:conversation:input:{workflow_instance_id}"
group_name = "OmAaasAgentConsumerGroup" # consumer group name
consumer_name = f"{workflow_instance_id}_agent" # consumer name
poll_interval: int = 1
if input_prompt is not None:
start_id = self.send_output_message(agent_id, conversation_id, chat_id, input_prompt)
else:
current_timestamp = int(time.time() * 1000)
start_id = f"{current_timestamp}-0"
result = {}
# ensure consumer group exists
try:
self.redis_stream_client._client.xgroup_create(
stream_name, group_name, id="0", mkstream=True
)
except Exception as e:
logging.debug(f"Consumer group may already exist: {e}")
logging.info(
f"Listening to Redis stream: {stream_name} in group: {group_name} start_id: {start_id}"
)
data_flag = False
while True:
try:
# logging.info(f"Checking workflow status: {workflow_instance_id}")
workflow_status = workflow_client.get_workflow_status(
workflow_instance_id
)
if workflow_status.status not in running_status:
logging.info(
f"Workflow {workflow_instance_id} is not running, exiting..."
)
break
# read new messages from redis stream
messages = self.redis_stream_client._client.xrevrange(
stream_name, max="+", min=start_id, count=1
)
logging.info(f"Messages: {messages}")
# Convert byte data to string
messages = [
(
message_id,
{
k.decode("utf-8"): v.decode("utf-8")
for k, v in message.items()
},
)
for message_id, message in messages
]
for message_id, message in messages:
data_flag = self.process_message(message, result)
if data_flag:
break
# Sleep for the specified interval before checking for new messages again
# logging.info(f"Sleeping for {poll_interval} seconds, waiting for {stream_name} ...")
time.sleep(poll_interval)
except Exception as e:
logging.error(f"Error while listening to stream: {e}")
time.sleep(poll_interval) # Wait before retrying
return result
def process_message(self, message, result):
logging.info(f"Received message: {message}")
try:
payload = message.get("payload")
messages = []
for dialong in payload.get('messages', []):
content = []
for item in dialong.get('contents', []):
content.append({
'type': item.get('contentType', 'unknown'),
'data': item.get('content')
})
messages.append({
'role': dialong.get('role'),
'content': content
})
payload['messages'] = messages
"""
{
"agent_id": "string",
"messages": [
{
"role": "string",
"content": [
{
"type": "string",
"data": "string"
}
]
}
],
"kwargs": {}
}
"""
# check payload data
if not payload:
logging.error("Payload is empty")
return False
try:
payload_data = json.loads(payload)
except json.JSONDecodeError as e:
logging.error(f"Payload is not a valid JSON: {e}")
return False
if "agent_id" not in payload_data:
logging.error("Payload does not contain 'agent_id' key")
return False
if "messages" not in payload_data:
logging.error("Payload does not contain 'messages' key")
return False
if not isinstance(payload_data["messages"], list):
logging.error("'messages' should be a list")
return False
for message in payload_data["messages"]:
if not isinstance(message, dict):
logging.error("Each item in 'messages' should be a dictionary")
return False
if "role" not in message or "content" not in message:
logging.error(
"Each item in 'messages' should contain 'role' and 'content' keys"
)
return False
if not isinstance(message["content"], list):
logging.error("'content' should be a list")
return False
for content in message["content"]:
if not isinstance(content, dict):
logging.error("Each item in 'content' should be a dictionary")
return False
if "type" not in content or "data" not in content:
logging.error(
"Each item in 'content' should contain 'type' and 'data' keys"
)
return False
message_data = json.loads(payload)
result.update(message_data)
except Exception as e:
logging.error(f"Error processing message: {e}")
return False
return True
@staticmethod
def _parse_workflow_instance_id(data: str):
split_data = data.split('|')
if not split_data:
return {}
result = {}
keys = [
'workflow_instance_id',
'agent_id',
'conversation_id',
'chat_id',
]
for index, value in enumerate(split_data):
if index + 1 <= len(keys):
result.setdefault(keys[index], value)
return result
def _create_output_data(
self,
event='',
conversation_id='',
chat_id='',
agent_id='',
status='',
contentType='',
content='',
type='',
is_finish=True
):
data = {
'content': json.dumps({
'event': event,
'data': {
'conversationId': conversation_id,
'chatId': chat_id,
'agentId': agent_id,
'createTime': None,
'endTime': None,
'status': status,
'contentType': contentType,
'content': content,
'type': type,
'isFinish': is_finish
}
}, ensure_ascii=False)
}
return data
def send_base_message(
self,
event='',
conversation_id='',
chat_id='',
agent_id='',
status='',
contentType='',
content='',
type='',
is_finish=True
):
stream_name = f"agent_os:conversation:output:{conversation_id}"
group_name = "OmAaasAgentConsumerGroup" # replace with your consumer group name
message = self._create_output_data(
event=event,
conversation_id=conversation_id,
chat_id=chat_id,
agent_id=agent_id,
status=status,
contentType=contentType,
content=content,
type=type,
is_finish=is_finish
)
message_id = self.send_to_group(stream_name, group_name, message)
return message_id
def send_output_message(
self,
agent_id,
conversation_id,
chat_id,
msg,
):
return self.send_base_message(
event=ConversationEvent.MESSAGE_DELTA.value,
conversation_id=conversation_id,
chat_id=chat_id,
agent_id=agent_id,
status='completed',
contentType=MessageType.TEXT.value,
content=msg,
type='ask_complete',
is_finish=True
)
def send_to_group(self, stream_name, group_name, data):
logging.info(f"Stream: {stream_name}, Group: {group_name}, Data: {data}")
message_id = self.redis_stream_client._client.xadd(stream_name, data)
try:
self.redis_stream_client._client.xgroup_create(
stream_name, group_name, id="0"
)
except Exception as e:
logging.debug(f"Consumer group may already exist: {e}")
return message_id