Construa um chatbot de IA no Delphi: memória de conversa e streaming

· Componentes

Resposta rápida: um chatbot é uma conclusão de chat mais memória. O sgcWebSockets vem com um componente dedicado TsgcAIChat que mantém todo o histórico de mensagens para você, de modo que cada turno é enviado com a conversa até ali e o modelo pode responder dentro do contexto. Coloque o componente, defina a chave de API e o modelo e depois chame Chat para uma resposta ou ChatStream para um efeito de digitação ao vivo, token a token. Limpar a conversa é uma única chamada a ClearHistory.

Se você já chamou um LLM a partir do Delphi, provavelmente notou algo frustrante: faça uma pergunta de acompanhamento e o modelo age como se nunca tivesse falado com você antes. Isso não é um bug, é como funciona uma conclusão de turno único. Transformar isso em um verdadeiro assistente conversacional é a diferença entre um brinquedo e um chatbot, e tudo se resume a uma ideia: memória.

Conclusão de turno único vs um chatbot

Uma API de LLM é sem estado. Cada requisição é independente, então o modelo só sabe o que você colocou naquela requisição. Uma chamada de turno único envia um único prompt:

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

A segunda pergunta falha porque o servidor não guardou nada da primeira. Um chatbot resolve isso reenviando toda a troca a cada vez: a mensagem de sistema, cada turno do usuário e cada resposta do assistente, em ordem. O modelo lê o histórico, vê que "its" se refere a Paris e responde corretamente. Você não precisa de um banco de dados nem de um servidor de sessão para isso, apenas de uma lista de mensagens que cresce com a conversa. O único trabalho real é construir e manter essa lista, e é exatamente isso que o componente de chatbot faz para você.

O componente TsgcAIChat: memória tratada para você

Em vez de montar um array de mensagens à mão, coloque um TsgcAIChat no seu formulário. Ele detém o histórico da conversa internamente, acrescenta cada mensagem do usuário e cada resposta do assistente automaticamente, e envia o contexto acumulado a cada chamada. Você define o provedor, a chave de API e um modelo e depois apenas chama 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;

Como o componente lembra do primeiro turno, o acompanhamento simplesmente funciona. A SystemMessage define a persona do assistente e é incluída em cada requisição. Quando você quiser uma conversa nova, chame Bot.ClearHistory; para inspecionar ou persistir o que foi dito, Bot.GetHistory retorna a lista de mensagens. Você também pode limitar a memória com MaxHistoryMessages para que um chat longo não cresça sem limites (os turnos mais antigos são removidos automaticamente).

O mesmo componente fala com todos os provedores que o sgcWebSockets suporta. Mude Provider para aicpAnthropic, aicpGemini, aicpDeepSeek, aicpOllama, aicpGrok ou aicpMistral, altere o nome do modelo, e o resto do código do seu chatbot permanece idêntico. Veja a página do componente ChatBot e o hub de componentes de IA & LLM.

Transmitindo uma resposta ao vivo

Esperar vários segundos para uma resposta completa aparecer parece lento. Chatbots reais transmitem a resposta para que as palavras apareçam conforme são geradas, o familiar efeito de digitação. O TsgcAIChat expõe isso por meio de ChatStream mais o evento OnChatStream, que dispara para cada bloco de texto conforme ele chega.

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;

Os blocos são entregues incrementalmente por Server-Sent Events por baixo dos panos, mas você nunca toca na infraestrutura do SSE. Quando o stream termina, a resposta completa do assistente é adicionada ao histórico, assim como em uma chamada sem streaming, de modo que o próximo turno ainda tem o contexto completo. O parâmetro Cancel permite implementar um botão de "parar de gerar". Há também OnChatMessage para a mensagem final montada e OnChatError para expor qualquer falha da API.

Um chatbot de voz, do começo ao fim

Se você quer que o assistente ouça e fale, o componente TsgcAIOpenAIChatBot encapsula todo o laço: ele captura o áudio do microfone, transcreve-o com o Whisper, envia o texto para Chat Completions e fala a resposta de volta por meio de um provedor de text-to-speech. Conecte um gravador de áudio e um motor de text-to-speech, defina a chave e chame 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;

O evento OnChatCompletion fornece o papel e o conteúdo de cada resposta, e OnTranscription permite inspecionar ou editar o que foi ouvido antes de ser enviado. É a mesma ideia conversacional do TsgcAIChat, apenas com áudio nas duas pontas.

Prefere gerenciar a lista você mesmo?

Você não precisa usar o componente de chatbot. Se quiser controle total, mantenha a sua própria lista de mensagens { role, content } e envie-a a cada chamada com TsgcHTTP_API_OpenAI._CreateChatCompletion. Acrescente a mensagem do usuário, envie o array e depois acrescente a resposta do assistente de volta à mesma lista antes do próximo turno. Essa é exatamente a contabilidade que o TsgcAIChat faz internamente, então a maioria das pessoas deixa o componente cuidar disso. A API de mais baixo nível é abordada no tutorial API da OpenAI no Delphi e na página do componente OpenAI.

Primeiros passos

Tudo aqui vem no sgcWebSockets. Baixe a versão de avaliação gratuita, coloque um TsgcAIChat em um formulário, defina a chave de API e o modelo, e você terá um chatbot consciente do contexto respondendo a perguntas de acompanhamento em poucas linhas. Adicione ChatStream para o efeito de digitação ao vivo quando estiver pronto.

Dúvidas, comentários ou ajuda para integrá-lo ao seu aplicativo? Entre em contato — você receberá uma resposta das pessoas que escreveram o código.

Relacionados