Skip to content
This repository has been archived by the owner on Jan 27, 2023. It is now read-only.

Commit

Permalink
Add override option to CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
kngwyu committed Jul 8, 2019
1 parent 8a3a3e0 commit 1a34cdc
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 27 deletions.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,30 @@ E.g., if you want to use two hosts(localhost and anotherhost) and run `ppo_atari
horovodrun -np 2 -H localhost:1,anotherhost:1 pipenv run python examples/ppo_atari.py train
```

## Override configuration from CLI
Currently, Rainy provides an easy-to-use CLI via [click](https://palletsprojects.com/p/click/).
You can view its usages by, say,
```bash
pipenv run python examples/a2c_cart_pole.py --help
```

This CLI has a simple data-driven interface.
I.e., once you fill a config object, then all commands(train, eval, retarain, and etc.) work.
So you can start experiments easily without copying and pasting, say, argument parser codes.

However, it has a limitation that you cannot add new options and arguments to each subcommands.

So Rainy-CLI provides an option named `override`, which executes the given string as a Python code
with the config object set as `config`.

Example usage:
```bash
pipenv run python examples/a2c_cart_pole.py --override='config.grad_clip=0.5; config.nsteps=10' train
```

If this feature still doesn't satisfy your requirement,
then unfortunately you need to write your own CLI :cold_sweat:.

## Implementation Status

|**Algorithm** |**Multi Worker(Sync)**|**Recurrent** |**Discrete Action** |**Continuous Action**|**MPI** |
Expand Down
65 changes: 38 additions & 27 deletions rainy/utils/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,26 @@


@click.group()
@click.option('--gpu', required=False, type=int)
@click.option('--seed', type=int, default=None)
@click.option('--gpu', required=False, type=int, help='How many gpus you allow Rainy to use')
@click.option('--seed', type=int, default=None, help='Random seed set before training')
@click.option('--override', type=str, default='', help='Override string(See README for detail)')
@click.pass_context
def rainy_cli(ctx: dict, gpu: Tuple[int], seed: Optional[int]) -> None:
def rainy_cli(ctx: dict, gpu: Tuple[int], seed: Optional[int], override: str) -> None:
ctx.obj['gpu'] = gpu
ctx.obj['config'].seed = seed
if len(override) > 0:
import builtins
try:
exec(override, builtins.__dict__, {'config': ctx.obj['config']})
except Exception as e:
print('!!! Your override string \'{}\' contains an error !!!'.format(override))
raise e


@rainy_cli.command()
@rainy_cli.command(help='Train agents')
@click.pass_context
@click.option('--comment', type=str, default=None)
@click.option('--prefix', type=str, default='')
@click.option('--comment', type=str, default=None, help='Comment wrote to fingerprint.txt')
@click.option('--prefix', type=str, default='', help='Prefix of the log directory')
def train(ctx: dict, comment: Optional[str], prefix: str) -> None:
c = ctx.obj['config']
scr = ctx.obj['script_path']
Expand All @@ -33,11 +41,12 @@ def train(ctx: dict, comment: Optional[str], prefix: str) -> None:
print("random play: {}, trained: {}".format(ag.random_episode(), ag.eval_episode()))


@rainy_cli.command()
@click.option('--save', is_flag=True)
@click.option('--render', is_flag=True)
@click.option('--replay', is_flag=True)
@click.option('--action-file', type=str, default='random-actions.json')
@rainy_cli.command(help='Run the random agent and show its result')
@click.option('--save', is_flag=True, help='Save actions')
@click.option('--render', is_flag=True, help='Render the agent')
@click.option('--replay', is_flag=True, help='Show replay(works with special environments)')
@click.option('--action-file', type=str,
default='best-actions.json', help='Name of the action file')
@click.pass_context
def random(ctx: dict, save: bool, render: bool, replay: bool, action_file: str) -> None:
c = ctx.obj['config']
Expand All @@ -46,11 +55,12 @@ def random(ctx: dict, save: bool, render: bool, replay: bool, action_file: str)
run.random_agent(ag, render=render, replay=replay, action_file=action_file)


@rainy_cli.command()
@rainy_cli.command(help='Load a save file and restart training')
@click.pass_context
@click.argument('logdir')
@click.option('--model', type=str, default=run.SAVE_FILE_DEFAULT)
@click.option('--additional-steps', type=int, default=100)
@click.option('--model', type=str, default=run.SAVE_FILE_DEFAULT, help='Name of the save file')
@click.option('--additional-steps', type=int,
default=100, help='The number of additional training steps')
def retrain(ctx: dict, logdir: str, model: str, additional_steps: int) -> None:
c = ctx.obj['config']
log = c.logger.retrive(logdir)
Expand All @@ -60,12 +70,13 @@ def retrain(ctx: dict, logdir: str, model: str, additional_steps: int) -> None:
print("random play: {}, trained: {}".format(ag.random_episode(), ag.eval_episode()))


@rainy_cli.command()
@click.argument('logdir', required=True, type=str)
@click.option('--model', type=str, default=run.SAVE_FILE_DEFAULT)
@click.option('--render', is_flag=True)
@click.option('--replay', is_flag=True)
@click.option('--action-file', type=str, default='best-actions.json')
@rainy_cli.command(help='Load a save file and evaluate the agent')
@click.argument('logdir')
@click.option('--model', type=str, default=run.SAVE_FILE_DEFAULT, help='Name of the save file')
@click.option('--render', is_flag=True, help='Render the agent')
@click.option('--replay', is_flag=True, help='Show replay(works with special environments)')
@click.option('--action-file', type=str,
default='best-actions.json', help='Name of the action file')
@click.pass_context
def eval(ctx: dict, logdir: str, model: str, render: bool, replay: bool, action_file: str) -> None:
c = ctx.obj['config']
Expand All @@ -80,19 +91,19 @@ def eval(ctx: dict, logdir: str, model: str, render: bool, replay: bool, action_
)


@rainy_cli.command()
@click.option('--log-dir', type=str)
@click.option('--vi-mode', is_flag=True)
@rainy_cli.command(help='Open an ipython shell with rainy imported')
@click.option('--logdir', type=str, help='Name of the directly where the log file')
@click.option('--vi-mode', is_flag=True, help='Open ipython shell with vi-mode enabled')
@click.pass_context
def ipython(ctx: dict, log_dir: Optional[str], vi_mode: bool) -> None:
def ipython(ctx: dict, logdir: Optional[str], vi_mode: bool) -> None:
config, make_agent = ctx.obj['config'], ctx.obj['make_agent'] # noqa
if log_dir is not None:
log = ExperimentLog(log_dir) # noqa
if logdir is not None:
log = ExperimentLog(logdir) # noqa
else:
open_log = ExperimentLog # noqa
try:
from ptpython.ipython import embed
del ctx, log_dir
del ctx, logdir
import rainy # noqa
embed(vi_mode=vi_mode)
except ImportError:
Expand Down

0 comments on commit 1a34cdc

Please sign in to comment.