Skip to content

Commit 69b06b3

Browse files
zshanhuifengju0213JINO-ROHIT
authored
update WorkforceLogger with log_message (#3485)
Co-authored-by: Tao Sun <[email protected]> Co-authored-by: JINO ROHIT <[email protected]>
1 parent 895d0d7 commit 69b06b3

File tree

5 files changed

+95
-10
lines changed

5 files changed

+95
-10
lines changed

camel/societies/workforce/events.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
class WorkforceEventBase(BaseModel):
2323
model_config = ConfigDict(frozen=True, extra='forbid')
2424
event_type: Literal[
25+
"log",
2526
"task_decomposed",
2627
"task_created",
2728
"task_assigned",
@@ -39,6 +40,25 @@ class WorkforceEventBase(BaseModel):
3940
)
4041

4142

43+
class LogEvent(WorkforceEventBase):
44+
event_type: Literal["log"] = "log"
45+
message: str
46+
level: Literal["debug", "info", "warning", "error", "critical"]
47+
color: (
48+
Literal[
49+
"red",
50+
"green",
51+
"yellow",
52+
"blue",
53+
"cyan",
54+
"magenta",
55+
"gray",
56+
"black",
57+
]
58+
| None
59+
) = None
60+
61+
4262
class WorkerCreatedEvent(WorkforceEventBase):
4363
event_type: Literal["worker_created"] = "worker_created"
4464
worker_id: str
@@ -109,6 +129,7 @@ class QueueStatusEvent(WorkforceEventBase):
109129

110130

111131
WorkforceEvent = Union[
132+
LogEvent,
112133
TaskDecomposedEvent,
113134
TaskCreatedEvent,
114135
TaskAssignedEvent,

camel/societies/workforce/workforce.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797

9898
from .events import (
9999
AllTasksCompletedEvent,
100+
LogEvent,
100101
TaskAssignedEvent,
101102
TaskCompletedEvent,
102103
TaskCreatedEvent,
@@ -3880,10 +3881,17 @@ async def _post_task(self, task: Task, assignee_id: str) -> None:
38803881
logger.error(
38813882
f"Failed to post task {task.id} to {assignee_id}: {e}"
38823883
)
3883-
print(
3884-
f"{Fore.RED}Failed to post task {task.id} to {assignee_id}: "
3885-
f"{e}{Fore.RESET}"
3886-
)
3884+
for cb in self._callbacks:
3885+
cb.log_message(
3886+
LogEvent(
3887+
message=(
3888+
f"Failed to post task {task.id} to {assignee_id}: "
3889+
f"{e}"
3890+
),
3891+
level="error",
3892+
color="red",
3893+
)
3894+
)
38873895

38883896
async def _post_dependency(self, dependency: Task) -> None:
38893897
await self._channel.post_dependency(dependency, self.node_id)
@@ -4010,7 +4018,12 @@ async def _create_worker_node_for_task(self, task: Task) -> Worker:
40104018
)
40114019
new_node.set_channel(self._channel)
40124020

4013-
print(f"{Fore.CYAN}{new_node} created.{Fore.RESET}")
4021+
for cb in self._callbacks:
4022+
cb.log_message(
4023+
LogEvent(
4024+
message=f"{new_node} created.", level="info", color="cyan"
4025+
)
4026+
)
40144027

40154028
self._children.append(new_node)
40164029

@@ -4657,10 +4670,17 @@ async def _handle_completed_task(self, task: Task) -> None:
46574670
tasks_list.pop(i)
46584671
self._pending_tasks = deque(tasks_list)
46594672
found_and_removed = True
4660-
print(
4661-
f"{Fore.GREEN}✅ Task {task.id} completed and removed "
4662-
f"from queue.{Fore.RESET}"
4663-
)
4673+
for cb in self._callbacks:
4674+
cb.log_message(
4675+
LogEvent(
4676+
message=(
4677+
f"✅ Task {task.id} completed and removed "
4678+
f"from queue."
4679+
),
4680+
level="info",
4681+
color="green",
4682+
)
4683+
)
46644684
break
46654685

46664686
if not found_and_removed:

camel/societies/workforce/workforce_callback.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@
1313
# ========= Copyright 2023-2025 @ CAMEL-AI.org. All Rights Reserved. =========
1414
from __future__ import annotations
1515

16+
import typing
1617
from abc import ABC, abstractmethod
1718

19+
from colorama import Fore
20+
1821
from .events import (
1922
AllTasksCompletedEvent,
23+
LogEvent,
2024
TaskAssignedEvent,
2125
TaskCompletedEvent,
2226
TaskCreatedEvent,
@@ -34,6 +38,30 @@ class WorkforceCallback(ABC):
3438
Implementations should persist or stream events as appropriate.
3539
"""
3640

41+
__COLOR_MAP: typing.ClassVar = {
42+
"yellow": Fore.YELLOW,
43+
"red": Fore.RED,
44+
"green": Fore.GREEN,
45+
"cyan": Fore.CYAN,
46+
"magenta": Fore.MAGENTA,
47+
"gray": Fore.LIGHTBLACK_EX,
48+
"black": Fore.BLACK,
49+
}
50+
51+
def _get_color_message(self, event: LogEvent) -> str:
52+
r"""Gets a colored message for a log event."""
53+
if event.color is None or event.color not in self.__COLOR_MAP:
54+
return event.message
55+
color = self.__COLOR_MAP.get(event.color)
56+
return f"{color}{event.message}{Fore.RESET}"
57+
58+
@abstractmethod
59+
def log_message(
60+
self,
61+
event: LogEvent,
62+
) -> None:
63+
pass
64+
3765
@abstractmethod
3866
def log_task_created(
3967
self,

camel/societies/workforce/workforce_logger.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from camel.logger import get_logger
1919
from camel.societies.workforce.events import (
2020
AllTasksCompletedEvent,
21+
LogEvent,
2122
QueueStatusEvent,
2223
TaskAssignedEvent,
2324
TaskCompletedEvent,
@@ -50,6 +51,11 @@ def __init__(self, workforce_id: str):
5051
self._worker_information: Dict[str, Dict[str, Any]] = {}
5152
self._initial_worker_logs: List[Dict[str, Any]] = []
5253

54+
def log_message(self, event: LogEvent) -> None:
55+
r"""Logs a message to the console with color."""
56+
colored_message = self._get_color_message(event)
57+
print(colored_message)
58+
5359
def _log_event(self, event_type: str, **kwargs: Any) -> None:
5460
r"""Internal method to create and store a log entry.
5561

examples/workforce/workforce_callbacks_example.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from camel.models import ModelFactory
2828
from camel.societies.workforce.events import (
2929
AllTasksCompletedEvent,
30+
LogEvent,
3031
TaskAssignedEvent,
3132
TaskCompletedEvent,
3233
TaskCreatedEvent,
@@ -38,6 +39,7 @@
3839
)
3940
from camel.societies.workforce.workforce import Workforce
4041
from camel.societies.workforce.workforce_callback import WorkforceCallback
42+
from camel.societies.workforce.workforce_logger import WorkforceLogger
4143
from camel.types import ModelPlatformType, ModelType
4244

4345
logger = get_logger(__name__)
@@ -46,6 +48,12 @@
4648
class PrintCallback(WorkforceCallback):
4749
r"""Simple callback printing events to logs to observe ordering."""
4850

51+
def log_message(self, event: LogEvent) -> None:
52+
print(
53+
f"[PrintCallback] {event.message} level={event.level}, "
54+
f"color={event.color}"
55+
)
56+
4957
def log_task_created(self, event: TaskCreatedEvent) -> None:
5058
print(
5159
f"[PrintCallback] task_created: id={event.task_id}, "
@@ -115,7 +123,9 @@ def build_student_agent() -> ChatAgent:
115123

116124

117125
async def run_demo() -> None:
118-
callbacks = [PrintCallback()]
126+
logger_cb = WorkforceLogger('demo-logger')
127+
print_cb = PrintCallback()
128+
callbacks = [logger_cb, print_cb]
119129

120130
workforce = Workforce(
121131
"Workforce Callbacks Demo",

0 commit comments

Comments
 (0)