Skip to content

Commit 37bdffd

Browse files
committed
refactor/treatments-return-ais
1 parent 81ae19e commit 37bdffd

16 files changed

+360
-222
lines changed

Package/DelphiAIDeveloper.dpk

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ contains
5757
DelphiAIDev.Test in '..\Src\Test\DelphiAIDev.Test.pas',
5858
DelphiAIDev.Settings.View in '..\Src\Settings\DelphiAIDev.Settings.View.pas' {DelphiAIDevSettingsView},
5959
DelphiAIDev.Settings in '..\Src\Settings\DelphiAIDev.Settings.pas',
60-
DelphiAIDev.AI in '..\Src\AI\DelphiAIDev.AI.pas',
60+
DelphiAIDev.AI.Facade in '..\Src\AI\DelphiAIDev.AI.Facade.pas',
6161
DelphiAIDev.Chat.View in '..\Src\Chat\DelphiAIDev.Chat.View.pas' {DelphiAIDevChatView},
6262
DelphiAIDev.Chat.ProcessResponse in '..\Src\Chat\DelphiAIDev.Chat.ProcessResponse.pas',
6363
DelphiAIDev.AI.Gemini in '..\Src\AI\DelphiAIDev.AI.Gemini.pas',
@@ -113,6 +113,7 @@ contains
113113
DelphiAIDev.IDE.NTAEditViewNotifier in '..\Src\IDE\NTAEditViewNotifier\DelphiAIDev.IDE.NTAEditViewNotifier.pas',
114114
DelphiAIDev.CodeCompletion.Search in '..\Src\CodeCompletion\DelphiAIDev.CodeCompletion.Search.pas',
115115
DelphiAIDev.Test.Client in '..\Src\Test\DelphiAIDev.Test.Client.pas',
116-
DelphiAIDev.CodeCompletion.KeyTab in '..\Src\CodeCompletion\DelphiAIDev.CodeCompletion.KeyTab.pas';
116+
DelphiAIDev.CodeCompletion.KeyTab in '..\Src\CodeCompletion\DelphiAIDev.CodeCompletion.KeyTab.pas',
117+
DelphiAIDev.AI.Response in '..\Src\AI\DelphiAIDev.AI.Response.pas';
117118

118119
end.

Package/DelphiAIDeveloper.dproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@
154154
<Form>DelphiAIDevSettingsView</Form>
155155
</DCCReference>
156156
<DCCReference Include="..\Src\Settings\DelphiAIDev.Settings.pas"/>
157-
<DCCReference Include="..\Src\AI\DelphiAIDev.AI.pas"/>
157+
<DCCReference Include="..\Src\AI\DelphiAIDev.AI.Facade.pas"/>
158158
<DCCReference Include="..\Src\Chat\DelphiAIDev.Chat.View.pas">
159159
<Form>DelphiAIDevChatView</Form>
160160
</DCCReference>
@@ -229,6 +229,7 @@
229229
<DCCReference Include="..\Src\CodeCompletion\DelphiAIDev.CodeCompletion.Search.pas"/>
230230
<DCCReference Include="..\Src\Test\DelphiAIDev.Test.Client.pas"/>
231231
<DCCReference Include="..\Src\CodeCompletion\DelphiAIDev.CodeCompletion.KeyTab.pas"/>
232+
<DCCReference Include="..\Src\AI\DelphiAIDev.AI.Response.pas"/>
232233
<RcItem Include="Img\c4d_Logo.bmp">
233234
<ResourceType>BITMAP</ResourceType>
234235
<ResourceId>c4d_Logo</ResourceId>

Src/AI/DelphiAIDev.AI.ChatGPT.pas

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,25 @@ interface
1616
TDelphiAIDevAIChatGPT = class(TInterfacedObject, IDelphiAIDevAI)
1717
private
1818
FSettings: TDelphiAIDevSettings;
19+
FResponse: IDelphiAIDevAIResponse;
1920
protected
20-
function GetResponse(const AQuestion: string): string;
21+
function GetResponse(const AQuestion: string): IDelphiAIDevAIResponse;
2122
public
22-
class function New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
23-
constructor Create(const ASettings: TDelphiAIDevSettings);
23+
constructor Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse);
2424
end;
2525

2626
implementation
2727

2828
const
2929
API_JSON_BODY_BASE = '{"model": "%s", "messages": [{"role": "user", "content": "%s"}], "stream": false, "max_tokens": 2048}';
3030

31-
class function TDelphiAIDevAIChatGPT.New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
32-
begin
33-
Result := Self.Create(ASettings);
34-
end;
35-
36-
constructor TDelphiAIDevAIChatGPT.Create(const ASettings: TDelphiAIDevSettings);
31+
constructor TDelphiAIDevAIChatGPT.Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse);
3732
begin
3833
FSettings := ASettings;
34+
FResponse := AResponse;
3935
end;
4036

41-
function TDelphiAIDevAIChatGPT.GetResponse(const AQuestion: string): string;
37+
function TDelphiAIDevAIChatGPT.GetResponse(const AQuestion: string): IDelphiAIDevAIResponse;
4238
var
4339
LResponse: IResponse;
4440
LJsonValueAll: TJSONValue;
@@ -48,8 +44,9 @@ function TDelphiAIDevAIChatGPT.GetResponse(const AQuestion: string): string;
4844
LJsonValueMessage: TJSONValue;
4945
LJsonObjMessage: TJSONObject;
5046
LItemChoices: Integer;
47+
LResult: string;
5148
begin
52-
Result := '';
49+
Result := FResponse;
5350

5451
LResponse := TRequest.New
5552
.BaseURL(FSettings.BaseUrlOpenAI)
@@ -59,18 +56,29 @@ function TDelphiAIDevAIChatGPT.GetResponse(const AQuestion: string): string;
5956
.AddBody(Format(API_JSON_BODY_BASE, [FSettings.ModelOpenAI, AQuestion]))
6057
.Post;
6158

59+
FResponse.SetStatusCode(LResponse.StatusCode);
60+
6261
if LResponse.StatusCode <> 200 then
63-
Exit('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
62+
begin
63+
FResponse.SetContentText('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
64+
Exit;
65+
end;
6466

6567
LJsonValueAll := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(LResponse.Content), 0);
6668
if not(LJsonValueAll is TJSONObject) then
67-
Exit('The question cannot be answered, return object not found.' + sLineBreak +
69+
begin
70+
FResponse.SetContentText('The question cannot be answered, return object not found.' + sLineBreak +
6871
'Return: ' + LResponse.Content);
72+
Exit;
73+
end;
6974

7075
LJsonValueChoices := TJSONObject(LJsonValueAll).GetValue('choices');
7176
if not(LJsonValueChoices is TJSONArray) then
72-
Exit('The question cannot be answered, choices not found.' + sLineBreak +
77+
begin
78+
FResponse.SetContentText('The question cannot be answered, choices not found.' + sLineBreak +
7379
'Return: ' + LResponse.Content);
80+
Exit;
81+
end;
7482

7583
LJsonArrayChoices := LJsonValueChoices as TJSONArray;
7684
for LItemChoices := 0 to Pred(LJsonArrayChoices.Count) do
@@ -88,10 +96,10 @@ function TDelphiAIDevAIChatGPT.GetResponse(const AQuestion: string): string;
8896

8997
//GET MESSAGE LIKE TJSONObject
9098
LJsonObjMessage := LJsonValueMessage as TJSONObject;
91-
Result := Result + TJSONString(LJsonObjMessage.GetValue('content')).Value.Trim + sLineBreak;
99+
LResult := LResult + TJSONString(LJsonObjMessage.GetValue('content')).Value.Trim + sLineBreak;
92100
end;
93101

94-
Result := Result.Trim;
102+
FResponse.SetContentText(LResult.Trim);
95103
end;
96104

97105
end.

Src/AI/DelphiAIDev.AI.Facade.pas

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
unit DelphiAIDev.AI.Facade;
2+
3+
interface
4+
5+
uses
6+
System.SysUtils,
7+
System.Classes,
8+
DelphiAIDev.Utils,
9+
DelphiAIDev.Types,
10+
DelphiAIDev.Settings,
11+
DelphiAIDev.AI.Interfaces,
12+
DelphiAIDev.AI.Response,
13+
DelphiAIDev.AI.Gemini,
14+
DelphiAIDev.AI.ChatGPT,
15+
DelphiAIDev.AI.Groq,
16+
DelphiAIDev.AI.Ollama;
17+
18+
type
19+
IDelphiAIDevAIResponse = DelphiAIDev.AI.Interfaces.IDelphiAIDevAIResponse;
20+
21+
TDelphiAIDevAIFacade = class
22+
private
23+
FAiUse: TC4DAiAvailable;
24+
FSettings: TDelphiAIDevSettings;
25+
FResponse: IDelphiAIDevAIResponse;
26+
public
27+
constructor Create;
28+
destructor Destroy; override;
29+
function AiUse(const Value: TC4DAiAvailable): TDelphiAIDevAIFacade;
30+
function ProcessSend(const AQuestion: string): TDelphiAIDevAIFacade;
31+
function Response: IDelphiAIDevAIResponse;
32+
end;
33+
34+
implementation
35+
36+
constructor TDelphiAIDevAIFacade.Create;
37+
begin
38+
FSettings := TDelphiAIDevSettings.GetInstance;
39+
FSettings.LoadData;
40+
FAiUse := FSettings.AIDefault;
41+
FResponse := TDelphiAIDevAIResponse.New;
42+
end;
43+
44+
destructor TDelphiAIDevAIFacade.Destroy;
45+
begin
46+
inherited;
47+
end;
48+
49+
function TDelphiAIDevAIFacade.AiUse(const Value: TC4DAiAvailable): TDelphiAIDevAIFacade;
50+
begin
51+
Result := Self;
52+
FAiUse := Value;
53+
end;
54+
55+
function TDelphiAIDevAIFacade.ProcessSend(const AQuestion: string): TDelphiAIDevAIFacade;
56+
var
57+
LQuestion: string;
58+
LRequest: IDelphiAIDevAI;
59+
begin
60+
Result := Self;
61+
LQuestion := TUtils.AdjustQuestionToJson(AQuestion);
62+
63+
if TUtils.DebugMyIsOn then
64+
TUtils.AddLogDeleteFileFirst(LQuestion, 'DelphiAIDevAI_ProcessSend');
65+
66+
case FAiUse of
67+
TC4DAiAvailable.Gemini:
68+
LRequest := TDelphiAIDevAIGemini.Create(FSettings, FResponse);
69+
TC4DAiAvailable.OpenAI:
70+
LRequest := TDelphiAIDevAIChatGPT.Create(FSettings, FResponse);
71+
TC4DAiAvailable.Groq:
72+
LRequest := TDelphiAIDevAIGroq.Create(FSettings, FResponse);
73+
TC4DAiAvailable.Ollama:
74+
LRequest := TDelphiAIDevAIOllama.Create(FSettings, FResponse);
75+
else
76+
FResponse.SetContentText('Default AI not reported in Delphi AI Developer settings');
77+
Exit;
78+
end;
79+
80+
LRequest.GetResponse(LQuestion);
81+
end;
82+
83+
function TDelphiAIDevAIFacade.Response: IDelphiAIDevAIResponse;
84+
begin
85+
Result := FResponse;
86+
end;
87+
88+
end.

Src/AI/DelphiAIDev.AI.Gemini.pas

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,32 @@ interface
1010
DelphiAIDev.Consts,
1111
DelphiAIDev.Utils,
1212
DelphiAIDev.Settings,
13-
DelphiAIDev.AI.Interfaces;
13+
DelphiAIDev.AI.Interfaces,
14+
DelphiAIDev.AI.Response;
1415

1516
type
1617
TDelphiAIDevAIGemini = class(TInterfacedObject, IDelphiAIDevAI)
1718
private
1819
FSettings: TDelphiAIDevSettings;
20+
FResponse: IDelphiAIDevAIResponse;
1921
protected
20-
function GetResponse(const AQuestion: string): string;
22+
function GetResponse(const AQuestion: string): IDelphiAIDevAIResponse;
2123
public
22-
class function New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
23-
constructor Create(const ASettings: TDelphiAIDevSettings);
24+
constructor Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse);
2425
end;
2526

2627
implementation
2728

2829
const
2930
API_JSON_BODY_BASE = '{"contents": [{"parts": [ {"text": "%s"}]}]}';
3031

31-
class function TDelphiAIDevAIGemini.New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
32-
begin
33-
Result := Self.Create(ASettings);
34-
end;
35-
36-
constructor TDelphiAIDevAIGemini.Create(const ASettings: TDelphiAIDevSettings);
32+
constructor TDelphiAIDevAIGemini.Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse);
3733
begin
3834
FSettings := ASettings;
35+
FResponse := AResponse;
3936
end;
4037

41-
function TDelphiAIDevAIGemini.GetResponse(const AQuestion: string): string;
38+
function TDelphiAIDevAIGemini.GetResponse(const AQuestion: string): IDelphiAIDevAIResponse;
4239
var
4340
LApiUrl: string;
4441
LResponse: IResponse;
@@ -49,23 +46,32 @@ function TDelphiAIDevAIGemini.GetResponse(const AQuestion: string): string;
4946
LJsonObjParts: TJsonObject;
5047
LItemCandidates: Integer;
5148
LItemParts: Integer;
49+
LResult: string;
5250
begin
53-
Result := '';
54-
LApiUrl := FSettings.BaseUrlGemini + FSettings.ModelGemini + '?key=' + FSettings.ApiKeyGemini;
51+
Result := FResponse;
5552

53+
LApiUrl := FSettings.BaseUrlGemini + FSettings.ModelGemini + '?key=' + FSettings.ApiKeyGemini;
5654
LResponse := TRequest.New
5755
.BaseURL(LApiUrl)
5856
.Accept(TConsts.APPLICATION_JSON)
5957
.AddBody(Format(API_JSON_BODY_BASE, [AQuestion]))
6058
.Post;
6159

60+
FResponse.SetStatusCode(LResponse.StatusCode);
61+
6262
if LResponse.StatusCode <> 200 then
63-
Exit('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
63+
begin
64+
FResponse.SetContentText('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
65+
Exit;
66+
end;
6467

6568
LJsonValueAll := TJsonObject.ParseJSONValue(LResponse.Content);
6669
if not(LJsonValueAll is TJSONObject) then
67-
Exit('The question cannot be answered, return object not found.' + sLineBreak +
70+
begin
71+
FResponse.SetContentText('The question cannot be answered, return object not found.' + sLineBreak +
6872
'Return: ' + LResponse.Content);
73+
Exit;
74+
end;
6975

7076
LJsonArrayCandidates := (LJsonValueAll as TJsonObject).GetValue<TJsonArray>('candidates');
7177
for LItemCandidates := 0 to Pred(LJsonArrayCandidates.Count) do
@@ -75,11 +81,11 @@ function TDelphiAIDevAIGemini.GetResponse(const AQuestion: string): string;
7581
for LItemParts := 0 to Pred(LJsonArrayParts.Count) do
7682
begin
7783
LJsonObjParts := LJsonArrayParts.Items[LItemParts] as TJsonObject;
78-
Result := Result + LJsonObjParts.GetValue<string>('text').Trim + sLineBreak;
84+
LResult := LResult + LJsonObjParts.GetValue<string>('text').Trim + sLineBreak;
7985
end;
8086
end;
8187

82-
Result := Result.Trim;
88+
FResponse.SetContentText(LResult.Trim);
8389
end;
8490

8591
end.

Src/AI/DelphiAIDev.AI.Groq.pas

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,35 @@ interface
1616
TDelphiAIDevAIGroq = class(TInterfacedObject, IDelphiAIDevAI)
1717
private
1818
FSettings: TDelphiAIDevSettings;
19+
FResponse: IDelphiAIDevAIResponse;
1920
protected
20-
function GetResponse(const AQuestion: string): string;
21+
function GetResponse(const AQuestion: string): IDelphiAIDevAIResponse;
2122
public
22-
class function New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
23-
constructor Create(const ASettings: TDelphiAIDevSettings);
23+
constructor Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse);
2424
end;
2525

2626
implementation
2727

2828
const
2929
API_JSON_BODY_BASE = '{"messages": [{"role": "user", "content": "%s"}], "model": "%s"}';
3030

31-
class function TDelphiAIDevAIGroq.New(const ASettings: TDelphiAIDevSettings): IDelphiAIDevAI;
32-
begin
33-
Result := Self.Create(ASettings);
34-
end;
35-
36-
constructor TDelphiAIDevAIGroq.Create(const ASettings: TDelphiAIDevSettings);
31+
constructor TDelphiAIDevAIGroq.Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse);
3732
begin
3833
FSettings := ASettings;
34+
FResponse := AResponse;
3935
end;
4036

41-
function TDelphiAIDevAIGroq.GetResponse(const AQuestion: string): string;
37+
function TDelphiAIDevAIGroq.GetResponse(const AQuestion: string): IDelphiAIDevAIResponse;
4238
var
4339
LResponse: IResponse;
4440
LJsonValueAll: TJSONVALUE;
4541
LJsonArrayChoices: TJsonArray;
4642
LJsonObjMessage: TJsonObject;
4743
LContent: string;
4844
LItemChoices: Integer;
45+
LResult: string;
4946
begin
50-
Result := '';
47+
Result := FResponse;
5148

5249
LResponse := TRequest.New
5350
.BaseURL(FSettings.BaseUrlGroq)
@@ -57,23 +54,31 @@ function TDelphiAIDevAIGroq.GetResponse(const AQuestion: string): string;
5754
.AddBody(Format(API_JSON_BODY_BASE, [AQuestion, FSettings.ModelGroq]))
5855
.Post;
5956

57+
FResponse.SetStatusCode(LResponse.StatusCode);
58+
6059
if LResponse.StatusCode <> 200 then
61-
Exit('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
60+
begin
61+
FResponse.SetContentText('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content);
62+
Exit;
63+
end;
6264

6365
LJsonValueAll := TJsonObject.ParseJSONValue(LResponse.Content);
6466
if not(LJsonValueAll is TJSONObject) then
65-
Exit('The question cannot be answered, return object not found.' + sLineBreak +
67+
begin
68+
FResponse.SetContentText('The question cannot be answered, return object not found.' + sLineBreak +
6669
'Return: ' + LResponse.Content);
70+
Exit;
71+
end;
6772

6873
LJsonArrayChoices := (LJsonValueAll as TJsonObject).GetValue<TJsonArray>('choices');
6974
for LItemChoices := 0 to Pred(LJsonArrayChoices.Count) do
7075
begin
7176
LJsonObjMessage := LJsonArrayChoices.Items[LItemChoices].GetValue<TJsonObject>('message');
7277
LContent := LJsonObjMessage.GetValue<string>('content');
73-
Result := Result + LContent.Trim + sLineBreak;
78+
LResult := LResult + LContent.Trim + sLineBreak;
7479
end;
7580

76-
Result := Result.Trim;
81+
FResponse.SetContentText(LResult.Trim);
7782
end;
7883

7984
end.

0 commit comments

Comments
 (0)