Skip to content

Delphi与ChatGPT集成指南:打造智能应用

在当今AI快速发展的时代,将ChatGPT等大型语言模型集成到传统应用程序中已成为提升用户体验的重要手段。本文将详细介绍如何在Delphi应用中集成OpenAI的ChatGPT API,实现智能对话和自动化功能。

为什么要在Delphi应用中集成ChatGPT?

将ChatGPT集成到Delphi应用中可以带来以下优势:

  1. 增强用户交互体验:提供自然语言界面,使用户能够通过对话方式操作应用
  2. 自动化复杂任务:利用AI处理复杂查询和任务,减轻用户负担
  3. 提供智能建议和辅助:根据用户行为和输入提供个性化建议
  4. 扩展应用功能:为传统应用增加现代AI能力,保持竞争力

技术准备

在开始集成之前,你需要准备以下内容:

  1. OpenAI API密钥:访问OpenAI平台注册并获取API密钥
  2. Delphi开发环境:建议使用Delphi 10.4或更高版本
  3. REST客户端组件:可以使用Indy、REST Debugger或TRESTClient组件
  4. JSON处理库:如System.JSON或其他第三方JSON库

基础实现:ChatGPT API调用

首先,我们创建一个基本的ChatGPT API调用类:

unit ChatGPTClient;

interface

uses
  System.SysUtils, System.Classes, System.Net.HttpClient, System.Net.URLClient,
  System.JSON, System.Generics.Collections;

type
  TChatMessage = record
    Role: string;
    Content: string;
    constructor Create(const ARole, AContent: string);
  end;

  TChatGPTClient = class
  private
    FApiKey: string;
    FModel: string;
    FMessages: TList<TChatMessage>;
    FTemperature: Double;
    FMaxTokens: Integer;
    FHttpClient: THTTPClient;

    function BuildRequestBody: TJSONObject;
  public
    constructor Create(const ApiKey: string);
    destructor Destroy; override;

    function SendMessage(const UserMessage: string): string;
    procedure ClearConversation;

    property Model: string read FModel write FModel;
    property Temperature: Double read FTemperature write FTemperature;
    property MaxTokens: Integer read FMaxTokens write FMaxTokens;
  end;

implementation

{ TChatMessage }

constructor TChatMessage.Create(const ARole, AContent: string);
begin
  Role := ARole;
  Content := AContent;
end;

{ TChatGPTClient }

constructor TChatGPTClient.Create(const ApiKey: string);
begin
  inherited Create;
  FApiKey := ApiKey;
  FModel := 'gpt-3.5-turbo';
  FTemperature := 0.7;
  FMaxTokens := 1000;
  FMessages := TList<TChatMessage>.Create;
  FHttpClient := THTTPClient.Create;
end;

destructor TChatGPTClient.Destroy;
begin
  FMessages.Free;
  FHttpClient.Free;
  inherited;
end;

function TChatGPTClient.BuildRequestBody: TJSONObject;
var
  RequestObj, MessageObj: TJSONObject;
  MessagesArray: TJSONArray;
  Message: TChatMessage;
begin
  RequestObj := TJSONObject.Create;
  MessagesArray := TJSONArray.Create;

  try
    RequestObj.AddPair('model', FModel);
    RequestObj.AddPair('temperature', TJSONNumber.Create(FTemperature));
    RequestObj.AddPair('max_tokens', TJSONNumber.Create(FMaxTokens));

    for Message in FMessages do
    begin
      MessageObj := TJSONObject.Create;
      MessageObj.AddPair('role', Message.Role);
      MessageObj.AddPair('content', Message.Content);
      MessagesArray.AddElement(MessageObj);
    end;

    RequestObj.AddPair('messages', MessagesArray);
    Result := RequestObj;
  except
    RequestObj.Free;
    raise;
  end;
end;

function TChatGPTClient.SendMessage(const UserMessage: string): string;
var
  URL: string;
  RequestBody, ResponseObj, ChoicesObj: TJSONObject;
  ResponseContent, ResponseText: string;
  Response: IHTTPResponse;
  ChoicesArray: TJSONArray;
begin
  Result := '';
  URL := 'https://api.openai.com/v1/chat/completions';

  // 添加用户消息到历史
  FMessages.Add(TChatMessage.Create('user', UserMessage));

  RequestBody := BuildRequestBody;
  try
    // 设置请求头
    FHttpClient.CustomHeaders['Authorization'] := 'Bearer ' + FApiKey;
    FHttpClient.CustomHeaders['Content-Type'] := 'application/json';

    // 发送请求
    Response := FHttpClient.Post(URL, TStringStream.Create(RequestBody.ToJSON), nil);
    ResponseContent := Response.ContentAsString;

    // 解析响应
    if Response.StatusCode = 200 then
    begin
      ResponseObj := TJSONObject.ParseJSONValue(ResponseContent) as TJSONObject;
      try
        ChoicesArray := ResponseObj.GetValue('choices') as TJSONArray;
        if (ChoicesArray <> nil) and (ChoicesArray.Count > 0) then
        begin
          ChoicesObj := ChoicesArray.Items[0] as TJSONObject;
          ResponseText := (ChoicesObj.GetValue('message') as TJSONObject).GetValue('content').Value;

          // 添加AI回复到历史
          FMessages.Add(TChatMessage.Create('assistant', ResponseText));
          Result := ResponseText;
        end;
      finally
        ResponseObj.Free;
      end;
    end
    else
      raise Exception.CreateFmt('API错误: %d - %s', [Response.StatusCode, ResponseContent]);
  finally
    RequestBody.Free;
  end;
end;

procedure TChatGPTClient.ClearConversation;
begin
  FMessages.Clear;
end;

end.

创建简单的聊天界面

接下来,我们创建一个简单的聊天界面来测试我们的ChatGPT集成:

unit MainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  ChatGPTClient;

type
  TfrmChatGPT = class(TForm)
    pnlTop: TPanel;
    pnlBottom: TPanel;
    memChat: TMemo;
    edtMessage: TEdit;
    btnSend: TButton;
    btnClear: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnSendClick(Sender: TObject);
    procedure btnClearClick(Sender: TObject);
    procedure edtMessageKeyPress(Sender: TObject; var Key: Char);
  private
    FChatGPT: TChatGPTClient;
    procedure AddMessageToChat(const Sender, Message: string);
    procedure SendUserMessage;
  public
    { Public declarations }
  end;

var
  frmChatGPT: TfrmChatGPT;

implementation

{$R *.dfm}

procedure TfrmChatGPT.FormCreate(Sender: TObject);
const
  API_KEY = '你的OpenAI API密钥'; // 替换为你的实际API密钥
begin
  FChatGPT := TChatGPTClient.Create(API_KEY);

  // 可选:配置ChatGPT参数
  FChatGPT.Model := 'gpt-3.5-turbo';
  FChatGPT.Temperature := 0.7;
  FChatGPT.MaxTokens := 1000;

  memChat.Lines.Add('ChatGPT助手已准备就绪。请输入您的问题...');
end;

procedure TfrmChatGPT.FormDestroy(Sender: TObject);
begin
  FChatGPT.Free;
end;

procedure TfrmChatGPT.AddMessageToChat(const Sender, Message: string);
begin
  memChat.Lines.Add(Format('[%s]: %s', [Sender, Message]));
  memChat.Lines.Add('');
end;

procedure TfrmChatGPT.SendUserMessage;
var
  UserMessage, AIResponse: string;
begin
  UserMessage := edtMessage.Text;
  if UserMessage.Trim.IsEmpty then
    Exit;

  // 显示用户消息
  AddMessageToChat('用户', UserMessage);
  edtMessage.Clear;

  // 禁用发送按钮,显示正在处理
  btnSend.Enabled := False;
  Application.ProcessMessages;

  try
    // 发送到ChatGPT并获取响应
    Screen.Cursor := crHourGlass;
    AIResponse := FChatGPT.SendMessage(UserMessage);

    // 显示AI响应
    AddMessageToChat('ChatGPT', AIResponse);
  except
    on E: Exception do
    begin
      memChat.Lines.Add('错误: ' + E.Message);
      memChat.Lines.Add('');
    end;
  end;

  // 恢复UI状态
  Screen.Cursor := crDefault;
  btnSend.Enabled := True;
  edtMessage.SetFocus;
end;

procedure TfrmChatGPT.btnSendClick(Sender: TObject);
begin
  SendUserMessage;
end;

procedure TfrmChatGPT.edtMessageKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #13 then // Enter键
  begin
    Key := #0;
    SendUserMessage;
  end;
end;

procedure TfrmChatGPT.btnClearClick(Sender: TObject);
begin
  memChat.Clear;
  FChatGPT.ClearConversation;
  memChat.Lines.Add('对话已清除。请输入新的问题...');
end;

end.

高级功能:流式响应

OpenAI API支持流式响应,可以实现打字机效果,提升用户体验。以下是实现流式响应的代码:

// 在ChatGPTClient单元中添加流式响应方法
function TChatGPTClient.SendMessageStreaming(const UserMessage: string; 
  OnChunk: TProc<string>): string;
var
  URL: string;
  RequestBody: TJSONObject;
  HttpRequest: THTTPRequest;
  HttpResponse: THTTPResponse;
  ResponseStream: TStringStream;
  Line, Content, Delta: string;
  JSONObj: TJSONObject;
  FullResponse: TStringBuilder;
begin
  URL := 'https://api.openai.com/v1/chat/completions';

  // 添加用户消息到历史
  FMessages.Add(TChatMessage.Create('user', UserMessage));

  RequestBody := BuildRequestBody;
  RequestBody.AddPair('stream', TJSONBool.Create(True));

  FullResponse := TStringBuilder.Create;
  ResponseStream := TStringStream.Create('', TEncoding.UTF8);
  HttpRequest := THTTPRequest.Create;
  HttpResponse := THTTPResponse.Create;

  try
    // 设置请求
    HttpRequest.Client := FHttpClient;
    HttpRequest.URL := URL;
    HttpRequest.MethodString := 'POST';
    HttpRequest.SourceStream := TStringStream.Create(RequestBody.ToJSON);
    HttpRequest.SourceStream.Position := 0;
    HttpRequest.Headers.Add('Authorization', 'Bearer ' + FApiKey);
    HttpRequest.Headers.Add('Content-Type', 'application/json');

    // 发送请求并处理流式响应
    if HttpRequest.Execute(HttpResponse, ResponseStream) then
    begin
      ResponseStream.Position := 0;

      while not ResponseStream.DataString.IsEmpty do
      begin
        Line := ResponseStream.DataString;
        ResponseStream.Size := 0;

        if Line.StartsWith('data: ') then
        begin
          Content := Line.Substring(6);

          if Content = '[DONE]' then
            Break;

          try
            JSONObj := TJSONObject.ParseJSONValue(Content) as TJSONObject;
            try
              if JSONObj.GetValue('choices') <> nil then
              begin
                Delta := (((JSONObj.GetValue('choices') as TJSONArray).Items[0] as TJSONObject)
                  .GetValue('delta') as TJSONObject).GetValue('content').Value;

                if not Delta.IsEmpty then
                begin
                  FullResponse.Append(Delta);
                  if Assigned(OnChunk) then
                    OnChunk(Delta);
                end;
              end;
            finally
              JSONObj.Free;
            end;
          except
            // 忽略解析错误
          end;
        end;

        if not HttpResponse.ConnectionClose then
          HttpRequest.Execute(HttpResponse, ResponseStream);
      end;
    end;

    Result := FullResponse.ToString;

    // 添加AI回复到历史
    if not Result.IsEmpty then
      FMessages.Add(TChatMessage.Create('assistant', Result));

  finally
    FullResponse.Free;
    ResponseStream.Free;
    HttpRequest.Free;
    HttpResponse.Free;
    RequestBody.Free;
  end;
end;

实际应用案例

1. 智能客服系统

// 在客服系统中集成ChatGPT处理常见问题
procedure TCustomerSupportForm.HandleCustomerQuery(const Query: string);
var
  Response: string;
begin
  // 首先检查是否是常见问题
  if IsCommonQuestion(Query) then
    DisplayPredefinedAnswer(Query)
  else
  begin
    // 使用ChatGPT处理复杂问题
    Response := FChatGPT.SendMessage(
      '你是一个客服助手,请回答以下问题: ' + Query);
    DisplayResponse(Response);
  end;
end;

2. 代码生成助手

// 使用ChatGPT生成代码片段
procedure TCodeGeneratorForm.GenerateCode;
var
  Prompt, GeneratedCode: string;
begin
  Prompt := Format(
    '请为以下功能生成Delphi代码: %s' + sLineBreak +
    '使用的组件: %s' + sLineBreak +
    '额外要求: %s',
    [edtFeature.Text, edtComponents.Text, memRequirements.Text]
  );

  GeneratedCode := FChatGPT.SendMessage(Prompt);

  // 提取代码块
  GeneratedCode := ExtractCodeBlock(GeneratedCode);

  // 显示生成的代码
  memGeneratedCode.Text := GeneratedCode;
end;

最佳实践与注意事项

  1. API密钥安全:不要在代码中硬编码API密钥,考虑使用配置文件或环境变量
  2. 错误处理:实现完善的错误处理机制,处理网络问题和API限制
  3. 上下文管理:合理管理对话历史,避免超出token限制
  4. 用户体验:实现流式响应和加载指示器,提升用户体验
  5. 成本控制:监控API使用情况,实施合理的使用限制

结论

通过将ChatGPT集成到Delphi应用中,我们可以为传统应用注入AI能力,显著提升用户体验和应用功能。随着AI技术的不断发展,这种集成将变得越来越重要,成为现代应用开发的标准实践。

希望本文能帮助你在Delphi应用中成功集成ChatGPT,打造更智能、更有竞争力的应用程序。


关于作者:付乙,资深Delphi开发者,专注于将现代技术与传统应用相结合,提升软件价值和用户体验。