Test-Apps für Gemini Api und Blockly

This commit is contained in:
Michael Schimmel
2025-06-10 17:08:09 +02:00
parent 312be15cc8
commit 0e598d595e
8 changed files with 1555 additions and 35 deletions
+204
View File
@@ -0,0 +1,204 @@
unit MainUnit;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
System.Net.HttpClient, System.Net.HttpClientComponent, System.JSON, System.Net.Mime, Vcl.AppEvnts,
Myc.Futures, System.Generics.Collections, ApiKey;
type
// NEU: Ein Record, um einen einzelnen Redebeitrag in der Konversation zu speichern
TChatTurn = record
Role: string; // 'user' oder 'model'
Text: string;
end;
TForm1 = class(TForm)
AnswerMemo: TMemo;
ExecButton: TButton;
ApplicationEvents: TApplicationEvents;
PromptMemo: TMemo;
procedure ExecButtonClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
private
FHttpClient: TNetHTTPClient;
FMyApiKey: string;
FAnswer: TFuture<String>;
FChatHistory: TList<TChatTurn>; // NEU: Liste für den Konversationsverlauf
procedure SendPrompt;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
const
GEMINI_MODEL = 'gemini-2.5-flash-preview-05-20';
API_BASE_URL = 'https://generativelanguage.googleapis.com/v1beta/models/';
{ TForm1 }
procedure TForm1.FormCreate(Sender: TObject);
begin
FHttpClient := TNetHTTPClient.Create(nil);
FMyApiKey := ApiKey.Value; // Eingelesen aus ApiKey.pas
// NEU: Initialisiert die Liste für den Konversationsverlauf
FChatHistory := TList<TChatTurn>.Create;
// Optional: Füge hier einen initialen System-Prompt hinzu, wenn gewünscht.
// Dieser wird dann immer als erste Nachricht mitgesendet.
// var initialTurn: TChatTurn;
// initialTurn.Role := 'user';
// initialTurn.Text := 'Du bist ein Delphi-Entwicklungs-Assistent...';
// FChatHistory.Add(initialTurn);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FAnswer.WaitFor;
FHttpClient.Free;
FChatHistory.Free; // NEU: Gibt die Verlaufsliste frei
end;
procedure TForm1.ApplicationEventsIdle(Sender: TObject; var Done: Boolean);
var
answerText: string;
modelTurn: TChatTurn;
begin
if FAnswer.Done.IsSet and not ExecButton.Enabled then
begin
answerText := FAnswer.Value;
AnswerMemo.Lines.Add(answerText);
// NEU: Füge die Antwort des Modells zum Verlauf hinzu
if not answerText.StartsWith('Fehler!') then
begin
modelTurn.Role := 'model';
modelTurn.Text := answerText;
FChatHistory.Add(modelTurn);
end;
FAnswer := FAnswer.Null;
ExecButton.Enabled := True;
end;
end;
procedure TForm1.ExecButtonClick(Sender: TObject);
begin
SendPrompt;
end;
procedure TForm1.SendPrompt;
var
userPrompt: string;
userTurn: TChatTurn;
begin
if not ExecButton.Enabled then
Exit;
userPrompt := PromptMemo.Lines.Text;
if userPrompt.IsEmpty then
begin
ShowMessage('Bitte geben Sie einen Prompt ein.');
Exit;
end;
// NEU: Füge die aktuelle Benutzereingabe zum Verlauf hinzu
userTurn.Role := 'user';
userTurn.Text := userPrompt;
FChatHistory.Add(userTurn);
// NEU: Leere das Eingabefeld für die nächste Nachricht
PromptMemo.Clear;
ExecButton.Enabled := False;
AnswerMemo.Lines.Add('');
AnswerMemo.Lines.Add('--- [USER] ---');
AnswerMemo.Lines.Add(userPrompt);
AnswerMemo.Lines.Add('... sende Anfrage an Gemini ...');
FAnswer := TFuture<string>.Construct(
function: string
var
jsonRequest: TJSONObject;
jsonContents: TJSONArray;
requestBody: TStringStream;
response: IHTTPResponse;
responseJson: TJSONValue;
apiUrl: string;
turn: TChatTurn;
begin
try
// 1. JSON-Body aus dem gesamten Konversationsverlauf erstellen
jsonRequest := TJSONObject.Create;
try
jsonContents := TJSONArray.Create;
jsonRequest.AddPair('contents', jsonContents);
// NEU: Iteriere durch den Verlauf und baue die JSON-Struktur auf
for turn in FChatHistory do
begin
var jsonTurn := TJSONObject.Create;
jsonTurn.AddPair('role', TJSONString.Create(turn.Role));
var jsonParts := TJSONArray.Create;
jsonTurn.AddPair('parts', jsonParts);
var jsonText := TJSONObject.Create;
jsonText.AddPair('text', TJSONString.Create(turn.Text));
jsonParts.Add(jsonText);
jsonContents.Add(jsonTurn);
end;
// 2. Request senden
requestBody := TStringStream.Create(jsonRequest.ToString, TEncoding.UTF8);
try
apiUrl := API_BASE_URL + GEMINI_MODEL + ':generateContent?key=' + FMyApiKey;
response := FHttpClient.Post(apiUrl, requestBody, nil);
// 3. Antwort verarbeiten
if (response.StatusCode = 200) then
begin
responseJson := TJSONObject.ParseJSONValue(response.ContentAsString(TEncoding.UTF8));
try
Result := responseJson.GetValue<TJSONArray>('candidates')
.Items[0].GetValue<TJSONObject>('content')
.GetValue<TJSONArray>('parts')
.Items[0].GetValue<string>('text');
finally
responseJson.Free;
end;
end
else
begin
Result := 'Fehler! Status: ' + response.StatusCode.ToString + ' - ' + response.StatusText +
sLineBreak + response.ContentAsString;
end;
finally
requestBody.Free;
end;
finally
jsonRequest.Free;
end;
except
on E: Exception do
begin
Result := '--- FEHLER IM TASK ---' + sLineBreak + E.Message;
end;
end;
end);
end;
end.