Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CAP] [Feature] Get list of actors from directory service. #2073

Merged
merged 22 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
f8417af
Search directory for list of actors using regex '.*' gets all actors
rajan-chari Mar 18, 2024
3b7d95a
docs changes
rajan-chari Mar 19, 2024
a6cd5ac
pre-commit fixes
rajan-chari Mar 19, 2024
3055b78
Use ActorInfo from protobuf
rajan-chari Mar 19, 2024
5858a9c
Merge branch 'main' into rajan/list-actors
rajan-chari Mar 19, 2024
2c79561
Merge branch 'main' into rajan/list-actors
rajan-chari Mar 19, 2024
bed19d7
pre-commit
rajan-chari Mar 19, 2024
588e4b7
Merge branch 'main' into rajan/list-actors
rajan-chari Mar 19, 2024
8963331
Merge branch 'main' into rajan/list-actors
rajan-chari Mar 21, 2024
603804e
Added zmq tests to work on removing sleeps
rajan-chari Mar 25, 2024
11019dd
Merge branch 'rajan/list-actors' of https://github.com/rajan-chari/au…
rajan-chari Mar 25, 2024
16c7b93
minor refactor of zmq tests
rajan-chari Mar 26, 2024
cd35cb1
1) Change DirSvr to user Broker. 2) Add req-router to broker 3) In A…
rajan-chari Mar 26, 2024
5b2b727
1) Change DirSvr to user Broker. 2) Add req-router to broker 3) In A…
rajan-chari Mar 26, 2024
b5f8907
move socket creation to thread with recv
rajan-chari Mar 26, 2024
ecf4fef
move socket creation to thread with recv
rajan-chari Mar 26, 2024
cf18ebf
Better logging for DirectorySvc
rajan-chari Mar 26, 2024
51d0f5c
better logging for directory svc
rajan-chari Mar 26, 2024
bb03669
Use logging config
rajan-chari Mar 26, 2024
bbdf193
Start removing sleeps
rajan-chari Mar 26, 2024
74fc690
pre-commit
rajan-chari Mar 26, 2024
c28fd9e
Cleanup monitor socket
rajan-chari Mar 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions samples/apps/cap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Actors can register themselves with CAP, find other agents, construct arbitrary
2) Many CAP Actors interacting with each other
3) A pair of interacting AutoGen Agents wrapped in CAP Actors
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
### Coming soon. Stay tuned! ###
1) Two AutoGen Agents running in different processes and communicating through CAP
1) AutoGen integration to list all registered agents
53 changes: 41 additions & 12 deletions samples/apps/cap/py/autogencap/DirectorySvc.py
sonichi marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,19 @@
from autogencap.DebugLog import Debug, Info, Error
from autogencap.ActorConnector import ActorConnector
from autogencap.Actor import Actor
from autogencap.proto.CAP_pb2 import ActorRegistration, ActorInfo, ActorLookup, ActorLookupResponse, Ping, Pong
from autogencap.proto.CAP_pb2 import (
ActorRegistration,
ActorInfo,
ActorLookup,
ActorLookupResponse,
Ping,
Pong,
ActorInfoCollection,
)
import zmq
import threading
import time
import re

# TODO (Future DirectorySv PR) use actor description, network_id, other properties to make directory
# service more generic and powerful
Expand Down Expand Up @@ -52,18 +61,27 @@ def _actor_lookup_msg_handler(self, topic: str, msg_type: str, msg: bytes, sende
actor_lookup = ActorLookup()
actor_lookup.ParseFromString(msg)
Debug("DirectorySvc", f"Actor lookup: {actor_lookup.actor_info.name}")
actor: ActorInfo = None
if actor_lookup.actor_info.name in self._registered_actors:
Info("DirectorySvc", f"Actor found: {actor_lookup.actor_info.name}")
actor = self._registered_actors[actor_lookup.actor_info.name]
else:
Error("DirectorySvc", f"Actor not found: {actor_lookup.actor_info.name}")
actor_lookup_resp = ActorLookupResponse()
if actor is not None:
actor_lookup_resp.actor.info_coll.extend([actor])
actor_lookup_resp.found = False
try:
pattern = re.compile(actor_lookup.actor_info.name)
except re.error:
Error("DirectorySvc", f"Invalid regex pattern: {actor_lookup.actor_info.name}")
else:
found_actor_list = [
self._registered_actors[registered_actor]
for registered_actor in self._registered_actors
if pattern.match(registered_actor)
]

if found_actor_list:
for actor in found_actor_list:
Info("DirectorySvc", f"Actor found: {actor}")
actor_lookup_resp.found = True
actor_lookup_resp.actor.info_coll.extend(found_actor_list)
else:
actor_lookup_resp.found = False
Error("DirectorySvc", f"Actor not found: {actor_lookup.actor_info.name}")

sender_connection = ActorConnector(self._context, sender_topic)
serialized_msg = actor_lookup_resp.SerializeToString()
sender_connection.send_bin_msg(ActorLookupResponse.__name__, serialized_msg)
Expand Down Expand Up @@ -110,18 +128,29 @@ def register_actor_by_name(self, actor_name: str):
actor_info = ActorInfo(name=actor_name)
self.register_actor(actor_info)

def lookup_actor_by_name(self, actor_name: str) -> ActorInfo:
actor_info = ActorInfo(name=actor_name)
def _lookup_actors_by_name(self, name_regex: str):
actor_info = ActorInfo(name=name_regex)
actor_lookup = ActorLookup(actor_info=actor_info)
serialized_msg = actor_lookup.SerializeToString()
_, _, _, resp = self._directory_connector.binary_request(ActorLookup.__name__, serialized_msg)
actor_lookup_resp = ActorLookupResponse()
actor_lookup_resp.ParseFromString(resp)
return actor_lookup_resp

def lookup_actor_by_name(self, actor_name: str) -> ActorInfo:
actor_lookup_resp = self._lookup_actors_by_name(actor_name)
if actor_lookup_resp.found:
if len(actor_lookup_resp.actor.info_coll) > 0:
return actor_lookup_resp.actor.info_coll[0]
return None

def lookup_actor_info_by_name(self, actor_name: str) -> ActorInfoCollection:
actor_lookup_resp = self._lookup_actors_by_name(actor_name)
if actor_lookup_resp.found:
if len(actor_lookup_resp.actor.info_coll) > 0:
return actor_lookup_resp.actor
return None


# Standalone min proxy for a standalone directory service
class MinProxy:
Expand Down
14 changes: 13 additions & 1 deletion samples/apps/cap/py/autogencap/LocalActorNetwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
from .DirectorySvc import DirectorySvc
from .Constants import Termination_Topic
from .Actor import Actor
from .proto.CAP_pb2 import ActorInfo
from .proto.CAP_pb2 import ActorInfo, ActorInfoCollection
from typing import List
import time

# TODO: remove time import
Expand Down Expand Up @@ -69,3 +70,14 @@ def lookup_actor(self, name: str) -> ActorConnector:
def lookup_termination(self) -> ActorConnector:
termination_topic: str = Termination_Topic
return self.actor_connector_by_topic(termination_topic)

def lookup_actor_info(self, name_regex) -> List[ActorInfo]:
actor_info: ActorInfoCollection = self._directory_svc.lookup_actor_info_by_name(name_regex)
if actor_info is None:
Warn("Local_Actor_Network", f"{name_regex}, not found in the network.")
return None
Debug("Local_Actor_Network", f"[{name_regex}] found in the network.")
actor_list = []
for actor in actor_info.info_coll:
actor_list.append(actor)
return actor_list
6 changes: 5 additions & 1 deletion samples/apps/cap/py/demo/App.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from CAPAutoGenPairDemo import cap_ag_pair_demo
from ComplexActorDemo import complex_actor_demo
from RemoteAGDemo import remote_ag_demo
from list_agents import list_agents

####################################################################################################

Expand Down Expand Up @@ -42,7 +43,8 @@ def main():
print("3. AutoGen Pair")
print("4. AutoGen GroupChat")
print("5. AutoGen Agents in different processes")
choice = input("Enter your choice (1-5): ")
print("6. List Actors in CAP")
choice = input("Enter your choice (1-6): ")

if choice == "1":
simple_actor_demo()
Expand All @@ -58,6 +60,8 @@ def main():
cap_ag_group_demo()
elif choice == "5":
remote_ag_demo()
elif choice == "6":
list_agents()
else:
print("Quitting...")
break
Expand Down
29 changes: 29 additions & 0 deletions samples/apps/cap/py/demo/list_agents.py
sonichi marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import time
from typing import List
from AppAgents import GreeterAgent, FidelityAgent
from autogencap.LocalActorNetwork import LocalActorNetwork
from autogencap.proto.CAP_pb2 import ActorInfo


def list_agents():
"""
Demonstrates the usage of the CAP platform by registering an actor, connecting to the actor,
sending a message, and performing cleanup operations.
"""
# CAP Platform

network = LocalActorNetwork()
# Register an actor
network.register(GreeterAgent())
# Register an actor
network.register(FidelityAgent())
# Tell actor to connect to other actors
network.connect()
# Get a list of actors
actor_infos: List[ActorInfo] = network.lookup_actor_info(name_regex=".*")
# Print out all actors found
for actor_info in actor_infos:
print(f"Name: {actor_info.name}, Namespace: {actor_info.namespace}, Description: {actor_info.description}")
time.sleep(1)
# Cleanup
network.disconnect()
Loading