-
Notifications
You must be signed in to change notification settings - Fork 352
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add example for router agent
- Loading branch information
Showing
5 changed files
with
206 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Conversation with Router Agent | ||
|
||
This example will show | ||
- How to build a router agent to route questions to agents with different abilities. | ||
|
||
The router agent is expected to route questions to the corresponding agents according to the question type in the following response | ||
```text | ||
<thought>{The thought of router agent}</thought> | ||
<agent>{agent name}</agent> | ||
``` | ||
If the router agent decides to answer the question itself, the response should be | ||
```text | ||
<thought>{The thought of router agent}</thought> | ||
<response>{The answer}</response> | ||
``` | ||
|
||
## Note | ||
This example is only for demonstration purposes. We simply use two agents who are good at math and history respectively. | ||
You can replace them with any other agents according to your needs. | ||
|
||
Besides, the memory management of the involved agents is not considered in this example. | ||
For example, does the router agent need to know the answer from the sub-agents? | ||
Improvements are encouraged by developers according to their own needs. | ||
|
||
## Tested Models | ||
|
||
These models are tested in this example. For other models, some modifications may be needed. | ||
- gpt-4o | ||
- qwen-max | ||
|
||
|
||
## Prerequisites | ||
|
||
1. Fill your model configuration correctly in `main.py`. | ||
2. Install the latest version of Agentscope from GitHub. | ||
```bash | ||
git clone https://github.com/modelscope/agentscope.git | ||
cd agentscope | ||
pip install -e . | ||
``` | ||
3. Run the example and input your questions. | ||
```bash | ||
python main.py | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# -*- coding: utf-8 -*- | ||
"""The main script for the example of conversation with router agent.""" | ||
from router_agent import RouterAgent | ||
|
||
import agentscope | ||
from agentscope.agents import DialogAgent, UserAgent | ||
|
||
# ================== Prepare model configuration ============================= | ||
|
||
YOUR_MODEL_CONFIGURATION_NAME = "{YOUR_MODEL_CONFIGURATION_NAME}" | ||
YOUR_MODEL_CONFIGURATION = { | ||
"config_name": YOUR_MODEL_CONFIGURATION_NAME, | ||
# ... | ||
} | ||
|
||
# ============================================================================ | ||
|
||
agentscope.init( | ||
model_configs=YOUR_MODEL_CONFIGURATION, | ||
project="Conversation with router agent", | ||
) | ||
|
||
# Let's build some working agents with different capabilities. For simplicity, | ||
# we just use the same agent. You can replace them with your own agents. | ||
agent_math = DialogAgent( | ||
name="Math", | ||
sys_prompt="You are a math assistant to help solve math problems.", | ||
model_config_name=YOUR_MODEL_CONFIGURATION_NAME, | ||
) | ||
|
||
agent_history = DialogAgent( | ||
name="History", | ||
sys_prompt="You are an assistant who is good at history.", | ||
model_config_name=YOUR_MODEL_CONFIGURATION_NAME, | ||
) | ||
|
||
# Init a router agent | ||
SYS_PROMPT_ROUTER = """You're a router assistant named {name}. | ||
## YOUR TARGET | ||
1. Given agents with different capabilities, your target is to assign questions to the corresponding agents according to the user requirement. | ||
2. You should make full use of the different abilities of the given agents. | ||
3. If no agent is suitable to answer user's question, then respond directly. | ||
## Agents You Can Use | ||
The agents are listed in the format of "{index}. {agent_name}: {agent_description}" | ||
1. math: An agent who is good at math. | ||
2. history: An agent who is good at history. | ||
""" # noqa | ||
|
||
router_agent = RouterAgent( | ||
sys_prompt=SYS_PROMPT_ROUTER, | ||
model_config_name=YOUR_MODEL_CONFIGURATION_NAME, | ||
) | ||
|
||
# Init a user agent | ||
user = UserAgent(name="user") | ||
|
||
# Start the conversation | ||
msg = None | ||
while True: | ||
user_msg = user(msg) | ||
if user_msg.content == "exit": | ||
break | ||
|
||
# Replied by router agent | ||
router_msg = router_agent(user_msg) | ||
|
||
# Route the question to the corresponding agents | ||
if router_msg.metadata == "math": | ||
msg = agent_math(user_msg) | ||
elif router_msg.metadata == "history": | ||
msg = agent_history(user_msg) | ||
else: | ||
# Answer the question by router agent directly | ||
msg = router_msg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# -*- coding: utf-8 -*- | ||
"""The router agent which routes the questions to the corresponding agents.""" | ||
from typing import Optional, Union, Sequence | ||
|
||
from agentscope.agents import AgentBase | ||
from agentscope.message import Msg | ||
from agentscope.parsers import RegexTaggedContentParser | ||
|
||
|
||
# Init a router agent | ||
class RouterAgent(AgentBase): | ||
""" | ||
The router agent who routes the questions to the corresponding agents. | ||
""" | ||
|
||
def __init__( | ||
self, | ||
sys_prompt: str, | ||
model_config_name: str, | ||
) -> None: | ||
"""Init a router agent.""" | ||
self.name = "Router" | ||
|
||
super().__init__( | ||
name=self.name, | ||
model_config_name=model_config_name, | ||
) | ||
|
||
self.sys_prompt = sys_prompt.format_map({"name": self.name}) | ||
|
||
self.memory.add(Msg(self.name, self.sys_prompt, "system")) | ||
|
||
self.parser = RegexTaggedContentParser( | ||
format_instruction="""Respond with specific tags as outlined below: | ||
- When routing questions to agents: | ||
<thought>what you thought</thought> | ||
<agent>the agent name</agent> | ||
- When answering questions directly: | ||
<thought>what you thought</thought> | ||
<response>what you respond</response> | ||
""", | ||
required_keys=["thought"], | ||
) | ||
|
||
def reply(self, x: Optional[Union[Msg, Sequence[Msg]]] = None) -> Msg: | ||
"""The reply function.""" | ||
self.memory.add(x) | ||
|
||
prompt = self.model.format( | ||
self.memory.get_memory(), | ||
Msg("system", self.parser.format_instruction, "system"), | ||
) | ||
|
||
response = self.model(prompt) | ||
|
||
# To be compatible with streaming mode | ||
self.speak(response.stream or response.text) | ||
|
||
# Parse the response by predefined parser | ||
parsed_dict = self.parser.parse(response).parsed | ||
|
||
msg = Msg(self.name, response.text, "assistant") | ||
|
||
# Assign the question to the corresponding agent in the metadata field | ||
if "agent" in parsed_dict: | ||
msg.metadata = parsed_dict["agent"] | ||
|
||
self.memory.add(msg) | ||
|
||
return msg |