/ REINFORCEMENT-LEARNING, MACHINE-LEARNING, ARTIFICIAL-INTELLIGENCE, DOTNET

Writing a C# SDK for the OpenAI Gym using .NET Core

When we take a look at the OpenAI Gym on Github (https://github.com/openai/gym-http-api), we see that it does not have bindings available for C#. Now since I am a firm believer of .NET Core and what it brings to developer ecosystem, I decided to write one myself (https://github.com/thebillkidy/dotnetcore-sdk-openai). Using what I learned in my previous blog post How to write a SDK in dotnet Core I created one that looks like this for the main method:

Note: You can test it using the Test() method in this class

using System;
using System.Threading.Tasks;
using System.Net.Http;
using OpenAI.SDK.Models.Response;
using OpenAI.SDK.Models.Request;
using Newtonsoft.Json;
using System.Text;

namespace OpenAI.SDK
{
    public class ApiService
    {
        private static readonly HttpClient client = new HttpClient();

        private readonly string host;

        public ApiService(string host = "http://127.0.0.1:5000")
        {
            this.host = host;
        }

        public async Task Test()
        {
            Console.WriteLine("========== CREATE ENVIRONMENT ==========");
            var env = await EnvCreate("CartPole-v0");
            Console.WriteLine("Created Environment: " + env.InstanceID);

            Console.WriteLine("========== ALL ENVIRONMENTS ==========");
            Console.WriteLine(await EnvListAll());

            Console.WriteLine("========== INITIAL OBSERVATION ==========");
            var initialObservation = await EnvReset<double[]>(env.InstanceID);
            Console.WriteLine(initialObservation.Observation);

            Console.WriteLine("========== STEP ==========");
            var stepTaken = await EnvStep<double[]>(env.InstanceID, 1);
            Console.WriteLine(stepTaken.IsDone);
            Console.WriteLine(stepTaken.Reward);
            Console.WriteLine(stepTaken.Observation);

            Console.WriteLine("========== SPACES ==========");
            var actionSpace = await EnvActionSpaceInfo<dynamic>(env.InstanceID);
            var observationSpace = await EnvObservationSpaceInfo<dynamic>(env.InstanceID);
            Console.WriteLine(actionSpace);
            Console.WriteLine(observationSpace);
        }

        public async Task<EnvGetAllResponse> EnvListAll()
        {
            var json = await client.GetStringAsync($"{this.host}/v1/envs/");
            var resParsed = JsonConvert.DeserializeObject<EnvGetAllResponse>(json);
            return resParsed;
        }

        public async Task<EnvCreateResponse> EnvCreate(string envID)
        {
            var requestBody = new EnvCreateRequest {
                EnvId = envID
            };
            var requestJson = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, "application/json");

            var res = await client.PostAsync($"{this.host}/v1/envs/", requestJson);
            var resContent = await res.Content.ReadAsStringAsync();
            var resParsed = JsonConvert.DeserializeObject<EnvCreateResponse>(resContent);
            return resParsed;
        }

        public async Task<EnvResetResponse<T>> EnvReset<T>(string instanceID)
        {
            var res = await client.PostAsync($"{this.host}/v1/envs/{instanceID}/reset/", null);
            var resContent = await res.Content.ReadAsStringAsync();
            var resParsed = JsonConvert.DeserializeObject<EnvResetResponse<T>>(resContent);
            return resParsed;
        }

        public async Task<EnvStepResponse<T>> EnvStep<T>(string instanceID, int action, bool isRender = false)
        {
            var requestBody = new EnvStepRequest {
                Action = action,
                IsRender = isRender
            };

            var requestJson = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, "application/json");

            var res = await client.PostAsync($"{this.host}/v1/envs/{instanceID}/step/", requestJson);
            var resContent = await res.Content.ReadAsStringAsync();
            var resParsed = JsonConvert.DeserializeObject<EnvStepResponse<T>>(resContent);
            return resParsed;
        }

        public async Task<EnvGetActionSpaceResponse<T>> EnvActionSpaceInfo<T>(string instanceID)
        {
            var json = await client.GetStringAsync($"{this.host}/v1/envs/{instanceID}/action_space/");
            var resParsed = JsonConvert.DeserializeObject<EnvGetActionSpaceResponse<T>>(json);
            return resParsed;
        }

        public async Task<EnvGetObservationSpaceResponse<T>> EnvObservationSpaceInfo<T>(string instanceID)
        {
            var json = await client.GetStringAsync($"{this.host}/v1/envs/{instanceID}/observation_space/");
            var resParsed = JsonConvert.DeserializeObject<EnvGetObservationSpaceResponse<T>>(json);
            return resParsed;
        }

        public async Task<EnvMonitorStartResponse> EnvMonitorStart(string instanceID, string directory, bool force, bool resume)
        {
            var requestBody = new EnvMonitorStartRequest {
                Directory = directory,
                Force = force,
                Resume = resume
            };

            var requestJson = new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, "application/json");

            var res = await client.PostAsync($"{this.host}/v1/envs/{instanceID}/monitor/start", requestJson);
            var resContent = await res.Content.ReadAsStringAsync();
            var resParsed = JsonConvert.DeserializeObject<EnvMonitorStartResponse>(resContent);
            return resParsed;
        }

        public async Task<EnvMonitorStopResponse> EnvMonitorStop(string instanceID)
        {
            var res = await client.PostAsync($"{this.host}/v1/envs/{instanceID}/monitor/close", null);
            var resContent = await res.Content.ReadAsStringAsync();
            var resParsed = JsonConvert.DeserializeObject<EnvMonitorStopResponse>(resContent);
            return resParsed;
        }

        public async Task<EnvCloseResponse> EnvClose(string instanceID)
        {
            var res = await client.PostAsync($"{this.host}/v1/envs/{instanceID}/close", null);
            var resContent = await res.Content.ReadAsStringAsync();
            var resParsed = JsonConvert.DeserializeObject<EnvCloseResponse>(resContent);
            return resParsed;
        }

        public async Task<ShutdownServerResponse> ShutdownServer()
        {
            var res = await client.PostAsync($"{this.host}/v1/shutdown", null);
            var resContent = await res.Content.ReadAsStringAsync();
            var resParsed = JsonConvert.DeserializeObject<ShutdownServerResponse>(resContent);
            return resParsed;
        }
    }
}
xavier

Xavier Geerinck

Xavier works as a Cloud Solution Architect at Microsoft, helping its customer unlock the full potential of the cloud. Even though he is still considered a young graduate, he achieved his first success at the age 16, by creating and selling his first startup. He then took this knowledge to create and help more startups in different markets such as technology, social media, philanthropy and home care. While in the meantime gaining more enterprise insights at renowned enterprises such as Nokia, Cisco and now Microsoft.

Read More