Skip to content

Commit 282244e

Browse files
pan-x-cpanxuchenPatrickG1014chenyushuo
authored
Add environment modules (#378)
Co-authored-by: panxuchen <[email protected]> Co-authored-by: gaoheyang <[email protected]> Co-authored-by: chenyushuo <[email protected]>
1 parent 7befaf8 commit 282244e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+8751
-2234
lines changed

docs/sphinx_doc/en/source/tutorial/208-distribute.md

+360-318
Large diffs are not rendered by default.

docs/sphinx_doc/zh_CN/source/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ AgentScope 文档
5858
agentscope.service
5959
agentscope.rpc
6060
agentscope.server
61+
agentscope.environment
6162
agentscope.web
6263
agentscope.prompt
6364
agentscope.utils

docs/sphinx_doc/zh_CN/source/tutorial/208-distribute.md

+369-316
Large diffs are not rendered by default.

examples/distributed_parallel_optimization/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def parse_args() -> argparse.Namespace:
5353
model_config_name="my_model",
5454
)
5555
if args.use_dist:
56-
answerer = answerer.to_dist(lazy_launch=False)
56+
answerer = answerer.to_dist()
5757
answerers.append(answerer)
5858

5959
user_agent = UserAgent()

examples/distributed_simulation/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ def run_main_process(
196196
Msg(
197197
name="Moderator",
198198
role="assistant",
199-
content=f"The average value is {summ/cnt} [takes {et-st} s]",
199+
content=f"The average value is {summ / cnt} [takes {et - st} s]",
200200
),
201201
)
202202

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Simple Auction Simulation
2+
3+
This is a simple example of auction simulation to show the environment module of AgentScope.
4+
5+
## Background
6+
7+
This example simulates the following scenario:
8+
9+
Some bidders, each carrying their own money, participate in an auction. After the bidding for an item begins, they decide whether to bid a higher price after hearing the bids of others. When no one places a bid after the waiting time has elapsed, the auctioneer announces the auction results.
10+
11+
## How to Run
12+
13+
```shell
14+
cd examples/environments/auction_simulation
15+
python main.py
16+
```
17+
18+
You can also set the following arguments:
19+
20+
- `bidder-num`: the number of bidders who participate in the auction.
21+
- `agent-type`: `random` or `llm`, the agent type of bidders.
22+
- `waiting-time`: the waiting time for the auctioneer to decide the winner.
23+
- `use-dist`: whether to use the distributed version. (You have to shut down the simulation manually in the distributed version.)
24+
25+
The following is sample output:
26+
27+
```log
28+
Auction: Auction starts!
29+
Listener: Notifying the bidder bidder_0...
30+
Listener: Notifying the bidder bidder_1...
31+
Listener: Notifying the bidder bidder_2...
32+
Listener: Notifying the bidder bidder_3...
33+
Listener: Notifying the bidder bidder_4...
34+
bidder_1: Bid 34 for oil_painting
35+
Listener: Bidder bidder_1 bids 34 for oil_painting. Notifying Bidder bidder_0
36+
Listener: Bidder bidder_1 bids 34 for oil_painting. Notifying Bidder bidder_2
37+
Listener: Bidder bidder_1 bids 34 for oil_painting. Notifying Bidder bidder_3
38+
Listener: Bidder bidder_1 bids 34 for oil_painting. Notifying Bidder bidder_4
39+
...
40+
bidder_1: Bid 88 for oil_painting
41+
Listener: Bidder bidder_1 bids 88 for oil_painting. Notifying Bidder bidder_0
42+
bidder_0: Bid 53 for oil_painting
43+
Listener: Bidder bidder_1 bids 88 for oil_painting. Notifying Bidder bidder_2
44+
Listener: Bidder bidder_1 bids 88 for oil_painting. Notifying Bidder bidder_3
45+
Listener: Bidder bidder_1 bids 88 for oil_painting. Notifying Bidder bidder_4
46+
bidder_3: Not bid for oil_painting
47+
bidder_0: Not bid for oil_painting
48+
bidder_3: Bid 35 for oil_painting
49+
bidder_4: Bid 21 for oil_painting
50+
bidder_0: Not bid for oil_painting
51+
bidder_1: Bid 26 for oil_painting
52+
bidder_2: Not bid for oil_painting
53+
Auction: Auction ends!
54+
Auction: oil_painting is sold to bidder_1 for 88
55+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# -*- coding: utf-8 -*-
2+
"""The agents used to simulate an auction."""
3+
import random
4+
import re
5+
import time
6+
from typing import Optional, Sequence, Union
7+
8+
from env import Item
9+
10+
from loguru import logger
11+
from agentscope.agents import AgentBase
12+
from agentscope.message import Msg
13+
14+
15+
class RandomBidder(AgentBase):
16+
"""A fake bidder agent who bids randomly."""
17+
18+
def __init__(
19+
self,
20+
name: str,
21+
money: int = 100,
22+
not_bid_ratio: float = 0.5,
23+
sleep_time: float = 1.0,
24+
) -> None:
25+
"""Initialize the bidder agent."""
26+
super().__init__(name=name)
27+
self.money = money
28+
self.not_bid_ratio = not_bid_ratio
29+
self.sleep_time = sleep_time
30+
31+
def generate_random_response(self, start: int = 0) -> Optional[int]:
32+
"""Generate a random bid or not to bid."""
33+
time.sleep(random.random() * self.sleep_time)
34+
if random.random() < self.not_bid_ratio:
35+
return None
36+
return random.randint(start, self.money)
37+
38+
def reply(self, x: Optional[Union[Msg, Sequence[Msg]]] = None) -> Msg:
39+
"""Generate a random value"""
40+
item = Item.from_dict(x.content["item"])
41+
# generate a random bid or not to bid
42+
response = self.generate_random_response(item.opening_price)
43+
if response is None:
44+
self.speak(
45+
Msg(
46+
self.name,
47+
content=f"Not bid for {item.name}",
48+
role="assistant",
49+
),
50+
)
51+
return Msg(self.name, content=None, role="assistant")
52+
else:
53+
self.speak(
54+
Msg(
55+
self.name,
56+
content=f"Bid {response} for {item.name}",
57+
role="assistant",
58+
),
59+
)
60+
msg = Msg(self.name, content=response, role="assistant")
61+
return msg
62+
63+
64+
class Bidder(AgentBase):
65+
"""The bidder agent."""
66+
67+
def __init__(
68+
self,
69+
name: str,
70+
model_config_name: str,
71+
money: int = 100,
72+
) -> None:
73+
"""Initialize the bidder agent."""
74+
super().__init__(
75+
name=name,
76+
model_config_name=model_config_name,
77+
use_memory=True,
78+
)
79+
self.money = money
80+
self.prompt = Msg(
81+
name="system",
82+
role="system",
83+
content="You are a bidder. You will be given an item. "
84+
f"You have {self.money} money. "
85+
"Please consider whether to bid for the item. "
86+
"If you want to bid, please provide the bid value "
87+
"(an integer between 1 and your money). "
88+
"If you don't want to bid, please provide 0.",
89+
)
90+
91+
def parse_value(self, txt: str) -> Optional[int]:
92+
"""Parse the bid from the response."""
93+
numbers = re.findall(r"\d+", txt)
94+
if len(numbers) == 0:
95+
logger.warning(
96+
f"Fail to parse value from [{txt}], use not bidding instead.",
97+
)
98+
return None
99+
elif int(numbers[-1]) > self.money:
100+
logger.warning(
101+
f"Try to bid more than {self.money}, "
102+
f"use {self.money} instead.",
103+
)
104+
return self.money
105+
else:
106+
return int(numbers[-1]) if numbers[-1] != "0" else None
107+
108+
def reply(self, x: Optional[Union[Msg, Sequence[Msg]]] = None) -> Msg:
109+
"""Generate a value by LLM"""
110+
111+
if self.memory:
112+
self.memory.add(x)
113+
114+
item = Item.from_dict(x.content["item"])
115+
bidder_name = x.content.get("bidder_name", None)
116+
prev_bid = x.content.get("bid", None)
117+
content = (
118+
f"The item is {item.name} and "
119+
f"the opening price is {item.opening_price}."
120+
)
121+
if bidder_name and prev_bid:
122+
content += f"\n{bidder_name} bid {prev_bid} for the item."
123+
bid_info = Msg("assistant", content=content, role="assistant")
124+
125+
# prepare prompt
126+
prompt = self.model.format(
127+
self.prompt,
128+
self.memory.get_memory(),
129+
bid_info,
130+
)
131+
132+
# call llm and generate response
133+
response = self.model(prompt).text
134+
bid = self.parse_value(response)
135+
msg = Msg(self.name, bid, role="assistant")
136+
if response is None:
137+
self.speak(
138+
Msg(
139+
self.name,
140+
content=f"Not bid for {item.name}",
141+
role="assistant",
142+
),
143+
)
144+
else:
145+
self.speak(
146+
Msg(
147+
self.name,
148+
content=f"Bid {response} for {item.name}",
149+
role="assistant",
150+
),
151+
)
152+
# Record the message in memory
153+
if self.memory:
154+
self.memory.add(msg)
155+
156+
return msg
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"config_name": "model",
4+
"model_type": "openai_chat",
5+
"model_name": "path-to-your-model-dir",
6+
"api_key": "EMPTY",
7+
"client_args": {
8+
"base_url": "http://localhost:8083/v1"
9+
},
10+
"generate_args": {
11+
"temperature": 1.0
12+
}
13+
}
14+
]

0 commit comments

Comments
 (0)