Skip to content

Commit 7a6cb7e

Browse files
committed
Merge branch 'develop'
2 parents c844463 + d056f0a commit 7a6cb7e

25 files changed

+849
-295
lines changed

Package/DelphiAIDeveloper.dpk

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ contains
4949
DelphiAIDev.MainMenu in '..\Src\MainMenu\DelphiAIDev.MainMenu.pas',
5050
DelphiAIDev.MainMenu.Clicks in '..\Src\MainMenu\DelphiAIDev.MainMenu.Clicks.pas',
5151
DelphiAIDev.View.About in '..\Src\View\DelphiAIDev.View.About.pas' {DelphiAIDevViewAbout},
52-
Test in '..\Src\Test\Test.pas',
52+
DelphiAIDev.Test in '..\Src\Test\DelphiAIDev.Test.pas',
5353
DelphiAIDev.Settings.View in '..\Src\Settings\DelphiAIDev.Settings.View.pas' {DelphiAIDevSettingsView},
5454
DelphiAIDev.Settings in '..\Src\Settings\DelphiAIDev.Settings.pas',
5555
DelphiAIDev.Chat in '..\Src\Chat\DelphiAIDev.Chat.pas',
@@ -72,6 +72,8 @@ contains
7272
DelphiAIDev.DefaultsQuestions.AddEdit.View in '..\Src\DefaultsQuestions\DelphiAIDev.DefaultsQuestions.AddEdit.View.pas' {DelphiAIDevDefaultsQuestionsAddEditView},
7373
DelphiAIDev.DefaultsQuestions.PopupMenu in '..\Src\DefaultsQuestions\DelphiAIDev.DefaultsQuestions.PopupMenu.pas',
7474
DelphiAIDev.Utils.ABMenuAction in '..\Src\Utils\DelphiAIDev.Utils.ABMenuAction.pas',
75-
DelphiAIDev.IDE.Splash in '..\Src\IDE\Splash\DelphiAIDev.IDE.Splash.pas';
75+
DelphiAIDev.IDE.Splash in '..\Src\IDE\Splash\DelphiAIDev.IDE.Splash.pas',
76+
DelphiAIDev.Chat.ProcessResponse in '..\Src\Chat\DelphiAIDev.Chat.ProcessResponse.pas',
77+
DelphiAIDev.AI.Groq in '..\Src\AI\DelphiAIDev.AI.Groq.pas';
7678

7779
end.

Package/DelphiAIDeveloper.dproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
<DCCReference Include="..\Src\View\DelphiAIDev.View.About.pas">
147147
<Form>DelphiAIDevViewAbout</Form>
148148
</DCCReference>
149-
<DCCReference Include="..\Src\Test\Test.pas"/>
149+
<DCCReference Include="..\Src\Test\DelphiAIDev.Test.pas"/>
150150
<DCCReference Include="..\Src\Settings\DelphiAIDev.Settings.View.pas">
151151
<Form>DelphiAIDevSettingsView</Form>
152152
<FormType>dfm</FormType>
@@ -179,6 +179,8 @@
179179
<DCCReference Include="..\Src\DefaultsQuestions\DelphiAIDev.DefaultsQuestions.PopupMenu.pas"/>
180180
<DCCReference Include="..\Src\Utils\DelphiAIDev.Utils.ABMenuAction.pas"/>
181181
<DCCReference Include="..\Src\IDE\Splash\DelphiAIDev.IDE.Splash.pas"/>
182+
<DCCReference Include="..\Src\Chat\DelphiAIDev.Chat.ProcessResponse.pas"/>
183+
<DCCReference Include="..\Src\AI\DelphiAIDev.AI.Groq.pas"/>
182184
<RcItem Include="Img\c4d_gear.bmp">
183185
<ResourceType>BITMAP</ResourceType>
184186
<ResourceId>c4d_gear</ResourceId>

Src/AI/DelphiAIDev.AI.ChatGPT.pas

Lines changed: 20 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,23 +39,21 @@ constructor TDelphiAIDevAIChatGPT.Create(const ASettings: TDelphiAIDevSettings);
3939

4040
function TDelphiAIDevAIChatGPT.GetResponse(const AQuestion: string): string;
4141
var
42-
LApiUrl: string;
4342
LQuestion: string;
4443
LResponse: IResponse;
45-
LReturnValue: TJSONValue;
46-
LChoicesValue: TJSONValue;
47-
LChoicesArray: TJSONArray;
48-
LChoicesObj: TJSONObject;
49-
LMessageValue: TJSONValue;
50-
LMessageObj: TJSONObject;
51-
I: Integer;
44+
LJsonValueAll: TJSONValue;
45+
LJsonValueChoices: TJSONValue;
46+
LJsonArrayChoices: TJSONArray;
47+
LJsonObjChoices: TJSONObject;
48+
LJsonValueMessage: TJSONValue;
49+
LJsonObjMessage: TJSONObject;
50+
LItemChoices: Integer;
5251
begin
5352
Result := '';
54-
LApiUrl := FSettings.BaseUrlOpenAI;
5553
LQuestion := TUtils.AdjustQuestionToJson(AQuestion); //AQuestion.Replace(sLineBreak, '\n', [rfReplaceAll, rfIgnoreCase]);
5654

5755
LResponse := TRequest.New
58-
.BaseURL(LApiUrl)
56+
.BaseURL(FSettings.BaseUrlOpenAI)
5957
.ContentType('application/json')
6058
.Accept('application/json')
6159
.Token('Bearer ' + FSettings.ApiKeyOpenAI)
@@ -65,37 +63,33 @@ function TDelphiAIDevAIChatGPT.GetResponse(const AQuestion: string): string;
6563
if LResponse.StatusCode <> 200 then
6664
Exit('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
6765

68-
//TJSONValue COMPLETE
69-
LReturnValue := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(LResponse.Content), 0);
70-
if not(LReturnValue is TJSONObject) then
66+
LJsonValueAll := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(LResponse.Content), 0);
67+
if not(LJsonValueAll is TJSONObject) then
7168
Exit('The question cannot be answered, return object not found.' + sLineBreak +
7269
'Return: ' + LResponse.Content);
7370

74-
//GET CHOICES LIKE TJSONValue
75-
LChoicesValue := TJSONObject(LReturnValue).GetValue('choices');
76-
77-
if not(LChoicesValue is TJSONArray) then
71+
LJsonValueChoices := TJSONObject(LJsonValueAll).GetValue('choices');
72+
if not(LJsonValueChoices is TJSONArray) then
7873
Exit('The question cannot be answered, choices not found.' + sLineBreak +
7974
'Return: ' + LResponse.Content);
8075

81-
//CAST CHOICES LIKE TJSONArray
82-
LChoicesArray := LChoicesValue as TJSONArray;
83-
for I := 0 to Pred(LChoicesArray.Count) do
76+
LJsonArrayChoices := LJsonValueChoices as TJSONArray;
77+
for LItemChoices := 0 to Pred(LJsonArrayChoices.Count) do
8478
begin
85-
if not(LChoicesArray.Items[I] is TJSONObject) then
79+
if not(LJsonArrayChoices.Items[LItemChoices] is TJSONObject) then
8680
Continue;
8781

8882
//CAST ITEM CHOICES LIKE TJSONObject
89-
LChoicesObj := LChoicesArray.Items[I] as TJSONObject;
83+
LJsonObjChoices := LJsonArrayChoices.Items[LItemChoices] as TJSONObject;
9084

9185
//GET MESSAGE LIKE TJSONValue
92-
LMessageValue := LChoicesObj.GetValue('message');
93-
if not(LMessageValue is TJSONObject) then
86+
LJsonValueMessage := LJsonObjChoices.GetValue('message');
87+
if not(LJsonValueMessage is TJSONObject) then
9488
Continue;
9589

9690
//GET MESSAGE LIKE TJSONObject
97-
LMessageObj := LMessageValue as TJSONObject;
98-
Result := Result + TJSONString(LMessageObj.GetValue('content')).Value + sLineBreak;
91+
LJsonObjMessage := LJsonValueMessage as TJSONObject;
92+
Result := Result + TJSONString(LJsonObjMessage.GetValue('content')).Value.Trim + sLineBreak;
9993
end;
10094

10195
Result := Result.Trim;

Src/AI/DelphiAIDev.AI.Gemini.pas

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,12 @@ function TDelphiAIDevAIGemini.GetResponse(const AQuestion: string): string;
4242
LApiUrl: string;
4343
LQuestion: string;
4444
LResponse: IResponse;
45-
LJsonValue: TJSONVALUE;
46-
LJsonArray: TJsonArray;
47-
LPartsArray: TJsonArray;
48-
LJsonObj: TJsonObject;
49-
LPartsObj: TJsonObject;
50-
LJsonText: string;
51-
i, j: Integer;
45+
LJsonValueAll: TJSONVALUE;
46+
LJsonArrayCandidates: TJsonArray;
47+
LJsonArrayParts: TJsonArray;
48+
LJsonObjContent: TJsonObject;
49+
LJsonObjParts: TJsonObject;
50+
LItemCandidates, LItemParts: Integer;
5251
begin
5352
Result := '';
5453
LApiUrl := FSettings.BaseUrlGemini + FSettings.ModelGemini + '?key=' + FSettings.ApiKeyGemini;
@@ -61,28 +60,26 @@ function TDelphiAIDevAIGemini.GetResponse(const AQuestion: string): string;
6160
.Post;
6261

6362
if LResponse.StatusCode <> 200 then
64-
begin
65-
Result := 'Question cannot be answered' + sLineBreak +
66-
'Return: ' + LResponse.Content;
67-
Exit;
68-
end;
63+
Exit('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
6964

70-
LJsonValue := TJsonObject.ParseJSONValue(LResponse.Content);
71-
if LJsonValue is TJsonObject then
65+
LJsonValueAll := TJsonObject.ParseJSONValue(LResponse.Content);
66+
if not(LJsonValueAll is TJSONObject) then
67+
Exit('The question cannot be answered, return object not found.' + sLineBreak +
68+
'Return: ' + LResponse.Content);
69+
70+
LJsonArrayCandidates := (LJsonValueAll as TJsonObject).GetValue<TJsonArray>('candidates');
71+
for LItemCandidates := 0 to Pred(LJsonArrayCandidates.Count) do
7272
begin
73-
LJsonArray := (LJsonValue as TJsonObject).GetValue<TJsonArray>('candidates');
74-
for i := 0 to Pred(LJsonArray.Count) do
73+
LJsonObjContent := LJsonArrayCandidates.Items[LItemCandidates].GetValue<TJsonObject>('content');
74+
LJsonArrayParts := LJsonObjContent.GetValue<TJsonArray>('parts');
75+
for LItemParts := 0 to Pred(LJsonArrayParts.Count) do
7576
begin
76-
LJsonObj := LJsonArray.Items[i].GetValue<TJsonObject>('content');
77-
LPartsArray := LJsonObj.GetValue<TJsonArray>('parts');
78-
for j := 0 to Pred(LPartsArray.Count) do
79-
begin
80-
LPartsObj := LPartsArray.Items[j] as TJsonObject;
81-
LJsonText := LPartsObj.GetValue<string>('text');
82-
Result := LJsonText.Trim;
83-
end;
77+
LJsonObjParts := LJsonArrayParts.Items[LItemParts] as TJsonObject;
78+
Result := Result + LJsonObjParts.GetValue<string>('text').Trim + sLineBreak;
8479
end;
8580
end;
81+
82+
Result := Result.Trim;
8683
end;
8784

8885
end.

Src/AI/DelphiAIDev.AI.Groq.pas

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
unit DelphiAIDev.AI.Groq;
2+
3+
interface
4+
5+
uses
6+
System.SysUtils,
7+
System.JSON,
8+
System.Classes,
9+
RESTRequest4D,
10+
DelphiAIDev.Utils,
11+
DelphiAIDev.Settings,
12+
DelphiAIDev.AI.Interfaces;
13+
14+
type
15+
TDelphiAIDevAIGroq = class(TInterfacedObject, IDelphiAIDevAI)
16+
private
17+
FSettings: TDelphiAIDevSettings;
18+
protected
19+
function GetResponse(const AQuestion: string): string;
20+
public
21+
class function New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
22+
constructor Create(const ASettings: TDelphiAIDevSettings);
23+
end;
24+
25+
implementation
26+
27+
const
28+
API_JSON_BODY_BASE = '{"messages": [{"role": "user", "content": "%s"}], "model": "%s"}';
29+
30+
class function TDelphiAIDevAIGroq.New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
31+
begin
32+
Result := Self.Create(ASettings);
33+
end;
34+
35+
constructor TDelphiAIDevAIGroq.Create(const ASettings: TDelphiAIDevSettings);
36+
begin
37+
FSettings := ASettings;
38+
end;
39+
40+
function TDelphiAIDevAIGroq.GetResponse(const AQuestion: string): string;
41+
var
42+
LQuestion: string;
43+
LResponse: IResponse;
44+
LJsonValueAll: TJSONVALUE;
45+
LJsonArrayChoices: TJsonArray;
46+
LJsonObjMessage: TJsonObject;
47+
LContent: string;
48+
LItemChoices: Integer;
49+
begin
50+
Result := '';
51+
LQuestion := TUtils.AdjustQuestionToJson(AQuestion);
52+
53+
LResponse := TRequest.New
54+
.BaseURL(FSettings.BaseUrlGroq)
55+
.ContentType('application/json')
56+
.Accept('application/json')
57+
.Token('Bearer ' + FSettings.ApiKeyGroq)
58+
.AddBody(Format(API_JSON_BODY_BASE, [LQuestion, FSettings.ModelGroq]))
59+
.Post;
60+
61+
if LResponse.StatusCode <> 200 then
62+
Exit('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
63+
64+
LJsonValueAll := TJsonObject.ParseJSONValue(LResponse.Content);
65+
if not(LJsonValueAll is TJSONObject) then
66+
Exit('The question cannot be answered, return object not found.' + sLineBreak +
67+
'Return: ' + LResponse.Content);
68+
69+
LJsonArrayChoices := (LJsonValueAll as TJsonObject).GetValue<TJsonArray>('choices');
70+
for LItemChoices := 0 to Pred(LJsonArrayChoices.Count) do
71+
begin
72+
LJsonObjMessage := LJsonArrayChoices.Items[LItemChoices].GetValue<TJsonObject>('message');
73+
LContent := LJsonObjMessage.GetValue<string>('content');
74+
Result := Result + LContent.Trim + sLineBreak;
75+
end;
76+
77+
Result := Result.Trim;
78+
end;
79+
80+
end.

0 commit comments

Comments
 (0)