self-evolve-framework 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/rules/ponytail.mdc +98 -23
- package/template/skills/skillopt-sleep/SKILL.md +42 -0
- package/template/skills/skillopt-sleep/configs/_base_/default.yaml +103 -0
- package/template/skills/skillopt-sleep/configs/alfworld/default.yaml +29 -0
- package/template/skills/skillopt-sleep/configs/docvqa/default.yaml +28 -0
- package/template/skills/skillopt-sleep/configs/features/soft_gate.yaml +47 -0
- package/template/skills/skillopt-sleep/configs/livemathematicianbench/default.yaml +22 -0
- package/template/skills/skillopt-sleep/configs/officeqa/default.yaml +34 -0
- package/template/skills/skillopt-sleep/configs/searchqa/default.yaml +32 -0
- package/template/skills/skillopt-sleep/configs/spreadsheetbench/default.yaml +34 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/__init__.py +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/config.py +282 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/datasets/__init__.py +7 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/datasets/base.py +512 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/engine/__init__.py +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/engine/trainer.py +2379 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/README.md +43 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/config_template.yaml +55 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/env_template.py +151 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/_template/loader_template.py +87 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/__init__.py +5 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/adapter.py +428 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/dataloader.py +123 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/analyst_error.md +55 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/analyst_success.md +33 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_no_history.md +8 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_with_history.md +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/prompts/rollout_with_memory.md +16 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/rollout.py +366 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/skills/initial.md +45 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/__init__.py +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_envs.py +221 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_projection.py +60 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/alfworld_prompts.py +8 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/config_tw.yaml +145 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/env_base.py +84 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/env_manager.py +139 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/memory.py +87 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/base.py +329 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/adapter.py +90 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/dataloader.py +61 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/evaluator.py +113 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/analyst_error.md +35 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/analyst_success.md +24 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/prompts/rollout_system.md +12 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/rollout.py +391 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/docvqa/skills/initial.md +11 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/adapter.py +129 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/dataloader.py +308 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/evaluator.py +62 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/analyst_error.md +37 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/analyst_success.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/prompts/rollout_system.md +12 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/rollout.py +434 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/livemathematicianbench/skills/initial.md +16 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/adapter.py +112 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/dataloader.py +71 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/evaluator.py +46 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/analyst_error.md +37 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/analyst_success.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/prompts/rollout_system.md +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/rollout.py +799 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/skills/initial.md +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/officeqa/tool_runtime.py +552 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/__init__.py +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/adapter.py +96 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/dataloader.py +42 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/evaluator.py +100 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/analyst_error.md +46 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/analyst_success.md +32 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/prompts/rollout_system.md +13 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/rollout.py +494 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/searchqa/skills/initial.md +3 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/__init__.py +5 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/adapter.py +159 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/codegen_agent.py +731 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/dataloader.py +37 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/evaluator.py +158 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/executor.py +67 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/analyst_error.md +46 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/analyst_success.md +32 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/codegen_system.md +1 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/critical_rules.md +9 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/prompts/react_system.md +21 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/react_agent.py +395 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/reflect.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/rollout.py +979 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/spreadsheetbench/skills/initial.md +56 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/evaluation/__init__.py +13 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/evaluation/gate.py +148 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/__init__.py +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/aggregate.py +253 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/gradient/reflect.py +635 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/__init__.py +514 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/azure_openai.py +915 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/backend_config.py +185 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/claude_backend.py +371 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/codex_backend.py +666 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/codex_harness.py +1057 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/common.py +229 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/minimax_backend.py +277 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/qwen_backend.py +456 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/model/router.py +236 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/__init__.py +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/appendix.py +156 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/clip.py +109 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/lr_autonomous.py +108 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/meta_skill.py +79 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/rewrite.py +59 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/scheduler.py +127 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/select.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/skill.py +201 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/skill_aware.py +206 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/slow_update.py +396 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/optimizer/update_modes.py +135 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/__init__.py +63 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error.md +41 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error_full_rewrite.md +32 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_error_rewrite.md +44 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success.md +36 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success_full_rewrite.md +30 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/analyst_success_rewrite.md +33 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/lr_autonomous.md +20 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure.md +30 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure_full_rewrite.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_failure_rewrite.md +26 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final.md +33 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final_full_rewrite.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_final_rewrite.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success_full_rewrite.md +28 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/merge_success_rewrite.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/meta_skill.md +40 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/ranking.md +20 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/ranking_rewrite.md +15 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/rewrite_skill.md +25 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/prompts/slow_update.md +60 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/scheduler/__init__.py +8 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/types.py +306 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/__init__.py +4 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/json_utils.py +172 -0
- package/template/skills/skillopt-sleep/scripts/framework/skillopt/utils/scoring.py +28 -0
- package/template/skills/ponytail/SKILL.md +0 -133
- package/template/skills/ponytail/scripts/hooks/claude-codex-hooks.json +0 -44
- package/template/skills/ponytail/scripts/hooks/copilot-hooks.json +0 -21
- package/template/skills/ponytail/scripts/hooks/ponytail-activate.js +0 -91
- package/template/skills/ponytail/scripts/hooks/ponytail-config.js +0 -122
- package/template/skills/ponytail/scripts/hooks/ponytail-instructions.js +0 -94
- package/template/skills/ponytail/scripts/hooks/ponytail-mode-tracker.js +0 -55
- package/template/skills/ponytail/scripts/hooks/ponytail-runtime.js +0 -68
- package/template/skills/ponytail/scripts/hooks/ponytail-statusline.ps1 +0 -21
- package/template/skills/ponytail/scripts/hooks/ponytail-statusline.sh +0 -12
- package/template/skills/ponytail/scripts/hooks/ponytail-subagent.js +0 -22
- package/template/skills/ponytail/scripts/mcp/README.md +0 -46
- package/template/skills/ponytail/scripts/mcp/index.js +0 -48
- package/template/skills/ponytail/scripts/mcp/instructions.js +0 -26
- package/template/skills/ponytail/scripts/mcp/package.json +0 -13
- package/template/skills/ponytail/scripts/mcp/test/instructions.test.js +0 -22
- package/template/skills/ponytail-audit/SKILL.md +0 -41
- package/template/skills/ponytail-debt/SKILL.md +0 -44
- package/template/skills/ponytail-gain/SKILL.md +0 -50
- package/template/skills/ponytail-help/SKILL.md +0 -69
- package/template/skills/ponytail-review/SKILL.md +0 -57
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
"""ALFWorld rollout module for ReflACT.
|
|
2
|
+
|
|
3
|
+
Provides:
|
|
4
|
+
- build_alfworld_env(): build ALFWorld environment (wraps vendored SkillRL env)
|
|
5
|
+
- run_alfworld_batch(): run a batch of ALFWorld episodes in parallel
|
|
6
|
+
- TASKS: list of ALFWorld task types
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import concurrent.futures
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
|
|
15
|
+
from skillopt.model import chat_target
|
|
16
|
+
|
|
17
|
+
# ── Constants ─────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
TASKS = [
|
|
20
|
+
"pick_and_place",
|
|
21
|
+
"pick_two_obj_and_place",
|
|
22
|
+
"look_at_obj_in_light",
|
|
23
|
+
"pick_heat_then_place_in_recep",
|
|
24
|
+
"pick_cool_then_place_in_recep",
|
|
25
|
+
"pick_clean_then_place_in_recep",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _get_task_type(gamefile: str) -> str:
|
|
32
|
+
for task in TASKS:
|
|
33
|
+
if task in gamefile:
|
|
34
|
+
return task
|
|
35
|
+
return "other"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _extract_action(model_response: str) -> str | None:
|
|
39
|
+
match = re.search(r"<action>(.*?)</action>", model_response, re.DOTALL)
|
|
40
|
+
return match.group(1).strip() if match else None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _extract_think(model_response: str) -> str | None:
|
|
44
|
+
match = re.search(r"<think>(.*?)</think>", model_response, re.DOTALL)
|
|
45
|
+
return match.group(1).strip() if match else None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _build_skill_prompt(skill_content: str) -> str:
|
|
49
|
+
"""Build the skill section to inject into the agent's system prompt."""
|
|
50
|
+
if not skill_content or not skill_content.strip():
|
|
51
|
+
return ""
|
|
52
|
+
return (
|
|
53
|
+
"\n\n## Skill Knowledge\n"
|
|
54
|
+
"Below is a skill document with learned strategies. "
|
|
55
|
+
"Use these guidelines to inform your decisions:\n\n"
|
|
56
|
+
f"{skill_content}\n"
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _append_diagnostic_instruction(prompt: str, diagnostic_instruction: str) -> str:
|
|
61
|
+
if not diagnostic_instruction or not diagnostic_instruction.strip():
|
|
62
|
+
return prompt
|
|
63
|
+
return f"{prompt}\n\n## Training Readout\n{diagnostic_instruction.strip()}\n"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _resolve_alfworld_gamefile(gamefile: str) -> str:
|
|
67
|
+
path = os.path.expanduser(os.path.expandvars(str(gamefile)))
|
|
68
|
+
if os.path.isabs(path):
|
|
69
|
+
return path
|
|
70
|
+
|
|
71
|
+
data_root = os.environ.get("ALFWORLD_DATA", "").strip()
|
|
72
|
+
if not data_root:
|
|
73
|
+
return path
|
|
74
|
+
|
|
75
|
+
root = os.path.expanduser(os.path.expandvars(data_root))
|
|
76
|
+
return os.path.abspath(os.path.join(root, path))
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _resolve_alfworld_gamefiles(gamefiles: list[str] | None) -> list[str] | None:
|
|
80
|
+
if gamefiles is None:
|
|
81
|
+
return None
|
|
82
|
+
return [_resolve_alfworld_gamefile(gamefile) for gamefile in gamefiles]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# ── Environment builder ──────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def build_alfworld_env(
|
|
89
|
+
env_num: int,
|
|
90
|
+
eval_dataset: str = "eval_out_of_distribution",
|
|
91
|
+
seed: int = 42,
|
|
92
|
+
is_train: bool = False,
|
|
93
|
+
specific_gamefiles: list[str] | None = None,
|
|
94
|
+
):
|
|
95
|
+
"""Build ALFWorld environment manager.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
env_num: number of parallel environments
|
|
99
|
+
eval_dataset: 'eval_in_distribution' or 'eval_out_of_distribution' or train
|
|
100
|
+
seed: random seed
|
|
101
|
+
is_train: whether to use training set
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
env_manager: AlfWorldEnvironmentManager instance
|
|
105
|
+
"""
|
|
106
|
+
from functools import partial
|
|
107
|
+
|
|
108
|
+
from omegaconf import OmegaConf
|
|
109
|
+
|
|
110
|
+
from skillopt.envs.alfworld.vendor.alfworld_envs import build_alfworld_envs
|
|
111
|
+
from skillopt.envs.alfworld.vendor.alfworld_projection import alfworld_projection
|
|
112
|
+
from skillopt.envs.alfworld.vendor.env_manager import AlfWorldEnvironmentManager
|
|
113
|
+
|
|
114
|
+
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
115
|
+
|
|
116
|
+
alf_config_path = os.path.join(HERE, "vendor", "config_tw.yaml")
|
|
117
|
+
env_kwargs = {"eval_dataset": eval_dataset}
|
|
118
|
+
resolved_gamefiles = _resolve_alfworld_gamefiles(specific_gamefiles)
|
|
119
|
+
|
|
120
|
+
envs = build_alfworld_envs(
|
|
121
|
+
alf_config_path,
|
|
122
|
+
seed=seed,
|
|
123
|
+
env_num=env_num,
|
|
124
|
+
group_n=1,
|
|
125
|
+
is_train=is_train,
|
|
126
|
+
env_kwargs=env_kwargs,
|
|
127
|
+
resources_per_worker=None,
|
|
128
|
+
gamefiles=resolved_gamefiles,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
config = OmegaConf.create(
|
|
132
|
+
{
|
|
133
|
+
"env": {
|
|
134
|
+
"history_length": 2,
|
|
135
|
+
"env_name": "alfworld/AlfredTWEnv",
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
projection_f = partial(alfworld_projection)
|
|
141
|
+
env_manager = AlfWorldEnvironmentManager(envs, projection_f, config)
|
|
142
|
+
return env_manager
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
# ── Batch rollout ─────────────────────────────────────────────────────────────
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def run_alfworld_batch(
|
|
149
|
+
env_manager,
|
|
150
|
+
skill_content: str,
|
|
151
|
+
max_steps: int = 50,
|
|
152
|
+
out_root: str = "",
|
|
153
|
+
max_api_workers: int = 8,
|
|
154
|
+
temperature: float = 0.4,
|
|
155
|
+
max_completion_tokens: int = 16384,
|
|
156
|
+
diagnostic_mode: bool = False,
|
|
157
|
+
diagnostic_instruction: str = "",
|
|
158
|
+
result_ids: list[str] | None = None,
|
|
159
|
+
) -> list[dict]:
|
|
160
|
+
"""Run a batch of ALFWorld episodes.
|
|
161
|
+
|
|
162
|
+
Returns a list of result dicts compatible with SkillOpt pipeline:
|
|
163
|
+
[
|
|
164
|
+
{
|
|
165
|
+
"id": "<env_idx>_<gamefile_hash>",
|
|
166
|
+
"hard": 0 or 1,
|
|
167
|
+
"soft": 0.0 or 1.0,
|
|
168
|
+
"n_turns": <int>,
|
|
169
|
+
"fail_reason": "<str>",
|
|
170
|
+
"agent_ok": True,
|
|
171
|
+
"task_type": "<str>",
|
|
172
|
+
"gamefile": "<str>",
|
|
173
|
+
"task_description": "<str>",
|
|
174
|
+
},
|
|
175
|
+
...
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
Also saves conversation.json per environment in out_root/predictions/<task_id>/
|
|
179
|
+
"""
|
|
180
|
+
skill_prompt = _build_skill_prompt(skill_content)
|
|
181
|
+
|
|
182
|
+
obs, infos = env_manager.reset({})
|
|
183
|
+
env_num = len(obs["text"])
|
|
184
|
+
env_dones = [False] * env_num
|
|
185
|
+
overall_success = [False] * env_num
|
|
186
|
+
|
|
187
|
+
# Build per-env metadata
|
|
188
|
+
env_meta: list[dict] = []
|
|
189
|
+
for i in range(env_num):
|
|
190
|
+
gamefile = infos[i].get("extra.gamefile", "") if isinstance(infos[i], dict) else ""
|
|
191
|
+
task_type = _get_task_type(gamefile)
|
|
192
|
+
# Extract task description from initial observation
|
|
193
|
+
task_desc = ""
|
|
194
|
+
anchor_text = obs["anchor"][i] if "anchor" in obs else ""
|
|
195
|
+
task_start = anchor_text.find("Your task is to: ")
|
|
196
|
+
if task_start != -1:
|
|
197
|
+
task_desc = anchor_text[task_start + len("Your task is to: "):].strip()
|
|
198
|
+
|
|
199
|
+
env_meta.append({
|
|
200
|
+
"gamefile": gamefile,
|
|
201
|
+
"task_type": task_type,
|
|
202
|
+
"task_description": task_desc,
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
# Per-env conversation records
|
|
206
|
+
conversations: list[list[dict]] = [[] for _ in range(env_num)]
|
|
207
|
+
|
|
208
|
+
for step_idx in range(max_steps):
|
|
209
|
+
if all(env_dones):
|
|
210
|
+
break
|
|
211
|
+
|
|
212
|
+
active_indices = [i for i in range(env_num) if not env_dones[i]]
|
|
213
|
+
|
|
214
|
+
# Build prompts with skill injection
|
|
215
|
+
prompts: dict[int, str] = {}
|
|
216
|
+
for i in active_indices:
|
|
217
|
+
prompt = obs["text"][i]
|
|
218
|
+
if skill_prompt:
|
|
219
|
+
# Inject skill before the action instruction
|
|
220
|
+
prompt = skill_prompt + "\n" + prompt
|
|
221
|
+
if diagnostic_mode and diagnostic_instruction.strip():
|
|
222
|
+
prompt = _append_diagnostic_instruction(prompt, diagnostic_instruction)
|
|
223
|
+
prompts[i] = prompt
|
|
224
|
+
|
|
225
|
+
# Call API in parallel
|
|
226
|
+
actions = ["None"] * env_num
|
|
227
|
+
|
|
228
|
+
def call_api(idx):
|
|
229
|
+
try:
|
|
230
|
+
response, _ = chat_target(
|
|
231
|
+
system="You are an expert agent operating in the ALFRED Embodied Environment.",
|
|
232
|
+
user=prompts[idx],
|
|
233
|
+
max_completion_tokens=max_completion_tokens,
|
|
234
|
+
retries=5,
|
|
235
|
+
stage="rollout",
|
|
236
|
+
timeout=None,
|
|
237
|
+
)
|
|
238
|
+
response = (response or "").strip()
|
|
239
|
+
if not response:
|
|
240
|
+
return idx, "<think>empty model response</think><action>look</action>"
|
|
241
|
+
if _extract_action(response) is None:
|
|
242
|
+
return idx, "<think>missing action tag</think><action>look</action>"
|
|
243
|
+
return idx, response
|
|
244
|
+
except Exception:
|
|
245
|
+
return idx, "<think>error</think><action>look</action>"
|
|
246
|
+
|
|
247
|
+
executor = concurrent.futures.ThreadPoolExecutor(max_workers=max_api_workers)
|
|
248
|
+
try:
|
|
249
|
+
futures = {executor.submit(call_api, i): i for i in active_indices}
|
|
250
|
+
pending_futs = set(futures)
|
|
251
|
+
while pending_futs:
|
|
252
|
+
done, _ = concurrent.futures.wait(
|
|
253
|
+
pending_futs,
|
|
254
|
+
timeout=5,
|
|
255
|
+
return_when=concurrent.futures.FIRST_COMPLETED,
|
|
256
|
+
)
|
|
257
|
+
for future in done:
|
|
258
|
+
pending_futs.remove(future)
|
|
259
|
+
try:
|
|
260
|
+
idx, response = future.result()
|
|
261
|
+
except Exception: # noqa: BLE001
|
|
262
|
+
idx = futures[future]
|
|
263
|
+
response = "<think>error</think><action>look</action>"
|
|
264
|
+
actions[idx] = response
|
|
265
|
+
finally:
|
|
266
|
+
executor.shutdown(wait=False, cancel_futures=True)
|
|
267
|
+
|
|
268
|
+
# Save model responses before stepping
|
|
269
|
+
model_responses = {i: actions[i] for i in active_indices}
|
|
270
|
+
|
|
271
|
+
# Step environment
|
|
272
|
+
obs, rewards, dones, infos = env_manager.step(actions)
|
|
273
|
+
|
|
274
|
+
# Record trajectory
|
|
275
|
+
for i in active_indices:
|
|
276
|
+
step_record = {
|
|
277
|
+
"step": step_idx,
|
|
278
|
+
"action": _extract_action(model_responses[i]),
|
|
279
|
+
"reasoning": _extract_think(model_responses[i]),
|
|
280
|
+
"model_response": model_responses[i],
|
|
281
|
+
"env_feedback": obs["anchor"][i] if "anchor" in obs else "",
|
|
282
|
+
"reward": float(rewards[i]),
|
|
283
|
+
"done": bool(dones[i]),
|
|
284
|
+
}
|
|
285
|
+
conversations[i].append(step_record)
|
|
286
|
+
|
|
287
|
+
# Update done status
|
|
288
|
+
for i in range(env_num):
|
|
289
|
+
if env_dones[i]:
|
|
290
|
+
continue
|
|
291
|
+
if dones[i]:
|
|
292
|
+
env_dones[i] = True
|
|
293
|
+
won = bool(infos[i].get("won", False))
|
|
294
|
+
overall_success[i] = won
|
|
295
|
+
|
|
296
|
+
# Build results and save conversations
|
|
297
|
+
results: list[dict] = []
|
|
298
|
+
pred_dir = os.path.join(out_root, "predictions") if out_root else ""
|
|
299
|
+
|
|
300
|
+
for i in range(env_num):
|
|
301
|
+
gamefile = env_meta[i]["gamefile"]
|
|
302
|
+
task_type = env_meta[i]["task_type"]
|
|
303
|
+
task_desc = env_meta[i]["task_description"]
|
|
304
|
+
n_turns = len(conversations[i])
|
|
305
|
+
won = overall_success[i]
|
|
306
|
+
|
|
307
|
+
# Generate stable task ID from env index and gamefile
|
|
308
|
+
task_id = str(result_ids[i]) if result_ids and i < len(result_ids) else f"env_{i:03d}"
|
|
309
|
+
|
|
310
|
+
fail_reason = ""
|
|
311
|
+
if not won:
|
|
312
|
+
if not env_dones[i]:
|
|
313
|
+
fail_reason = f"Timeout after {max_steps} steps"
|
|
314
|
+
else:
|
|
315
|
+
fail_reason = "Episode ended without completing the task"
|
|
316
|
+
|
|
317
|
+
result = {
|
|
318
|
+
"id": task_id,
|
|
319
|
+
"hard": 1 if won else 0,
|
|
320
|
+
"soft": 1.0 if won else 0.0,
|
|
321
|
+
"n_turns": n_turns,
|
|
322
|
+
"fail_reason": fail_reason,
|
|
323
|
+
"agent_ok": True, # ALFWorld agent always runs OK (no crash)
|
|
324
|
+
"task_type": task_type,
|
|
325
|
+
"gamefile": gamefile,
|
|
326
|
+
"task_description": task_desc,
|
|
327
|
+
"instruction_type": task_type, # for compatibility with v2 pipeline
|
|
328
|
+
}
|
|
329
|
+
results.append(result)
|
|
330
|
+
|
|
331
|
+
# Save conversation
|
|
332
|
+
if pred_dir:
|
|
333
|
+
conv_dir = os.path.join(pred_dir, task_id)
|
|
334
|
+
os.makedirs(conv_dir, exist_ok=True)
|
|
335
|
+
with open(os.path.join(conv_dir, "conversation.json"), "w") as f:
|
|
336
|
+
json.dump(conversations[i], f, ensure_ascii=False, indent=2)
|
|
337
|
+
|
|
338
|
+
return results
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
# ── Item loading (for compatibility with split_three_way) ────────────────────
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def load_alfworld_items(
|
|
345
|
+
eval_dataset: str,
|
|
346
|
+
env_num: int,
|
|
347
|
+
seed: int = 42,
|
|
348
|
+
is_train: bool = False,
|
|
349
|
+
) -> list[dict]:
|
|
350
|
+
"""Create pseudo-item dicts for ALFWorld environments.
|
|
351
|
+
|
|
352
|
+
Since ALFWorld doesn't have a static JSON dataset like SpreadsheetBench,
|
|
353
|
+
we create lightweight item dicts that carry enough metadata for the pipeline.
|
|
354
|
+
The actual environment is built dynamically.
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
List of dicts with "id" keys, one per environment slot.
|
|
358
|
+
"""
|
|
359
|
+
items = []
|
|
360
|
+
for i in range(env_num):
|
|
361
|
+
items.append({
|
|
362
|
+
"id": f"env_{i:03d}",
|
|
363
|
+
"eval_dataset": eval_dataset,
|
|
364
|
+
"env_index": i,
|
|
365
|
+
})
|
|
366
|
+
return items
|
package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/skills/initial.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# ALFWorld Embodied Agent Skill
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This skill guides agents operating in the ALFWorld text-based embodied environment.
|
|
5
|
+
The agent must complete household tasks by navigating rooms, interacting with objects,
|
|
6
|
+
and using appliances. Actions must be chosen from the admissible action list provided
|
|
7
|
+
at each step.
|
|
8
|
+
|
|
9
|
+
**Output format**: Always output `<think>...</think>` for reasoning, then `<action>...</action>` for the chosen action.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Task Types
|
|
14
|
+
|
|
15
|
+
| Type | Goal | Key Steps |
|
|
16
|
+
|------|------|-----------|
|
|
17
|
+
| Pick & Place | Put object X in/on receptacle Y | Find X -> take X -> go to Y -> put X in/on Y |
|
|
18
|
+
| Pick Two & Place | Put two instances of X in/on Y | Find X1 -> take -> place -> find X2 -> take -> place |
|
|
19
|
+
| Examine in Light | Examine object X under desklamp | Find X -> take X -> find desklamp -> use desklamp |
|
|
20
|
+
| Clean & Place | Clean object X and put in/on Y | Find X -> take X -> go to sink -> clean X -> go to Y -> put X |
|
|
21
|
+
| Heat & Place | Heat object X and put in/on Y | Find X -> take X -> go to microwave -> heat X -> go to Y -> put X |
|
|
22
|
+
| Cool & Place | Cool object X and put in/on Y | Find X -> take X -> go to fridge -> cool X -> go to Y -> put X |
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## General Principles
|
|
27
|
+
|
|
28
|
+
1. **Decompose the task**: Parse the goal into ordered sub-goals (locate, acquire, transform, deliver). Complete each before moving to the next.
|
|
29
|
+
2. **Systematic exploration**: Search each surface and container exactly once before revisiting. Open closed containers (drawers, cabinets, fridge) before judging them empty.
|
|
30
|
+
3. **Grab immediately**: When a required object is visible and reachable, take it right away before moving elsewhere.
|
|
31
|
+
4. **Transform before placing**: If the task requires cleaning, heating, or cooling, perform the state change at the appropriate appliance before heading to the final destination.
|
|
32
|
+
5. **Direct delivery**: Once holding the transformed (or untransformed) goal object, navigate straight to the target receptacle and place it.
|
|
33
|
+
6. **Track progress**: Maintain an internal count of how many objects still need to be found and placed. Only stop searching when the count reaches zero.
|
|
34
|
+
7. **Avoid loops**: Never repeat the same action more than twice in a row. If stuck, move to a different unexplored location.
|
|
35
|
+
8. **Only choose admissible actions**: Always pick an action from the admissible action list. Do not invent actions.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Common Mistakes to Avoid
|
|
40
|
+
|
|
41
|
+
- **Revisiting searched locations**: Keep track of which surfaces/containers have been checked; do not re-examine them.
|
|
42
|
+
- **Ignoring visible objects**: If the target object appears in the observation, pick it up immediately.
|
|
43
|
+
- **Skipping state changes**: Do not place an object at the destination without first cleaning/heating/cooling it when required.
|
|
44
|
+
- **Premature termination**: Do not stop the episode until all goal conditions are verified as met.
|
|
45
|
+
- **Action loops**: Repeatedly toggling or examining the same object wastes steps. Move on to new locations instead.
|
package/template/skills/skillopt-sleep/scripts/framework/skillopt/envs/alfworld/vendor/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Vendored ALFWorld environment runtime.
|
|
2
|
+
|
|
3
|
+
Minimal subset of SkillRL's agent_system package needed to run
|
|
4
|
+
ALFWorld environments with ReflACT. Original source:
|
|
5
|
+
https://github.com/NTU-LANTERN/SkillRL (Apache-2.0 License)
|
|
6
|
+
"""
|
|
7
|
+
from .alfworld_envs import AlfworldEnvs, build_alfworld_envs
|
|
8
|
+
from .alfworld_projection import alfworld_projection
|
|
9
|
+
from .env_manager import AlfWorldEnvironmentManager
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# Vendored from SkillRL (Apache-2.0 License)
|
|
2
|
+
# Original: agent_system/environments/env_package/alfworld/envs.py
|
|
3
|
+
# Modified: imports use pip-installed alfworld package instead of vendored copy.
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import multiprocessing as mp
|
|
7
|
+
import traceback
|
|
8
|
+
import yaml
|
|
9
|
+
import gymnasium as gym
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
from alfworld.agents.environment import get_environment
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_config_file(path):
|
|
16
|
+
assert os.path.exists(path), f"Invalid config file: {path}"
|
|
17
|
+
with open(path) as reader:
|
|
18
|
+
config = yaml.safe_load(reader)
|
|
19
|
+
return config
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def compute_reward(info, multi_modal=False):
|
|
23
|
+
if multi_modal:
|
|
24
|
+
reward = 10.0 * float(info['won']) + float(info['goal_condition_success_rate'])
|
|
25
|
+
else:
|
|
26
|
+
reward = 10.0 * float(info['won'])
|
|
27
|
+
return reward
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class AlfworldWorker:
|
|
31
|
+
"""Stateful worker that holds one ALFWorld sub-environment."""
|
|
32
|
+
|
|
33
|
+
def __init__(self, config, seed, base_env, gamefile=None):
|
|
34
|
+
if gamefile:
|
|
35
|
+
base_env.game_files = [gamefile]
|
|
36
|
+
if hasattr(base_env, "num_games"):
|
|
37
|
+
base_env.num_games = 1
|
|
38
|
+
self.env = base_env.init_env(batch_size=1)
|
|
39
|
+
self.env.seed(seed)
|
|
40
|
+
|
|
41
|
+
def step(self, action):
|
|
42
|
+
actions = [action]
|
|
43
|
+
obs, scores, dones, infos = self.env.step(actions)
|
|
44
|
+
infos['observation_text'] = obs
|
|
45
|
+
return obs, scores, dones, infos
|
|
46
|
+
|
|
47
|
+
def reset(self):
|
|
48
|
+
obs, infos = self.env.reset()
|
|
49
|
+
infos['observation_text'] = obs
|
|
50
|
+
return obs, infos
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _worker_loop(cmd_q, result_q, config, seed, is_train, eval_dataset, gamefile):
|
|
54
|
+
"""Run one ALFWorld environment in a child process."""
|
|
55
|
+
try:
|
|
56
|
+
env_type = config['env']['type']
|
|
57
|
+
base_env = get_environment(env_type)(
|
|
58
|
+
config,
|
|
59
|
+
train_eval='train' if is_train else eval_dataset,
|
|
60
|
+
)
|
|
61
|
+
worker = AlfworldWorker(config, seed, base_env, gamefile)
|
|
62
|
+
result_q.put((True, "ready"))
|
|
63
|
+
except BaseException:
|
|
64
|
+
result_q.put((False, traceback.format_exc()))
|
|
65
|
+
return
|
|
66
|
+
|
|
67
|
+
while True:
|
|
68
|
+
cmd, payload = cmd_q.get()
|
|
69
|
+
if cmd == "close":
|
|
70
|
+
result_q.put((True, None))
|
|
71
|
+
return
|
|
72
|
+
try:
|
|
73
|
+
if cmd == "reset":
|
|
74
|
+
result = worker.reset()
|
|
75
|
+
elif cmd == "step":
|
|
76
|
+
result = worker.step(payload)
|
|
77
|
+
else:
|
|
78
|
+
raise ValueError(f"Unknown ALFWorld worker command: {cmd}")
|
|
79
|
+
result_q.put((True, result))
|
|
80
|
+
except BaseException:
|
|
81
|
+
result_q.put((False, traceback.format_exc()))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class _ProcessWorker:
|
|
85
|
+
"""Small stdlib actor wrapper for one environment process."""
|
|
86
|
+
|
|
87
|
+
def __init__(self, ctx, config, seed, is_train, eval_dataset, gamefile=None):
|
|
88
|
+
self.cmd_q = ctx.Queue(maxsize=1)
|
|
89
|
+
self.result_q = ctx.Queue(maxsize=1)
|
|
90
|
+
self.process = ctx.Process(
|
|
91
|
+
target=_worker_loop,
|
|
92
|
+
args=(self.cmd_q, self.result_q, config, seed, is_train, eval_dataset, gamefile),
|
|
93
|
+
)
|
|
94
|
+
self.process.start()
|
|
95
|
+
ok, payload = self.result_q.get()
|
|
96
|
+
if not ok:
|
|
97
|
+
self.close(kill=True)
|
|
98
|
+
raise RuntimeError(f"Failed to start ALFWorld worker:\n{payload}")
|
|
99
|
+
|
|
100
|
+
def send(self, cmd, payload=None):
|
|
101
|
+
self.cmd_q.put((cmd, payload))
|
|
102
|
+
|
|
103
|
+
def recv(self):
|
|
104
|
+
ok, payload = self.result_q.get()
|
|
105
|
+
if not ok:
|
|
106
|
+
raise RuntimeError(f"ALFWorld worker failed:\n{payload}")
|
|
107
|
+
return payload
|
|
108
|
+
|
|
109
|
+
def close(self, kill=False):
|
|
110
|
+
if self.process.is_alive() and not kill:
|
|
111
|
+
try:
|
|
112
|
+
self.send("close")
|
|
113
|
+
self.recv()
|
|
114
|
+
except Exception:
|
|
115
|
+
kill = True
|
|
116
|
+
if kill and self.process.is_alive():
|
|
117
|
+
self.process.terminate()
|
|
118
|
+
self.process.join(timeout=5)
|
|
119
|
+
if self.process.is_alive():
|
|
120
|
+
self.process.kill()
|
|
121
|
+
self.process.join(timeout=1)
|
|
122
|
+
self.cmd_q.close()
|
|
123
|
+
self.result_q.close()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class AlfworldEnvs(gym.Env):
|
|
127
|
+
"""Vectorized ALFWorld environment using local process workers."""
|
|
128
|
+
|
|
129
|
+
def __init__(self, alf_config_path, seed, env_num, group_n,
|
|
130
|
+
resources_per_worker, is_train=True, env_kwargs=None, gamefiles=None):
|
|
131
|
+
super().__init__()
|
|
132
|
+
if env_kwargs is None:
|
|
133
|
+
env_kwargs = {}
|
|
134
|
+
|
|
135
|
+
eval_dataset = env_kwargs.get('eval_dataset', 'eval_in_distribution')
|
|
136
|
+
config = load_config_file(alf_config_path)
|
|
137
|
+
env_type = config['env']['type']
|
|
138
|
+
self.multi_modal = (env_type == 'AlfredThorEnv')
|
|
139
|
+
self.num_processes = env_num * group_n
|
|
140
|
+
self.group_n = group_n
|
|
141
|
+
self.gamefiles = list(gamefiles or [])
|
|
142
|
+
if self.gamefiles and len(self.gamefiles) != self.num_processes:
|
|
143
|
+
raise ValueError(
|
|
144
|
+
f"Expected {self.num_processes} gamefiles, got {len(self.gamefiles)}"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
start_method = os.environ.get("ALFWORLD_WORKER_START_METHOD") or None
|
|
148
|
+
ctx = mp.get_context(start_method) if start_method else mp.get_context()
|
|
149
|
+
self.workers = []
|
|
150
|
+
for i in range(self.num_processes):
|
|
151
|
+
worker_gamefile = self.gamefiles[i] if self.gamefiles else None
|
|
152
|
+
worker = _ProcessWorker(
|
|
153
|
+
ctx,
|
|
154
|
+
config,
|
|
155
|
+
seed + (i // self.group_n),
|
|
156
|
+
is_train,
|
|
157
|
+
eval_dataset,
|
|
158
|
+
worker_gamefile,
|
|
159
|
+
)
|
|
160
|
+
self.workers.append(worker)
|
|
161
|
+
|
|
162
|
+
self.prev_admissible_commands = [None for _ in range(self.num_processes)]
|
|
163
|
+
|
|
164
|
+
def step(self, actions):
|
|
165
|
+
assert len(actions) == self.num_processes
|
|
166
|
+
|
|
167
|
+
for i, worker in enumerate(self.workers):
|
|
168
|
+
worker.send("step", actions[i])
|
|
169
|
+
results = [worker.recv() for worker in self.workers]
|
|
170
|
+
|
|
171
|
+
text_obs_list = []
|
|
172
|
+
rewards_list = []
|
|
173
|
+
dones_list = []
|
|
174
|
+
info_list = []
|
|
175
|
+
|
|
176
|
+
for i, (obs, scores, dones, info) in enumerate(results):
|
|
177
|
+
for k in info.keys():
|
|
178
|
+
info[k] = info[k][0]
|
|
179
|
+
text_obs_list.append(obs[0])
|
|
180
|
+
dones_list.append(dones[0])
|
|
181
|
+
info_list.append(info)
|
|
182
|
+
self.prev_admissible_commands[i] = info['admissible_commands']
|
|
183
|
+
rewards_list.append(compute_reward(info, self.multi_modal))
|
|
184
|
+
|
|
185
|
+
image_obs_list = None
|
|
186
|
+
return text_obs_list, image_obs_list, rewards_list, dones_list, info_list
|
|
187
|
+
|
|
188
|
+
def reset(self):
|
|
189
|
+
for worker in self.workers:
|
|
190
|
+
worker.send("reset")
|
|
191
|
+
results = [worker.recv() for worker in self.workers]
|
|
192
|
+
|
|
193
|
+
text_obs_list = []
|
|
194
|
+
info_list = []
|
|
195
|
+
|
|
196
|
+
for i, (obs, info) in enumerate(results):
|
|
197
|
+
for k in info.keys():
|
|
198
|
+
info[k] = info[k][0]
|
|
199
|
+
text_obs_list.append(obs[0])
|
|
200
|
+
self.prev_admissible_commands[i] = info['admissible_commands']
|
|
201
|
+
info_list.append(info)
|
|
202
|
+
|
|
203
|
+
image_obs_list = None
|
|
204
|
+
return text_obs_list, image_obs_list, info_list
|
|
205
|
+
|
|
206
|
+
@property
|
|
207
|
+
def get_admissible_commands(self):
|
|
208
|
+
return self.prev_admissible_commands
|
|
209
|
+
|
|
210
|
+
def close(self):
|
|
211
|
+
for worker in self.workers:
|
|
212
|
+
worker.close()
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def build_alfworld_envs(alf_config_path, seed, env_num, group_n,
|
|
216
|
+
resources_per_worker, is_train=True, env_kwargs=None, gamefiles=None):
|
|
217
|
+
"""Build vectorized ALFWorld environments."""
|
|
218
|
+
return AlfworldEnvs(
|
|
219
|
+
alf_config_path, seed, env_num, group_n,
|
|
220
|
+
resources_per_worker, is_train, env_kwargs, gamefiles,
|
|
221
|
+
)
|