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] 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(