Skip to content

Commit

Permalink
Merge branch 'master' into memory_liubo
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin-eecs authored Sep 10, 2023
2 parents a3e0d57 + e780681 commit 9cd8f52
Show file tree
Hide file tree
Showing 15 changed files with 499 additions and 15 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@
<a href="https://colab.research.google.com/drive/1AzP33O8rnMW__7ocWJhVBXjKziJXPtim?usp=sharing" target="_blank">
<img alt="Open In Colab" src="https://colab.research.google.com/assets/colab-badge.svg" />
</a>
<a href="https://huggingface.co/camel-ai" target="_blank">
<img alt="Hugging Face" src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-CAMEL--AI-ffc107?color=ffc107&logoColor=white" />
</a>
<a href="https://join.slack.com/t/camel-kwr1314/shared_invite/zt-1vy8u9lbo-ZQmhIAyWSEfSwLCl2r2eKA" target="_blank">
<img alt="Slack" src="https://img.shields.io/badge/Slack-CAMEL--AI-blueviolet?logo=slack" />
</a>
<a href="https://discord.gg/CNcNpquyDc" target="_blank">
<img alt="Discord" src="https://img.shields.io/badge/Discord-CAMEL--AI-7289da?logo=discord&logoColor=white&color=7289da" />
</a>
<a href="https://huggingface.co/camel-ai" target="_blank">
<img alt="Hugging Face" src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-CAMEL--AI-ffc107?color=ffc107&logoColor=white" />
<a href="https://ghli.org/camel/wechat.png" target="_blank">
<img alt="Discord" src="https://img.shields.io/badge/WeChat-CamelAIOrg-brightgreen?logo=wechat&logoColor=white" />
</a>
<a href="https://twitter.com/CamelAIOrg" target="_blank">
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/CamelAIOrg?style=social&color=brightgreen&logo=twitter" />
Expand Down Expand Up @@ -50,7 +53,9 @@
The rapid advancement of conversational and chat-based language models has led to remarkable progress in complex task-solving. However, their success heavily relies on human input to guide the conversation, which can be challenging and time-consuming. This paper explores the potential of building scalable techniques to facilitate autonomous cooperation among communicative agents and provide insight into their "cognitive" processes. To address the challenges of achieving autonomous cooperation, we propose a novel communicative agent framework named *role-playing*. Our approach involves using *inception prompting* to guide chat agents toward task completion while maintaining consistency with human intentions. We showcase how role-playing can be used to generate conversational data for studying the behaviors and capabilities of chat agents, providing a valuable resource for investigating conversational language models. Our contributions include introducing a novel communicative agent framework, offering a scalable approach for studying the cooperative behaviors and capabilities of multi-agent systems, and open-sourcing our library to support research on communicative agents and beyond. The GitHub repository of this project is made publicly available on: [https://github.com/camel-ai/camel](https://github.com/camel-ai/camel).

## Community
🐫 CAMEL is an open-source library designed for the study of autonomous and communicative agents. We believe that studying these agents on a large scale offers valuable insights into their behaviors, capabilities, and potential risks. To facilitate research in this field, we implement and support various types of agents, tasks, prompts, models, and simulated environments. Join us ([slack](https://join.slack.com/t/camel-kwr1314/shared_invite/zt-1vy8u9lbo-ZQmhIAyWSEfSwLCl2r2eKA), [discord](https://discord.gg/CNcNpquyDc)) in pushing the boundaries of simulating AI Society with CAMEL.
🐫 CAMEL is an open-source library designed for the study of autonomous and communicative agents. We believe that studying these agents on a large scale offers valuable insights into their behaviors, capabilities, and potential risks. To facilitate research in this field, we implement and support various types of agents, tasks, prompts, models, and simulated environments.

Join us ([*Slack*](https://join.slack.com/t/camel-kwr1314/shared_invite/zt-1vy8u9lbo-ZQmhIAyWSEfSwLCl2r2eKA), [*Discord*](https://discord.gg/CNcNpquyDc) or [*WeChat*](https://ghli.org/camel/wechat.png)) in pushing the boundaries of building AI Societiy.

## Try it yourself
We provide a [![Google Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1AzP33O8rnMW__7ocWJhVBXjKziJXPtim?usp=sharing) demo showcasing a conversation between two ChatGPT agents playing roles as a python programmer and a stock trader collaborating on developing a trading bot for stock market.
Expand Down
2 changes: 2 additions & 0 deletions camel/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .tool_agents.base import BaseToolAgent
from .tool_agents.hugging_face_tool_agent import HuggingFaceToolAgent
from .embodied_agent import EmbodiedAgent
from .role_assignment_agent import RoleAssignmentAgent

__all__ = [
'BaseAgent',
Expand All @@ -36,4 +37,5 @@
'BaseToolAgent',
'HuggingFaceToolAgent',
'EmbodiedAgent',
'RoleAssignmentAgent',
]
120 changes: 120 additions & 0 deletions camel/agents/role_assignment_agent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
# Licensed under the Apache License, Version 2.0 (the “License”);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an “AS IS” BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
import re
from typing import Any, Dict, Optional, Union

from tenacity import retry, stop_after_attempt, wait_exponential

from camel.agents import ChatAgent
from camel.messages import BaseMessage
from camel.prompts import TextPrompt
from camel.typing import ModelType, RoleType


class RoleAssignmentAgent(ChatAgent):
r"""An agent that generates role names based on the task prompt.
Attributes:
role_assignment_prompt (TextPrompt): A prompt for the agent to generate
role names.
Args:
model (ModelType, optional): The type of model to use for the agent.
(default: :obj:`ModelType.GPT_3_5_TURBO`)
model_config (Any, optional): The configuration for the model.
(default: :obj:`None`)
"""

def __init__(
self,
model: ModelType = ModelType.GPT_3_5_TURBO,
model_config: Optional[Any] = None,
) -> None:
system_message = BaseMessage(
role_name="Role Assigner",
role_type=RoleType.ASSISTANT,
meta_dict=None,
content="You assign roles based on tasks.",
)
super().__init__(system_message, model, model_config)

@retry(wait=wait_exponential(min=5, max=60), stop=stop_after_attempt(5))
def run(
self,
task_prompt: Union[str, TextPrompt],
num_roles: int = 2,
) -> Dict[str, str]:
r"""Generate role names based on the input task prompt.
Args:
task_prompt (Union[str, TextPrompt]): The prompt
for the task based on which the roles are to be generated.
num_roles (int, optional): The number of roles to generate.
(default: :obj:`2`)
Returns:
Dict[str, str]: A dictionary mapping role names to their
descriptions.
"""
self.reset()

expert_prompt = "===== ANSWER PROMPT =====\n" + "\n".join(
f"Domain expert {i + 1}: <BLANK>\n"
f"Associated competencies, characteristics, duties "
f"and workflows: <BLANK>. End." for i in range(num_roles or 0))
role_assignment_generation_prompt = TextPrompt(
"You are a role assignment agent, and you're in charge of " +
"recruiting {num_roles} experts for the following task." +
"\n==== TASK =====\n {task}\n\n" +
"Identify the domain experts you'd recruit and detail their " +
"associated competencies, characteristics, duties and workflows " +
"to complete the task.\n " +
"Your answer MUST adhere to the format of ANSWER PROMPT, and " +
"ONLY answer the BLANKs.\n" + expert_prompt)
role_assignment_generation = role_assignment_generation_prompt.format(
num_roles=num_roles, task=task_prompt)

role_assignment_generation_msg = BaseMessage.make_user_message(
role_name="Role Assigner", content=role_assignment_generation)

response = self.step(input_message=role_assignment_generation_msg)

msg = response.msg # type: BaseMessage
terminated = response.terminated

# Distribute the output completions into role names and descriptions
role_names = [
desc.replace("<|", "").replace("|>", "") for desc in re.findall(
r"Domain expert \d: (.+?)\nAssociated competencies,",
msg.content,
re.DOTALL,
)
]
role_descriptions = [
desc.replace("<|", "").replace("|>", "") for desc in re.findall(
r"Associated competencies, characteristics, "
r"duties and workflows: (.+?) End.", msg.content, re.DOTALL)
]

if len(role_names) != num_roles or len(role_descriptions) != num_roles:
raise RuntimeError(
"Got None or insufficient information of roles.")
if terminated:
raise RuntimeError("Role assignment failed.")

role_descriptions_dict = {
role_name: description
for role_name, description in zip(role_names, role_descriptions)
}

return role_descriptions_dict
3 changes: 1 addition & 2 deletions camel/functions/search_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
from typing import List

import wikipedia

from .openai_function import OpenAIFunction


Expand All @@ -29,6 +27,7 @@ def search_wiki(entity: str) -> str:
string: The search result. If the page corresponding to the entity
exists, return the summary of this entity in a string.
"""
import wikipedia
result: str

try:
Expand Down
2 changes: 2 additions & 0 deletions camel/prompts/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .translation import TranslationPromptTemplateDict
from .solution_extraction import SolutionExtractionPromptTemplateDict
from .evaluation import EvaluationPromptTemplateDict
from .role_description_prompt_template import RoleDescriptionPromptTemplateDict
from .task_prompt_template import TaskPromptTemplateDict
from .prompt_templates import PromptTemplateGenerator

Expand All @@ -30,6 +31,7 @@
'MisalignmentPromptTemplateDict',
'TranslationPromptTemplateDict',
'EvaluationPromptTemplateDict',
'RoleDescriptionPromptTemplateDict',
'TaskPromptTemplateDict',
'PromptTemplateGenerator',
'SolutionExtractionPromptTemplateDict',
Expand Down
8 changes: 4 additions & 4 deletions camel/prompts/ai_society.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ class AISocietyPromptTemplateDict(TextPromptDict):
Please reply with the specified task in {word_limit} words or less. Do not add anything else."""
)

ASSISTANT_PROMPT: TextPrompt = TextPrompt(
"""Never forget you are a {assistant_role} and I am a {user_role}. Never flip roles! Never instruct me!
ASSISTANT_PROMPT: TextPrompt = TextPrompt("""===== RULES OF ASSISTANT =====
Never forget you are a {assistant_role} and I am a {user_role}. Never flip roles! Never instruct me!
We share a common interest in collaborating to successfully complete a task.
You must help me to complete the task.
Here is the task: {task}. Never forget our task!
Expand All @@ -75,8 +75,8 @@ class AISocietyPromptTemplateDict(TextPromptDict):
<YOUR_SOLUTION> should be very specific, include detailed explanations and provide preferable detailed implementations and examples and lists for task-solving.
Always end <YOUR_SOLUTION> with: Next request.""")

USER_PROMPT: TextPrompt = TextPrompt(
"""Never forget you are a {user_role} and I am a {assistant_role}. Never flip roles! You will always instruct me.
USER_PROMPT: TextPrompt = TextPrompt("""===== RULES OF USER =====
Never forget you are a {user_role} and I am a {assistant_role}. Never flip roles! You will always instruct me.
We share a common interest in collaborating to successfully complete a task.
I must help you to complete the task.
Here is the task: {task}. Never forget our task!
Expand Down
53 changes: 53 additions & 0 deletions camel/prompts/role_description_prompt_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
# Licensed under the Apache License, Version 2.0 (the “License”);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an “AS IS” BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
from typing import Any

from camel.prompts import AISocietyPromptTemplateDict, TextPrompt
from camel.typing import RoleType


# flake8: noqa :E501
class RoleDescriptionPromptTemplateDict(AISocietyPromptTemplateDict):
r"""A dictionary containing :obj:`TextPrompt` used in the `role description`
task.
Attributes:
ROLE_DESCRIPTION_PROMPT (TextPrompt): A default prompt to
describe the role descriptions.
ASSISTANT_PROMPT (TextPrompt): A system prompt for the AI assistant
that outlines the rules of the conversation and provides
instructions for completing tasks.
USER_PROMPT (TextPrompt): A system prompt for the AI user that
outlines the rules of the conversation and provides instructions
for giving instructions to the AI assistant.
"""
ROLE_DESCRIPTION_PROMPT = TextPrompt("""===== ROLES WITH DESCRIPTION =====
{user_role} and {assistant_role} are collaborating to complete a task: {task}.
Competencies, characteristics, duties and workflows of {user_role} to complete the task: {user_description}
{assistant_role}'s competencies, characteristics, duties and workflows to complete the task: {assistant_description}
""")

ASSISTANT_PROMPT = TextPrompt(ROLE_DESCRIPTION_PROMPT +
AISocietyPromptTemplateDict.ASSISTANT_PROMPT)

USER_PROMPT = TextPrompt(ROLE_DESCRIPTION_PROMPT +
AISocietyPromptTemplateDict.USER_PROMPT)

def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self.update({
"role_description": self.ROLE_DESCRIPTION_PROMPT,
RoleType.ASSISTANT: self.ASSISTANT_PROMPT,
RoleType.USER: self.USER_PROMPT,
})
3 changes: 3 additions & 0 deletions camel/prompts/task_prompt_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
CodePromptTemplateDict,
EvaluationPromptTemplateDict,
MisalignmentPromptTemplateDict,
RoleDescriptionPromptTemplateDict,
SolutionExtractionPromptTemplateDict,
TextPromptDict,
TranslationPromptTemplateDict,
Expand Down Expand Up @@ -50,4 +51,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
EvaluationPromptTemplateDict(),
TaskType.SOLUTION_EXTRACTION:
SolutionExtractionPromptTemplateDict(),
TaskType.ROLE_DESCRIPTION:
RoleDescriptionPromptTemplateDict(),
})
16 changes: 10 additions & 6 deletions camel/societies/role_playing.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def __init__(

sys_msg_generator = SystemMessageGenerator(
task_type=self.task_type, **(sys_msg_generator_kwargs or {}))

(init_assistant_sys_msg, init_user_sys_msg,
sys_msg_meta_dicts) = self.get_sys_message_info(
assistant_role_name, user_role_name, sys_msg_generator,
Expand All @@ -131,7 +132,6 @@ def __init__(
user_agent_kwargs,
output_language,
)

self.critic: Optional[Union[CriticAgent, Human]] = None
self.critic_sys_msg: Optional[BaseMessage] = None
self.init_critic(critic_role_name, critic_criteria, critic_kwargs,
Expand Down Expand Up @@ -211,9 +211,11 @@ def init_planned_task_prompt(self,
self.planned_task_prompt = None

def get_sys_message_info(
self, assistant_role_name: str, user_role_name: str,
self,
assistant_role_name: str,
user_role_name: str,
sys_msg_generator: SystemMessageGenerator,
extend_sys_msg_meta_dicts: Optional[List[Dict]]
extend_sys_msg_meta_dicts: Optional[List[Dict]] = None,
) -> Tuple[BaseMessage, BaseMessage, List[Dict]]:
r"""Get initial assistant and user system message with a list of
system message meta dicts.
Expand All @@ -233,12 +235,15 @@ def get_sys_message_info(
initial system message, and a list of system message meta dicts.
"""
sys_msg_meta_dicts = [dict(task=self.task_prompt) for _ in range(2)]
if (extend_sys_msg_meta_dicts is None and self.task_type
in [TaskType.AI_SOCIETY, TaskType.MISALIGNMENT]):
if (extend_sys_msg_meta_dicts is None and self.task_type in [
TaskType.AI_SOCIETY,
TaskType.MISALIGNMENT,
]):
extend_sys_msg_meta_dicts = [
dict(assistant_role=assistant_role_name,
user_role=user_role_name) for _ in range(2)
]

if extend_sys_msg_meta_dicts is not None:
sys_msg_meta_dicts = [{
**sys_msg_meta_dict,
Expand Down Expand Up @@ -426,7 +431,6 @@ def step(
whether the user agent terminated the conversation, and any
additional user information.
"""

user_response = self.user_agent.step(assistant_msg)
if user_response.terminated or user_response.msgs is None:
return (ChatAgentResponse([], False, {}),
Expand Down
1 change: 1 addition & 0 deletions camel/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class TaskType(Enum):
TRANSLATION = "translation"
EVALUATION = "evaluation"
SOLUTION_EXTRACTION = "solution_extraction"
ROLE_DESCRIPTION = "role_description"
DEFAULT = "default"


Expand Down
43 changes: 43 additions & 0 deletions examples/role_description/role_generation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
# Licensed under the Apache License, Version 2.0 (the “License”);
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an “AS IS” BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# =========== Copyright 2023 @ CAMEL-AI.org. All Rights Reserved. ===========
from colorama import Fore

from camel.agents import RoleAssignmentAgent
from camel.configs import ChatGPTConfig


def main(model_type=None, num_roles=3) -> None:
task_prompt = "Develop a trading bot for the stock market."

model_config_description = ChatGPTConfig()
role_description_agent = RoleAssignmentAgent(
model=model_type, model_config=model_config_description)

role_description_dict = role_description_agent.run(task_prompt=task_prompt,
num_roles=num_roles)

if (len(role_description_dict) != num_roles):
raise ValueError(
f"Length of role_names ({len(role_description_dict)}) "
f"does not equal to num_roles ({num_roles}).")

print(Fore.YELLOW + f"Original task prompt:\n{task_prompt}\n")
print(Fore.GREEN + f"List of {num_roles} roles with description:")
for role_name in role_description_dict.keys():
print(Fore.BLUE + f"{role_name}:\n"
f"{role_description_dict[role_name]}\n")


if __name__ == "__main__":
main()
Loading

0 comments on commit 9cd8f52

Please sign in to comment.