-
Notifications
You must be signed in to change notification settings - Fork 503
add reflection mechanism #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
34 commits
Select commit
Hold shift + click to select a range
49a32fc
addalice_home yaml config file
Dr-Left f1b0408
add OPREnvironment.py
Dr-Left d4ef881
finish LongtermMemory and Reflection adjustment
Dr-Left b4ac153
Unit test for memory finished(no bug). Debug.Performance waited to be…
Dr-Left 9446058
add openai direct chat method and get_embedding
Dr-Left a7c46ba
modify ltmelement unit test
Dr-Left da2d7c2
base police s1->p->r
chanchimin fc2da3b
Merge branch 'remove_langchain' of https://github.com/OpenBMB/AgentVe…
chanchimin 60c7667
add initialization for OPR
Dr-Left 8d30e19
merge from main
Dr-Left 0f082fb
prisoner
chanchimin f547a6f
merge from zjw
chanchimin e7894c2
planner unittest
chanchimin 4ededdf
change get_next_plan to get_plan with time input
Dr-Left 0e1c4d1
basic runnable generative agents, need to insert plan in prompt
chanchimin c019a91
add plan and event_memory in prompt
chanchimin 3cf12cc
fix llm.generate_response bug in reflection
chanchimin 513f78f
merge from main
chanchimin 81ea48b
fix annotation
chanchimin f9668b0
add car, basic logic without communication, lack collision and reache…
chanchimin 1b7d894
reflection
chanchimin 7a023bf
remove redundancy
chanchimin 41d2c4d
code cleaning
chanchimin fb4d6b1
code cleaning
chanchimin e41e36b
comment bmtools in AgentVerse/agentverse/initialization.py.
yushengsu-thu bb63742
package release
chenweize1998 24a125f
package release
chenweize1998 9433044
update README.md
chenweize1998 d6cdc99
resolve conflict
chenweize1998 5d66ddf
Delete setup.py
chenweize1998 de0d345
remove traffic
chanchimin b3bb7cf
resolve confliction
chanchimin b052598
remove 127.0.0.1
chanchimin 50891cf
code cleaning
chanchimin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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,2 @@ | ||
| include agentverse/tasks/*/* | ||
| include agentverse/tasks/*/*/* |
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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,212 @@ | ||
| from __future__ import annotations | ||
|
|
||
| """ | ||
| An agent based upon Observation-Planning-Reflection architecture. | ||
| """ | ||
|
|
||
| from logging import getLogger | ||
|
|
||
| from abc import abstractmethod | ||
| from typing import List, Set, Union, NamedTuple, TYPE_CHECKING | ||
|
|
||
| from pydantic import BaseModel, Field, validator | ||
|
|
||
| from agentverse.llms import BaseLLM | ||
| from agentverse.memory import BaseMemory, ChatHistoryMemory | ||
| from agentverse.message import Message | ||
| from agentverse.parser import OutputParser | ||
|
|
||
| from agentverse.message import Message | ||
| from agentverse.agents.base import BaseAgent | ||
|
|
||
| from datetime import datetime as dt | ||
| import datetime | ||
|
|
||
| from . import agent_registry | ||
| from string import Template | ||
|
|
||
|
|
||
| logger = getLogger(__file__) | ||
|
|
||
| if TYPE_CHECKING: | ||
| from agentverse.environments.base import BaseEnvironment | ||
|
|
||
|
|
||
| @agent_registry.register("reflection") | ||
| class ReflectionAgent(BaseAgent): | ||
| async_mode: bool = True, | ||
| current_time: str = None, | ||
| environment: BaseEnvironment = None | ||
| step_cnt: int = 0 | ||
|
|
||
| manipulated_memory: str = Field(default="", description="one fragment used in prompt construction") | ||
|
|
||
| @validator('current_time') | ||
| def convert_str_to_dt(cls, current_time): | ||
| if not isinstance(current_time, str): | ||
| raise ValueError('current_time should be str') | ||
| return dt.strptime(current_time, "%Y-%m-%d %H:%M:%S") | ||
|
|
||
| def step(self, current_time: dt, env_description: str = "") -> Message: | ||
| """ | ||
| Call this method at each time frame | ||
| """ | ||
| self.current_time = current_time | ||
|
|
||
| self.manipulated_memory = self.memory_manipulator.manipulate_memory() | ||
|
|
||
| prompt = self._fill_prompt_template(env_description) | ||
|
|
||
| parsed_response, reaction, target = None, None, None | ||
| for i in range(self.max_retry): | ||
| try: | ||
| response = self.llm.agenerate_response(prompt) | ||
| parsed_response = self.output_parser.parse(response) | ||
|
|
||
| if 'say(' in parsed_response.return_values["output"]: | ||
| reaction, target = eval("self._" + parsed_response.return_values["output"].strip()) | ||
| elif 'act(' in parsed_response.return_values["output"]: | ||
| reaction, target = eval("self._" + parsed_response.return_values["output"].strip()) | ||
| elif 'do_nothing(' in parsed_response.return_values["output"]: | ||
| reaction, target = None, None | ||
| else: | ||
| raise Exception(f"no valid parsed_response detected, " | ||
| f"cur response {parsed_response.return_values['output']}") | ||
| break | ||
|
|
||
| except Exception as e: | ||
| logger.error(e) | ||
| logger.warning("Retrying...") | ||
| continue | ||
|
|
||
| if parsed_response is None: | ||
| logger.error(f"{self.name} failed to generate valid response.") | ||
|
|
||
| if reaction is None: | ||
| reaction = "Keep doing last action ..." | ||
|
|
||
| message = Message( | ||
| content="" | ||
| if reaction is None | ||
| else reaction, | ||
| sender=self.name, | ||
| receiver=self.get_receiver() if target is None else self.get_valid_receiver(target), | ||
| ) | ||
|
|
||
| self.step_cnt += 1 | ||
|
|
||
| return message | ||
|
|
||
| async def astep(self, current_time: dt, env_description: str = "") -> Message: | ||
| """Asynchronous version of step""" | ||
| #use environment's time to update agent's time | ||
| self.current_time = current_time | ||
| # Before the agent step, we check current status, | ||
| # TODO add this func after | ||
| # self.check_status_passive() | ||
|
|
||
| self.manipulated_memory = self.memory_manipulator.manipulate_memory() | ||
|
|
||
| prompt = self._fill_prompt_template(env_description) | ||
|
|
||
| parsed_response, reaction, target = None, None, None | ||
| for i in range(self.max_retry): | ||
| try: | ||
| response = await self.llm.agenerate_response(prompt) | ||
| parsed_response = self.output_parser.parse(response) | ||
|
|
||
| if 'say(' in parsed_response.return_values["output"]: | ||
| reaction, target = eval("self._" + parsed_response.return_values["output"].strip()) | ||
| elif 'act(' in parsed_response.return_values["output"]: | ||
| reaction, target = eval("self._" + parsed_response.return_values["output"].strip()) | ||
| elif 'do_nothing(' in parsed_response.return_values["output"]: | ||
| reaction, target = None, None | ||
| else: | ||
| raise Exception(f"no valid parsed_response detected, " | ||
| f"cur response {parsed_response.return_values['output']}") | ||
|
|
||
| break | ||
|
|
||
| except Exception as e: | ||
| logger.error(e) | ||
| logger.warning("Retrying...") | ||
| continue | ||
|
|
||
| if parsed_response is None: | ||
| logger.error(f"{self.name} failed to generate valid response.") | ||
|
|
||
| if reaction is None: | ||
| reaction = "Keep doing last action ..." | ||
|
|
||
| message = Message( | ||
| content="" | ||
| if reaction is None | ||
| else reaction, | ||
| sender=self.name, | ||
| receiver=self.get_receiver() if target is None else self.get_valid_receiver(target), | ||
| ) | ||
|
|
||
| self.step_cnt += 1 | ||
|
|
||
| return message | ||
|
|
||
| def _act(self, description=None, target=None): | ||
| if description is None: | ||
| return "" | ||
| if target is None: | ||
| reaction_content = f"{self.name} performs action: '{description}'." | ||
| else: | ||
| reaction_content = f"{self.name} performs action to {target}: '{description}'." | ||
| # self.environment.broadcast_observations(self, target, reaction_content) | ||
| return reaction_content, target | ||
|
|
||
| def _say(self, description, target=None): | ||
| if description is None: | ||
| return "" | ||
| if target is None: | ||
| reaction_content = f"{self.name} says: '{description}'." | ||
| else: | ||
| reaction_content = f"{self.name} says to {target}: '{description}'." | ||
| # self.environment.broadcast_observations(self, target, reaction_content) | ||
| return reaction_content, target | ||
|
|
||
| def get_valid_receiver(self, target: str) -> set(): | ||
|
|
||
| all_agents_name = [] | ||
| for agent in self.environment.agents: | ||
| all_agents_name.append(agent.name) | ||
|
|
||
| if not (target in all_agents_name): | ||
| return {"all"} | ||
| else: | ||
| return {target} | ||
|
|
||
| def _fill_prompt_template(self, env_description: str = "") -> str: | ||
| """Fill the placeholders in the prompt template | ||
|
|
||
| In the conversation agent, three placeholders are supported: | ||
| - ${agent_name}: the name of the agent | ||
| - ${env_description}: the description of the environment | ||
| - ${role_description}: the description of the role of the agent | ||
| - ${chat_history}: the chat history of the agent | ||
| """ | ||
| input_arguments = { | ||
| "agent_name": self.name, | ||
| "role_description": self.role_description, | ||
| "chat_history": self.memory.to_string(add_sender_prefix=True), | ||
| "current_time": self.current_time, | ||
| "env_description": env_description, | ||
| } | ||
| return Template(self.prompt_template).safe_substitute(input_arguments) | ||
|
|
||
| def add_message_to_memory(self, messages: List[Message]) -> None: | ||
| self.memory.add_message(messages) | ||
|
|
||
| def reset(self, environment: BaseEnvironment) -> None: | ||
| """Reset the agent""" | ||
| self.environment = environment | ||
| self.memory.reset() | ||
| self.memory_manipulator.agent = self | ||
| self.memory_manipulator.memory = self.memory | ||
|
|
||
|
|
||
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.