Skip to content

Commit

Permalink
[BUFG][Majority Voting]
Browse files Browse the repository at this point in the history
  • Loading branch information
Kye committed Mar 7, 2024
1 parent b679ae9 commit e38f48d
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 99 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,54 @@ print(inference)
```


## Majority Voting
Multiple-agents will evaluate an idea based off of an parsing or evaluation function. From papers like "[More agents is all you need](https://arxiv.org/pdf/2402.05120.pdf)

```python
from swarms import Agent, MajorityVoting, ChromaDB, Anthropic

# Initialize the llm
llm = Anthropic()

# Agents
agent1 = Agent(
llm = llm,
system_prompt="You are the leader of the Progressive Party. What is your stance on healthcare?",
agent_name="Progressive Leader",
agent_description="Leader of the Progressive Party",
long_term_memory=ChromaDB(),
max_steps=1,
)

agent2 = Agent(
llm=llm,
agent_name="Conservative Leader",
agent_description="Leader of the Conservative Party",
long_term_memory=ChromaDB(),
max_steps=1,
)

agent3 = Agent(
llm=llm,
agent_name="Libertarian Leader",
agent_description="Leader of the Libertarian Party",
long_term_memory=ChromaDB(),
max_steps=1,
)

# Initialize the majority voting
mv = MajorityVoting(
agents=[agent1, agent2, agent3],
output_parser=llm.majority_voting,
autosave=False,
verbose=True,
)


# Start the majority voting
mv.run("What is your stance on healthcare?")
```

## Real-World Deployment

### Multi-Agent Swarm for Logistics
Expand Down
42 changes: 42 additions & 0 deletions majority_voting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from swarms import Agent, MajorityVoting, ChromaDB, Anthropic

# Initialize the llm
llm = Anthropic()

# Agents
agent1 = Agent(
llm = llm,
system_prompt="You are the leader of the Progressive Party. What is your stance on healthcare?",
agent_name="Progressive Leader",
agent_description="Leader of the Progressive Party",
long_term_memory=ChromaDB(),
max_steps=1,
)

agent2 = Agent(
llm=llm,
agent_name="Conservative Leader",
agent_description="Leader of the Conservative Party",
long_term_memory=ChromaDB(),
max_steps=1,
)

agent3 = Agent(
llm=llm,
agent_name="Libertarian Leader",
agent_description="Leader of the Libertarian Party",
long_term_memory=ChromaDB(),
max_steps=1,
)

# Initialize the majority voting
mv = MajorityVoting(
agents=[agent1, agent2, agent3],
output_parser=llm.majority_voting,
autosave=False,
verbose=True,
)


# Start the majority voting
mv.run("What is your stance on healthcare?")
21 changes: 0 additions & 21 deletions playground/structs/majority_voting.py

This file was deleted.

File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "swarms"
version = "4.2.7"
version = "4.2.8"
description = "Swarms - Pytorch"
license = "MIT"
authors = ["Kye Gomez <[email protected]>"]
Expand Down
1 change: 1 addition & 0 deletions swarms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
from swarms.tokenizers import * # noqa: E402, F403
from swarms.tools import * # noqa: E402, F403
from swarms.utils import * # noqa: E402, F403
from swarms.memory import * # noqa: E402, F403
3 changes: 2 additions & 1 deletion swarms/models/gemini.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ def get_gemini_api_key_env():
key = os.getenv("GEMINI_API_KEY")
if key is None:
raise ValueError("Please provide a Gemini API key")
return key
return str(key)



# Main class
Expand Down
113 changes: 37 additions & 76 deletions swarms/structs/majority_voting.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import asyncio
import concurrent.futures
import re
import sys
from collections import Counter
from multiprocessing import Pool
from typing import Any, List
from typing import Any, Callable, List, Optional

from loguru import logger

from swarms.structs.agent import Agent
from swarms.structs.conversation import Conversation
from swarms.utils.file_processing import create_file

# Configure loguru logger with advanced settings
logger.remove()
Expand Down Expand Up @@ -96,15 +95,14 @@ def most_frequent(

for i in clist:
current_frequency = sum(cmp_func(i, item) for item in clist)
print(current_frequency)
if current_frequency > counter:
counter = current_frequency
num = i

return num, counter


def majority_voting(answers: list):
def majority_voting(answers: List[str]):
"""
Performs majority voting on a list of answers and returns the most common answer.
Expand All @@ -115,7 +113,12 @@ def majority_voting(answers: list):
The most common answer in the list.
"""
counter = Counter(answers)
answer = counter.most_common(1)[0][0]
if counter:

answer = counter.most_common(1)[0][0]
else:
answer = "I don't know"

return answer


Expand All @@ -124,13 +127,11 @@ class MajorityVoting:
Class representing a majority voting system for agents.
Args:
agents (List[Agent]): A list of agents to use in the majority voting system.
concurrent (bool, optional): Whether to run the agents concurrently. Defaults to False.
multithreaded (bool, optional): Whether to run the agents using multithreading. Defaults to False.
multiprocess (bool, optional): Whether to run the agents using multiprocessing. Defaults to False.
asynchronous (bool, optional): Whether to run the agents asynchronously. Defaults to False.
output_parser (callable, optional): A callable function to parse the output of the majority voting system. Defaults to None.
agents (list): A list of agents to be used in the majority voting system.
output_parser (function, optional): A function used to parse the output of the agents.
If not provided, the default majority voting function is used.
autosave (bool, optional): A boolean indicating whether to autosave the conversation to a file.
verbose (bool, optional): A boolean indicating whether to enable verbose logging.
Examples:
>>> from swarms.structs.agent import Agent
>>> from swarms.structs.majority_voting import MajorityVoting
Expand All @@ -148,21 +149,13 @@ class MajorityVoting:
def __init__(
self,
agents: List[Agent],
concurrent: bool = False,
multithreaded: bool = False,
multiprocess: bool = False,
asynchronous: bool = False,
output_parser: callable = None,
output_parser: Optional[Callable] = majority_voting,
autosave: bool = False,
verbose: bool = False,
*args,
**kwargs,
):
self.agents = agents
self.concurrent = concurrent
self.multithreaded = multithreaded
self.multiprocess = multiprocess
self.asynchronous = asynchronous
self.output_parser = output_parser
self.autosave = autosave
self.verbose = verbose
Expand All @@ -173,7 +166,7 @@ def __init__(

# If autosave is enabled, save the conversation to a file
if self.autosave:
self.conversation.save()
create_file(str(self.conversation), "majority_voting.json")

# Log the agents
logger.info("Initializing majority voting system")
Expand All @@ -198,69 +191,37 @@ def run(self, task: str, *args, **kwargs) -> List[Any]:
"""
# Route to each agent
if self.concurrent:
with concurrent.futures.ThreadPoolExecutor() as executor:
# Log the agents
logger.info("Running agents concurrently")
futures = [
executor.submit(agent.run, task, *args)
for agent in self.agents
]
results = [
future.result()
for future in concurrent.futures.as_completed(
futures
)
]
elif self.multithreaded:
logger.info("Running agents using multithreading")
with concurrent.futures.ThreadPoolExecutor() as executor:
results = [
executor.submit(agent.run, task, *args)
for agent in self.agents
]
results = [future.result() for future in results]
elif self.multiprocess:
logger.info("Running agents using multiprocessing")
with Pool() as pool:
results = pool.starmap(
Agent.run,
[(agent, task, *args) for agent in self.agents],
)
elif self.asynchronous:
loop = asyncio.get_event_loop()
tasks = [
loop.run_in_executor(None, agent.run, task, *args)
with concurrent.futures.ThreadPoolExecutor() as executor:
logger.info("Running agents concurrently")

futures = [
executor.submit(agent.run, task, *args)
for agent in self.agents
]
results = loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
else:
results = [
agent.run(task, *args) for agent in self.agents
future.result()
for future in concurrent.futures.as_completed(futures)
]

# Add responses to conversation and log them
for agent, response in zip(self.agents, results):
logger.info(f"[{agent.agent_id}][{response}]")

response = (
response if isinstance(response, list) else [response]
)
response = response if isinstance(response, list) else [response]
self.conversation.add(agent.agent_name, response)
logger.info(f"[{agent.agent_id}][{response}]")
logger.info(f"[Agent][Name: {agent.agent_name}][Response: {response}]")

# Perform majority voting on the conversation
majority_vote = majority_voting(self.conversation.responses)

# Log the majority vote
logger.info(f"Majority vote: {majority_vote}")

# If an output parser is provided, parse the output
if self.output_parser:
majority_vote = self.output_parser(
majority_vote, *args, **kwargs
)
responses = [
message["content"]
for message in self.conversation.conversation_history
if message["role"] == "agent"
]

# If an output parser is provided, parse the responses
if self.output_parser is not None:
majority_vote = self.output_parser(responses, *args, **kwargs)
else:
majority_vote = majority_voting(responses)


# Return the majority vote
return majority_vote

0 comments on commit e38f48d

Please sign in to comment.