Skip to content

Commit

Permalink
Merge branch 'master' into feature/ReAct
Browse files Browse the repository at this point in the history
The file structure in master branch was modified to be different as this
branch. The merge is for convenience of developing later.
  • Loading branch information
HalberdOfPineapple committed Jun 26, 2023
2 parents 8917b15 + cde10f8 commit 689adc8
Show file tree
Hide file tree
Showing 36 changed files with 578 additions and 299 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -415,3 +415,8 @@ tags

# Camel
logs/

# Data
datasets_test/
evaluation_data/
camel_data/
3 changes: 2 additions & 1 deletion apps/agents/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
import tenacity

from apps.agents.text_utils import split_markdown_code
from camel.agents import RolePlaying, TaskSpecifyAgent
from camel.agents import TaskSpecifyAgent
from camel.messages import AssistantChatMessage
from camel.societies import RolePlaying

REPO_ROOT = os.path.realpath(
os.path.join(os.path.dirname(os.path.abspath(__file__)), "../.."))
Expand Down
2 changes: 0 additions & 2 deletions camel/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from .tool_agents.base import BaseToolAgent
from .tool_agents.hugging_face_tool_agent import HuggingFaceToolAgent
from .embodied_agent import EmbodiedAgent
from .role_playing import RolePlaying

__all__ = [
'BaseAgent',
Expand All @@ -29,5 +28,4 @@
'BaseToolAgent',
'HuggingFaceToolAgent',
'EmbodiedAgent',
'RolePlaying',
]
45 changes: 35 additions & 10 deletions camel/agents/chat_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,9 @@
from camel.agents import BaseAgent
from camel.configs import ChatGPTConfig
from camel.messages import ChatMessage, MessageType, SystemMessage
from camel.model_backend import ModelBackend, ModelFactory
from camel.models import BaseModelBackend, ModelFactory
from camel.typing import ModelType, RoleType
from camel.utils import (
get_model_token_limit,
num_tokens_from_messages,
openai_api_key_required,
)
from camel.utils import num_tokens_from_messages, openai_api_key_required


@dataclass(frozen=True)
Expand Down Expand Up @@ -67,6 +63,8 @@ class ChatAgent(BaseAgent):
message_window_size (int, optional): The maximum number of previous
messages to include in the context window. If `None`, no windowing
is performed. (default: :obj:`None`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
"""

def __init__(
Expand All @@ -75,20 +73,24 @@ def __init__(
model: Optional[ModelType] = None,
model_config: Optional[Any] = None,
message_window_size: Optional[int] = None,
output_language: Optional[str] = None,
) -> None:

self.system_message: SystemMessage = system_message
self.role_name: str = system_message.role_name
self.role_type: RoleType = system_message.role_type
self.output_language: Optional[str] = output_language
if output_language is not None:
self.set_output_language(self.output_language)

self.model: ModelType = (model if model is not None else
ModelType.GPT_3_5_TURBO)
self.model_config: ChatGPTConfig = model_config or ChatGPTConfig()
self.model_token_limit: int = get_model_token_limit(self.model)
self.message_window_size: Optional[int] = message_window_size

self.model_backend: ModelBackend = ModelFactory.create(
self.model_backend: BaseModelBackend = ModelFactory.create(
self.model, self.model_config.__dict__)
self.model_token_limit: int = self.model_backend.token_limit

self.terminated: bool = False
self.init_messages()
Expand All @@ -104,6 +106,25 @@ def reset(self) -> List[MessageType]:
self.init_messages()
return self.stored_messages

def set_output_language(self, output_language: str) -> SystemMessage:
r"""Sets the output language for the system message. This method
updates the output language for the system message. The output
language determines the language in which the output text should be
generated.
Args:
output_language (str): The desired output language.
Returns:
SystemMessage: The updated system message object.
"""
self.output_language = output_language
content = (self.system_message.content +
("\nRegardless of the input language, "
f"you must output text in {output_language}."))
self.system_message = self.system_message.create_new_instance(content)
return self.system_message

def get_info(
self,
id: Optional[str],
Expand Down Expand Up @@ -161,14 +182,18 @@ def step(
Args:
input_message (ChatMessage): The input message to the agent.
Its `role` field that specifies the role at backen may be either
`user` or `assistant` but it will be set to `user` anyway since
for the self agent any incoming message is external.
Returns:
ChatAgentResponse: A struct
containing the output messages, a boolean indicating whether
the chat session has terminated, and information about the chat
session.
"""
messages = self.update_messages(input_message)
msg_user_at_backend = input_message.set_user_role_at_backend()
messages = self.update_messages(msg_user_at_backend)
if self.message_window_size is not None and len(
messages) > self.message_window_size:
messages = [self.system_message
Expand All @@ -180,7 +205,7 @@ def step(
info: Dict[str, Any]

if num_tokens < self.model_token_limit:
response = self.model_backend.run(messages=openai_messages)
response = self.model_backend.run(openai_messages)
if not isinstance(response, dict):
raise RuntimeError("OpenAI returned unexpected struct")
output_messages = [
Expand Down
2 changes: 1 addition & 1 deletion camel/agents/critic_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ def step(self, messages: Sequence[ChatMessage]) -> ChatMessage:
input_msg = copy.deepcopy(meta_chat_message)
input_msg.content = flatten_options

option = self.get_option(input_msg.set_user_role_at_backend())
option = self.get_option(input_msg)
output_msg = copy.deepcopy(meta_chat_message)
output_msg.content = option

Expand Down
24 changes: 17 additions & 7 deletions camel/agents/task_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


class TaskSpecifyAgent(ChatAgent):
r"""An agent that Specifies a given task prompt by prompting the user to
r"""An agent that specifies a given task prompt by prompting the user to
provide more details.
Attributes:
Expand All @@ -39,6 +39,8 @@ class TaskSpecifyAgent(ChatAgent):
the task. (default: :obj:`None`)
word_limit (int): The word limit for the task prompt.
(default: :obj:`50`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
"""
DEFAULT_WORD_LIMIT = 50

Expand All @@ -49,6 +51,7 @@ def __init__(
model_config: Optional[Any] = None,
task_specify_prompt: Optional[Union[str, TextPrompt]] = None,
word_limit: int = DEFAULT_WORD_LIMIT,
output_language: str = None,
) -> None:

if task_specify_prompt is None:
Expand All @@ -67,7 +70,9 @@ def __init__(
role_type=RoleType.ASSISTANT,
content="You can make a task more specific.",
)
super().__init__(system_message, model, model_config)

super().__init__(system_message, model, model_config,
output_language=output_language)

def step(
self,
Expand Down Expand Up @@ -121,12 +126,15 @@ class TaskPlannerAgent(ChatAgent):
(default: :obj:`ModelType.GPT_3_5_TURBO`)
model_config (Any): The configuration for the model.
(default: :obj:`None`)
output_language (str, optional): The language to be output by the
agent. (default: :obj:`None`)
"""

def __init__(
self,
model: Optional[ModelType] = None,
model_config: Any = None,
output_language: str = None,
) -> None:

self.task_planner_prompt = TextPrompt(
Expand All @@ -137,7 +145,9 @@ def __init__(
role_type=RoleType.ASSISTANT,
content="You are a helpful task planner.",
)
super().__init__(system_message, model, model_config)

super().__init__(system_message, model, model_config,
output_language=output_language)

def step(
self,
Expand All @@ -160,12 +170,12 @@ def step(
task_msg = UserChatMessage(role_name="Task Planner",
content=self.task_planner_prompt)
# sub_tasks_msgs, terminated, _
task_tesponse = super().step(task_msg)
task_response = super().step(task_msg)

if task_tesponse.msgs is None:
if task_response.msgs is None:
raise RuntimeError("Got None Subtasks messages.")
if task_tesponse.terminated:
if task_response.terminated:
raise RuntimeError("Task planning failed.")

sub_tasks_msg = task_tesponse.msgs[0]
sub_tasks_msg = task_response.msgs[0]
return TextPrompt(sub_tasks_msg.content)
8 changes: 8 additions & 0 deletions camel/agents/tool_agents/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,13 @@ def __init__(self, name: str, description: str) -> None:
self.name = name
self.description = description

def reset(self) -> None:
r"""Resets the agent to its initial state."""
pass

def step(self) -> None:
r"""Performs a single step of the agent."""
pass

def __str__(self) -> str:
return f"{self.name}: {self.description}"
38 changes: 19 additions & 19 deletions camel/agents/tool_agents/hugging_face_tool_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ def __init__(
"pip install huggingface_hub==0.14.1 transformers==4.29.0 diffusers accelerate datasets torch soundfile sentencepiece opencv-python"
)
self.agent = OpenAiAgent(*args, **kwargs)
self.name = name
self.remote = remote
self.description = f"""The `{self.name}` is a tool agent that can perform a variety of tasks including:
description = f"""The `{name}` is a tool agent that can perform a variety of tasks including:
- Document question answering: given a document (such as a PDF) in image format, answer a question on this document
- Text question answering: given a long text and a question, answer the question in the text
- Unconditional image captioning: Caption the image!
Expand All @@ -73,73 +71,75 @@ def __init__(
Single execution (step) mode, the single execution method is when using the step() method of the agent:
```
# Text to image
rivers_and_lakes_image = {self.name}.step("Draw me a picture of rivers and lakes.")
rivers_and_lakes_image = {name}.step("Draw me a picture of rivers and lakes.")
rivers_and_lakes_image.save("./rivers_and_lakes_image.png")
# Text to image -> Image transformation
sea_add_island_image = {self.name}.step("Draw me a picture of the sea then transform the picture to add an island")
sea_add_island_image = {name}.step("Draw me a picture of the sea then transform the picture to add an island")
sea_add_island_image.save("./sea_add_island_image.png")
# If you'd like to keep a state across executions or to pass non-text objects to the agent,
# you can do so by specifying variables that you would like the agent to use. For example,
# you could generate the first image of rivers and lakes, and ask the model to update that picture to add an island by doing the following:
picture = {self.name}.step("Generate a picture of rivers and lakes.")
picture = {name}.step("Generate a picture of rivers and lakes.")
picture.save("./picture.png")
updated_picture = {self.name}.step("Transform the image in `picture` to add an island to it.", picture=picture)
updated_picture = {name}.step("Transform the image in `picture` to add an island to it.", picture=picture)
updated_picture.save("./updated_picture.png")
capybara_sea_image = {self.name}.step("Draw me a picture of the `prompt`", prompt="a capybara swimming in the sea")
capybara_sea_image = {name}.step("Draw me a picture of the `prompt`", prompt="a capybara swimming in the sea")
capybara_sea_image.save("./capybara_sea_image.png")
# Document question answering
answer = {self.name}.step(
answer = {name}.step(
"In the following `document`, where will the TRRF Scientific Advisory Council Meeting take place?",
document=document,
)
print(answer)
# Text to image
boat_image = {self.name}.step("Generate an image of a boat in the water")
boat_image = {name}.step("Generate an image of a boat in the water")
boat_image.save("./boat_image.png")
# Unconditional image captioning
boat_image_caption = {self.name}.step("Can you caption the `boat_image`?", boat_image=boat_image)
boat_image_caption = {name}.step("Can you caption the `boat_image`?", boat_image=boat_image)
print(boat_image_caption)
# Text to image -> Unconditional image captioning -> Text to speech
boat_audio = {self.name}.step("Can you generate an image of a boat? Please read out loud the contents of the image afterwards")
boat_audio = {name}.step("Can you generate an image of a boat? Please read out loud the contents of the image afterwards")
# Text downloading
document = {self.name}.step("Download the text from http://hf.co")
document = {name}.step("Download the text from http://hf.co")
print(document)
# Text summarization
summary = {self.name}.step("Summarize the following text: `document`", document=document)
summary = {name}.step("Summarize the following text: `document`", document=document)
print(summary)
# Text downloading -> Text summarization -> Text to speech
audio = {self.name}.step("Read out loud the summary of http://hf.co")
audio = {name}.step("Read out loud the summary of http://hf.co")
```
Chat-based execution (chat), the agent also has a chat-based approach, using the chat() method:
```
# Clean the chat history
{self.name}.reset()
{name}.reset()
# Text to image
capybara_image = {self.name}.chat("Show me an an image of a capybara")
capybara_image = {name}.chat("Show me an an image of a capybara")
capybara_image.save("./capybara_image.png")
# Image transformation
transformed_capybara_image = {self.name}.chat("Transform the image so that it snows")
transformed_capybara_image = {name}.chat("Transform the image so that it snows")
transformed_capybara_image.save("./transformed_capybara_image.png")
# Image segmentation
segmented_transformed_capybara_image = {self.name}.chat("Show me a mask of the snowy capybaras")
segmented_transformed_capybara_image = {name}.chat("Show me a mask of the snowy capybaras")
segmented_transformed_capybara_image.save("./segmented_transformed_capybara_image.png")
```
"""
super(HuggingFaceToolAgent, self).__init__(name, description)
self.remote = remote

def reset(self) -> None:
r"""Resets the chat history of the agent."""
Expand Down
Loading

0 comments on commit 689adc8

Please sign in to comment.