-
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 a group chat example with '@' mention feature. (#55)
- Loading branch information
1 parent
197d597
commit 1d4c6f9
Showing
10 changed files
with
281 additions
and
7 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
# Multi-Agent Group Conversation in AgentScope | ||
|
||
This example demonstrates a multi-agent group conversation facilitated by AgentScope. The script `main.py` sets up a virtual chat room where a user agent interacts with several NPC (non-player character) agents. The chat utilizes a special **"@"** mention functionality, which allows participants to address specific agents and have a more directed conversation. | ||
|
||
## Key Features | ||
|
||
- **Real-time Group Conversation**: Engage in a chat with multiple agents responding in real time. | ||
- **@ Mention Functionality**: Use the "@" symbol followed by an agent's name to specifically address that agent within the conversation. | ||
- **Dynamic Flow**: User-driven conversation with agents responding based on the context and mentions. | ||
- **Configurable Agent Roles**: Easily modify agent roles and behaviors by editing the `sys_prompt` in the configuration files. | ||
- **User Timeout**: If the user does not respond within a specified time, the conversation continues with the next agent. | ||
|
||
## How to Use | ||
|
||
To start the group conversation, follow these steps: | ||
|
||
1. Make sure to set your `api_key` in the `configs/model_configs.json` file. | ||
2. Run the script using the following command: | ||
|
||
```bash | ||
python main.py | ||
|
||
# or launch agentscope studio | ||
as_studio main.py | ||
``` | ||
|
||
1. To address a specific agent in the chat, type "@" followed by the agent's name in your message. | ||
2. To exit the chat, simply type "exit" when it's your turn to speak. | ||
|
||
## Background and Conversation Flow | ||
|
||
The conversation takes place in a simulated chat room environment with roles defined for each participant. The user acts as a regular chat member with the ability to speak freely and address any agent. NPC agents are pre-configured with specific roles that determine their responses and behavior in the chat. The topic of the conversation is open-ended and can evolve organically based on the user's input and agents' programmed personas. | ||
|
||
### Example Interaction | ||
|
||
``` | ||
User input: Hi, everyone! I'm excited to join this chat. | ||
AgentA: Welcome! We're glad to have you here. | ||
User input: @AgentB, what do you think about the new technology trends? | ||
AgentB: It's an exciting time for tech! There are so many innovations on the horizon. | ||
... | ||
``` | ||
|
||
## Customization Options | ||
|
||
The group conversation script provides several options for customization, allowing you to tailor the chat experience to your preferences. | ||
|
||
You can customize the conversation by editing the agent configurations and model parameters. The `agent_configs.json` file allows you to set specific behaviors for each NPC agent, while `model_configs.json` contains the parameters for the conversation model. | ||
|
||
### Changing User Input Time Limit | ||
|
||
The `USER_TIME_TO_SPEAK` variable sets the time limit (in seconds) for the user to input their message during each round. By default, this is set to 10 seconds. You can adjust this time limit by modifying the value of `USER_TIME_TO_SPEAK` in the `main.py` script. | ||
|
||
For example, to change the time limit to 20 seconds, update the line in `main.py` as follows: | ||
|
||
``` | ||
USER_TIME_TO_SPEAK = 20 # User has 20 seconds to type their message | ||
``` | ||
|
||
### Setting a Default Topic for the Chat Room | ||
|
||
The `DEFAULT_TOPIC` variable defines the initial message or topic of the chat room. It sets the stage for the conversation and is announced at the beginning of the chat session. You can change this message to prompt a specific discussion topic or to provide instructions to the agents. | ||
|
||
To customize this message, modify the `DEFAULT_TOPIC` variable in the `main.py` script. For instance, if you want to set the default topic to discuss "The Future of Artificial Intelligence," you would change the code as follows: | ||
|
||
```python | ||
DEFAULT_TOPIC = """ | ||
This is a chat room about the Future of Artificial Intelligence and you can | ||
speak freely and briefly. | ||
""" | ||
``` | ||
|
||
With these customizations, the chat room can be tailored to fit specific themes or time constraints, enhancing the user's control over the chat experience. |
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,29 @@ | ||
[ | ||
{ | ||
"class": "DialogAgent", | ||
"args": { | ||
"name": "Lingfeng", | ||
"sys_prompt":"You are Lingfeng, a noble in the imperial court, known for your wisdom and strategic acumen. You often engage in complex political intrigues and have recently suspected the Queen’s adviser of treachery. Your speaking style is reminiscent of classical literature.", | ||
"model_config_name": "gpt-4", | ||
"use_memory": true | ||
} | ||
}, | ||
{ | ||
"class": "DialogAgent", | ||
"args": { | ||
"name": "Boyu", | ||
"sys_prompt":"You are Boyu, a friend of Lingfeng and an enthusiast of court dramas. Your speech is modern but with a flair for the dramatic, matching your love for emotive storytelling. You've been closely following Lingfeng’s political maneuvers in the imperial court through secret correspondence.", | ||
"model_config_name": "gpt-4", | ||
"use_memory": true | ||
} | ||
}, | ||
{ | ||
"class": "DialogAgent", | ||
"args": { | ||
"name": "Haotian", | ||
"sys_prompt":"You are Haotian, Lingfeng’s cousin who prefers the open fields to the confines of court life. As a celebrated athlete, your influence has protected Lingfeng in times of political strife. You promote physical training as a way to prepare for life's battles, often using sports metaphors in conversation.", | ||
"model_config_name": "gpt-4", | ||
"use_memory": true | ||
} | ||
} | ||
] |
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,19 @@ | ||
[ | ||
{ | ||
"model_type": "openai", | ||
"config_name": "gpt-4", | ||
"model_name": "gpt-4", | ||
"api_key": "xxx", | ||
"organization": "xxx", | ||
"generate_args": { | ||
"temperature": 0.5 | ||
} | ||
}, | ||
{ | ||
"model_type": "post_api_chat", | ||
"config_name": "my_post_api", | ||
"api_url": "https://xxx", | ||
"headers": {}, | ||
"json_args": {} | ||
} | ||
] |
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,37 @@ | ||
# -*- coding: utf-8 -*- | ||
""" Group chat utils.""" | ||
import re | ||
from typing import Sequence | ||
|
||
|
||
def select_next_one(agents: Sequence, rnd: int) -> Sequence: | ||
""" | ||
Select next agent. | ||
""" | ||
return agents[rnd % len(agents)] | ||
|
||
|
||
def filter_agents(string: str, agents: Sequence) -> Sequence: | ||
""" | ||
This function filters the input string for occurrences of the given names | ||
prefixed with '@' and returns a list of the found names. | ||
""" | ||
if len(agents) == 0: | ||
return [] | ||
|
||
# Create a pattern that matches @ followed by any of the candidate names | ||
pattern = ( | ||
r"@(" + "|".join(re.escape(agent.name) for agent in agents) + r")\b" | ||
) | ||
|
||
# Find all occurrences of the pattern in the string | ||
matches = re.findall(pattern, string) | ||
|
||
# Create a dictionary mapping agent names to agent objects for quick lookup | ||
agent_dict = {agent.name: agent for agent in agents} | ||
|
||
# Return the list of matched agent objects preserving the order | ||
ordered_agents = [ | ||
agent_dict[name] for name in matches if name in agent_dict | ||
] | ||
return ordered_agents |
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,77 @@ | ||
# -*- coding: utf-8 -*- | ||
""" A group chat where user can talk any time implemented by agentscope. """ | ||
from loguru import logger | ||
from groupchat_utils import ( | ||
select_next_one, | ||
filter_agents, | ||
) | ||
|
||
import agentscope | ||
from agentscope.agents import UserAgent | ||
from agentscope.message import Msg | ||
from agentscope.msghub import msghub | ||
|
||
USER_TIME_TO_SPEAK = 10 | ||
DEFAULT_TOPIC = """ | ||
This is a chat room and you can speak freely and briefly. | ||
""" | ||
|
||
SYS_PROMPT = """ | ||
You can designate a member to reply to your message, you can use the @ symbol. | ||
This means including the @ symbol in your message, followed by | ||
that person's name, and leaving a space after the name. | ||
All participants are: {agent_names} | ||
""" | ||
|
||
|
||
def main() -> None: | ||
"""group chat""" | ||
npc_agents = agentscope.init( | ||
model_configs="./configs/model_configs.json", | ||
agent_configs="./configs/agent_configs.json", | ||
) | ||
|
||
user = UserAgent() | ||
|
||
agents = list(npc_agents) + [user] | ||
|
||
hint = Msg( | ||
name="Host", | ||
content=DEFAULT_TOPIC | ||
+ SYS_PROMPT.format( | ||
agent_names=[agent.name for agent in agents], | ||
), | ||
) | ||
|
||
rnd = 0 | ||
speak_list = [] | ||
with msghub(agents, announcement=hint): | ||
while True: | ||
try: | ||
x = user(timeout=USER_TIME_TO_SPEAK) | ||
if x.content == "exit": | ||
break | ||
except TimeoutError: | ||
x = {"content": ""} | ||
logger.info( | ||
f"User has not typed text for " | ||
f"{USER_TIME_TO_SPEAK} seconds, skip.", | ||
) | ||
|
||
speak_list += filter_agents(x.get("content", ""), npc_agents) | ||
|
||
if len(speak_list) > 0: | ||
next_agent = speak_list.pop(0) | ||
x = next_agent() | ||
else: | ||
next_agent = select_next_one(npc_agents, rnd) | ||
x = next_agent() | ||
|
||
speak_list += filter_agents(x.content, npc_agents) | ||
|
||
rnd += 1 | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
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
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