it:ai_delphi

Artificial Intelligence using Delphi Programming Tool

Introduction

  • Embarcadero's Delphi Rapid Application Design software allows very efficient and fast computing with easy modern graphic user interface design
  • the Object Pascal programming language is relatively easy to learn being derived from Pascal, and in many ways resembles Python
  • it is extremely extensible through its VCL and Firemonkey component frameworks
  • there are now bidirectional support for Python libraries

Native Delphi Tools for AI

general mathematical and statistical analysis components

  • Torry's listing of stats component packages: https://torry.net/components/science/statistic/
  • ESBConsult (Australian developer): $AU228
    • Complex numbers, 3D vectors and tensors
    • Universal algorithms for working with formulae of any complexity and for working with physics concepts
    • calculation of special functions (Bessel, Legendre) and their derivatives
    • least squares approximation of multidimensional data
    • calculating definite integral values for one- and two- dimensional functions
    • solving initial value problems for the systems of ordinary differential equations
    • finding roots and extremums for univariate functions
    • solving systems of nonlinear equations
    • MtxVec - math engine for science and engineering
    • Stats Master
    • signal processing packages:
      • DSP Master - advanced signal processing package
      • FFT Properties - signal analyzer and recorder
    • CUDA support only for C not Object Pascal as yet

accessing the GPU for advanced mathematical computation as in AI requirements

  • moving data from RAM to GPU VRAM is expensive
    • for mathematical functions such as sine or exponential functions, CUDA pays off from greater than 100,000 vector elements
    • for matrix multiplication, payback occurs in the region of 200×200 elements

OpenCL

Delphi native OpenCL components

CUDA

  • NVidia proprietary interface to their GPU's
  • CUDA kernels need to be written in C/C++ (Delphi language would need to be extended to be able to natively do this)

neural network architecture components

  • Mitov neural networking components
    • contains classifiers, training components, and a general purpose neuron component
      • neural networks, self-organizing map, naive Bayes, K nearest neighbor, Radial Basis Function Network, Back propagation training, RProp training, Data preparation, Timing components
    • fully compatible and directly integrates with Mitov's SignalLab, VideoLab, AudioLab, VisionLab, InstrumentLab, and PlotLab.
    • “Data Miner package” - neural network components for classification algorithms: Naive Bayes, K nearest neighbors, Linear Classifier
  • issues:
    • no native library for the latest AI tools such as:
      • the latest neural network architectures

Using Python libraries within Delphi

  • this gives access to Python's amazing array of AI tools including CUDA and tensorflow
  • HOWEVER, it has the downsides of using Python:
    • requires a Python install on the local machine and all required Python libraries to be installed as per usual for Python
    • Python code is by its nature slow to run being interpreted code not native executables

Using APIs from Delphi to access third party online AI tools

Gary Ayton's Delphi Perplexity API code

  • see my app called perplexity with working code but their API has limitations as of March 2024:
    • no GPT or Claude model available
    • online version of sonar should not have a system prompt - the medium version does not seem to do well at diagnosis
    • no citations currently available
    • no ongoing conversation - each call has zero memory of prior calls
    • costs money
    • seems slower than their website calls
    • their website does not have a Delphi example of accessing their API so I had to write one - see below:
procedure RunPerplexity(systemprompt, userprompt, model:String; var MemoResponse:TMemo);
var
  zURL,  response: String;
  zJsonStreamIn, zJsonStreamOut: TStringStream;
  NetHTTPClient: TNetHTTPClient;
  NetHTTPRequest: TNetHTTPRequest;
  i:Integer;


begin
  zURL := 'https://api.perplexity.ai/chat/completions';
  API_Key := 'MyAPIKey';

  // Create a JSON object from the string
  //perplexity request format: {"model":"mistral-7b-instruct","messages":[{"content":"string","role":"system"}],"max_tokens":0,"temperature":0.2,"top_p":0.9,"top_k":0,"stream":false,"presence_penalty":0,"frequency_penalty":1}
 zJsonStreamIn := TStringStream.Create('{"model":"'+model+'","messages":[{"role":"system","content":"' + SystemPrompt + '"},{"role":"user","content":"' + UserPrompt + '"}]}');
  try
    zJsonStreamOut := TStringStream.Create;
    try
      NetHTTPClient := TNetHTTPClient.Create(nil);
      try
        NetHTTPRequest := TNetHTTPRequest.Create(nil);
        try
          MemoResponse.Lines.Clear;
          application.ProcessMessages;

          NetHTTPRequest.Client := NetHTTPClient;
          NetHTTPRequest.URL := zURL;
          NetHTTPRequest.MethodString := 'POST /chat/completions HTTP/1.1';
          NetHTTPRequest.CustomHeaders['Authorization'] := 'Bearer ' + API_Key;

          // Make the POST request and capture the response
          NetHTTPRequest.Post(zURL, zJsonStreamIn, zJsonStreamOut);

          // Display the response in a TMemo component:

          try
          // Extract the LLM response text from the response JSON object stream
          response := ExtractContentFromJSON(zJsonStreamOut.DataString);
          //now need to format the embedded line breaks:
          i :=  pos(#$A, response);    // #$A is = /n
            try
            MemoResponse.Lines.BeginUpdate;  //prevent control visually updating each line add
            while i > 0 do   //create new lines for line breaks
             begin
             MemoResponse.Lines.Add(Copy(response,0,i-1));
             response := Copy(response,i+1,length(response)-1);
             i :=  pos(#$A, response);
             end;
             MemoResponse.Lines.Add(response);
             //now scroll to top of memo:
             MemoResponse.SelStart := 0;
             MemoResponse.SelLength := 0;
             MemoResponse.Perform(EM_SCROLLCARET, 0, 0);
            finally
            MemoResponse.Lines.EndUpdate;
            end;
           Except on E:exception do
            begin
            MemoResponse.Lines.Add('Error: '+#13+zJsonStreamOut.DataString);
            end;
           end;
        finally
          NetHTTPRequest.Free;
        end;
      finally
        NetHTTPClient.Free;
      end;
    finally
      zJsonStreamOut.Free;
    end;
  finally
    zJsonStreamIn.Free;
  end;
 {
In this code:

- `TNetHTTPClient` is used to manage the HTTP requests.
- `TNetHTTPRequest` is used to configure and execute the specific POST request.
- The `CustomHeaders` property of `TNetHTTPRequest` is used to set the 'Authorization' header.
- The `Post` method of `TNetHTTPRequest` is used to send the request and receive the response.

Make sure to add `System.Net.HttpClient`, `System.Net.URLClient`, `System.Classes`, and `System.SysUtils` to the uses clause of your unit.
  }

end;

function ExtractContentFromJSON(const AJSONText: string):String;
var
  JSONValue, ChoicesArrayValue, ChoiceValue, MessageValue: TJSONValue;
  JSONObj: TJSONObject;
  JSONArray: TJSONArray;

begin
  // Parse the JSON string into a JSONValue
  JSONValue := TJSONObject.ParseJSONValue(AJSONText);
  if JSONValue = nil then
    raise Exception.Create('Invalid JSON string');

  try
    // Cast the JSONValue to a JSONObject
    JSONObj := JSONValue as TJSONObject;

    // Get the 'choices' array from the JSON object
    ChoicesArrayValue := JSONObj.Values['choices'];
    if ChoicesArrayValue = nil then
      raise Exception.Create('Choices array not found');

    // Cast the ChoicesArrayValue to a JSONArray
    JSONArray := ChoicesArrayValue as TJSONArray;

    // Get the first object from the 'choices' array
    ChoiceValue := JSONArray.Items[0];
    if ChoiceValue = nil then
      raise Exception.Create('Choice object not found');

    // Cast the ChoiceValue to a JSONObject
    JSONObj := ChoiceValue as TJSONObject;

    // Get the 'message' object from the choice
    MessageValue := JSONObj.Values['message'];
    if MessageValue = nil then
      raise Exception.Create('Message object not found');

    // Cast the MessageValue to a JSONObject
    JSONObj := MessageValue as TJSONObject;

    // Get the 'content' string from the 'message' object
    result := JSONObj.Values['content'].Value;

  finally
    JSONValue.Free;
  end;
end;
it/ai_delphi.txt · Last modified: 2024/04/01 09:37 by gary1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki