From 7093cfd0919b15c8c1e99aa717bcd6a97a4c41ba Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 28 May 2024 08:09:35 -0400 Subject: [PATCH 01/13] First pass: message loop in main thread --- samples/apps/cap/py/autogencap/Actor.py | 93 +++++++++++-------- .../cap/py/autogencap/ComponentEnsemble.py | 7 +- .../apps/cap/py/autogencap/DirectorySvc.py | 2 +- .../cap/py/autogencap/ag_adapter/AGActor.py | 4 +- samples/apps/cap/py/demo/App.py | 4 + samples/apps/cap/py/demo/AppAgents.py | 3 +- samples/apps/cap/py/demo/SimpleActorDemo.py | 9 +- samples/apps/cap/py/demo/single_threaded.py | 37 ++++++++ 8 files changed, 102 insertions(+), 57 deletions(-) create mode 100644 samples/apps/cap/py/demo/single_threaded.py diff --git a/samples/apps/cap/py/autogencap/Actor.py b/samples/apps/cap/py/autogencap/Actor.py index 87c3d7ea8c2e..6961b1dcaa4e 100644 --- a/samples/apps/cap/py/autogencap/Actor.py +++ b/samples/apps/cap/py/autogencap/Actor.py @@ -1,19 +1,17 @@ import threading -import time import traceback - import zmq - from .Config import xpub_url from .DebugLog import Debug, Error, Info class Actor: - def __init__(self, agent_name: str, description: str): + def __init__(self, agent_name: str, description: str, start_thread: bool = True): self.actor_name: str = agent_name self.agent_description: str = description self.run = False self._start_event = threading.Event() + self._start_thread = start_thread def on_connect(self, network): Debug(self.actor_name, f"is connecting to {network}") @@ -27,37 +25,50 @@ def on_bin_msg(self, msg: bytes, msg_type: str, receiver: str, sender: str) -> b Info(self.actor_name, f"Msg: receiver=[{receiver}], msg_type=[{msg_type}]") return True - def _recv_thread(self): + def _msg_loop_init(self): + Debug(self.actor_name, "recv thread started") + self._socket: zmq.Socket = self._context.socket(zmq.SUB) + self._socket.setsockopt(zmq.RCVTIMEO, 500) + self._socket.connect(xpub_url) + str_topic = f"{self.actor_name}" + Debug(self.actor_name, f"subscribe to: {str_topic}") + self._socket.setsockopt_string(zmq.SUBSCRIBE, f"{str_topic}") + self._start_event.set() + + def get_message(self): try: - Debug(self.actor_name, "recv thread started") - self._socket: zmq.Socket = self._context.socket(zmq.SUB) - self._socket.setsockopt(zmq.RCVTIMEO, 500) - self._socket.connect(xpub_url) - str_topic = f"{self.actor_name}" - Debug(self.actor_name, f"subscribe to: {str_topic}") - self._socket.setsockopt_string(zmq.SUBSCRIBE, f"{str_topic}") - self._start_event.set() + topic, msg_type, sender_topic, msg = self._socket.recv_multipart() + topic = topic.decode("utf-8") # Convert bytes to string + msg_type = msg_type.decode("utf-8") # Convert bytes to string + sender_topic = sender_topic.decode("utf-8") # Convert bytes to string + except zmq.Again: + return None # No message received, continue to next iteration + except Exception as e: + Error(self.actor_name, f"recv thread encountered an error: {e}") + traceback.print_exc() + return None + return topic, msg_type, sender_topic, msg + + def dispatch_message(self, message): + if message is None: + return + topic, msg_type, sender_topic, msg = message + if msg_type == "text": + msg = msg.decode("utf-8") # Convert bytes to string + if not self.on_txt_msg(msg, msg_type, topic, sender_topic): + msg = "quit" + if msg.lower() == "quit": + self.run = False + else: + if not self.on_bin_msg(msg, msg_type, topic, sender_topic): + self.run = False + + def _msg_loop(self): + try: + self._msg_loop_init() while self.run: - try: - topic, msg_type, sender_topic, msg = self._socket.recv_multipart() - topic = topic.decode("utf-8") # Convert bytes to string - msg_type = msg_type.decode("utf-8") # Convert bytes to string - sender_topic = sender_topic.decode("utf-8") # Convert bytes to string - except zmq.Again: - continue # No message received, continue to next iteration - except Exception as e: - Error(self.actor_name, f"recv thread encountered an error: {e}") - traceback.print_exc() - continue - if msg_type == "text": - msg = msg.decode("utf-8") # Convert bytes to string - if not self.on_txt_msg(msg, msg_type, topic, sender_topic): - msg = "quit" - if msg.lower() == "quit": - break - else: - if not self.on_bin_msg(msg, msg_type, topic, sender_topic): - break + message = self.get_message() + self.dispatch_message(message) except Exception as e: Debug(self.actor_name, f"recv thread encountered an error: {e}") traceback.print_exc() @@ -68,12 +79,15 @@ def _recv_thread(self): self._start_event.set() Debug(self.actor_name, "recv thread ended") - def start(self, context: zmq.Context): + def on_start(self, context: zmq.Context): self._context = context self.run: bool = True - self._thread = threading.Thread(target=self._recv_thread) - self._thread.start() - self._start_event.wait() + if self._start_thread: + self._thread = threading.Thread(target=self._msg_loop) + self._thread.start() + self._start_event.wait() + else: + self._msg_loop_init() def disconnect_network(self, network): Debug(self.actor_name, f"is disconnecting from {network}") @@ -82,6 +96,7 @@ def disconnect_network(self, network): def stop(self): self.run = False - self._thread.join() + if self._start_thread: + self._thread.join() self._socket.setsockopt(zmq.LINGER, 0) - self._socket.close() + self._socket.close() \ No newline at end of file diff --git a/samples/apps/cap/py/autogencap/ComponentEnsemble.py b/samples/apps/cap/py/autogencap/ComponentEnsemble.py index 3c726bcb2d17..4bba27603b2b 100644 --- a/samples/apps/cap/py/autogencap/ComponentEnsemble.py +++ b/samples/apps/cap/py/autogencap/ComponentEnsemble.py @@ -1,8 +1,6 @@ import time from typing import List - import zmq - from .Actor import Actor from .ActorConnector import ActorConnector from .Broker import Broker @@ -11,9 +9,6 @@ from .DirectorySvc import DirectorySvc from .proto.CAP_pb2 import ActorInfo, ActorInfoCollection -# TODO: remove time import - - class ComponentEnsemble: def __init__(self, name: str = "Local Actor Network", start_broker: bool = True): self.local_actors = {} @@ -43,7 +38,7 @@ def register(self, actor: Actor): # that we can look up the actor by name self._directory_svc.register_actor_by_name(actor.actor_name) self.local_actors[actor.actor_name] = actor - actor.start(self._context) + actor.on_start(self._context) Debug("Local_Actor_Network", f"{actor.actor_name} registered in the network.") def connect(self): diff --git a/samples/apps/cap/py/autogencap/DirectorySvc.py b/samples/apps/cap/py/autogencap/DirectorySvc.py index 66ff07f5f03b..acb3b6223df5 100644 --- a/samples/apps/cap/py/autogencap/DirectorySvc.py +++ b/samples/apps/cap/py/autogencap/DirectorySvc.py @@ -121,7 +121,7 @@ def start(self): self._directory_connector = ActorConnector(self._context, Directory_Svc_Topic) if self._no_other_directory(): self._directory_actor = DirectoryActor(Directory_Svc_Topic, "Directory Service") - self._directory_actor.start(self._context) + self._directory_actor.on_start(self._context) Info("DirectorySvc", "Directory service started.") else: Info("DirectorySvc", "Another directory service is running. This instance will not start.") diff --git a/samples/apps/cap/py/autogencap/ag_adapter/AGActor.py b/samples/apps/cap/py/autogencap/ag_adapter/AGActor.py index fd14a88056dc..cc301f38e7e7 100644 --- a/samples/apps/cap/py/autogencap/ag_adapter/AGActor.py +++ b/samples/apps/cap/py/autogencap/ag_adapter/AGActor.py @@ -6,8 +6,8 @@ class AGActor(Actor): - def start(self, context: zmq.Context): - super().start(context) + def on_start(self, context: zmq.Context): + super().on_start(context) str_topic = Termination_Topic Debug(self.actor_name, f"subscribe to: {str_topic}") self._socket.setsockopt_string(zmq.SUBSCRIBE, f"{str_topic}") diff --git a/samples/apps/cap/py/demo/App.py b/samples/apps/cap/py/demo/App.py index 8af8c97b0e5a..19987ab75ca1 100644 --- a/samples/apps/cap/py/demo/App.py +++ b/samples/apps/cap/py/demo/App.py @@ -15,6 +15,7 @@ from list_agents import list_agents from RemoteAGDemo import remote_ag_demo from SimpleActorDemo import simple_actor_demo +from single_threaded import single_threaded_demo #################################################################################################### @@ -46,6 +47,7 @@ def main(): print("4. AutoGen GroupChat") print("5. AutoGen Agents in different processes") print("6. List Actors in CAP (Registry)") + print("7. Agent loop in main thread (no background thread for Agent)") choice = input("Enter your choice (1-6): ") if choice == "1": @@ -64,6 +66,8 @@ def main(): remote_ag_demo() elif choice == "6": list_agents() + elif choice == "7": + single_threaded_demo() else: print("Quitting...") break diff --git a/samples/apps/cap/py/demo/AppAgents.py b/samples/apps/cap/py/demo/AppAgents.py index d2a11e4e3823..bed163a293ee 100644 --- a/samples/apps/cap/py/demo/AppAgents.py +++ b/samples/apps/cap/py/demo/AppAgents.py @@ -17,10 +17,11 @@ class GreeterAgent(Actor): def __init__( self, + start_thread=True, agent_name="Greeter", description="This is the greeter agent, who knows how to greet people.", ): - super().__init__(agent_name, description) + super().__init__(agent_name, description, start_thread=start_thread) class FidelityAgent(Actor): diff --git a/samples/apps/cap/py/demo/SimpleActorDemo.py b/samples/apps/cap/py/demo/SimpleActorDemo.py index 0e60e0daeaab..0bdde6f4127f 100644 --- a/samples/apps/cap/py/demo/SimpleActorDemo.py +++ b/samples/apps/cap/py/demo/SimpleActorDemo.py @@ -17,12 +17,5 @@ def simple_actor_demo(): ensemble.register(agent) ensemble.connect() greeter_link = ensemble.find_by_name("Greeter") - ensemble.disconnect() - - ping = Ping() - # Serialize and send the message - msg_type_str = Ping.__name__ - msg_bytes = ping.SerializeToString() greeter_link.send_txt_msg("Hello World!") - greeter_link.send_bin_msg(msg_type_str, msg_bytes) - _, resp_type, resp_msg_bytes = greeter_link.send_recv_msg(msg_type_str, msg_bytes) + ensemble.disconnect() diff --git a/samples/apps/cap/py/demo/single_threaded.py b/samples/apps/cap/py/demo/single_threaded.py new file mode 100644 index 000000000000..8967f513e1a4 --- /dev/null +++ b/samples/apps/cap/py/demo/single_threaded.py @@ -0,0 +1,37 @@ +import _paths + +from AppAgents import GreeterAgent +from autogencap.ComponentEnsemble import ComponentEnsemble +from autogencap.DebugLog import Error +from autogencap.proto.CAP_pb2 import Ping + + +def single_threaded_demo(): + """ + Demonstrates the usage of the CAP platform by registering an actor, connecting to the actor, + sending a message, and performing cleanup operations. + """ + # CAP Platform + ensemble = ComponentEnsemble() + agent = GreeterAgent(start_thread=False) + ensemble.register(agent) + ensemble.connect() + greeter_link = ensemble.find_by_name("Greeter") + greeter_link.send_txt_msg("Hello World!") + + no_msg = 0 + while no_msg < 5: + message = agent.get_message() + agent.dispatch_message(message) + if message is None: no_msg += 1 + + message = agent.get_message() + agent.dispatch_message(message) + + ensemble.disconnect() + +def main(): + single_threaded_demo() + +if __name__ == "__main__": + main() \ No newline at end of file From 76402f476b0f9e470861b0d1097cca1c0855d774 Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 28 May 2024 08:13:16 -0400 Subject: [PATCH 02/13] pypi version bump --- samples/apps/cap/py/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/apps/cap/py/pyproject.toml b/samples/apps/cap/py/pyproject.toml index c52a59a0950f..8988604a334f 100644 --- a/samples/apps/cap/py/pyproject.toml +++ b/samples/apps/cap/py/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "autogencap_rajan.jedi" -version = "0.0.9" +version = "0.0.10" authors = [ { name="Rajan Chari", email="rajan.jedi@gmail.com" }, ] From a71ea23fdff09ae0689199361b58177c332ecd78 Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 28 May 2024 09:20:45 -0400 Subject: [PATCH 03/13] Fix readme --- samples/apps/cap/py/README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/samples/apps/cap/py/README.md b/samples/apps/cap/py/README.md index e11fa3d048fc..e6c989df3bb5 100644 --- a/samples/apps/cap/py/README.md +++ b/samples/apps/cap/py/README.md @@ -15,19 +15,20 @@ AutoGen is about Agents and Agent Orchestration. CAP extends AutoGen to allows Actors can register themselves with CAP, find other agents, construct arbitrary graphs, send and receive messages independently and many, many, many other things. ```python - # CAP Platform - network = LocalActorNetwork() + ensemble = ComponentEnsemble() + # Create an agent + agent = GreeterAgent() # Register an agent - network.register(GreeterAgent()) - # Tell agents to connect to other agents - network.connect() + ensemble.register(agent) # start message processing + # call on_connect() on all Agents + ensemble.connect() # Get a channel to the agent - greeter_link = network.lookup_agent("Greeter") - # Send a message to the agent + greeter_link = ensemble.find_by_name("Greeter") + Send a message to the agent greeter_link.send_txt_msg("Hello World!") # Cleanup greeter_link.close() - network.disconnect() + ensemble.disconnect() ``` ### Check out other demos in the `py/demo` directory. We show the following: ### 1) Hello World shown above From 5ddae51479992f257e9eedb2e4ace80cbf9dadc4 Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 28 May 2024 11:46:26 -0400 Subject: [PATCH 04/13] Better example --- samples/apps/cap/py/README.md | 50 ++++++++++++++------- samples/apps/cap/py/demo/SimpleActorDemo.py | 4 -- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/samples/apps/cap/py/README.md b/samples/apps/cap/py/README.md index e6c989df3bb5..f00d065b31b5 100644 --- a/samples/apps/cap/py/README.md +++ b/samples/apps/cap/py/README.md @@ -3,7 +3,7 @@ ## I just want to run the remote AutoGen agents! *Python Instructions (Windows, Linux, MacOS):* -pip install autogencap +pip install autogencap-rajan.jedi 1) AutoGen require OAI_CONFIG_LIST. AutoGen python requirements: 3.8 <= python <= 3.11 @@ -14,22 +14,40 @@ pip install autogencap AutoGen is about Agents and Agent Orchestration. CAP extends AutoGen to allows Agents to communicate via a message bus. CAP, therefore, deals with the space between these components. CAP is a message based, actor platform that allows actors to be composed into arbitrary graphs. Actors can register themselves with CAP, find other agents, construct arbitrary graphs, send and receive messages independently and many, many, many other things. + ```python - ensemble = ComponentEnsemble() - # Create an agent - agent = GreeterAgent() - # Register an agent - ensemble.register(agent) # start message processing - # call on_connect() on all Agents - ensemble.connect() - # Get a channel to the agent - greeter_link = ensemble.find_by_name("Greeter") - Send a message to the agent - greeter_link.send_txt_msg("Hello World!") - # Cleanup - greeter_link.close() - ensemble.disconnect() +# CAP Library +from autogencap.ComponentEnsemble import ComponentEnsemble +from autogencap.Actor import Actor + +# A simple Agent +class GreeterAgent(Actor): + def __init__(self): + super().__init__( + agent_name="Greeter", + description="This is the greeter agent, who knows how to greet people.") + + # Prints out the message it receives + def on_txt_msg(self, msg): + print(f"Greeter received: {msg}") + return "Greeter says: Hello!" + +ensemble = ComponentEnsemble() +# Create an agent +agent = GreeterAgent() +# Register an agent +ensemble.register(agent) # start message processing +# call on_connect() on all Agents +ensemble.connect() +# Get a channel to the agent +greeter_link = ensemble.find_by_name("Greeter") +#Send a message to the agent +greeter_link.send_txt_msg("Hello World!") +# Cleanup +greeter_link.close() +ensemble.disconnect() ``` + ### Check out other demos in the `py/demo` directory. We show the following: ### 1) Hello World shown above 2) Many CAP Actors interacting with each other @@ -37,4 +55,4 @@ Actors can register themselves with CAP, find other agents, construct arbitrary 4) CAP wrapped AutoGen Agents in a group chat 5) Two AutoGen Agents running in different processes and communicating through CAP 6) List all registered agents in CAP -7) AutoGen integration to list all registered agents +7) Run Agent in user supplied message loop diff --git a/samples/apps/cap/py/demo/SimpleActorDemo.py b/samples/apps/cap/py/demo/SimpleActorDemo.py index 0bdde6f4127f..f0f081a5d630 100644 --- a/samples/apps/cap/py/demo/SimpleActorDemo.py +++ b/samples/apps/cap/py/demo/SimpleActorDemo.py @@ -1,9 +1,5 @@ -import time - from AppAgents import GreeterAgent from autogencap.ComponentEnsemble import ComponentEnsemble -from autogencap.DebugLog import Error -from autogencap.proto.CAP_pb2 import Ping def simple_actor_demo(): From 27a2957e45d26a13fc3cedb362219fb53eed2ef6 Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 28 May 2024 14:01:52 -0400 Subject: [PATCH 05/13] Fixed docs --- samples/apps/cap/py/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/apps/cap/py/README.md b/samples/apps/cap/py/README.md index f00d065b31b5..88415226a018 100644 --- a/samples/apps/cap/py/README.md +++ b/samples/apps/cap/py/README.md @@ -30,7 +30,7 @@ class GreeterAgent(Actor): # Prints out the message it receives def on_txt_msg(self, msg): print(f"Greeter received: {msg}") - return "Greeter says: Hello!" + return True ensemble = ComponentEnsemble() # Create an agent From 7818ff1995be4e362cea4dd57d82a863b50b4909 Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 28 May 2024 18:28:36 -0400 Subject: [PATCH 06/13] pre-commit fixes --- samples/apps/cap/py/README.md | 2 +- samples/apps/cap/py/autogencap/Actor.py | 8 +++++--- .../apps/cap/py/autogencap/ComponentEnsemble.py | 3 +++ samples/apps/cap/py/demo/single_threaded.py | 14 ++++++++------ 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/samples/apps/cap/py/README.md b/samples/apps/cap/py/README.md index 88415226a018..a885e001e155 100644 --- a/samples/apps/cap/py/README.md +++ b/samples/apps/cap/py/README.md @@ -26,7 +26,7 @@ class GreeterAgent(Actor): super().__init__( agent_name="Greeter", description="This is the greeter agent, who knows how to greet people.") - + # Prints out the message it receives def on_txt_msg(self, msg): print(f"Greeter received: {msg}") diff --git a/samples/apps/cap/py/autogencap/Actor.py b/samples/apps/cap/py/autogencap/Actor.py index 6961b1dcaa4e..778fd7634c21 100644 --- a/samples/apps/cap/py/autogencap/Actor.py +++ b/samples/apps/cap/py/autogencap/Actor.py @@ -1,6 +1,8 @@ import threading import traceback + import zmq + from .Config import xpub_url from .DebugLog import Debug, Error, Info @@ -48,7 +50,7 @@ def get_message(self): traceback.print_exc() return None return topic, msg_type, sender_topic, msg - + def dispatch_message(self, message): if message is None: return @@ -62,7 +64,7 @@ def dispatch_message(self, message): else: if not self.on_bin_msg(msg, msg_type, topic, sender_topic): self.run = False - + def _msg_loop(self): try: self._msg_loop_init() @@ -99,4 +101,4 @@ def stop(self): if self._start_thread: self._thread.join() self._socket.setsockopt(zmq.LINGER, 0) - self._socket.close() \ No newline at end of file + self._socket.close() diff --git a/samples/apps/cap/py/autogencap/ComponentEnsemble.py b/samples/apps/cap/py/autogencap/ComponentEnsemble.py index 4bba27603b2b..ebb31fb9aa7c 100644 --- a/samples/apps/cap/py/autogencap/ComponentEnsemble.py +++ b/samples/apps/cap/py/autogencap/ComponentEnsemble.py @@ -1,6 +1,8 @@ import time from typing import List + import zmq + from .Actor import Actor from .ActorConnector import ActorConnector from .Broker import Broker @@ -9,6 +11,7 @@ from .DirectorySvc import DirectorySvc from .proto.CAP_pb2 import ActorInfo, ActorInfoCollection + class ComponentEnsemble: def __init__(self, name: str = "Local Actor Network", start_broker: bool = True): self.local_actors = {} diff --git a/samples/apps/cap/py/demo/single_threaded.py b/samples/apps/cap/py/demo/single_threaded.py index 8967f513e1a4..43cffbf02c89 100644 --- a/samples/apps/cap/py/demo/single_threaded.py +++ b/samples/apps/cap/py/demo/single_threaded.py @@ -1,5 +1,4 @@ import _paths - from AppAgents import GreeterAgent from autogencap.ComponentEnsemble import ComponentEnsemble from autogencap.DebugLog import Error @@ -14,7 +13,7 @@ def single_threaded_demo(): # CAP Platform ensemble = ComponentEnsemble() agent = GreeterAgent(start_thread=False) - ensemble.register(agent) + ensemble.register(agent) ensemble.connect() greeter_link = ensemble.find_by_name("Greeter") greeter_link.send_txt_msg("Hello World!") @@ -23,15 +22,18 @@ def single_threaded_demo(): while no_msg < 5: message = agent.get_message() agent.dispatch_message(message) - if message is None: no_msg += 1 - + if message is None: + no_msg += 1 + message = agent.get_message() agent.dispatch_message(message) - + ensemble.disconnect() + def main(): single_threaded_demo() + if __name__ == "__main__": - main() \ No newline at end of file + main() From e132e069b77a9e27ddfb19cacd69f48ec746ab64 Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 25 Jun 2024 14:24:23 -0400 Subject: [PATCH 07/13] Convenience methods for protobufs --- samples/apps/cap/py/autogencap/ActorConnector.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/samples/apps/cap/py/autogencap/ActorConnector.py b/samples/apps/cap/py/autogencap/ActorConnector.py index 588d4c463b62..1595f641fc83 100644 --- a/samples/apps/cap/py/autogencap/ActorConnector.py +++ b/samples/apps/cap/py/autogencap/ActorConnector.py @@ -120,6 +120,16 @@ def send_txt_msg(self, msg): def send_bin_msg(self, msg_type: str, msg): self._sender.send_bin_msg(msg_type, msg) + def send_proto_msg(self, msg): + bin_msg = msg.SerializeToString() + class_type = type(msg) + self._sender.send_bin_msg(class_type.__name__, bin_msg) + + def send_recv_proto_msg(self, msg, num_attempts=5): + bin_msg = msg.SerializeToString() + class_type = type(msg) + return self.send_recv_msg(class_type.__name, bin_msg, num_attempts) + def send_recv_msg(self, msg_type: str, msg, num_attempts=5): original_timeout: int = 0 if num_attempts == -1: From 4e670254dc631e7d10a0c3adbe3441716cda9bfc Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 25 Jun 2024 14:27:44 -0400 Subject: [PATCH 08/13] support non-color consoles --- samples/apps/cap/py/autogencap/DebugLog.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/samples/apps/cap/py/autogencap/DebugLog.py b/samples/apps/cap/py/autogencap/DebugLog.py index c3d6ca421276..f8a3f209ee3a 100644 --- a/samples/apps/cap/py/autogencap/DebugLog.py +++ b/samples/apps/cap/py/autogencap/DebugLog.py @@ -34,19 +34,25 @@ def WriteLog(self, level, context, msg): class ConsoleLogger(BaseLogger): - def __init__(self): + def __init__(self, use_color=True): super().__init__() + self._use_color = use_color + + def _colorize(self, msg, color): + if self._use_color: + return colored(msg, color) + return msg def WriteLog(self, level, context, msg): - timestamp = colored(datetime.datetime.now().strftime("%m/%d/%y %H:%M:%S"), "dark_grey") + timestamp = self._colorize(datetime.datetime.now().strftime("%m/%d/%y %H:%M:%S"), "dark_grey") # Translate level number to name and color - level_name = colored(LEVEL_NAMES[level], LEVEL_COLOR[level]) + level_name = self._colorize(LEVEL_NAMES[level], LEVEL_COLOR[level]) # Left justify the context and color it blue - context = colored(context.ljust(14), "blue") + context = self._colorize(context.ljust(14), "blue") # Left justify the threadid and color it blue - thread_id = colored(str(threading.get_ident()).ljust(5), "blue") + thread_id = self._colorize(str(threading.get_ident()).ljust(5), "blue") # color the msg based on the level - msg = colored(msg, LEVEL_COLOR[level]) + msg = self._colorize(msg, LEVEL_COLOR[level]) print(f"{thread_id} {timestamp} {level_name}: [{context}] {msg}") From c673456147feaac6e88e123b48ffa4841ef86cbc Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 25 Jun 2024 14:28:23 -0400 Subject: [PATCH 09/13] Non-color console and allow user input --- samples/apps/cap/py/demo/CAPAutoGenPairDemo.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py b/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py index 732bfecad17b..1741ff51af29 100644 --- a/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py +++ b/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py @@ -3,11 +3,15 @@ from autogencap.ag_adapter.CAPPair import CAPPair from autogencap.ComponentEnsemble import ComponentEnsemble from autogencap.DebugLog import Info +from autogencap.DebugLog import ConsoleLogger +import autogencap.DebugLog as DebugLog from autogen import AssistantAgent, UserProxyAgent, config_list_from_json def cap_ag_pair_demo(): + DebugLog.LOGGER = ConsoleLogger(use_color=False) + config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST") assistant = AssistantAgent("assistant", llm_config={"config_list": config_list}) user_proxy = UserProxyAgent( @@ -20,7 +24,10 @@ def cap_ag_pair_demo(): ensemble = ComponentEnsemble() pair = CAPPair(ensemble, user_proxy, assistant) - pair.initiate_chat("Plot a chart of MSFT daily closing prices for last 1 Month.") + user_cmd = "Plot a chart of MSFT daily closing prices for last 1 Month" + print(f"Default: {user_cmd}") + user_cmd = input("Enter a command: ") or user_cmd + pair.initiate_chat(user_cmd) # Wait for the pair to finish try: From daf55720488524afc0ee5ef0baec3687eb1525ec Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 25 Jun 2024 14:29:04 -0400 Subject: [PATCH 10/13] Minor update to single_threaded_demo --- samples/apps/cap/py/demo/single_threaded.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/samples/apps/cap/py/demo/single_threaded.py b/samples/apps/cap/py/demo/single_threaded.py index 43cffbf02c89..d95f67128e64 100644 --- a/samples/apps/cap/py/demo/single_threaded.py +++ b/samples/apps/cap/py/demo/single_threaded.py @@ -19,14 +19,19 @@ def single_threaded_demo(): greeter_link.send_txt_msg("Hello World!") no_msg = 0 + + # This is where we process the messages in this thread + # instead of using a separate thread + + # 5 consecutive times with no message received + # will break the loop while no_msg < 5: + # Get the message for the actor message = agent.get_message() + # Let the actor process the message agent.dispatch_message(message) - if message is None: - no_msg += 1 - - message = agent.get_message() - agent.dispatch_message(message) + # If no message is received, increment the counter otherwise reset it + no_msg = no_msg + 1 if message is None else 0 ensemble.disconnect() From 37dfb32764b9a24df74dcd1da3d3c0dcd6876327 Mon Sep 17 00:00:00 2001 From: Rajan Date: Tue, 25 Jun 2024 14:34:05 -0400 Subject: [PATCH 11/13] new pypi version --- samples/apps/cap/py/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/apps/cap/py/pyproject.toml b/samples/apps/cap/py/pyproject.toml index 8988604a334f..294f199cc913 100644 --- a/samples/apps/cap/py/pyproject.toml +++ b/samples/apps/cap/py/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "autogencap_rajan.jedi" -version = "0.0.10" +version = "0.0.11" authors = [ { name="Rajan Chari", email="rajan.jedi@gmail.com" }, ] From f970e22d631ab53c7ea1f53804502f40d9c30d1f Mon Sep 17 00:00:00 2001 From: Rajan Date: Fri, 12 Jul 2024 21:04:22 -0400 Subject: [PATCH 12/13] pre-commit fixes --- samples/apps/cap/py/demo/CAPAutoGenPairDemo.py | 5 ++--- samples/apps/cap/py/demo/single_threaded.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py b/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py index 1741ff51af29..00ff7a892878 100644 --- a/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py +++ b/samples/apps/cap/py/demo/CAPAutoGenPairDemo.py @@ -1,10 +1,9 @@ import time +import autogencap.DebugLog as DebugLog from autogencap.ag_adapter.CAPPair import CAPPair from autogencap.ComponentEnsemble import ComponentEnsemble -from autogencap.DebugLog import Info -from autogencap.DebugLog import ConsoleLogger -import autogencap.DebugLog as DebugLog +from autogencap.DebugLog import ConsoleLogger, Info from autogen import AssistantAgent, UserProxyAgent, config_list_from_json diff --git a/samples/apps/cap/py/demo/single_threaded.py b/samples/apps/cap/py/demo/single_threaded.py index 86bf7c3904c0..d95f67128e64 100644 --- a/samples/apps/cap/py/demo/single_threaded.py +++ b/samples/apps/cap/py/demo/single_threaded.py @@ -35,7 +35,7 @@ def single_threaded_demo(): ensemble.disconnect() - + def main(): single_threaded_demo() From ae1006703db2e6d061a09834aa88c79ca7720784 Mon Sep 17 00:00:00 2001 From: Rajan Date: Sat, 13 Jul 2024 00:44:46 -0400 Subject: [PATCH 13/13] change pypi name --- samples/apps/cap/py/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/apps/cap/py/pyproject.toml b/samples/apps/cap/py/pyproject.toml index 294f199cc913..8a0fe227e805 100644 --- a/samples/apps/cap/py/pyproject.toml +++ b/samples/apps/cap/py/pyproject.toml @@ -3,7 +3,7 @@ requires = ["hatchling"] build-backend = "hatchling.build" [project] -name = "autogencap_rajan.jedi" +name = "autogencap" version = "0.0.11" authors = [ { name="Rajan Chari", email="rajan.jedi@gmail.com" },