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

Changing cross-agent synchronization mechanism to socket-based with z… #25

Merged
merged 5 commits into from
Apr 4, 2025

Conversation

zomux
Copy link
Contributor

@zomux zomux commented Apr 3, 2025

Changing cross-agent synchronization mechanism to socket-based with zeromq; Changed agent meta class to lazy initialization to resolve cross-process sync problems

The developer interface will look like

from chorus.core import Chorus

from chorus.agents import  TaskCoordinatorAgent, ConversationalTaskAgent
from chorus.teams import Team
from chorus.collaboration import CentralizedCollaboration

from chorus.toolbox import WebRetrieverTool
from chorus.toolbox import DuckDuckGoWebSearchTool

from chorus.workspace import NoActivityStopper


if __name__ == '__main__':
    coordinator_agent = TaskCoordinatorAgent(
        instruction="""
        Do not do any task by yourself, always try to call other agents.
        If there is no relevant agent available, tell the user that you do not have a agent to answer the question.
        Make your answer comprehensive and detailed.
        """,
        reachable_agents={
            "FactResearchAgent": "An agent that can help user to find facts related to fitness and summarize them by search web and access pages.",
            "KnowledgeAgent": "An agent that can help user to answer general questions about fitness." 
        }
    ).name("FitnessAnsweringAgent")
    
    fact_research_agent = ConversationalTaskAgent(
        instruction="You can help user to find facts related to fitness and summarize them by search web and access pages.",
        tools=[
            DuckDuckGoWebSearchTool(),
            WebRetrieverTool()
        ]
    ).name("FactResearchAgent")
    
    knowledge_agent = ConversationalTaskAgent(
        instruction="Help user to answer general questions about fitness, nutrition, exercise and healthy lifestyle.",
    ).name("KnowledgeAgent")

    team = Team(
        name="HelloWorldTeam",
        agents=[coordinator_agent, fact_research_agent, knowledge_agent],
        collaboration=CentralizedCollaboration(
            coordinator=coordinator_agent.identifier()
        )
    )

    chorus = Chorus(
        teams=[team],
        stop_conditions=[NoActivityStopper()]
    )
    chorus.start()

    msg = chorus.send_and_wait(
        destination=team.identifier(),
        message="What are the best parks in New York City for running?"
    )
    print(msg.content)
    chorus.stop()

…eromq; Changed agent meta class to lazt intialization to resolve cross-process sync problems
@zomux zomux requested a review from ybdarrenwang April 3, 2025 17:53
@zomux
Copy link
Contributor Author

zomux commented Apr 4, 2025

Start to merge PR 25 since all other features depend on it.

@zomux zomux merged commit d96c3dd into nightly Apr 4, 2025
1 of 2 checks passed
instruction="Test instruction",
tools=[self.mock_tool],
lm=self.mock_lm,
prompter=BedrockConverseToolChatPrompter()
)
).name("TestAgent")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind moving name functionality outside of init. But do we have any default naming mechanism for cases when traceability is desired but user didn't assign agent names, e.g. voting?

from chorus.data.dialog import Message


class MockMessageClient(ChorusMessageClient):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this's not put in tests folder instead?

try:
observation = executor.execute(action)
except Exception as e:
import traceback
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this import needed?

"""
A team of agents that collaborate to achieve a goal.
"""

def name_to_identifier(self, name: str) -> str:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why we need two difference concept of name vs identifier.

obj._init_kwargs = kwargs
obj._agent_name = None

# Immediately call __init__ instead of delayed initialization
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain what's this for?

@@ -30,7 +30,7 @@ class SimpleToolExecutor(ToolExecutor):
"""

def __init__(self, tools: List[ExecutableTool], agent_context: Optional[AgentContext] = None, tolerate_error: bool = True):
for tool in tools:
for i, tool in enumerate(tools):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't seem needed

@@ -69,7 +69,7 @@ class AgentContext(OrchestrationContext):

agent_id: str
team_info: Optional[TeamInfo] = None
message_service: MessageService = Field(default_factory=MessageService)
message_client: Optional[ChorusMessageClient] = None
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see we name-changed message_service to message_client everywhere. Any reason behind this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants