From 4008ce3b1503d524a51a9cbf392ae476b8f1178f Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Tue, 3 Oct 2023 18:30:00 +0800
Subject: [PATCH 01/12] add_inner_voice & reflect_role & agent_memory bug
fixs
---
examples/__init__.py | 0
.../st_game/actions/inner_voice_action.py | 37 +++++++++++
.../st_game/actions/run_reflect_action.py | 6 +-
examples/st_game/memory/agent_memory.py | 28 ++++----
examples/st_game/memory/retrieve.py | 1 -
.../prompts/whisper_inner_thought_v1.txt | 11 ++++
examples/st_game/reflect/reflect.py | 6 +-
examples/st_game/roles/st_role.py | 30 +++++++--
.../st_game/tests/actions/test_reflect.py | 0
.../st_game/tests/actions/test_retrieve.py | 0
examples/st_game/tests/test_memory.py | 65 +++++++++++++++++++
11 files changed, 158 insertions(+), 26 deletions(-)
create mode 100644 examples/__init__.py
create mode 100644 examples/st_game/actions/inner_voice_action.py
create mode 100644 examples/st_game/prompts/whisper_inner_thought_v1.txt
create mode 100644 examples/st_game/tests/actions/test_reflect.py
create mode 100644 examples/st_game/tests/actions/test_retrieve.py
create mode 100644 examples/st_game/tests/test_memory.py
diff --git a/examples/__init__.py b/examples/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/st_game/actions/inner_voice_action.py b/examples/st_game/actions/inner_voice_action.py
new file mode 100644
index 000000000..2a9bb0afc
--- /dev/null
+++ b/examples/st_game/actions/inner_voice_action.py
@@ -0,0 +1,37 @@
+import re
+from examples.st_game.roles.st_role import STRole
+from examples.st_game.actions.st_action import STAction
+from examples.st_game.memory.agent_memory import BasicMemory
+from metagpt.logs import logger
+
+class AgentWhisperThoughtAction(STAction):
+
+ def __init__(self, name="AgentWhisperThoughtAction", context: list[BasicMemory] = None, llm=None):
+ super().__init__(name, context, llm)
+
+ def _func_validate(self, llm_resp: str, prompt: str) -> bool:
+ try:
+ self._func_cleanup(llm_resp, prompt)
+ return True
+ except:
+ return False
+
+ def _func_cleanup(self, llm_resp: str, prompt: str = "") -> list:
+ return llm_resp.split('"')[0].strip()
+
+ def _func_fail_default_resp(self) -> str:
+ pass
+
+ async def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
+ def create_prompt_input(role: STRole, statements, test_input=None):
+ prompt_input = [role.scratch.name, statements]
+ return prompt_input
+
+ prompt_input = create_prompt_input(role, statements)
+ prompt = self.generate_prompt_with_tmpl_filename(prompt_input,
+ "whisper_inner_thought_v1.txt")
+
+ output = await self._run_v1(prompt)
+ logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
+ return output
+
diff --git a/examples/st_game/actions/run_reflect_action.py b/examples/st_game/actions/run_reflect_action.py
index ab83a22ee..923cf68eb 100644
--- a/examples/st_game/actions/run_reflect_action.py
+++ b/examples/st_game/actions/run_reflect_action.py
@@ -22,7 +22,7 @@ class AgentFocusPt(STAction):
except:
return False
- def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
+ def _func_cleanup(self, llm_resp: str, prompt: str = "") -> list:
llm_resp = "1) " + llm_resp.strip()
ret = []
for i in llm_resp.split("\n"):
@@ -145,7 +145,7 @@ class AgentEventPoignancy(STAction):
except:
return False
- def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
+ def _func_cleanup(self, llm_resp: str, prompt: str = "") -> int:
llm_resp = int(llm_resp.strip())
return llm_resp
@@ -186,7 +186,7 @@ class AgentChatPoignancy(STAction):
except:
return False
- def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
+ def _func_cleanup(self, llm_resp: str, prompt: str = "") -> int:
llm_resp = int(llm_resp.strip())
return llm_resp
diff --git a/examples/st_game/memory/agent_memory.py b/examples/st_game/memory/agent_memory.py
index 60aa4ae81..617603195 100644
--- a/examples/st_game/memory/agent_memory.py
+++ b/examples/st_game/memory/agent_memory.py
@@ -33,7 +33,7 @@ class BasicMemory(Message):
self.memory_count: int = memory_count # 第几个记忆,实际数值与Memory相等
self.type_count: int = type_count # 第几种记忆,类型为整数(具体不太理解如何生成的)
self.memory_type: str = memory_type # 记忆类型,包含 event,thought,chat三种类型
- self.depth: str = depth # 记忆深度,类型为整数
+ self.depth: int = depth # 记忆深度,类型为整数
self.created: datetime = created # 创建时间
self.expiration: datetime = expiration # 记忆失效时间,默认为空()
@@ -62,10 +62,10 @@ class BasicMemory(Message):
memory_dict[node_id] = dict()
memory_dict[node_id]["node_count"] = self.memory_count
memory_dict[node_id]["type_count"] = self.type_count
- memory_dict[node_id]["type"] = self.type
+ memory_dict[node_id]["type"] = self.memory_type
memory_dict[node_id]["depth"] = self.depth
- memory_dict[node_id]["cmemory_dicteated"] = self.created.strftime('%Y-%m-%d %H:%M:%S')
+ memory_dict[node_id]["created"] = self.created.strftime('%Y-%m-%d %H:%M:%S')
memory_dict[node_id]["expiration"] = None
if self.expiration:
memory_dict[node_id]["expiration"] = (self.expiration
@@ -75,7 +75,7 @@ class BasicMemory(Message):
memory_dict[node_id]["predicate"] = self.predicate
memory_dict[node_id]["object"] = self.object
- memory_dict[node_id]["description"] = self.description
+ memory_dict[node_id]["description"] = self.content
memory_dict[node_id]["embedding_key"] = self.embedding_key
memory_dict[node_id]["poignancy"] = self.poignancy
memory_dict[node_id]["keywords"] = list(self.keywords)
@@ -102,7 +102,7 @@ class AgentMemory(Memory):
"""
super(AgentMemory, self).__init__()
self.id_to_node = dict() # TODO jiayi add
- self.storage: list[BasicMemory] = [] # 重写Stroage,存储BasicMemory所有节点
+ self.storage: list[BasicMemory] = [] # 重写Storage,存储BasicMemory所有节点
self.event_list = [] # 存储event记忆
self.thought_list = [] # 存储thought记忆
self.chat_list = [] # chat-related memory
@@ -122,7 +122,7 @@ class AgentMemory(Memory):
def save(self, memory_saved: str):
"""
- 将MemormyBasic类存储为Nodes.json形式。复现GA中的Kw Strength.json形式
+ 将MemoryBasic类存储为Nodes.json形式。复现GA中的Kw Strength.json形式
这里添加一个路径即可
"""
@@ -152,16 +152,13 @@ class AgentMemory(Memory):
node_id = f"node_{str(count + 1)}"
node_details = memory_load[node_id]
node_type = node_details["type"]
- created = datetime.datetime.strptime(node_details["created"],
+ created = datetime.strptime(node_details["created"],
'%Y-%m-%d %H:%M:%S')
expiration = None
if node_details["expiration"]:
- expiration = datetime.datetime.strptime(node_details["expiration"],
+ expiration = datetime.strptime(node_details["expiration"],
'%Y-%m-%d %H:%M:%S')
- if node_details["cause_by"]:
- cause_by = node_details["cause_by"]
-
s = node_details["subject"]
p = node_details["predicate"]
o = node_details["object"]
@@ -177,6 +174,7 @@ class AgentMemory(Memory):
self.add_event(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling)
elif node_type == "chat":
+ cause_by = node_details["cause_by"]
self.add_chat(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling, cause_by)
elif node_type == "thought":
@@ -200,10 +198,10 @@ class AgentMemory(Memory):
if memory_basic.cause_by:
self.index[memory_basic.cause_by][0:0] = [memory_basic]
return
- if memory_basic.type == "thought":
+ if memory_basic.memory_type == "thought":
self.thought_list[0:0] = [memory_basic]
return
- if memory_basic.type == "event":
+ if memory_basic.memory_type == "event":
self.event_list[0:0] = [memory_basic]
def add_chat(self, created, expiration, s, p, o,
@@ -211,7 +209,7 @@ class AgentMemory(Memory):
embedding_pair, filling,
cause_by):
"""
- 调用add方法,初始化chat,在创建的时候就需要调用embeeding函数
+ 调用add方法,初始化chat,在创建的时候就需要调用embedding函数
"""
memory_count = len(self.storage) + 1
type_count = len(self.thought_list) + 1
@@ -330,7 +328,7 @@ class AgentMemory(Memory):
ret_set.add(e_node.summary())
return ret_set
- def get_last_chat(self, target_role_name: str) -> str:
+ def get_last_chat(self, target_role_name: str):
if target_role_name.lower() in self.chat_keywords:
return self.chat_keywords[target_role_name.lower()][0]
else:
diff --git a/examples/st_game/memory/retrieve.py b/examples/st_game/memory/retrieve.py
index 9f19a41d4..0656d5c05 100644
--- a/examples/st_game/memory/retrieve.py
+++ b/examples/st_game/memory/retrieve.py
@@ -3,7 +3,6 @@
# @Desc : Retrieve函数实现
import datetime
-from typing import Union
from numpy import dot
from numpy.linalg import norm
diff --git a/examples/st_game/prompts/whisper_inner_thought_v1.txt b/examples/st_game/prompts/whisper_inner_thought_v1.txt
new file mode 100644
index 000000000..b1ed50aaa
--- /dev/null
+++ b/examples/st_game/prompts/whisper_inner_thought_v1.txt
@@ -0,0 +1,11 @@
+whisper_inner_thought_v1.txt
+
+Variables:
+!! -- init persona name
+!! -- whisper
+
+###
+Translate the following thought into a statement about !!.
+
+Thought: "!!"
+Statement: "
\ No newline at end of file
diff --git a/examples/st_game/reflect/reflect.py b/examples/st_game/reflect/reflect.py
index 6c19cf3fc..6cb7d86f2 100644
--- a/examples/st_game/reflect/reflect.py
+++ b/examples/st_game/reflect/reflect.py
@@ -5,7 +5,7 @@
import datetime
from metagpt.logs import logger
-
+from examples.st_game.roles.st_role import STRole
from examples.st_game.utils.utils import get_embedding
from examples.st_game.actions.run_reflect_action import (
AgentFocusPt, AgentInsightAndGuidance, AgentEventTriple,
@@ -62,7 +62,7 @@ def generate_action_event_triple(act_desp, role):
return AgentEventTriple(act_desp, role)
-def generate_poig_score(role: "STRole", event_type, description):
+def generate_poig_score(role: STRole, event_type, description):
if "is idle" in description:
return 1
@@ -167,7 +167,7 @@ def reset_reflection_counter(role: "STRole"):
# Question 1 chat函数
-def reflect(role: "STRole"):
+def role_reflect(role: "STRole"):
"""
The main reflection module for the role. We first check if the trigger
conditions are met, and if so, run the reflection and reset any of the
diff --git a/examples/st_game/roles/st_role.py b/examples/st_game/roles/st_role.py
index bd96b70c6..43e2e0472 100644
--- a/examples/st_game/roles/st_role.py
+++ b/examples/st_game/roles/st_role.py
@@ -34,6 +34,9 @@ from examples.st_game.utils.utils import get_embedding, path_finder
from examples.st_game.utils.const import collision_block_id, STORAGE_PATH
from examples.st_game.reflect.reflect import generate_poig_score
from examples.st_game.utils.mg_ga_transform import save_movement, get_role_environment
+from examples.st_game.actions.inner_voice_action import AgentWhisperThoughtAction
+from examples.st_game.actions.run_reflect_action import AgentEventTriple
+from examples.st_game.reflect.reflect import role_reflect
class STRoleContext(RoleContext):
@@ -122,13 +125,32 @@ class STRole(Role):
if len(self._rc.news) == 1 and isinstance(self._rc.news[0], UserRequirement):
# add inner voice
# TODO
+ self.add_inner_voice(self._rc.news[0].content)
logger.warning(f"Role: {self.name} add inner voice: {self._rc.news[0].content}")
return 1 # always return 1 to execute role's `_react`
- def add_inner_voice(self):
+ def add_inner_voice(self, whisper):
# TODO
- pass
+ def generate_inner_thought(strole: STRole, whisper):
+ run_whisper_thought = AgentWhisperThoughtAction()
+ inner_thought = run_whisper_thought.run(self, whisper)
+ return inner_thought
+
+ whisper = input("Enter Input: ")
+ thought = generate_inner_thought(whisper)
+
+ created = self._rc.scratch.curr_time
+ expiration = self._rc.scratch.curr_time + datetime.timedelta(days=30)
+ run_event_triple = AgentEventTriple()
+ s, p, o = run_event_triple(thought, self)
+ keywords = set([s, p, o])
+ thought_poignancy = generate_poig_score(self, "event", whisper)
+ thought_embedding_pair = (thought, get_embedding(thought))
+ self._rc.memory.add_thought(created, expiration, s, p, o,
+ thought, keywords, thought_poignancy,
+ thought_embedding_pair, None)
+
async def observe(self) -> list[BasicMemory]:
# TODO observe info from maze_env
@@ -288,9 +310,9 @@ class STRole(Role):
async def reflect(self):
# TODO reflection if meet reflect condition
-
+ role_reflect(self)
# TODO re-add result to memory
- pass
+ # 已封装到Reflect函数之中
def execute(self, plan: str):
"""
diff --git a/examples/st_game/tests/actions/test_reflect.py b/examples/st_game/tests/actions/test_reflect.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/st_game/tests/actions/test_retrieve.py b/examples/st_game/tests/actions/test_retrieve.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/examples/st_game/tests/test_memory.py b/examples/st_game/tests/test_memory.py
new file mode 100644
index 000000000..9c0354b36
--- /dev/null
+++ b/examples/st_game/tests/test_memory.py
@@ -0,0 +1,65 @@
+from datetime import datetime
+from metagpt.logs import logger
+from ..memory.agent_memory import AgentMemory, BasicMemory
+
+# Create some sample BasicMemory instances
+memory1 = BasicMemory(
+ memory_id="1",
+ memory_count=1,
+ type_count=1,
+ memory_type="event",
+ depth=1,
+ created=datetime.now(),
+ expiration=datetime.now(),
+ subject="Subject1",
+ predicate="Predicate1",
+ object="Object1",
+ content="This is content 1",
+ embedding_key="embedding_key_1",
+ poignancy=1,
+ keywords=["keyword1", "keyword2"],
+ filling=["memory_id_2"]
+)
+
+memory2 = BasicMemory(
+ memory_id="2",
+ memory_count=2,
+ type_count=2,
+ memory_type="thought",
+ depth=2,
+ created=datetime.now(),
+ expiration=None,
+ subject="Subject2",
+ predicate="Predicate2",
+ object="Object2",
+ content="This is content 2",
+ embedding_key="embedding_key_2",
+ poignancy=2,
+ keywords=["keyword3", "keyword4"],
+ filling=[]
+)
+
+if __name__ == "__main__":
+ # Create an AgentMemory instance and add the created BasicMemory instances
+ agent_memory = AgentMemory(memory_saved="sample_memory_folder")
+ agent_memory.add_event(memory1)
+ agent_memory.add_thought(memory2)
+
+ # Save the AgentMemory to a JSON file
+ agent_memory.save("sample_memory_folder")
+
+ # Load the AgentMemory from the JSON file
+ loaded_agent_memory = AgentMemory(memory_saved="sample_memory_folder")
+
+ # Get the summarized latest events
+ latest_events = loaded_agent_memory.get_summarized_latest_events(retention=2)
+ print("Summarized Latest Events:")
+ for event in latest_events:
+ print(event)
+
+ # Get the last chat for a specific role
+ last_chat = loaded_agent_memory.get_last_chat(target_role_name="role1")
+ if last_chat:
+ print(f"Last chat for role1: {last_chat.content}")
+ else:
+ print("No chat found for role1")
From ba7897a2ab29848980a201e4a5f8feb964f3dba7 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Tue, 3 Oct 2023 23:00:22 +0800
Subject: [PATCH 02/12] Retrieve & Reflect bug fix
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
修复了Retrieve与Reflect函数中的bug
---
.../st_game/actions/run_reflect_action.py | 88 +++++++++---------
examples/st_game/actions/st_action.py | 2 +-
examples/st_game/memory/agent_memory.py | 6 ++
examples/st_game/memory/retrieve.py | 23 +++--
.../st_game/reflect/ga_prompt_generator.py | 64 -------------
examples/st_game/reflect/reflect.py | 58 ++++++------
examples/st_game/reflect/st_reflect.py | 92 -------------------
examples/st_game/roles/st_role.py | 21 +++--
.../st_game/tests/actions/test_reflect.py | 0
.../st_game/tests/actions/test_retrieve.py | 0
examples/st_game/tests/test_memory.py | 2 +-
11 files changed, 105 insertions(+), 251 deletions(-)
delete mode 100644 examples/st_game/reflect/ga_prompt_generator.py
delete mode 100644 examples/st_game/reflect/st_reflect.py
delete mode 100644 examples/st_game/tests/actions/test_reflect.py
delete mode 100644 examples/st_game/tests/actions/test_retrieve.py
diff --git a/examples/st_game/actions/run_reflect_action.py b/examples/st_game/actions/run_reflect_action.py
index 923cf68eb..4f53e5647 100644
--- a/examples/st_game/actions/run_reflect_action.py
+++ b/examples/st_game/actions/run_reflect_action.py
@@ -7,6 +7,7 @@ from metagpt.logs import logger
from examples.st_game.actions.st_action import STAction
from examples.st_game.memory.agent_memory import BasicMemory
+from examples.st_game.roles.st_role import STRole
# Run GPT Prompt Focal Point method
@@ -32,8 +33,8 @@ class AgentFocusPt(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, role: "STRole", statements: str, n: int, test_input=None) -> str:
- def create_prompt_input(role: "STRole", statements, n, test_input=None):
+ def run(self, role: STRole, statements: str, n: int, test_input=None) -> str:
+ def create_prompt_input(role: STRole, statements, n, test_input=None):
prompt_input = [statements, str(n)]
return prompt_input
@@ -43,9 +44,9 @@ class AgentFocusPt(STAction):
example_output = '["What should Jane do for lunch", "Does Jane like strawberry", "Who is Jane"]'
special_instruction = "Output must be a list of str."
- output = await self._run_v2(prompt,
- example_output,
- special_instruction)
+ output = self._run_v2(prompt,
+ example_output,
+ special_instruction)
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
return output
@@ -63,7 +64,7 @@ class AgentInsightAndGuidance(STAction):
except:
return False
- def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
+ def _func_cleanup(self, llm_resp: str, prompt: str = "") -> dict:
llm_resp = "1. " + llm_resp.strip()
ret = dict()
for i in llm_resp.split("\n"):
@@ -78,8 +79,8 @@ class AgentInsightAndGuidance(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, role: "STRole", statements: str, n: int, test_input=None) -> str:
- def create_prompt_input(role: "STRole", statements, n, test_input=None):
+ def run(self, role: STRole, statements: str, n: int, test_input=None) -> dict:
+ def create_prompt_input(role, statements, n, test_input=None):
prompt_input = [statements, str(n)]
return prompt_input
@@ -87,7 +88,7 @@ class AgentInsightAndGuidance(STAction):
prompt = self.generate_prompt_with_tmpl_filename(prompt_input,
"insight_and_evidence_v1.txt")
- output = await self._run_v1(prompt)
+ output = self._run_v1(prompt)
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
return output
@@ -106,7 +107,7 @@ class AgentEventTriple(STAction):
return False
return True
- def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
+ def _func_cleanup(self, llm_resp: str, prompt: str = "") -> list:
cr = llm_resp.strip()
cr = [i.strip() for i in cr.split(")")[0].split(",")]
return cr
@@ -114,23 +115,24 @@ class AgentEventTriple(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, statements: str, role: "STRole", verbose=False) -> str:
+ def run(self, statements: str, role: STRole, verbose=False) -> str:
def create_prompt_input(statements, role):
if "(" in statements:
statements = statements.split("(")[-1].split(")")[0]
- prompt_input = [role._rc.scratch.name,
+ prompt_input = [role.scratch.name,
statements,
- role._rc.scratch.name]
+ role.scratch.name]
return prompt_input
prompt_input = create_prompt_input(statements, role)
prompt = self.generate_prompt_with_tmpl_filename(prompt_input,
"generate_event_triple_v1.txt")
- output = await self._run_v1(prompt)
+ output = self._run_v1(prompt)
+ output = (role.scratch.name,output[0],output[1])
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
- return output[0]
+ return output
# Run GPT Prompt Event Poignancy
@@ -152,11 +154,11 @@ class AgentEventPoignancy(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
- def create_prompt_input(role: "STRole", statements: str, test_input=None):
- prompt_input = [role._rc.scratch.name,
- role._rc.scratch.get_str_iss(),
- role._rc.scratch.name,
+ def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
+ def create_prompt_input(role: STRole, statements: str, test_input=None):
+ prompt_input = [role.scratch.name,
+ role.scratch.get_str_iss(),
+ role.scratch.name,
statements]
return prompt_input
@@ -166,9 +168,9 @@ class AgentEventPoignancy(STAction):
example_output = "5" # ########
special_instruction = "The output should ONLY contain ONE integer value on the scale of 1 to 10."
- output = await self._run_v2(prompt,
- example_output,
- special_instruction)
+ output = self._run_v2(prompt,
+ example_output,
+ special_instruction)
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
return output
@@ -193,11 +195,11 @@ class AgentChatPoignancy(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
- def create_prompt_input(role: "STRole", statements, test_input=None):
- prompt_input = [role._rc.scratch.name,
- role._rc.scratch.get_str_iss(),
- role._rc.scratch.name,
+ def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
+ def create_prompt_input(role: STRole, statements, test_input=None):
+ prompt_input = [role.scratch.name,
+ role.scratch.get_str_iss(),
+ role.scratch.name,
statements]
return prompt_input
@@ -207,9 +209,9 @@ class AgentChatPoignancy(STAction):
example_output = "5" # ########
special_instruction = "The output should ONLY contain ONE integer value on the scale of 1 to 10."
- output = await self._run_v2(prompt,
- example_output,
- special_instruction)
+ output = self._run_v2(prompt,
+ example_output,
+ special_instruction)
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
return output
@@ -233,19 +235,19 @@ class AgentPlanThoughtOnConvo(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
+ def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
def create_prompt_input(role, statements, test_input=None):
prompt_input = [statements,
- role._rc.scratch.name,
- role._rc.scratch.name,
- role._rc.scratch.name]
+ role.scratch.name,
+ role.scratch.name,
+ role.scratch.name]
return prompt_input
prompt_input = create_prompt_input(role, statements)
prompt = self.generate_prompt_with_tmpl_filename(prompt_input,
"planning_thought_on_convo_v1.txt")
- output = await self._run_v1(prompt)
+ output = self._run_v1(prompt)
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
return output
@@ -269,12 +271,12 @@ class AgentMemoryOnConvo(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
+ def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
def create_prompt_input(role, statements, test_input=None):
prompt_input = [statements,
- role._rc.scratch.name,
- role._rc.scratch.name,
- role._rc.scratch.name]
+ role.scratch.name,
+ role.scratch.name,
+ role.scratch.name]
return prompt_input
prompt_input = create_prompt_input(role, statements)
@@ -282,9 +284,9 @@ class AgentMemoryOnConvo(STAction):
"memo_on_convo_v1.txt")
example_output = 'Jane Doe was interesting to talk to.'
special_instruction = 'The output should ONLY contain a string that summarizes anything interesting that the agent may have noticed'
- output = await self._run_v2(prompt,
- example_output,
- special_instruction)
+ output = self._run_v2(prompt,
+ example_output,
+ special_instruction)
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
return output
diff --git a/examples/st_game/actions/st_action.py b/examples/st_game/actions/st_action.py
index 60f73f36d..e5c048b4e 100644
--- a/examples/st_game/actions/st_action.py
+++ b/examples/st_game/actions/st_action.py
@@ -56,7 +56,7 @@ class STAction(Action):
def _ask(self, prompt: str, system_msgs: Optional[list[str]] = None) -> str:
return self.llm.ask(prompt)
- def _run_v1(self, prompt: str, retry: int = 3) -> str:
+ def _run_v1(self, prompt: str, retry: int = 3) :
"""
same with `gpt_structure.safe_generate_response`
default post-preprocess operations of LLM response
diff --git a/examples/st_game/memory/agent_memory.py b/examples/st_game/memory/agent_memory.py
index 617603195..5c23c9e24 100644
--- a/examples/st_game/memory/agent_memory.py
+++ b/examples/st_game/memory/agent_memory.py
@@ -7,6 +7,7 @@ from datetime import datetime
from metagpt.memory.memory import Memory
from metagpt.schema import Message
+from metagpt.logs import logger
class BasicMemory(Message):
@@ -114,6 +115,9 @@ class AgentMemory(Memory):
self.kw_strength_event = dict() # 关键词影响存储
self.kw_strength_thought = dict()
+ self.memory_saved = None
+ self.embeddings = None
+
# self.load(memory_saved)
def set_mem_path(self, memory_saved: str):
@@ -129,6 +133,7 @@ class AgentMemory(Memory):
memory_json = dict()
for i in range(len(self.storage)):
memory_node = self.storage[i]
+ memory_node = memory_node.save_to_dict()
memory_json.update(memory_node)
with open(memory_saved + "/nodes.json", "w") as outfile:
json.dump(memory_json, outfile)
@@ -253,6 +258,7 @@ class AgentMemory(Memory):
depth_list = [memory_node.depth for memory_node in self.storage if memory_node.memory_id in filling]
depth += max(depth_list)
except Exception as exp:
+ logger.warning(f"filling init occur {exp}")
pass
memory_node = BasicMemory(memory_id, memory_count, type_count, memory_type, depth,
diff --git a/examples/st_game/memory/retrieve.py b/examples/st_game/memory/retrieve.py
index 0656d5c05..55e5b873f 100644
--- a/examples/st_game/memory/retrieve.py
+++ b/examples/st_game/memory/retrieve.py
@@ -7,12 +7,13 @@ import datetime
from numpy import dot
from numpy.linalg import norm
-from examples.st_game.memory.agent_memory import AgentMemory, BasicMemory
+from examples.st_game.memory.agent_memory import BasicMemory
from examples.st_game.utils.utils import get_embedding
+from examples.st_game.roles.st_role import STRole
-def agent_retrieve(agent_memory: AgentMemory, curr_time: datetime.datetime, memory_forget: float, query: str,
- topk: int = 4) -> list[BasicMemory]:
+def agent_retrieve(curr_time: datetime.datetime, memory_forget: float, query: str, nodes: list[BasicMemory],
+ topk: int = 4, ) -> list[BasicMemory]:
"""
Retrieve需要集合Role使用,原因在于Role才具有AgentMemory,scratch
逻辑:Role调用该函数,self._rc.AgentMemory,self._rc.scratch.curr_time,self._rc.scratch.memory_forget
@@ -26,7 +27,7 @@ def agent_retrieve(agent_memory: AgentMemory, curr_time: datetime.datetime, memo
"relevance": 搜索结果
}
"""
- memories = agent_memory.storage
+ memories = nodes
memories = sorted(memories, key=lambda memory_node: memory_node.last_accessed, reverse=True)
score_list = []
@@ -49,25 +50,27 @@ def agent_retrieve(agent_memory: AgentMemory, curr_time: datetime.datetime, memo
return result # 返回的是一个BasicMemory列表
-def new_agent_retrieve(strole: "STRole", focus_points: list, n_count=30):
+def new_agent_retrieve(role: STRole, focus_points: list, n_count=30) -> dict:
"""
- 输入为Strole,关注点列表,返回记忆数量
+ 输入为role,关注点列表,返回记忆数量
输出为字典,键为focus_point,值为对应的记忆列表
"""
retrieved = dict()
for focal_pt in focus_points:
nodes = [[i.last_accessed, i]
- for i in strole._rc.memory.event_list + strole._rc.memory.thought_list
+ for i in role.memory.event_list + role.memory.thought_list
if "idle" not in i.embedding_key]
nodes = sorted(nodes, key=lambda x: x[0])
nodes = [i for created, i in nodes]
- results = agent_retrieve(strole._rc.memory, strole._rc.scratch.curr_time, strole._rc.scratch.recency_decay,
- focal_pt, n_count)
+ results = agent_retrieve(role.scratch.curr_time, role.scratch.recency_decay,
+ focal_pt, nodes, n_count)
for n in results:
- n.last_accessed = strole._rc.scratch.curr_time
+ n.last_accessed = role.scratch.curr_time
retrieved[focal_pt] = results
+ return retrieved
+
def top_highest_x_values(d, x):
"""
diff --git a/examples/st_game/reflect/ga_prompt_generator.py b/examples/st_game/reflect/ga_prompt_generator.py
deleted file mode 100644
index 81ed5e7f7..000000000
--- a/examples/st_game/reflect/ga_prompt_generator.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# author: didi
-# Date:9.25
-
-import openai
-from metagpt.llm import DEFAULT_LLM
-# 直接调用Prompt生成
-# ga的prompt构建格式和metagpt完全不同。没有办法融合。
-
-
-# 特殊指令加入Prompt生成
-
-
-async def final_response(prompt, special_instruction, example_output=None):
- """
- 通过将特殊指令加入Prompt生成最终的响应。
-
- 参数:
- - prompt:要生成响应的提示文本。
- - special_instruction:要加入Prompt的特殊指令。
- - example_output(可选):示例输出的JSON字符串。
-
- 返回:
- 生成的最终响应。
-
- """
- prompt = '"""\n' + prompt + '\n"""\n'
- prompt += f"Output the response to the prompt above in json. {special_instruction}\n"
- if example_output:
- prompt += "Example output json:\n"
- prompt += '{"output": "' + str(example_output) + '"}'
- return await DEFAULT_LLM.aask(prompt)
-
-# prompt填充模板
-
-
-def prompt_generate(curr_input, prompt_lib_file):
- """
- Takes in the current input (e.g. comment that you want to classifiy) and
- the path to a prompt file. The prompt file contains the raw str prompt that
- will be used, which contains the following substr: !! -- this
- function replaces this substr with the actual curr_input to produce the
- final promopt that will be sent to the GPT3 server.
- ARGS:
- curr_input: the input we want to feed in (IF THERE ARE MORE THAN ONE
- INPUT, THIS CAN BE A LIST.)
- prompt_lib_file: the path to the promopt file.
- RETURNS:
- a str prompt that will be sent to OpenAI's GPT server.
- """
- if isinstance(curr_input, str):
- curr_input = [curr_input]
- curr_input = [str(i) for i in curr_input]
-
- f = open(prompt_lib_file, "r")
- prompt = f.read()
- f.close()
- for count, i in enumerate(curr_input):
- prompt = prompt.replace(f"!!", i)
- if "###" in prompt:
- prompt = prompt.split(
- "###")[1]
- return prompt.strip()
diff --git a/examples/st_game/reflect/reflect.py b/examples/st_game/reflect/reflect.py
index 6cb7d86f2..1ff0c16ab 100644
--- a/examples/st_game/reflect/reflect.py
+++ b/examples/st_game/reflect/reflect.py
@@ -17,14 +17,14 @@ from examples.st_game.actions.run_reflect_action import (
def generate_focal_points(role: "STRole", n=3):
nodes = [
[i.last_accessed, i] for i in
- role._rc.memory.event_list + role._rc.memory.thought_list
+ role.memory.event_list + role.memory.thought_list
if "idle" not in i.embedding_key
]
nodes = sorted(nodes, key=lambda x: x[0])
nodes = [i for _, i in nodes]
statements = ""
- for node in nodes[-1 * role._rc.scratch.importance_ele_n:]:
+ for node in nodes[-1 * role.scratch.importance_ele_n:]:
statements += node.embedding_key + "\n"
run_focal_pt = AgentFocusPt()
return run_focal_pt.run(role, statements, n)
@@ -59,7 +59,8 @@ def generate_action_event_triple(act_desp, role):
"🧈🍞"
"""
run_event_triple = AgentEventTriple()
- return AgentEventTriple(act_desp, role)
+ result = run_event_triple.run(act_desp, role)
+ return result
def generate_poig_score(role: STRole, event_type, description):
@@ -72,7 +73,7 @@ def generate_poig_score(role: STRole, event_type, description):
elif event_type == "chat":
run_chat_poignancy = AgentChatPoignancy()
return run_chat_poignancy.run(role,
- role._rc.scratch.act_description)[0]
+ role.scratch.act_description)[0]
def generate_planning_thought_on_convo(role, all_utt):
@@ -114,17 +115,16 @@ def run_reflect(role: "STRole"):
created = role.scratch.curr_time
expiration = created + datetime.timedelta(days=30)
s, p, o = generate_action_event_triple(thought, role)
- keywords = set([s, p, o])
+ keywords = {[s, p, o]}
thought_poignancy = generate_poig_score(role, "thought", thought)
thought_embedding_pair = (thought, get_embedding(thought))
- role._rc.memory.add_thought(
+ role.memory.add_thought(
created, expiration, s, p, o, thought, keywords,
thought_poignancy, thought_embedding_pair, evidence
)
-# Done
def reflection_trigger(role: "STRole"):
"""
Given the current role, determine whether the role should run a
@@ -140,13 +140,13 @@ def reflection_trigger(role: "STRole"):
False otherwise.
"""
logger.info(
- role._rc.scratch.name, "role.scratch.importance_trigger_curr::",
- role._rc.scratch.importance_trigger_curr
+ role.scratch.name, "role.scratch.importance_trigger_curr::",
+ role.scratch.importance_trigger_curr
)
- logger.info(role._rc.scratch.importance_trigger_max)
+ logger.info(role.scratch.importance_trigger_max)
- if (role._rc.scratch.importance_trigger_curr <= 0 and
- [] != role._rc.memory.seq_event + role._rc.memory.seq_thought):
+ if (role.scratch.importance_trigger_curr <= 0 and
+ [] != role.memory.seq_event + role.memory.seq_thought):
return True
return False
@@ -161,12 +161,11 @@ def reset_reflection_counter(role: "STRole"):
Output:
None
"""
- role_imt_max = role._rc.scratch.importance_trigger_max
- role._rc.scratch.importance_trigger_curr = role_imt_max
- role._rc.scratch.importance_ele_n = 0
+ role_imt_max = role.scratch.importance_trigger_max
+ role.scratch.importance_trigger_curr = role_imt_max
+ role.scratch.importance_ele_n = 0
-# Question 1 chat函数
def role_reflect(role: "STRole"):
"""
The main reflection module for the role. We first check if the trigger
@@ -182,42 +181,41 @@ def role_reflect(role: "STRole"):
run_reflect(role)
reset_reflection_counter(role)
- if role._rc.scratch.chatting_end_time:
- if role._rc.scratch.curr_time + datetime.timedelta(0, 10) == role._rc.scratch.chatting_end_time:
+ if role.scratch.chatting_end_time:
+ if role.scratch.curr_time + datetime.timedelta(0, 10) == role.scratch.chatting_end_time:
all_utt = ""
- if role._rc.scratch.chat:
- for row in role._rc.scratch.chat:
+ if role.scratch.chat:
+ for row in role.scratch.chat:
all_utt += f"{row[0]}: {row[1]}\n"
- # Question memory添加对话函数
- evidence = [role._rc.memory.get_last_chat(role._rc.scratch.chatting_with).memory_id]
+ evidence = [role.memory.get_last_chat(role.scratch.chatting_with).memory_id]
planning_thought = generate_planning_thought_on_convo(role, all_utt)
- planning_thought = f"For {role._rc.scratch.name}'s planning: {planning_thought}"
+ planning_thought = f"For {role.scratch.name}'s planning: {planning_thought}"
- created = role._rc.scratch.curr_time
+ created = role.scratch.curr_time
expiration = created + datetime.timedelta(days=30)
s, p, o = generate_action_event_triple(planning_thought, role)
- keywords = set([s, p, o])
+ keywords = {[s, p, o]}
thought_poignancy = generate_poig_score(role, "thought", planning_thought)
thought_embedding_pair = (planning_thought, get_embedding(planning_thought))
- role._rc.memory.add_thought(
+ role.memory.add_thought(
created, expiration, s, p, o, planning_thought, keywords,
thought_poignancy, thought_embedding_pair, evidence
)
memo_thought = generate_memo_on_convo(role, all_utt)
- memo_thought = f"{role._rc.scratch.name} {memo_thought}"
+ memo_thought = f"{role.scratch.name} {memo_thought}"
- created = role._rc.scratch.curr_time
+ created = role.scratch.curr_time
expiration = created + datetime.timedelta(days=30)
s, p, o = generate_action_event_triple(memo_thought, role)
- keywords = set([s, p, o])
+ keywords = {[s, p, o]}
thought_poignancy = generate_poig_score(role, "thought", memo_thought)
thought_embedding_pair = (memo_thought, get_embedding(memo_thought))
- role._rc.memory.add_thought(
+ role.memory.add_thought(
created, expiration, s, p, o, memo_thought, keywords,
thought_poignancy, thought_embedding_pair, evidence
)
diff --git a/examples/st_game/reflect/st_reflect.py b/examples/st_game/reflect/st_reflect.py
deleted file mode 100644
index f4b4c448c..000000000
--- a/examples/st_game/reflect/st_reflect.py
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# @Desc : st's reflection execution
-
-import asyncio
-import json
-import time
-from metagpt.logs import logger
-
-from examples.st_game.prompts.wrapper_prompt import special_response_generate
-from examples.st_game.memory.agent_memory import BasicMemory
-
-
-async def agent_reflect(memories_list):
- """
- 代理反思函数:生成关注点并生成洞察和证据
-
- """
- A = await generate_focus_point(memories_list)
-
- for i in A:
- B = await generate_insights_and_evidence(memories_list, question=i)
-
-
-async def generate_focus_point(memories_list: list[BasicMemory], n=3):
- """
- 生成关注点函数:根据记忆列表生成关注点
- """
- wait_sorted_mem = [[i.accessed_time, i] for i in memories_list]
- sorted_memories = sorted(wait_sorted_mem, key=lambda x: x[0])
- memorys = [i for created, i in sorted_memories]
- statements = ''
- for i in memorys:
- statements += i.description + "\n"
- prompt = '''
- {statements}
- Given only the information above, what are {num_question} most salient high-level questions we can answer about the subjects grounded in the statements?
- '''
- example_output = '["What should Jane do for lunch", "Does Jane like strawberry", "Who is Jane"]'
- out = await final_response(prompt.format(statements=statements, num_question=n),
- "Output must be a list of str.", example_output)
- try:
- poi_dict = json.loads(out)
- return poi_dict['output']
- except ValueError:
- print(out)
- logger.error('无法返回正常结果')
- return out
-
-
-async def generate_insights_and_evidence(memories_list: list[BasicMemory], question: str, n=5):
- """
- 生成洞察和证据函数:根据问题生成洞察和证据
- """
- memories_list = await agent_retrieve(agent, question, 50, 10)
- statements = ""
- for count, mem in enumerate(memories_list):
- statements += f'{str(count)}. {mem.description}\n'
- prompt = '''
- Input:
- {statements}
-
- What {n} high-level insights can you infer from the above statements?
- You should return a list of list[str,list]. The first element is the insight you have found. The second element is the
- '''
-
- ret = final_response(prompt.format(
- question=question, statements=statements, n=n), "['insightA',[1,2,3]]")
- try:
- insight_list = json.loads(ret)
- for insight, index in insight_list:
- agent.memory_list.append(BasicMemory(
- time.time(), None, insight, None, None))
- return insight_list
- except:
- logger.error('我们无法获得想要的返回。')
- return ret
-
-
-""" if __name__ == "__main__":
- # 例子,构建John Agent,实现retrive
- John_iss = "John Lin is a pharmacy shopkeeper at the Willow Market and Pharmacy who loves to help people. He is always looking for ways to make the process of getting medication easier for his customers; John Lin is living with his wife, Mei Lin, who is a college professor, and son, Eddy Lin, who is a student studying music theory; John Lin loves his family very much; John Lin has known the old couple next-door, Sam Moore and Jennifer Moore, for a few years; John Lin thinks Sam Moore is a kind and nice man; John Lin knows his neighbor, Yuriko Yamamoto, well; John Lin knows of his neighbors, Tamara Taylor and Carmen Ortiz, but has not met them before; John Lin and Tom Moreno are colleagues at The Willows Market and Pharmacy; John Lin and Tom Moreno are friends and like to discuss local politics together; John Lin knows the Moreno family somewhat well — the husband Tom Moreno and the wife Jane Moreno."
- John = AgentMemory(
- "John", John_iss, memory_path="agent_memories/John_memory.json")
-
- # John的相关信息:{'Had a friendly chat with Yuriko about her garden.': 2.4992317730827667, 'Helped Mrs. Moore carry groceries into her house.': 1.957656720441911, 'Discussed local politics with Tom Moreno.': 1.9458268038234035}
- asyncio.run(agent_reflect(John))
- '''
- 这里是输出,list形式,返回给记忆。
- [['The pharmacy is a friendly and helpful community.', [0, 2, 9, 12]], ['The pharmacy is a place where people come for more than just medication.', [3, 5, 13, 14]], ['The pharmacy is a place where people come for advice and conversation.', [0, 2, 6, 9, 12]], ['The pharmacy is a place where people come for assistance with daily tasks.', [3, 5, 13, 14]], ['The pharmacy is a place where people come for political discussions.', [1]]]
- '''
- """
diff --git a/examples/st_game/roles/st_role.py b/examples/st_game/roles/st_role.py
index 1ca6db09d..ad53dc4c7 100644
--- a/examples/st_game/roles/st_role.py
+++ b/examples/st_game/roles/st_role.py
@@ -104,6 +104,10 @@ class STRole(Role):
def scratch(self):
return self._rc.scratch
+ @property
+ def memory(self):
+ return self._rc.memory
+
def load_from(self, folder: Path):
"""
load role data from `storage/{simulation_name}/personas/{role_name}
@@ -123,8 +127,6 @@ class STRole(Role):
observed = self._rc.env.memory.get_by_actions(self._rc.watch)
self._rc.news = self._rc.memory.remember(observed)
if len(self._rc.news) == 1 and self._rc.news[0].cause_by == UserRequirement:
- # add inner voice
- # TODO
self.add_inner_voice(self._rc.news[0].content)
logger.warning(f"Role: {self.name} add inner voice: {self._rc.news[0].content}")
@@ -132,25 +134,24 @@ class STRole(Role):
def add_inner_voice(self, whisper):
# TODO
- def generate_inner_thought(strole: STRole, whisper):
+ def generate_inner_thought(role: STRole, whisper):
run_whisper_thought = AgentWhisperThoughtAction()
inner_thought = run_whisper_thought.run(self, whisper)
return inner_thought
-
+
whisper = input("Enter Input: ")
thought = generate_inner_thought(whisper)
created = self._rc.scratch.curr_time
expiration = self._rc.scratch.curr_time + datetime.timedelta(days=30)
run_event_triple = AgentEventTriple()
- s, p, o = run_event_triple(thought, self)
+ s, p, o = run_event_triple.run(thought, self)
keywords = set([s, p, o])
thought_poignancy = generate_poig_score(self, "event", whisper)
thought_embedding_pair = (thought, get_embedding(thought))
- self._rc.memory.add_thought(created, expiration, s, p, o,
- thought, keywords, thought_poignancy,
- thought_embedding_pair, None)
-
+ self._rc.memory.add_thought(created, expiration, s, p, o,
+ thought, keywords, thought_poignancy,
+ thought_embedding_pair, None)
async def observe(self) -> list[BasicMemory]:
# TODO observe info from maze_env
@@ -293,7 +294,7 @@ class STRole(Role):
return ret_events
- async def retrieve(self, focus_points, n=30):
+ def retrieve(self, focus_points, n=30) -> dict:
# TODO retrieve memories from agent_memory
retrieve_memories = new_agent_retrieve(self, focus_points, n)
return retrieve_memories
diff --git a/examples/st_game/tests/actions/test_reflect.py b/examples/st_game/tests/actions/test_reflect.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/examples/st_game/tests/actions/test_retrieve.py b/examples/st_game/tests/actions/test_retrieve.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/examples/st_game/tests/test_memory.py b/examples/st_game/tests/test_memory.py
index 9c0354b36..451addc8b 100644
--- a/examples/st_game/tests/test_memory.py
+++ b/examples/st_game/tests/test_memory.py
@@ -1,6 +1,6 @@
from datetime import datetime
from metagpt.logs import logger
-from ..memory.agent_memory import AgentMemory, BasicMemory
+from examples.st_game.memory.agent_memory import AgentMemory, BasicMemory
# Create some sample BasicMemory instances
memory1 = BasicMemory(
From 33fb645d5d29645a3cb291e5e4d602c842886a08 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Wed, 4 Oct 2023 01:52:16 +0800
Subject: [PATCH 03/12] fix
---
config/config.yaml | 2 +-
examples/st_game/actions/run_reflect_action.py | 5 +++--
examples/st_game/memory/agent_memory.py | 1 +
examples/st_game/tests/test_reflect.py | 8 ++++++++
4 files changed, 13 insertions(+), 3 deletions(-)
create mode 100644 examples/st_game/tests/test_reflect.py
diff --git a/config/config.yaml b/config/config.yaml
index 444f55efd..a13068639 100644
--- a/config/config.yaml
+++ b/config/config.yaml
@@ -7,7 +7,7 @@
## Or, you can configure OPENAI_PROXY to access official OPENAI_API_BASE.
OPENAI_API_BASE: "https://api.openai.com/v1"
#OPENAI_PROXY: "http://127.0.0.1:8118"
-#OPENAI_API_KEY: "YOUR_API_KEY"
+OPENAI_API_KEY: "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"
OPENAI_API_MODEL: "gpt-4"
MAX_TOKENS: 1500
RPM: 10
diff --git a/examples/st_game/actions/run_reflect_action.py b/examples/st_game/actions/run_reflect_action.py
index 4f53e5647..40bb54d7b 100644
--- a/examples/st_game/actions/run_reflect_action.py
+++ b/examples/st_game/actions/run_reflect_action.py
@@ -3,6 +3,7 @@
# @Desc : Integration Reflect Action
import re
+
from metagpt.logs import logger
from examples.st_game.actions.st_action import STAction
@@ -115,7 +116,7 @@ class AgentEventTriple(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, statements: str, role: STRole, verbose=False) -> str:
+ def run(self, statements: str, role: STRole, verbose=False) -> tuple:
def create_prompt_input(statements, role):
if "(" in statements:
statements = statements.split("(")[-1].split(")")[0]
@@ -129,7 +130,7 @@ class AgentEventTriple(STAction):
"generate_event_triple_v1.txt")
output = self._run_v1(prompt)
- output = (role.scratch.name,output[0],output[1])
+ output = (role.scratch.name, output[0], output[1])
logger.info(f"Run action: {self.__class__.__name__} with result: {output}")
return output
diff --git a/examples/st_game/memory/agent_memory.py b/examples/st_game/memory/agent_memory.py
index 5c23c9e24..1db2566f6 100644
--- a/examples/st_game/memory/agent_memory.py
+++ b/examples/st_game/memory/agent_memory.py
@@ -128,6 +128,7 @@ class AgentMemory(Memory):
"""
将MemoryBasic类存储为Nodes.json形式。复现GA中的Kw Strength.json形式
这里添加一个路径即可
+ TODO 这里需要添加Const常量
"""
memory_json = dict()
diff --git a/examples/st_game/tests/test_reflect.py b/examples/st_game/tests/test_reflect.py
new file mode 100644
index 000000000..54544f051
--- /dev/null
+++ b/examples/st_game/tests/test_reflect.py
@@ -0,0 +1,8 @@
+
+from metagpt.logs import logger
+from examples.st_game.memory.agent_memory import AgentMemory, BasicMemory
+
+"""
+测试思路
+1.
+"""
\ No newline at end of file
From 6e0701eb7ea892fdd5c15355da47f80a678234c3 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Wed, 4 Oct 2023 12:58:50 +0800
Subject: [PATCH 04/12] Update config.yaml
---
config/config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/config.yaml b/config/config.yaml
index a13068639..e76deac50 100644
--- a/config/config.yaml
+++ b/config/config.yaml
@@ -7,7 +7,7 @@
## Or, you can configure OPENAI_PROXY to access official OPENAI_API_BASE.
OPENAI_API_BASE: "https://api.openai.com/v1"
#OPENAI_PROXY: "http://127.0.0.1:8118"
-OPENAI_API_KEY: "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"
+#OPENAI_API_KEY: "YOUR OPENAI KEY"
OPENAI_API_MODEL: "gpt-4"
MAX_TOKENS: 1500
RPM: 10
From 11bef70fd7c6579cb7ab784a6550e8e52ca143d7 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Wed, 4 Oct 2023 17:36:52 +0800
Subject: [PATCH 05/12] =?UTF-8?q?memory=20&=20retrieve=20=E6=B5=8B?=
=?UTF-8?q?=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
examples/st_game/memory/agent_memory.py | 26 ++++----
examples/st_game/memory/retrieve.py | 26 +++++---
examples/st_game/tests/test_agent_memory.py | 72 +++++++++++++++++++++
examples/st_game/tests/test_basic_memory.py | 66 +++++++++++++++++++
examples/st_game/tests/test_memory.py | 65 -------------------
5 files changed, 167 insertions(+), 88 deletions(-)
create mode 100644 examples/st_game/tests/test_agent_memory.py
create mode 100644 examples/st_game/tests/test_basic_memory.py
delete mode 100644 examples/st_game/tests/test_memory.py
diff --git a/examples/st_game/memory/agent_memory.py b/examples/st_game/memory/agent_memory.py
index 1db2566f6..97644c5b8 100644
--- a/examples/st_game/memory/agent_memory.py
+++ b/examples/st_game/memory/agent_memory.py
@@ -128,12 +128,11 @@ class AgentMemory(Memory):
"""
将MemoryBasic类存储为Nodes.json形式。复现GA中的Kw Strength.json形式
这里添加一个路径即可
- TODO 这里需要添加Const常量
+ TODO 这里在存储时候进行倒序存储,之后需要验证(test_memory通过)
"""
-
memory_json = dict()
for i in range(len(self.storage)):
- memory_node = self.storage[i]
+ memory_node = self.storage[len(self.storage)-i-1]
memory_node = memory_node.save_to_dict()
memory_json.update(memory_node)
with open(memory_saved + "/nodes.json", "w") as outfile:
@@ -175,14 +174,15 @@ class AgentMemory(Memory):
poignancy = node_details["poignancy"]
keywords = set(node_details["keywords"])
filling = node_details["filling"]
-
+ # print(node_type)
if node_type == "event":
self.add_event(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling)
elif node_type == "chat":
- cause_by = node_details["cause_by"]
+ # cause_by = node_details["cause_by"]
+ logger.info(f"{node_id}")
self.add_chat(created, expiration, s, p, o,
- description, keywords, poignancy, embedding_pair, filling, cause_by)
+ description, keywords, poignancy, embedding_pair, filling)
elif node_type == "thought":
self.add_thought(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling)
@@ -198,11 +198,11 @@ class AgentMemory(Memory):
Add a new message to storage, while updating the index
重写add方法,修改原有的Message类为BasicMemory类,并添加不同的记忆类型添加方式
"""
- if memory_basic in self.storage:
+ if memory_basic.memory_id in self.storage:
return
self.storage.append(memory_basic)
- if memory_basic.cause_by:
- self.index[memory_basic.cause_by][0:0] = [memory_basic]
+ if memory_basic.memory_type == "chat":
+ self.chat_list[0:0] = [memory_basic]
return
if memory_basic.memory_type == "thought":
self.thought_list[0:0] = [memory_basic]
@@ -213,14 +213,14 @@ class AgentMemory(Memory):
def add_chat(self, created, expiration, s, p, o,
content, keywords, poignancy,
embedding_pair, filling,
- cause_by):
+ cause_by = ''):
"""
调用add方法,初始化chat,在创建的时候就需要调用embedding函数
"""
memory_count = len(self.storage) + 1
type_count = len(self.thought_list) + 1
memory_type = "chat"
- memory_id = f"memory_{str(memory_count)}"
+ memory_id = f"node_{str(memory_count)}"
depth = 1
memory_node = BasicMemory(memory_id, memory_count, type_count, memory_type, depth,
@@ -251,7 +251,7 @@ class AgentMemory(Memory):
memory_count = len(self.storage) + 1
type_count = len(self.thought_list) + 1
memory_type = "event"
- memory_id = f"memory_{str(memory_count)}"
+ memory_id = f"node_{str(memory_count)}"
depth = 1
try:
@@ -296,7 +296,7 @@ class AgentMemory(Memory):
memory_count = len(self.storage) + 1
type_count = len(self.event_list) + 1
memory_type = "event"
- memory_id = f"memory_{str(memory_count)}"
+ memory_id = f"node_{str(memory_count)}"
depth = 0
if "(" in content:
diff --git a/examples/st_game/memory/retrieve.py b/examples/st_game/memory/retrieve.py
index 55e5b873f..ffba5dcbb 100644
--- a/examples/st_game/memory/retrieve.py
+++ b/examples/st_game/memory/retrieve.py
@@ -9,10 +9,10 @@ from numpy.linalg import norm
from examples.st_game.memory.agent_memory import BasicMemory
from examples.st_game.utils.utils import get_embedding
-from examples.st_game.roles.st_role import STRole
+from metagpt.logs import logger
-def agent_retrieve(curr_time: datetime.datetime, memory_forget: float, query: str, nodes: list[BasicMemory],
+def agent_retrieve(agent_memory, curr_time: datetime.datetime, memory_forget: float, query: str, nodes: list[BasicMemory],
topk: int = 4, ) -> list[BasicMemory]:
"""
Retrieve需要集合Role使用,原因在于Role才具有AgentMemory,scratch
@@ -28,12 +28,13 @@ def agent_retrieve(curr_time: datetime.datetime, memory_forget: float, query: st
}
"""
memories = nodes
+ agent_memory_embedding = agent_memory.embeddings
memories = sorted(memories, key=lambda memory_node: memory_node.last_accessed, reverse=True)
score_list = []
score_list = extract_importance(memories, score_list)
score_list = extract_recency(curr_time, memory_forget, score_list)
- score_list = extract_relevance(query, score_list)
+ score_list = extract_relevance(agent_memory_embedding,query, score_list)
score_list = normalize_score_floats(score_list, 0, 1)
total_dict = {}
@@ -43,14 +44,14 @@ def agent_retrieve(curr_time: datetime.datetime, memory_forget: float, query: st
score_list[i]['recency'] * gw[1] +
score_list[i]['relevance'] * gw[2]
)
- total_dict[score_list[i]['memory']] = total_score
+ total_dict[score_list[i]['memory'].memory_id] = total_score
result = top_highest_x_values(total_dict, topk)
return result # 返回的是一个BasicMemory列表
-def new_agent_retrieve(role: STRole, focus_points: list, n_count=30) -> dict:
+def new_agent_retrieve(role, focus_points: list, n_count=30) -> dict:
"""
输入为role,关注点列表,返回记忆数量
输出为字典,键为focus_point,值为对应的记忆列表
@@ -62,12 +63,16 @@ def new_agent_retrieve(role: STRole, focus_points: list, n_count=30) -> dict:
if "idle" not in i.embedding_key]
nodes = sorted(nodes, key=lambda x: x[0])
nodes = [i for created, i in nodes]
- results = agent_retrieve(role.scratch.curr_time, role.scratch.recency_decay,
+ results = agent_retrieve(role.memory, role.scratch.curr_time, role.scratch.recency_decay,
focal_pt, nodes, n_count)
+ final_result = []
for n in results:
- n.last_accessed = role.scratch.curr_time
+ for i in role.memory.storage:
+ if i.memory_id == n:
+ i.last_accessed = role.scratch.curr_time
+ final_result.append(i.content)
- retrieved[focal_pt] = results
+ retrieved[focal_pt] = final_result
return retrieved
@@ -93,14 +98,15 @@ def extract_importance(memories, score_list):
return score_list
-def extract_relevance(query, score_list):
+def extract_relevance(agent_memory_embedding,query, score_list):
"""
抽取相关性
"""
query_embedding = get_embedding(query)
# 进行
for i in range(len(score_list)):
- result = cos_sim(score_list[i]["memory"].embedding_key, query_embedding)
+ node_embedding = agent_memory_embedding[score_list[i]["memory"].embedding_key]
+ result = cos_sim(node_embedding, query_embedding)
score_list[i]['relevance'] = result
return score_list
diff --git a/examples/st_game/tests/test_agent_memory.py b/examples/st_game/tests/test_agent_memory.py
new file mode 100644
index 000000000..08d065afd
--- /dev/null
+++ b/examples/st_game/tests/test_agent_memory.py
@@ -0,0 +1,72 @@
+import pytest
+import os
+import time
+from datetime import datetime, timedelta
+from metagpt.logs import logger
+from examples.st_game.memory.agent_memory import AgentMemory
+from examples.st_game.utils.const import STORAGE_PATH
+from examples.st_game.memory.retrieve import agent_retrieve
+
+"""
+memory测试思路
+1. Basic Memory测试
+2. Agent Memory测试
+ 2.1 Load & Save方法测试; Load方法中使用了add方法,验证Load即可验证所有add
+ 2.2 Get方法测试
+"""
+memory_easy_storage_path = os.path.join(STORAGE_PATH,"July1_the_ville_isabella_maria_klaus-step-3-4/personas/Isabella Rodriguez/bootstrap_memory/associative_memory")
+memroy_chat_storage_path = os.path.join(STORAGE_PATH,"July1_the_ville_isabella_maria_klaus-step-3-11/personas/Isabella Rodriguez/bootstrap_memory/associative_memory")
+memory_save_easy_test_path = os.path.join(STORAGE_PATH,"July1_the_ville_isabella_maria_klaus-step-3-4/personas/Isabella Rodriguez/bootstrap_memory/test_memory")
+memory_save_chat_test_path = os.path.join(STORAGE_PATH,"July1_the_ville_isabella_maria_klaus-step-3-11/personas/Isabella Rodriguez/bootstrap_memory/test_memory")
+class TestAgentMemory:
+ @pytest.fixture
+ def agent_memory(self):
+ # 创建一个AgentMemory实例并返回,可以在所有测试用例中共享
+ test_agent_memory = AgentMemory()
+ test_agent_memory.set_mem_path(memroy_chat_storage_path)
+ return test_agent_memory
+
+ def test_load(self,agent_memory):
+ logger.info(f"存储路径为:{agent_memory.memory_saved}")
+ logger.info(f"存储记忆条数为:{len(agent_memory.storage)}")
+ logger.info(f"kw_strength为{agent_memory.kw_strength_event},{agent_memory.kw_strength_thought}")
+ logger.info(f"embeeding.json条数为{len(agent_memory.embeddings)}")
+
+ assert agent_memory.embeddings != None
+
+ def test_save(self,agent_memory):
+ try:
+ agent_memory.save(memory_save_chat_test_path)
+ logger.info("成功存储")
+ except:
+ pass
+
+ def test_summary_function(self, agent_memory):
+ logger.info(f"event长度为{len(agent_memory.event_list)}")
+ logger.info(f"thought长度为{len(agent_memory.thought_list)}")
+ result1 = agent_memory.get_summarized_latest_events(4)
+ logger.info(f"总结最近事件结果为:{result1}")
+ def test_get_last_chat_function(self,agent_memory):
+ result2 = agent_memory.get_last_chat("customers")
+ logger.info(f"上一次对话是{result2}")
+
+ def test_retrieve_function(self,agent_memory):
+ focus_points = ["who i love?"]
+ retrieved = dict()
+ for focal_pt in focus_points:
+ nodes = [[i.last_accessed, i]
+ for i in agent_memory.event_list + agent_memory.thought_list
+ if "idle" not in i.embedding_key]
+ nodes = sorted(nodes, key=lambda x: x[0])
+ nodes = [i for created, i in nodes]
+ results = agent_retrieve(agent_memory, datetime.now()-timedelta(days=120), 0.99,
+ focal_pt, nodes, 5)
+ final_result = []
+ for n in results:
+ for i in agent_memory.storage:
+ if i.memory_id == n:
+ i.last_accessed = datetime.now()-timedelta(days=120)
+ final_result.append(i.content)
+
+ retrieved[focal_pt] = final_result
+ logger.info(f"检索结果为{retrieved}")
\ No newline at end of file
diff --git a/examples/st_game/tests/test_basic_memory.py b/examples/st_game/tests/test_basic_memory.py
new file mode 100644
index 000000000..79184ceae
--- /dev/null
+++ b/examples/st_game/tests/test_basic_memory.py
@@ -0,0 +1,66 @@
+from datetime import datetime, timedelta
+from metagpt.logs import logger
+from examples.st_game.memory.agent_memory import BasicMemory
+import pytest
+
+"""
+memory测试思路
+1. Basic Memory测试
+2. Agent Memory测试
+ 2.1 Load & Save方法测试
+ 2.2 Add方法测试
+ 2.3 Get方法测试
+"""
+
+# Create some sample BasicMemory instances
+memory1 = BasicMemory(
+ memory_id="1",
+ memory_count=1,
+ type_count=1,
+ memory_type="event",
+ depth=1,
+ created=datetime.now(),
+ expiration=datetime.now() + timedelta(days=30),
+ subject="Subject1",
+ predicate="Predicate1",
+ object="Object1",
+ content="This is content 1",
+ embedding_key="embedding_key_1",
+ poignancy=1,
+ keywords=["keyword1", "keyword2"],
+ filling=["memory_id_2"]
+)
+memory2 = BasicMemory(
+ memory_id="2",
+ memory_count=2,
+ type_count=2,
+ memory_type="thought",
+ depth=2,
+ created=datetime.now(),
+ expiration=datetime.now() + timedelta(days=30),
+ subject="Subject2",
+ predicate="Predicate2",
+ object="Object2",
+ content="This is content 2",
+ embedding_key="embedding_key_2",
+ poignancy=2,
+ keywords=["keyword3", "keyword4"],
+ filling=[]
+)
+
+@pytest.fixture
+def basic_mem_set():
+ basic_mem2 = memory2
+ yield basic_mem2
+
+def test_basic_mem_function(basic_mem_set):
+ a, b, c = basic_mem_set.summary()
+ logger.info(f"{a}{b}{c}")
+ assert a == "Subject2"
+
+def test_basic_mem_save(basic_mem_set):
+ result = basic_mem_set.save_to_dict()
+ logger.info(f"save结果为{result}")
+
+if __name__ == "__main__":
+ pytest.main()
diff --git a/examples/st_game/tests/test_memory.py b/examples/st_game/tests/test_memory.py
deleted file mode 100644
index 451addc8b..000000000
--- a/examples/st_game/tests/test_memory.py
+++ /dev/null
@@ -1,65 +0,0 @@
-from datetime import datetime
-from metagpt.logs import logger
-from examples.st_game.memory.agent_memory import AgentMemory, BasicMemory
-
-# Create some sample BasicMemory instances
-memory1 = BasicMemory(
- memory_id="1",
- memory_count=1,
- type_count=1,
- memory_type="event",
- depth=1,
- created=datetime.now(),
- expiration=datetime.now(),
- subject="Subject1",
- predicate="Predicate1",
- object="Object1",
- content="This is content 1",
- embedding_key="embedding_key_1",
- poignancy=1,
- keywords=["keyword1", "keyword2"],
- filling=["memory_id_2"]
-)
-
-memory2 = BasicMemory(
- memory_id="2",
- memory_count=2,
- type_count=2,
- memory_type="thought",
- depth=2,
- created=datetime.now(),
- expiration=None,
- subject="Subject2",
- predicate="Predicate2",
- object="Object2",
- content="This is content 2",
- embedding_key="embedding_key_2",
- poignancy=2,
- keywords=["keyword3", "keyword4"],
- filling=[]
-)
-
-if __name__ == "__main__":
- # Create an AgentMemory instance and add the created BasicMemory instances
- agent_memory = AgentMemory(memory_saved="sample_memory_folder")
- agent_memory.add_event(memory1)
- agent_memory.add_thought(memory2)
-
- # Save the AgentMemory to a JSON file
- agent_memory.save("sample_memory_folder")
-
- # Load the AgentMemory from the JSON file
- loaded_agent_memory = AgentMemory(memory_saved="sample_memory_folder")
-
- # Get the summarized latest events
- latest_events = loaded_agent_memory.get_summarized_latest_events(retention=2)
- print("Summarized Latest Events:")
- for event in latest_events:
- print(event)
-
- # Get the last chat for a specific role
- last_chat = loaded_agent_memory.get_last_chat(target_role_name="role1")
- if last_chat:
- print(f"Last chat for role1: {last_chat.content}")
- else:
- print("No chat found for role1")
From 4e4a3bce584e5f14ea5c396320a4766061d18163 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Wed, 4 Oct 2023 23:19:47 +0800
Subject: [PATCH 06/12] =?UTF-8?q?=E8=AE=B0=E5=BF=86=E6=A8=A1=E5=9D=97?=
=?UTF-8?q?=E5=85=A8=E9=83=A8=E6=B5=8B=E8=AF=95=E5=AE=8C=E6=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
examples/st_game/memory/agent_memory.py | 21 ++++++++++-----------
examples/st_game/tests/test_agent_memory.py | 1 +
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/examples/st_game/memory/agent_memory.py b/examples/st_game/memory/agent_memory.py
index 97644c5b8..f80361395 100644
--- a/examples/st_game/memory/agent_memory.py
+++ b/examples/st_game/memory/agent_memory.py
@@ -174,18 +174,16 @@ class AgentMemory(Memory):
poignancy = node_details["poignancy"]
keywords = set(node_details["keywords"])
filling = node_details["filling"]
- # print(node_type)
- if node_type == "event":
- self.add_event(created, expiration, s, p, o,
- description, keywords, poignancy, embedding_pair, filling)
- elif node_type == "chat":
- # cause_by = node_details["cause_by"]
- logger.info(f"{node_id}")
- self.add_chat(created, expiration, s, p, o,
- description, keywords, poignancy, embedding_pair, filling)
- elif node_type == "thought":
+ if node_details["type"] == "thought":
self.add_thought(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling)
+ if node_details["type"] == "event":
+ self.add_event(created, expiration, s, p, o,
+ description, keywords, poignancy, embedding_pair, filling)
+ if node_details["type"] == "chat":
+ self.add_chat(created, expiration, s, p, o,
+ description, keywords, poignancy, embedding_pair, filling)
+
strength_keywords_load = json.load(open(memory_saved + "/kw_strength.json"))
if strength_keywords_load["kw_strength_event"]:
@@ -209,6 +207,7 @@ class AgentMemory(Memory):
return
if memory_basic.memory_type == "event":
self.event_list[0:0] = [memory_basic]
+ return
def add_chat(self, created, expiration, s, p, o,
content, keywords, poignancy,
@@ -250,7 +249,7 @@ class AgentMemory(Memory):
"""
memory_count = len(self.storage) + 1
type_count = len(self.thought_list) + 1
- memory_type = "event"
+ memory_type = "thought"
memory_id = f"node_{str(memory_count)}"
depth = 1
diff --git a/examples/st_game/tests/test_agent_memory.py b/examples/st_game/tests/test_agent_memory.py
index 08d065afd..f487218ea 100644
--- a/examples/st_game/tests/test_agent_memory.py
+++ b/examples/st_game/tests/test_agent_memory.py
@@ -44,6 +44,7 @@ class TestAgentMemory:
def test_summary_function(self, agent_memory):
logger.info(f"event长度为{len(agent_memory.event_list)}")
logger.info(f"thought长度为{len(agent_memory.thought_list)}")
+ logger.info(f"chat长度为{len(agent_memory.chat_list)}")
result1 = agent_memory.get_summarized_latest_events(4)
logger.info(f"总结最近事件结果为:{result1}")
def test_get_last_chat_function(self,agent_memory):
From 90bb3f94f61ade18777a232044f88085249add91 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Wed, 4 Oct 2023 23:36:29 +0800
Subject: [PATCH 07/12] =?UTF-8?q?=E5=BE=AA=E7=8E=AFimport=E8=A7=A3?=
=?UTF-8?q?=E5=86=B3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../st_game/actions/inner_voice_action.py | 5 ++---
.../st_game/actions/run_reflect_action.py | 21 +++++++++----------
examples/st_game/reflect/reflect.py | 3 +--
examples/st_game/tests/test_reflect.py | 13 +++++++++++-
4 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/examples/st_game/actions/inner_voice_action.py b/examples/st_game/actions/inner_voice_action.py
index 2a9bb0afc..082921554 100644
--- a/examples/st_game/actions/inner_voice_action.py
+++ b/examples/st_game/actions/inner_voice_action.py
@@ -1,5 +1,4 @@
import re
-from examples.st_game.roles.st_role import STRole
from examples.st_game.actions.st_action import STAction
from examples.st_game.memory.agent_memory import BasicMemory
from metagpt.logs import logger
@@ -22,8 +21,8 @@ class AgentWhisperThoughtAction(STAction):
def _func_fail_default_resp(self) -> str:
pass
- async def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
- def create_prompt_input(role: STRole, statements, test_input=None):
+ async def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
+ def create_prompt_input(role: "STRole", statements, test_input=None):
prompt_input = [role.scratch.name, statements]
return prompt_input
diff --git a/examples/st_game/actions/run_reflect_action.py b/examples/st_game/actions/run_reflect_action.py
index 40bb54d7b..1e26145c2 100644
--- a/examples/st_game/actions/run_reflect_action.py
+++ b/examples/st_game/actions/run_reflect_action.py
@@ -8,7 +8,6 @@ from metagpt.logs import logger
from examples.st_game.actions.st_action import STAction
from examples.st_game.memory.agent_memory import BasicMemory
-from examples.st_game.roles.st_role import STRole
# Run GPT Prompt Focal Point method
@@ -34,8 +33,8 @@ class AgentFocusPt(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, role: STRole, statements: str, n: int, test_input=None) -> str:
- def create_prompt_input(role: STRole, statements, n, test_input=None):
+ def run(self, role: "STRole", statements: str, n: int, test_input=None) -> str:
+ def create_prompt_input(role: "STRole", statements, n, test_input=None):
prompt_input = [statements, str(n)]
return prompt_input
@@ -80,7 +79,7 @@ class AgentInsightAndGuidance(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, role: STRole, statements: str, n: int, test_input=None) -> dict:
+ def run(self, role: "STRole", statements: str, n: int, test_input=None) -> dict:
def create_prompt_input(role, statements, n, test_input=None):
prompt_input = [statements, str(n)]
return prompt_input
@@ -116,7 +115,7 @@ class AgentEventTriple(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, statements: str, role: STRole, verbose=False) -> tuple:
+ def run(self, statements: str, role: "STRole", verbose=False) -> tuple:
def create_prompt_input(statements, role):
if "(" in statements:
statements = statements.split("(")[-1].split(")")[0]
@@ -155,8 +154,8 @@ class AgentEventPoignancy(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
- def create_prompt_input(role: STRole, statements: str, test_input=None):
+ def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
+ def create_prompt_input(role: "STRole", statements: str, test_input=None):
prompt_input = [role.scratch.name,
role.scratch.get_str_iss(),
role.scratch.name,
@@ -196,8 +195,8 @@ class AgentChatPoignancy(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
- def create_prompt_input(role: STRole, statements, test_input=None):
+ def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
+ def create_prompt_input(role: "STRole", statements, test_input=None):
prompt_input = [role.scratch.name,
role.scratch.get_str_iss(),
role.scratch.name,
@@ -236,7 +235,7 @@ class AgentPlanThoughtOnConvo(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
+ def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
def create_prompt_input(role, statements, test_input=None):
prompt_input = [statements,
role.scratch.name,
@@ -272,7 +271,7 @@ class AgentMemoryOnConvo(STAction):
def _func_fail_default_resp(self) -> str:
pass
- def run(self, role: STRole, statements: str, test_input=None, verbose=False) -> str:
+ def run(self, role: "STRole", statements: str, test_input=None, verbose=False) -> str:
def create_prompt_input(role, statements, test_input=None):
prompt_input = [statements,
role.scratch.name,
diff --git a/examples/st_game/reflect/reflect.py b/examples/st_game/reflect/reflect.py
index 1ff0c16ab..77a1554e6 100644
--- a/examples/st_game/reflect/reflect.py
+++ b/examples/st_game/reflect/reflect.py
@@ -5,7 +5,6 @@
import datetime
from metagpt.logs import logger
-from examples.st_game.roles.st_role import STRole
from examples.st_game.utils.utils import get_embedding
from examples.st_game.actions.run_reflect_action import (
AgentFocusPt, AgentInsightAndGuidance, AgentEventTriple,
@@ -63,7 +62,7 @@ def generate_action_event_triple(act_desp, role):
return result
-def generate_poig_score(role: STRole, event_type, description):
+def generate_poig_score(role: "STRole", event_type, description):
if "is idle" in description:
return 1
diff --git a/examples/st_game/tests/test_reflect.py b/examples/st_game/tests/test_reflect.py
index 54544f051..e1b77a591 100644
--- a/examples/st_game/tests/test_reflect.py
+++ b/examples/st_game/tests/test_reflect.py
@@ -1,7 +1,18 @@
+import pytest
+from examples.st_game.roles.st_role import STRole
from metagpt.logs import logger
-from examples.st_game.memory.agent_memory import AgentMemory, BasicMemory
+
+class TestReflect:
+ @pytest.fixture
+ def init_agent(self):
+ # 创建一个AgentMemory实例并返回,可以在所有测试用例中共享
+ role = STRole('Isabella Rodriguez', 'STMember', 'base_the_vile_isabella_maria_klaus')
+ return role
+
+ def test_focus(self, init_agent):
+ init_agent.reflect()
"""
测试思路
1.
From 6f449f1505be9779884ff3423f07eed060947449 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Thu, 5 Oct 2023 01:22:12 +0800
Subject: [PATCH 08/12] =?UTF-8?q?Reflect=E6=B5=8B=E8=AF=95=E6=A0=B7?=
=?UTF-8?q?=E4=BE=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../st_game/actions/run_reflect_action.py | 14 ++++++----
examples/st_game/memory/agent_memory.py | 6 ++---
examples/st_game/reflect/reflect.py | 9 +++----
examples/st_game/roles/st_role.py | 4 +--
examples/st_game/tests/test_reflect.py | 26 +++++++++++++------
5 files changed, 35 insertions(+), 24 deletions(-)
diff --git a/examples/st_game/actions/run_reflect_action.py b/examples/st_game/actions/run_reflect_action.py
index 1e26145c2..9c688421c 100644
--- a/examples/st_game/actions/run_reflect_action.py
+++ b/examples/st_game/actions/run_reflect_action.py
@@ -24,11 +24,15 @@ class AgentFocusPt(STAction):
return False
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> list:
- llm_resp = "1) " + llm_resp.strip()
- ret = []
- for i in llm_resp.split("\n"):
- ret += [i.split(") ")[-1]]
- return ret
+ try:
+ return llm_resp
+ # llm_resp = "1) " + llm_resp.strip()
+ # ret = []
+ # for i in llm_resp.split("\n"):
+ # ret += [i.split(") ")[-1]]
+ # return ret
+ except Exception as exp:
+ print(f"cleanup 错误 {exp}")
def _func_fail_default_resp(self) -> str:
pass
diff --git a/examples/st_game/memory/agent_memory.py b/examples/st_game/memory/agent_memory.py
index f80361395..869f94a4d 100644
--- a/examples/st_game/memory/agent_memory.py
+++ b/examples/st_game/memory/agent_memory.py
@@ -174,13 +174,13 @@ class AgentMemory(Memory):
poignancy = node_details["poignancy"]
keywords = set(node_details["keywords"])
filling = node_details["filling"]
- if node_details["type"] == "thought":
+ if node_type == "thought":
self.add_thought(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling)
- if node_details["type"] == "event":
+ if node_type == "event":
self.add_event(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling)
- if node_details["type"] == "chat":
+ if node_type == "chat":
self.add_chat(created, expiration, s, p, o,
description, keywords, poignancy, embedding_pair, filling)
diff --git a/examples/st_game/reflect/reflect.py b/examples/st_game/reflect/reflect.py
index 77a1554e6..d32d64200 100644
--- a/examples/st_game/reflect/reflect.py
+++ b/examples/st_game/reflect/reflect.py
@@ -122,6 +122,7 @@ def run_reflect(role: "STRole"):
created, expiration, s, p, o, thought, keywords,
thought_poignancy, thought_embedding_pair, evidence
)
+ logger.info(f"主谓宾为:{s}{p}{o},描述为{thought}")
def reflection_trigger(role: "STRole"):
@@ -138,14 +139,10 @@ def reflection_trigger(role: "STRole"):
True if we are running a new reflection.
False otherwise.
"""
- logger.info(
- role.scratch.name, "role.scratch.importance_trigger_curr::",
- role.scratch.importance_trigger_curr
- )
- logger.info(role.scratch.importance_trigger_max)
+ logger.info(f"{role.scratch.name} role.scratch.importance_trigger_curr:: {role.scratch.importance_trigger_curr}"),
if (role.scratch.importance_trigger_curr <= 0 and
- [] != role.memory.seq_event + role.memory.seq_thought):
+ [] != role.memory.event_list + role.memory.thought_list):
return True
return False
diff --git a/examples/st_game/roles/st_role.py b/examples/st_game/roles/st_role.py
index ad53dc4c7..ca1bac6e0 100644
--- a/examples/st_game/roles/st_role.py
+++ b/examples/st_game/roles/st_role.py
@@ -309,9 +309,9 @@ class STRole(Role):
# TODO re-add result into memory
pass
- async def reflect(self):
+ def reflect(self):
# TODO reflection if meet reflect condition
- role_reflect(self)
+ result = role_reflect(self)
# TODO re-add result to memory
# 已封装到Reflect函数之中
diff --git a/examples/st_game/tests/test_reflect.py b/examples/st_game/tests/test_reflect.py
index e1b77a591..307e17729 100644
--- a/examples/st_game/tests/test_reflect.py
+++ b/examples/st_game/tests/test_reflect.py
@@ -1,19 +1,29 @@
import pytest
from examples.st_game.roles.st_role import STRole
+from examples.st_game.actions.run_reflect_action import AgentFocusPt
from metagpt.logs import logger
-class TestReflect:
+class TestReflectFunction:
@pytest.fixture
def init_agent(self):
- # 创建一个AgentMemory实例并返回,可以在所有测试用例中共享
- role = STRole('Isabella Rodriguez', 'STMember', 'base_the_vile_isabella_maria_klaus')
+ # 创建一个STRole实例,注意从GA中copy过来JSON文件
+ role = STRole(sim_code="July1_the_ville_isabella_maria_klaus-step-3-11", start_date='February 13, 2023', curr_time='February 13, 2023, 14:53:10')
+ logger.info(role.scratch.name)
+ logger.info(f"记忆长度为{len(role.memory.storage)}")
return role
- def test_focus(self, init_agent):
+ def test_fuction_point_action(self,init_agent):
+ """
+
+ """
+ run_focus = AgentFocusPt()
+ statements = "" # 这个statements 与 n 设置是遵循reflect里面实际设置# 来的,你写的时候可以对应代码看一下
+ run_focus.run(init_agent, statements, n=3)
+
+ # 测试全部Reflection功能
+ def test_reflect_function(self, init_agent):
+ # 修改 近期 importace 确保Reflect机制能够触发
+ init_agent.scratch.importance_trigger_curr = -1
init_agent.reflect()
-"""
-测试思路
-1.
-"""
\ No newline at end of file
From d79ed767e2a28e0fd66ab8a46659403d253a0c63 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Thu, 5 Oct 2023 01:28:33 +0800
Subject: [PATCH 09/12] =?UTF-8?q?=E5=AE=8C=E6=88=90=E4=BE=9D=E8=B5=96?=
=?UTF-8?q?=E5=87=BD=E6=95=B0=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
examples/st_game/memory/retrieve.py | 2 +-
examples/st_game/reflect/reflect.py | 1 +
examples/st_game/tests/test_agent_memory.py | 2 +-
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/examples/st_game/memory/retrieve.py b/examples/st_game/memory/retrieve.py
index ffba5dcbb..9478b1f9f 100644
--- a/examples/st_game/memory/retrieve.py
+++ b/examples/st_game/memory/retrieve.py
@@ -70,7 +70,7 @@ def new_agent_retrieve(role, focus_points: list, n_count=30) -> dict:
for i in role.memory.storage:
if i.memory_id == n:
i.last_accessed = role.scratch.curr_time
- final_result.append(i.content)
+ final_result.append(i)
retrieved[focal_pt] = final_result
diff --git a/examples/st_game/reflect/reflect.py b/examples/st_game/reflect/reflect.py
index d32d64200..761f3d943 100644
--- a/examples/st_game/reflect/reflect.py
+++ b/examples/st_game/reflect/reflect.py
@@ -105,6 +105,7 @@ def run_reflect(role: "STRole"):
# For each of the focal points, generate thoughts and save it in the
# agent's memory.
for focal_pt, nodes in retrieved.items():
+
xx = [i.embedding_key for i in nodes]
for xxx in xx: logger.info(xxx)
diff --git a/examples/st_game/tests/test_agent_memory.py b/examples/st_game/tests/test_agent_memory.py
index f487218ea..9596f97d4 100644
--- a/examples/st_game/tests/test_agent_memory.py
+++ b/examples/st_game/tests/test_agent_memory.py
@@ -67,7 +67,7 @@ class TestAgentMemory:
for i in agent_memory.storage:
if i.memory_id == n:
i.last_accessed = datetime.now()-timedelta(days=120)
- final_result.append(i.content)
+ final_result.append(i)
retrieved[focal_pt] = final_result
logger.info(f"检索结果为{retrieved}")
\ No newline at end of file
From 1ec2b922c13c87cc9d48c08a1f3246f43c2386e2 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Thu, 5 Oct 2023 19:45:37 +0800
Subject: [PATCH 10/12] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E9=9C=80=E8=A6=81?=
=?UTF-8?q?=E6=B5=8B=E8=AF=95Agent=E7=B1=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
examples/st_game/tests/test_reflect.py | 28 +++++++++++++++++++++++---
1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/examples/st_game/tests/test_reflect.py b/examples/st_game/tests/test_reflect.py
index 307e17729..43139de4b 100644
--- a/examples/st_game/tests/test_reflect.py
+++ b/examples/st_game/tests/test_reflect.py
@@ -1,7 +1,7 @@
import pytest
from examples.st_game.roles.st_role import STRole
-from examples.st_game.actions.run_reflect_action import AgentFocusPt
+from examples.st_game.actions.run_reflect_action import AgentFocusPt, AgentInsightAndGuidance, AgentEventTriple, AgentEventPoignancy, AgentChatPoignancy, AgentPlanThoughtOnConvo, AgentMemoryOnConvo
from metagpt.logs import logger
@@ -14,14 +14,36 @@ class TestReflectFunction:
logger.info(f"记忆长度为{len(role.memory.storage)}")
return role
- def test_fuction_point_action(self,init_agent):
+ def test_function_focus_and_insight_action(self,init_agent):
"""
-
+ 单个Action测试样例
"""
run_focus = AgentFocusPt()
statements = "" # 这个statements 与 n 设置是遵循reflect里面实际设置# 来的,你写的时候可以对应代码看一下
run_focus.run(init_agent, statements, n=3)
+ run_insight = AgentInsightAndGuidance()
+ # 这里主要需要查看,Looger.info(filling)
+ # 完善代码
+
+ def test_event_triple_action(self,init_agent):
+ """
+ 测试tripleAgent Action
+ """
+ pass
+
+ def test_poignancy_action(self,init_agent):
+ """
+ 测试两个关于poignancy的Action
+ """
+ pass
+
+ def test_convo_action(self,init_agent):
+ """
+ 测试两个convo相关的类
+ """
+ pass
+
# 测试全部Reflection功能
def test_reflect_function(self, init_agent):
# 修改 近期 importace 确保Reflect机制能够触发
From e40e3bacc56c4b42f279372677d3978e7733e645 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Fri, 6 Oct 2023 01:44:45 +0800
Subject: [PATCH 11/12] =?UTF-8?q?Reflect=E6=B5=8B=E8=AF=95=E7=AC=AC?=
=?UTF-8?q?=E4=B8=80=E7=89=88=E6=9C=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1. 能通过
2. insight不稳定
---
.../st_game/actions/run_reflect_action.py | 63 ++++++++++++-------
.../prompts/insight_and_evidence_v1.txt | 2 +-
examples/st_game/reflect/reflect.py | 27 ++++----
examples/st_game/tests/test_reflect.py | 25 +++++---
4 files changed, 74 insertions(+), 43 deletions(-)
diff --git a/examples/st_game/actions/run_reflect_action.py b/examples/st_game/actions/run_reflect_action.py
index 9c688421c..10e22dbcf 100644
--- a/examples/st_game/actions/run_reflect_action.py
+++ b/examples/st_game/actions/run_reflect_action.py
@@ -69,16 +69,20 @@ class AgentInsightAndGuidance(STAction):
return False
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> dict:
- llm_resp = "1. " + llm_resp.strip()
- ret = dict()
- for i in llm_resp.split("\n"):
- row = i.split(". ")[-1]
- thought = row.split("(because of ")[0].strip()
- evi_raw = row.split("(because of ")[1].split(")")[0].strip()
- evi_raw = re.findall(r'\d+', evi_raw)
- evi_raw = [int(i.strip()) for i in evi_raw]
- ret[thought] = evi_raw
- return ret
+ try:
+ logger.info(f"Run prompt Insight get {llm_resp}")
+ llm_resp = "1. " + llm_resp.strip()
+ ret = dict()
+ for i in llm_resp.split("\n"):
+ row = i.split(". ")[-1]
+ thought = row.split("(because of ")[0].strip()
+ evi_raw = row.split("(because of ")[1].split(")")[0].strip()
+ evi_raw = re.findall(r'\d+', evi_raw)
+ evi_raw = [int(i.strip()) for i in evi_raw]
+ ret[thought] = evi_raw
+ return ret
+ except Exception as exp:
+ logger.error(f"AGent Insight 报错{exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -112,9 +116,15 @@ class AgentEventTriple(STAction):
return True
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> list:
- cr = llm_resp.strip()
- cr = [i.strip() for i in cr.split(")")[0].split(",")]
- return cr
+ try:
+ cr = llm_resp.strip()
+ cr = [i.strip() for i in cr.split(")")[0].split(",")]
+ if len(cr) != 2:
+ return cr[-2:]
+ logger.info(f"cr结果为{cr}")
+ return cr
+ except Exception as exp:
+ logger.error(f"AGent Triple 报错{exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -152,9 +162,11 @@ class AgentEventPoignancy(STAction):
return False
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> int:
- llm_resp = int(llm_resp.strip())
- return llm_resp
-
+ try:
+ llm_resp = int(llm_resp.strip())
+ return llm_resp
+ except Exception as exp:
+ logger.error(f"AGent Event poignancy 报错{exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -193,9 +205,11 @@ class AgentChatPoignancy(STAction):
return False
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> int:
- llm_resp = int(llm_resp.strip())
- return llm_resp
-
+ try:
+ llm_resp = int(llm_resp.strip())
+ return llm_resp
+ except Exception as exp:
+ logger.error(f"AGent Chat poignancy 报错{exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -234,7 +248,10 @@ class AgentPlanThoughtOnConvo(STAction):
return False
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
- return llm_resp.split('"')[0].strip()
+ try:
+ return llm_resp.split('"')[0].strip()
+ except Exception as exp:
+ logger.error(f"AGent PlanThought 报错{exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -270,8 +287,10 @@ class AgentMemoryOnConvo(STAction):
return False
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
- return llm_resp.split('"')[0].strip()
-
+ try:
+ return llm_resp.split('"')[0].strip()
+ except Exception as exp:
+ logger.error(f"AGent MemoryOnconvo 报错{exp}")
def _func_fail_default_resp(self) -> str:
pass
diff --git a/examples/st_game/prompts/insight_and_evidence_v1.txt b/examples/st_game/prompts/insight_and_evidence_v1.txt
index 579c81637..35671023b 100644
--- a/examples/st_game/prompts/insight_and_evidence_v1.txt
+++ b/examples/st_game/prompts/insight_and_evidence_v1.txt
@@ -8,5 +8,5 @@ Variables:
Input:
!!
-What !! high-level insights can you infer from the above statements? (example format: insight (because of 1, 5, 3))
+What !! high-level insights can you infer from the above statements? Please ensure it includes 'because of' and generates according to the example format.(example format: insight (because of 1, 5, 3)) .
1.
\ No newline at end of file
diff --git a/examples/st_game/reflect/reflect.py b/examples/st_game/reflect/reflect.py
index 761f3d943..5423e52bf 100644
--- a/examples/st_game/reflect/reflect.py
+++ b/examples/st_game/reflect/reflect.py
@@ -37,12 +37,14 @@ def generate_insights_and_evidence(role, nodes, n=5):
ret = run_insight_and_guidance.run(role, statements, n)
logger.info(ret)
+
try:
for thought, evi_raw in ret.items():
- evidence_node_id = [nodes[i].node_id for i in evi_raw]
+ evidence_node_id = [nodes[i].memory_id for i in evi_raw]
ret[thought] = evidence_node_id
return ret
- except:
+ except Exception as exp:
+ logger.info(f"insight处理错误为{exp}")
return {"this is blank": "node_1"}
@@ -57,6 +59,7 @@ def generate_action_event_triple(act_desp, role):
EXAMPLE OUTPUT:
"🧈🍞"
"""
+ logger.info(f"event Triple 输入为:{act_desp}")
run_event_triple = AgentEventTriple()
result = run_event_triple.run(act_desp, role)
return result
@@ -68,11 +71,11 @@ def generate_poig_score(role: "STRole", event_type, description):
if event_type == "event" or event_type == "thought":
run_event_poignancy = AgentEventPoignancy()
- return run_event_poignancy.run(role, description)[0]
+ return run_event_poignancy.run(role, description)
elif event_type == "chat":
run_chat_poignancy = AgentChatPoignancy()
return run_chat_poignancy.run(role,
- role.scratch.act_description)[0]
+ role.scratch.act_description)
def generate_planning_thought_on_convo(role, all_utt):
@@ -98,24 +101,24 @@ def run_reflect(role: "STRole"):
"""
# Reflection requires certain focal points. Generate that first.
focal_points = generate_focal_points(role, 3)
- # Retrieve the relevant Nodes object for each of the focal points.
+ # Retrieve the relevant Nodesobject for each of the focal points.
# has keys of focal points, and values of the associated Nodes.
retrieved = role.retrieve(focal_points)
# For each of the focal points, generate thoughts and save it in the
# agent's memory.
for focal_pt, nodes in retrieved.items():
-
- xx = [i.embedding_key for i in nodes]
- for xxx in xx: logger.info(xxx)
+ logger.info(f"检索结果为{nodes}")
+ # xx = [i.embedding_key for i in nodes]
+ # for xxx in xx: logger.info(xxx)
thoughts = generate_insights_and_evidence(role, nodes, 5)
# 生成的是字典类型
for thought, evidence in thoughts.items():
created = role.scratch.curr_time
expiration = created + datetime.timedelta(days=30)
- s, p, o = generate_action_event_triple(thought, role)
- keywords = {[s, p, o]}
+ s, p, o = generate_action_event_triple("("+thought+")", role)
+ keywords = set([s, p, o])
thought_poignancy = generate_poig_score(role, "thought", thought)
thought_embedding_pair = (thought, get_embedding(thought))
@@ -193,7 +196,7 @@ def role_reflect(role: "STRole"):
created = role.scratch.curr_time
expiration = created + datetime.timedelta(days=30)
s, p, o = generate_action_event_triple(planning_thought, role)
- keywords = {[s, p, o]}
+ keywords = set([s, p, o])
thought_poignancy = generate_poig_score(role, "thought", planning_thought)
thought_embedding_pair = (planning_thought, get_embedding(planning_thought))
@@ -208,7 +211,7 @@ def role_reflect(role: "STRole"):
created = role.scratch.curr_time
expiration = created + datetime.timedelta(days=30)
s, p, o = generate_action_event_triple(memo_thought, role)
- keywords = {[s, p, o]}
+ keywords = set([s, p, o])
thought_poignancy = generate_poig_score(role, "thought", memo_thought)
thought_embedding_pair = (memo_thought, get_embedding(memo_thought))
diff --git a/examples/st_game/tests/test_reflect.py b/examples/st_game/tests/test_reflect.py
index 43139de4b..1593d9aaa 100644
--- a/examples/st_game/tests/test_reflect.py
+++ b/examples/st_game/tests/test_reflect.py
@@ -10,32 +10,41 @@ class TestReflectFunction:
def init_agent(self):
# 创建一个STRole实例,注意从GA中copy过来JSON文件
role = STRole(sim_code="July1_the_ville_isabella_maria_klaus-step-3-11", start_date='February 13, 2023', curr_time='February 13, 2023, 14:53:10')
- logger.info(role.scratch.name)
- logger.info(f"记忆长度为{len(role.memory.storage)}")
return role
def test_function_focus_and_insight_action(self,init_agent):
"""
单个Action测试样例
"""
- run_focus = AgentFocusPt()
- statements = "" # 这个statements 与 n 设置是遵循reflect里面实际设置# 来的,你写的时候可以对应代码看一下
- run_focus.run(init_agent, statements, n=3)
+ logger.info(f"{__name__}函数启动")
+ # run_focus = AgentFocusPt()
+ # statements = "" # 这个statements 与 n 设置是遵循reflect里面实际设置# 来的,你写的时候可以对应代码看一下
+ # out_put = run_focus.run(init_agent, statements, n=3)
- run_insight = AgentInsightAndGuidance()
- # 这里主要需要查看,Looger.info(filling)
- # 完善代码
+ """
+ 这里有通过测试的结果,但是更多时候LLM生成的结果缺少了because of;考虑修改一下prompt
+ result = {'Klaus Mueller and Maria Lopez have a close relationship because they have been friends for a long time and have a strong bond': [1, 2, 5, 9, 11, 14], 'Klaus Mueller has a crush on Maria Lopez': [8, 15, 24], 'Klaus Mueller is academically inclined and actively researching a topic': [13, 20], 'Klaus Mueller is socially active and acquainted with Isabella Rodriguez': [17, 21, 22], 'Klaus Mueller is organized and prepared': [19]}
+ """
+ # run_insight = AgentInsightAndGuidance()
+ # statements = "[user: Klaus Mueller has a close relationship with Maria Lopez, user:s Mueller and Maria Lopez have a close relationship, user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller and Maria Lopez have a strong relationship, user: Klaus Mueller is a dormmate of Maria Lopez., user: Klaus Mueller and Maria Lopez have a strong bond, user: Klaus Mueller has a crush on Maria Lopez, user: Klaus Mueller and Maria Lopez have been friends for more than 2 years., user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller Maria Lopez is heading off to college., user: Klaus Mueller and Maria Lopez have a close relationship, user: Klaus Mueller is actively researching a topic, user: Klaus Mueller is close friends and classmates with Maria Lopez., user: Klaus Mueller is socially active, user: Klaus Mueller has a crush on Maria Lopez., user: Klaus Mueller and Maria Lopez have been friends for a long time, user: Klaus Mueller is academically inclined, user: For Klaus Mueller's planning: should remember to ask Maria Lopez about her research paper, as she found it interesting that he mentioned it., user: Klaus Mueller is acquainted with Isabella Rodriguez, user: Klaus Mueller is organized and prepared, user: Maria Lopez is conversing about conversing about Maria's research paper mentioned by Klaus, user: Klaus Mueller is conversing about conversing about Maria's research paper mentioned by Klaus, user: Klaus Mueller is a student, user: Klaus Mueller is a student, user: Klaus Mueller is conversing about two friends named Klaus Mueller and Maria Lopez discussing their morning plans and progress on a research paper before Maria heads off to college., user: Klaus Mueller is socially active, user: Klaus Mueller is socially active, user: Klaus Mueller is socially active and acquainted with Isabella Rodriguez, user: Klaus Mueller has a crush on Maria Lopez]"
+ # run_insight.run(init_agent, statements, n=5)
def test_event_triple_action(self,init_agent):
"""
测试tripleAgent Action
+ 我们需要限制生成字数在15之内,生成字数没有限制的时候很容易跑通
+ Prompt同样存在问题,但是我做了处理
"""
+ run_triple = AgentEventTriple()
+ statements = "(Klaus Mueller is academically inclined)"
+ run_triple.run(statements,init_agent)
pass
def test_poignancy_action(self,init_agent):
"""
测试两个关于poignancy的Action
"""
+
pass
def test_convo_action(self,init_agent):
From da44e12677142f003f23a7211a27eb068f6e2326 Mon Sep 17 00:00:00 2001
From: didi <2020201387@ruc.edu.cn>
Date: Fri, 6 Oct 2023 20:13:46 +0800
Subject: [PATCH 12/12] =?UTF-8?q?PEP8=E6=A0=BC=E5=BC=8F=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../st_game/actions/run_reflect_action.py | 29 +++++----
examples/st_game/reflect/reflect.py | 12 ++--
examples/st_game/tests/test_reflect.py | 63 ++++++++++---------
3 files changed, 53 insertions(+), 51 deletions(-)
diff --git a/examples/st_game/actions/run_reflect_action.py b/examples/st_game/actions/run_reflect_action.py
index 10e22dbcf..d29b654f8 100644
--- a/examples/st_game/actions/run_reflect_action.py
+++ b/examples/st_game/actions/run_reflect_action.py
@@ -23,16 +23,14 @@ class AgentFocusPt(STAction):
except:
return False
- def _func_cleanup(self, llm_resp: str, prompt: str = "") -> list:
+ def _func_cleanup(self, llm_resp: str, prompt: str = "") -> str:
try:
+ """
+ Cleanup handling has been completed for run_v2
+ """
return llm_resp
- # llm_resp = "1) " + llm_resp.strip()
- # ret = []
- # for i in llm_resp.split("\n"):
- # ret += [i.split(") ")[-1]]
- # return ret
except Exception as exp:
- print(f"cleanup 错误 {exp}")
+ logger.error(f"{self.__class__.__name__} with error {exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -70,7 +68,6 @@ class AgentInsightAndGuidance(STAction):
def _func_cleanup(self, llm_resp: str, prompt: str = "") -> dict:
try:
- logger.info(f"Run prompt Insight get {llm_resp}")
llm_resp = "1. " + llm_resp.strip()
ret = dict()
for i in llm_resp.split("\n"):
@@ -82,7 +79,7 @@ class AgentInsightAndGuidance(STAction):
ret[thought] = evi_raw
return ret
except Exception as exp:
- logger.error(f"AGent Insight 报错{exp}")
+ logger.error(f"{self.__class__.__name__} with error {exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -121,10 +118,9 @@ class AgentEventTriple(STAction):
cr = [i.strip() for i in cr.split(")")[0].split(",")]
if len(cr) != 2:
return cr[-2:]
- logger.info(f"cr结果为{cr}")
return cr
except Exception as exp:
- logger.error(f"AGent Triple 报错{exp}")
+ logger.error(f"{self.__class__.__name__} with error {exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -166,7 +162,8 @@ class AgentEventPoignancy(STAction):
llm_resp = int(llm_resp.strip())
return llm_resp
except Exception as exp:
- logger.error(f"AGent Event poignancy 报错{exp}")
+ logger.error(f"{self.__class__.__name__} with error {exp}")
+
def _func_fail_default_resp(self) -> str:
pass
@@ -209,7 +206,8 @@ class AgentChatPoignancy(STAction):
llm_resp = int(llm_resp.strip())
return llm_resp
except Exception as exp:
- logger.error(f"AGent Chat poignancy 报错{exp}")
+ logger.error(f"{self.__class__.__name__} with error {exp}")
+
def _func_fail_default_resp(self) -> str:
pass
@@ -251,7 +249,7 @@ class AgentPlanThoughtOnConvo(STAction):
try:
return llm_resp.split('"')[0].strip()
except Exception as exp:
- logger.error(f"AGent PlanThought 报错{exp}")
+ logger.error(f"{self.__class__.__name__} with error {exp}")
def _func_fail_default_resp(self) -> str:
pass
@@ -290,7 +288,8 @@ class AgentMemoryOnConvo(STAction):
try:
return llm_resp.split('"')[0].strip()
except Exception as exp:
- logger.error(f"AGent MemoryOnconvo 报错{exp}")
+ logger.error(f"{self.__class__.__name__} with error {exp}")
+
def _func_fail_default_resp(self) -> str:
pass
diff --git a/examples/st_game/reflect/reflect.py b/examples/st_game/reflect/reflect.py
index 5423e52bf..62f835e1a 100644
--- a/examples/st_game/reflect/reflect.py
+++ b/examples/st_game/reflect/reflect.py
@@ -44,7 +44,7 @@ def generate_insights_and_evidence(role, nodes, n=5):
ret[thought] = evidence_node_id
return ret
except Exception as exp:
- logger.info(f"insight处理错误为{exp}")
+ logger.error(f"generate_insights_and_evidence error:{exp}")
return {"this is blank": "node_1"}
@@ -59,7 +59,6 @@ def generate_action_event_triple(act_desp, role):
EXAMPLE OUTPUT:
"🧈🍞"
"""
- logger.info(f"event Triple 输入为:{act_desp}")
run_event_triple = AgentEventTriple()
result = run_event_triple.run(act_desp, role)
return result
@@ -108,16 +107,15 @@ def run_reflect(role: "STRole"):
# For each of the focal points, generate thoughts and save it in the
# agent's memory.
for focal_pt, nodes in retrieved.items():
- logger.info(f"检索结果为{nodes}")
- # xx = [i.embedding_key for i in nodes]
- # for xxx in xx: logger.info(xxx)
+ xx = [i.embedding_key for i in nodes]
+ for xxx in xx: logger.info(f"Nodes retrieved for {focal_pt} are {xxx}.")
thoughts = generate_insights_and_evidence(role, nodes, 5)
# 生成的是字典类型
for thought, evidence in thoughts.items():
created = role.scratch.curr_time
expiration = created + datetime.timedelta(days=30)
- s, p, o = generate_action_event_triple("("+thought+")", role)
+ s, p, o = generate_action_event_triple("(" + thought + ")", role)
keywords = set([s, p, o])
thought_poignancy = generate_poig_score(role, "thought", thought)
thought_embedding_pair = (thought, get_embedding(thought))
@@ -126,7 +124,7 @@ def run_reflect(role: "STRole"):
created, expiration, s, p, o, thought, keywords,
thought_poignancy, thought_embedding_pair, evidence
)
- logger.info(f"主谓宾为:{s}{p}{o},描述为{thought}")
+ logger.info(f"add thought memory: {thought}")
def reflection_trigger(role: "STRole"):
diff --git a/examples/st_game/tests/test_reflect.py b/examples/st_game/tests/test_reflect.py
index 1593d9aaa..191e46279 100644
--- a/examples/st_game/tests/test_reflect.py
+++ b/examples/st_game/tests/test_reflect.py
@@ -1,60 +1,65 @@
-
import pytest
from examples.st_game.roles.st_role import STRole
-from examples.st_game.actions.run_reflect_action import AgentFocusPt, AgentInsightAndGuidance, AgentEventTriple, AgentEventPoignancy, AgentChatPoignancy, AgentPlanThoughtOnConvo, AgentMemoryOnConvo
+from examples.st_game.actions.run_reflect_action import AgentFocusPt, AgentInsightAndGuidance, AgentEventTriple, \
+ AgentEventPoignancy, AgentChatPoignancy, AgentPlanThoughtOnConvo, AgentMemoryOnConvo
from metagpt.logs import logger
class TestReflectFunction:
@pytest.fixture
def init_agent(self):
- # 创建一个STRole实例,注意从GA中copy过来JSON文件
- role = STRole(sim_code="July1_the_ville_isabella_maria_klaus-step-3-11", start_date='February 13, 2023', curr_time='February 13, 2023, 14:53:10')
+ """
+ init STRole form local json, set sim_code(path),curr_time & start_date
+ """
+ role = STRole(sim_code="July1_the_ville_isabella_maria_klaus-step-3-11", start_date='February 13, 2023',
+ curr_time='February 13, 2023, 14:53:10')
return role
- def test_function_focus_and_insight_action(self,init_agent):
+ def test_function_focus_and_insight_action(self, init_agent):
"""
- 单个Action测试样例
+ test for AgentFocusPt & AgentInsightAndGuidance
"""
logger.info(f"{__name__}函数启动")
- # run_focus = AgentFocusPt()
- # statements = "" # 这个statements 与 n 设置是遵循reflect里面实际设置# 来的,你写的时候可以对应代码看一下
- # out_put = run_focus.run(init_agent, statements, n=3)
+ run_focus = AgentFocusPt()
+ statements = ""
+ run_focus.run(init_agent, statements, n=3)
"""
这里有通过测试的结果,但是更多时候LLM生成的结果缺少了because of;考虑修改一下prompt
result = {'Klaus Mueller and Maria Lopez have a close relationship because they have been friends for a long time and have a strong bond': [1, 2, 5, 9, 11, 14], 'Klaus Mueller has a crush on Maria Lopez': [8, 15, 24], 'Klaus Mueller is academically inclined and actively researching a topic': [13, 20], 'Klaus Mueller is socially active and acquainted with Isabella Rodriguez': [17, 21, 22], 'Klaus Mueller is organized and prepared': [19]}
"""
- # run_insight = AgentInsightAndGuidance()
- # statements = "[user: Klaus Mueller has a close relationship with Maria Lopez, user:s Mueller and Maria Lopez have a close relationship, user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller and Maria Lopez have a strong relationship, user: Klaus Mueller is a dormmate of Maria Lopez., user: Klaus Mueller and Maria Lopez have a strong bond, user: Klaus Mueller has a crush on Maria Lopez, user: Klaus Mueller and Maria Lopez have been friends for more than 2 years., user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller Maria Lopez is heading off to college., user: Klaus Mueller and Maria Lopez have a close relationship, user: Klaus Mueller is actively researching a topic, user: Klaus Mueller is close friends and classmates with Maria Lopez., user: Klaus Mueller is socially active, user: Klaus Mueller has a crush on Maria Lopez., user: Klaus Mueller and Maria Lopez have been friends for a long time, user: Klaus Mueller is academically inclined, user: For Klaus Mueller's planning: should remember to ask Maria Lopez about her research paper, as she found it interesting that he mentioned it., user: Klaus Mueller is acquainted with Isabella Rodriguez, user: Klaus Mueller is organized and prepared, user: Maria Lopez is conversing about conversing about Maria's research paper mentioned by Klaus, user: Klaus Mueller is conversing about conversing about Maria's research paper mentioned by Klaus, user: Klaus Mueller is a student, user: Klaus Mueller is a student, user: Klaus Mueller is conversing about two friends named Klaus Mueller and Maria Lopez discussing their morning plans and progress on a research paper before Maria heads off to college., user: Klaus Mueller is socially active, user: Klaus Mueller is socially active, user: Klaus Mueller is socially active and acquainted with Isabella Rodriguez, user: Klaus Mueller has a crush on Maria Lopez]"
- # run_insight.run(init_agent, statements, n=5)
+ run_insight = AgentInsightAndGuidance()
+ statements = "[user: Klaus Mueller has a close relationship with Maria Lopez, user:s Mueller and Maria Lopez have a close relationship, user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller and Maria Lopez have a strong relationship, user: Klaus Mueller is a dormmate of Maria Lopez., user: Klaus Mueller and Maria Lopez have a strong bond, user: Klaus Mueller has a crush on Maria Lopez, user: Klaus Mueller and Maria Lopez have been friends for more than 2 years., user: Klaus Mueller has a close relationship with Maria Lopez, user: Klaus Mueller Maria Lopez is heading off to college., user: Klaus Mueller and Maria Lopez have a close relationship, user: Klaus Mueller is actively researching a topic, user: Klaus Mueller is close friends and classmates with Maria Lopez., user: Klaus Mueller is socially active, user: Klaus Mueller has a crush on Maria Lopez., user: Klaus Mueller and Maria Lopez have been friends for a long time, user: Klaus Mueller is academically inclined, user: For Klaus Mueller's planning: should remember to ask Maria Lopez about her research paper, as she found it interesting that he mentioned it., user: Klaus Mueller is acquainted with Isabella Rodriguez, user: Klaus Mueller is organized and prepared, user: Maria Lopez is conversing about conversing about Maria's research paper mentioned by Klaus, user: Klaus Mueller is conversing about conversing about Maria's research paper mentioned by Klaus, user: Klaus Mueller is a student, user: Klaus Mueller is a student, user: Klaus Mueller is conversing about two friends named Klaus Mueller and Maria Lopez discussing their morning plans and progress on a research paper before Maria heads off to college., user: Klaus Mueller is socially active, user: Klaus Mueller is socially active, user: Klaus Mueller is socially active and acquainted with Isabella Rodriguez, user: Klaus Mueller has a crush on Maria Lopez]"
+ run_insight.run(init_agent, statements, n=5)
- def test_event_triple_action(self,init_agent):
+ def test_event_triple_action(self, init_agent):
"""
- 测试tripleAgent Action
- 我们需要限制生成字数在15之内,生成字数没有限制的时候很容易跑通
- Prompt同样存在问题,但是我做了处理
+ test for AgentEventTriple
+ error:遇到复杂情况时(多个Object)无法正确归纳,
+ solution: 限制MaxTokens为15
"""
run_triple = AgentEventTriple()
statements = "(Klaus Mueller is academically inclined)"
- run_triple.run(statements,init_agent)
- pass
+ run_triple.run(statements, init_agent)
- def test_poignancy_action(self,init_agent):
+ def test_poignancy_action(self, init_agent):
"""
- 测试两个关于poignancy的Action
- """
-
- pass
-
- def test_convo_action(self,init_agent):
- """
- 测试两个convo相关的类
+ test for AgentEventPoignancy, AgentChatPoignancy
+ done in reflect test
+ """
+ pass
+
+ def test_convo_action(self, init_agent):
+ """
+ test for AgentPlanThoughtOnConvo, AgentMemoryOnConvo
+ TODO Undone
"""
pass
- # 测试全部Reflection功能
def test_reflect_function(self, init_agent):
- # 修改 近期 importace 确保Reflect机制能够触发
+ """
+ test for reflection
+ modify importance_trigger_curr to trigger reflect
+ """
init_agent.scratch.importance_trigger_curr = -1
init_agent.reflect()