Model or dataset
HemulGM/DelphiOpenAI avatar
HemulGM/DelphiOpenAI

DelphiOpenAI ships thirty units at the root and two ways to build a chat message

OpenAI (and DeepSeek, Azure OpenAI, YandexGPT, Ollama, GigaChat, Qwen) API wrapper for Delphi. Use ChatGPT, DALL-E, Whisper and other products.

315 stars86 forksPascalMIT

At a glance

What is it?
An unofficial Pascal client for the OpenAI API, also used against Azure OpenAI, DeepSeek, YandexGPT, Qwen, and GigaChat. The coverage is broad and the API surface is fluent, but the samples disagree with each other in small ways and the newest release tag is two years old.
Who is it for?
DelphiOpenAI is a reasonable choice if you have a Delphi codebase and want an OpenAI-compatible client without leaving Pascal, especially since the same units work against DeepSeek, Azure OpenAI, YandexGPT, Qwen, and GigaChat by changing the endpoint. Two practical warnings.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 81 days ago.
What is it written in?
Mainly Pascal, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Ollama is in the repository description and absent from the compatibility list

The repository description names six providers: OpenAI, DeepSeek, Azure OpenAI, YandexGPT, Ollama, and GigaChat, plus Qwen in the expanded form.

The compatibility section names five: OpenAI Azure, DeepSeek, YandexGPT, Qwen, and GigaChat. Ollama is not in that list.

So one provider appears in the metadata and not in the tested list. That is not necessarily a defect, since Ollama exposes an OpenAI-compatible surface and the section closes by saying other OpenAI-compatible APIs work too, but the word used for the five is that they were tested. There is no claim either way about Ollama.

The file layout is consistent with the list rather than the description. There is a dedicated `OpenAI.GigaChat.pas` unit, and the other providers do not get one, which suggests GigaChat needed something extra in the request shape. Everything else goes through the generic OpenAI units.

Which means the provider list is really a list of endpoint overrides rather than of separate implementations, and the way to use a different host is to redirect the base URL rather than to import a different unit. That is the piece of information the compatibility section implies without spelling out.

Two entry points, one of which needs a component owner

Initialization takes an API token and produces one of two different things.

Pascal
uses OpenAI;

var OpenAI := TOpenAIComponent.Create(Self, API_TOKEN);

or

Pascal
uses OpenAI;

var OpenAI: IOpenAI := TOpenAI.Create(API_TOKEN);

The first takes an owner as its first argument, `Self`, which is the classic component pattern: the instance has a lifetime tied to a form or another component, and is what you would drop on a form at design time. The second returns an interface and needs no owner at all, which is what you want in a console program, a service, or a unit test.

The parameter configuration style is the same in both cases. Because there are many parameters and not all are required, they are set inside an anonymous procedure that receives a typed params object, so you write only what you care about:

Pascal
var Completions := OpenAI.Completion.Create(
  procedure(Params: TCompletionParams)
  begin
    Params.Prompt(MemoPrompt.Text);
    Params.MaxTokens(2048);
  end);

The chain reads `OpenAI`, then the endpoint family, then `Create`, then a lambda. It is fluent and it is the main reason the library is pleasant to use.

Token handling is entirely on the caller. The token is a string you supply at construction, and nothing in the samples reads it from a configuration file or an environment variable, so where it comes from is a decision your application makes.

Every result is a manually freed object

Look at the shape of all three usage samples and the same three lines appear at the bottom of each:

Pascal
try
  for var Choice in Chat.Choices do
    MemoChat.Lines.Add(Choice.Message.Content);
finally
  Chat.Free;
end;

`Chat.Free`, `Completions.Free`, `Models.Free`. The results are objects with an owner, not interfaces, so the caller is responsible for releasing them. Iterating the choices is safe inside the try, but an exception thrown by the body still has to be caught by your own error handling, and a forgotten free leaks the whole response including the raw JSON behind it.

This is the single most important thing to know before writing Delphi code against this library, because it is not the Delphi you might expect from an interface-based client. The entry point can hand you an interface, but the calls on it return owned objects.

The error unit and the exceptions section in the table of contents are the intended place to handle failures, and the parameters API means a partially specified call is not a compile error, so the failure will surface as a runtime API error rather than as a rejected argument.

The samples build a chat message two different ways

Two message construction APIs appear in the samples, and they do not match.

The plain chat sample uses an explicit role constructor:

Pascal
Params.Messages([TChatMessageBuild.Create(TMessageRole.User, Text)]);

The streaming sample uses a one-argument convenience call:

Pascal
Params.Messages([TchatMessageBuild.User(Buf.Text)]);

Note also the casing. One is `TChatMessageBuild`, the other is `TchatMessageBuild`. Delphi is case-insensitive so both compile, which is exactly why the inconsistency survives in the documentation.

The convenience form infers the user role, which is why it takes only the text. The explicit form takes the role as a parameter, which is what you need for a system message or an assistant turn.

So both paths exist in the unit. That is reasonable, since most chat calls are single user messages, but the samples do not say so, and a reader copying the streaming sample first will not discover the role parameter exists until they need a system prompt.

The vision sample takes a third route again, building an array of message content and appending a text part and a base64 image part to it, so a multimodal turn needs its own construction path on top of whichever builder you use for plain text.

Two endpoints OpenAI retired are marked as done

The coverage table marks fourteen areas complete. Among them are fine-tunes and engines, and both are annotated as deprecated on the API side while still being shown as finished here.

That is an honest reflection of a client library's job rather than a mistake: the code works because the endpoints worked when it was written. But it does mean the table is a description of past compatibility, not of what you can call today.

The four areas still in progress are assistants, threads, messages, and runs. That set is one coherent subsystem, the conversation and run machinery, and it is exactly the part of the OpenAI API that has been reshaped more than once.

The repository contains an `OpenAI.Assistants.pas` unit, so work has started. Chat vision, edits, audio, files, fine-tuning, and moderations are all listed as complete, along with the legacy completions endpoint alongside the modern chat one.

Reading the table as a whole, the shape is a complete client for the generation and file endpoints and an unfinished one for the agent endpoints. Anyone building a tool-calling loop against it should confirm which of those two categories their code actually needs.

Two doc hostnames and a model name that dates the guide

The README links to the API reference on one hostname and to the per-endpoint documentation on another. The introduction points at `beta.openai.com/docs/api-reference/`, and the review links under Models, Completions, and Chat point at `platform.openai.com/docs/api-reference/`. Both are the same vendor, and only one of them is the current documentation host.

The chat section is older still. It states that ChatGPT is powered by gpt-3.5-turbo and calls it the most advanced language model, then lists the things you could build with it. The vision sample names its model explicitly, and the name it uses is a preview identifier rather than a general release.

Neither statement breaks anything. They matter because they tell you when the examples were written, and therefore which parts of the sample code to trust as current and which to check against the vendor's own reference before copying.

The same caution applies to the compatibility list, which uses the word tested without saying when. There is a test matrix somewhere or there is not, and the README does not say.

One more small thing: the first line of the file contains the word repositorty.

The newest release tag is two years old and installation is a folder on a path

The release history has three tags. v1.2 and v1.3 share the same date in September 2023, and v1.4 is dated August 2024. The default branch was last pushed in July 2026.

So there has been roughly two years of commits past the newest tag. If you install from GetIt you get whatever the package manager considers current, which may be a tag or may be a snapshot; the documentation does not say.

Installation itself has two routes and neither one names a version. You can install the package from GetIt inside the IDE, or add the root folder to the IDE library path or to your project source path. The second route is the interesting one, because it means you are consuming the working tree rather than a released artifact, which is how most of the samples in the repository are meant to be run.

The layout supports that. There are more than thirty Pascal units at the root, one per API area, plus shared units for types, base64 encoding, a JSON cleaner, an object holder, and errors. A Delphi package project, the design-time installable unit, sits beside them with its resources and an icon.

Sample projects are grouped separately: a chat sample, a quick chat sample, a general sample, and a group project that ties them together.

Editorial conclusion

DelphiOpenAI is a reasonable choice if you have a Delphi codebase and want an OpenAI-compatible client without leaving Pascal, especially since the same units work against DeepSeek, Azure OpenAI, YandexGPT, Qwen, and GigaChat by changing the endpoint. Two practical warnings. First, the return values are owned objects, so every call needs a try and finally with an explicit free, which is the pattern in all three samples and easy to miss when you write the first call yourself. Second, the documentation is a mix of vintages: the chat section still describes a 3.5-turbo model as the most advanced, the model identifier in the vision sample is a preview name, and the newest release tag is from 2024 while the branch has moved since. Install from GetIt or add the root folder to your library path, and check the endpoint override for whichever provider you target before assuming the default host works.

Frequently asked questions

Is DelphiOpenAI an official OpenAI library?

No. The README states it is an unofficial library and that OpenAI does not provide an official library for Delphi. It is licensed MIT and written in Pascal.

Which providers does DelphiOpenAI work with?

The compatibility section names OpenAI Azure, DeepSeek, YandexGPT, Qwen, and GigaChat as tested, plus any other API compatible with the OpenAI API. The repository description also lists Ollama, which does not appear in the tested list.

How do I initialise the DelphiOpenAI client?

Create the instance with your API token. `TOpenAI.Create(API_TOKEN)` returns an `IOpenAI` interface and needs no owner, while `TOpenAIComponent.Create(Self, API_TOKEN)` takes a component owner for design-time use. Request parameters are then set inside an anonymous procedure.

Do I have to free the results returned by DelphiOpenAI?

Yes. Results such as Chat, Completions, and Models are objects, not interfaces, and every sample wraps the work in a try and finally block that calls Free on the result. The entry point can return an interface, but its calls return owned objects.

Which DelphiOpenAI endpoints are still in progress?

Assistants, Threads, Messages, and Runs are all marked in progress. Models, the legacy completions endpoint, chat, chat vision, edits, images, embeddings, audio, files, fine-tunes, fine-tuning, moderations, and engines are all marked complete.

Official sources

  1. HemulGM/DelphiOpenAI on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hemulgm-delphiopenai.svg)](https://hysenlabs.com/projects/hemulgm-delphiopenai)