mirror of https://github.com/microsoft/autogen.git
make logging independent module
This commit is contained in:
parent
b0b0825c1d
commit
13c135100f
|
@ -5,12 +5,12 @@ from typing import List, Protocol
|
|||
from autogen_agentchat.agents._base_chat_agent import ChatMessage
|
||||
from autogen_core.application.logging import EVENT_LOGGER_NAME
|
||||
|
||||
from ._utils import AgentChatLogHandler
|
||||
from .logging import ConsoleLogHandler, EVENT_LOGGER_NAME
|
||||
|
||||
logger = logging.getLogger(EVENT_LOGGER_NAME + ".agentchatchat")
|
||||
logger = logging.getLogger(EVENT_LOGGER_NAME)
|
||||
logger.setLevel(logging.INFO)
|
||||
log_handler = AgentChatLogHandler(filename="log.jsonl")
|
||||
logger.handlers = [log_handler]
|
||||
console_handler = ConsoleLogHandler()
|
||||
logger.addHandler(console_handler)
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
|
@ -7,11 +7,11 @@ from autogen_core.base import AgentId, AgentType, MessageContext
|
|||
from autogen_core.components import DefaultTopicId, event
|
||||
from autogen_core.components.models import FunctionExecutionResult
|
||||
from autogen_core.components.tool_agent import ToolException
|
||||
from autogen_core.application.logging import EVENT_LOGGER_NAME
|
||||
|
||||
from ...agents import BaseChatAgent, MultiModalMessage, StopMessage, TextMessage, ToolCallMessage, ToolCallResultMessage
|
||||
from ._events import ContentPublishEvent, ContentRequestEvent
|
||||
from ._sequential_routed_agent import SequentialRoutedAgent
|
||||
from ..logging import EVENT_LOGGER_NAME
|
||||
|
||||
|
||||
class BaseChatAgentContainer(SequentialRoutedAgent):
|
||||
|
@ -31,7 +31,7 @@ class BaseChatAgentContainer(SequentialRoutedAgent):
|
|||
self._agent = agent
|
||||
self._message_buffer: List[TextMessage | MultiModalMessage | StopMessage] = []
|
||||
self._tool_agent_id = AgentId(type=tool_agent_type, key=self.id.key)
|
||||
self._logger = self.logger = logging.getLogger(EVENT_LOGGER_NAME + f".agentchatchat")
|
||||
self._logger = self.logger = logging.getLogger(EVENT_LOGGER_NAME)
|
||||
|
||||
@event
|
||||
async def handle_content_publish(self, message: ContentPublishEvent, ctx: MessageContext) -> None:
|
||||
|
|
|
@ -7,7 +7,7 @@ from autogen_core.components import event
|
|||
from ...agents import StopMessage, TextMessage, ChatMessage
|
||||
from ._events import ContentPublishEvent, ContentRequestEvent
|
||||
from ._sequential_routed_agent import SequentialRoutedAgent
|
||||
from autogen_core.application.logging import EVENT_LOGGER_NAME
|
||||
from ..logging import EVENT_LOGGER_NAME
|
||||
|
||||
|
||||
class BaseGroupChatManager(SequentialRoutedAgent):
|
||||
|
|
|
@ -55,12 +55,7 @@ class RoundRobinGroupChat(BaseTeam):
|
|||
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
participants: List[BaseChatAgent],
|
||||
*,
|
||||
tools: List[Tool] | None = None
|
||||
):
|
||||
def __init__(self, participants: List[BaseChatAgent], *, tools: List[Tool] | None = None):
|
||||
if len(participants) == 0:
|
||||
raise ValueError("At least one participant is required.")
|
||||
if len(participants) != len(set(participant.name for participant in participants)):
|
||||
|
@ -75,8 +70,7 @@ class RoundRobinGroupChat(BaseTeam):
|
|||
def _factory() -> BaseChatAgentContainer:
|
||||
id = AgentInstantiationContext.current_agent_id()
|
||||
assert id == AgentId(type=agent.name, key=self._team_id)
|
||||
container = BaseChatAgentContainer(
|
||||
parent_topic_type, agent, tool_agent_type)
|
||||
container = BaseChatAgentContainer(parent_topic_type, agent, tool_agent_type)
|
||||
assert container.id == id
|
||||
return container
|
||||
|
||||
|
@ -95,8 +89,7 @@ class RoundRobinGroupChat(BaseTeam):
|
|||
|
||||
# Register the tool agent.
|
||||
tool_agent_type = await ToolAgent.register(
|
||||
runtime, "tool_agent", lambda: ToolAgent(
|
||||
"Tool agent for round-robin group chat", self._tools)
|
||||
runtime, "tool_agent", lambda: ToolAgent("Tool agent for round-robin group chat", self._tools)
|
||||
)
|
||||
# No subscriptions are needed for the tool agent, which will be called via direct messages.
|
||||
|
||||
|
@ -109,8 +102,7 @@ class RoundRobinGroupChat(BaseTeam):
|
|||
topic_type = participant.name
|
||||
# Register the participant factory.
|
||||
await BaseChatAgentContainer.register(
|
||||
runtime, type=agent_type, factory=self._create_factory(
|
||||
group_topic_type, participant, tool_agent_type)
|
||||
runtime, type=agent_type, factory=self._create_factory(group_topic_type, participant, tool_agent_type)
|
||||
)
|
||||
# Add subscriptions for the participant.
|
||||
await runtime.add_subscription(TypeSubscription(topic_type=topic_type, agent_type=agent_type))
|
||||
|
@ -132,16 +124,13 @@ class RoundRobinGroupChat(BaseTeam):
|
|||
)
|
||||
# Add subscriptions for the group chat manager.
|
||||
await runtime.add_subscription(
|
||||
TypeSubscription(topic_type=group_chat_manager_topic_type,
|
||||
agent_type=group_chat_manager_agent_type.type)
|
||||
TypeSubscription(topic_type=group_chat_manager_topic_type, agent_type=group_chat_manager_agent_type.type)
|
||||
)
|
||||
await runtime.add_subscription(
|
||||
TypeSubscription(topic_type=group_topic_type,
|
||||
agent_type=group_chat_manager_agent_type.type)
|
||||
TypeSubscription(topic_type=group_topic_type, agent_type=group_chat_manager_agent_type.type)
|
||||
)
|
||||
await runtime.add_subscription(
|
||||
TypeSubscription(topic_type=team_topic_type,
|
||||
agent_type=group_chat_manager_agent_type.type)
|
||||
TypeSubscription(topic_type=team_topic_type, agent_type=group_chat_manager_agent_type.type)
|
||||
)
|
||||
|
||||
group_chat_messages: List[ChatMessage] = []
|
||||
|
@ -156,8 +145,7 @@ class RoundRobinGroupChat(BaseTeam):
|
|||
type="collect_group_chat_messages",
|
||||
closure=collect_group_chat_messages,
|
||||
subscriptions=lambda: [
|
||||
TypeSubscription(topic_type=group_topic_type,
|
||||
agent_type="collect_group_chat_messages")
|
||||
TypeSubscription(topic_type=group_topic_type, agent_type="collect_group_chat_messages")
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -166,11 +154,9 @@ class RoundRobinGroupChat(BaseTeam):
|
|||
|
||||
# Run the team by publishing the task to the team topic and then requesting the result.
|
||||
team_topic_id = TopicId(type=team_topic_type, source=self._team_id)
|
||||
group_chat_manager_topic_id = TopicId(
|
||||
type=group_chat_manager_topic_type, source=self._team_id)
|
||||
group_chat_manager_topic_id = TopicId(type=group_chat_manager_topic_type, source=self._team_id)
|
||||
await runtime.publish_message(
|
||||
ContentPublishEvent(agent_message=TextMessage(
|
||||
content=task, source="user")),
|
||||
ContentPublishEvent(agent_message=TextMessage(content=task, source="user")),
|
||||
topic_id=team_topic_id,
|
||||
)
|
||||
await runtime.publish_message(ContentRequestEvent(), topic_id=group_chat_manager_topic_id)
|
||||
|
|
|
@ -2,7 +2,7 @@ from datetime import datetime
|
|||
import json
|
||||
import logging
|
||||
import sys
|
||||
from typing import Optional, Union, List, Dict, Any, Sequence
|
||||
from typing import Union, List, Dict, Any, Sequence
|
||||
from dataclasses import asdict, is_dataclass
|
||||
|
||||
from .group_chat._events import ContentPublishEvent
|
||||
|
@ -10,56 +10,11 @@ from ..agents import ChatMessage, TextMessage, MultiModalMessage, ToolCallMessag
|
|||
from autogen_core.components import FunctionCall, Image
|
||||
from autogen_core.components.models import FunctionExecutionResult
|
||||
|
||||
ContentType = Union[str, List[Union[str, Image]],
|
||||
List[FunctionCall], List[FunctionExecutionResult]]
|
||||
EVENT_LOGGER_NAME = "autogen_agentchat.events"
|
||||
ContentType = Union[str, List[Union[str, Image]], List[FunctionCall], List[FunctionExecutionResult]]
|
||||
|
||||
|
||||
class AgentChatLogHandler(logging.Handler):
|
||||
def __init__(self, filename: Optional[str] = None) -> None:
|
||||
super().__init__()
|
||||
self.filename = filename
|
||||
self.file_handler: Optional[logging.FileHandler] = None
|
||||
if filename:
|
||||
self.file_handler = logging.FileHandler(filename)
|
||||
|
||||
def emit(self, record: logging.LogRecord) -> None:
|
||||
try:
|
||||
ts = datetime.fromtimestamp(record.created).isoformat()
|
||||
if isinstance(record.msg, ContentPublishEvent):
|
||||
console_message = (
|
||||
f"\n{'-'*75} \n"
|
||||
f"\033[91m[{ts}], {record.msg.agent_message.source}:\033[0m\n"
|
||||
f"\n{self.serialize_content(record.msg.agent_message.content)}"
|
||||
)
|
||||
# print , flush true
|
||||
sys.stdout.write(console_message)
|
||||
|
||||
log_entry = json.dumps(
|
||||
{
|
||||
"timestamp": ts,
|
||||
"source": record.msg.agent_message.source,
|
||||
"message": self.serialize_content(record.msg.agent_message.content),
|
||||
"type": "OrchestrationEvent",
|
||||
},
|
||||
default=self.json_serializer,
|
||||
)
|
||||
|
||||
if self.file_handler:
|
||||
file_record = logging.LogRecord(
|
||||
name=record.name,
|
||||
level=record.levelno,
|
||||
pathname=record.pathname,
|
||||
lineno=record.lineno,
|
||||
msg=log_entry,
|
||||
args=(),
|
||||
exc_info=record.exc_info,
|
||||
)
|
||||
self.file_handler.emit(file_record)
|
||||
else:
|
||||
sys.stderr.write(log_entry)
|
||||
except Exception:
|
||||
self.handleError(record)
|
||||
|
||||
class BaseLogHandler(logging.Handler):
|
||||
def serialize_content(
|
||||
self, content: Union[ContentType, Sequence[ChatMessage], ChatMessage]
|
||||
) -> Union[List[Any], Dict[str, Any], str]:
|
||||
|
@ -83,7 +38,56 @@ class AgentChatLogHandler(logging.Handler):
|
|||
return str(obj)
|
||||
return str(obj)
|
||||
|
||||
|
||||
class ConsoleLogHandler(BaseLogHandler):
|
||||
def emit(self, record: logging.LogRecord) -> None:
|
||||
try:
|
||||
ts = datetime.fromtimestamp(record.created).isoformat()
|
||||
if isinstance(record.msg, ContentPublishEvent):
|
||||
console_message = (
|
||||
f"\n{'-'*75} \n"
|
||||
f"\033[91m[{ts}], {record.msg.agent_message.source}:\033[0m\n"
|
||||
f"\n{self.serialize_content(record.msg.agent_message.content)}"
|
||||
)
|
||||
sys.stdout.write(console_message)
|
||||
sys.stdout.flush()
|
||||
except Exception:
|
||||
self.handleError(record)
|
||||
|
||||
|
||||
class FileLogHandler(BaseLogHandler):
|
||||
def __init__(self, filename: str) -> None:
|
||||
super().__init__()
|
||||
self.filename = filename
|
||||
self.file_handler = logging.FileHandler(filename)
|
||||
|
||||
def emit(self, record: logging.LogRecord) -> None:
|
||||
try:
|
||||
ts = datetime.fromtimestamp(record.created).isoformat()
|
||||
if isinstance(record.msg, ContentPublishEvent):
|
||||
log_entry = json.dumps(
|
||||
{
|
||||
"timestamp": ts,
|
||||
"source": record.msg.agent_message.source,
|
||||
"message": self.serialize_content(record.msg.agent_message.content),
|
||||
"type": "OrchestrationEvent",
|
||||
},
|
||||
default=self.json_serializer,
|
||||
)
|
||||
|
||||
file_record = logging.LogRecord(
|
||||
name=record.name,
|
||||
level=record.levelno,
|
||||
pathname=record.pathname,
|
||||
lineno=record.lineno,
|
||||
msg=log_entry,
|
||||
args=(),
|
||||
exc_info=record.exc_info,
|
||||
)
|
||||
self.file_handler.emit(file_record)
|
||||
except Exception:
|
||||
self.handleError(record)
|
||||
|
||||
def close(self) -> None:
|
||||
if self.file_handler:
|
||||
self.file_handler.close()
|
||||
super().close()
|
Loading…
Reference in New Issue