diff --git a/LGPD.md b/LGPD.md new file mode 100644 index 0000000..44686c9 --- /dev/null +++ b/LGPD.md @@ -0,0 +1,26 @@ +# LGPD Compliance + +The LGPD, or General Law for the Protection of Personal Data (Law No. 13.709/2018), is the Brazilian legislation that regulates the use, collection, storage and sharing of personal data of individuals in Brazil. + +## Introduction +**Delphi AI Developer** was developed for use in Delphi IDE in compliance with the guidelines of the General Law on the Protection of Personal Data (LGPD), ensuring that user data is not used by us. + +## Data Collection and Use +**Delphi AI Developer** uses Artificial Intelligence APIs to enhance the programming experience and facilitate interaction with the database structure. When operating, the plugin: +- **Sends code snippets and database structure to Artificial Intelligence APIs**, aiming to provide suggestions and automation in development. +- **Does not store any user information on external servers**, including code snippets, database structure or other personal data. + +## Database Structure Storage +The plugin **does not access, store or send data from the database** itself. Only the **database structure** is used, including the database name, table names, field names, field data types and field sizes. This structure is **stored locally in a JSON file** on the user's own computer, without being exposed to any server or external source. This local storage aims to optimize the plugin's performance and interaction with the APIs, while maintaining data security and privacy. + +## Data Subject Rights +Although Delphi AI Developer does not collect or store personal data, users can request more information about the functioning and data processing at any time. For questions related to the use of data by the tool, please contact **[contato@code4delphi.com.br](mailto:contato@code4delphi.com.br)**. + +## Segurança e Privacidade +O Delphi AI Developer adota medidas de segurança rigorosas para proteger as interações entre o plugin e as APIs de Inteligência Artificial, além de garantir que o arquivo JSON local seja seguro e acessível apenas ao usuário. Todo o processamento de dados é feito com transparência e alinhado aos princípios da LGPD. + +## Privacy Policy Updates +Any changes in LGPD compliance or data usage practices will be added to this page. + +## Contact +For questions or requests regarding the use of data by **Delphi AI Developer**, please contact **[contato@code4delphi.com.br](mailto:contato@code4delphi.com.br)**. diff --git a/Package/DelphiAIDeveloper.dpk b/Package/DelphiAIDeveloper.dpk index 576683c..28b6eda 100644 --- a/Package/DelphiAIDeveloper.dpk +++ b/Package/DelphiAIDeveloper.dpk @@ -114,6 +114,7 @@ contains DelphiAIDev.CodeCompletion.Search in '..\Src\CodeCompletion\DelphiAIDev.CodeCompletion.Search.pas', DelphiAIDev.Test.Client in '..\Src\Test\DelphiAIDev.Test.Client.pas', DelphiAIDev.CodeCompletion.KeyTab in '..\Src\CodeCompletion\DelphiAIDev.CodeCompletion.KeyTab.pas', - DelphiAIDev.AI.Response in '..\Src\AI\DelphiAIDev.AI.Response.pas'; + DelphiAIDev.AI.Response in '..\Src\AI\DelphiAIDev.AI.Response.pas', + DelphiAIDev.AI.Mistral in '..\Src\AI\DelphiAIDev.AI.Mistral.pas'; end. diff --git a/Package/DelphiAIDeveloper.dproj b/Package/DelphiAIDeveloper.dproj index 66a3dfc..cd6848e 100644 --- a/Package/DelphiAIDeveloper.dproj +++ b/Package/DelphiAIDeveloper.dproj @@ -2,13 +2,14 @@ {7EF46619-47CC-4A26-9369-BCDD8C5ECFA8} DelphiAIDeveloper.dpk - 18.8 + 20.2 VCL True Debug Win32 - 1 + 1048577 Package + DelphiAIDeveloper true @@ -38,6 +39,11 @@ Base true + + true + Base + true + true Base @@ -75,11 +81,13 @@ None android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar rtl;bindengine;bindcomp;RESTComponents;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACIBDriver;$(DCC_UsePackage) + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png None android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar rtl;bindengine;bindcomp;RESTComponents;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACIBDriver;$(DCC_UsePackage) + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png rtl;bindengine;bindcomp;RESTComponents;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACIBDriver;FireDACMySQLDriver;$(DCC_UsePackage) @@ -95,6 +103,13 @@ rtl;bindengine;bindcomp;RESTComponents;vclFireDAC;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACIBDriver;FireDACMySQLDriver;$(DCC_UsePackage) + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + true + 1033 + true + DEBUG;$(DCC_Define) true @@ -230,6 +245,7 @@ + BITMAP c4d_Logo @@ -262,10 +278,6 @@ BITMAP c4d_database_execute - - Cfg_2 - Base - Base @@ -273,6 +285,10 @@ Cfg_1 Base + + Cfg_2 + Base + Delphi.Personality.12 @@ -290,28 +306,15 @@ Microsoft Office XP Sample Automation Server Wrapper Components - - - - true - - - - - true - - - - - true - - - - - DelphiAIDeveloper.bpl - true - - + + + + + + + + + 1 @@ -320,16 +323,6 @@ 0 - - - classes - 1 - - - classes - 1 - - res\xml @@ -340,12 +333,6 @@ 1 - - - library\lib\armeabi-v7a - 1 - - library\lib\armeabi @@ -398,6 +385,16 @@ 1 + + + res\drawable-anydpi-v21 + 1 + + + res\drawable-anydpi-v21 + 1 + + res\values @@ -418,6 +415,66 @@ 1 + + + res\values-v31 + 1 + + + res\values-v31 + 1 + + + + + res\drawable-anydpi-v26 + 1 + + + res\drawable-anydpi-v26 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-anydpi-v33 + 1 + + + res\drawable-anydpi-v33 + 1 + + res\values @@ -428,6 +485,16 @@ 1 + + + res\values-night-v21 + 1 + + + res\values-night-v21 + 1 + + res\drawable @@ -448,6 +515,16 @@ 1 + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + res\drawable-ldpi @@ -588,6 +665,56 @@ 1 + + + res\drawable-anydpi-v24 + 1 + + + res\drawable-anydpi-v24 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-night-anydpi-v21 + 1 + + + res\drawable-night-anydpi-v21 + 1 + + + + + res\drawable-anydpi-v31 + 1 + + + res\drawable-anydpi-v31 + 1 + + + + + res\drawable-night-anydpi-v31 + 1 + + + res\drawable-night-anydpi-v31 + 1 + + 1 @@ -608,6 +735,10 @@ 1 .framework + + 1 + .framework + 0 @@ -621,6 +752,10 @@ 1 .dylib + + 1 + .dylib + 0 .dll;.bpl @@ -635,7 +770,7 @@ 1 .dylib - + 1 .dylib @@ -647,6 +782,10 @@ 1 .dylib + + 1 + .dylib + 0 .bpl @@ -665,7 +804,7 @@ 0 - + 0 @@ -674,394 +813,350 @@ 0 + + 0 + 0 - - - 1 - - + + 1 - + 1 - - + + + + + + Contents\Resources 1 - + + Contents\Resources 1 - + + Contents\Resources 1 - - - 1 - - + + + library\lib\armeabi-v7a 1 - + + library\lib\arm64-v8a 1 - - 1 1 - - 1 - - - - + 1 - + 1 - + 1 - - - + 1 - + 1 - - 1 + + 0 - - - 1 - - - 1 - - + + + library\lib\armeabi-v7a 1 - - + + 1 - + 1 - + 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 1 - + + + + 1 1 - + 1 - - - 1 - - + + + Assets 1 - + + Assets 1 - - - 1 - - + + + Assets 1 - + + Assets 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF - 1 - + - ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 - - - - - - + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - - - - Contents\Resources + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Contents\Resources + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - library\lib\armeabi-v7a - 1 - - - library\lib\arm64-v8a - 1 - - - 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - 1 - - - 1 - - - 1 - - - 1 - - - 0 - - - - - library\lib\armeabi-v7a + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - Assets + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Assets + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - - Assets + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - Assets + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1 - - + + + + + - - - - + + + + False @@ -1069,6 +1164,7 @@ False True False + True 12 diff --git a/Package/DelphiAIDeveloper.res b/Package/DelphiAIDeveloper.res index 9273b09..4a37369 100644 Binary files a/Package/DelphiAIDeveloper.res and b/Package/DelphiAIDeveloper.res differ diff --git a/README.md b/README.md index 75857a7..9b37e71 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Delphi AI Developer (Copilot) -Inspired by GitHub Copilot, Delphi AI Developer is a plugin that adds Artificial intelligence (AI) interaction capabilities to the Delphi IDE, using both the OpenAI API, Gemini API and Groq API, as well as offering offline AI support. +Inspired by GitHub Copilot, Delphi AI Developer is a plugin that adds Artificial intelligence (AI) interaction capabilities to the Delphi IDE, using both the OpenAI API, Gemini API, Mistral API and Groq API, as well as offering offline AI support. With Delphi AI Developer, you will have assistance in generating and refactoring code, facilitating and accelerating development. @@ -7,27 +7,13 @@ Receive suggestions for creating and improving code directly in the IDE and take ## 📞 Contacts -

- - - -   - - - -   - - - -   - - - -   - - - -

+[![Telegram](https://img.shields.io/badge/Telegram-Join-blue?logo=telegram)](https://t.me/Code4Delphi) +[![YouTube](https://img.shields.io/badge/YouTube-Join-red?logo=youtube&logoColor=red)](https://www.youtube.com/@code4delphi) +[![Instagram](https://img.shields.io/badge/Intagram-Follow-red?logo=instagram&logoColor=pink)](https://www.instagram.com/code4delphi/) +[![LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue)](https://www.linkedin.com/in/cesar-cardoso-dev) +[![Blog](https://img.shields.io/badge/Blog-Code4Delphi-F00?logo=delphi)](https://code4delphi.com.br/blog/) +[![Course](https://img.shields.io/badge/Course-Delphi-F00?logo=delphi)](https://go.hotmart.com/U81331747Y?dp=1) +[![E-mail](https://img.shields.io/badge/E--mail-Send-yellowgreen?logo=maildotru&logoColor=yellowgreen)](mailto:contato@code4delphi.com.br) ## 🚀 INSTALLATION @@ -63,10 +49,10 @@ Access the menu “AI Developer” > “Settings” > Tab “Preferences”
-## ⚪ CONFIGURING IAS ONLINE +## ⚪ CONFIGURING AI ONLINE You can choose between 3 APIs, Gemini (Google), ChatGPT (OpenAI) and Groq. Gemini and Groq APIs are free. -Access the menu “AI Developer” > “Settings” > Tab “IAs on-line” +Access the menu “AI Developer” > “Settings” > Tab “AI on-line” ![image](https://github.com/user-attachments/assets/2c3a45a2-94c8-4449-8c71-58246f6ca67f) 1. Inform the desired model. @@ -151,7 +137,7 @@ Note: If the current unit has any code selected, only the selected code snippet
-## 🟤 IAS OFF-LINE +## 🟤 AI OFF-LINE To use AI offline, follow these steps: 1. Install Ollama, which can be found at the following link: [https://ollama.com/download](https://ollama.com/download) @@ -159,15 +145,15 @@ To use AI offline, follow these steps: ![image](https://github.com/user-attachments/assets/1c259158-8118-421e-84ab-f6931b1438c0) 3. Open command prompt or terminal and run the command “ollama run ” and wait for the installation to finish ![image](https://github.com/user-attachments/assets/b5c12854-5ce4-4fe7-aa49-b0396f0d4040) -4. **To configure**, access the menu “AI Developer” > “Settings” > Tab “IAs off-Line“ +4. **To configure**, access the menu “AI Developer” > “Settings” > Tab “AI off-Line“ ![image](https://github.com/user-attachments/assets/f821ab05-743a-480f-a72b-f7ca3809ae6b)
## ▶️ DEMO VIDEO -We have also created a video with details on how to download, install and use the plugin. The video is in Portuguese (ptBR), but we are providing subtitles and possibly a video in English. -* [https://www.youtube.com/watch?v=2NAlUFK2FGs](https://www.youtube.com/watch?v=2NAlUFK2FGs) +For more details about the plugin, watch our talk, voted one of the best of Embarcadero Conference 2024. The video is in Portuguese (pt-BR), but we are providing subtitles and possibly an English version. +* [https://www.youtube.com/live/7UcfPyqR2TY?si=bLw27HQP4diF7TCB&t=2822](https://www.youtube.com/live/7UcfPyqR2TY?si=bLw27HQP4diF7TCB&t=2822)
@@ -176,6 +162,11 @@ Any suggestions or help are welcome. Send us a pull request or open an [issue](/
+## 📄 LGPD Compliance +[Access information about LGPD](https://github.com/Code4Delphi/Delphi-AI-Developer/blob/master/LGPD.md) + +
+ ## ⚠️ LICENSE `Delphi AI Developer` is free and open-source wizard licensed under the [MIT License](LICENSE). diff --git a/Src/AI/DelphiAIDev.AI.Facade.pas b/Src/AI/DelphiAIDev.AI.Facade.pas index ab1e983..d7f418d 100644 --- a/Src/AI/DelphiAIDev.AI.Facade.pas +++ b/Src/AI/DelphiAIDev.AI.Facade.pas @@ -13,6 +13,7 @@ interface DelphiAIDev.AI.Gemini, DelphiAIDev.AI.ChatGPT, DelphiAIDev.AI.Groq, + DelphiAIDev.AI.Mistral, DelphiAIDev.AI.Ollama; type @@ -70,6 +71,8 @@ function TDelphiAIDevAIFacade.ProcessSend(const AQuestion: string): TDelphiAIDev LRequest := TDelphiAIDevAIChatGPT.Create(FSettings, FResponse); TC4DAiAvailable.Groq: LRequest := TDelphiAIDevAIGroq.Create(FSettings, FResponse); + TC4DAiAvailable.Mistral: + LRequest := TDelphiAIDevAIMistral.Create(FSettings, FResponse); TC4DAiAvailable.Ollama: LRequest := TDelphiAIDevAIOllama.Create(FSettings, FResponse); else diff --git a/Src/AI/DelphiAIDev.AI.Mistral.pas b/Src/AI/DelphiAIDev.AI.Mistral.pas new file mode 100644 index 0000000..572dcba --- /dev/null +++ b/Src/AI/DelphiAIDev.AI.Mistral.pas @@ -0,0 +1,84 @@ +unit DelphiAIDev.AI.Mistral; + +interface + +uses + System.SysUtils, + System.JSON, + System.Classes, + RESTRequest4D, + DelphiAIDev.Consts, + DelphiAIDev.Utils, + DelphiAIDev.Settings, + DelphiAIDev.AI.Interfaces; + +type + TDelphiAIDevAIMistral = class(TInterfacedObject, IDelphiAIDevAI) + private + FSettings: TDelphiAIDevSettings; + FResponse: IDelphiAIDevAIResponse; + protected + function GetResponse(const AQuestion: string): IDelphiAIDevAIResponse; + public + constructor Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse); + end; + +implementation + +const + API_JSON_BODY_BASE = '{"messages": [{"role": "user", "content": "%s"}], "model": "%s"}'; + +constructor TDelphiAIDevAIMistral.Create(const ASettings: TDelphiAIDevSettings; const AResponse: IDelphiAIDevAIResponse); +begin + FSettings := ASettings; + FResponse := AResponse; +end; + +function TDelphiAIDevAIMistral.GetResponse(const AQuestion: string): IDelphiAIDevAIResponse; +var + LResponse: IResponse; + LJsonValueAll: TJSONVALUE; + LJsonArrayChoices: TJsonArray; + LJsonObjMessage: TJsonObject; + LContent: string; + LItemChoices: Integer; + LResult: string; +begin + Result := FResponse; + + LResponse := TRequest.New + .BaseURL(FSettings.BaseUrlMistral) + .ContentType(TConsts.APPLICATION_JSON) + .Accept(TConsts.APPLICATION_JSON) + .Token('Bearer ' + FSettings.ApiKeyMistral) + .AddBody(Format(API_JSON_BODY_BASE, [AQuestion, FSettings.ModelMistral])) + .Post; + + FResponse.SetStatusCode(LResponse.StatusCode); + + if LResponse.StatusCode <> 200 then + begin + FResponse.SetContentText('Question cannot be answered' + sLineBreak + 'Return: ' + LResponse.Content); + Exit; + end; + + LJsonValueAll := TJsonObject.ParseJSONValue(LResponse.Content); + if not(LJsonValueAll is TJSONObject) then + begin + FResponse.SetContentText('The question cannot be answered, return object not found.' + sLineBreak + + 'Return: ' + LResponse.Content); + Exit; + end; + + LJsonArrayChoices := (LJsonValueAll as TJsonObject).GetValue('choices'); + for LItemChoices := 0 to Pred(LJsonArrayChoices.Count) do + begin + LJsonObjMessage := LJsonArrayChoices.Items[LItemChoices].GetValue('message'); + LContent := LJsonObjMessage.GetValue('content'); + LResult := LResult + LContent.Trim + sLineBreak; + end; + + FResponse.SetContentText(LResult.Trim); +end; + +end. diff --git a/Src/Chat/DelphiAIDev.Chat.View.dfm b/Src/Chat/DelphiAIDev.Chat.View.dfm index 264b2a0..e98bf09 100644 --- a/Src/Chat/DelphiAIDev.Chat.View.dfm +++ b/Src/Chat/DelphiAIDev.Chat.View.dfm @@ -12,7 +12,6 @@ object DelphiAIDevChatView: TDelphiAIDevChatView Font.Name = 'Tahoma' Font.Style = [] KeyPreview = True - OldCreateOrder = False Position = poScreenCenter ShowHint = True OnActivate = FormActivate @@ -22,7 +21,6 @@ object DelphiAIDevChatView: TDelphiAIDevChatView DesignSize = ( 975 661) - PixelsPerInch = 96 TextHeight = 13 object pnBack: TPanel Left = 0 @@ -80,7 +78,6 @@ object DelphiAIDevChatView: TDelphiAIDevChatView ScrollBars = ssVertical ShowHint = True TabOrder = 1 - Zoom = 100 end object pnBackQuestion: TPanel Left = 18 @@ -138,7 +135,7 @@ object DelphiAIDevChatView: TDelphiAIDevChatView Left = 0 Top = 3 Width = 56 - Height = 13 + Height = 22 Cursor = crHandPoint Hint = 'AI being used' Margins.Left = 0 @@ -149,6 +146,7 @@ object DelphiAIDevChatView: TDelphiAIDevChatView Caption = 'lbCurrentAI' PopupMenu = pMenuCurrentAI OnClick = lbCurrentAIClick + ExplicitHeight = 13 end object btnSend: TButton AlignWithMargins = True @@ -817,8 +815,13 @@ object DelphiAIDevChatView: TDelphiAIDevChatView Caption = 'Groq' OnClick = Gemini1Click end - object Ollama1: TMenuItem + object Mistral1: TMenuItem Tag = 3 + Caption = 'Mistral' + OnClick = Gemini1Click + end + object Ollama1: TMenuItem + Tag = 4 Caption = 'Ollama (offline)' OnClick = Gemini1Click end diff --git a/Src/Chat/DelphiAIDev.Chat.View.pas b/Src/Chat/DelphiAIDev.Chat.View.pas index 1c695ba..7896092 100644 --- a/Src/Chat/DelphiAIDev.Chat.View.pas +++ b/Src/Chat/DelphiAIDev.Chat.View.pas @@ -74,6 +74,7 @@ TDelphiAIDevChatView = class(TDockableForm) pMenuQuestions: TPopupMenu; btnCleanAll: TSpeedButton; Groq1: TMenuItem; + Mistral1: TMenuItem; Ollama1: TMenuItem; procedure FormShow(Sender: TObject); procedure cBoxSizeFontKeyPress(Sender: TObject; var Key: Char); @@ -612,6 +613,7 @@ procedure TDelphiAIDevChatView.pMenuCurrentAIPopup(Sender: TObject); Gemini1.Checked := False; ChatGPT1.Checked := False; Groq1.Checked := False; + Mistral1.Checked := False; Ollama1.Checked := False; case FSettings.AIDefault of TC4DAiAvailable.Gemini: @@ -620,6 +622,8 @@ procedure TDelphiAIDevChatView.pMenuCurrentAIPopup(Sender: TObject); ChatGPT1.Checked := True; TC4DAiAvailable.Groq: Groq1.Checked := True; + TC4DAiAvailable.Mistral: + Mistral1.Checked := True; TC4DAiAvailable.Ollama: Ollama1.Checked := True; end; @@ -636,6 +640,8 @@ procedure TDelphiAIDevChatView.ConfLabelCurrentAI; lbCurrentAI.Hint := FSettings.ModelOpenAI; TC4DAiAvailable.Groq: lbCurrentAI.Hint := FSettings.ModelGroq; + TC4DAiAvailable.Mistral: + lbCurrentAI.Hint := FSettings.ModelMistral; TC4DAiAvailable.Ollama: lbCurrentAI.Hint := FSettings.ModelOllama; end; @@ -650,7 +656,7 @@ procedure TDelphiAIDevChatView.Gemini1Click(Sender: TObject); begin //*SEVERAL LTag := TMenuItem(Sender).Tag; - if not(LTag in [0, 1, 2, 3])then + if not(LTag in [0, 1, 2, 3, 4])then Exit; FSettings.AIDefault := TC4DAiAvailable(LTag); diff --git a/Src/Consts/DelphiAIDev.Consts.pas b/Src/Consts/DelphiAIDev.Consts.pas index ee03c30..c052748 100644 --- a/Src/Consts/DelphiAIDev.Consts.pas +++ b/Src/Consts/DelphiAIDev.Consts.pas @@ -5,7 +5,7 @@ interface type TConsts = class public const - SEMANTIC_VERSION = '2.3.0'; + SEMANTIC_VERSION = '2.4.0'; SEMANTIC_VERSION_LB = 'Version: ' + SEMANTIC_VERSION; WIN_CONTROL_FOCU_NIL = nil; DELPHI_AI_DEVELOPER_DPROJ = 'DelphiAIDeveloper.dproj'; @@ -38,6 +38,9 @@ TConsts = class BASE_URL_GROQ = 'https://api.groq.com/openai/v1/chat/completions'; MODEL_GROQ_DEFAULT = 'llama3-70b-8192'; //'llama3-8b-8192';; + BASE_URL_Mistral = 'https://api.mistral.ai/v1/chat/completions'; + MODEL_Mistral_DEFAULT = 'mistral-small-latest'; + BASE_URL_OLLAMA = 'http://localhost:11434/api/chat'; MODEL_OLLAMA_DEFAULT = ''; //'tinyllama' 'mistral'; @@ -55,7 +58,7 @@ TConsts = class //ABOUT AND SPLASH ABOUT_TITLE = 'Delphi AI Developer'; - ABOUT_COPY_RIGHT = 'Copyright 2024 Code4Delphi Team.'; + ABOUT_COPY_RIGHT = 'Copyright 2025 Code4Delphi Team.'; ABOUT_DESCRIPTION = 'Plugin designed to be used in the Delphi IDE.'; PLUGIN_LICENSE = 'MIT license'; IS_UNREGISTERED = False; diff --git a/Src/DB/Chat/DelphiAIDev.DB.Chat.View.dfm b/Src/DB/Chat/DelphiAIDev.DB.Chat.View.dfm index ce46b48..2fd2bc6 100644 --- a/Src/DB/Chat/DelphiAIDev.DB.Chat.View.dfm +++ b/Src/DB/Chat/DelphiAIDev.DB.Chat.View.dfm @@ -12,7 +12,6 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView Font.Name = 'Tahoma' Font.Style = [] KeyPreview = True - OldCreateOrder = False Position = poScreenCenter ShowHint = True OnActivate = FormActivate @@ -22,7 +21,6 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView DesignSize = ( 975 661) - PixelsPerInch = 96 TextHeight = 13 object pnBack: TPanel Left = 0 @@ -91,7 +89,6 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView ScrollBars = ssVertical ShowHint = True TabOrder = 1 - Zoom = 100 end object pnBackQuestion: TPanel Left = 18 @@ -161,7 +158,7 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView Left = 0 Top = 3 Width = 56 - Height = 13 + Height = 22 Cursor = crHandPoint Hint = 'AI being used' Margins.Left = 0 @@ -172,6 +169,7 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView Caption = 'lbCurrentAI' PopupMenu = pMenuCurrentAI OnClick = lbCurrentAIClick + ExplicitHeight = 13 end object btnSend: TButton AlignWithMargins = True @@ -298,19 +296,21 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView Left = 899 Top = 3 Width = 36 - Height = 13 + Height = 21 Align = alRight Caption = '000000' Layout = tlCenter + ExplicitHeight = 13 end object Label3: TLabel Left = 863 Top = 3 Width = 36 - Height = 13 + Height = 21 Align = alRight Caption = 'Count: ' Layout = tlCenter + ExplicitHeight = 13 end end end @@ -332,17 +332,18 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView Left = 337 Top = 0 Width = 85 - Height = 13 + Height = 25 Align = alLeft Caption = ' Last generation: ' Layout = tlCenter + ExplicitHeight = 13 end object lbLastGeneration: TLabel AlignWithMargins = True Left = 422 Top = 0 Width = 81 - Height = 13 + Height = 25 Margins.Left = 0 Margins.Top = 0 Margins.Right = 5 @@ -350,6 +351,7 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView Align = alLeft Caption = 'lbLastGeneration' Layout = tlCenter + ExplicitHeight = 13 end object btnExecuteSQL: TButton AlignWithMargins = True @@ -983,8 +985,13 @@ object DelphiAIDevDBChatView: TDelphiAIDevDBChatView Caption = 'Groq' OnClick = Gemini1Click end - object Ollama1: TMenuItem + object Mistral1: TMenuItem Tag = 3 + Caption = 'Mistral' + OnClick = Gemini1Click + end + object Ollama1: TMenuItem + Tag = 4 Caption = 'Ollama (offline)' OnClick = Gemini1Click end diff --git a/Src/DB/Chat/DelphiAIDev.DB.Chat.View.pas b/Src/DB/Chat/DelphiAIDev.DB.Chat.View.pas index e42fe37..22f5e27 100644 --- a/Src/DB/Chat/DelphiAIDev.DB.Chat.View.pas +++ b/Src/DB/Chat/DelphiAIDev.DB.Chat.View.pas @@ -83,6 +83,7 @@ TDelphiAIDevDBChatView = class(TDockableForm) pMenuQuestions: TPopupMenu; btnCleanAll: TSpeedButton; Groq1: TMenuItem; + Mistral1: TMenuItem; pnGridBack: TPanel; DBGrid1: TDBGrid; Splitter2: TSplitter; @@ -611,6 +612,7 @@ procedure TDelphiAIDevDBChatView.pMenuCurrentAIPopup(Sender: TObject); Gemini1.Checked := False; ChatGPT1.Checked := False; Groq1.Checked := False; + Mistral1.Checked := False; Ollama1.Checked := False; case FSettings.AIDefault of TC4DAiAvailable.Gemini: @@ -619,6 +621,8 @@ procedure TDelphiAIDevDBChatView.pMenuCurrentAIPopup(Sender: TObject); ChatGPT1.Checked := True; TC4DAiAvailable.Groq: Groq1.Checked := True; + TC4DAiAvailable.Mistral: + Mistral1.Checked := True; TC4DAiAvailable.Ollama: Ollama1.Checked := True; end; @@ -635,6 +639,8 @@ procedure TDelphiAIDevDBChatView.ConfLabelCurrentAI; lbCurrentAI.Hint := FSettings.ModelOpenAI; TC4DAiAvailable.Groq: lbCurrentAI.Hint := FSettings.ModelGroq; + TC4DAiAvailable.Mistral: + lbCurrentAI.Hint := FSettings.ModelMistral; TC4DAiAvailable.Ollama: lbCurrentAI.Hint := FSettings.ModelOllama; end; @@ -649,7 +655,7 @@ procedure TDelphiAIDevDBChatView.Gemini1Click(Sender: TObject); begin //*SEVERAL LTag := TMenuItem(Sender).Tag; - if not(LTag in [0, 1, 2, 3])then + if not(LTag in [0, 1, 2, 3, 4])then Exit; FSettings.AIDefault := TC4DAiAvailable(LTag); diff --git a/Src/Settings/DelphiAIDev.Settings.View.dfm b/Src/Settings/DelphiAIDev.Settings.View.dfm index 14e7cc2..b023496 100644 --- a/Src/Settings/DelphiAIDev.Settings.View.dfm +++ b/Src/Settings/DelphiAIDev.Settings.View.dfm @@ -2,7 +2,7 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView Left = 0 Top = 0 Caption = 'Delphi AI Developer - Settings' - ClientHeight = 601 + ClientHeight = 676 ClientWidth = 670 Color = clBtnFace Font.Charset = DEFAULT_CHARSET @@ -11,25 +11,23 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView Font.Name = 'Tahoma' Font.Style = [] KeyPreview = True - OldCreateOrder = False Position = poScreenCenter OnClose = FormClose OnCreate = FormCreate OnKeyDown = FormKeyDown OnShow = FormShow - PixelsPerInch = 96 TextHeight = 13 object pnBackAll: TPanel Left = 0 Top = 0 Width = 670 - Height = 601 + Height = 676 Align = alClient BevelOuter = bvNone TabOrder = 0 object pnBottom: TPanel Left = 0 - Top = 566 + Top = 641 Width = 670 Height = 35 Margins.Left = 0 @@ -103,7 +101,7 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView Left = 0 Top = 0 Width = 670 - Height = 566 + Height = 641 Align = alClient BevelOuter = bvNone TabOrder = 1 @@ -156,7 +154,7 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView Margins.Right = 0 Margins.Bottom = 1 Align = alLeft - Caption = 'IAs on-line' + Caption = 'AI on-line' TabOrder = 1 OnClick = btnIAsOnlineClick end @@ -171,7 +169,7 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView Margins.Right = 0 Margins.Bottom = 1 Align = alLeft - Caption = 'IAs off-Line' + Caption = 'AI off-Line' TabOrder = 2 OnClick = btnIAsOfflineClick end @@ -195,7 +193,7 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView Left = 0 Top = 30 Width = 670 - Height = 536 + Height = 611 Align = alClient BevelOuter = bvNone TabOrder = 1 @@ -207,14 +205,10 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView Top = 33 Width = 667 Height = 521 - ActivePage = TabSheet4 + ActivePage = TabSheet2 TabOrder = 1 object TabSheet1: TTabSheet Caption = 'Preferences' - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 object pnPreferencesBack: TPanel Left = 0 Top = 0 @@ -326,12 +320,8 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView end end object TabSheet2: TTabSheet - Caption = 'IAs on-line' + Caption = 'AI on-line' ImageIndex = 1 - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 object pnIAsOnLineBack: TPanel Left = 0 Top = 0 @@ -358,7 +348,7 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView object Bevel2: TBevel AlignWithMargins = True Left = 0 - Top = 381 + Top = 505 Width = 659 Height = 1 Margins.Left = 0 @@ -699,7 +689,8 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView 'gpt-3.5-turbo-16k' 'gpt-4' 'gpt-4o-2024-05-13' - 'gpt-4o-2024-08-06') + 'gpt-4o-2024-08-06' + 'gpt-4-turbo') end end end @@ -869,15 +860,175 @@ object DelphiAIDevSettingsView: TDelphiAIDevSettingsView end end end + object gBoxMistral: TGroupBox + Left = 0 + Top = 381 + Width = 659 + Height = 124 + Align = alTop + Caption = ' Mistral ' + ParentBackground = False + TabOrder = 3 + object pnMistralBack: TPanel + AlignWithMargins = True + Left = 5 + Top = 18 + Width = 649 + Height = 101 + Align = alClient + BevelOuter = bvNone + ParentBackground = False + TabOrder = 0 + object Label20: TLabel + Left = 16 + Top = 5 + Width = 45 + Height = 13 + Caption = 'Base URL' + end + object Label21: TLabel + Left = 16 + Top = 44 + Width = 37 + Height = 13 + Caption = 'API key' + end + object Label22: TLabel + Left = 374 + Top = 5 + Width = 28 + Height = 13 + Caption = 'Model' + end + object lbLinkMistral01: TLabel + Left = 16 + Top = 84 + Width = 86 + Height = 13 + Cursor = crHandPoint + Hint = 'https://console.mistral.ai/api-keys/' + Caption = 'Generate API Key' + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlue + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + ParentFont = False + ParentShowHint = False + ShowHint = True + OnClick = lbLinkGpt01Click + end + object btnApiKeyMistralView: TSpeedButton + Left = 582 + Top = 59 + Width = 23 + Height = 22 + Cursor = crHandPoint + Hint = 'Show/Hide API Key' + Flat = True + Glyph.Data = { + 36030000424D3603000000000000360000002800000010000000100000000100 + 18000000000000030000120B0000120B00000000000000000000FF00FF4A667C + BE9596FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 + FFFF00FFFF00FFFF00FF6B9CC31E89E84B7AA3C89693FF00FFFF00FFFF00FFFF + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF4BB4FE51B5FF + 2089E94B7AA2C69592FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00 + FFFF00FFFF00FFFF00FFFF00FF51B7FE51B3FF1D87E64E7AA0CA9792FF00FFFF + 00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + 51B7FE4EB2FF1F89E64E7BA2B99497FF00FFFF00FFFF00FFFF00FFFF00FFFF00 + FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF52B8FE4BB1FF2787D95F6A76FF + 00FFB0857FC09F94C09F96BC988EFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF + FF00FFFF00FF55BDFFB5D6EDBF9D92BB9B8CE7DAC2FFFFE3FFFFE5FDFADAD8C3 + B3B58D85FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFCEA795FD + EEBEFFFFD8FFFFDAFFFFDBFFFFE6FFFFFBEADDDCAE837FFF00FFFF00FFFF00FF + FF00FFFF00FFFF00FFFF00FFC1A091FBDCA8FEF7D0FFFFDBFFFFE3FFFFF8FFFF + FDFFFFFDC6A99CFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFC1A091FEE3ACF1 + C491FCF2CAFFFFDDFFFFE4FFFFF7FFFFF7FFFFE9EEE5CBB9948CFF00FFFF00FF + FF00FFFF00FFFF00FFC2A191FFE6AEEEB581F7DCAEFEFDD8FFFFDFFFFFE3FFFF + E4FFFFE0F3ECD2BB968EFF00FFFF00FFFF00FFFF00FFFF00FFBC978CFBE7B7F4 + C791F2C994F8E5B9FEFCD8FFFFDDFFFFDCFFFFE0E2D2BAB68E86FF00FFFF00FF + FF00FFFF00FFFF00FFFF00FFD9C3A9FFFEE5F7DCB8F2C994F5D4A5FAE8BDFDF4 + C9FDFBD6B69089FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFB58D85E8 + DEDDFFFEF2F9D8A3F4C48CF9D49FFDEAB8D0B49FB89086FF00FFFF00FFFF00FF + FF00FFFF00FFFF00FFFF00FFFF00FFAD827FC9AA9EEFE0B7EFDFB2E7CEACB890 + 86B89086FF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF + 00FFFF00FFBA968ABB988CB79188FF00FFFF00FFFF00FFFF00FF} + ParentShowHint = False + ShowHint = True + OnClick = btnApiKeyMistralViewClick + end + object lbLinkMistral02: TLabel + Left = 128 + Top = 84 + Width = 72 + Height = 13 + Cursor = crHandPoint + Hint = 'https://docs.mistral.ai/getting-started/quickstart/' + Caption = 'Documentation' + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlue + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + ParentFont = False + ParentShowHint = False + ShowHint = True + OnClick = lbLinkGpt01Click + end + object lbLinkMistral03: TLabel + Left = 232 + Top = 84 + Width = 67 + Height = 13 + Cursor = crHandPoint + Hint = 'https://docs.mistral.ai/getting-started/models/models_overview/' + Caption = 'Mistral Models' + Font.Charset = DEFAULT_CHARSET + Font.Color = clBlue + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + ParentFont = False + ParentShowHint = False + ShowHint = True + OnClick = lbLinkGpt01Click + end + object edtBaseUrlMistral: TEdit + Left = 16 + Top = 21 + Width = 356 + Height = 21 + TabOrder = 0 + end + object edtApiKeyMistral: TEdit + Left = 16 + Top = 60 + Width = 563 + Height = 21 + PasswordChar = '*' + TabOrder = 2 + end + object cBoxModelMistral: TComboBox + Left = 374 + Top = 21 + Width = 226 + Height = 21 + TabOrder = 1 + Items.Strings = ( + 'codestral-latest' + 'mistral-large-latest' + 'ministral-3b-latest' + 'ministral-8b-latest' + 'mistral-small-latest' + 'open-codestral-mamba') + end + end + end end end object TabSheet3: TTabSheet - Caption = 'IAs off-Line' + Caption = 'AI off-Line' ImageIndex = 2 - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 object pnIAsOffLineBack: TPanel Left = 0 Top = 0 diff --git a/Src/Settings/DelphiAIDev.Settings.View.pas b/Src/Settings/DelphiAIDev.Settings.View.pas index 0d5c909..5703288 100644 --- a/Src/Settings/DelphiAIDev.Settings.View.pas +++ b/Src/Settings/DelphiAIDev.Settings.View.pas @@ -119,6 +119,18 @@ TDelphiAIDevSettingsView = class(TForm) mmCodeCompletionDefaultPrompt: TMemo; Label19: TLabel; mmDefaultPrompt: TMemo; + gBoxMistral: TGroupBox; + pnMistralBack: TPanel; + Label20: TLabel; + Label21: TLabel; + Label22: TLabel; + lbLinkMistral01: TLabel; + btnApiKeyMistralView: TSpeedButton; + lbLinkMistral02: TLabel; + lbLinkMistral03: TLabel; + edtBaseUrlMistral: TEdit; + edtApiKeyMistral: TEdit; + cBoxModelMistral: TComboBox; procedure FormCreate(Sender: TObject); procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure btnCloseClick(Sender: TObject); @@ -138,6 +150,7 @@ TDelphiAIDevSettingsView = class(TForm) procedure btnCodeCompletionClick(Sender: TObject); procedure btnOpenDataFolderClick(Sender: TObject); procedure ckCodeCompletionSuggestionColorUseClick(Sender: TObject); + procedure btnApiKeyMistralViewClick(Sender: TObject); private FSettings: TDelphiAIDevSettings; procedure SaveSettings; @@ -229,6 +242,9 @@ procedure TDelphiAIDevSettingsView.ConfigScreen; lbLinkGroq01.Font.Color := LColor; lbLinkGroq02.Font.Color := LColor; lbLinkGroq03.Font.Color := LColor; + lbLinkMistral01.Font.Color := LColor; + lbLinkMistral02.Font.Color := LColor; + lbLinkMistral03.Font.Color := LColor; lbRestoreDefaults.Font.Color := LColor; lbLinkOllama01.Font.Color := LColor; lbLinkOllama02.Font.Color := LColor; @@ -250,6 +266,11 @@ procedure TDelphiAIDevSettingsView.btnApiKeyGroqViewClick(Sender: TObject); TUtils.TogglePasswordChar(edtApiKeyGroq); end; +procedure TDelphiAIDevSettingsView.btnApiKeyMistralViewClick(Sender: TObject); +begin + TUtils.TogglePasswordChar(edtApiKeyMistral); +end; + procedure TDelphiAIDevSettingsView.btnCloseClick(Sender: TObject); begin Self.Close; @@ -270,7 +291,7 @@ procedure TDelphiAIDevSettingsView.FormKeyDown(Sender: TObject; var Key: Word; S procedure TDelphiAIDevSettingsView.lbLinkGpt01Click(Sender: TObject); begin - //**Several + //**SEVERAL TUtils.OpenLink(TLabel(Sender).Hint.Trim); end; @@ -279,11 +300,13 @@ procedure TDelphiAIDevSettingsView.lbRestoreDefaultsClick(Sender: TObject); LApiKeyGemini: string; LApiKeyOpenAI: string; LApiKeyGroq: string; + LApiKeyMistral: string; LApiKeyOllama: string; begin LApiKeyGemini := FSettings.ApiKeyGemini; LApiKeyOpenAI := FSettings.ApiKeyOpenAI; LApiKeyGroq := FSettings.ApiKeyGroq; + LApiKeyMistral := FSettings.ApiKeyMistral; LApiKeyOllama := FSettings.ApiKeyOllama; FSettings.LoadDefaults; @@ -291,6 +314,7 @@ procedure TDelphiAIDevSettingsView.lbRestoreDefaultsClick(Sender: TObject); FSettings.ApiKeyGemini := LApiKeyGemini; FSettings.ApiKeyOpenAI := LApiKeyOpenAI; FSettings.ApiKeyGroq := LApiKeyGroq; + FSettings.ApiKeyMistral := LApiKeyMistral; FSettings.ApiKeyOllama := LApiKeyOllama; Self.LoadSettings; @@ -375,6 +399,12 @@ procedure TDelphiAIDevSettingsView.LoadSettings; cBoxModelGroq.Text := FSettings.ModelGroq; edtApiKeyGroq.Text := FSettings.ApiKeyGroq; + edtBaseUrlMistral.Text := FSettings.BaseUrlMistral; + cBoxModelMistral.ItemIndex := cBoxModelMistral.Items.IndexOf(FSettings.ModelMistral); + if cBoxModelMistral.ItemIndex < 0 then + cBoxModelMistral.Text := FSettings.ModelMistral; + edtApiKeyMistral.Text := FSettings.ApiKeyMistral; + edtBaseUrlOllama.Text := FSettings.BaseUrlOllama; cBoxModelOllama.ItemIndex := cBoxModelOllama.Items.IndexOf(FSettings.ModelOllama); if cBoxModelOllama.ItemIndex < 0 then @@ -410,6 +440,10 @@ procedure TDelphiAIDevSettingsView.SaveSettings; FSettings.ModelGroq := cBoxModelGroq.Text; FSettings.ApiKeyGroq := edtApiKeyGroq.Text; + FSettings.BaseUrlMistral := edtBaseUrlMistral.Text; + FSettings.ModelMistral := cBoxModelMistral.Text; + FSettings.ApiKeyMistral := edtApiKeyMistral.Text; + FSettings.BaseUrlOllama := edtBaseUrlOllama.Text; FSettings.ModelOllama := cBoxModelOllama.Text; FSettings.ApiKeyOllama := edtApiKeyOllama.Text; diff --git a/Src/Settings/DelphiAIDev.Settings.pas b/Src/Settings/DelphiAIDev.Settings.pas index ac9d175..7b73466 100644 --- a/Src/Settings/DelphiAIDev.Settings.pas +++ b/Src/Settings/DelphiAIDev.Settings.pas @@ -35,6 +35,9 @@ TDelphiAIDevSettings = class FIELD_BaseUrlGroq = 'BaseUrlGroq'; FIELD_ModelGroq = 'ModelGroq'; FIELD_ApiKeyGroq = 'ApiKeyGroq'; + FIELD_BaseUrlMistral = 'BaseUrlMistral'; + FIELD_ModelMistral = 'ModelMistral'; + FIELD_ApiKeyMistral = 'ApiKeyMistral'; FIELD_BaseUrlOllama = 'BaseUrlOllama'; FIELD_ModelOllama = 'ModelOllama'; FIELD_ApiKeyOllama = 'ApiKeyOllama'; @@ -64,6 +67,10 @@ TDelphiAIDevSettings = class FModelGroq: string; FApiKeyGroq: string; + FBaseUrlMistral: string; + FModelMistral: string; + FApiKeyMistral: string; + FBaseUrlOllama: string; FModelOllama: string; FApiKeyOllama: string; @@ -104,6 +111,10 @@ TDelphiAIDevSettings = class property ModelGroq: string read FModelGroq write FModelGroq; property ApiKeyGroq: string read FApiKeyGroq write FApiKeyGroq; + property BaseUrlMistral: string read FBaseUrlMistral write FBaseUrlMistral; + property ModelMistral: string read FModelMistral write FModelMistral; + property ApiKeyMistral: string read FApiKeyMistral write FApiKeyMistral; + property BaseUrlOllama: string read FBaseUrlOllama write FBaseUrlOllama; property ModelOllama: string read FModelOllama write FModelOllama; property ApiKeyOllama: string read FApiKeyOllama write FApiKeyOllama; @@ -154,6 +165,10 @@ procedure TDelphiAIDevSettings.LoadDefaults; FModelGroq := TConsts.MODEL_GROQ_DEFAULT; FApiKeyGroq := ''; + FBaseUrlMistral := TConsts.BASE_URL_Mistral; + FModelMistral := TConsts.MODEL_Mistral_DEFAULT; + FApiKeyMistral := ''; + FBaseUrlOllama := TConsts.BASE_URL_OLLAMA; FModelOllama := TConsts.MODEL_OLLAMA_DEFAULT; FApiKeyOllama := ''; @@ -196,6 +211,10 @@ procedure TDelphiAIDevSettings.SaveData; LReg.WriteString(FIELD_ModelGroq, FModelGroq); LReg.WriteString(FIELD_ApiKeyGroq, FApiKeyGroq); + LReg.WriteString(FIELD_BaseUrlMistral, FBaseUrlMistral); + LReg.WriteString(FIELD_ModelMistral, FModelMistral); + LReg.WriteString(FIELD_ApiKeyMistral, FApiKeyMistral); + LReg.WriteString(FIELD_BaseUrlOllama, FBaseUrlOllama); LReg.WriteString(FIELD_ModelOllama, FModelOllama); LReg.WriteString(FIELD_ApiKeyOllama, FApiKeyOllama); @@ -285,6 +304,16 @@ procedure TDelphiAIDevSettings.LoadData; if LReg.ValueExists(FIELD_ApiKeyGroq) then fApiKeyGroq := LReg.ReadString(FIELD_ApiKeyGroq); + //MISTRAL + if LReg.ValueExists(FIELD_BaseUrlMistral) then + fBaseUrlMistral := LReg.ReadString(FIELD_BaseUrlMistral); + + if LReg.ValueExists(FIELD_ModelMistral) then + fModelMistral := LReg.ReadString(FIELD_ModelMistral); + + if LReg.ValueExists(FIELD_ApiKeyMistral) then + fApiKeyMistral := LReg.ReadString(FIELD_ApiKeyMistral); + //OLLAMA if LReg.ValueExists(FIELD_BaseUrlOllama) then fBaseUrlOllama := LReg.ReadString(FIELD_BaseUrlOllama); @@ -359,6 +388,17 @@ procedure TDelphiAIDevSettings.ValidateFillingSelectedAIInternal( if FApiKeyGroq.Trim.IsEmpty then ShowMsgInternal(['API Key', 'Groq']); end; + TC4DAiAvailable.Mistral: + begin + if FBaseUrlMistral.Trim.IsEmpty then + ShowMsgInternal(['Base URL', 'Mistral']); + + if FModelMistral.Trim.IsEmpty then + ShowMsgInternal(['Model', 'Mistral']); + + if FApiKeyMistral.Trim.IsEmpty then + ShowMsgInternal(['API Key', 'Mistral']); + end; TC4DAiAvailable.Ollama: begin if FBaseUrlOllama.Trim.IsEmpty then diff --git a/Src/Types/DelphiAIDev.Types.pas b/Src/Types/DelphiAIDev.Types.pas index 27097b0..08a8b70 100644 --- a/Src/Types/DelphiAIDev.Types.pas +++ b/Src/Types/DelphiAIDev.Types.pas @@ -11,7 +11,7 @@ interface TC4DWizardMenuContextList = procedure(const MenuContextList: IInterfaceList) of object; {$SCOPEDENUMS ON} - TC4DAiAvailable = (Gemini, OpenAI, Groq, Ollama); + TC4DAiAvailable = (Gemini, OpenAI, Groq, Mistral, Ollama); TC4DLanguage = (en, ptBR, es); TC4DExtensionsFiles = (None, PAS, DFM, FMX, DPR, DPK, DPROJ, GROUPPROJ, ZIP, BMP, INI, ALL); TC4DExtensionsOfFiles = set of TC4DExtensionsFiles; diff --git a/Src/Utils/DelphiAIDev.Utils.OTA.pas b/Src/Utils/DelphiAIDev.Utils.OTA.pas index afa4630..68ebe78 100644 --- a/Src/Utils/DelphiAIDev.Utils.OTA.pas +++ b/Src/Utils/DelphiAIDev.Utils.OTA.pas @@ -42,7 +42,7 @@ TUtilsOTA = class class function ActiveThemeForCode: TColor; class function ActiveThemeIsDark: Boolean; class function GetIOTAFormEditor(const AIOTAModule: IOTAModule): IOTAFormEditor; - {$IF CompilerVersion >= 32.0} //Tokyo + {$IF CompilerVersion > 32.0} //Tokyo class function GetIOTAIDEThemingServices: IOTAIDEThemingServices; class function GetIOTAIDEThemingServices250: IOTAIDEThemingServices250; {$ENDIF} @@ -512,7 +512,7 @@ class function TUtilsOTA.CheckIfExistFileInCurrentsProjectGroups(const ANameFile end; class procedure TUtilsOTA.IDEThemingAll(AFormClass: TCustomFormClass; AForm: TForm); -{$IF CompilerVersion >= 32.0} //Tokyo +{$IF CompilerVersion > 32.0} //Tokyo var i: Integer; LIOTAIDEThemingServices250: IOTAIDEThemingServices250; @@ -521,7 +521,7 @@ class procedure TUtilsOTA.IDEThemingAll(AFormClass: TCustomFormClass; AForm: TFo AForm.Constraints.MinHeight := AForm.Height; AForm.Constraints.MinWidth := AForm.Width; - {$IF CompilerVersion >= 32.0} + {$IF CompilerVersion > 32.0} LIOTAIDEThemingServices250 := Self.GetIOTAIDEThemingServices250; LIOTAIDEThemingServices250.RegisterFormClass(AFormClass); LIOTAIDEThemingServices250.ApplyTheme(AForm); @@ -555,7 +555,7 @@ class function TUtilsOTA.ActiveThemeIsDark: Boolean; const THEME_DARK = 'dark'; begin - {$IF CompilerVersion >= 32.0} //Tokyo + {$IF CompilerVersion > 32.0} //Tokyo Result := Self.GetIOTAIDEThemingServices.ActiveTheme.ToLower.Equals(THEME_DARK); {$ELSE} Result := False; @@ -584,7 +584,7 @@ class function TUtilsOTA.GetIOTAFormEditor(const AIOTAModule: IOTAModule): IOTAF end; end; -{$IF CompilerVersion >= 32.0} //Tokyo +{$IF CompilerVersion > 32.0} //Tokyo class function TUtilsOTA.GetIOTAIDEThemingServices: IOTAIDEThemingServices; begin if not Supports(BorlandIDEServices, IOTAIDEThemingServices, Result) then diff --git a/Src/Utils/DelphiAIDev.Utils.pas b/Src/Utils/DelphiAIDev.Utils.pas index dfcf513..68067a3 100644 --- a/Src/Utils/DelphiAIDev.Utils.pas +++ b/Src/Utils/DelphiAIDev.Utils.pas @@ -29,7 +29,6 @@ TUtils = class class function ShowMsgInternal(const AMsg, ADetails: string; const AIcon: TC4DIcon; const AButtons: TC4DButtons; const ABtnFocu: TC4DBtnFocu; const AWinControlFocu: TWinControl): Boolean; public - class procedure TryGetValueJson(const AJSONObject: TJSONObject; const AKey: string; AResult: T); class function GetExceptionMessage(const E: Exception): string; class function StrToDefaultsQuestionsKind(Value: string): TC4DQuestionKind; class function StrToDriverID(Value: string): TC4DDriverID; @@ -149,12 +148,6 @@ implementation DelphiAIDev.View.Dialog, DelphiAIDev.WaitingScreen; -class procedure TUtils.TryGetValueJson(const AJSONObject: TJSONObject; const AKey: string; AResult: T); -begin - if AJSONObject.GetValue(AKey) <> nil then - AResult := AJSONObject.GetValue(AKey); -end; - class function TUtils.GetExceptionMessage(const E: Exception): string; begin Result := E.Message;