Skip to content
Merged
Show file tree
Hide file tree
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 May 18, 2023
f1b0408
add OPREnvironment.py
Dr-Left May 18, 2023
d4ef881
finish LongtermMemory and Reflection adjustment
Dr-Left May 18, 2023
b4ac153
Unit test for memory finished(no bug). Debug.Performance waited to be…
Dr-Left May 18, 2023
9446058
add openai direct chat method and get_embedding
Dr-Left May 18, 2023
a7c46ba
modify ltmelement unit test
Dr-Left May 18, 2023
da2d7c2
base police s1->p->r
chanchimin May 21, 2023
fc2da3b
Merge branch 'remove_langchain' of https://github.com/OpenBMB/AgentVe…
chanchimin May 21, 2023
60c7667
add initialization for OPR
Dr-Left May 24, 2023
8d30e19
merge from main
Dr-Left May 24, 2023
0f082fb
prisoner
chanchimin May 24, 2023
f547a6f
merge from zjw
chanchimin May 24, 2023
e7894c2
planner unittest
chanchimin May 26, 2023
4ededdf
change get_next_plan to get_plan with time input
Dr-Left May 26, 2023
0e1c4d1
basic runnable generative agents, need to insert plan in prompt
chanchimin May 29, 2023
c019a91
add plan and event_memory in prompt
chanchimin May 30, 2023
3cf12cc
fix llm.generate_response bug in reflection
chanchimin May 30, 2023
513f78f
merge from main
chanchimin May 30, 2023
81ea48b
fix annotation
chanchimin Jun 12, 2023
f9668b0
add car, basic logic without communication, lack collision and reache…
chanchimin Jun 26, 2023
1b7d894
reflection
chanchimin Jul 1, 2023
7a023bf
remove redundancy
chanchimin Jul 1, 2023
41d2c4d
code cleaning
chanchimin Jul 1, 2023
fb4d6b1
code cleaning
chanchimin Jul 1, 2023
e41e36b
comment bmtools in AgentVerse/agentverse/initialization.py.
yushengsu-thu Jul 3, 2023
bb63742
package release
chenweize1998 Jul 4, 2023
24a125f
package release
chenweize1998 Jul 4, 2023
9433044
update README.md
chenweize1998 Jul 4, 2023
d6cdc99
resolve conflict
chenweize1998 Jul 4, 2023
5d66ddf
Delete setup.py
chenweize1998 Jul 5, 2023
de0d345
remove traffic
chanchimin Jul 5, 2023
b3bb7cf
resolve confliction
chanchimin Jul 5, 2023
b052598
remove 127.0.0.1
chanchimin Jul 5, 2023
50891cf
code cleaning
chanchimin Jul 5, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .idea/AgentVerse.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include agentverse/tasks/*/*
include agentverse/tasks/*/*/*
31 changes: 25 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ https://github.com/OpenBMB/AgentVerse/assets/11704492/4d07da68-f942-4205-b558-f1

## Contents

- [✨ Features](#-features)
- [📰 What's New](#-whats-new)
- [🗓 Coming Soon](#-coming-soon)
- [👾 Simple Demo Video](#-simple-demo-video)
- [NLP Classroom](#nlp-classroom)
- [Prisoner Dilemma](#prisoner-dilemma)
- [Software Design](#software-design)
- [Database Administrator (DBA)](#database-administrator-dba)
- [Pokemon](#pokemon)
- [Contents](#contents)
- [🚀 Getting Started](#-getting-started)
- [Installation](#installation)
- [CLI Example](#cli-example)
Expand All @@ -141,21 +151,30 @@ https://github.com/OpenBMB/AgentVerse/assets/11704492/4d07da68-f942-4205-b558-f1
### Installation

```bash
# Install the dependencies
pip install -U agentverse
```
Or you can install the package by manually cloning the latest repository
```bash
git clone https://github.com/OpenBMB/AgentVerse.git --depth 1
cd AgentVerse
pip install -r requirements.txt
```
Some users have reported problems installing the `orjson` required by `gradio`. One simple workaround is to install it with Anaconda `conda install -c conda-forge orjson`.

cd ../
You also need to export your OpenAI API key as follows
```bash
# Export your OpenAI API key
export OPENAI_API_KEY="your_api_key_here"
```

If you want to use the tools provided by BMTools, you need to install BMTools as follows:
```bash
git clone git+https://github.com/OpenBMB/BMTools.git
cd BMTools
pip install -r requirements.txt
python setup.py develop

# Export your OpenAI API key
export OPENAI_API_KEY="your_api_key_here"
```

Some users have reported problems installing the `orjson` required by `gradio`. One simple workaround is to install it with Anaconda `conda install -c conda-forge orjson`.

<!--
# Install BMTools
Expand Down
2 changes: 2 additions & 0 deletions agentverse/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
from .base import BaseAgent
from .conversation_agent import ConversationAgent
from .tool_agent import ToolAgent

from .prisoner_dilemma_agent import PoliceAgent, PrisonerAgent
from .reflection_agent import ReflectionAgent
3 changes: 2 additions & 1 deletion agentverse/agents/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from agentverse.memory import BaseMemory, ChatHistoryMemory
from agentverse.message import Message
from agentverse.parser import OutputParser

from agentverse.memory_manipulator import BaseMemoryManipulator

class BaseAgent(BaseModel):
name: str
Expand All @@ -17,6 +17,7 @@ class BaseAgent(BaseModel):
prompt_template: str
role_description: str = Field(default="")
memory: BaseMemory = Field(default_factory=ChatHistoryMemory)
memory_manipulator: BaseMemoryManipulator = Field(default_factory=BaseMemoryManipulator)
max_retry: int = Field(default=3)
receiver: Set[str] = Field(default=set({"all"}))
async_mode: bool = Field(default=True)
Expand Down
212 changes: 212 additions & 0 deletions agentverse/agents/reflection_agent.py
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
Comment thread
chenweize1998 marked this conversation as resolved.

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


5 changes: 5 additions & 0 deletions agentverse/environments/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
from .base import BaseEnvironment
from .basic import BasicEnvironment
from .pokemon import PokemonEnvironment

from .prisoner_dilemma import PrisonerDilemmaEnvironment

from .sde_team import SdeTeamEnvironment
from .sde_team_given_tests import SdeTeamGivenTestsEnvironment

from .reflection import ReflectionEnvironment

Loading