Skip to content

Commit

Permalink
Add an example to interact with user. A new kind of coordinator (Sequ…
Browse files Browse the repository at this point in the history
…entialMemoryCoordinatorWiseAgent) and collaboration type are added to support this. Fixes wise-agents#331 and wise-agents#122
  • Loading branch information
maeste committed Sep 26, 2024
1 parent 9bced6b commit 571c2f1
Show file tree
Hide file tree
Showing 7 changed files with 332 additions and 7 deletions.
15 changes: 10 additions & 5 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ The example consists of two main agents:

1. **Web Interface Agent**: Simulates a web-based client for interacting with other agents.
2. **Intelligent Agent**: Handles requests and provides intelligent responses based on memory and context.

* [memory_agentic_chatbot_groq](./memory_agentic_chatbot_groq/README.md)

This guide walks you through running a practical example of a multi-agent system using Wise Agents. In this example, two agents (a web interface agent and an intelligent agent) are started, allowing you to experiment with agent communication and interaction in a simulated environment. This is the same as described in [memory_agentic_chatbot](./memory_agentic_chatbot/), but instead of using a local LLM it uses [https://groq.com/](https://groq.com/) for model inference. Please obtain an API key from [https://console.groq.com/keys](https://console.groq.com/keys) and set the env variable GROQ_API_KEY to start playing with this example.

* [sequential_coordinator](./sequential_coordinator/README.md)
The example consists of four agents:

Expand All @@ -15,7 +20,7 @@ The example consists of four agents:
*"You are an expert translator from english to italian. Translate the provided text from english to italian. "*
4. **SequentialCoordinator**: Take care of coordinating the request handling from the user delagating the work to other agents in a predetermined order.

* [peceive_and_act](./perceive_and_act/README.md)
* [perceive_and_act](./perceive_and_act/README.md)
The example consists of four agents:

1. **PerceivingAgent**: This is an agent that can perceive file changes. In case of changes it send a message with the list of books contained in books_read.txt to the SequentialCoordinator. This agent code is not part of wise-agents framework, but it's defined for this example use only in `custom_agent.py` present in the example directory.
Expand All @@ -24,10 +29,10 @@ The example consists of four agents:
3. **ActionAgent**: This agent will write what received (the books suggested) in a file (books_suggested.txt). It will override the file each time. This agent code is not part of wise-agents framework, but it's defined for this example use only in `custom_agent.py` present in the example directory.
4. **SequentialCoordinator**: Take care of coordinating the request handling from the user delagating the work to other agents in a predetermined order.

* [run_examples_podman](./run_examples_podman/README.md)
* [perceive_ask_and_act](./perceive_ask_and_act/README.md)

This guide walks you through running any of the example in the examples directory in podman containers
This guide walks you through running a practical example of a multi-agent system using Wise Agents. In this example, six agents (an agent interacting with a human with a text based interface, a sequential agent coordinator, and four intelligent agents) are started, allowing you to experiment with agents/humans communication and interaction in a simulated environment. It uses a sequential coordination able to share chat history between involved agents.

* [memory_agentic_chatbot_groq](./memory_agentic_chatbot_groq/README.md)
* [run_examples_podman](./run_examples_podman/README.md)

This guide walks you through running a practical example of a multi-agent system using Wise Agents. In this example, two agents (a web interface agent and an intelligent agent) are started, allowing you to experiment with agent communication and interaction in a simulated environment. This is the same as described in [memory_agentic_chatbot](./memory_agentic_chatbot/), but instead of using a local LLM it uses [https://groq.com/](https://groq.com/) for model inference. Please obtain an API key from [https://console.groq.com/keys](https://console.groq.com/keys) and set the env variable GROQ_API_KEY to start playing with this example.
This guide walks you through running any of the example in the examples directory in podman containers
78 changes: 78 additions & 0 deletions examples/perceive_ask_and_act/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@

# Perceive, ask and Act Example

This guide walks you through running a practical example of a multi-agent system using Wise Agents. In this example, six agents (an agent interacting with a human with a text based interface, a sequential agent coordinator, and four intelligent agents) are started, allowing you to experiment with agents/humans communication and interaction in a simulated environment. It uses a sequential coordination able to share chat history between involved agents.


## Example Overview

The example consists of six agents:

1. **PerceivingAgent**: This is an agent that can perceive file changes. In case of changes it send a message with the list of books contained in books_read.txt to the SequentialCoordinator. This agent code is not part of wise-agents framework, but it's defined for this example use only in `custom_agent.py` present in the example directory.
2. **LiterateAgent**: Handles requests and provides intelligent responses. Its system message says:
*"You are an english literature expert. The user will provide you with a list of books they have read. Suggest the next 5 books they should read and ask user for their favorite one in this list"*
3. **UserQuestionAgent**: ask a question to the user and pass over the answer as part of the flow. This is not defined in the yaml, but started from `custom_agent.py` instantiating the agent from the code. It provides also a very simple text based interface to ask a question which is needed to complete the designed flow.
4. **FinalLiterateAgent**: Handles requests and provides intelligent responses. Its system message says:
*"You will receive a preference from the user. Considering the previous books read , the user's preference on your first list of suggestion, suggest the next 3 books they should read."*
5. **ActionAgent**: This agent will write what received (the books suggested) in a file (books_suggested.txt). It will override the file each time. This agent code is not part of wise-agents framework, but it's defined for this example use only in `custom_agent.py` present in the example directory.
6. **SequentialCoordinator**: Take care of coordinating the request handling from the user delagating the work to other agents in a predetermined order. Note the SequentialCoordinar here will use the `wiseagents.agents.SequentialMemoryCoordinatorWiseAgent` which share the chat history between all agents involved in the sequence, permitting them to make reasoning based on all the interaction with LLM happened in previous step. In this example, the **FinalLiterateAgent** will use info coming from **PerceivingAgent**, **LiterateAgent**, and **UserQuestionAgent** to produce the final list of 3 suggested books.

These agents are defined in YAML configuration files located in the `examples/perceive_ask_and_act` directory.

## Prerequisite For Running the Example
1. Clone the repository
2. Configure and start redis
3. Start artemis
4. Start Ollama

For detailed instructions on how to satisfy those prerequisite please refer to [prerequisites.md](../prerequisites.md)


### Step 1: Start the Intelligent Agent

In a console, run the intelligent agents and coordinator agent. Having custom created agents in the directory of example you need to run the script from there after setting PYTHONPATH env variable. Here you have all the commands needed pretending you are in the project main directory:

```bash
cd examples/perceive_ask_and_act
export PYTHONPATH="."
python ../../src/wiseagents/cli/wise_agent_cli.py ./intelligent-agents.yaml
```

This will initialize the intelligent agents and coordinator agent, which will be ready to watch `books_read.txt` for changes.

### Step 2: Start UserQuestionAgent
In a console, start the UserQuestionAgent. Having custom created agents in the directory of example you need to run the script from there after setting PYTHONPATH env variable. Here you have all the commands needed pretending you are in the project main directory:

```bash
cd examples/perceive_ask_and_act
export PYTHONPATH="."
python ./custom_agents.py
```

This will initialize the UserQuestionAgent, and will be ready to show question and accept answer from the user.

### Step 3: Interaction

Once all agents are up and running, you can edit `books_read.txt` file and `PerceivingAgent` will start sending requests to the coordinator agent. The coordinator agent will take care to interact to the `LiterateAgent`. `Literate Agent` will create a list of 5 suggested books and a question asking the user for a preference. Then the message will be sent to `UserQuestionAgent` which will show the list and the question in the console, asking for an answer. The answer inserted by the user will be passed to the `ActionAgent` which will write the results to `books_suggested.txt`. You will be able to see the interaction between the agents through the logs in both consoles.


### Step 4: Experiment

You can experiment with different agent configurations or modify the agent behaviors by editing the YAML files located in the `examples/perceive_ask_and_act` directory. These configuration files define the agents' properties, including memory, communication methods, and response patterns. You can do that without restarting everything, just edit the yaml file(s) and use CLI's /reload command (see our documentation for more details on how to use CLI)

## Understanding the YAML Configuration and custom_agents.py

- **intelligent-agents.yaml**: Defines all the agents discussed in this document and needed to run the example
- **custom_agents.py**: contain 3 custom agents defined for the purpose of this example. It has also a `main()` function which instantiate the `UserQuestionAgent`

These YAML files include the specific `WiseAgent` classes and configuration needed to run the agents. Feel free to explore and modify these files to customize the agents' behavior.

## Additional Resources

For more information about the architecture and advanced configurations of wise-agents, refer to the [Wise Agents Architecture Document](wise_agents_architecture.md), which provides insights into how the system can be scaled and deployed in distributed environments.

## Conclusion

By following these steps, you have successfully run a simple sequential coordinated multi-agent chatbot using Wise Agents. You can now explore further by modifying agent behaviors, adding new agents, or experimenting with different message flows.

For any further assistance, feel free to refer to the official Wise Agents documentation or reach out to the repository maintainers.
1 change: 1 addition & 0 deletions examples/perceive_ask_and_act/books_read.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
King Lear
155 changes: 155 additions & 0 deletions examples/perceive_ask_and_act/custom_agents.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import os
import signal
import threading
import time
from openai.types.chat import ChatCompletionToolParam, ChatCompletionMessageParam
from typing import List, Optional
from wiseagents import WiseAgent, WiseAgentEvent, WiseAgentMessage, WiseAgentTransport
from wiseagents.transports.stomp import StompWiseAgentTransport
from wiseagents.yaml import WiseAgentsLoader

class PerceivingAgent(WiseAgent):
yaml_tag = u'!custom_agents.PerceivingAgent'
yaml_loader = WiseAgentsLoader

stop_event = threading.Event()

def __init__(self, name: str, description: str, transport: WiseAgentTransport, file_path: str, check_interval: float, destination_agent_name: str):
self._file_path = file_path
self._check_interval = check_interval
self._destination_agent_name = destination_agent_name
super().__init__(name=name, description=description, transport=transport)

def start_agent(self):
super().start_agent()
self.stop_event.clear()
self.perceive(self._file_path, self.on_file_change, self._check_interval)

def stop_agent(self):
self.stop_event.set()
super().stop_agent()

def process_request(self, request: WiseAgentMessage,
conversation_history: List[ChatCompletionMessageParam]) -> Optional[str]:
pass

def process_response(self, response: WiseAgentMessage):
pass

def process_event(self, event: WiseAgentEvent):
pass

def process_error(self, error: WiseAgentMessage):
pass

def perceive(self, file_path, callback, check_interval=1.0):
"""
Monitors a file for any changes and invokes a callback with the file's content upon modification.
Args:
file_path (str): The path to the file to monitor.
callback (callable): A function to call with the file's content when it changes.
check_interval (float, optional): Time in seconds between checks. Defaults to 1.0.
"""
def watch():
try:
last_mtime = os.path.getmtime(file_path)
except FileNotFoundError:
last_mtime = None

while not self.stop_event.is_set():
try:
print(f"Checking file {file_path}")
current_mtime = os.path.getmtime(file_path)
if last_mtime is None:
last_mtime = current_mtime
elif current_mtime != last_mtime:
print(f"File {file_path} has changed")
last_mtime = current_mtime
with open(file_path, 'r') as f:
content = f.read()
callback(content)
except FileNotFoundError:
if last_mtime is not None:
last_mtime = None
except Exception as e:
print(f"Error monitoring file: {e}")
time.sleep(check_interval)

thread = threading.Thread(target=watch, daemon=True)
thread.start()

def on_file_change(self, content):
print(f"sending message: {content}, {self.name}, {self._destination_agent_name}")
self.send_request(WiseAgentMessage(content, self.name), self._destination_agent_name)

class ActionAgent(WiseAgent):
yaml_tag = u'!custom_agents.ActionAgent'
yaml_loader = WiseAgentsLoader

def __init__(self, name: str, description: str, transport: WiseAgentTransport, destination_file_path: str):
self._destination_file_path = destination_file_path
super().__init__(name=name, description=description, transport=transport)


def process_request(self, request: WiseAgentMessage, conversation_history: List[ChatCompletionMessageParam]) -> Optional[str]:
with open(self._destination_file_path, 'w') as f:
f.write(request.message)
self.send_response(WiseAgentMessage("File updated", self.name), request.sender)


def process_response(self, response: WiseAgentMessage):
pass

def process_event(self, event: WiseAgentEvent):
pass

def process_error(self, error: WiseAgentMessage):
pass

class UserQuestionAgent(WiseAgent):
yaml_tag = u'!custom_agents.UserQuestionAgent'
yaml_loader = WiseAgentsLoader

def __init__(self, name: str, description: str, transport: WiseAgentTransport):
super().__init__(name=name, description=description, transport=transport)


def process_request(self, request: WiseAgentMessage, conversation_history: List[ChatCompletionMessageParam]) -> Optional[str]:
print(f"User question: {request.message}")
userAnswer = input("Answer: ")
return userAnswer

def process_response(self, response: WiseAgentMessage):
pass

def process_event(self, event: WiseAgentEvent):
pass

def process_error(self, error: WiseAgentMessage):
pass


def signal_handler(sig, frame):
global user_question_agent
print('You pressed Ctrl+C!')
user_question_agent.stop_agent()
exit(0)



def main():
global user_question_agent
stomp_transport = StompWiseAgentTransport("localhost", 61616, "UserQuestionAgent")
#create and start the agent
user_question_agent = UserQuestionAgent(name="UserQuestionAgent", description="Asks the user a question", transport=stomp_transport)

signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C to exit')
signal.pause()
while True:
pass

if __name__ == "__main__":
main()
53 changes: 53 additions & 0 deletions examples/perceive_ask_and_act/intelligent-agents.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
!wiseagents.agents.ChatWiseAgent
_description: This is an agent that can give suggestion on what to read next
_llm: !wiseagents.llm.OpenaiAPIWiseAgentLLM
_model_name: llama3.1
_remote_address: http://localhost:11434/v1
_system_message: You are an english literature expert. The user will provide you with a list of books they have read. Suggest the next 5 books they should read and ask user for their favorite one in this list
_name: LiterateAgent
_transport: !wiseagents.transports.StompWiseAgentTransport
_host: localhost
_port: 61616
_agent_name: LiterateAgent
---
!custom_agents.PerceivingAgent
_description: This is an agent that can perceive file changes
_name: PerceivingAgent
_file_path: ./books_read.txt
_check_interval: 5
_destination_agent_name: SequentialCoordinator
_transport: !wiseagents.transports.StompWiseAgentTransport
_host: localhost
_port: 61616
_agent_name: PerceivingAgent
---
!custom_agents.ActionAgent
_description: This is an agent that can write a file
_name: ActionAgent
_destination_file_path: ./books_suggested.txt
_transport: !wiseagents.transports.StompWiseAgentTransport
_host: localhost
_port: 61616
_agent_name: ActionAgent
---
!wiseagents.agents.ChatWiseAgent
_description: This is an agent that can give suggestion on what to read next
_llm: !wiseagents.llm.OpenaiAPIWiseAgentLLM
_model_name: llama3.1
_remote_address: http://localhost:11434/v1
_system_message: You will receive a preference from the user. Considering the previous books read , the user's preference on your first list of suggestion, suggest the next 3 books they should read.
_name: FinalLiterateAgent
_transport: !wiseagents.transports.StompWiseAgentTransport
_host: localhost
_port: 61616
_agent_name: FinalLiterateAgent
---
!wiseagents.agents.SequentialMemoryCoordinatorWiseAgent
_description: This is a coordinator agent
_name: SequentialCoordinator
_agents: ["LiterateAgent", "UserQuestionAgent", "FinalLiterateAgent", "ActionAgent"]
_transport: !wiseagents.transports.StompWiseAgentTransport
_host: localhost
_port: 61616
_agent_name: SequentialCoordinator
Loading

0 comments on commit 571c2f1

Please sign in to comment.