An implementation of the OpenAI API for GNU Guile

Andrew Whatson 751cd5db5f Bump version to 0.2 10 months ago
build-aux 19c630405d Add autotools build system 10 months ago
openai 9a9fa57ee1 Document openai-text-edit and openai-code-edit 10 months ago
.dir-locals.el e9097f1632 Adjust fill-column and re-wrap README 11 months ago
.envrc 19c630405d Add autotools build system 10 months ago
.gitignore 19c630405d Add autotools build system 10 months ago
COPYING d6ad7282fb Documentation, license, top-level module 1 year ago
Makefile.am 19c630405d Add autotools build system 10 months ago
README.md dabfa4eba5 Document the autotools build 10 months ago
bootstrap 19c630405d Add autotools build system 10 months ago
configure.ac 751cd5db5f Bump version to 0.2 10 months ago
guix.scm 751cd5db5f Bump version to 0.2 10 months ago
openai.scm c2413de182 Add openai-image-edit 11 months ago
pre-inst-env.in 19c630405d Add autotools build system 10 months ago

README.md

guile-openai

This is a GNU Guile client for the OpenAI API. It currently implements the Chat and Image APIs, with support for chat response streaming and inline image display in a Geiser REPL.

Installation

Guix

An up-to-date GNU Guix package definition is provided in the repository, so you can install it into your profile with the following:

guix package -f path/to/guile-openai/guix.scm

Alternatively, you can jump straight into an interactive environment by loading it with Guile Studio:

guix shell guile guile-studio -f path/to/guile-openai/guix.scm -- guile-studio

Autotools

A conventional build system is also provided:

cd path/to/guile-openai
./bootstrap
./configure && make

Documentation

Quick start

The library is designed for convenient interactive use, so many useful settings are defined as parameters. Reasonable defaults are provided, so all you need to get started is an API key and a Guile REPL.

To get an API key, you'll need to sign up for an account with OpenAI. Currently new accounts get a certain number of free requests, but ultimately the OpenAI API is a paid service.

(use-modules (openai))

;; Set your OpenAI API key
(openai-api-key "MYVERYSECRETAPIKEY")

;; Simple chat example
(openai-chat "Why is software freedom important?")

;; Simple image example
(openai-image "A cute drawing of a kid in a gnu onesie programming a
 robot with their laptop computer")

;; Generate a prompt to generate an image
(let ((rsp (openai-chat "A short paragraph describing a cute mascot for
 the GNU Guile Scheme programming language")))
  (display rsp)
  (newline)
  (openai-image (chat-content rsp)))

;; Generate an image and a variation of that image
(let* ((original (openai-image "A whimsical scheme wizard."))
       (variation (openai-image-variation original)))
  (values original variation))

;; Interactive chat example
(use-modules (ice-9 readline))

(define default-prompt
  "You are an AI assistant embedded in a GNU Guile Scheme REPL, which
 answers user enquiries in a helpful and playful manner while strongly
 advocating for Free Software and the principles of user freedom.")

(define* (interactive-chat #:optional (prompt default-prompt))
  (let loop ((msgs `((system . ,prompt))))
    (let ((query (readline "> ")))
      (if (or (eof-object? query)
              (string-null? query))
          msgs
          (let* ((msgs (append msgs `((user . ,query))))
                 (chat (openai-chat msgs)))
            (newline)
            (display chat)
            (display "\n\n")
            (let* ((text (chat-content chat))
                   (msgs (append msgs `((assistant . ,text)))))
              (loop msgs)))))))

Configuration

Parameter for the URI of the OpenAI API endpoint.

  • (openai-api-key unspecified)

Parameter for the API key to use for requests.

  • (openai-organization unspecified)

Parameter for an optional organization ID to include in requests.

  • (openai-default-headers '())

Parameter for additional HTTP headers to include in requests.

  • (openai-default-user unspecified)

Parameter for a default value for the #:user argument of requests.

Chat API

  • (openai-chat prompt [keyword arguments])

Send a chat completion request. Returns a chat record.

The prompt can be a string, which will be sent as a user message. Alternatively, prompt can be a list of (role . content) pairs, where content is a string and role is a symbol system, user, or assistant.

The keyword arguments correspond to the request parameters described in the chat completion request documentation:

  • #:n

    The number of responses to generate, returned as multiple values.

  • #:stream?

    Whether to stream the response(s), defaults to #t.

  • #:model

    A symbol or string identifying the model to use. Defaults to gpt-3.5-turbo, but if you're lucky you might be able to use gpt-4 or gpt-4-32k here.

  • #:temperature

    The sampling temperature to use, a number between 0 and 2.

  • #:top-p

    An alternative sampling parameter, a number between 0 and 1.

  • #:user

    An optional username to associate with this request.

The #:stop, #:max-tokens, #:logit-bias, #:presence-penalty, #:frequency-penalty parameters are implemented but untested.

  • (openai-default-chat-model 'gpt-3.5-turbo)

Parameter for the default #:model value.

  • (openai-default-chat-temperature unspecified)

Parameter for the default #:temperature value.

  • (openai-default-chat-top-p unspecified)

Parameter for the default #:top-p value.

  • (openai-default-chat-stream? #t)

Parameter for the default #:stream? value.

  • (chat? chat)

Type predicate for chat responses.

  • (chat-content chat)

Return the chat response as a string.

  • (chat-stream chat)

Return the chat response as a stream of strings.

Image API

  • (openai-image prompt [keyword arguments])

Send an image generation request. Returns an image record.

The prompt must be a string.

The keyword arguments correspond to the request parameters described in the image generation request documentation:

  • #:n

    The number of images to generate, returned as multiple values.

  • #:size

    A number specifying the generated image size, either 256, 512, or 1024. The symbols 256x256, 512x512 and 1024x1024 are also supported.

  • #:format

    How the image data will be returned, either url (hosted on a cloud server), or b64 (embedded in the response message, the default). In either case, the image data will be fetched and stored locally for display.

  • #:user

    An optional username to associate with this request.

  • (openai-image-edit image prompt [keyword arguments])

Send an image edit request. Returns an image record.

The image can be an image record or a string path to the image file to be varied. The API requires the image to be a valid PNG file, less than 4MB, and square.

The *prompt** must be a string describing the changes to be made to the image.

The keyword arguments correspond to the request parameters described in the image edit request documentation:

  • #:mask

An image record or a string path to an image file to use as the edit mask. The model will only edit pixels which are fully transparent (ie. alpha 0) in the mask image. The mask must have the same dimensions as IMAGE. The default is fully opaque, so no pixels will be edited and a copy of the original image will be returned.

  • #:n, #:size, #:format, #:user

    See openai-image.

  • (openai-image-variation image [keyword arguments])

Send an image variation request. Returns an image record.

The image can be an image record or a string path to the image file to be varied. The API requires the image to be a valid PNG file, less than 4MB, and square.

The keyword arguments correspond to the request parameters described in the image variation request documentation:

  • #:n, #:size, #:format, #:user

    See openai-image.

  • (openai-default-image-size 512)

Parameter for the default #:size value.

  • (openai-default-image-format 'b64)

Parameter for the default #:format value.

  • (image? image)

Type predicate for image responses.

  • (image-url image)

The URL of the image, if using the url format.

  • (image-file image)

The temporary filename containing the image data.

Embedding API

  • (openai-embedding input [keyword arguments])

Send an embedding request. Returns an embedding record.

The input must be a string to be embedded.

The keyword arguments correspond to the request parameters described in the embedding request documentation:

  • #:model

    A symbol or string identifying the model to use. Defaults to text-embedding-ada-002.

  • #:user

    An optional username to associate with this request.

  • (openai-default-embedding-model 'text-embedding-ada-002)

Parameter for the default #:model value.

  • (embedding? embedding)

Type predicate for embedding responses.

  • (embedding-vector embedding)

The embedding vector generated by the model.

Text Edit API

  • (openai-text-edit input instruction [keyword arguments])

Send an edit request. Returns an edit record.

The input must be a string, which is the text to be edited. The instruction is a string describing the changes to be made.

The keyword arguments correspond to the request parameters described in the edit request documentation:

  • #:model

    A symbol or string identifying the model to use. Defaults to text-davinci-edit-001.

  • #:n

    The number of responses to generate, returned as multiple values.

  • #:temperature

    The sampling temperature to use, a number between 0 and 2.

  • #:top-p

    An alternative sampling parameter, a number between 0 and 1.

  • (openai-code-edit input instruction [keyword arguments])

Identical to openai-text-edit, except it defaults to the code-davinci-edit-001 model.

  • (openai-default-text-edit-model 'text-davinci-edit-001)

Parameter for the default #:model value (text edit).

  • (openai-default-text-edit-temperature unspecified)

Parameter for the default #:temperature value (text edit).

  • (openai-default-text-edit-top-p unspecified)

Parameter for the default #:top-p value (text edit).

  • (openai-default-code-edit-model 'code-davinci-edit-001)

Parameter for the default #:model value (code edit).

  • (openai-default-code-edit-temperature unspecified)

Parameter for the default #:temperature value (code edit).

  • (openai-default-code-edit-top-p unspecified)

Parameter for the default #:top-p value (code edit).

  • (edit? edit)

Type predicate for edit responses.

  • (edit-content edit)

The edited content generated by the model.

Moderation API

  • (openai-moderation input [keyword arguments])

Send a moderation request. Returns a moderation record.

The input must be a string to be classified by the moderation model.

The keyword arguments correspond to the request parameters described in the moderation request documentation:

  • #:model

    A symbol or string identifying the model to use. The default is *unspecified*, which is equivalent to text-moderation-latest.

  • (openai-default-moderation-model unspecified)

Parameter for the default #:model value.

  • (moderation? moderation)

Type predicate for moderation responses.

  • (moderation-flagged? moderation)

Whether the content was in violation of OpenAI's content policy.

  • (moderation-categories moderation)

The list of categories which caused this content to be flagged.

  • (moderation-scores moderation)

An association list of the scores for this content in each category.

  • (moderation-score moderation category)

The moderation score for this content in the specified category.

License

Copyright © 2023 Andrew Whatson whatson@tailcall.au

guile-openai is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

guile-openai is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with guile-openai. If not, see https://www.gnu.org/licenses/.

See COPYING for details.