Unlocking the Power of OpenAI in Ada programs

By Stephane Carrez

OpenAI has recently emerged, and its usage has increased in various areas. It was time to make it available to Ada programs using the Ada OpenAI library. The library provides an Ada API to make requests on the GPT-4, GPT-3, DALL.E and other AI models. The article does not assess the merits and drawbacks of using such technologies but instead focuses on the technical aspects of utilizing them within an Ada application.

Ada/openai-img.jpg

The OpenAI provides a service that can be queried using REST requests. The service API can be classified as follows:

  • OpenAI's GPT (generative pre-trained transformer) is the well-known text generation based on text inputs. It gives access to several AI models that have been trained to understand natural language and code.
  • Image generation gives access to the DALL.E for both generating images based on a text description, or, modify an existing image based on a text description.
  • Speech to text gives access to the Whisper model that converts audio records into text (several languages are supported).
  • OpenAI’s text embeddings measure the relatedness of text strings.

For a detailed description of these API have a look at the OpenAI API Introduction document. To use these APIs, you'll first need to register on their service and get an API key that will grant access to the operations.

The library was generated by the OpenAPI code generator from the OpenAPI description of the OpenAI service and it uses the OpenAPI Ada library to make HTTP requests and perform JSON serialization and de-serialization. Each OpenAI operation is made available through an Ada procedure which takes care of building the request that was filled within some Ada record, submitting it to the OpenAI server and extract the response in another Ada record. Every request submitted to the OpenAI server is therefore strongly typed!

Setup

To use the library, you should use Alire to setup your project and use:

alr index --add git+https://gitlab.com/stcarrez/awa-alire-index.git --name awa
alr with openai

For the HTTP connection, you can either use AWS or curl and run one of the following commands:

alr with utilada_curl
alr with utilada_aws

Initialization

First, make sure you import at least the following Ada packages:

with Util.Http.Clients.Curl; --  replace Curl with AWS if needed
with OpenAPI.Credentials.OAuth;
with OpenAI.Clients;
with OpenAI.Models;

If you want to use curl, the initialization should use the following:

Util.Http.Clients.Curl.Register;

But if you want to use AWS, you will initialize with:

Util.Http.Clients.AWS.Register;

After the initialization is done, you will declare the OpenAI client instance to access the API operations. The OpenAI service uses an OAuth bearer API key to authenticate requests made on the server. We will need an OAuth2_Credential_Type instance represented by Cred below.

Cred   : aliased OpenAPI.Credentials.OAuth.OAuth2_Credential_Type;
Client : OpenAI.Clients.Client_Type;

Credential setup

For the credential setup you will first need to get your access key from your account. Once you have your key as a String, you can configure the Cred object and tell the client connection entry point which credentials to use:

Api_Key : constant String := ...;

   Cred.Bearer_Token (Api_Key);
   Client.Set_Credentials (Cred'Unchecked_Access);

OpenAPI client setup

The last step necessary before you can make requests, is to setup the server base URL to connect for the REST requests:

  Client.Set_Server ("https://api.openai.com/v1");

API for chat

The Create_Chat is the main operation for the conversation chat generation. The request is represented by the ChatRequest_Type type which describes the OpenAI chat model that must be used and the query parameters. The request can be filled with a complete conversation chat which means it is possible to call it several times with previous queries and responses to proceed in the chat conversation.

C       : OpenAI.Clients.Client_Type;
Req     : OpenAI.Models.ChatRequest_Type;
Reply   : OpenAI.Models.ChatResponse_Type;
...
   Req.Model := OpenAPI.To_UString ("gpt-3.5-turbo");
   Req.Messages.Append ((Role => Openapi.To_Ustring ("user"),
                         Content => Prompt,
                         others => <>));
   Req.Temperature := 0.3;
   Req.Max_Tokens := (Is_Null => False, Value => 1000);
   Req.Top_P := 1.0;
   Req.Frequency_Penalty := 0.0;
   Req.Presence_Penalty := 0.0;
   C.Create_Chat (Req, Reply);

Upon successful completion, we get a list of choices in the reply that contains the text of the conversation. You can iterate over the list with the following code extract. Beware that the returned string is using UTF-8 encoding and it may need a conversion to a Wide_Wide_String if necessary.

   for Choice of Reply.Choices loop
      declare
         Utf8 : constant String := OpenAPI.To_String (Choice.Message.Content);
      begin
         Put_Line (Ada.Strings.UTF_Encoding.Wide_Wide_Strings.Decode (Utf8));
      end;
   end loop;

The complete chat example is available at: OpenAI Chat .

Generating an image

The image generation is based on the DALL.E model generator. The creation is made by populating a request object, making the call (which is an HTTP POST) and getting the result in a response. Both request and response are represented by full Ada types and are strongly typed:

The request contains a prompt string which must be provided and is the textual description of the image to create. An optional parameter allows to control the number of images which are created (from 1 to 10). Another optional parameter controls the dimension of the final image. The OpenAI API limits the possible values to: 256x256, 512x512 and 1024x1024. The image creation is represented by the Create_Image procedure and we can call it with our request instance:

Req     : OpenAI.Models.CreateImagesRequest_Type;
Reply   : OpenAI.Models.ImagesResponse_Type;
...
   Req.Prompt := Prompt;
   Req.N := (Is_Null => False, Value => 3);
   Req.Size := (Is_Null => False, Value => "512x512");
   C.Create_Image (Req, Reply);

Once it has finished, it produces a response which basically contains a list of URLs for each generated image.

   for Url of Reply.Data loop
      if not Url.Url.Is_Null then
         Ada.Text_IO.Put_Line (OpenAPI.To_String (Url.Url.Value));
      end if;
   end loop;

The complete image generation example is available at: OpenAI Image Generation .

For more information about the image creation, have a look at the OpenAI Images API reference.

Conclusion

The Ada OpenAI library is eagerly awaiting your Ada programming creativity. You can try using the chat generation example to ask the AI to generate some Ada code, but you'll likely be disappointed by the poor quality of Ada programs that OpenAI generates. However, you may still find some small benefits in using it across different domains. I encourage you to give it a try for your enjoyment and pleasure.

Add a comment

To add a comment, you must be connected. Login