|
- import os
- from datetime import datetime
- from queue import Queue
- from typing import Any, Dict, List, Optional, Tuple, Union
-
- from loguru import logger
-
- from .datamodel import Message
- from .websocket_connection_manager import WebSocketConnectionManager
- from .workflowmanager import WorkflowManager
-
-
- class AutoGenChatManager:
- """
- This class handles the automated generation and management of chat interactions
- using an automated workflow configuration and message queue.
- """
-
- def __init__(
- self, message_queue: Queue, websocket_manager: WebSocketConnectionManager = None, human_input_timeout: int = 180
- ) -> None:
- """
- Initializes the AutoGenChatManager with a message queue.
-
- :param message_queue: A queue to use for sending messages asynchronously.
- """
- self.message_queue = message_queue
- self.websocket_manager = websocket_manager
- self.a_human_input_timeout = human_input_timeout
-
- def send(self, message: dict) -> None:
- """
- Sends a message by putting it into the message queue.
-
- :param message: The message string to be sent.
- """
- if self.message_queue is not None:
- self.message_queue.put_nowait(message)
-
- async def a_send(self, message: dict) -> None:
- """
- Asynchronously sends a message via the WebSocketManager class
-
- :param message: The message string to be sent.
- """
- for connection, socket_client_id in self.websocket_manager.active_connections:
- if message["connection_id"] == socket_client_id:
- logger.info(
- f"Sending message to connection_id: {message['connection_id']}. Connection ID: {socket_client_id}"
- )
- await self.websocket_manager.send_message(message, connection)
- else:
- logger.info(
- f"Skipping message for connection_id: {message['connection_id']}. Connection ID: {socket_client_id}"
- )
-
- async def a_prompt_for_input(self, prompt: dict, timeout: int = 60) -> str:
- """
- Sends the user a prompt and waits for a response asynchronously via the WebSocketManager class
-
- :param message: The message string to be sent.
- """
-
- for connection, socket_client_id in self.websocket_manager.active_connections:
- if prompt["connection_id"] == socket_client_id:
- logger.info(
- f"Sending message to connection_id: {prompt['connection_id']}. Connection ID: {socket_client_id}"
- )
- try:
- result = await self.websocket_manager.get_input(prompt, connection, timeout)
- return result
- except Exception as e:
- return f"Error: {e}\nTERMINATE"
- else:
- logger.info(
- f"Skipping message for connection_id: {prompt['connection_id']}. Connection ID: {socket_client_id}"
- )
-
- def chat(
- self,
- message: Message,
- history: List[Dict[str, Any]],
- workflow: Any = None,
- connection_id: Optional[str] = None,
- user_dir: Optional[str] = None,
- **kwargs,
- ) -> Message:
- """
- Processes an incoming message according to the agent's workflow configuration
- and generates a response.
-
- :param message: An instance of `Message` representing an incoming message.
- :param history: A list of dictionaries, each representing a past interaction.
- :param flow_config: An instance of `AgentWorkFlowConfig`. If None, defaults to a standard configuration.
- :param connection_id: An optional connection identifier.
- :param kwargs: Additional keyword arguments.
- :return: An instance of `Message` representing a response.
- """
-
- # create a working director for workflow based on user_dir/session_id/time_hash
- work_dir = os.path.join(
- user_dir,
- str(message.session_id),
- datetime.now().strftime("%Y%m%d_%H-%M-%S"),
- )
- os.makedirs(work_dir, exist_ok=True)
-
- # if no flow config is provided, use the default
- if workflow is None:
- raise ValueError("Workflow must be specified")
-
- workflow_manager = WorkflowManager(
- workflow=workflow,
- history=history,
- work_dir=work_dir,
- send_message_function=self.send,
- a_send_message_function=self.a_send,
- connection_id=connection_id,
- )
-
- message_text = message.content.strip()
- result_message: Message = workflow_manager.run(message=f"{message_text}", clear_history=False, history=history)
-
- result_message.user_id = message.user_id
- result_message.session_id = message.session_id
- return result_message
-
- async def a_chat(
- self,
- message: Message,
- history: List[Dict[str, Any]],
- workflow: Any = None,
- connection_id: Optional[str] = None,
- user_dir: Optional[str] = None,
- **kwargs,
- ) -> Message:
- """
- Processes an incoming message according to the agent's workflow configuration
- and generates a response.
-
- :param message: An instance of `Message` representing an incoming message.
- :param history: A list of dictionaries, each representing a past interaction.
- :param flow_config: An instance of `AgentWorkFlowConfig`. If None, defaults to a standard configuration.
- :param connection_id: An optional connection identifier.
- :param kwargs: Additional keyword arguments.
- :return: An instance of `Message` representing a response.
- """
-
- # create a working director for workflow based on user_dir/session_id/time_hash
- work_dir = os.path.join(
- user_dir,
- str(message.session_id),
- datetime.now().strftime("%Y%m%d_%H-%M-%S"),
- )
- os.makedirs(work_dir, exist_ok=True)
-
- # if no flow config is provided, use the default
- if workflow is None:
- raise ValueError("Workflow must be specified")
-
- workflow_manager = WorkflowManager(
- workflow=workflow,
- history=history,
- work_dir=work_dir,
- send_message_function=self.send,
- a_send_message_function=self.a_send,
- a_human_input_function=self.a_prompt_for_input,
- a_human_input_timeout=self.a_human_input_timeout,
- connection_id=connection_id,
- )
-
- message_text = message.content.strip()
- result_message: Message = await workflow_manager.a_run(
- message=f"{message_text}", clear_history=False, history=history
- )
-
- result_message.user_id = message.user_id
- result_message.session_id = message.session_id
- return result_message
|