mirror of https://github.com/microsoft/autogen.git
Merge branch '0.2' into feature/import-endpoint
This commit is contained in:
commit
604d2da83e
|
@ -102,6 +102,9 @@ class MessageHistoryLimiter:
|
||||||
if remaining_count == 0:
|
if remaining_count == 0:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if not transforms_util.is_tool_call_valid(truncated_messages):
|
||||||
|
truncated_messages.pop()
|
||||||
|
|
||||||
return truncated_messages
|
return truncated_messages
|
||||||
|
|
||||||
def get_logs(self, pre_transform_messages: List[Dict], post_transform_messages: List[Dict]) -> Tuple[str, bool]:
|
def get_logs(self, pre_transform_messages: List[Dict], post_transform_messages: List[Dict]) -> Tuple[str, bool]:
|
||||||
|
@ -229,6 +232,9 @@ class MessageTokenLimiter:
|
||||||
processed_messages_tokens += msg_tokens
|
processed_messages_tokens += msg_tokens
|
||||||
processed_messages.insert(0, msg)
|
processed_messages.insert(0, msg)
|
||||||
|
|
||||||
|
if not transforms_util.is_tool_call_valid(processed_messages):
|
||||||
|
processed_messages.pop()
|
||||||
|
|
||||||
return processed_messages
|
return processed_messages
|
||||||
|
|
||||||
def get_logs(self, pre_transform_messages: List[Dict], post_transform_messages: List[Dict]) -> Tuple[str, bool]:
|
def get_logs(self, pre_transform_messages: List[Dict], post_transform_messages: List[Dict]) -> Tuple[str, bool]:
|
||||||
|
@ -319,7 +325,7 @@ class TextMessageCompressor:
|
||||||
text_compressor: Optional[TextCompressor] = None,
|
text_compressor: Optional[TextCompressor] = None,
|
||||||
min_tokens: Optional[int] = None,
|
min_tokens: Optional[int] = None,
|
||||||
compression_params: Dict = dict(),
|
compression_params: Dict = dict(),
|
||||||
cache: Optional[AbstractCache] = Cache.disk(),
|
cache: Optional[AbstractCache] = None,
|
||||||
filter_dict: Optional[Dict] = None,
|
filter_dict: Optional[Dict] = None,
|
||||||
exclude_filter: bool = True,
|
exclude_filter: bool = True,
|
||||||
):
|
):
|
||||||
|
@ -391,6 +397,7 @@ class TextMessageCompressor:
|
||||||
|
|
||||||
cache_key = transforms_util.cache_key(message["content"], self._min_tokens)
|
cache_key = transforms_util.cache_key(message["content"], self._min_tokens)
|
||||||
cached_content = transforms_util.cache_content_get(self._cache, cache_key)
|
cached_content = transforms_util.cache_content_get(self._cache, cache_key)
|
||||||
|
|
||||||
if cached_content is not None:
|
if cached_content is not None:
|
||||||
message["content"], savings = cached_content
|
message["content"], savings = cached_content
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -112,3 +112,7 @@ def should_transform_message(message: Dict[str, Any], filter_dict: Optional[Dict
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return len(filter_config([message], filter_dict, exclude)) > 0
|
return len(filter_config([message], filter_dict, exclude)) > 0
|
||||||
|
|
||||||
|
|
||||||
|
def is_tool_call_valid(messages: List[Dict[str, Any]]) -> bool:
|
||||||
|
return messages[0].get("role") != "tool"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
__version__ = "0.2.36"
|
__version__ = "0.2.37"
|
||||||
|
|
|
@ -5,3 +5,4 @@ xpub_url: str = "tcp://127.0.0.1:5555"
|
||||||
xsub_url: str = "tcp://127.0.0.1:5556"
|
xsub_url: str = "tcp://127.0.0.1:5556"
|
||||||
router_url: str = "tcp://127.0.0.1:5557"
|
router_url: str = "tcp://127.0.0.1:5557"
|
||||||
dealer_url: str = "tcp://127.0.0.1:5558"
|
dealer_url: str = "tcp://127.0.0.1:5558"
|
||||||
|
USE_COLOR_LOGGING = True
|
||||||
|
|
|
@ -1,57 +1,38 @@
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import zmq
|
from .actor_runtime import IMessageReceiver, IMsgActor, IRuntime
|
||||||
|
from .debug_log import Debug, Info
|
||||||
from .Config import xpub_url
|
|
||||||
from .DebugLog import Debug, Error, Info
|
|
||||||
|
|
||||||
|
|
||||||
class Actor:
|
class Actor(IMsgActor):
|
||||||
def __init__(self, agent_name: str, description: str, start_thread: bool = True):
|
def __init__(self, agent_name: str, description: str, start_thread: bool = True):
|
||||||
|
"""Initialize the Actor with a name, description, and threading option."""
|
||||||
self.actor_name: str = agent_name
|
self.actor_name: str = agent_name
|
||||||
self.agent_description: str = description
|
self.agent_description: str = description
|
||||||
self.run = False
|
self.run = False
|
||||||
self._start_event = threading.Event()
|
self._start_event = threading.Event()
|
||||||
self._start_thread = start_thread
|
self._start_thread = start_thread
|
||||||
|
self._msg_receiver: IMessageReceiver = None
|
||||||
|
self._runtime: IRuntime = None
|
||||||
|
|
||||||
def on_connect(self, network):
|
def on_connect(self):
|
||||||
Debug(self.actor_name, f"is connecting to {network}")
|
"""Connect the actor to the runtime."""
|
||||||
|
Debug(self.actor_name, f"is connecting to {self._runtime}")
|
||||||
Debug(self.actor_name, "connected")
|
Debug(self.actor_name, "connected")
|
||||||
|
|
||||||
def on_txt_msg(self, msg: str, msg_type: str, receiver: str, sender: str) -> bool:
|
def on_txt_msg(self, msg: str, msg_type: str, receiver: str, sender: str) -> bool:
|
||||||
|
"""Handle incoming text messages."""
|
||||||
Info(self.actor_name, f"InBox: {msg}")
|
Info(self.actor_name, f"InBox: {msg}")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_bin_msg(self, msg: bytes, msg_type: str, receiver: str, sender: str) -> bool:
|
def on_bin_msg(self, msg: bytes, msg_type: str, receiver: str, sender: str) -> bool:
|
||||||
|
"""Handle incoming binary messages."""
|
||||||
Info(self.actor_name, f"Msg: receiver=[{receiver}], msg_type=[{msg_type}]")
|
Info(self.actor_name, f"Msg: receiver=[{receiver}], msg_type=[{msg_type}]")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
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:
|
|
||||||
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):
|
def dispatch_message(self, message):
|
||||||
|
"""Dispatch the received message based on its type."""
|
||||||
if message is None:
|
if message is None:
|
||||||
return
|
return
|
||||||
topic, msg_type, sender_topic, msg = message
|
topic, msg_type, sender_topic, msg = message
|
||||||
|
@ -65,40 +46,50 @@ class Actor:
|
||||||
if not self.on_bin_msg(msg, msg_type, topic, sender_topic):
|
if not self.on_bin_msg(msg, msg_type, topic, sender_topic):
|
||||||
self.run = False
|
self.run = False
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
"""Retrieve a message from the runtime implementation."""
|
||||||
|
return self._msg_receiver.get_message()
|
||||||
|
|
||||||
def _msg_loop(self):
|
def _msg_loop(self):
|
||||||
|
"""Main message loop for receiving and dispatching messages."""
|
||||||
try:
|
try:
|
||||||
self._msg_loop_init()
|
self._msg_receiver = self._runtime.get_new_msg_receiver()
|
||||||
|
self._msg_receiver.init(self.actor_name)
|
||||||
|
self._start_event.set()
|
||||||
while self.run:
|
while self.run:
|
||||||
message = self.get_message()
|
message = self._msg_receiver.get_message()
|
||||||
self.dispatch_message(message)
|
self.dispatch_message(message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
Debug(self.actor_name, f"recv thread encountered an error: {e}")
|
Debug(self.actor_name, f"recv thread encountered an error: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
finally:
|
finally:
|
||||||
self.run = False
|
|
||||||
# In case there was an exception at startup signal
|
# In case there was an exception at startup signal
|
||||||
# the main thread.
|
# the main thread.
|
||||||
self._start_event.set()
|
self._start_event.set()
|
||||||
|
self.run = False
|
||||||
Debug(self.actor_name, "recv thread ended")
|
Debug(self.actor_name, "recv thread ended")
|
||||||
|
|
||||||
def on_start(self, context: zmq.Context):
|
def on_start(self, runtime: IRuntime):
|
||||||
self._context = context
|
"""Start the actor and its message receiving thread if applicable."""
|
||||||
self.run: bool = True
|
self._runtime = runtime # Save the runtime
|
||||||
|
self.run = True
|
||||||
if self._start_thread:
|
if self._start_thread:
|
||||||
self._thread = threading.Thread(target=self._msg_loop)
|
self._thread = threading.Thread(target=self._msg_loop)
|
||||||
self._thread.start()
|
self._thread.start()
|
||||||
self._start_event.wait()
|
self._start_event.wait()
|
||||||
else:
|
else:
|
||||||
self._msg_loop_init()
|
self._msg_receiver = self._runtime.get_new_msg_receiver()
|
||||||
|
self._msg_receiver.init(self.actor_name)
|
||||||
|
|
||||||
def disconnect_network(self, network):
|
def disconnect_network(self, network):
|
||||||
|
"""Disconnect the actor from the network."""
|
||||||
Debug(self.actor_name, f"is disconnecting from {network}")
|
Debug(self.actor_name, f"is disconnecting from {network}")
|
||||||
Debug(self.actor_name, "disconnected")
|
Debug(self.actor_name, "disconnected")
|
||||||
self.stop()
|
self.stop()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
"""Stop the actor and its message receiver."""
|
||||||
self.run = False
|
self.run = False
|
||||||
if self._start_thread:
|
if self._start_thread:
|
||||||
self._thread.join()
|
self._thread.join()
|
||||||
self._socket.setsockopt(zmq.LINGER, 0)
|
self._msg_receiver.stop()
|
||||||
self._socket.close()
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
from abc import ABC, abstractmethod
|
||||||
|
from typing import Any, Optional, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
class IActorConnector(ABC):
|
||||||
|
"""
|
||||||
|
Abstract base class for actor connectors. Each runtime will have a different implementation.
|
||||||
|
Obtain an instance of the correct connector from the runtime by calling the runtime's find_by_xyz
|
||||||
|
method.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def send_txt_msg(self, msg: str) -> None:
|
||||||
|
"""
|
||||||
|
Send a text message to the actor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): The text message to send.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def send_bin_msg(self, msg_type: str, msg: bytes) -> None:
|
||||||
|
"""
|
||||||
|
Send a binary message to the actor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg_type (str): The type of the binary message.
|
||||||
|
msg (bytes): The binary message to send.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def send_proto_msg(self, msg: Any) -> None:
|
||||||
|
"""
|
||||||
|
Send a protocol buffer message to the actor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (Any): The protocol buffer message to send.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def send_recv_proto_msg(
|
||||||
|
self, msg: Any, num_attempts: int = 5
|
||||||
|
) -> Tuple[Optional[str], Optional[str], Optional[bytes]]:
|
||||||
|
"""
|
||||||
|
Send a protocol buffer message and receive a response from the actor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (Any): The protocol buffer message to send.
|
||||||
|
num_attempts (int, optional): Number of attempts to send and receive. Defaults to 5.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple[Optional[str], Optional[str], Optional[bytes]]: A tuple containing the topic,
|
||||||
|
message type, and response message, or None if no response is received.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def send_recv_msg(
|
||||||
|
self, msg_type: str, msg: bytes, num_attempts: int = 5
|
||||||
|
) -> Tuple[Optional[str], Optional[str], Optional[bytes]]:
|
||||||
|
"""
|
||||||
|
Send a binary message and receive a response from the actor.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg_type (str): The type of the binary message.
|
||||||
|
msg (bytes): The binary message to send.
|
||||||
|
num_attempts (int, optional): Number of attempts to send and receive. Defaults to 5.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Tuple[Optional[str], Optional[str], Optional[bytes]]: A tuple containing the topic,
|
||||||
|
message type, and response message, or None if no response is received.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def close(self) -> None:
|
||||||
|
"""
|
||||||
|
Close the actor connector and release any resources.
|
||||||
|
"""
|
||||||
|
pass
|
|
@ -1,36 +1,108 @@
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from .Actor import Actor
|
from .actor_connector import IActorConnector
|
||||||
from .ActorConnector import ActorConnector
|
|
||||||
from .proto.CAP_pb2 import ActorInfo
|
from .proto.CAP_pb2 import ActorInfo
|
||||||
|
|
||||||
|
|
||||||
class IRuntime(ABC):
|
class IMsgActor(ABC):
|
||||||
|
"""Abstract base class for message based actors."""
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def register(self, actor: Actor):
|
def on_connect(self, runtime: "IRuntime"):
|
||||||
|
"""Called when the actor connects to the runtime."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_txt_msg(self, msg: str, msg_type: str, receiver: str, sender: str) -> bool:
|
||||||
|
"""Handle incoming text messages."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_bin_msg(self, msg: bytes, msg_type: str, receiver: str, sender: str) -> bool:
|
||||||
|
"""Handle incoming binary messages."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def on_start(self):
|
||||||
|
"""Called when the actor starts."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def stop(self):
|
||||||
|
"""Stop the actor."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def dispatch_message(self, message):
|
||||||
|
"""Dispatch the received message based on its type."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class IMessageReceiver(ABC):
|
||||||
|
"""Abstract base class for message receivers. Implementations are runtime specific."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def init(self, actor_name: str):
|
||||||
|
"""Initialize the message receiver."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def add_listener(self, topic: str):
|
||||||
|
"""Add a topic to the message receiver."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_message(self):
|
||||||
|
"""Retrieve a message from the runtime implementation."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def stop(self):
|
||||||
|
"""Stop the message receiver."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Abstract base class for the runtime environment
|
||||||
|
class IRuntime(ABC):
|
||||||
|
"""Abstract base class for the actor runtime environment."""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def register(self, actor: IMsgActor):
|
||||||
|
"""Register an actor with the runtime."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def get_new_msg_receiver(self) -> IMessageReceiver:
|
||||||
|
"""Create and return a new message receiver."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def connect(self):
|
def connect(self):
|
||||||
|
"""Connect the runtime to the messaging system."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
|
"""Disconnect the runtime from the messaging system."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def find_by_topic(self, topic: str) -> ActorConnector:
|
def find_by_topic(self, topic: str) -> IActorConnector:
|
||||||
|
"""Find an actor connector by topic."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def find_by_name(self, name: str) -> ActorConnector:
|
def find_by_name(self, name: str) -> IActorConnector:
|
||||||
|
"""Find an actor connector by name."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def find_termination(self) -> ActorConnector:
|
def find_termination(self) -> IActorConnector:
|
||||||
|
"""Find the termination actor connector."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def find_by_name_regex(self, name_regex) -> List[ActorInfo]:
|
def find_by_name_regex(self, name_regex) -> List["ActorInfo"]:
|
||||||
|
"""Find actors by name using a regular expression."""
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
import zmq
|
|
||||||
|
|
||||||
from autogencap.Actor import Actor
|
|
||||||
from autogencap.constants import Termination_Topic
|
|
||||||
from autogencap.DebugLog import Debug
|
|
||||||
|
|
||||||
|
|
||||||
class AGActor(Actor):
|
|
||||||
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}")
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
from autogencap.actor import Actor
|
||||||
|
from autogencap.constants import Termination_Topic
|
||||||
|
from autogencap.debug_log import Debug
|
||||||
|
|
||||||
|
|
||||||
|
class AGActor(Actor):
|
||||||
|
def on_start(self, runtime):
|
||||||
|
super().on_start(runtime)
|
||||||
|
str_topic = Termination_Topic
|
||||||
|
self._msg_receiver.add_listener(str_topic)
|
||||||
|
Debug(self.actor_name, f"subscribe to: {str_topic}")
|
|
@ -4,7 +4,7 @@ from typing import Callable, Dict, List, Optional, Union
|
||||||
from autogen import Agent, ConversableAgent
|
from autogen import Agent, ConversableAgent
|
||||||
|
|
||||||
from ..actor_runtime import IRuntime
|
from ..actor_runtime import IRuntime
|
||||||
from .AutoGenConnector import AutoGenConnector
|
from .autogen_connector import AutoGenConnector
|
||||||
|
|
||||||
|
|
||||||
class AG2CAP(ConversableAgent):
|
class AG2CAP(ConversableAgent):
|
|
@ -2,8 +2,8 @@ import time
|
||||||
|
|
||||||
from autogen import ConversableAgent
|
from autogen import ConversableAgent
|
||||||
|
|
||||||
from ..DebugLog import Info, Warn
|
from ..debug_log import Info, Warn
|
||||||
from .CAP2AG import CAP2AG
|
from .cap_to_ag import CAP2AG
|
||||||
|
|
||||||
|
|
||||||
class Agent:
|
class Agent:
|
||||||
|
|
|
@ -3,7 +3,7 @@ from typing import Dict, Optional, Union
|
||||||
|
|
||||||
from autogen import Agent
|
from autogen import Agent
|
||||||
|
|
||||||
from ..ActorConnector import ActorConnector
|
from ..actor_connector import IActorConnector
|
||||||
from ..proto.Autogen_pb2 import GenReplyReq, GenReplyResp, PrepChat, ReceiveReq, Terminate
|
from ..proto.Autogen_pb2 import GenReplyReq, GenReplyResp, PrepChat, ReceiveReq, Terminate
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ class AutoGenConnector:
|
||||||
to/from the CAP system.
|
to/from the CAP system.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, cap_sender: ActorConnector):
|
def __init__(self, cap_sender: IActorConnector):
|
||||||
self._can_channel: ActorConnector = cap_sender
|
self._can_channel: IActorConnector = cap_sender
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
|
@ -1,8 +1,8 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from autogen import Agent, AssistantAgent, GroupChat
|
from autogen import Agent, AssistantAgent, GroupChat
|
||||||
from autogencap.ag_adapter.AG2CAP import AG2CAP
|
from autogencap.ag_adapter.ag_to_cap import AG2CAP
|
||||||
from autogencap.ag_adapter.CAP2AG import CAP2AG
|
from autogencap.ag_adapter.cap_to_ag import CAP2AG
|
||||||
|
|
||||||
from ..actor_runtime import IRuntime
|
from ..actor_runtime import IRuntime
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from autogen import GroupChatManager
|
from autogen import GroupChatManager
|
||||||
from autogencap.ActorConnector import ActorConnector
|
from autogencap.actor_connector import IActorConnector
|
||||||
from autogencap.ag_adapter.CAP2AG import CAP2AG
|
from autogencap.ag_adapter.cap_group_chat import CAPGroupChat
|
||||||
from autogencap.ag_adapter.CAPGroupChat import CAPGroupChat
|
from autogencap.ag_adapter.cap_to_ag import CAP2AG
|
||||||
|
|
||||||
from ..actor_runtime import IRuntime
|
from ..actor_runtime import IRuntime
|
||||||
|
|
||||||
|
|
||||||
class CAPGroupChatManager:
|
class CAPGroupChatManager:
|
||||||
def __init__(self, groupchat: CAPGroupChat, llm_config: dict, network: IRuntime):
|
def __init__(self, groupchat: CAPGroupChat, llm_config: dict, runtime: IRuntime):
|
||||||
self._ensemble: IRuntime = network
|
self._runtime: IRuntime = runtime
|
||||||
self._cap_group_chat: CAPGroupChat = groupchat
|
self._cap_group_chat: CAPGroupChat = groupchat
|
||||||
self._ag_group_chat_manager: GroupChatManager = GroupChatManager(
|
self._ag_group_chat_manager: GroupChatManager = GroupChatManager(
|
||||||
groupchat=self._cap_group_chat, llm_config=llm_config
|
groupchat=self._cap_group_chat, llm_config=llm_config
|
||||||
|
@ -21,11 +21,11 @@ class CAPGroupChatManager:
|
||||||
init_chat=False,
|
init_chat=False,
|
||||||
self_recursive=True,
|
self_recursive=True,
|
||||||
)
|
)
|
||||||
self._ensemble.register(self._cap_proxy)
|
self._runtime.register(self._cap_proxy)
|
||||||
|
|
||||||
def initiate_chat(self, txt_msg: str) -> None:
|
def initiate_chat(self, txt_msg: str) -> None:
|
||||||
self._ensemble.connect()
|
self._runtime.connect()
|
||||||
user_proxy_conn: ActorConnector = self._ensemble.find_by_name(self._cap_group_chat.chat_initiator)
|
user_proxy_conn: IActorConnector = self._runtime.find_by_name(self._cap_group_chat.chat_initiator)
|
||||||
user_proxy_conn.send_txt_msg(txt_msg)
|
user_proxy_conn.send_txt_msg(txt_msg)
|
||||||
self._wait_for_user_exit()
|
self._wait_for_user_exit()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from autogencap.ag_adapter.CAP2AG import CAP2AG
|
from autogencap.ag_adapter.cap_to_ag import CAP2AG
|
||||||
|
|
||||||
|
|
||||||
class CAPPair:
|
class CAPPair:
|
|
@ -5,10 +5,10 @@ from typing import Optional
|
||||||
from autogen import ConversableAgent
|
from autogen import ConversableAgent
|
||||||
|
|
||||||
from ..actor_runtime import IRuntime
|
from ..actor_runtime import IRuntime
|
||||||
from ..DebugLog import Debug, Error, Info, Warn, shorten
|
from ..debug_log import Debug, Error, Info, Warn, shorten
|
||||||
from ..proto.Autogen_pb2 import GenReplyReq, GenReplyResp, PrepChat, ReceiveReq, Terminate
|
from ..proto.Autogen_pb2 import GenReplyReq, GenReplyResp, PrepChat, ReceiveReq, Terminate
|
||||||
from .AG2CAP import AG2CAP
|
from .ag_actor import AGActor
|
||||||
from .AGActor import AGActor
|
from .ag_to_cap import AG2CAP
|
||||||
|
|
||||||
|
|
||||||
class CAP2AG(AGActor):
|
class CAP2AG(AGActor):
|
||||||
|
@ -27,15 +27,13 @@ class CAP2AG(AGActor):
|
||||||
self.STATE = self.States.INIT
|
self.STATE = self.States.INIT
|
||||||
self._can2ag_name: str = self.actor_name + ".can2ag"
|
self._can2ag_name: str = self.actor_name + ".can2ag"
|
||||||
self._self_recursive: bool = self_recursive
|
self._self_recursive: bool = self_recursive
|
||||||
self._ensemble: IRuntime = None
|
|
||||||
self._connectors = {}
|
self._connectors = {}
|
||||||
|
|
||||||
def on_connect(self, ensemble: IRuntime):
|
def on_connect(self):
|
||||||
"""
|
"""
|
||||||
Connect to the AutoGen system.
|
Connect to the AutoGen system.
|
||||||
"""
|
"""
|
||||||
self._ensemble = ensemble
|
self._ag2can_other_agent = AG2CAP(self._runtime, self._other_agent_name)
|
||||||
self._ag2can_other_agent = AG2CAP(self._ensemble, self._other_agent_name)
|
|
||||||
Debug(self._can2ag_name, "connected to {ensemble}")
|
Debug(self._can2ag_name, "connected to {ensemble}")
|
||||||
|
|
||||||
def disconnect_network(self, ensemble: IRuntime):
|
def disconnect_network(self, ensemble: IRuntime):
|
||||||
|
@ -117,7 +115,7 @@ class CAP2AG(AGActor):
|
||||||
if topic in self._connectors:
|
if topic in self._connectors:
|
||||||
return self._connectors[topic]
|
return self._connectors[topic]
|
||||||
else:
|
else:
|
||||||
connector = self._ensemble.find_by_topic(topic)
|
connector = self._runtime.find_by_topic(topic)
|
||||||
self._connectors[topic] = connector
|
self._connectors[topic] = connector
|
||||||
return connector
|
return connector
|
||||||
|
|
|
@ -3,8 +3,8 @@ import time
|
||||||
|
|
||||||
import zmq
|
import zmq
|
||||||
|
|
||||||
from autogencap.Config import router_url, xpub_url, xsub_url
|
from autogencap.config import router_url, xpub_url, xsub_url
|
||||||
from autogencap.DebugLog import Debug, Info, Warn
|
from autogencap.debug_log import Debug, Info, Warn
|
||||||
|
|
||||||
|
|
||||||
class Broker:
|
class Broker:
|
|
@ -3,7 +3,7 @@ import threading
|
||||||
|
|
||||||
from termcolor import colored
|
from termcolor import colored
|
||||||
|
|
||||||
import autogencap.Config as Config
|
import autogencap.config as config
|
||||||
|
|
||||||
# Define log levels as constants
|
# Define log levels as constants
|
||||||
DEBUG = 0
|
DEBUG = 0
|
||||||
|
@ -22,9 +22,9 @@ class BaseLogger:
|
||||||
|
|
||||||
def Log(self, level, context, msg):
|
def Log(self, level, context, msg):
|
||||||
# Check if the current level meets the threshold
|
# Check if the current level meets the threshold
|
||||||
if level >= Config.LOG_LEVEL: # Use the LOG_LEVEL from the Config module
|
if level >= config.LOG_LEVEL: # Use the LOG_LEVEL from the Config module
|
||||||
# Check if the context is in the list of ignored contexts
|
# Check if the context is in the list of ignored contexts
|
||||||
if context in Config.IGNORED_LOG_CONTEXTS:
|
if context in config.IGNORED_LOG_CONTEXTS:
|
||||||
return
|
return
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self.WriteLog(level, context, msg)
|
self.WriteLog(level, context, msg)
|
||||||
|
@ -34,7 +34,7 @@ class BaseLogger:
|
||||||
|
|
||||||
|
|
||||||
class ConsoleLogger(BaseLogger):
|
class ConsoleLogger(BaseLogger):
|
||||||
def __init__(self, use_color=True):
|
def __init__(self, use_color=config.USE_COLOR_LOGGING):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._use_color = use_color
|
self._use_color = use_color
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ class ConsoleLogger(BaseLogger):
|
||||||
print(f"{thread_id} {timestamp} {level_name}: [{context}] {msg}")
|
print(f"{thread_id} {timestamp} {level_name}: [{context}] {msg}")
|
||||||
|
|
||||||
|
|
||||||
|
# Modify this line to disable color logging by default
|
||||||
LOGGER = ConsoleLogger()
|
LOGGER = ConsoleLogger()
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from autogencap.actor_runtime import IRuntime
|
from autogencap.actor_runtime import IRuntime
|
||||||
from autogencap.constants import ZMQ_Runtime
|
from autogencap.constants import ZMQ_Runtime
|
||||||
from autogencap.DebugLog import Error
|
from autogencap.debug_log import Error
|
||||||
from autogencap.zmq_runtime import ZMQRuntime
|
from autogencap.zmq_runtime import ZMQRuntime
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from autogencap.DebugLog import Error
|
from autogencap.debug_log import Error
|
||||||
from autogencap.proto.CAP_pb2 import Error as ErrorMsg
|
from autogencap.proto.CAP_pb2 import Error as ErrorMsg
|
||||||
from autogencap.proto.CAP_pb2 import ErrorCode
|
from autogencap.proto.CAP_pb2 import ErrorCode
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
# Agent_Sender takes a zmq context, Topic and creates a
|
|
||||||
# socket that can publish to that topic. It exposes this functionality
|
|
||||||
# using send_msg method
|
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
@ -8,11 +5,12 @@ from typing import Any, Dict
|
||||||
import zmq
|
import zmq
|
||||||
from zmq.utils.monitor import recv_monitor_message
|
from zmq.utils.monitor import recv_monitor_message
|
||||||
|
|
||||||
from .Config import router_url, xpub_url, xsub_url
|
from .actor_connector import IActorConnector
|
||||||
from .DebugLog import Debug, Error, Info
|
from .config import router_url, xpub_url, xsub_url
|
||||||
|
from .debug_log import Debug, Error, Info
|
||||||
|
|
||||||
|
|
||||||
class ActorSender:
|
class ZMQActorSender:
|
||||||
def __init__(self, context, topic):
|
def __init__(self, context, topic):
|
||||||
self._context = context
|
self._context = context
|
||||||
self._topic = topic
|
self._topic = topic
|
||||||
|
@ -73,12 +71,12 @@ class ActorSender:
|
||||||
self._pub_socket.close()
|
self._pub_socket.close()
|
||||||
|
|
||||||
|
|
||||||
class ActorConnector:
|
class ZMQActorConnector(IActorConnector):
|
||||||
def __init__(self, context, topic):
|
def __init__(self, context, topic):
|
||||||
self._context = context
|
self._context = context
|
||||||
self._topic = topic
|
self._topic = topic
|
||||||
self._connect_sub_socket()
|
self._connect_sub_socket()
|
||||||
self._sender = ActorSender(context, topic)
|
self._sender = ZMQActorSender(context, topic)
|
||||||
time.sleep(0.1) # Wait for the socket to connect
|
time.sleep(0.1) # Wait for the socket to connect
|
||||||
|
|
||||||
def _connect_sub_socket(self):
|
def _connect_sub_socket(self):
|
|
@ -4,12 +4,10 @@ import time
|
||||||
|
|
||||||
import zmq
|
import zmq
|
||||||
|
|
||||||
from autogencap.Actor import Actor
|
from autogencap.actor import Actor
|
||||||
from autogencap.ActorConnector import ActorConnector, ActorSender
|
from autogencap.broker import Broker
|
||||||
from autogencap.Broker import Broker
|
|
||||||
from autogencap.Config import router_url, xpub_url, xsub_url
|
|
||||||
from autogencap.constants import Directory_Svc_Topic
|
from autogencap.constants import Directory_Svc_Topic
|
||||||
from autogencap.DebugLog import Debug, Error, Info
|
from autogencap.debug_log import Debug, Error, Info
|
||||||
from autogencap.proto.CAP_pb2 import (
|
from autogencap.proto.CAP_pb2 import (
|
||||||
ActorInfo,
|
ActorInfo,
|
||||||
ActorInfoCollection,
|
ActorInfoCollection,
|
||||||
|
@ -24,16 +22,18 @@ from autogencap.proto.CAP_pb2 import (
|
||||||
Error as ErrorMsg,
|
Error as ErrorMsg,
|
||||||
)
|
)
|
||||||
from autogencap.utility import report_error_msg
|
from autogencap.utility import report_error_msg
|
||||||
|
from autogencap.zmq_actor_connector import ZMQActorConnector, ZMQActorSender
|
||||||
|
|
||||||
# TODO (Future DirectorySv PR) use actor description, network_id, other properties to make directory
|
# TODO (Future DirectorySv PR) use actor description, network_id, other properties to make directory
|
||||||
# service more generic and powerful
|
# service more generic and powerful
|
||||||
|
|
||||||
|
|
||||||
class DirectoryActor(Actor):
|
class ZMQDirectoryActor(Actor):
|
||||||
def __init__(self, topic: str, name: str):
|
def __init__(self, topic: str, name: str, context: zmq.Context):
|
||||||
super().__init__(topic, name)
|
super().__init__(topic, name)
|
||||||
self._registered_actors = {}
|
self._registered_actors = {}
|
||||||
self._network_prefix = ""
|
self._network_prefix = ""
|
||||||
|
self._context = context
|
||||||
|
|
||||||
def on_bin_msg(self, msg: bytes, msg_type: str, topic: str, sender: str) -> bool:
|
def on_bin_msg(self, msg: bytes, msg_type: str, topic: str, sender: str) -> bool:
|
||||||
if msg_type == ActorRegistration.__name__:
|
if msg_type == ActorRegistration.__name__:
|
||||||
|
@ -50,7 +50,7 @@ class DirectoryActor(Actor):
|
||||||
Info("DirectorySvc", f"Ping received: {sender_topic}")
|
Info("DirectorySvc", f"Ping received: {sender_topic}")
|
||||||
pong = Pong()
|
pong = Pong()
|
||||||
serialized_msg = pong.SerializeToString()
|
serialized_msg = pong.SerializeToString()
|
||||||
sender_connection = ActorSender(self._context, sender_topic)
|
sender_connection = ZMQActorSender(self._context, sender_topic)
|
||||||
sender_connection.send_bin_msg(Pong.__name__, serialized_msg)
|
sender_connection.send_bin_msg(Pong.__name__, serialized_msg)
|
||||||
|
|
||||||
def _on_actor_registration_msg(self, topic: str, msg_type: str, msg: bytes, sender_topic: str):
|
def _on_actor_registration_msg(self, topic: str, msg_type: str, msg: bytes, sender_topic: str):
|
||||||
|
@ -67,7 +67,7 @@ class DirectoryActor(Actor):
|
||||||
else:
|
else:
|
||||||
self._registered_actors[name] = actor_reg.actor_info
|
self._registered_actors[name] = actor_reg.actor_info
|
||||||
|
|
||||||
sender_connection = ActorSender(self._context, sender_topic)
|
sender_connection = ZMQActorSender(self._context, sender_topic)
|
||||||
serialized_msg = err.SerializeToString()
|
serialized_msg = err.SerializeToString()
|
||||||
sender_connection.send_bin_msg(ErrorMsg.__name__, serialized_msg)
|
sender_connection.send_bin_msg(ErrorMsg.__name__, serialized_msg)
|
||||||
|
|
||||||
|
@ -96,16 +96,16 @@ class DirectoryActor(Actor):
|
||||||
else:
|
else:
|
||||||
Error("DirectorySvc", f"Actor not found: {actor_lookup.actor_info.name}")
|
Error("DirectorySvc", f"Actor not found: {actor_lookup.actor_info.name}")
|
||||||
|
|
||||||
sender_connection = ActorSender(self._context, sender_topic)
|
sender_connection = ZMQActorSender(self._context, sender_topic)
|
||||||
serialized_msg = actor_lookup_resp.SerializeToString()
|
serialized_msg = actor_lookup_resp.SerializeToString()
|
||||||
sender_connection.send_bin_msg(ActorLookupResponse.__name__, serialized_msg)
|
sender_connection.send_bin_msg(ActorLookupResponse.__name__, serialized_msg)
|
||||||
|
|
||||||
|
|
||||||
class DirectorySvc:
|
class ZMQDirectorySvc:
|
||||||
def __init__(self, context: zmq.Context = zmq.Context()):
|
def __init__(self, context: zmq.Context = zmq.Context()):
|
||||||
self._context: zmq.Context = context
|
self._context: zmq.Context = context
|
||||||
self._directory_connector: ActorConnector = None
|
self._directory_connector: ZMQActorConnector = None
|
||||||
self._directory_actor: DirectoryActor = None
|
self._directory_actor: ZMQDirectoryActor = None
|
||||||
|
|
||||||
def _no_other_directory(self) -> bool:
|
def _no_other_directory(self) -> bool:
|
||||||
Debug("DirectorySvc", "Pinging existing DirectorySvc")
|
Debug("DirectorySvc", "Pinging existing DirectorySvc")
|
||||||
|
@ -116,12 +116,14 @@ class DirectorySvc:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def start(self):
|
def start(self, runtime):
|
||||||
Debug("DirectorySvc", "Starting.")
|
Debug("DirectorySvc", "Starting.")
|
||||||
self._directory_connector = ActorConnector(self._context, Directory_Svc_Topic)
|
self._directory_connector = ZMQActorConnector(self._context, Directory_Svc_Topic)
|
||||||
if self._no_other_directory():
|
if self._no_other_directory():
|
||||||
self._directory_actor = DirectoryActor(Directory_Svc_Topic, "Directory Service")
|
self._directory_actor = ZMQDirectoryActor(
|
||||||
self._directory_actor.on_start(self._context)
|
Directory_Svc_Topic, "Directory Service", self._context
|
||||||
|
) # Update this line
|
||||||
|
self._directory_actor.on_start(runtime)
|
||||||
Info("DirectorySvc", "Directory service started.")
|
Info("DirectorySvc", "Directory service started.")
|
||||||
else:
|
else:
|
||||||
Info("DirectorySvc", "Another directory service is running. This instance will not start.")
|
Info("DirectorySvc", "Another directory service is running. This instance will not start.")
|
||||||
|
@ -176,15 +178,8 @@ def main():
|
||||||
proxy: Broker = Broker(context)
|
proxy: Broker = Broker(context)
|
||||||
proxy.start()
|
proxy.start()
|
||||||
# Start the directory service
|
# Start the directory service
|
||||||
directory_svc = DirectorySvc(context)
|
directory_svc = ZMQDirectorySvc(context)
|
||||||
directory_svc.start()
|
directory_svc.start()
|
||||||
# # How do you register an actor?
|
|
||||||
# directory_svc.register_actor_by_name("my_actor")
|
|
||||||
#
|
|
||||||
# # How do you look up an actor?
|
|
||||||
# actor: ActorInfo = directory_svc.lookup_actor_by_name("my_actor")
|
|
||||||
# if actor is not None:
|
|
||||||
# Info("main", f"Found actor: {actor.name}")
|
|
||||||
|
|
||||||
# DirectorySvc is running in a separate thread. Here we are watching the
|
# DirectorySvc is running in a separate thread. Here we are watching the
|
||||||
# status and printing status every few seconds. This is
|
# status and printing status every few seconds. This is
|
|
@ -0,0 +1,51 @@
|
||||||
|
# ZMQ implementation of the message receiver
|
||||||
|
import threading
|
||||||
|
|
||||||
|
import zmq
|
||||||
|
|
||||||
|
from autogencap.actor_runtime import IMessageReceiver
|
||||||
|
from autogencap.config import xpub_url
|
||||||
|
from autogencap.debug_log import Debug, Error
|
||||||
|
|
||||||
|
|
||||||
|
class ZMQMsgReceiver(IMessageReceiver):
|
||||||
|
def __init__(self, context: zmq.Context):
|
||||||
|
self._socket = None
|
||||||
|
self._context = context
|
||||||
|
self._start_event = threading.Event()
|
||||||
|
self.run = False
|
||||||
|
|
||||||
|
def init(self, actor_name: str):
|
||||||
|
"""Initialize the ZMQ message receiver."""
|
||||||
|
self.actor_name = actor_name
|
||||||
|
self._socket = self._context.socket(zmq.SUB)
|
||||||
|
self._socket.setsockopt(zmq.RCVTIMEO, 500)
|
||||||
|
self._socket.connect(xpub_url)
|
||||||
|
str_topic = f"{self.actor_name}"
|
||||||
|
self.add_listener(str_topic)
|
||||||
|
self._start_event.set()
|
||||||
|
|
||||||
|
def add_listener(self, topic: str):
|
||||||
|
"""Add a topic to the message receiver."""
|
||||||
|
Debug(self.actor_name, f"subscribe to: {topic}")
|
||||||
|
self._socket.setsockopt_string(zmq.SUBSCRIBE, f"{topic}")
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
"""Retrieve a message from the ZMQ socket."""
|
||||||
|
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:
|
||||||
|
return None # No message received, continue to next iteration
|
||||||
|
except Exception as e:
|
||||||
|
Error(self.actor_name, f"recv thread encountered an error: {e}")
|
||||||
|
return None
|
||||||
|
return topic, msg_type, sender_topic, msg
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""Stop the ZMQ message receiver."""
|
||||||
|
self.run = False
|
||||||
|
self._socket.setsockopt(zmq.LINGER, 0)
|
||||||
|
self._socket.close()
|
|
@ -3,27 +3,31 @@ from typing import List
|
||||||
|
|
||||||
import zmq
|
import zmq
|
||||||
|
|
||||||
from .Actor import Actor
|
from .actor import Actor
|
||||||
from .actor_runtime import IRuntime
|
from .actor_connector import IActorConnector
|
||||||
from .ActorConnector import ActorConnector
|
from .actor_runtime import IMessageReceiver, IRuntime
|
||||||
from .Broker import Broker
|
from .broker import Broker
|
||||||
from .constants import Termination_Topic
|
from .constants import Termination_Topic
|
||||||
from .DebugLog import Debug, Warn
|
from .debug_log import Debug, Warn
|
||||||
from .DirectorySvc import DirectorySvc
|
|
||||||
from .proto.CAP_pb2 import ActorInfo, ActorInfoCollection
|
from .proto.CAP_pb2 import ActorInfo, ActorInfoCollection
|
||||||
|
from .zmq_actor_connector import ZMQActorConnector
|
||||||
|
|
||||||
|
|
||||||
class ZMQRuntime(IRuntime):
|
class ZMQRuntime(IRuntime):
|
||||||
def __init__(self, name: str = "Local Actor Network", start_broker: bool = True):
|
def __init__(self, start_broker: bool = True):
|
||||||
self.local_actors = {}
|
self.local_actors = {}
|
||||||
self.name: str = name
|
|
||||||
self._context: zmq.Context = zmq.Context()
|
self._context: zmq.Context = zmq.Context()
|
||||||
self._start_broker: bool = start_broker
|
self._start_broker: bool = start_broker
|
||||||
self._broker: Broker = None
|
self._broker: Broker = None
|
||||||
self._directory_svc: DirectorySvc = None
|
self._directory_svc = None
|
||||||
|
self._log_name = self.__class__.__name__
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.name}"
|
return f" \
|
||||||
|
{self._log_name}\n \
|
||||||
|
is_broker: {self._broker is not None}\n \
|
||||||
|
is_directory_svc: {self._directory_svc is not None}\n \
|
||||||
|
local_actors: {self.local_actors}\n"
|
||||||
|
|
||||||
def _init_runtime(self):
|
def _init_runtime(self):
|
||||||
if self._start_broker and self._broker is None:
|
if self._start_broker and self._broker is None:
|
||||||
|
@ -32,23 +36,28 @@ class ZMQRuntime(IRuntime):
|
||||||
self._start_broker = False # Don't try to start the broker again
|
self._start_broker = False # Don't try to start the broker again
|
||||||
self._broker = None
|
self._broker = None
|
||||||
if self._directory_svc is None:
|
if self._directory_svc is None:
|
||||||
self._directory_svc = DirectorySvc(self._context)
|
from .zmq_directory_svc import ZMQDirectorySvc
|
||||||
self._directory_svc.start()
|
|
||||||
|
self._directory_svc = ZMQDirectorySvc(self._context)
|
||||||
|
self._directory_svc.start(self)
|
||||||
time.sleep(0.25) # Process queued thread events in Broker and Directory
|
time.sleep(0.25) # Process queued thread events in Broker and Directory
|
||||||
|
|
||||||
def register(self, actor: Actor):
|
def register(self, actor: Actor):
|
||||||
self._init_runtime()
|
self._init_runtime()
|
||||||
# Get actor's name and description and add to a dictionary so
|
|
||||||
# that we can look up the actor by name
|
|
||||||
self._directory_svc.register_actor_by_name(actor.actor_name)
|
self._directory_svc.register_actor_by_name(actor.actor_name)
|
||||||
self.local_actors[actor.actor_name] = actor
|
self.local_actors[actor.actor_name] = actor
|
||||||
actor.on_start(self._context)
|
actor.on_start(self) # Pass self (the runtime) to on_start
|
||||||
Debug("Local_Actor_Network", f"{actor.actor_name} registered in the network.")
|
Debug(self._log_name, f"{actor.actor_name} registered in the network.")
|
||||||
|
|
||||||
|
def get_new_msg_receiver(self) -> IMessageReceiver:
|
||||||
|
from .zmq_msg_receiver import ZMQMsgReceiver
|
||||||
|
|
||||||
|
return ZMQMsgReceiver(self._context)
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
self._init_runtime()
|
self._init_runtime()
|
||||||
for actor in self.local_actors.values():
|
for actor in self.local_actors.values():
|
||||||
actor.on_connect(self)
|
actor.on_connect()
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
for actor in self.local_actors.values():
|
for actor in self.local_actors.values():
|
||||||
|
@ -58,27 +67,27 @@ class ZMQRuntime(IRuntime):
|
||||||
if self._broker:
|
if self._broker:
|
||||||
self._broker.stop()
|
self._broker.stop()
|
||||||
|
|
||||||
def find_by_topic(self, topic: str) -> ActorConnector:
|
def find_by_topic(self, topic: str) -> IActorConnector:
|
||||||
return ActorConnector(self._context, topic)
|
return ZMQActorConnector(self._context, topic)
|
||||||
|
|
||||||
def find_by_name(self, name: str) -> ActorConnector:
|
def find_by_name(self, name: str) -> IActorConnector:
|
||||||
actor_info: ActorInfo = self._directory_svc.lookup_actor_by_name(name)
|
actor_info: ActorInfo = self._directory_svc.lookup_actor_by_name(name)
|
||||||
if actor_info is None:
|
if actor_info is None:
|
||||||
Warn("Local_Actor_Network", f"{name}, not found in the network.")
|
Warn(self._log_name, f"{name}, not found in the network.")
|
||||||
return None
|
return None
|
||||||
Debug("Local_Actor_Network", f"[{name}] found in the network.")
|
Debug(self._log_name, f"[{name}] found in the network.")
|
||||||
return self.find_by_topic(name)
|
return self.find_by_topic(name)
|
||||||
|
|
||||||
def find_termination(self) -> ActorConnector:
|
def find_termination(self) -> IActorConnector:
|
||||||
termination_topic: str = Termination_Topic
|
termination_topic: str = Termination_Topic
|
||||||
return self.find_by_topic(termination_topic)
|
return self.find_by_topic(termination_topic)
|
||||||
|
|
||||||
def find_by_name_regex(self, name_regex) -> List[ActorInfo]:
|
def find_by_name_regex(self, name_regex) -> List[ActorInfo]:
|
||||||
actor_info: ActorInfoCollection = self._directory_svc.lookup_actor_info_by_name(name_regex)
|
actor_info: ActorInfoCollection = self._directory_svc.lookup_actor_info_by_name(name_regex)
|
||||||
if actor_info is None:
|
if actor_info is None:
|
||||||
Warn("Local_Actor_Network", f"{name_regex}, not found in the network.")
|
Warn(self._log_name, f"{name_regex}, not found in the network.")
|
||||||
return None
|
return None
|
||||||
Debug("Local_Actor_Network", f"[{name_regex}] found in the network.")
|
Debug(self._log_name, f"[{name_regex}] found in the network.")
|
||||||
actor_list = []
|
actor_list = []
|
||||||
for actor in actor_info.info_coll:
|
for actor in actor_info.info_coll:
|
||||||
actor_list.append(actor)
|
actor_list.append(actor)
|
||||||
|
|
|
@ -5,16 +5,16 @@ Demo App
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
import _paths
|
import _paths
|
||||||
import autogencap.Config as Config
|
import autogencap.config as config
|
||||||
import autogencap.DebugLog as DebugLog
|
import autogencap.debug_log as debug_log
|
||||||
from AGDemo import ag_demo
|
from ag_demo import ag_demo
|
||||||
from AGGroupChatDemo import ag_groupchat_demo
|
from ag_group_chat_demo import ag_groupchat_demo
|
||||||
from CAPAutGenGroupDemo import cap_ag_group_demo
|
from cap_autogen_group_demo import cap_ag_group_demo
|
||||||
from CAPAutoGenPairDemo import cap_ag_pair_demo
|
from cap_autogen_pair_demo import cap_ag_pair_demo
|
||||||
from ComplexActorDemo import complex_actor_demo
|
from complex_actor_demo import complex_actor_demo
|
||||||
from list_agents import list_agents
|
from list_agents import list_agents
|
||||||
from RemoteAGDemo import remote_ag_demo
|
from remote_autogen_demo import remote_ag_demo
|
||||||
from SimpleActorDemo import simple_actor_demo
|
from simple_actor_demo import simple_actor_demo
|
||||||
from single_threaded import single_threaded_demo
|
from single_threaded import single_threaded_demo
|
||||||
|
|
||||||
####################################################################################################
|
####################################################################################################
|
||||||
|
@ -28,8 +28,8 @@ def parse_args():
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
# Set the log level
|
# Set the log level
|
||||||
# Print log level string based on names in debug_log.py
|
# Print log level string based on names in debug_log.py
|
||||||
print(f"Log level: {DebugLog.LEVEL_NAMES[args.log_level]}")
|
print(f"Log level: {debug_log.LEVEL_NAMES[args.log_level]}")
|
||||||
Config.LOG_LEVEL = args.log_level
|
config.LOG_LEVEL = args.log_level
|
||||||
# Config.IGNORED_LOG_CONTEXTS.extend(["BROKER"])
|
# Config.IGNORED_LOG_CONTEXTS.extend(["BROKER"])
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,10 @@ Each agent represents a different role and knows how to connect to external syst
|
||||||
to retrieve information.
|
to retrieve information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from autogencap.Actor import Actor
|
from autogencap.actor import Actor
|
||||||
|
from autogencap.actor_connector import IActorConnector
|
||||||
from autogencap.actor_runtime import IRuntime
|
from autogencap.actor_runtime import IRuntime
|
||||||
from autogencap.ActorConnector import ActorConnector
|
from autogencap.debug_log import Debug, Info, shorten
|
||||||
from autogencap.DebugLog import Debug, Info, shorten
|
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
|
||||||
|
|
||||||
|
|
||||||
class GreeterAgent(Actor):
|
class GreeterAgent(Actor):
|
||||||
|
@ -132,23 +131,23 @@ class PersonalAssistant(Actor):
|
||||||
description="This is the personal assistant, who knows how to connect to the other agents and get information from them.",
|
description="This is the personal assistant, who knows how to connect to the other agents and get information from them.",
|
||||||
):
|
):
|
||||||
super().__init__(agent_name, description)
|
super().__init__(agent_name, description)
|
||||||
self.fidelity: ActorConnector = None
|
self.fidelity: IActorConnector = None
|
||||||
self.financial_planner: ActorConnector = None
|
self.financial_planner: IActorConnector = None
|
||||||
self.quant: ActorConnector = None
|
self.quant: IActorConnector = None
|
||||||
self.risk_manager: ActorConnector = None
|
self.risk_manager: IActorConnector = None
|
||||||
|
|
||||||
def on_connect(self, network: IRuntime):
|
def on_connect(self):
|
||||||
"""
|
"""
|
||||||
Connects the personal assistant to the specified local actor network.
|
Connects the personal assistant to the specified local actor network.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
network (LocalActorNetwork): The local actor network to connect to.
|
network (LocalActorNetwork): The local actor network to connect to.
|
||||||
"""
|
"""
|
||||||
Debug(self.actor_name, f"is connecting to {network}")
|
Debug(self.actor_name, f"is connecting to {self._runtime}")
|
||||||
self.fidelity = network.find_by_name("Fidelity")
|
self.fidelity = self._runtime.find_by_name("Fidelity")
|
||||||
self.financial_planner = network.find_by_name("Financial Planner")
|
self.financial_planner = self._runtime.find_by_name("Financial Planner")
|
||||||
self.quant = network.find_by_name("Quant")
|
self.quant = self._runtime.find_by_name("Quant")
|
||||||
self.risk_manager = network.find_by_name("Risk Manager")
|
self.risk_manager = self._runtime.find_by_name("Risk Manager")
|
||||||
Debug(self.actor_name, "connected")
|
Debug(self.actor_name, "connected")
|
||||||
|
|
||||||
def disconnect_network(self, network: IRuntime):
|
def disconnect_network(self, network: IRuntime):
|
|
@ -1,6 +1,6 @@
|
||||||
from autogencap.ag_adapter.CAPGroupChat import CAPGroupChat
|
from autogencap.ag_adapter.cap_group_chat import CAPGroupChat
|
||||||
from autogencap.ag_adapter.CAPGroupChatManager import CAPGroupChatManager
|
from autogencap.ag_adapter.cap_group_chat_manager import CAPGroupChatManager
|
||||||
from autogencap.DebugLog import Info
|
from autogencap.debug_log import Info
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
|
|
||||||
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json
|
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json
|
||||||
|
@ -35,7 +35,7 @@ def cap_ag_group_demo():
|
||||||
cap_groupchat = CAPGroupChat(
|
cap_groupchat = CAPGroupChat(
|
||||||
agents=[user_proxy, coder, pm], messages=[], max_round=12, ensemble=ensemble, chat_initiator=user_proxy.name
|
agents=[user_proxy, coder, pm], messages=[], max_round=12, ensemble=ensemble, chat_initiator=user_proxy.name
|
||||||
)
|
)
|
||||||
manager = CAPGroupChatManager(groupchat=cap_groupchat, llm_config=gpt4_config, network=ensemble)
|
manager = CAPGroupChatManager(groupchat=cap_groupchat, llm_config=gpt4_config, runtime=ensemble)
|
||||||
manager.initiate_chat("Find a latest paper about gpt-4 on arxiv and find its potential applications in software.")
|
manager.initiate_chat("Find a latest paper about gpt-4 on arxiv and find its potential applications in software.")
|
||||||
ensemble.disconnect()
|
ensemble.disconnect()
|
||||||
Info("App", "App Exit")
|
Info("App", "App Exit")
|
|
@ -1,15 +1,15 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import autogencap.DebugLog as DebugLog
|
import autogencap.debug_log as debug_log
|
||||||
from autogencap.ag_adapter.CAPPair import CAPPair
|
from autogencap.ag_adapter.cap_pair import CAPPair
|
||||||
from autogencap.DebugLog import ConsoleLogger, Info
|
from autogencap.debug_log import ConsoleLogger, Info
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
|
|
||||||
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json
|
from autogen import AssistantAgent, UserProxyAgent, config_list_from_json
|
||||||
|
|
||||||
|
|
||||||
def cap_ag_pair_demo():
|
def cap_ag_pair_demo():
|
||||||
DebugLog.LOGGER = ConsoleLogger(use_color=False)
|
debug_log.LOGGER = ConsoleLogger(use_color=False)
|
||||||
|
|
||||||
config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")
|
config_list = config_list_from_json(env_or_file="OAI_CONFIG_LIST")
|
||||||
assistant = AssistantAgent("assistant", llm_config={"config_list": config_list})
|
assistant = AssistantAgent("assistant", llm_config={"config_list": config_list})
|
|
@ -1,6 +1,6 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from AppAgents import FidelityAgent, FinancialPlannerAgent, PersonalAssistant, QuantAgent, RiskManager
|
from app_agents import FidelityAgent, FinancialPlannerAgent, PersonalAssistant, QuantAgent, RiskManager
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
from termcolor import colored
|
from termcolor import colored
|
||||||
|
|
||||||
|
@ -14,17 +14,17 @@ def complex_actor_demo():
|
||||||
sends them to the personal assistant agent, and terminates
|
sends them to the personal assistant agent, and terminates
|
||||||
when the user enters "quit".
|
when the user enters "quit".
|
||||||
"""
|
"""
|
||||||
ensemble = RuntimeFactory.get_runtime("ZMQ")
|
runtime = RuntimeFactory.get_runtime("ZMQ")
|
||||||
# Register agents
|
# Register agents
|
||||||
ensemble.register(PersonalAssistant())
|
runtime.register(PersonalAssistant())
|
||||||
ensemble.register(FidelityAgent())
|
runtime.register(FidelityAgent())
|
||||||
ensemble.register(FinancialPlannerAgent())
|
runtime.register(FinancialPlannerAgent())
|
||||||
ensemble.register(RiskManager())
|
runtime.register(RiskManager())
|
||||||
ensemble.register(QuantAgent())
|
runtime.register(QuantAgent())
|
||||||
# Tell agents to connect to other agents
|
# Tell agents to connect to other agents
|
||||||
ensemble.connect()
|
runtime.connect()
|
||||||
# Get a channel to the personal assistant agent
|
# Get a channel to the personal assistant agent
|
||||||
pa = ensemble.find_by_name(PersonalAssistant.cls_agent_name)
|
pa = runtime.find_by_name(PersonalAssistant.cls_agent_name)
|
||||||
info_msg = """
|
info_msg = """
|
||||||
This is an imaginary personal assistant agent scenario.
|
This is an imaginary personal assistant agent scenario.
|
||||||
Five actors are connected in a self-determined graph. The user
|
Five actors are connected in a self-determined graph. The user
|
||||||
|
@ -48,4 +48,4 @@ def complex_actor_demo():
|
||||||
# Cleanup
|
# Cleanup
|
||||||
|
|
||||||
pa.close()
|
pa.close()
|
||||||
ensemble.disconnect()
|
runtime.disconnect()
|
|
@ -1,8 +1,8 @@
|
||||||
import time
|
import time
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from AppAgents import FidelityAgent, GreeterAgent
|
from app_agents import FidelityAgent, GreeterAgent
|
||||||
from autogencap.DebugLog import Info
|
from autogencap.debug_log import Info
|
||||||
from autogencap.proto.CAP_pb2 import ActorInfo
|
from autogencap.proto.CAP_pb2 import ActorInfo
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from AppAgents import GreeterAgent
|
from app_agents import GreeterAgent
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import _paths
|
import _paths
|
||||||
from AppAgents import GreeterAgent
|
from app_agents import GreeterAgent
|
||||||
from autogencap.DebugLog import Error
|
from autogencap.debug_log import Error
|
||||||
from autogencap.proto.CAP_pb2 import Ping
|
from autogencap.proto.CAP_pb2 import Ping
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
import time
|
|
||||||
|
|
||||||
import _paths
|
|
||||||
from autogencap.ag_adapter.CAP2AG import CAP2AG
|
|
||||||
from autogencap.Config import IGNORED_LOG_CONTEXTS
|
|
||||||
from autogencap.DebugLog import Info
|
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
|
||||||
|
|
||||||
from autogen import UserProxyAgent, config_list_from_json
|
|
||||||
|
|
||||||
|
|
||||||
# Starts the Broker and the Assistant. The UserProxy is started separately.
|
|
||||||
class StandaloneUserProxy:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
print("Running the StandaloneUserProxy")
|
|
||||||
|
|
||||||
user_proxy = UserProxyAgent(
|
|
||||||
"user_proxy",
|
|
||||||
code_execution_config={"work_dir": "coding"},
|
|
||||||
is_termination_msg=lambda x: "TERMINATE" in x.get("content"),
|
|
||||||
)
|
|
||||||
# Composable Agent Network adapter
|
|
||||||
ensemble = RuntimeFactory.get_runtime("ZMQ")
|
|
||||||
user_proxy_adptr = CAP2AG(ag_agent=user_proxy, the_other_name="assistant", init_chat=True, self_recursive=True)
|
|
||||||
ensemble.register(user_proxy_adptr)
|
|
||||||
ensemble.connect()
|
|
||||||
|
|
||||||
# Send a message to the user_proxy
|
|
||||||
user_proxy_conn = ensemble.find_by_name("user_proxy")
|
|
||||||
example = "Plot a chart of MSFT daily closing prices for last 1 Month."
|
|
||||||
print(f"Example: {example}")
|
|
||||||
try:
|
|
||||||
user_input = input("Please enter your command: ")
|
|
||||||
if user_input == "":
|
|
||||||
user_input = example
|
|
||||||
print(f"Sending: {user_input}")
|
|
||||||
user_proxy_conn.send_txt_msg(user_input)
|
|
||||||
|
|
||||||
# Hang around for a while
|
|
||||||
while user_proxy_adptr.run:
|
|
||||||
time.sleep(0.5)
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print("Interrupted by user, shutting down.")
|
|
||||||
ensemble.disconnect()
|
|
||||||
Info("StandaloneUserProxy", "App Exit")
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
IGNORED_LOG_CONTEXTS.extend(["BROKER", "DirectorySvc"])
|
|
||||||
assistant = StandaloneUserProxy()
|
|
||||||
assistant.run()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -1,8 +1,8 @@
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import _paths
|
import _paths
|
||||||
from autogencap.ag_adapter.CAP2AG import CAP2AG
|
from autogencap.ag_adapter.cap_to_ag import CAP2AG
|
||||||
from autogencap.DebugLog import Info
|
from autogencap.debug_log import Info
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
|
|
||||||
from autogen import AssistantAgent, config_list_from_json
|
from autogen import AssistantAgent, config_list_from_json
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import _paths
|
import _paths
|
||||||
from autogencap.Broker import main
|
from autogencap.broker import main
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
|
@ -1,5 +1,5 @@
|
||||||
import _paths
|
import _paths
|
||||||
from autogencap.DirectorySvc import main
|
from autogencap.zmq_directory_svc import main
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -2,7 +2,7 @@ import time
|
||||||
|
|
||||||
import _paths
|
import _paths
|
||||||
from autogencap.ag_adapter.agent import Agent
|
from autogencap.ag_adapter.agent import Agent
|
||||||
from autogencap.Config import IGNORED_LOG_CONTEXTS
|
from autogencap.config import IGNORED_LOG_CONTEXTS
|
||||||
from autogencap.runtime_factory import RuntimeFactory
|
from autogencap.runtime_factory import RuntimeFactory
|
||||||
|
|
||||||
from autogen import UserProxyAgent
|
from autogen import UserProxyAgent
|
||||||
|
|
|
@ -4,7 +4,7 @@ from typing import Any, Dict
|
||||||
|
|
||||||
import _paths
|
import _paths
|
||||||
import zmq
|
import zmq
|
||||||
from autogencap.Config import dealer_url, router_url, xpub_url, xsub_url
|
from autogencap.config import dealer_url, router_url, xpub_url, xsub_url
|
||||||
from zmq.utils.monitor import recv_monitor_message
|
from zmq.utils.monitor import recv_monitor_message
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
"It functions similarly to the `DockerCommandLineCodeExecutor`, but specifically creates container within Kubernetes environments.\n",
|
"It functions similarly to the `DockerCommandLineCodeExecutor`, but specifically creates container within Kubernetes environments.\n",
|
||||||
"\n",
|
"\n",
|
||||||
"There are two condition to use PodCommandLineCodeExecutor.\n",
|
"There are two condition to use PodCommandLineCodeExecutor.\n",
|
||||||
|
"\n",
|
||||||
"- Access to a Kubernetes cluster\n",
|
"- Access to a Kubernetes cluster\n",
|
||||||
"- installation `autogen` with the extra requirements `'pyautogen[kubernetes]'`\n",
|
"- installation `autogen` with the extra requirements `'pyautogen[kubernetes]'`\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"source": [
|
"source": [
|
||||||
"There are four options PodCommandLineCodeExecutor to access kubernetes API server.\n",
|
"There are four options PodCommandLineCodeExecutor to access kubernetes API server.\n",
|
||||||
|
"\n",
|
||||||
"- default kubeconfig file path: `~/.kube/config`\n",
|
"- default kubeconfig file path: `~/.kube/config`\n",
|
||||||
"- Provide a custom kubeconfig file path using the `kube_config_file` argument of `PodCommandLineCodeExecutor`.\n",
|
"- Provide a custom kubeconfig file path using the `kube_config_file` argument of `PodCommandLineCodeExecutor`.\n",
|
||||||
"- Set the kubeconfig file path using the `KUBECONFIG` environment variable.\n",
|
"- Set the kubeconfig file path using the `KUBECONFIG` environment variable.\n",
|
||||||
|
|
Loading…
Reference in New Issue