diff --git a/binding-hs/README.md b/binding-hs/README.md index 5068ec6..18e0e33 100644 --- a/binding-hs/README.md +++ b/binding-hs/README.md @@ -5,6 +5,7 @@ stack setup stack build stack exec example +stack haddock ``` ## Checklist diff --git a/binding-hs/src/OpenAI/Gym.hs b/binding-hs/src/OpenAI/Gym.hs index c7a2ef3..4e4823a 100644 --- a/binding-hs/src/OpenAI/Gym.hs +++ b/binding-hs/src/OpenAI/Gym.hs @@ -1,8 +1,8 @@ --- * reexports module OpenAI.Gym ( module X ) where import OpenAI.Gym.API as X import OpenAI.Gym.Data as X +-- * reexports diff --git a/binding-hs/src/OpenAI/Gym/API.hs b/binding-hs/src/OpenAI/Gym/API.hs index 03e07b8..f237643 100644 --- a/binding-hs/src/OpenAI/Gym/API.hs +++ b/binding-hs/src/OpenAI/Gym/API.hs @@ -12,6 +12,7 @@ module OpenAI.Gym.API where import OpenAI.Gym.Prelude import OpenAI.Gym.Data +-- | a description of the Gym HTTP API type GymAPI = "v1" :> ( "envs" :> ( ReqBody '[JSON] GymEnv :> Post '[JSON] InstID :<|> Get '[JSON] Environment @@ -28,22 +29,36 @@ type GymAPI :<|> "shutdown" :> Post '[HTML] ()) +-- | a proxy representing the Gym API gymAPI :: Proxy GymAPI gymAPI = Proxy +-- | Create an instance of the specified environment envCreate :: GymEnv -> ClientM InstID +-- | List all environments running on the server envListAll :: ClientM Environment +-- | Reset the state of the environment and return an initial observation. envReset :: InstID -> ClientM Observation +-- | Step though an environment using an action. envStep :: InstID -> Step -> ClientM Outcome +-- | Get information (name and dimensions/bounds) of the env's `action_space` envActionSpaceInfo :: InstID -> ClientM Info +-- | Get a sample from the env's action_space envActionSpaceSample :: InstID -> ClientM Action +-- | Assess that value is a member of the env's action_space envActionSpaceContains :: InstID -> Int -> ClientM Object +-- | Get information (name and dimensions/bounds) of the env's `observation_space` envObservationSpaceInfo :: InstID -> ClientM Info +-- | Start monitoring. envMonitorStart :: InstID -> Monitor -> ClientM () +-- | Flush all monitor data to disk. envMonitorClose :: InstID -> ClientM () +-- | Manually close an environment envClose :: InstID -> ClientM () +-- | Upload the results of training (as automatically recorded by your env's monitor) to OpenAI Gym. upload :: Config -> ClientM () +-- | Request a server shutdown shutdownServer :: ClientM () diff --git a/binding-hs/src/OpenAI/Gym/Data.hs b/binding-hs/src/OpenAI/Gym/Data.hs index 76b1b27..c71bbab 100644 --- a/binding-hs/src/OpenAI/Gym/Data.hs +++ b/binding-hs/src/OpenAI/Gym/Data.hs @@ -23,6 +23,7 @@ import OpenAI.Gym.Prelude import qualified Data.Text as T import qualified Data.Aeson as A +-- | a Gym environment data GymEnv -- | Classic Control Environments = CartPoleV0 -- ^ Balance a pole on a cart (for a short time). @@ -32,7 +33,7 @@ data GymEnv | MountainCarContinuousV0 -- ^ Drive up a big hill with continuous control. | PendulumV0 -- ^ Swing up a pendulum. - -- Toy text games + -- | Toy text games | FrozenLakeV0 -- ^ Swing up a pendulum. -- | Atari Games @@ -56,6 +57,7 @@ instance ToJSON GymEnv where toJSON env = object [ "env_id" .= show env ] +-- | instance identifyier for the environment data InstID = InstID !Text deriving (Eq, Show, Generic) @@ -69,6 +71,8 @@ instance FromJSON InstID where parseJSON = parseSingleton InstID "instance_id" +-- | dict mapping `instance_id` to `env_id` (e.g. `{'3c657dbc': 'CartPole-v0'}`) +-- for every env on the server newtype Environment = Environment { all_envs :: HashMap Text Text } deriving (Eq, Show, Generic) @@ -76,6 +80,8 @@ instance ToJSON Environment instance FromJSON Environment +-- | an observation of the environment, conforming to the environment's +-- observation space data Observation = Observation !Value deriving (Eq, Show, Generic) @@ -86,6 +92,7 @@ instance FromJSON Observation where parseJSON = parseSingleton Observation "observation" +-- | settings for the environment's `step` data Step = Step { action :: !Value , render :: !Bool @@ -94,6 +101,7 @@ data Step = Step instance ToJSON Step +-- | the outcome of an action in the environment data Outcome = Outcome { observation :: !Value , reward :: !Double @@ -105,6 +113,7 @@ instance ToJSON Outcome instance FromJSON Outcome +-- | additional info provided by the environment for debugging purposes data Info = Info !Object deriving (Eq, Show, Generic) @@ -115,6 +124,8 @@ instance FromJSON Info where parseJSON = parseSingleton Info "info" +-- | an action to take in the environment, constrained by the environment's +-- action space data Action = Action !Value deriving (Eq, Show, Generic) @@ -125,20 +136,31 @@ instance FromJSON Action where parseJSON = parseSingleton Action "action" +-- | configurations for monitoring the environment data Monitor = Monitor - { directory :: !Text - , force :: !Bool - , resume :: !Bool - , video_callable :: !Bool + { directory :: !Text -- ^ Directory to dump the monitoring files. + , force :: !Bool -- ^ Clear out existing training data from this + -- directory (by deleting every file prefixed + -- with "openaigym.") + , resume :: !Bool -- ^ Retain the training data already in this + -- directory, which will be merged with our new data + , video_callable :: !Bool -- ^ Whether to record a video on this episode. + -- Not yet implemented in the HTTP API, so fixed to + -- false to disable video recording. Otherwise for + -- null takes perfect cubes, capped at 1000. } deriving (Generic, Eq, Show) instance ToJSON Monitor +-- | settings for uploading run data to OpenAI Gym data Config = Config - { training_dir :: !Text - , algorithm_id :: !Text - , api_key :: !Text + { training_dir :: !Text -- ^ training_dir: A directory containing the results + -- of a training run. + , algorithm_id :: !Text -- ^ algorithm_id (default=None): An arbitrary string + -- indicating the paricular version of the algorithm + -- (including choices of parameters) you are running. + , api_key :: !Text -- ^ api_key: Your OpenAI API key } deriving (Generic, Eq, Show) instance ToJSON Config diff --git a/binding-hs/src/OpenAI/Gym/Prelude.hs b/binding-hs/src/OpenAI/Gym/Prelude.hs index aaf6242..834221e 100644 --- a/binding-hs/src/OpenAI/Gym/Prelude.hs +++ b/binding-hs/src/OpenAI/Gym/Prelude.hs @@ -34,10 +34,12 @@ import Data.Aeson.Types (Parser) instance MimeUnrender HTML () where mimeUnrender _ _ = return () +-- | parses a JSON value parseSingleton :: FromJSON a => (a -> b) -> Text -> Value -> Parser b parseSingleton fn f (Object v) = fn <$> v .: f parseSingleton fn f _ = mempty +-- | serializes an object to JSON toSingleton :: ToJSON a => Text -> a -> Value toSingleton f a = object [ f .= toJSON a ]