Skip to content

Commit c265fba

Browse files
committed
Add example_cocktail_rl_v2 with configurable batch ratios and dynamic scheduling
- Implemented AppWorld and AIME swarm clients for the new cocktail RL version. - Introduced CocktailV2Config as a single source of truth for configuration values. - Created train_appworld_as_swarm_client_0 and train_aime_as_swarm_client_1 scripts for running the respective clients. - Added cocktail_v2_runner to manage shared functionality between clients. - Included readme.md for setup instructions and configuration details. - Enhanced evaluation and logging mechanisms for better performance tracking.
1 parent bba6661 commit c265fba

20 files changed

Lines changed: 1498 additions & 146 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,5 @@ research_*.json
185185
research_*.jsonc
186186
daemon_logs*
187187
paper
188+
val_results.md
189+
cocktail_vs_separate*

ajet/copilot/monitor-with-tmux/SKILL.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,3 +180,11 @@ $ python3 /tmp/tmux_wait.py ajet_session 240 && tmux capture-pane -t ajet_sessio
180180
tmux kill-session -t ajet_session
181181
182182
```
183+
184+
185+
## For AgentJet Swarm
186+
187+
- You should create seperate tmux session for each agentjet swarm servers and each agentjet swarm clients
188+
- When debugging, please do not restart agentjet swarm servers frequently, that waste too much time
189+
- When you really having difficulty for clearing GPU memory, run `ajet --autokill` to automatically kill all python and ray processes (however, I still recommend using this as a last resort).
190+
- For AgentJet, always use tmux session name that starts with `ajet-*`

ajet/default_config/ajet_config_schema.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class AjetModel:
4040
class AjetData:
4141
max_prompt_length: int = 3000
4242
max_response_length: int = 15000
43+
# Note that this value is ignored when swarm_mode_sample_collection_method="rollout_until_all_clients_agree_sync_weight"
4344
train_batch_size: int = 32
4445

4546

ajet/default_config/ajet_default.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ ajet:
1616
# max number of tokens for response
1717
max_response_length: 15000
1818
# how many tasks per training batch
19+
# Note that this value is ignored when swarm_mode_sample_collection_method="rollout_until_all_clients_agree_sync_weight"
1920
train_batch_size: 32
2021
# [Hint]: The final number of samples per update will be: N_{sample} = (data.train_batch_size * rollout.num_repeat * rollout.multi_turn.expected_steps)
2122

ajet/default_config/ajet_swarm_default.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ ajet:
6767
# max number of tokens for response
6868
max_response_length: 15000
6969
# how many tasks per training batch
70+
# Note that this value is ignored when swarm_mode_sample_collection_method="rollout_until_all_clients_agree_sync_weight"
7071
train_batch_size: 32
7172
# [Hint]: The final number of samples per update will be: N_{sample} = (data.train_batch_size * rollout.num_repeat * rollout.multi_turn.expected_steps)
7273

ajet/swarm_cli.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from dotenv import load_dotenv
66
from loguru import logger
77

8+
from ajet.utils.cleaner import fast_kill_by_keyword_bash
89
from ajet.utils.config_utils import prepare_experiment_config
910
from ajet.utils.launch_utils import (
1011
dict_to_namespace,
@@ -41,6 +42,21 @@ def start_swarm_server(env, config, port):
4142

4243
def cmd_start(args):
4344
"""Handle the 'start' subcommand."""
45+
if args.autokill:
46+
args.kill = "ray|vllm|VLLM|python"
47+
48+
if args.kill:
49+
logger.info(f"Killing processes matching keywords: {args.kill}")
50+
for keyword in args.kill.split("|"):
51+
logger.info(f"Killing processes matching keyword: {keyword}")
52+
killed_pids = fast_kill_by_keyword_bash(keyword)
53+
if killed_pids:
54+
logger.success(
55+
f"Successfully killed processes with PIDs: {killed_pids}"
56+
)
57+
else:
58+
logger.warning(f"No processes found matching keyword: {keyword}")
59+
4460
# Use default config if not provided
4561
exp_base_dir = args.exp_dir or DEFAULT_DIR
4662
if not args.conf:
@@ -126,6 +142,19 @@ def main():
126142
required=False,
127143
help="Debug tags; enables Ray post-mortem and DEBUG_TAGS env",
128144
)
145+
parser_start.add_argument(
146+
"--kill",
147+
type=str,
148+
default="",
149+
required=False,
150+
help="list of keywords for killing processes",
151+
)
152+
parser_start.add_argument(
153+
"--autokill",
154+
action="store_true",
155+
default=False,
156+
help="Kill system processes (ray + vllm + python) that may block the current experiment",
157+
)
129158

130159
parser_start.set_defaults(func=cmd_start)
131160

ajet/task_rollout/async_llm_bridge.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ async def llm_chat_verl(
122122
):
123123

124124
parsed_tool_calls = self.tool_parser.extract_tool_calls(decoded_text, None) # type: ignore
125-
parsed_tool_calls = parsed_tool_calls.model_dump()
125+
parsed_tool_calls = parsed_tool_calls.model_dump(mode='json')
126126

127127
model_called = parsed_tool_calls["tools_called"]
128128
if model_called:
@@ -155,7 +155,7 @@ async def llm_chat_verl(
155155
"completion_tokens": len(token_array), # type: ignore
156156
"total_tokens": len(prompt_token_ids) + len(token_array), # type: ignore
157157
}
158-
# from ajet import bp; bp("DECODE")
158+
159159
return {
160160
"role": "assistant",
161161
"request_id": request_id,
@@ -327,7 +327,7 @@ async def chat_completion_request(
327327
episode_uuid: str,
328328
):
329329
from openai.types.chat.chat_completion import ChatCompletion
330-
req_as_dict = req.model_dump()
330+
req_as_dict = req.model_dump(mode='json')
331331

332332
# infer + process with context tracker
333333
llm_output = await self.run_infer(

ajet/utils/env_service_client/env_client_ng.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,18 +207,20 @@ def call():
207207
messages=action,
208208
params=params,
209209
)
210-
return resp["data"]
210+
data = resp["data"]
211+
while "data" in data and "state" not in data:
212+
data = data["data"]
213+
data["state"] = data["state"][0]
214+
return data
211215

212-
res = retry_call(
216+
return retry_call(
213217
call,
214218
max_retry=max_retry,
215219
fail_return=fallback,
216220
err_prefix="[step]",
217221
instance_id=instance_id,
218222
action_name="step",
219223
)
220-
res["state"] = res["state"][0]
221-
return res
222224

223225
def evaluate(
224226
self,

appworld_swarm_results/val_results.md

Lines changed: 0 additions & 77 deletions
This file was deleted.

tutorial/example_appworld/appworld.md

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,19 @@
11
## Run Appworld AgentScope Agent
22

3-
### 1. Install Appworld
3+
### 1. Install and Run Appworld
4+
5+
- Install:
6+
```
7+
rm -rf /tmp/pack_all_in_one & wget https://dail-wlcb.oss-cn-wulanchabu.aliyuncs.com/astuner_archive/appworld_pack_v3.tar.gz && tar -xzf ./appworld_pack_v3.tar.gz -C /tmp
48
```
5-
def install_appworld():
6-
# run:
7-
# `rm -rf /tmp/pack_all_in_one & wget https://dail-wlcb.oss-cn-wulanchabu.aliyuncs.com/astuner_archive/appworld_pack_v3.tar.gz && tar -xzf ./appworld_pack_v3.tar.gz -C /tmp`
8-
import shutil
9-
10-
if os.path.exists("/tmp/pack_all_in_one"):
11-
shutil.rmtree("/tmp/pack_all_in_one")
12-
if os.path.exists("./appworld_pack_v3.tar.gz"):
13-
os.remove("./appworld_pack_v3.tar.gz")
14-
subprocess.run(
15-
[
16-
"wget",
17-
"https://dail-wlcb.oss-cn-wulanchabu.aliyuncs.com/astuner_archive/appworld_pack_v3.tar.gz",
18-
]
19-
)
20-
subprocess.run(
21-
[
22-
"tar",
23-
"-xzf",
24-
"./appworld_pack_v3.tar.gz",
25-
"-C",
26-
"/tmp",
27-
]
28-
)
29-
# write
30-
os.environ["APPWORLD_PATH"] = "/tmp/pack_all_in_one"
31-
os.environ["APPWORLD_SCRIPT"] = "bash EnvService/env_sandbox/appworld.sh"
9+
10+
- Run:
3211
```
12+
export APPWORLD_PATH="/tmp/pack_all_in_one"
13+
export APPWORLD_SCRIPT="bash EnvService/env_sandbox/appworld.sh"
14+
ajet --with-appworld --skip-check-avail-gpu
15+
```
16+
3317

3418

3519
### 2. Prepare AgentScope Workflow

0 commit comments

Comments
 (0)