Skip to content

Commit d8ff3d9

Browse files
aact moderator (sotopia-lab#257)
* initial framework * initial conv * fix module error * feat: Add 3 new features to Moderator (sotopia-lab#266) * feat:introduce booting procedure, saving, and ending chat to moderator * fix: moderator will now ignore none AgentAction, Observations now don't have to include all channels in the mapping * merge changes of example into the original one * fix: 1. save() method now accepts push_to_db config 2. booting()'s waiting time is changed to 0.1 sec * fix: rewrite booting() so that different agent will receive different background information * fix: moderator now inherits from Node directly, instead of from BaseAgent --------- Co-authored-by: JXZhou <JXZhou> * add save condition for moderator * push to db false * to fully stop * stopping all agents * fix mypy * fix mypy error --------- Co-authored-by: JXZhou <[email protected]>
1 parent 672fcf7 commit d8ff3d9

File tree

11 files changed

+503
-6
lines changed

11 files changed

+503
-6
lines changed

examples/experimental/nodes/initial_message_node.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ def __init__(
1818
input_tick_channel: str,
1919
output_channels: list[str],
2020
env_scenario: str,
21+
node_name: str,
2122
redis_url: str = "redis://localhost:6379/0",
2223
):
2324
super().__init__(
@@ -26,6 +27,7 @@ def __init__(
2627
(output_channel, Text) for output_channel in output_channels
2728
],
2829
redis_url=redis_url,
30+
node_name=node_name,
2931
)
3032
self.env_scenario = env_scenario
3133
self.output_channels = output_channels
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import logging
2+
import sys
3+
from rich.logging import RichHandler
4+
5+
from aact import NodeFactory
6+
7+
from sotopia.experimental.agents.base_agent import BaseAgent
8+
from sotopia.experimental.agents.datamodels import Observation, AgentAction
9+
10+
from sotopia.generation_utils import agenerate
11+
from sotopia.generation_utils.generate import StrOutputParser
12+
13+
# Check Python version
14+
if sys.version_info >= (3, 11):
15+
pass
16+
else:
17+
pass
18+
19+
# Configure logging
20+
FORMAT = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"
21+
logging.basicConfig(
22+
level=logging.WARNING,
23+
format=FORMAT,
24+
datefmt="[%X]",
25+
handlers=[RichHandler()],
26+
)
27+
28+
29+
@NodeFactory.register("llm_agent")
30+
class LLMAgent(BaseAgent[Observation, AgentAction]):
31+
def __init__(
32+
self,
33+
input_channels: list[str],
34+
output_channel: str,
35+
query_interval: int,
36+
agent_name: str,
37+
node_name: str,
38+
goal: str,
39+
model_name: str,
40+
redis_url: str,
41+
):
42+
super().__init__(
43+
[(input_channel, Observation) for input_channel in input_channels],
44+
[(output_channel, AgentAction)],
45+
redis_url,
46+
node_name,
47+
)
48+
self.output_channel = output_channel
49+
self.query_interval = query_interval
50+
self.count_ticks = 0
51+
self.message_history: list[Observation] = []
52+
self.name = agent_name
53+
self.model_name = model_name
54+
self.goal = goal
55+
56+
def _format_message_history(self, message_history: list[Observation]) -> str:
57+
## TODO: akhatua Fix the mapping of action to be gramatically correct
58+
return "\n".join(message.to_natural_language() for message in message_history)
59+
60+
async def aact(self, obs: Observation) -> AgentAction:
61+
if obs.turn_number == -1:
62+
return AgentAction(
63+
agent_name=self.name,
64+
output_channel=self.output_channel,
65+
action_type="none",
66+
argument=self.model_name,
67+
)
68+
69+
self.message_history.append(obs)
70+
71+
if len(obs.available_actions) == 1 and "none" in obs.available_actions:
72+
return AgentAction(
73+
agent_name=self.name,
74+
output_channel=self.output_channel,
75+
action_type="none",
76+
argument="",
77+
)
78+
elif len(obs.available_actions) == 1 and "leave" in obs.available_actions:
79+
self.shutdown_event.set()
80+
return AgentAction(
81+
agent_name=self.name,
82+
output_channel=self.output_channel,
83+
action_type="leave",
84+
argument="",
85+
)
86+
else:
87+
history = self._format_message_history(self.message_history)
88+
action: str = await agenerate(
89+
model_name=self.model_name,
90+
template="Imagine that you are a friend of the other persons. Here is the "
91+
"conversation between you and them.\n"
92+
"You are {agent_name} in the conversation.\n"
93+
"{message_history}\n"
94+
"and you plan to {goal}.\n"
95+
"You can choose to interrupt the other person "
96+
"by saying something or not to interrupt by outputting notiong. What would you say? "
97+
"Please only output a sentence or not outputting anything."
98+
"{format_instructions}",
99+
input_values={
100+
"message_history": history,
101+
"goal": self.goal,
102+
"agent_name": self.name,
103+
},
104+
temperature=0.7,
105+
output_parser=StrOutputParser(),
106+
)
107+
108+
return AgentAction(
109+
agent_name=self.name,
110+
output_channel=self.output_channel,
111+
action_type="speak",
112+
argument=action,
113+
)
Lines changed: 1 addition & 0 deletions
Loading

0 commit comments

Comments
 (0)