Ein LLM aus Delphi aufrufen

Schicke einen Prompt aus einer VCL-, FMX- oder Konsolenanwendung und bekomme eine Antwort zurück, von einem gehosteten Modell wie OpenAI oder Anthropic Claude oder von einem Modell, das über Ollama auf deinem eigenen Rechner läuft. Diese Seite bringt dich vom leeren Formular zu einem funktionierenden Aufruf und dann zu den drei Dingen, auf die jedes Projekt als Nächstes stößt: Streaming, Tool Calling und die Entscheidung zwischen gehostetem und lokalem Modell.

OpenAI, Claude, Gemini, Grok, DeepSeek, Mistral, Ollama
Streaming über Server-Sent Events
Delphi 7 bis RAD Studio 13

Zwei Wege, den Aufruf zu machen

Es gibt eine anbieterneutrale Chat-Komponente, und es gibt je Hersteller einen eigenen REST-Client. Beide stecken in derselben Bibliothek, du kannst also mit dem einen anfangen und zum anderen wechseln, ohne das Projekt zu wechseln.

TsgcAIChat, eine API für jeden Anbieter

Setze Provider, einen API-Schlüssel und ein Modell, dann rufe Chat auf. Die Komponente baut das JSON des Herstellers, hält den Gesprächsverlauf und gibt den Assistententext zurück. Der Wechsel von OpenAI zu Claude oder zu einem lokalen Ollama-Modell ist eine Zuweisung. Implementiert von TsgcAI_Chat in der Unit sgcAI_Chat und auf der Palette registriert als TsgcAIChat.

Die REST-Clients je Hersteller

TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic and TsgcHTTP_API_Ollama legen die jeweilige Hersteller-API vollständig offen, auch die Teile, die keine neutrale Schicht abdecken kann: Bildeingabe, Dokumenteingabe, Extended Thinking, Batches, Dateien, Embeddings, Bildgenerierung und Transkription. Nimm sie, wenn du einen bestimmten Endpunkt brauchst.

Edition und Plattform

Die KI- und LLM-Clients sind eine Funktion der Edition Enterprise von sgcWebSockets, nicht Standard und nicht Professional, oder du kaufst das eigenständige Paket sgcAI.

Die Plattform zählt hier. Die drei REST-Clients kompilieren unter Windows, macOS, Linux, iOS und Android. TsgcAIChat nicht: Es wird nur für Windows kompiliert, bei einem Linux-Dienst, einem macOS-Build oder einem Mobilziel rufst du also den REST-Client direkt auf. Die Beispiele auf dieser Seite sind so geschrieben, dass beide Wege funktionieren.

Dein erster Aufruf, in etwa zehn Zeilen

Komponente ablegen, Schlüssel und Modell setzen, Prompt senden. Wähle den Tab für den Anbieter, mit dem du startest. Der letzte Tab braucht überhaupt keinen API-Schlüssel, weil das Modell auf deinem Rechner läuft.

uChat.pas
uses
  Classes, SysUtils,
  // sgc
  sgcAI_Chat;

procedure TfrmMain.btnAskClick(Sender: TObject);
var
  oChat: TsgcAI_Chat;
begin
  oChat := TsgcAI_Chat.Create(nil);
  try
    oChat.Provider := aicpOpenAI;
    oChat.ChatOptions.ApiKey := GetApiKey;
    oChat.ChatOptions.Model := 'gpt-4o-mini';
    oChat.ChatOptions.MaxTokens := 1024;
    oChat.SystemMessage := 'You are a concise assistant inside a Delphi ERP.';

    memoAnswer.Lines.Text := oChat.Chat(memoPrompt.Lines.Text);
  finally
    oChat.Free;
  end;
end;

Der Herstellerwechsel ist eine einzige Zeile. Provider akzeptiert aicpOpenAI, aicpAnthropic, aicpGemini, aicpDeepSeek, aicpOllama, aicpGrok und aicpMistral. Alles andere in deinem Code bleibt, wo es ist.

Nur Windows. TsgcAI_Chat und die zugehörige Palettenkomponente TsgcAIChat werden für Windows kompiliert, Win32 und Win64. Unter macOS, Linux, iOS und Android wird die Unit gar nicht kompiliert, wenn dein Ziel also ein Linux-Dienst oder eine mobile App ist, nimm die REST-Clients der Hersteller in den anderen drei Tabs. Die haben keine Plattformbeschränkung.

uOpenAI.pas
uses
  Classes, SysUtils,
  // sgc
  sgcHTTP_API_OpenAI;

var
  oOpenAI: TsgcHTTP_API_OpenAI;
begin
  oOpenAI := TsgcHTTP_API_OpenAI.Create(nil);
  try
    oOpenAI.OpenAIOptions.ApiKey := GetApiKey;

    // Shortcut: model plus one user message, raw JSON back
    memoAnswer.Lines.Text := oOpenAI._CreateChatCompletion(
      'gpt-4o', 'Say hello');
  finally
    oOpenAI.Free;
  end;
end;

Die Unterstrich-Methoden sind String-Abkürzungen, die den rohen Antwortkörper zurückgeben. Wenn du ein geparstes Objekt willst, baue ein TsgcOpenAIClass_Request_ChatCompletion und rufe CreateChatCompletion auf, weiter unten auf dieser Seite gezeigt.

uClaude.pas
uses
  Classes, SysUtils,
  // sgc
  sgcHTTP_API_Anthropic;

var
  oAnthropic: TsgcHTTP_API_Anthropic;
begin
  oAnthropic := TsgcHTTP_API_Anthropic.Create(nil);
  try
    oAnthropic.AnthropicOptions.ApiKey := GetApiKey;
    oAnthropic.AnthropicOptions.AnthropicVersion := '2023-06-01';

    // Model, prompt, max tokens
    memoAnswer.Lines.Text := oAnthropic._CreateMessage(
      'claude-sonnet-4-20250514',
      'Summarise RFC 6455 in three bullet points.', 1024);
  finally
    oAnthropic.Free;
  end;
end;

Claude verlangt den API-Versions-Header, setze also AnthropicVersion zusätzlich zum Schlüssel. _CreateMessageWithSystem ergänzt einen System-Prompt, und _CountTokens bepreist einen Prompt, bevor du ihn abschickst.

uOllama.pas
uses
  Classes, SysUtils,
  // sgc
  sgcHTTP_API_Ollama;

var
  oOllama: TsgcHTTP_API_Ollama;
begin
  oOllama := TsgcHTTP_API_Ollama.Create(nil);
  try
    // Local server, no API key required
    oOllama.OllamaOptions.Host := 'http://localhost:11434';

    // Which models are pulled on this machine?
    memoModels.Lines.Text := oOllama._GetTags;

    memoAnswer.Lines.Text := oOllama._CreateMessage(
      'llama3', 'Summarise this invoice in one line.');
  finally
    oOllama.Free;
  end;
end;

Host zeigt standardmäßig auf http://localhost:11434, bei einer Standardinstallation kannst du es also so lassen. _PullModel lädt ein Modell herunter, _GetTags listet auf, was schon auf der Platte liegt, und _ShowModel liest die Details.

Die Antwort zeigen, während sie entsteht

Ein einmaliger Aufruf blockiert, bis das Modell fertig ist, was sich bei einer langen Antwort kaputt anfühlt. Streaming liefert die Antwort in Fragmenten, Text erscheint also in deinem Memo, während das Modell noch denkt. An dieser Stelle hängen die meisten fest, deshalb hier beide Ebenen davon.

Mit TsgcAIChat, Deltas bereits dekodiert

Rufe ChatStream statt Chat auf und behandle OnChatStream. Die Komponente fordert beim Anbieter eine gestreamte Antwort an, parst jedes Server-Sent Event und übergibt dir aChunk, also den neuen Text und sonst nichts. Du hängst ihn an, und das ist die ganze Implementierung.

Jeder Anbieter streamt eine andere JSON-Form. OpenAI, DeepSeek, Ollama, Grok und Mistral legen den Text in choices[0].delta.content, Claude in delta.text, Gemini noch tiefer in candidates. TsgcAIChat weiß bereits, welche davon für den gewählten Anbieter gilt, dein Handler sieht also nie JSON.

Setze Cancel im Handler auf True, um eine ausufernde Antwort zu stoppen. Die Anfrage wird an dieser Stelle abgebrochen, weitere Chunks kommen nicht mehr an. Wenn der Stream endet, wird der zusammengesetzte Text dem Verlauf hinzugefügt und von ChatStream zurückgegeben, und OnChatMessage wird einmal mit der vollständigen Antwort ausgelöst.

uChatStream.pas
procedure TfrmMain.btnStreamClick(Sender: TObject);
begin
  FChat.Provider := aicpAnthropic;
  FChat.ChatOptions.ApiKey := GetApiKey;
  FChat.ChatOptions.Model := 'claude-sonnet-4-20250514';
  FChat.OnChatStream := OnChatStream;
  FChat.OnChatError := OnChatError;

  memoAnswer.Lines.Clear;
  FChat.ChatStream(memoPrompt.Lines.Text);
end;

procedure TfrmMain.OnChatStream(Sender: TObject;
  const aChunk: string; var Cancel: Boolean);
begin
  memoAnswer.Text := memoAnswer.Text + aChunk;
  Cancel := FUserPressedStop;
end;

procedure TfrmMain.OnChatError(Sender: TObject;
  const aError: string);
begin
  memoAnswer.Lines.Add('ERROR: ' + aError);
end;

Mit einem Hersteller-Client, rohe Ereignisse

Die REST-Clients streamen ebenfalls. Weise OnHTTPAPISSE zu und rufe die Streaming-Abkürzung auf: _CreateMessageStream bei Claude und bei Ollama, und bei OpenAI ein TsgcOpenAIClass_Request_ChatCompletion mit Stream auf True gesetzt. Das Ereignis gibt dir aEvent, den Namen des Server-Sent Event, und aData, die Nutzlast dieses Ereignisses, genau so, wie der Hersteller sie geschickt hat.

Auf dieser Ebene parst du das JSON selbst, und genau darum geht es: Du siehst Tool-Call-Deltas, Stoppgründe, Nutzungsdaten und alles andere, was der Hersteller auf die Leitung legt. Teilweise Netzwerklesevorgänge sind bereits für dich zusammengesetzt, ein Ereignis, das über zwei TCP-Lesevorgänge verteilt ist, kommt also vollständig an, und Ollamas zeilengetrenntes JSON wird über dasselbe Ereignis geliefert.

Die Abschlusskennungen unterscheiden sich je Hersteller. OpenAI schließt mit dem Literal [DONE], Claude mit einem Ereignis namens message_stop. Behandle beide, wenn dein Code beide anspricht.

uRawStream.pas
procedure TfrmMain.FormCreate(Sender: TObject);
begin
  FAnthropic := TsgcHTTP_API_Anthropic.Create(nil);
  FAnthropic.AnthropicOptions.ApiKey := GetApiKey;
  FAnthropic.AnthropicOptions.AnthropicVersion := '2023-06-01';
  FAnthropic.OnHTTPAPISSE := HandleSSE;
  FAnthropic.OnHTTPAPIException := HandleException;
end;

procedure TfrmMain.btnStreamClick(Sender: TObject);
begin
  memoRaw.Lines.Clear;
  FAnthropic._CreateMessageStream(
    'claude-sonnet-4-20250514',
    'Write a haiku about Object Pascal.', 1024);
end;

procedure TfrmMain.HandleSSE(Sender: TObject;
  const aEvent, aData: string; var Cancel: Boolean);
begin
  if (aEvent = 'message_stop') or (aData = '[DONE]') then
    Exit;
  memoRaw.Lines.Add(aEvent + ': ' + aData);
end;

procedure TfrmMain.HandleException(Sender: TObject;
  E: Exception);
begin
  memoRaw.Lines.Add('ERROR: ' + E.Message);
end;

Threads. Chat und ChatStream sind synchron, ein Aufruf direkt aus einem Button-Klick friert das Formular also für die Dauer der Anfrage ein. Ab Delphi 2010 führt ChatAsync den Aufruf auf einem Worker-Thread aus und gibt ein IsgcFuture<string> zurück. Verkette ThenProc für das Ergebnis und OnError für Fehler, und rufe Cancel auf, um eine laufende Anfrage abzubrechen. Der Callback ThenProc wird im Haupt-Thread ausgeführt, du kannst die UI daraus also direkt anfassen.

Lass das Modell deinen Pascal-Code aufrufen

Tool Calling, auch Function Calling genannt, ist der Weg, auf dem ein Modell deine Anwendung bittet, etwas nachzuschlagen oder eine Aktion auszuführen. Du beschreibst die Funktion mit einem JSON Schema, das Modell antwortet mit den gewünschten Argumenten, du führst den Pascal-Code aus und schickst das Ergebnis zurück. Das ist der Mechanismus hinter jedem nützlichen Assistenten in einer Fachanwendung.

Claude, mit typisierten Tool-Objekten

Baue ein TsgcAnthropicClass_Request_Messages, hänge einen oder mehrere Einträge TsgcAnthropicClass_Request_Tool an und rufe CreateMessage auf. Jedes Tool trägt einen Name, eine Description und ein InputSchema, also das JSON Schema für seine Argumente.

Die Antwort ist ein TsgcAnthropicClass_Response_Messages, dessen Content ein Array von Blöcken ist. Ein Block, dessen ContentType gleich 'tool_use' ist, trägt den Tool-Namen in Name, die Argumente in Input und eine Id. Führe deine Funktion aus und schicke dann eine Folgenachricht mit einem TsgcAnthropicClass_Request_Content_Block mit ContentType gesetzt auf 'tool_result', derselben ToolUseId und deiner Antwort in Content. Setze IsError, wenn der Aufruf fehlgeschlagen ist, damit das Modell sich fangen kann, statt zu raten.

Achte auf die Besitzverhältnisse: Die Anthropic-Anfrage besitzt die angehängten Nachrichten und Tools nicht, gib sie also selbst frei, wie im Beispiel.

uToolUse.pas
var
  oRequest: TsgcAnthropicClass_Request_Messages;
  oMessage: TsgcAnthropicClass_Request_Message;
  oTool: TsgcAnthropicClass_Request_Tool;
  oMessages: TsgcAnthropicArray_Request_Messages;
  oTools: TsgcAnthropicArray_Request_Tools;
  oResponse: TsgcAnthropicClass_Response_Messages;
  i: Integer;
begin
  oRequest := TsgcAnthropicClass_Request_Messages.Create;
  try
    oRequest.Model := 'claude-sonnet-4-20250514';
    oRequest.MaxTokens := 4096;

    oMessage := TsgcAnthropicClass_Request_Message.Create;
    oMessage.Role := 'user';
    oMessage.Content := 'What is the stock of SKU 8841?';
    SetLength(oMessages, 1);
    oMessages[0] := oMessage;
    oRequest.Messages := oMessages;

    oTool := TsgcAnthropicClass_Request_Tool.Create;
    oTool.Name := 'get_stock';
    oTool.Description := 'Read the on-hand stock for a SKU';
    oTool.InputSchema :=
      '{"type":"object","properties":{"sku":{"type":"string",' +
      '"description":"The product code"}},"required":["sku"]}';
    SetLength(oTools, 1);
    oTools[0] := oTool;
    oRequest.Tools := oTools;

    oResponse := FAnthropic.CreateMessage(oRequest);
    try
      for i := 0 to Length(oResponse.Content) - 1 do
        if oResponse.Content[i].ContentType = 'tool_use' then
          // .Name is the tool, .Input the JSON arguments,
          // .Id the value to echo back as ToolUseId
          RunTool(oResponse.Content[i].Name,
            oResponse.Content[i].Input, oResponse.Content[i].Id)
        else if oResponse.Content[i].ContentType = 'text' then
          memoAnswer.Lines.Add(oResponse.Content[i].Text);
    finally
      oResponse.Free;
    end;
  finally
    sgcFree(oMessage);
    sgcFree(oTool);
    sgcFree(oRequest);
  end;
end;

OpenAI, mit einer typisierten Anfrage

Dieselbe Idee, andere Form. Fülle ein TsgcOpenAIClass_Request_ChatCompletion, weise das Array Messages zu, lege deine Tool-Definitionen als JSON-Array in Tools und steuere das Modell optional mit ToolChoice. ParallelToolCalls steuert, ob das Modell mehrere Tools auf einmal anfordern darf, und ResponseFormat zwingt die Antwort auf JSON, wenn du sie parsen musst.

CreateChatCompletion gibt ein geparstes TsgcOpenAIClass_Response_ChatCompletion zurück. Lies die Antwort aus Choices[0]._Message.Content, die angeforderten Aufrufe aus Choices[0]._Message.ToolCalls, den Grund für den Stopp aus Choices[0].FinishReason, und die Kosten aus Usage.PromptTokens, Usage.CompletionTokens und Usage.TotalTokens. Anders als die Anthropic-Anfrage besitzt diese die angehängten Nachrichtenobjekte und gibt sie mit sich selbst frei.

Die älteren Eigenschaften Functions und FunctionCall gibt es weiterhin, für Code, der gegen die ursprüngliche OpenAI-Form des Function Calling geschrieben wurde.

uTypedRequest.pas
var
  oRequest: TsgcOpenAIClass_Request_ChatCompletion;
  oResponse: TsgcOpenAIClass_Response_ChatCompletion;
  oSystem, oUser: TsgcOpenAIClass_Request_Completion_Message;
  oMessages: TsgcOpenAIArray_Request_Completion_Messages;
begin
  oRequest := TsgcOpenAIClass_Request_ChatCompletion.Create;
  try
    oRequest.Model := 'gpt-4o';
    oRequest.MaxTokens := 1024;
    oRequest.Temperature := 0.2;

    oSystem := TsgcOpenAIClass_Request_Completion_Message.Create;
    oSystem.Role := 'system';
    oSystem.Content := 'You are a warehouse assistant.';

    oUser := TsgcOpenAIClass_Request_Completion_Message.Create;
    oUser.Role := 'user';
    oUser.Content := 'What is the stock of SKU 8841?';

    SetLength(oMessages, 2);
    oMessages[0] := oSystem;
    oMessages[1] := oUser;
    oRequest.Messages := oMessages;

    // Tool definitions as a JSON array
    oRequest.Tools :=
      '[{"type":"function","function":{"name":"get_stock",' +
      '"description":"Read the on-hand stock for a SKU",' +
      '"parameters":{"type":"object","properties":' +
      '{"sku":{"type":"string"}},"required":["sku"]}}}]';
    oRequest.ToolChoice := 'auto';

    oResponse := FOpenAI.CreateChatCompletion(oRequest);
    try
      if Length(oResponse.Choices) > 0 then
      begin
        memoAnswer.Lines.Text := oResponse.Choices[0]._Message.Content;
        memoTools.Lines.Text := oResponse.Choices[0]._Message.ToolCalls;
        lblStop.Caption := oResponse.Choices[0].FinishReason;
      end;
      lblTokens.Caption := IntToStr(oResponse.Usage.TotalTokens);
    finally
      oResponse.Free;
    end;
  finally
    // frees the attached Messages too
    oRequest.Free;
  end;
end;

Gehostetes Modell oder lokales Modell

Wenn deine Prompts Kundendaten, medizinische Daten, Verträge oder irgendetwas enthalten, das unter einen Auftragsverarbeitungsvertrag fällt, ist das keine Performancefrage, sondern eine Compliance-Frage. Hier ist der Vergleich.

Gehostet, OpenAI oder Claude Lokal, Ollama
Wohin der Prompt geht Zum Hersteller, über HTTPS, unter dessen Bedingungen Nirgendwohin. Die Anfrage geht an http://localhost:11434
Zugangsdaten Ein API-Schlüssel, den du aus der Versionsverwaltung und aus der Binärdatei heraushalten musst Standardmäßig keine. OllamaOptions.ApiKey gibt es für eine Instanz hinter einem Proxy oder auf einem entfernten Host
Antwortqualität Die stärksten heute verfügbaren Modelle Gut und besser werdend, bei schwerem Reasoning deutlich hinter der Spitze
Kosten Pro Token, dauerhaft. Im Blick behalten: Usage.TotalTokens Deine Hardware, einmalig. Ein brauchbares Modell will viel RAM oder eine GPU
Latenz Ein Netzwerk-Roundtrip, dazu Warteschlangen beim Hersteller zu Stoßzeiten Kein Netzwerk. Das Tempo ist das, was dein Rechner hergibt
Offline und ohne Netzanbindung Nein Ja
Rate Limits und Ausfälle Beim Hersteller. Nutze RetryOptions und beachte Retry-After Nur deine eigene Kapazität
Komponente TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic TsgcHTTP_API_Ollama

Eine häufige Antwort ist: beides. Weil TsgcAIChat jeden Anbieter hinter eine API stellt, kannst du zur Laufzeit nach Datenklassifizierung routen: lokal für alles, was einen Kundendatensatz berührt, gehostet für den Rest. Der Umschalter ist Provider, dazu ChatOptions.BaseUrl, wenn der Anbieter Ollama ist.

if aContainsPersonalData then
begin
  FChat.Provider := aicpOllama;
  FChat.ChatOptions.BaseUrl := 'http://localhost:11434';
  FChat.ChatOptions.Model := 'llama3';
end
else
begin
  FChat.Provider := aicpOpenAI;
  FChat.ChatOptions.ApiKey := GetApiKey;
  FChat.ChatOptions.Model := 'gpt-4o-mini';
end;

memoAnswer.Lines.Text := FChat.Chat(memoPrompt.Lines.Text);

Die Einstellungen, die im Produktivbetrieb zählen

Eine Demo, die auf deinem Schreibtisch läuft, ist nicht dasselbe wie ein Client, der ein Rate Limit, ein langsames Modell und ein Supportticket mit dem Text "es hat einfach aufgehört" übersteht.

Wiederholungen und Backoff

Jeder Client trägt einen Block RetryOptions: Enabled, Retries, Wait, Multiplier, MaxInterval, Jitter und HonorRetryAfter. Schalte ihn ein, und ein vorübergehender Fehler wird mit exponentiellem Backoff wiederholt, statt als Exception aufzutauchen. HonorRetryAfter bringt den Client dazu, den Header Retry-After des Herstellers zu befolgen, statt zu raten.

Timeouts

HttpOptions.ReadTimeout ist der Wert, den du erhöhen solltest. Eine lange Generierung, besonders bei einem lokalen Modell, kann ein Standard-HTTP-Read-Timeout überdauern und mitten in einer bis dahin guten Antwort scheitern.

Logging

LogOptions.Enabled zusammen mit LogOptions.FileName schreibt den Datenverkehr in eine Datei. Wenn sich ein Prompt im Produktivbetrieb anders verhält, ist das der schnellste Weg, das JSON zu sehen, das dein Code tatsächlich geschickt hat.

Gesprächsverlauf

TsgcAIChat hält den Austausch fest und spielt ihn beim nächsten Aufruf wieder ein, das ist es, was eine Rückfrage funktionieren lässt. Begrenze ihn mit MaxHistoryMessages, damit eine lange Sitzung den Prompt und damit die Rechnung nicht unbegrenzt wachsen lässt. ClearHistory fängt neu an, und GetHistory legt Count und die einzelnen Nachrichten offen.

Azure OpenAI

Setze OpenAIOptions.Provider auf oapvAzure und fülle AzureOptions.ResourceName, AzureOptions.DeploymentId und AzureOptions.APIVersion. Der Rest deines Codes bleibt unverändert, und das zählt, wenn der Einkauf darauf besteht, dass der Datenverkehr in deinem Azure-Tenant bleibt.

Fehler und Circuit Breaking

OnHTTPAPIException bringt Fehler der REST-Clients zum Vorschein, und OnChatError tut dasselbe für TsgcAIChat. Ein HTTP-Fehler kommt als EsgcHTTPAPIProtocolException an, die weiterhin von EIdHTTPProtocolException abstammt und zusätzlich die Antwort-Header trägt. CircuitBreaker und RateLimit stehen am Client für die Aufrufe bereit, die du selbst machst.

Was Leute nach dem ersten Aufruf bauen

Ein Chatfenster ist der Anfang. Das sind die vier Richtungen, die diese Arbeit meist nimmt, und jede davon steckt bereits in der Bibliothek.

Aus deinen eigenen Daten antworten

Verwandle deine Dokumente mit TsgcAIOpenAIEmbeddings in Vektoren, speichere sie in TsgcAIDatabaseVectorFile oder TsgcAIDatabaseVectorPinecone und hole die nächstliegenden Passagen für den Prompt. Das ist Retrieval Augmented Generation, und so verhinderst du, dass das Modell Antworten über dein Geschäft erfindet.

Embeddings und Vektordatenbanken

Sprich mit ihm, und lass es zurücksprechen

TsgcAIOpenAIChatBot verdrahtet Aufnahme, Transkription, den Chat-Aufruf und Text-to-Speech in einer Komponente, sodass jemand ein gesprochenes Gespräch mit deiner Anwendung führen kann. TsgcAIOpenAITranslator tut dasselbe für Live-Übersetzung.

KI-ChatBot und KI-Übersetzer

Deine App einem KI-Agenten zugänglich machen

Das Model Context Protocol ist der Weg, auf dem Assistenten Tools finden und aufrufen. TsgcWSServer_API_MCP macht aus deiner Delphi-Anwendung einen MCP-Server, den Claude und andere Clients steuern können, und TsgcWSAPI_Client_MCP nutzt andere Server aus deinem Code heraus. Auf der Palette erscheinen sie als TsgcWSAPIServer_MCP und TsgcWSAPIClient_MCP.

Gut zu wissen: Anders als die Chat-Komponente sind die MCP-Units nicht auf Windows beschränkt, ein in Delphi geschriebener MCP-Server kann also unter Linux laufen.

MCP-Übersicht, MCP-Server und MCP-Client

Den Rest der jeweiligen Hersteller-API nutzen

Bildgenerierung, Transkription, Moderation, Batches und Fine-Tuning bei OpenAI. Vision, Dokumente, Extended Thinking, Websuche und Token-Zählung bei Claude. Embeddings und Modellverwaltung bei Ollama. Jede Herstellerseite führt auf, was ihr Client bietet.

OpenAI, Claude und Ollama

Referenz, Demos und Tutorials

Die Komponentenreferenz dokumentiert jede Eigenschaft und jedes Ereignis. Lauffähige Demoprojekte liegen in der Bibliothek unter Demos\AI.

Referenz, OpenAI-Client Jede Methode, Option und jedes Ereignis von TsgcHTTP_API_OpenAI.
Referenz, Anthropic-Client Nachrichten, Tools, Vision, Batches und Token-Zählung bei TsgcHTTP_API_Anthropic.
Tutorial, Claude aus Delphi Die ausführliche Durchsprache des Anthropic-Clients, von Anfang bis Ende.
Tutorial, lokale Modelle mit Ollama Ein Modell ziehen, den Client auf localhost richten und offline betreiben.
Tutorial, Function Calling Ein Modell Schritt für Schritt mit deinen eigenen Pascal-Funktionen verdrahten.
Benutzerhandbuch (PDF) Umfassendes Handbuch zu jeder Komponente der Bibliothek.

Weiterlesen: der OpenAI-Client aus Delphi, einen KI-Chatbot bauen, einen KI-Agenten bauen und der MCP-Client. Die Komponentenseiten sind Delphi OpenAI-Client und Anthropic API.

Diese Seite ist einer der Delphi-Anwendungsfälle, die jeweils eine einzelne Aufgabe von Anfang bis Ende durchgehen. Die anderen bisher sind eine Anmeldung mit OAuth2 und PKCE und zwei Anwendungen per WebRTC Peer-to-Peer verbinden.

Häufige Fragen

Erzeuge ein TsgcAI_Chat aus der Unit sgcAI_Chat, setze Provider auf den gewünschten Hersteller, setze ChatOptions.ApiKey und ChatOptions.Model und rufe dann Chat('your prompt') auf, das die Antwort als String zurückgibt. Wenn du lieber direkt mit einer Hersteller-API sprichst, nimm TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic oder TsgcHTTP_API_Ollama und rufe _CreateChatCompletion oder _CreateMessage auf. Beide Wege stecken in sgcWebSockets und im eigenständigen Paket sgcAI, und sie funktionieren von Delphi 7 bis RAD Studio 13.
Rufe ChatStream statt Chat auf und behandle OnChatStream, das mit aChunk ausgelöst wird, dem dekodierten Text jedes Deltas, und mit einem Flag Cancel, das du setzen kannst, um früh abzubrechen. Auf Ebene der REST-Clients weist du OnHTTPAPISSE zu und rufst _CreateMessageStream an den Claude- und Ollama-Clients auf, oder du setzt Stream auf True an einem TsgcOpenAIClass_Request_ChatCompletion. Dieses Ereignis gibt dir Name und Daten des rohen Server-Sent Event, wobei teilweise Netzwerklesevorgänge bereits zusammengesetzt sind.
Ja. Installiere Ollama, zieh ein Modell und richte dann TsgcHTTP_API_Ollama darauf. OllamaOptions.Host zeigt bereits standardmäßig auf http://localhost:11434, bei einer Standardinstallation wählst du also nur ein Modell und rufst _CreateMessage auf. Nichts verlässt den Rechner, es wird kein API-Schlüssel gebraucht, und die Anwendung funktioniert offline. Über TsgcAIChat erreichst du denselben Server, indem du Provider auf aicpOllama setzt und, wenn der Server nicht auf localhost läuft, ChatOptions.BaseUrl angibst.
Beschreibe die Funktion mit einem JSON Schema und hänge es an die Anfrage. Bei Claude fügst du ein TsgcAnthropicClass_Request_Tool mit Name, Description und InputSchema dem Array Tools eines TsgcAnthropicClass_Request_Messages hinzu. Die Antwort enthält dann einen Content-Block, dessen ContentType gleich tool_use ist und der Name, Input und Id trägt, und du antwortest mit einem Block tool_result, der dieselbe ToolUseId zitiert. Bei OpenAI legst du die Definitionen in die Eigenschaft Tools eines TsgcOpenAIClass_Request_ChatCompletion und liest die angeforderten Aufrufe aus Choices[0]._Message.ToolCalls.
Die KI- und LLM-Clients sind eine Funktion der Edition Enterprise von sgcWebSockets. In den Editionen Standard und Professional sind sie nicht enthalten. Wenn du den Rest von sgcWebSockets nicht brauchst, enthält das eigenständige Paket sgcAI dieselben Komponenten samt der Runtime, die sie benötigen. Die Bibliothek unterstützt Delphi 7 bis RAD Studio 13 und die passenden C++-Builder-Versionen. Zu den Plattformen: Die REST-Clients TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic und TsgcHTTP_API_Ollama kompilieren für Windows, macOS, Linux, iOS und Android, während TsgcAIChat nur für Windows kompiliert wird, Win32 und Win64. Der MCP-Client und -Server sind ebenfalls nicht auf Windows beschränkt.
Bei gehosteten Anbietern ja. Die Komponenten sind REST-Clients, du bringst also einen Schlüssel aus deinem eigenen Konto bei OpenAI, Anthropic, Google, xAI, DeepSeek oder Mistral mit und weist ihn ChatOptions.ApiKey zu, oder den Herstelleroptionen wie OpenAIOptions.ApiKey. Die Nutzung rechnet der Hersteller gegen deinen Schlüssel ab, und du kannst sie je Antwort über Usage.PromptTokens, Usage.CompletionTokens und Usage.TotalTokens verfolgen. Ollama braucht keinen Schlüssel, weil das Modell lokal läuft.
Chat und ChatStream sind synchron. Ab Delphi 2010 rufst du stattdessen ChatAsync auf: Es führt die Anfrage auf einem Worker-Thread aus und gibt ein IsgcFuture of string zurück, du verkettest also ThenProc, um die Antwort zu bekommen, OnError, um eine Exception zu bekommen, und Cancel, um eine laufende Anfrage abzubrechen. Der Callback ThenProc wird im Haupt-Thread ausgeführt, du kannst daraus also gefahrlos die UI aktualisieren. Erhöhe außerdem HttpOptions.ReadTimeout, weil eine lange Generierung ein Standard-Read-Timeout überdauern kann.
Ja. Setze OpenAIOptions.Provider auf oapvAzure und fülle AzureOptions.ResourceName, AzureOptions.DeploymentId und AzureOptions.APIVersion. Der Client zielt dann auf dein Azure-Deployment, und die Aufrufe, die du bereits geschrieben hast, bleiben genau gleich.

Bereit, ein LLM aus deiner Delphi-App aufzurufen?

Lade die kostenlose Testversion herunter und mach heute deinen ersten Aufruf.