Créer un chatbot IA en Delphi : mémoire de conversation et diffusion

· Composants

Réponse rapide : un chatbot est une complétion de discussion plus de la mémoire. sgcWebSockets fournit un composant dédié TsgcAIChat qui conserve l'historique complet des messages pour vous, de sorte que chaque tour est envoyé avec la conversation jusqu'à présent et que le modèle peut répondre en contexte. Déposez le composant, définissez la clé d'API et le modèle, puis appelez Chat pour une réponse ou ChatStream pour un effet de frappe en direct, jeton par jeton. Effacer la conversation se fait en un seul appel à ClearHistory.

Si vous avez déjà appelé un LLM depuis Delphi, vous avez probablement remarqué quelque chose de frustrant : posez une question de suivi et le modèle agit comme s'il ne vous avait jamais parlé. Ce n'est pas un bug, c'est ainsi que fonctionne une complétion ponctuelle. Transformer cela en un véritable assistant conversationnel est ce qui distingue un jouet d'un chatbot, et tout se résume à une seule idée : la mémoire.

Complétion ponctuelle vs chatbot

Une API de LLM est sans état. Chaque requête est indépendante, donc le modèle ne connaît que ce que vous mettez dans cette requête. Un appel ponctuel envoie un seul prompt :

// User: "What is the capital of France?"  ->  "Paris."
// User: "And its population?"             ->  "Population of what?"

La deuxième question échoue parce que le serveur n'a rien conservé de la première. Un chatbot corrige cela en renvoyant l'échange complet à chaque fois : le message système, chaque tour de l'utilisateur et chaque réponse de l'assistant, dans l'ordre. Le modèle lit l'historique, voit que « sa » fait référence à Paris, et répond correctement. Vous n'avez besoin ni d'une base de données ni d'un serveur de session pour cela, juste d'une liste de messages qui s'agrandit avec la conversation. Le seul vrai travail est de construire et de maintenir cette liste, et c'est exactement ce que le composant chatbot fait pour vous.

Le composant TsgcAIChat : la mémoire gérée pour vous

Plutôt que de câbler un tableau de messages à la main, déposez un TsgcAIChat sur votre fiche. Il détient l'historique de la conversation en interne, ajoute automatiquement chaque message de l'utilisateur et chaque réponse de l'assistant, et envoie le contexte accumulé à chaque appel. Vous définissez le fournisseur, la clé d'API et un modèle, puis vous appelez simplement Chat.

uses
  sgcAI, sgcAI_Chat;

var
  Bot: TsgcAIChat;
begin
  Bot := TsgcAIChat.Create(nil);
  Bot.Provider := aicpOpenAI;
  Bot.ChatOptions.ApiKey := 'sk-...';
  Bot.ChatOptions.Model  := 'gpt-4o-mini';
  Bot.SystemMessage := 'You are a concise assistant for Delphi developers.';

  // Each call adds to the same conversation:
  ShowMessage(Bot.Chat('What is the capital of France?'));  // "Paris."
  ShowMessage(Bot.Chat('And its population?'));             // answers about Paris
end;

Parce que le composant se souvient du premier tour, la question de suivi fonctionne simplement. Le SystemMessage définit la personnalité de l'assistant et est inclus dans chaque requête. Lorsque vous voulez une nouvelle conversation, appelez Bot.ClearHistory ; pour inspecter ou conserver ce qui a été dit, Bot.GetHistory renvoie la liste des messages. Vous pouvez aussi plafonner la mémoire avec MaxHistoryMessages afin qu'une longue discussion ne grossisse pas sans limite (les tours plus anciens sont élagués automatiquement).

Le même composant dialogue avec tous les fournisseurs pris en charge par sgcWebSockets. Basculez Provider sur aicpAnthropic, aicpGemini, aicpDeepSeek, aicpOllama, aicpGrok ou aicpMistral, changez le nom du modèle, et le reste de votre code de chatbot reste identique. Consultez la page du composant ChatBot et le hub des composants IA et LLM.

Diffuser une réponse en direct

Attendre plusieurs secondes qu'une réponse complète apparaisse semble lent. Les vrais chatbots diffusent la réponse pour que les mots apparaissent à mesure qu'ils sont générés, le familier effet de frappe. TsgcAIChat expose cela via ChatStream ainsi que l'événement OnChatStream, qui se déclenche pour chaque fragment de texte à mesure qu'il arrive.

Bot.OnChatStream := BotChatStream;
Bot.ChatStream('Explain WebSockets in two sentences.');

procedure TForm1.BotChatStream(Sender: TObject; const aChunk: string;
  var Cancel: Boolean);
begin
  Memo1.Text := Memo1.Text + aChunk;  // append each token as it arrives
  // set Cancel := True to stop the response early
end;

Les fragments sont livrés de façon incrémentale via les Server-Sent Events en coulisses, mais vous ne touchez jamais à la plomberie SSE. Lorsque la diffusion se termine, la réponse complète de l'assistant est ajoutée à l'historique tout comme un appel non diffusé, de sorte que le tour suivant dispose toujours du contexte complet. Le paramètre Cancel vous permet d'implémenter un bouton « arrêter la génération ». Il existe aussi OnChatMessage pour le message final assemblé et OnChatError pour faire remonter les éventuelles défaillances de l'API.

Un chatbot vocal, de bout en bout

Si vous voulez que l'assistant écoute et parle, le composant TsgcAIOpenAIChatBot englobe toute la boucle : il capture l'audio du microphone, le transcrit avec Whisper, envoie le texte aux Chat Completions, et restitue la réponse par la voix via un fournisseur de synthèse vocale. Branchez un enregistreur audio et un moteur de synthèse vocale, définissez la clé, et appelez Start.

uses
  sgcAI, sgcAI_OpenAI_Audio_ChatBot,
  sgcAI_AudioRecorder_MCI, sgcAI_TextToSpeech_System;

var
  ChatBot: TsgcAIOpenAIChatBot;
begin
  ChatBot := TsgcAIOpenAIChatBot.Create(nil);
  ChatBot.OpenAIOptions.ApiKey := 'sk-...';
  ChatBot.AudioRecorder := TsgcAudioRecorderMCI.Create(nil);
  ChatBot.TextToSpeech  := TsgcTextToSpeechSystem.Create(nil);
  ChatBot.OnChatCompletion := ChatBotChatCompletion;

  ChatBot.Start;                          // begin listening; Stop ends it
  ChatBot.ChatAsUser('Tell me a joke');   // or push a turn programmatically
end;

L'événement OnChatCompletion vous donne le rôle et le contenu de chaque réponse, et OnTranscription vous permet d'inspecter ou de modifier ce qui a été entendu avant l'envoi. C'est la même idée conversationnelle que TsgcAIChat, simplement avec de l'audio aux deux extrémités.

Vous préférez gérer la liste vous-même ?

Vous n'êtes pas obligé d'utiliser le composant chatbot. Si vous voulez un contrôle total, conservez votre propre liste de messages { role, content } et envoyez-la à chaque appel avec TsgcHTTP_API_OpenAI._CreateChatCompletion. Ajoutez le message de l'utilisateur, envoyez le tableau, puis ajoutez la réponse de l'assistant à la même liste avant le tour suivant. C'est précisément la comptabilité que TsgcAIChat effectue en interne, donc la plupart des gens laissent le composant s'en charger. L'API de plus bas niveau est traitée dans le tutoriel L'API OpenAI en Delphi et sur la page du composant OpenAI.

Pour commencer

Tout ce qui figure ici est fourni avec sgcWebSockets. Récupérez la version d'essai gratuite, déposez un TsgcAIChat sur une fiche, définissez la clé d'API et le modèle, et vous aurez un chatbot conscient du contexte qui répond aux questions de suivi en quelques lignes. Ajoutez ChatStream pour l'effet de frappe en direct quand vous serez prêt.

Des questions, des retours ou de l'aide pour l'intégrer à votre application ? Contactez-nous — vous recevrez une réponse des personnes qui ont écrit le code.

Sur le même thème