Delphi에서 LLM 호출하기

VCL, FMX 또는 콘솔 애플리케이션에서 프롬프트를 보내고 답변을 받아요. OpenAI나 Anthropic Claude 같은 호스팅 모델도 되고, Ollama로 내 컴퓨터에서 돌아가는 모델도 돼요. 이 페이지는 빈 폼에서 시작해 동작하는 호출까지, 그리고 모든 프로젝트가 다음으로 마주치는 세 가지인 스트리밍, 툴 호출, 그리고 호스팅 모델과 로컬 모델 사이의 선택까지 데려가요.

OpenAI, Claude, Gemini, Grok, DeepSeek, Mistral, Ollama
Server-Sent Events 기반 스트리밍
Delphi 7부터 RAD Studio 13까지

호출하는 두 가지 방법

공급자에 얽매이지 않는 채팅 컴포넌트가 하나 있고, 공급자마다 전용 REST 클라이언트가 따로 있어요. 둘 다 같은 라이브러리에 들어 있어서 하나로 시작했다가 프로젝트를 바꾸지 않고 다른 쪽으로 내려갈 수 있어요.

TsgcAIChat, 모든 공급자를 위한 하나의 API

Provider와 API 키, 모델을 설정한 다음 Chat을 호출하세요. 컴포넌트가 공급자별 JSON을 만들고, 대화 기록을 유지하고, 어시스턴트의 텍스트를 돌려줘요. OpenAI에서 Claude로, 또는 로컬 Ollama 모델로 바꾸는 일은 대입 한 번이에요. 구현은 sgcAI_Chat 유닛의 TsgcAI_Chat이고, 팔레트에는 TsgcAIChat으로 등록돼 있어요.

공급자별 REST 클라이언트

TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic, TsgcHTTP_API_Ollama는 각 공급자 API를 전부 노출해요. 중립 계층으로는 덮을 수 없는 부분, 즉 비전 입력과 문서 입력, 확장 사고, 배치, 파일, Embeddings, 이미지 생성, 음성 전사까지 포함해요. 특정 엔드포인트가 필요할 때 이 클라이언트를 쓰세요.

에디션과 플랫폼

AI와 LLM 클라이언트는 sgcWebSockets의 Enterprise 기능이에요. Standard에도 Professional에도 들어 있지 않아요. 아니면 단독 sgcAI 패키지를 구매할 수 있어요.

여기서는 플랫폼이 중요해요. 세 가지 REST 클라이언트는 Windows, macOS, Linux, iOS, Android에서 컴파일돼요. TsgcAIChat은 그렇지 않아요. Windows 전용으로만 컴파일되기 때문에 Linux 서비스나 macOS 빌드, 모바일 타깃에서는 REST 클라이언트를 직접 호출해요. 이 페이지의 예제는 두 경로 모두에서 동작하도록 작성했어요.

열 줄 남짓으로 만드는 첫 호출

컴포넌트를 올리고, 키와 모델을 설정하고, 프롬프트를 보내세요. 처음 쓰려는 공급자의 탭을 고르면 돼요. 마지막 탭은 모델이 내 컴퓨터에서 돌아가기 때문에 API 키가 아예 필요 없어요.

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;

공급자를 바꾸는 일은 한 줄이에요. ProvideraicpOpenAI, aicpAnthropic, aicpGemini, aicpDeepSeek, aicpOllama, aicpGrok, aicpMistral을 받아요. 코드의 나머지는 그대로 있어요.

Windows 전용이에요. TsgcAI_Chat과 팔레트 컴포넌트 TsgcAIChat은 Windows용, 즉 Win32와 Win64로만 컴파일돼요. macOS, Linux, iOS, Android에서는 유닛 자체가 컴파일되지 않아요. 그래서 타깃이 Linux 서비스나 모바일 앱이라면 다른 세 탭에 있는 공급자 REST 클라이언트를 쓰세요. 그쪽은 플랫폼 제약이 없어요.

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;

밑줄로 시작하는 메서드는 원시 응답 본문을 그대로 돌려주는 문자열 단축 메서드예요. 파싱된 객체가 필요하다면 TsgcOpenAIClass_Request_ChatCompletion을 만들어 CreateChatCompletion을 호출하세요. 이 페이지 아래쪽에 나와요.

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는 API 버전 헤더를 요구하므로 키와 함께 AnthropicVersion도 설정하세요. _CreateMessageWithSystem은 시스템 프롬프트를 추가하고, _CountTokens는 보내기 전에 프롬프트의 비용을 계산해요.

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의 기본값은 http://localhost:11434이므로 기본 설치 상태라면 그대로 두면 돼요. _PullModel은 모델을 내려받고, _GetTags는 디스크에 이미 있는 모델을 나열하고, _ShowModel은 그 상세 정보를 읽어요.

답변이 쓰이는 대로 보여주기

한 번에 받는 호출은 모델이 끝낼 때까지 멈춰 있어요. 답변이 길면 고장 난 것처럼 보이죠. 스트리밍은 응답을 조각으로 전달하기 때문에 모델이 아직 생각하는 동안에도 메모에 텍스트가 나타나요. 많은 분이 여기서 막히므로 두 수준을 모두 보여드릴게요.

TsgcAIChat으로, 이미 디코딩된 델타

Chat 대신 ChatStream을 호출하고 OnChatStream을 처리하세요. 컴포넌트가 공급자에게 스트리밍 응답을 요청하고, 각 Server-Sent Event를 파싱해서 aChunk를 건네줘요. 이건 새로 도착한 텍스트일 뿐 그 외에는 아무것도 아니에요. 그걸 이어 붙이면 구현은 끝이에요.

공급자마다 스트리밍하는 JSON 모양이 달라요. OpenAI, DeepSeek, Ollama, Grok, Mistral은 텍스트를 choices[0].delta.content에 담고, Claude는 delta.text에, Gemini는 그보다 더 깊은 candidates 안에 담아요. TsgcAIChat은 선택한 공급자에 어떤 모양이 적용되는지 이미 알고 있어서, 여러분의 핸들러는 JSON을 볼 일이 없어요.

답변이 걷잡을 수 없이 길어지면 핸들러 안에서 CancelTrue로 설정해 멈추세요. 그 시점에 요청이 중단되고 이후 청크는 도착하지 않아요. 스트림이 끝나면 조립된 텍스트가 기록에 추가되고 ChatStream이 그것을 반환하며, OnChatMessage가 완성된 답변과 함께 한 번 발생해요.

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;

공급자 클라이언트로, 원시 이벤트

REST 클라이언트도 스트리밍을 해요. OnHTTPAPISSE를 할당하고 스트리밍 단축 메서드를 호출하세요. Claude와 Ollama에서는 _CreateMessageStream이고, OpenAI에서는 StreamTrue로 설정한 TsgcOpenAIClass_Request_ChatCompletion이에요. 이벤트는 Server-Sent Event 이름인 aEvent와, 그 이벤트의 페이로드를 공급자가 보낸 그대로 담은 aData를 넘겨줘요.

이 수준에서는 JSON을 직접 파싱해요. 그게 바로 요점이에요. 툴 호출 델타, 중단 이유, 사용량 기록, 그 밖에 공급자가 회선에 실어 보내는 모든 것을 볼 수 있어요. 부분적인 네트워크 읽기는 이미 다시 조립돼 있어서, TCP 읽기 두 번에 걸쳐 쪼개진 이벤트도 온전한 형태로 도착하고, Ollama의 줄바꿈 구분 JSON도 같은 이벤트로 전달돼요.

종료 표시는 공급자마다 달라요. OpenAI는 리터럴 [DONE]로 닫고, Claude는 message_stop이라는 이름의 이벤트로 닫아요. 코드가 둘 다를 대상으로 한다면 둘 다 처리하세요.

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;

스레드. ChatChatStream은 동기 메서드예요. 그래서 버튼 클릭에서 바로 호출하면 요청이 끝날 때까지 폼이 멈춰요. Delphi 2010 이상에서는 ChatAsync가 호출을 워커 스레드에서 실행하고 IsgcFuture<string>을 반환해요. 결과에는 ThenProc을, 실패에는 OnError를 체이닝하고, 진행 중인 요청을 버리려면 Cancel을 호출하세요. ThenProc 콜백은 메인 스레드에서 디스패치되므로 거기서 UI를 직접 건드려도 돼요.

모델이 여러분의 Pascal 코드를 호출하게 하기

함수 호출이라고도 부르는 툴 호출은 모델이 여러분의 애플리케이션에 무언가를 조회하거나 어떤 동작을 수행해 달라고 요청하는 방식이에요. 함수를 JSON Schema로 기술하면 모델이 원하는 인수를 담아 답하고, 여러분이 Pascal 코드를 실행한 뒤 결과를 돌려줘요. 업무용 애플리케이션 안에서 쓸모 있는 어시스턴트는 모두 이 구조 위에 서 있어요.

Claude, 타입이 있는 툴 객체로

TsgcAnthropicClass_Request_Messages를 만들고 TsgcAnthropicClass_Request_Tool 항목을 하나 이상 붙인 다음 CreateMessage를 호출하세요. 각 툴은 Name, Description, 그리고 인수의 JSON Schema인 InputSchema를 담아요.

응답은 TsgcAnthropicClass_Response_Messages이고, 그 Content는 블록의 배열이에요. ContentType'tool_use'인 블록은 툴의 Name, Input에 담긴 인수, 그리고 Id를 실어 나르죠. 함수를 실행한 다음, ContentType'tool_result'로 설정하고 같은 ToolUseIdContent에 담은 답을 가진 TsgcAnthropicClass_Request_Content_Block을 포함한 후속 메시지를 보내세요. 호출이 실패했다면 IsError를 설정해서 모델이 추측하지 않고 복구할 수 있게 하세요.

소유권에 주의하세요. Anthropic 요청은 여러분이 붙인 메시지와 툴을 소유하지 않아요. 그러니 예제처럼 직접 해제해야 해요.

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, 타입이 있는 요청으로

같은 발상이지만 모양이 달라요. TsgcOpenAIClass_Request_ChatCompletion을 채우고, Messages 배열을 할당하고, 툴 정의를 JSON 배열로 Tools에 넣고, 필요하면 ToolChoice로 모델을 유도하세요. ParallelToolCalls는 모델이 여러 툴을 한 번에 요청할 수 있는지를 정하고, ResponseFormat은 답을 파싱해야 할 때 응답을 JSON으로 고정해요.

CreateChatCompletion은 파싱된 TsgcOpenAIClass_Response_ChatCompletion을 반환해요. 답변은 Choices[0]._Message.Content에서, 요청된 호출은 Choices[0]._Message.ToolCalls에서, 모델이 멈춘 이유는 Choices[0].FinishReason에서, 비용은 Usage.PromptTokensUsage.CompletionTokens, Usage.TotalTokens에서 읽으세요. Anthropic 요청과 달리 이쪽은 붙인 메시지 객체를 소유하고 자기 자신과 함께 해제해요.

예전의 FunctionsFunctionCall 속성도 그대로 남아 있어요. 초기 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;

호스팅 모델이냐 로컬 모델이냐

프롬프트에 고객 기록이나 의료 데이터, 계약서처럼 데이터 처리 계약이 적용되는 내용이 들어간다면, 이건 성능 문제가 아니라 컴플라이언스 문제예요. 비교표를 보세요.

호스팅, OpenAI 또는 Claude 로컬, Ollama
프롬프트가 가는 곳 공급자에게, HTTPS로, 그들의 약관에 따라 어디에도 가지 않아요. 요청은 http://localhost:11434로 가요
자격 증명 소스 관리와 바이너리 밖에 두어야 하는 API 키 기본적으로 없어요. OllamaOptions.ApiKey는 프록시를 거치거나 원격에 있는 인스턴스를 위한 거예요
답변 품질 오늘 쓸 수 있는 가장 강력한 모델 좋고 계속 나아지고 있지만, 어려운 추론에서는 최전선에 확실히 뒤져요
비용 토큰당, 계속해서. Usage.TotalTokens를 지켜보세요 하드웨어 비용을 한 번. 쓸 만한 모델은 많은 RAM이나 GPU를 원해요
지연 시간 네트워크 왕복, 그리고 붐빌 때는 공급자 쪽 대기열까지 네트워크가 없어요. 속도는 내 컴퓨터가 내는 만큼이에요
오프라인과 망 분리 아니요
속도 제한과 장애 공급자 쪽 문제예요. RetryOptions를 쓰고 Retry-After를 존중하세요 오직 내 쪽 용량만
컴포넌트 TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic TsgcHTTP_API_Ollama

흔한 답은 둘 다예요. TsgcAIChat이 모든 공급자를 하나의 API 뒤에 두기 때문에 런타임에 데이터 등급에 따라 경로를 나눌 수 있어요. 고객 기록을 건드리는 건 로컬로, 나머지는 호스팅으로 보내는 식이죠. 전환은 Provider 하나이고, 공급자가 Ollama일 때는 ChatOptions.BaseUrl이 더해져요.

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

운영 환경에서 중요한 설정

내 책상에서 잘 도는 데모와, 속도 제한과 느린 모델과 "그냥 멈췄어요"라는 지원 티켓을 견뎌내는 클라이언트는 같지 않아요.

재시도와 백오프

클라이언트마다 RetryOptions 블록이 있어요. Enabled, Retries, Wait, Multiplier, MaxInterval, Jitter, HonorRetryAfter가 들어 있죠. 이걸 켜면 일시적인 실패가 예외로 드러나는 대신 지수 백오프로 재시도돼요. HonorRetryAfter는 클라이언트가 추측하지 않고 공급자의 Retry-After 헤더를 따르게 해요.

타임아웃

올려야 할 값은 HttpOptions.ReadTimeout이에요. 특히 로컬 모델에서 생성이 길어지면 기본 HTTP 읽기 타임아웃을 넘겨서, 잘 나오고 있던 답변이 중간에 끊길 수 있어요.

로깅

LogOptions.EnabledLogOptions.FileName을 함께 쓰면 트래픽이 파일로 기록돼요. 운영 환경에서 프롬프트가 다르게 동작할 때, 코드가 실제로 보낸 JSON을 확인하는 가장 빠른 방법이에요.

대화 기록

TsgcAIChat은 주고받은 내용을 보관했다가 다음 호출에서 다시 보내요. 후속 질문이 통하는 이유가 그거예요. MaxHistoryMessages로 상한을 두어 긴 세션이 프롬프트를, 따라서 청구서를 한없이 키우지 않게 하세요. ClearHistory는 처음부터 다시 시작하고, GetHistoryCount와 개별 메시지를 노출해요.

Azure OpenAI

OpenAIOptions.ProvideroapvAzure로 설정하고 AzureOptions.ResourceName, AzureOptions.DeploymentId, AzureOptions.APIVersion을 채우세요. 코드의 나머지는 그대로예요. 구매 부서가 트래픽이 Azure 테넌트 안에 머물러야 한다고 못 박을 때 이 점이 중요해요.

오류와 Circuit Breaker

OnHTTPAPIException은 REST 클라이언트의 실패를 드러내고, OnChatErrorTsgcAIChat에서 같은 일을 해요. HTTP 오류는 EsgcHTTPAPIProtocolException으로 도착하는데, 이건 여전히 EIdHTTPProtocolException을 상속하면서 응답 헤더까지 함께 담고 있어요. 직접 만드는 호출을 위해 클라이언트에서 CircuitBreakerRateLimit을 쓸 수 있어요.

첫 호출 다음에 사람들이 만드는 것

채팅 상자는 시작일 뿐이에요. 이 작업이 보통 향하는 네 가지 방향이 있고, 그 하나하나가 이미 라이브러리 안에 들어 있어요.

내 데이터로 답하기

TsgcAIOpenAIEmbeddings로 문서를 벡터로 바꾸고, TsgcAIDatabaseVectorFile이나 TsgcAIDatabaseVectorPinecone에 저장한 뒤, 가장 가까운 구절을 찾아 프롬프트에 넣으세요. 이것이 검색 증강 생성이고, 모델이 우리 회사 이야기를 지어내지 않게 만드는 방법이에요.

Embeddings벡터 데이터베이스

말을 걸고, 대답을 듣기

TsgcAIOpenAIChatBot은 녹음기와 음성 전사, 채팅 호출, 음성 합성을 하나의 컴포넌트로 엮어요. 그래서 사용자가 애플리케이션과 말로 대화할 수 있어요. TsgcAIOpenAITranslator는 실시간 번역에서 같은 일을 해요.

AI ChatBotAI Translator

AI 에이전트에 앱을 열어주기

Model Context Protocol은 어시스턴트가 툴을 찾아내고 호출하는 방식이에요. TsgcWSServer_API_MCP는 여러분의 Delphi 애플리케이션을 Claude를 비롯한 클라이언트가 조작할 수 있는 MCP 서버로 바꿔주고, TsgcWSAPI_Client_MCP는 코드에서 다른 서버를 소비해요. 팔레트에는 TsgcWSAPIServer_MCPTsgcWSAPIClient_MCP로 나타나요.

알아둘 점이 있어요. 채팅 컴포넌트와 달리 MCP 유닛은 Windows에 묶여 있지 않아서, Delphi로 작성한 MCP 서버를 Linux에서 돌릴 수 있어요.

MCP 개요, MCP 서버, MCP 클라이언트

각 공급자 API의 나머지 활용하기

OpenAI에서는 이미지 생성과 음성 전사, 모더레이션, 배치, 파인 튜닝을 쓸 수 있어요. Claude에서는 비전과 문서, 확장 사고, 웹 검색, 토큰 계산을 쓸 수 있고요. Ollama에서는 Embeddings와 모델 관리를 쓸 수 있어요. 각 공급자 페이지에 해당 클라이언트가 노출하는 기능이 정리돼 있어요.

OpenAI, Claude, Ollama

레퍼런스, 데모, 튜토리얼

컴포넌트 레퍼런스에 모든 속성과 이벤트가 문서화돼 있어요. 바로 실행할 수 있는 데모 프로젝트는 라이브러리 안 Demos\AI 폴더에 들어 있어요.

레퍼런스, OpenAI 클라이언트 TsgcHTTP_API_OpenAI의 모든 메서드와 옵션, 이벤트를 담았어요.
레퍼런스, Anthropic 클라이언트 TsgcHTTP_API_Anthropic의 메시지, 툴, 비전, 배치, 토큰 계산을 담았어요.
튜토리얼, Delphi에서 Claude 쓰기 Anthropic 클라이언트를 처음부터 끝까지 길게 따라가는 안내예요.
튜토리얼, Ollama로 로컬 모델 쓰기 모델을 내려받고, 클라이언트를 localhost로 향하게 하고, 오프라인에서 실행해요.
튜토리얼, 함수 호출 모델을 여러분의 Pascal 함수에 연결하는 과정을 단계별로 다뤄요.
사용자 설명서 (PDF) 라이브러리의 모든 컴포넌트를 다루는 종합 설명서예요.

더 읽을거리로는 Delphi에서 쓰는 OpenAI 클라이언트, AI 챗봇 만들기, AI 에이전트 만들기, MCP 클라이언트가 있어요. 컴포넌트 소개 페이지는 Delphi OpenAI 클라이언트Anthropic API예요.

이 페이지는 Delphi 사용 사례 중 하나예요. 각 페이지가 하나의 작업을 처음부터 끝까지 다뤄요. 지금까지 나온 다른 페이지는 OAuth2와 PKCE로 사용자 로그인 처리하기WebRTC로 두 애플리케이션을 피어 투 피어로 연결하기예요.

자주 묻는 질문

sgcAI_Chat 유닛의 TsgcAI_Chat을 만들고, Provider를 원하는 공급자로 설정하고, ChatOptions.ApiKeyChatOptions.Model을 설정한 다음 Chat('your prompt')를 호출하세요. 답변이 문자열로 돌아와요. 공급자 API 하나와 직접 이야기하고 싶다면 TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic, TsgcHTTP_API_Ollama를 쓰고 _CreateChatCompletion이나 _CreateMessage를 호출하세요. 두 방식 모두 sgcWebSockets와 단독 sgcAI 패키지에 들어 있고, Delphi 7부터 RAD Studio 13까지 동작해요.
Chat 대신 ChatStream을 호출하고 OnChatStream을 처리하세요. 이 이벤트는 각 델타의 디코딩된 텍스트인 aChunk와, 일찍 멈추려고 설정할 수 있는 Cancel 플래그와 함께 발생해요. REST 클라이언트 수준에서는 OnHTTPAPISSE를 할당하고 Claude와 Ollama 클라이언트에서 _CreateMessageStream을 호출하거나, TsgcOpenAIClass_Request_ChatCompletion에서 StreamTrue로 설정하세요. 그 이벤트는 원시 Server-Sent Event 이름과 데이터를 넘겨주고, 부분적인 네트워크 읽기는 이미 다시 조립돼 있어요.
네. Ollama를 설치하고 모델을 내려받은 다음 TsgcHTTP_API_Ollama가 그쪽을 보게 하세요. OllamaOptions.Host의 기본값이 이미 http://localhost:11434라서, 기본 설치 상태라면 모델만 고르고 _CreateMessage를 호출하면 돼요. 아무것도 컴퓨터 밖으로 나가지 않고, API 키도 필요 없으며, 애플리케이션은 오프라인에서도 동작해요. TsgcAIChat에서는 ProvideraicpOllama로 설정하면 같은 서버에 닿고, 서버가 localhost에 없다면 ChatOptions.BaseUrl도 설정하세요.
함수를 JSON Schema로 기술해서 요청에 붙이세요. Claude에서는 Name, Description, InputSchema를 가진 TsgcAnthropicClass_Request_ToolTsgcAnthropicClass_Request_MessagesTools 배열에 추가해요. 그러면 응답에 ContentTypetool_use인 콘텐츠 블록이 들어 있고 NameInput, Id를 담고 있어요. 여러분은 같은 ToolUseId를 인용한 tool_result 블록으로 답하면 돼요. OpenAI에서는 정의를 TsgcOpenAIClass_Request_ChatCompletionTools 속성에 넣고, 요청된 호출을 Choices[0]._Message.ToolCalls에서 읽으세요.
AI와 LLM 클라이언트는 sgcWebSockets의 Enterprise 기능이에요. Standard나 Professional 에디션에는 들어 있지 않아요. sgcWebSockets의 나머지가 필요하지 않다면, 단독 sgcAI 패키지에 같은 컴포넌트와 그것들이 필요로 하는 런타임이 함께 들어 있어요. 라이브러리는 Delphi 7부터 RAD Studio 13까지, 그리고 대응하는 C++ Builder 버전을 지원해요. 플랫폼을 보면 REST 클라이언트인 TsgcHTTP_API_OpenAI, TsgcHTTP_API_Anthropic, TsgcHTTP_API_Ollama는 Windows, macOS, Linux, iOS, Android용으로 컴파일되고, TsgcAIChat은 Windows 전용, 즉 Win32와 Win64로만 컴파일돼요. MCP 클라이언트와 서버도 Windows에 묶여 있지 않아요.
호스팅 공급자라면 필요해요. 컴포넌트는 REST 클라이언트라서, 본인의 OpenAI, Anthropic, Google, xAI, DeepSeek, Mistral 계정에서 키를 가져와 ChatOptions.ApiKeyOpenAIOptions.ApiKey 같은 공급자 옵션에 할당해요. 사용량은 그 공급자가 여러분의 키에 청구하고, 응답마다 Usage.PromptTokens, Usage.CompletionTokens, Usage.TotalTokens로 추적할 수 있어요. Ollama는 모델이 로컬에서 돌기 때문에 키가 필요 없어요.
ChatChatStream은 동기 메서드예요. Delphi 2010 이상에서는 대신 ChatAsync를 호출하세요. 요청을 워커 스레드에서 실행하고 문자열의 IsgcFuture를 반환하므로, 답변을 받으려면 ThenProc을, 예외를 받으려면 OnError를, 진행 중인 요청을 버리려면 Cancel을 체이닝하면 돼요. ThenProc 콜백은 메인 스레드에서 디스패치되므로 거기서 UI를 갱신해도 안전해요. 생성이 길어지면 기본 읽기 타임아웃을 넘길 수 있으니 HttpOptions.ReadTimeout도 올리세요.
네. OpenAIOptions.ProvideroapvAzure로 설정하고 AzureOptions.ResourceName, AzureOptions.DeploymentId, AzureOptions.APIVersion을 채우세요. 그러면 클라이언트가 여러분의 Azure 배포를 대상으로 하고, 이미 작성해 둔 호출은 그대로 유지돼요.
최고의 가성비: All-Access모든 eSeGeCe 제품과 프리미엄 지원이 포함되어 연 €1,059부터 이용할 수 있어요.
All-Access 가격 보기

Delphi 앱에서 LLM을 호출할 준비가 되셨나요?

무료 체험판을 내려받고 오늘 첫 호출을 해 보세요.