diff --git a/examples/st_game/actions/gen_iter_chat_utt.py b/examples/st_game/actions/gen_iter_chat_utt.py
new file mode 100644
index 000000000..02a96191f
--- /dev/null
+++ b/examples/st_game/actions/gen_iter_chat_utt.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# @Desc : generate_iterative_chat_utt
+
+from metagpt.logs import logger
+from metagpt.schema import Message
+
+from ..roles.st_role import STRole
+from ..actions.st_action import STAction
+from ..utils.utils import extract_first_json_dict
+from ..maze import Maze
+
+
+class GenIterChatUTT(STAction):
+
+ def __init__(self, name="GenIterChatUTT", context: list[Message] = None, llm=None):
+ super().__init__(name, context, llm)
+
+ def _func_validate(self, llm_resp: str, prompt: str) -> bool:
+ resp = False
+ try:
+ _ = extract_first_json_dict(llm_resp)
+ resp = True
+ except Exception as exp:
+ pass
+ return resp
+
+ def _func_cleanup(self, llm_resp: str, prompt: str) -> dict:
+ gpt_response = extract_first_json_dict(llm_resp)
+
+ cleaned_dict = dict()
+ cleaned = []
+ for key, val in gpt_response.items():
+ cleaned += [val]
+ cleaned_dict["utterance"] = cleaned[0]
+ cleaned_dict["end"] = True
+ if "f" in str(cleaned[1]) or "F" in str(cleaned[1]):
+ cleaned_dict["end"] = False
+
+ return cleaned_dict
+
+ def _func_fail_default_resp(self) -> dict:
+ cleaned_dict = dict()
+ cleaned_dict["utterance"] = "..."
+ cleaned_dict["end"] = False
+ return cleaned_dict
+
+ async def run(self, maze: Maze, init_role: STRole, target_role: STRole, retrieved: dict, curr_context: str,
+ curr_chat: list[str], *args, **kwargs) -> dict:
+ def create_prompt_input(maze: Maze, init_role: STRole, target_role: STRole,
+ retrieved: dict, curr_context: str, curr_chat: list[str]):
+ role = init_role
+ scratch = role._rc.scratch
+ target_scratch = target_role._rc.scratch
+ prev_convo_insert = "\n"
+ if role._rc.memory.chat_list:
+ for i in role._rc.memory.chat_list:
+ if i.object == target_role.name:
+ v1 = int((scratch.curr_time - i.created).total_seconds() / 60)
+ prev_convo_insert += f"{str(v1)} minutes ago, {scratch.name} and " \
+ f"{target_scratch.name} were already {i.description} " \
+ f"This context takes place after that conversation."
+ break
+ if prev_convo_insert == "\n":
+ prev_convo_insert = ""
+ if role._rc.memory.chat_list:
+ if int((scratch.curr_time - role._rc.memory.chat_list[-1].created).total_seconds() / 60) > 480:
+ prev_convo_insert = ""
+ print(prev_convo_insert)
+
+ curr_sector = f"{maze.access_tile(scratch.curr_tile)['sector']}"
+ curr_arena = f"{maze.access_tile(scratch.curr_tile)['arena']}"
+ curr_location = f"{curr_arena} in {curr_sector}"
+
+ retrieved_str = ""
+ for key, vals in retrieved.items():
+ for v in vals:
+ retrieved_str += f"- {v.description}\n"
+
+ convo_str = ""
+ for i in curr_chat:
+ convo_str += ": ".join(i) + "\n"
+ if convo_str == "":
+ convo_str = "[The conversation has not started yet -- start it!]"
+
+ init_iss = f"Here is Here is a brief description of {scratch.name}.\n{scratch.get_str_iss()}"
+ prompt_input = [init_iss, scratch.name, retrieved_str, prev_convo_insert,
+ curr_location, curr_context, scratch.name, target_scratch.name,
+ convo_str, scratch.name, target_scratch.name,
+ scratch.name, scratch.name,
+ scratch.name
+ ]
+ return prompt_input
+
+ prompt_input = create_prompt_input(maze, init_role, target_role, retrieved, curr_context, curr_chat)
+ prompt = self.generate_prompt_with_tmpl_filename(prompt_input,
+ "iterative_convo_v1.txt")
+ # original using `ChatGPT_safe_generate_response_OLD`
+ self.fail_default_resp = self._func_fail_default_resp()
+ output = await self._run_v1(prompt)
+ return output
diff --git a/examples/st_game/plan/converse.py b/examples/st_game/plan/converse.py
new file mode 100644
index 000000000..cf1d92f08
--- /dev/null
+++ b/examples/st_game/plan/converse.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# @Desc : conversation between two agents
+
+from typing import Union, Tuple
+
+from metagpt.logs import logger
+
+from ..maze import Maze
+from ..roles.st_role import STRole
+from ..memory.retrieve import new_retrieve
+from ..actions.agent_chat_sum_rel import AgentChatSumRel
+from ..actions.gen_iter_chat_utt import GenIterChatUTT
+
+
+def agent_conversation(maze: Maze, init_role: STRole, target_role: STRole) -> list[str]:
+ curr_chat = []
+ logger.info(f"Role: {init_role.name} starts a conversation with Role: {target_role.name}")
+
+ conv_rounds = 8
+ for idx in range(conv_rounds):
+ scratch = init_role._rc.scratch
+ target_scratch = target_role._rc.scratch
+
+ focal_points = [f"{target_scratch.name}"]
+ retrieved = new_retrieve(init_role, focal_points, 50)
+ relationship = generate_summarize_agent_relationship(init_role, target_role, retrieved)
+ print("-------- relationship: ", relationship)
+ last_chat = ""
+ for i in curr_chat[-4:]:
+ last_chat += ": ".join(i) + "\n"
+ if last_chat:
+ focal_points = [f"{relationship}",
+ f"{target_scratch.name} is {target_scratch.act_description}",
+ last_chat]
+ else:
+ focal_points = [f"{relationship}",
+ f"{target_scratch.name} is {target_scratch.act_description}"]
+ retrieved = new_retrieve(init_role, focal_points, 15)
+ utt, end = generate_one_utterance(maze, init_role, target_role, retrieved, curr_chat)
+
+ curr_chat += [[scratch.name, utt]]
+ if end:
+ break
+
+ focal_points = [f"{scratch.name}"]
+ retrieved = new_retrieve(target_role, focal_points, 50)
+ relationship = generate_summarize_agent_relationship(target_role, init_role, retrieved)
+ print("-------- relationship: ", relationship)
+ last_chat = ""
+ for i in curr_chat[-4:]:
+ last_chat += ": ".join(i) + "\n"
+ if last_chat:
+ focal_points = [f"{relationship}",
+ f"{scratch.name} is {scratch.act_description}",
+ last_chat]
+ else:
+ focal_points = [f"{relationship}",
+ f"{scratch.name} is {scratch.act_description}"]
+ retrieved = new_retrieve(target_role, focal_points, 15)
+ utt, end = generate_one_utterance(maze, target_role, init_role, retrieved, curr_chat)
+
+ curr_chat += [[target_scratch.name, utt]]
+ if end:
+ break
+
+ print("July 23 PU")
+ for row in curr_chat:
+ print(row)
+ print("July 23 FIN")
+
+ return curr_chat
+
+
+def generate_summarize_agent_relationship(init_role: STRole,
+ target_role: STRole,
+ retrieved: dict) -> str:
+ all_embedding_keys = list()
+ for key, val in retrieved.items():
+ for i in val:
+ all_embedding_keys += [i.embedding_key]
+ all_embedding_key_str = ""
+ for i in all_embedding_keys:
+ all_embedding_key_str += f"{i}\n"
+
+ summarized_relationship = AgentChatSumRel().run(init_role,
+ target_role,
+ all_embedding_key_str)
+ return summarized_relationship
+
+
+def generate_one_utterance(maze: Maze, init_role, target_role, retrieved: dict, curr_chat: list) -> Tuple[str, str]:
+ # Chat version optimized for speed via batch generation
+ scratch = init_role._rc.scratch
+ target_scratch = target_role._rc.scratch
+ curr_context = (f"{scratch.name} " +
+ f"was {scratch.act_description} " +
+ f"when {scratch.name} " +
+ f"saw {target_scratch.name} " +
+ f"in the middle of {target_scratch.act_description}.\n")
+ curr_context += (f"{scratch.name} " +
+ f"is initiating a conversation with " +
+ f"{target_scratch.name}.")
+
+ print("July 23 5")
+ x = GenIterChatUTT().run(maze, init_role, target_role, retrieved, curr_context, curr_chat)
+
+ print("July 23 6")
+
+ return x["utterance"], x["end"]
diff --git a/examples/st_game/prompts/decide_to_talk_v2.txt b/examples/st_game/prompts/decide_to_talk_v2.txt
new file mode 100644
index 000000000..94204f9eb
--- /dev/null
+++ b/examples/st_game/prompts/decide_to_talk_v2.txt
@@ -0,0 +1,18 @@
+decide_to_talk_v1.txt
+
+###
+Task -- given context, determine whether the subject will initiate a conversation with another.
+Format:
+Context: []
+Question: []
+Reasoning: []
+Answer in "yes" or "no": []
+---
+Context: !!
+Right now, it is !!. !! and !! last chatted at !! about !!.
+!!
+!!
+
+Question: Would !! initiate a conversation with !!?
+
+Reasoning: Let's think step by step.
\ No newline at end of file
diff --git a/examples/st_game/prompts/iterative_convo_v1.txt b/examples/st_game/prompts/iterative_convo_v1.txt
new file mode 100644
index 000000000..7bd4e7216
--- /dev/null
+++ b/examples/st_game/prompts/iterative_convo_v1.txt
@@ -0,0 +1,46 @@
+iterative_convo_v1.txt
+
+Variables:
+!! -- persona ISS
+!! -- persona name
+!! -- retrieved memory
+!! -- past context
+!! -- current location
+!! -- current context
+!! -- persona name
+!! -- target persona name
+!! -- curr convo
+!! -- persona name
+!! -- target persona name
+!! -- persona name
+!! -- persona name
+!! -- persona name
+###
+Context for the task:
+
+PART 1.
+!!
+
+Here is the memory that is in !!'s head:
+!!
+
+PART 2.
+Past Context:
+!!
+
+Current Location: !!
+
+Current Context:
+!!
+
+!! and !! are chatting. Here is their conversation so far:
+!!
+
+---
+Task: Given the above, what should !! say to !! next in the conversation? And did it end the conversation?
+
+Output format: Output a json of the following format:
+{
+"!!": "!'s utterance>",
+"Did the conversation end with !!'s utterance?": ""
+}
\ No newline at end of file
diff --git a/examples/st_game/prompts/new_decomp_schedule_v1.txt b/examples/st_game/prompts/new_decomp_schedule_v1.txt
new file mode 100644
index 000000000..e21dc69eb
--- /dev/null
+++ b/examples/st_game/prompts/new_decomp_schedule_v1.txt
@@ -0,0 +1,24 @@
+new_decomp_schedule_v1.txt
+
+Variables:
+!! -- persona name
+!! -- start hour
+!! -- end hour
+!! -- original plan
+!! -- persona name
+!! -- new event
+!! -- new event duration
+!! -- persona name
+!! -- start hour
+!! -- end hour
+!! -- end hour
+!! -- new schedule init
+
+
+###
+Here was !!'s originally planned schedule from !! to !!.
+!!
+
+But !! unexpectedly ended up !! for !! minutes. Revise !!'s schedule from !! to !! accordingly (it has to end by !!).
+The revised schedule:
+!!
\ No newline at end of file
diff --git a/examples/st_game/prompts/summarize_chat_relationship_v2.txt b/examples/st_game/prompts/summarize_chat_relationship_v2.txt
new file mode 100644
index 000000000..6f71824da
--- /dev/null
+++ b/examples/st_game/prompts/summarize_chat_relationship_v2.txt
@@ -0,0 +1,15 @@
+summarize_chat_relationship_v2.txt
+
+Variables:
+!! -- Statements
+!! -- curr persona name
+!! -- target_persona.scratch.name
+
+###
+[Statements]
+!!
+
+Based on the statements above, summarize !! and !!'s relationship. What do they feel or know about each other?
+
+
+"
\ No newline at end of file
diff --git a/examples/st_game/prompts/summarize_conversation_v1.txt b/examples/st_game/prompts/summarize_conversation_v1.txt
new file mode 100644
index 000000000..1cb423c7d
--- /dev/null
+++ b/examples/st_game/prompts/summarize_conversation_v1.txt
@@ -0,0 +1,11 @@
+summarize_conversation_v1.txt
+
+Variables:
+!! -- init_persona_name
+
+###
+Conversation:
+!!
+
+Summarize the conversation above in one sentence:
+This is a conversation about
\ No newline at end of file