unit uMain; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, FMX.StdCtrls, FMX.Controls.Presentation, FMX.Layouts, REST.Types, REST.Client, Data.Bind.Components, Data.Bind.ObjectScope, System.JSON, FMX.Edit; type TForm1 = class(TForm) RESTClient1: TRESTClient; RESTRequest1: TRESTRequest; RESTResponse1: TRESTResponse; MaterialOxfordBlueSB: TStyleBook; Timer1: TTimer; MemoOutput: TMemo; MemoResponse: TMemo; Panel1: TPanel; BtnSend: TButton; MemoInput: TMemo; Panel2: TPanel; Edit1: TEdit; Label1: TLabel; Splitter1: TSplitter; procedure BtnSendClick(Sender: TObject); procedure MemoInputKeyDown(Sender: TObject; var Key: Word; var KeyChar: WideChar; Shift: TShiftState); procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); private { Private declarations } procedure HandleResponse; public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.BtnSendClick(Sender: TObject); var JsonObj: TJSONObject; memostr : string; begin memostr := MemoInput.Text; MemoInput.Text := ''; MemoInput.Lines.Add(''); // 1. ÀÔ·Â È®ÀÎ if Trim(memostr) = '' then Exit; // 2. UI ¾÷µ¥ÀÌÆ® (¸ð¹ÙÀÏ¿¡¼­´Â ŰÆÐµå ³»·ÁÁÖ±â À§ÇØ Æ÷Ä¿½º À̵¿ µîÀ» °í·ÁÇÒ ¼ö ÀÖÀ½) MemoOutput.Lines.Add('Áú¹®: ' + memostr); MemoOutput.Lines.Add('´äº¯À» ±â´Ù¸®´Â Áß...'); MemoOutput.GoToTextEnd; BtnSend.Enabled := False; // Áߺ¹ Àü¼Û ¹æÁö RESTClient1.BaseURL := Edit1.Text; RESTRequest1.Accept := 'application/json, text/plain;q=0.9, text/html;q=0.8'; RESTRequest1.Method := rmPOST; RESTRequest1.Resource := 'chat'; // 3. JSON »ý¼º JsonObj := TJSONObject.Create; try JsonObj.AddPair('prompt', memostr); JsonObj.AddPair('max_tokens', TJSONNumber.Create(512)); // ÅäÅ« ¼ö ³Ë³ËÇÏ°Ô // 4. Request ¼³Á¤ RESTRequest1.ClearBody; // Áß¿ä: ¸ð¹ÙÀÏ ¹®Àڼ ȣȯÀ» À§ÇØ TRESTContentType.ctAPPLICATION_JSON ¸í½Ã RESTRequest1.AddBody(JsonObj.ToString, TRESTContentType.ctAPPLICATION_JSON); finally JsonObj.Free; end; RESTRequest1.ExecuteAsync( procedure begin // MemoInput.Lines.Text := RESTResponse1.Content HandleResponse; BtnSend.Enabled := True; end, True, True, procedure(AObject: TObject) begin MemoOutput.Lines.Add('Error: ' + ERESTException(AObject).Message); BtnSend.Enabled := True; end); { // 5. ºñµ¿±â Àü¼Û (ExecuteAsync) // [¼öÁ¤] ´Ù½Ã ÆÄ¶ó¹ÌÅͰ¡ ¾ø´Â ±âº» ÇüÅ·Πµ¹¾Æ°©´Ï´Ù. RESTRequest1.ExecuteAsync( procedure begin // Àü¼Û ¼º°ø ½Ã ½ÇÇàµÉ ÄÚµå HandleResponse; BtnSend.Enabled := True; end, True, // Synchronized True, // FreeThread procedure(E: Exception) begin // ¿¡·¯ ¹ß»ý ½Ã ½ÇÇàµÉ ÄÚµå ShowMessage('Åë½Å ¿¡·¯: ' + E.Message); BtnSend.Enabled := True; end ); } { // [ºñ»ó ´ëÃ¥] °¡Àå ´Ü¼øÇÑ ÇüÅ (¿¡·¯ 󸮴 ³ªÁß¿¡ Ãß°¡) RESTRequest1.ExecuteAsync( procedure begin HandleResponse; BtnSend.Enabled := True; end ); } end; procedure TForm1.FormCreate(Sender: TObject); begin {$IF defined(MSWINDOWS)} MemoInput.ImeMode := TImeMode.imSHanguel; {$ELSEIF defined(MACOS)} MemoInput.TextSettings.Font.Family := 'Apple SD Gothic Neo'; MemoInput.Lines.Add(''); {$ELSEIF defined(ANDROID)} // {$ELSEIF defined(IOS)} // {$ENDIF} MemoInput.SetFocus; end; procedure TForm1.HandleResponse; var JsonValue: TJSONValue; JsonObject: TJSONObject; DataArray: TJSONArray; DataItem: TJSONValue; Status, MessageStr: string; I: Integer; Pair: TJSONPair; begin if RESTResponse1.StatusCode = 200 then begin JsonValue := RESTResponse1.JSONValue; Timer1.Enabled := False; MemoResponse.Text := 'Response: ' + JsonValue.ToString; if JsonValue is TJSONObject then begin JsonObject := JsonValue as TJSONObject; // 1. ¼­¹ö ó¸® »óÅÂ(status) È®ÀÎ if JsonObject.TryGetValue('status', Status) then begin // 2. ¼­¹ö°¡ º¸³½ ¸Þ½ÃÁö(message) ÃßÃâ JsonObject.TryGetValue('message', MessageStr); MemoOutput.Lines.Add('»óÅÂ: ' + Status); MemoOutput.Lines.Add('¸Þ½ÃÁö: ' + MessageStr); // 3. ¼º°ø ½Ã ½ÇÁ¦ µ¥ÀÌÅÍ(data) ÆÄ½Ì if (Status = 'success') and JsonObject.TryGetValue('data', DataArray) then begin MemoOutput.Lines.Add('[µ¥ÀÌÅÍ ³»¿ª]'); for I := 0 to DataArray.Count - 1 do begin DataItem := DataArray.Items[I]; if DataItem is TJSONObject then begin // °¢ ·¹ÄÚµåÀÇ Å°(Ä÷³¸í)-°ª(µ¥ÀÌÅÍ)À» ÃßÃâÇÏ¿© Ãâ·Â for Pair in (DataItem as TJSONObject) do begin MemoOutput.Lines.Add(' ' + Pair.JsonString.Value + ': ' + Pair.JsonValue.Value); end; MemoOutput.Lines.Add(' ------------------'); end; end; end // 4. µ¥ÀÌÅͰ¡ ¾ø´Â °æ¿ì(empty) ó¸® else if Status = 'empty' then begin MemoOutput.Lines.Add('°Ë»ö °á°ú°¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù.'); end; MemoOutput.Lines.Add('------------------------'); MemoOutput.GoToTextEnd; end else begin MemoOutput.Lines.Add('JSON ÀÀ´ä ±¸Á¶°¡ ±âÁ¸°ú ´Ù¸¨´Ï´Ù.'); end; end; end else begin Timer1.Enabled := False; ShowMessage('¼­¹ö ¿À·ù (' + RESTResponse1.StatusCode.ToString + '): ' + RESTResponse1.StatusText); end; end; procedure TForm1.MemoInputKeyDown(Sender: TObject; var Key: Word; var KeyChar: WideChar; Shift: TShiftState); var memostr : string; begin // 1. ¿£ÅÍ۰¡ ¾Æ´Ï¸é ¹«Á¶°Ç Å»Ãâ (ÇÑ±Û Á¶ÇÕ ¿À·ù ¹æÁö) if Key <> vkReturn then Exit; // 2. Shift + Enter´Â ÁÙ¹Ù²Þ Çã¿ë if ssShift in Shift then Exit; memostr := MemoInput.Text; // 3. ³»¿ëÀÌ ÀÖÀ» ¶§¸¸ Àü¼Û if Trim(memostr) <> '' then begin // [Áß¿ä] ¼ø¼­°¡ ÇÙ½ÉÀÔ´Ï´Ù! // (1) ¸ÕÀú Ű ÀÔ·ÂÀ» '¹«È¿È­' ½ÃÄѼ­ ´õ ÀÌ»ó ¿£ÅͰ¡ ¸ÔÁö ¾Ê°Ô ÇÔ Key := 0; KeyChar := #0; MemoResponse.Text := ''; Timer1.Enabled := True; // (2) ±× ´ÙÀ½¿¡ Àü¼ÛÇÏ°í ¸Þ¸ðÀåÀ» ºñ¿ò BtnSendClick(nil); // (3) ¸Þ¸ðÀåÀÌ ºñ¿öÁø ÈÄ, Æ÷Ä¿½º³ª Ä¿¼­ À§Ä¡ ÀçÁ¶Á¤ (¼±Åà »çÇ×) // MemoInput.SelStart := 0; end else begin // ³»¿ëÀÌ ¾ø¾îµµ ¿£ÅÍŰ ÀÔ·Â ÀÚü´Â ¸·¾Æ¾ß ÁٹٲÞÀÌ ¾È »ý±è Timer1.Enabled := False; MemoInput.Text; MemoInput.Lines.Add(''); Key := 0; KeyChar := #0; end; end; procedure TForm1.Timer1Timer(Sender: TObject); begin MemoResponse.Text := MemoResponse.Text + '. '; end; end.