Chiamare un LLM da Delphi

Invia un prompt da un'applicazione VCL, FMX o console e ottieni una risposta, da un modello ospitato come OpenAI o Anthropic Claude, oppure da un modello in esecuzione sulla tua macchina tramite Ollama. Questa pagina ti porta da un form vuoto a una chiamata funzionante, e poi alle tre cose che ogni progetto incontra subito dopo: lo streaming, il tool calling e la scelta tra un modello ospitato e uno locale.

OpenAI, Claude, Gemini, Grok, DeepSeek, Mistral, Ollama
Streaming tramite Server-Sent Events
Da Delphi 7 a RAD Studio 13

Due modi per effettuare la chiamata

C'è un componente di chat indipendente dal provider e c'è un client REST dedicato per ogni fornitore. Entrambi fanno parte della stessa libreria, quindi puoi iniziare con uno e scendere all'altro senza cambiare progetto.

TsgcAIChat, un'unica API per ogni provider

Imposta Provider, una chiave API e un modello, poi chiama Chat. Il componente costruisce il JSON del fornitore, conserva la cronologia della conversazione e restituisce il testo dell'assistente. Passare da OpenAI a Claude, o a un modello Ollama locale, è una sola assegnazione. È implementato da TsgcAI_Chat nell'unit sgcAI_Chat e registrato nella palette come TsgcAIChat.

I client REST per singolo fornitore

TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic e TsgcHTTP_API_Ollama espongono per intero l'API di ciascun fornitore, comprese le parti che nessuno strato neutrale può coprire: input di immagini, input di documenti, extended thinking, batch, file, embeddings, generazione di immagini e trascrizione. Usali quando ti serve un endpoint specifico.

Edizione e piattaforma

I client AI e LLM sono una funzionalità Enterprise di sgcWebSockets, non Standard e non Professional, oppure puoi acquistare il pacchetto autonomo sgcAI.

Qui la piattaforma conta. I tre client REST si compilano su Windows, macOS, Linux, iOS e Android. TsgcAIChat no: è compilato solo per Windows, quindi in un servizio Linux, in una build macOS o su un target mobile chiami direttamente il client REST. Gli esempi di questa pagina sono scritti in modo che funzionino entrambe le strade.

La tua prima chiamata, in una decina di righe

Trascina il componente, imposta una chiave e un modello, invia un prompt. Scegli la scheda del provider da cui vuoi partire. L'ultima scheda non richiede alcuna chiave API, perché il modello gira sulla tua macchina.

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;

Cambiare fornitore è una sola riga. Provider accetta aicpOpenAI, aicpAnthropic, aicpGemini, aicpDeepSeek, aicpOllama, aicpGrok e aicpMistral. Tutto il resto del tuo codice resta dov'è.

Solo Windows. TsgcAI_Chat e il suo componente di palette TsgcAIChat sono compilati per Windows, Win32 e Win64. Su macOS, Linux, iOS e Android l'unit non viene compilata affatto, quindi se il tuo target è un servizio Linux o un'app mobile, usa i client REST dei fornitori nelle altre tre schede. Quelli non hanno restrizioni di piattaforma.

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;

I metodi con l'underscore sono scorciatoie stringa che restituiscono il corpo grezzo della risposta. Quando vuoi un oggetto già interpretato, costruisci un TsgcOpenAIClass_Request_ChatCompletion e chiama CreateChatCompletion, mostrato più avanti in questa pagina.

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 richiede l'header con la versione dell'API, quindi imposta AnthropicVersion insieme alla chiave. _CreateMessageWithSystem aggiunge un system prompt e _CountTokens calcola il costo di un prompt prima di inviarlo.

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 vale per impostazione predefinita http://localhost:11434, quindi con un'installazione standard puoi lasciarlo così com'è. _PullModel scarica un modello, _GetTags elenca ciò che è già su disco e _ShowModel ne legge i dettagli.

Mostra la risposta mentre viene scritta

Una chiamata one-shot resta bloccata finché il modello non ha finito, e su una risposta lunga sembra che qualcosa non funzioni. Lo streaming consegna la risposta a frammenti, così il testo compare nella tua memo mentre il modello sta ancora ragionando. È la parte su cui la maggior parte delle persone si blocca, quindi qui trovi entrambi i livelli.

Con TsgcAIChat, delta già decodificati

Chiama ChatStream invece di Chat e gestisci OnChatStream. Il componente chiede al provider una risposta in streaming, interpreta ogni Server-Sent Event e ti passa aChunk, che è il testo nuovo e nient'altro. Tu lo accodi, e l'implementazione finisce qui.

Ogni provider trasmette in streaming una forma JSON diversa. OpenAI, DeepSeek, Ollama, Grok e Mistral mettono il testo in choices[0].delta.content, Claude in delta.text, Gemini ancora più in profondità dentro candidates. TsgcAIChat sa già quale si applica al provider che hai selezionato, quindi il tuo handler non vede mai il JSON.

Imposta Cancel a True dentro l'handler per fermare una risposta fuori controllo. A quel punto la richiesta viene abbandonata e non arrivano altri chunk. Quando lo stream termina, il testo assemblato viene aggiunto alla cronologia e restituito da ChatStream, e OnChatMessage scatta una volta con la risposta completa.

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;

Con un client del fornitore, eventi grezzi

Anche i client REST fanno streaming. Assegna OnHTTPAPISSE e chiama la scorciatoia di streaming: _CreateMessageStream su Claude e su Ollama, e su OpenAI un TsgcOpenAIClass_Request_ChatCompletion con Stream impostato a True. L'evento ti dà aEvent, il nome del Server-Sent Event, e aData, il payload di quell'evento, esattamente come lo ha inviato il fornitore.

A questo livello interpreti tu stesso il JSON, ed è proprio questo il punto: vedi i delta delle chiamate ai tool, i motivi di arresto, i record di utilizzo e qualsiasi altra cosa il fornitore metta sul filo. Le letture di rete parziali sono già riassemblate per te, quindi un evento spezzato su due letture TCP arriva comunque intero, e il JSON delimitato da newline di Ollama viene consegnato attraverso lo stesso evento.

I terminatori cambiano da fornitore a fornitore. OpenAI chiude con il letterale [DONE], Claude con un evento chiamato message_stop. Gestiscili entrambi se il tuo codice li supporta entrambi.

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;

Thread. Chat e ChatStream sono sincroni, quindi chiamarli direttamente dal clic di un pulsante congela il form per tutta la durata della richiesta. Su Delphi 2010 e successivi, ChatAsync esegue la chiamata su un thread di lavoro e restituisce un IsgcFuture<string>. Concatena ThenProc per il risultato e OnError per gli errori, e chiama Cancel per abbandonare una richiesta in corso. La callback ThenProc viene eseguita sul thread principale, quindi puoi toccare la UI direttamente da lì.

Lascia che sia il modello a chiamare il tuo codice Pascal

Il tool calling, chiamato anche function calling, è il modo in cui un modello chiede alla tua applicazione di cercare qualcosa o di eseguire un'azione. Descrivi la funzione con un JSON Schema, il modello risponde con gli argomenti che vuole, tu esegui il codice Pascal e rimandi indietro il risultato. È il meccanismo dietro ogni assistente utile all'interno di un'applicazione gestionale.

Claude, con oggetti tool tipizzati

Costruisci un TsgcAnthropicClass_Request_Messages, allega una o più voci TsgcAnthropicClass_Request_Tool e chiama CreateMessage. Ogni tool porta con sé un Name, una Description e un InputSchema, che è il JSON Schema dei suoi argomenti.

La risposta è un TsgcAnthropicClass_Response_Messages il cui Content è un array di blocchi. Un blocco con ContentType uguale a 'tool_use' porta il Name del tool, gli argomenti in Input e un Id. Esegui la tua funzione, poi invia un messaggio successivo che contiene un TsgcAnthropicClass_Request_Content_Block con ContentType impostato a 'tool_result', lo stesso ToolUseId e la tua risposta in Content. Imposta IsError quando la chiamata è fallita, così il modello può recuperare invece di tirare a indovinare.

Attenzione alla proprietà degli oggetti: la richiesta Anthropic non possiede i messaggi e i tool che le alleghi, quindi liberali tu, come nell'esempio.

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, con una richiesta tipizzata

Stessa idea, forma diversa. Riempi un TsgcOpenAIClass_Request_ChatCompletion, assegna l'array Messages, metti le definizioni dei tuoi tool in Tools come array JSON e, se vuoi, guida il modello con ToolChoice. ParallelToolCalls controlla se il modello può chiedere più tool contemporaneamente, e ResponseFormat vincola la risposta al JSON quando devi interpretarla.

CreateChatCompletion restituisce un TsgcOpenAIClass_Response_ChatCompletion già interpretato. Leggi la risposta da Choices[0]._Message.Content, le chiamate richieste da Choices[0]._Message.ToolCalls, il motivo per cui il modello si è fermato da Choices[0].FinishReason e quanto è costata da Usage.PromptTokens, Usage.CompletionTokens e Usage.TotalTokens. A differenza della richiesta Anthropic, questa possiede gli oggetti messaggio che le alleghi e li libera insieme a sé.

Le vecchie proprietà Functions e FunctionCall sono ancora presenti per il codice scritto sulla forma originale del function calling di OpenAI.

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;

Modello ospitato o modello locale

Se i tuoi prompt contengono dati di clienti, dati sanitari, contratti o qualsiasi cosa coperta da un accordo sul trattamento dei dati, questa non è una questione di prestazioni, è una questione di conformità. Ecco il confronto.

Ospitato, OpenAI o Claude Locale, Ollama
Dove va il prompt Al fornitore, via HTTPS, secondo le sue condizioni Da nessuna parte. La richiesta va a http://localhost:11434
Credenziali Una chiave API che devi tenere fuori dal controllo di versione e fuori dal binario Nessuna per impostazione predefinita. OllamaOptions.ApiKey esiste per un'istanza remota o dietro proxy
Qualità della risposta I modelli più potenti disponibili oggi Buona e in miglioramento, chiaramente dietro alla frontiera sui ragionamenti difficili
Costo A token, per sempre. Tieni d'occhio Usage.TotalTokens Il tuo hardware, una volta sola. Un modello utile vuole molta RAM o una GPU
Latenza Un round trip di rete, più le code del fornitore nei momenti di traffico Nessuna rete. La velocità è quella della tua macchina
Offline e air-gapped No
Limiti di frequenza e disservizi Lato fornitore. Usa RetryOptions e rispetta Retry-After Solo la tua capacità
Componente TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic TsgcHTTP_API_Ollama

Una risposta frequente è entrambi. Poiché TsgcAIChat mette ogni provider dietro un'unica API, puoi instradare in base alla classificazione dei dati a runtime: locale per tutto ciò che tocca il record di un cliente, ospitato per il resto. L'interruttore è Provider, più ChatOptions.BaseUrl quando il provider è Ollama.

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);

Le impostazioni che contano in produzione

Una demo che funziona sulla tua scrivania non è la stessa cosa di un client che sopravvive a un rate limit, a un modello lento e a un ticket di supporto che dice "si è semplicemente fermato".

Retry e backoff

Ogni client porta con sé un blocco RetryOptions: Enabled, Retries, Wait, Multiplier, MaxInterval, Jitter e HonorRetryAfter. Attivalo e un errore transitorio viene ritentato con backoff esponenziale invece di emergere come eccezione. HonorRetryAfter fa sì che il client rispetti l'header Retry-After del fornitore invece di tirare a indovinare.

Timeout

HttpOptions.ReadTimeout è quello da alzare. Una generazione lunga, soprattutto su un modello locale, può durare più del timeout di lettura HTTP predefinito e fallire a metà di una risposta che stava andando bene.

Logging

LogOptions.Enabled insieme a LogOptions.FileName scrive il traffico su un file. Quando un prompt si comporta in modo diverso in produzione, questo è il modo più rapido per vedere il JSON che il tuo codice ha effettivamente inviato.

Cronologia della conversazione

TsgcAIChat conserva lo scambio e lo ripropone alla chiamata successiva, ed è questo che fa funzionare una domanda di follow up. Limitalo con MaxHistoryMessages così una sessione lunga non fa crescere il prompt, e quindi il conto, senza limiti. ClearHistory ricomincia da capo e GetHistory espone Count e i singoli messaggi.

Azure OpenAI

Imposta OpenAIOptions.Provider a oapvAzure e compila AzureOptions.ResourceName, AzureOptions.DeploymentId e AzureOptions.APIVersion. Il resto del tuo codice resta invariato, cosa che conta quando l'ufficio acquisti pretende che il traffico resti dentro il tuo tenant Azure.

Errori e circuit breaking

OnHTTPAPIException fa emergere gli errori dei client REST, e OnChatError fa lo stesso per TsgcAIChat. Un errore HTTP arriva come EsgcHTTPAPIProtocolException, che discende ancora da EIdHTTPProtocolException e in più porta con sé gli header della risposta. CircuitBreaker e RateLimit sono disponibili sul client per le chiamate che fai tu.

Cosa si costruisce dopo la prima chiamata

Una chat box è solo l'inizio. Queste sono le quattro direzioni che questo lavoro prende di solito, e ognuna di esse è già nella libreria.

Rispondi partendo dai tuoi dati

Trasforma i tuoi documenti in vettori con TsgcAIOpenAIEmbeddings, archiviali in TsgcAIDatabaseVectorFile o TsgcAIDatabaseVectorPinecone e recupera i passaggi più vicini da inserire nel prompt. Questa è la retrieval augmented generation, ed è così che impedisci al modello di inventare risposte sulla tua azienda.

Embeddings e database vettoriali

Parlagli, e lascia che ti risponda

TsgcAIOpenAIChatBot collega in un unico componente un registratore, la trascrizione, la chiamata di chat e la sintesi vocale, così un utente può tenere una conversazione parlata con la tua applicazione. TsgcAIOpenAITranslator fa lo stesso per la traduzione dal vivo.

AI ChatBot e AI Translator

Esponi la tua app a un agente AI

Il Model Context Protocol è il modo in cui gli assistenti scoprono e chiamano i tool. TsgcWSServer_API_MCP trasforma la tua applicazione Delphi in un server MCP che Claude e altri client possono pilotare, e TsgcWSAPI_Client_MCP consuma altri server dal tuo codice. Nella palette compaiono come TsgcWSAPIServer_MCP e TsgcWSAPIClient_MCP.

Vale la pena saperlo: a differenza del componente di chat, le unit MCP non sono limitate a Windows, quindi un server MCP scritto in Delphi può girare su Linux.

Panoramica MCP, server MCP e client MCP

Usa il resto dell'API di ogni fornitore

Generazione di immagini, trascrizione, moderazione, batch e fine tuning su OpenAI. Vision, documenti, extended thinking, ricerca web e conteggio dei token su Claude. Embeddings e gestione dei modelli su Ollama. La pagina di ogni fornitore elenca ciò che il suo client espone.

OpenAI, Claude e Ollama

Reference, demo e tutorial

Il reference dei componenti documenta ogni proprietà ed evento. I progetti demo pronti all'uso sono inclusi nella libreria, sotto Demos\AI.

Reference, client OpenAI Ogni metodo, opzione ed evento di TsgcHTTP_API_OpenAI.
Reference, client Anthropic Messaggi, tool, vision, batch e conteggio dei token su TsgcHTTP_API_Anthropic.
Tutorial, Claude da Delphi La guida estesa al client Anthropic, dall'inizio alla fine.
Tutorial, modelli locali con Ollama Scarica un modello, punta il client su localhost ed eseguilo offline.
Tutorial, function calling Collegare un modello alle tue funzioni Pascal, passo dopo passo.
Manuale utente (PDF) Manuale completo che copre ogni componente della libreria.

Altre letture: il client OpenAI da Delphi, costruire un chatbot AI, costruire un agente AI e il client MCP. Le pagine dei componenti sono client OpenAI per Delphi e API Anthropic.

Questa pagina fa parte dei casi d'uso Delphi, ognuno dei quali affronta un singolo lavoro dall'inizio alla fine. Gli altri finora sono l'accesso di un utente con OAuth2 e PKCE e il collegamento peer to peer di due applicazioni con WebRTC.

Domande frequenti

Crea un TsgcAI_Chat dall'unit sgcAI_Chat, imposta Provider sul fornitore che vuoi, imposta ChatOptions.ApiKey e ChatOptions.Model, poi chiama Chat('your prompt'), che restituisce la risposta come stringa. Se preferisci parlare direttamente con l'API di un singolo fornitore, usa TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic o TsgcHTTP_API_Ollama e chiama _CreateChatCompletion o _CreateMessage. Entrambi gli approcci sono inclusi in sgcWebSockets e nel pacchetto autonomo sgcAI, e funzionano da Delphi 7 fino a RAD Studio 13.
Chiama ChatStream invece di Chat e gestisci OnChatStream, che scatta con aChunk, il testo decodificato di ogni delta, e un flag Cancel che puoi impostare per fermarti prima. A livello di client REST, assegna OnHTTPAPISSE e chiama _CreateMessageStream sui client Claude e Ollama, oppure imposta Stream a True su un TsgcOpenAIClass_Request_ChatCompletion. Quell'evento ti dà il nome e i dati grezzi del Server-Sent Event, con le letture di rete parziali già riassemblate.
Sì. Installa Ollama, scarica un modello, poi punta TsgcHTTP_API_Ollama su di esso. OllamaOptions.Host vale già per impostazione predefinita http://localhost:11434, quindi con un'installazione standard devi solo scegliere un modello e chiamare _CreateMessage. Nulla esce dalla macchina, non serve alcuna chiave API e l'applicazione funziona offline. Con TsgcAIChat lo stesso server si raggiunge impostando Provider su aicpOllama e, quando il server non è su localhost, ChatOptions.BaseUrl.
Descrivi la funzione con un JSON Schema e allegala alla richiesta. Su Claude, aggiungi un TsgcAnthropicClass_Request_Tool con Name, Description e InputSchema all'array Tools di un TsgcAnthropicClass_Request_Messages. La risposta contiene poi un blocco di contenuto il cui ContentType è tool_use, che porta Name, Input e Id, e tu rispondi con un blocco tool_result che cita lo stesso ToolUseId. Su OpenAI, metti le definizioni nella proprietà Tools di un TsgcOpenAIClass_Request_ChatCompletion e leggi le chiamate richieste da Choices[0]._Message.ToolCalls.
I client AI e LLM sono una funzionalità Enterprise di sgcWebSockets. Non sono inclusi nelle edizioni Standard o Professional. Se non ti serve il resto di sgcWebSockets, il pacchetto autonomo sgcAI contiene gli stessi componenti insieme al runtime di cui hanno bisogno. La libreria supporta da Delphi 7 fino a RAD Studio 13 e le versioni corrispondenti di C++ Builder. Sul fronte delle piattaforme, i client REST TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic e TsgcHTTP_API_Ollama si compilano per Windows, macOS, Linux, iOS e Android, mentre TsgcAIChat è compilato solo per Windows, Win32 e Win64. Nemmeno il client e il server MCP sono limitati a Windows.
Per i provider ospitati, sì. I componenti sono client REST, quindi porti una chiave del tuo account OpenAI, Anthropic, Google, xAI, DeepSeek o Mistral e la assegni a ChatOptions.ApiKey, oppure alle opzioni del fornitore come OpenAIOptions.ApiKey. L'utilizzo viene fatturato da quel fornitore sulla tua chiave, e puoi monitorarlo risposta per risposta tramite Usage.PromptTokens, Usage.CompletionTokens e Usage.TotalTokens. Ollama non richiede alcuna chiave, perché il modello gira in locale.
Chat e ChatStream sono sincroni. Su Delphi 2010 e successivi, chiama invece ChatAsync: esegue la richiesta su un thread di lavoro e restituisce un IsgcFuture di string, così concateni ThenProc per ricevere la risposta, OnError per ricevere un'eccezione e Cancel per abbandonare una richiesta in corso. La callback ThenProc viene eseguita sul thread principale, quindi è sicuro aggiornare la UI da lì. Alza anche HttpOptions.ReadTimeout, perché una generazione lunga può durare più del timeout di lettura predefinito.
Sì. Imposta OpenAIOptions.Provider a oapvAzure e compila AzureOptions.ResourceName, AzureOptions.DeploymentId e AzureOptions.APIVersion. Il client punta allora al tuo deployment Azure, e le chiamate che hai già scritto restano esattamente le stesse.

Pronto a chiamare un LLM dalla tua app Delphi?

Scarica la versione di prova gratuita e fai oggi stesso la tua prima chiamata.