Skip to content

Instantly share code, notes, and snippets.

@DarrenSem
Last active April 25, 2024 19:59
Show Gist options
  • Save DarrenSem/44a4a09fdbcf06d45e80ac50c0a256fd to your computer and use it in GitHub Desktop.
Save DarrenSem/44a4a09fdbcf06d45e80ac50c0a256fd to your computer and use it in GitHub Desktop.
chatgpt-lite.js equivalent in Csharp is... not nearly as minimal (ChatGPT results, MarkDown) (1st comment = final C# version, 2nd comment = Java version)

SYSTEM:

You are an expert at JavaScript and C#

. You must format indents using 2 spaces, and you must wrap strings using doublequotes " instead of '.

Let's think step by step.

ME:

Make a similarly minimal C# version of this JavaScript:

let OpenAI = function({apiKey} = {}) {
  let openai = {
    create: async ({...options}) => {
      return ( await fetch( "https://api.openai.com/v1/chat/completions", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: "Bearer " + apiKey
        },
        body: JSON.stringify( {
          ...options,
        } )
      } ) )
      .json();
    },
  };
  return openai;
};

BOT:

For a C# version that accomplishes a similar functionality, you would typically use HttpClient for web requests. This version also involves asynchronous programming, similar to the JavaScript example.

Here is a minimal C# version:

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json; // Make sure to include Newtonsoft.Json for JSON operations

public class OpenAI
{
  private readonly string apiKey;

  public OpenAI(string apiKey)
  {
    this.apiKey = apiKey;
  }

  public async Task<string> CreateAsync(object options)
  {
    var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
    httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");

    var jsonOptions = JsonConvert.SerializeObject(options);
    var content = new StringContent(jsonOptions, Encoding.UTF8, "application/json");

    var response = await httpClient.PostAsync("https://api.openai.com/v1/chat/completions", content);
    return await response.Content.ReadAsStringAsync();
  }
}

In this C# version, you instantiate an OpenAI object with an API key. The CreateAsync method allows you to send a POST request similar to the JavaScript example's create method. This method takes an options object, serializes it to JSON, and sends it in the request body. The response is read as a string asynchronously.

Please note:

  • You need to have Newtonsoft.Json package installed to use JsonConvert for serializing the options. Alternatively, if you are using .NET Core 3.0 or later, you might use the System.Text.Json namespace.
  • This example uses HttpClient in a simplified manner. For real-world applications, it's recommended to use HttpClient as a singleton or a single instance for the application's lifetime to avoid socket exhaustion issues.
  • Don't forget to handle exceptions and errors properly in production code, as this example lacks those checks for brevity.

ME:

Here is JavaScript usage example. Show me similar usage for the C# code you generated above.

import OpenAI from "chatgpt-lite"; // ESM.mjs

async function main() {

  const openai = OpenAI({
    // for minimal size it does NOT currently default to setting apiKey = process.env["OPENAI_API_KEY"]
    apiKey: "api_key_can_not_be_omitted"
    // apiKey: process.env["OPENAI_API_KEY"] || await fetchApiKey()
  });

  console.log("openai:", openai);
  // openai: {
  //   apiKey: 'sk-QiyAbcDe1FGhIjk23l4mnOpQ5RstuV67w89x012y2z34Ab7C',
  //   create: [AsyncFunction: create]
  // }

  const completion = await openai.create({
    messages: [{ role: "user", content: "Say this is a test" }],
    model: "gpt-3.5-turbo",
  });

  console.log("completion:", completion);
  // completion: {
  //   id: 'chatcmpl-8xAbCdEFghI4JklmNopQrs7TuvwxYz',
  //   object: 'chat.completion',
  //   created: 1709167986,
  //   model: 'gpt-3.5-turbo-0125',
  //   choices: [
  //     {
  //       index: 0,
  //       message: [Object],
  //       logprobs: null,
  //       finish_reason: 'stop'
  //     }
  //   ],
  //   usage: { prompt_tokens: 12, completion_tokens: 5, total_tokens: 17 },
  //   system_fingerprint: 'fp_86123a45b6'
  // }

  const {usage} = completion;
  console.log("usage:", usage);
  // usage: { prompt_tokens: 12, completion_tokens: 5, total_tokens: 17 }

  const message = completion.error || completion.choices[0].message;
  console.log("message:", message);
  // message: { role: 'assistant', content: 'This is a test.' }

};

main();
// TODO:

BOT:

To create a similar C# example using the OpenAI class I provided, you would first make sure to have your project environment set up for asynchronous main methods, which is supported in C# 7.1 and later. If you're using an older version, you'll have to adjust the structure accordingly (e.g., by calling GetAwaiter().GetResult() on asynchronous calls or using async event handlers in a desktop application).

I'll show you how to use the OpenAI class in a console application scenario:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        // Assuming OpenAI class is defined in the same project and Newtonsoft.Json is installed

        var apiKey = "api_key_can_not_be_omitted"; // Consider using Environment.GetEnvironmentVariable("OPENAI_API_KEY") for real applications

        var openai = new OpenAI(apiKey);
        Console.WriteLine("openai: instance created.");

        var options = new
        {
            messages = new List<object>
            {
                new { role = "user", content = "Say this is a test" }
            },
            model = "gpt-3.5-turbo",
        };

        var completionJson = await openai.CreateAsync(options);
        Console.WriteLine($"completion: {completionJson}");

        // Since the completion is a JSON string, parsing it to work with the data similarly to the JS example would require JSON parsing. For simplicity, we'll print the JSON.
        // In a real scenario, you would parse this JSON to dynamically access its properties.

        // Optional: Parse the JSON string to an object to access specific fields like 'usage'
        // var completionObj = JsonConvert.DeserializeObject<dynamic>(completionJson);
        // Console.WriteLine($"usage: {completionObj.usage}");

        // For accessing and displaying a message or error similarly
        // var message = completionObj.error != null ? completionObj.error : completionObj.choices[0].message;
        // Console.WriteLine($"message: {message}");
    }
}

Note:

  • This example demonstrates how to asynchronously make a call to the CreateAsync method of the OpenAI class and print the result.
  • Parsing the JSON string to a dynamic object or a specific class is necessary to access individual properties of the response, such as usage or choices, as you would in the provided JavaScript example. I mentioned this as an optional step because it requires defining a model that fits the JSON structure or using a dynamic object with JsonConvert.
  • Remember to handle exceptions and errors that could occur during the HTTP call or JSON parsing, which are not shown in this minimal example for brevity.
  • Ensure your project either targets .NET Core 3.1/.NET 5+ or has the Newtonsoft.Json NuGet package installed for JSON operations.
@DarrenSem
Copy link
Author

DarrenSem commented Apr 20, 2024

// ChatGPT model *ALIAS* info... (as of 20Apr2024)

var model = "gpt-4"; // "gpt-4-0613" (Jun 2023)

var model = "gpt-4-turbo-preview"; // "gpt-4-0125-preview" (Jan 2024)

var model = "gpt-4-turbo"; // "gpt-4-turbo-2024-04-09" (Apr 2024)

OpenAI({apiKey}).create({
  model,
  messages: [
    { role:"user", content:"" }
  ]
}).then(res => console.log(res.model));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment