{"id":23193275,"url":"https://github.com/maxidonkey/delphigemini","last_synced_at":"2025-04-05T07:25:24.689Z","repository":{"id":260530335,"uuid":"874808077","full_name":"MaxiDonkey/DelphiGemini","owner":"MaxiDonkey","description":"The Gemini API wrapper for Delphi utilizes advanced models developed by Google to provide robust capabilities, including interactive chat, text embeddings, code generation, image and video prompting, audio analysis and transcription, fine-tuning, caching, and integration with Google Search.","archived":false,"fork":false,"pushed_at":"2025-03-13T21:18:13.000Z","size":196,"stargazers_count":27,"open_issues_count":5,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-13T21:34:32.970Z","etag":null,"topics":["agents","api-wrapper","audio-transcription","delphi","fine-tuning","finetuning","gemini","gemini-ai","gemini-api","gemini-flash","gemini-pro-vision","google-search","gpt","image-prompting","video-prompting","vision"],"latest_commit_sha":null,"homepage":"","language":"Pascal","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MaxiDonkey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-18T13:53:52.000Z","updated_at":"2025-03-13T21:03:47.000Z","dependencies_parsed_at":"2024-10-31T21:22:14.568Z","dependency_job_id":"92a5d267-cae8-4e37-b52f-6e29b36c2165","html_url":"https://github.com/MaxiDonkey/DelphiGemini","commit_stats":null,"previous_names":["maxidonkey/delphigemini"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiGemini","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiGemini/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiGemini/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiGemini/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaxiDonkey","download_url":"https://codeload.github.com/MaxiDonkey/DelphiGemini/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247302028,"owners_count":20916623,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agents","api-wrapper","audio-transcription","delphi","fine-tuning","finetuning","gemini","gemini-ai","gemini-api","gemini-flash","gemini-pro-vision","google-search","gpt","image-prompting","video-prompting","vision"],"created_at":"2024-12-18T13:10:33.243Z","updated_at":"2025-04-05T07:25:24.670Z","avatar_url":"https://github.com/MaxiDonkey.png","language":"Pascal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Delphi Gemini API\n\n___\n![GitHub](https://img.shields.io/badge/IDE%20Version-Delphi%2010.3/11/12-yellow)\n![GitHub](https://img.shields.io/badge/platform-all%20platforms-green)\n![GitHub](https://img.shields.io/badge/Updated%20the%2011/02/2024-blue)\n\n\u003cbr/\u003e\n\u003cbr/\u003e\n\n- [Introduction](#Introduction)\n- [Remarks](#remarks)\n- [Usage](#usage)\n    - [Initialization](#initialization)\n    - [Asynchronous callback mode management](#Asynchronous-callback-mode-management)\n    - [Gemini Models Overview](#Gemini-Models-Overview)\n    - [Embeddings](#embeddings)\n    - [Generate text](#Generate-text)\n        - [Generate text from text-only input](#Generate-text-from-text-only-input)\n        - [Generate text from text-and-image input](#Generate-text-from-text-and-image-input)\n        - [Generate a text stream](#Generate-a-text-stream)\n        - [Build an interactive chat](#Build-an-interactive-chat)\n        - [Configure text generation](#Configure-text-generation)\n    - [Document processing](#Document-processing)\n        - [Upload a document and generate content](#Upload-a-document-and-generate-content)\n        - [Get metadata for a file](#Get-metadata-for-a-file)\n        - [List files](#List-files)\n        - [Delete files](#Delete-files)\n    - [System instructions](#System-instructions)\n    - [Vision](#Vision)\n        - [Prompting with images](#Prompting-with-images)\n        - [Prompting with video](#Prompting-with-video)\n    - [Audio](#Audio)\n        - [Speech-to-text](#Speech-to-text)\n        - [Text-to-speech](#Text-to-speech)\n    - [Long context](#Long-context)\n    - [Code execution](#Code-execution)\n    - [Function calling](#Function-calling)\n    - [Context caching](#Context-caching)\n        - [Set the context to cache](#Set-the-context-to-cache)\n        - [Use cached context](#Use-cached-context)\n        - [List caches](#List-caches)\n        - [Retrieve a cache](#Retrieve-a-cache)\n        - [Update a cache](#Update-a-cache)\n        - [Delete a cache](#Delete-a-cache)\n    - [Safety](#Safety)\n        - [TSafety record](#TSafety-record)\n    - [Fine-tuning](#Fine-tuning)\n        - [Create tuning task](#Create-tuning-task)\n        - [Upload tuning dataset](#Upload-tuning-dataset)\n        - [Try the model](#Try-the-model)\n        - [List tuned models](#List-tuned-models)\n        - [Retrieve tuned model](#Retrieve-tuned-model)\n        - [Update tuned model](#Update-tuned-model)\n        - [Delete tuned model](#Delete-tuned-model)\n    - [Grounding with Google Search](#Grounding-with-Google-Search)\n        - [Why is Grounding with Google Search useful](#Why-is-Grounding-with-Google-Search-useful)\n        - [Important note](#Important-note)\n- [Methods for the Tutorial Display](#Methods-for-the-Tutorial-Display)\n- [Contributing](#contributing)\n- [License](#license)\n\n\u003cbr/\u003e\n\n# Introduction\n\nWelcome to the unofficial Delphi Gemini API library! This project is designed to offer a seamless interface for Delphi developers to interact with the Gemini public API, enabling easy integration of advanced natural language processing capabilities into your Delphi applications. Whether you're looking to generate text, create embeddings, use conversational models, or generate code, this library provides a straightforward and efficient solution.\n\nGemini is a robust natural language processing API that empowers developers to add sophisticated AI features to their applications. For more information, refer to the official [Gemini documentation](https://ai.google.dev/gemini-api/docs).\n\n\u003cbr/\u003e\n\n# Remarks\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e This is an unofficial library. **Google** does not provide any official library for `Delphi`.\n\u003e This repository contains `Delphi` implementation over [Gemini](https://ai.google.dev/api) public API.\n\n\u003cbr/\u003e\n\n# Usage\n\n\u003cbr/\u003e\n\n## Initialization\n\nTo initialize the API instance, you need to [obtain an API key from Google](https://aistudio.google.com/app/apikey?hl=fr).\n\nOnce you have a token, you can initialize `IGemini` interface, which is an entry point to the API.\n\nDue to the fact that there can be many parameters and not all of them are required, they are configured using an anonymous function.\n\n\u003e [!NOTE]\n\u003e```Pascal\n\u003euses Gemini;\n\u003e\n\u003evar Gemini := TGeminiFactory.CreateInstance(API_KEY);\n\u003e```\n\n\u003e[!Warning]\n\u003e To use the examples provided in this tutorial, especially to work with asynchronous methods, I recommend defining the Gemini interface with the widest possible scope.\n\u003e\u003cbr/\u003e\n\u003e So, set `Gemini := TGeminiFactory.CreateInstance(My_Key);` in the `OnCreate` event of your application.\n\u003e\u003cbr\u003e\n\u003eWhere `Gemini: IGemini;`\n\n\u003cbr/\u003e\n\n## Asynchronous callback mode management\n\nIn the context of asynchronous methods, for a method that does not involve streaming, callbacks use the following generic record: `TAsynCallBack\u003cT\u003e = record` defined in the `Gemini.Async.Support.pas` unit. This record exposes the following properties:\n\n```Pascal\n   TAsynCallBack\u003cT\u003e = record\n   ... \n       Sender: TObject;\n       OnStart: TProc\u003cTObject\u003e;\n       OnSuccess: TProc\u003cTObject, T\u003e;\n       OnError: TProc\u003cTObject, string\u003e; \n```\n\u003cbr/\u003e\n\nFor methods requiring streaming, callbacks use the generic record `TAsynStreamCallBack\u003cT\u003e = record`, also defined in the `Gemini.Async.Support.pas` unit. This record exposes the following properties:\n\n```Pascal\n   TAsynCallBack\u003cT\u003e = record\n   ... \n       Sender: TObject;\n       OnStart: TProc\u003cTObject\u003e;\n       OnSuccess: TProc\u003cTObject, T\u003e;\n       OnProgress: TProc\u003cTObject, T\u003e;\n       OnError: TProc\u003cTObject, string\u003e;\n       OnCancellation: TProc\u003cTObject\u003e;\n       OnDoCancel: TFunc\u003cBoolean\u003e;\n```\n\nThe name of each property is self-explanatory; if needed, refer to the internal documentation for more details.\n\n\u003cbr/\u003e\n\n## Gemini Models Overview\n\nList the various models available in the API. You can refer to the Models documentation to understand what models are available. See [Models Documentation](https://ai.google.dev/gemini-api/docs/models/gemini?hl=fr).\n\nAlongside its standard models, the `Gemini` API also includes experimental models offered in Preview mode. These models are intended for testing and feedback purposes and are not suitable for production use. `Google` releases these experimental models to gather insights from users, but there's no commitment that they will be developed into stable models in the future.\n\nRetrieving the list of available models through the API.\n\n1. **Synchronously**\n\n```Pascal\n// uses Gemini, Gemini.Models;\n\n  var List := Gemini.Models.List;\n  try\n    for var Item in List.Models do\n      WriteLn( Item.DisplayName );\n  finally\n    List.Free;\n  end;\n```\n\n2. **Asynchronously** : Using query parameters\n\n```Pascal\n// uses Gemini, Gemini.Models;\n\n// Declare \"Next\" a global variable, var Next: string;\n\n  Gemini.Models.AsynList(5, Next,\n    function : TAsynModels\n    begin\n      Result.Sender := Memo1;   // Set a TMemo on the form\n\n      Result.OnStart :=\n        procedure (Sender: TObject)\n        begin\n          // Handle the start\n        end;\n\n      Result.OnSuccess :=\n        procedure (Sender: TObject; List: TModels)\n        begin\n          var M := Sender as TMemo;\n          for var Item in List.Models do\n            begin\n              M.Text := M.Text + sLineBreak + Item.DisplayName;\n              Next := List.NextPageToken;\n            end;\n          M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n        end;\n\n      Result.OnError :=\n        procedure (Sender: TObject; Error: string)\n        begin\n          //Handle the error message\n        end\n    end);\n```\nThe previous example displays the models in batches of 5.\n\n3. **Asynchronously** : Retrive a model.\n\n```Pascal\n// uses Gemini, Gemini.Models;\n\n// Set a TMemo on the form\n\n  Gemini.Models.AsynList('models/Gemini-1.5-flash',\n    function : TAsynModel\n    begin\n      Result.OnSuccess :=\n        procedure (Sender: TObject; List: TModel)\n        begin\n          Memo1.Text := Memo1.Text + sLineBreak + List.DisplayName;\n          M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n        end;\n    end);\n```\n\n\u003cbr/\u003e\n\n## Embeddings\n\n**Embeddings** are numerical representations of text inputs that enable a variety of unique applications, including *clustering*, *measuring similarity*, and *information retrieval*. For an introduction, take a look at the [Embeddings guide](https://ai.google.dev/gemini-api/docs/embeddings). \u003cbr/\u003e\nSee also the [embeddings models](https://ai.google.dev/gemini-api/docs/models/gemini#text-embedding).\n\nIn the following examples, we will use the procedures 'Display' to simplify the examples.\n\n\u003e [!TIP]\n\u003e```Pascal\n\u003e  procedure Display(Sender: TObject; Embed: TEmbeddingValues); overload;\n\u003e  begin\n\u003e    var M := Sender as TMemo;\n\u003e    for var Item in Embed.Values do\n\u003e      begin\n\u003e        M.Lines.Text := M.Text + sLineBreak + Item.ToString;\n\u003e      end;\n\u003e    M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e  end;\n\u003e```\n\u003e\n\u003e```Pascal\n\u003e  procedure Display(Sender: TObject; Embed: TEmbeddings); overload;\n\u003e  begin\n\u003e    for var Item in Embed.Embeddings do\n\u003e      begin\n\u003e        Display(Sender, Item);\n\u003e      end;\n\u003e  end;\n\u003e```\n\n1. **Synchronously** : Get the vector representation of the text *'This is an example'*.\n\n```Pascal\n// uses Gemini, Gemini.Embeddings; \n\n  var Integration := Gemini.Embeddings.Create('models/text-embedding-004',\n            procedure (Params: TEmbeddingParams)\n            begin\n              Params.Content(['This is an example']);\n            end);\n  // For displaying, add a TMemo on the form\n  try\n    Display(Memo1, Integration.Embedding)\n  finally\n    Integration.Free;\n  end;\n```\n\n2. **Asynchronously** : Get the vector representation of the text *'This is an example'* and *'Second example'*.\u003cbr/\u003e\n - The vectors will be of reduced dimension (20).\n\n```Pascal\n// uses Gemini, Gemini.Embeddings; \n\n    Gemini.Embeddings.AsynCreateBatch('models/text-embedding-004',\n       procedure (Parameters: TEmbeddingBatchParams)\n       begin\n         Parameters.Requests(\n           [\n            TEmbeddingRequestParams.Create(\n              procedure (var Params: TEmbeddingRequestParams)\n              begin\n                Params.Content(['This is an example']);\n                Params.OutputDimensionality(20);\n              end),\n\n            TEmbeddingRequestParams.Create(\n              procedure (var Params: TEmbeddingRequestParams)\n              begin\n                Params.Content(['Second example']);\n                Params.OutputDimensionality(20);\n              end)\n           ]);\n       end,\n       // For displaying, add a TMemo on the form\n       function : TAsynEmbeddings\n       begin\n         Result.Sender := Memo1; \n         Result.OnSuccess := Display;\n       end);  \n```\n\u003cbr/\u003e\n\n## Generate text\n\nThe Gemini API enables [`text generation`](https://ai.google.dev/api/generate-content#method:-models.generatecontent) from a variety of inputs, including text, images, video, and audio. It can be used for a range of applications, such as:\n\n- Creative writing\n- Describing or interpreting media assets\n- Text completion\n- Summarizing open-form text\n- Translating between languages\n- Chatbots\n- Your own unique use cases\n\nIn the following examples, we will use the procedures 'Display' to simplify the examples.\n\u003e [!TIP] \n\u003e```Pascal\n\u003e  procedure Display(Sender: TObject; Chat: TChat); overload;\n\u003e  begin\n\u003e    var M := Sender as TMemo;\n\u003e    for var Item in Chat.Candidates do\n\u003e      begin\n\u003e        if Item.FinishReason = STOP then\n\u003e          for var SubItem in Item.Content.Parts do\n\u003e            begin\n\u003e              M.Lines.Text := M.Text + sLineBreak + SubItem.Text;\n\u003e            end;\n\u003e        M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e      end;\n\u003e  end;\n\u003e```\n\u003e\n\u003e```Pascal\n\u003e  procedure Display(Sender: TObject; Error: string); overload;\n\u003e  begin\n\u003e    var M := Sender as TMemo;\n\u003e    M.Lines.Text := M.Text + sLineBreak + Error;\n\u003e    M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e  end;  \n\u003e```\n\n\u003cbr/\u003e\n\n### Generate text from text-only input\n\nSynchronous mode\n```Pascal\n// uses Gemini, Gemini.Chat;\n\n  var Chat := Gemini.Chat.Create('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Write a story about a magic backpack.')]);\n    end);\n  // For displaying, add a TMemo on the form\n  try\n    Display(Memo1, Chat);\n  finally\n    Chat.Free;\n  end;\n```\n\nAsynchronous mode\n```Pascal\n// uses Gemini, Gemini.Chat;\n\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Write a story about a magic backpack.')]);\n    end,\n    // For displaying, add a TMemo on the form\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\nIn this example, the prompt (\"Write a story about a magic backpack\") doesn’t include output examples, system instructions, or formatting details, making it a [`zero-shot`](https://ai.google.dev/gemini-api/docs/models/generative-models#zero-shot-prompts) approach. In some cases, using a [`one-shot`](https://ai.google.dev/gemini-api/docs/models/generative-models#one-shot-prompts) or [`few-shot`](https://ai.google.dev/gemini-api/docs/models/generative-models#few-shot-prompts) prompt could generate responses that better match user expectations. You might also consider adding [`system instructions`](https://ai.google.dev/gemini-api/docs/system-instructions?lang=rest) to guide the model in understanding the task or following specific guidelines.\n\n\u003cbr/\u003e\n\n### Generate text from text-and-image input\n\nThe Gemini API supports multimodal inputs that combine text with media files. The example below demonstrates how to generate text from an input that includes both text and images.\n\n```Pascal\n  var Ref := 'D:\\MyFolder\\Images\\Image.png';\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Describe this image.', [Ref])]);\n    end,\n    // For displaying, add a TMemo on the form\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\nIn multimodal prompting, as with text-only prompting, various strategies and refinements can be applied. Based on the results from this example, you may want to add additional steps to the prompt or provide more specific instructions. For further information, [refer to strategies for file-based prompting](https://ai.google.dev/gemini-api/docs/file-prompting-strategies).\n\n\u003cbr/\u003e\n\n### Generate a text stream\n\nThe model typically returns a response only after finishing the entire text generation process. Faster interactions can be achieved by enabling streaming, allowing partial results to be handled as they’re generated.\n\nThe example below demonstrates how to implement streaming using the [`streamGenerateContent`](https://ai.google.dev/api/generate-content#method:-models.streamgeneratecontent) method to generate text from a text-only input prompt.\n\nDeclare this method for displaying.\n\n\u003e [!TIP]\n\u003e```Pascal\n\u003e  procedure DisplayStream(Sender: TObject; Buffer: string); overload;\n\u003e  begin\n\u003e  var M := Sender as TMemo;\n\u003e  for var i := 1 to Length(Buffer) do\n\u003e    begin\n\u003e      M.Lines.Text := M.Text + Buffer[i];\n\u003e      M.Lines.BeginUpdate;\n\u003e      try\n\u003e        Application.ProcessMessages;\n\u003e        M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e      finally\n\u003e        M.Lines.EndUpdate;\n\u003e      end;\n\u003e    end;\n\u003e  end;\n\u003e```\n\u003e\n\u003e```Pascal\n\u003e  procedure Display(Sender: TObject; Candidate: TChatCandidate); overload;\n\u003e  begin\n\u003e    for var Item in Candidate.Content.Parts do\n\u003e      if Assigned(Item) then\n\u003e        DisplayStream(Sender, Item.Text);\n\u003e  end;\n\u003e```\n\u003e\n\u003e```Pascal\n\u003e  procedure Display(Sender: TObject); overload;\n\u003e  begin\n\u003e    var M := Sender as TMemo;\n\u003e    M.Lines.Text := M.Text + sLineBreak;\n\u003e    M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e  end;\n\u003e\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Safety;\n\n  Gemini.Chat.CreateStream('models/gemini-1.5-flash',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Write a story about a magic backpack.')]);\n    end,\n    // For displaying, add a TMemo on the form\n    procedure (var Chat: TChat; IsDone: Boolean; var Cancel: Boolean)\n    begin\n      if IsDone then\n        begin\n          Display(Memo1);\n        end;\n      if Assigned(Chat) then\n        begin\n          for var Item in Chat.Candidates do\n            begin\n              if Item.FinishReason \u003c\u003e TFinishReason.SAFETY then\n                begin\n                  Display(Memo1, Item);\n                end;\n            end;\n        end;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Build an interactive chat\n\nYou can leverage the Gemini API to create interactive chat experiences tailored for your users. By using the API’s chat feature, you can gather multiple rounds of questions and responses, enabling users to progress gradually toward their answers or receive assistance with complex, multi-part issues. This functionality is especially useful for applications that require continuous communication, such as chatbots, interactive learning tools, or customer support assistants.\n\nHere’s an example of a basic chat implementation:\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Safety;\n\n  Gemini.Chat.CreateStream('models/gemini-1.5-flash',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([\n        TPayload.User('Hello'),\n        TPayload.Assistant('Great to meet you. What would you like to know?'),\n        TPayload.User('I have two dogs in my house. How many paws are in my house?')\n      ]);\n    end,\n    // For displaying, add a TMemo on the form\n    procedure (var Chat: TChat; IsDone: Boolean; var Cancel: Boolean)\n    begin\n      if IsDone then\n        begin\n          Display(Memo1);\n        end;\n      if Assigned(Chat) then\n        begin\n          for var Item in Chat.Candidates do\n            begin\n              if Item.FinishReason \u003c\u003e TFinishReason.SAFETY then\n                begin\n                  Display(Memo1, Item);\n                end;\n            end;\n        end;\n    end);  \n```\n\u003cbr/\u003e\n\nHere’s an example of a asynchronous chat implementation\n\nDeclare this method for displaying.\n\u003e [!TIP]\n\u003e```Pascal\n\u003e  procedure DisplayStream(Sender: TObject; Chat: TChat); overload;\n\u003e  begin\n\u003e    Display(Sender, Chat.Candidates[0]);\n\u003e  end;\n\u003e```\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Safety;\n\n  Gemini.Chat.AsynCreateStream('models/gemini-1.5-flash',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([\n        TPayload.User('Hello'),\n        TPayload.Assistant('Great to meet you. What would you like to know?'),\n        TPayload.User('I have two dogs in my house. How many paws are in my house?')\n      ]);\n    end,\n    // For displaying, add a TMemo on the form    \n    function : TAsynChatStream\n    begin\n      Result.Sender := Memo1;\n      Result.OnProgress := DisplayStream;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Configure text generation\n\nEach prompt sent to the model includes settings that control how responses are generated. You can adjust these settings using the `GenerationConfig`, which allows you to customize various [parameters](https://ai.google.dev/gemini-api/docs/models/generative-models#model-parameters). If no configurations are applied, the model will rely on default settings, which may differ depending on the model.\n \nHere's an example demonstrating how to adjust several of these options.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Safety;\n  var GenerateContent := Gemini.Chat.Create('models/gemini-1.5-flash',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Write a story about a magic backpack.')]);\n\n      {--- Specifies safety settings to block unsafe content. }\n      Params.SafetySettings([\n        TSafety.DangerousContent(BLOCK_ONLY_HIGH),\n        TSafety.HateSpeech(BLOCK_MEDIUM_AND_ABOVE) ]);\n\n      {--- Configures generation options for the model's outputs. }\n      Params.GenerationConfig(\n        procedure (var Params: TGenerationConfig)\n        begin\n          Params.StopSequences(['Title']);\n          Params.Temperature(1.0);\n          Params.MaxOutputTokens(800);\n          Params.TopP(0.8);\n          Params.TopK(10);\n        end);\n    end);\n```\n\n- The Gemini API offers adjustable safety settings that you can configure during the prototyping phase to decide if your application needs a stricter or more flexible safety setup. [Refer to the official documentation](https://ai.google.dev/gemini-api/docs/safety-settings).\nSee also the `Gemini.Safety.pas` unit and the `TSafety` record.\n\n- The generation configuration allows for setting up the output production of a model. A complete description of the manageable parameters can be found at the following [`GitHub address`](https://github.com/google-gemini/generative-ai-python/blob/main/docs/api/google/generativeai/types/GenerationConfig.md). Internally, these parameters are defined within the `TGenerationConfig` class, which extends TJSONParam in the `Gemini.Chat.pas` unit.\n\n\u003cbr/\u003e\n\n## Document processing\n\nThe Gemini API can handle and perform inference on uploaded PDF documents. Once a PDF is provided, the Gemini API can:\n\n- Describe or answer questions about the content\n- Summarize the content\n- Generate extrapolations based on the content\n\nThis guide illustrates various methods for prompting the Gemini API using uploaded PDF documents. All outputs are text-only.\n\nThe `Gemini 1.5 Pro` and `1.5 Flash` models can handle up to **3,600 pages** per document. Supported file types for text data include:\n\n- **PDF**: `application/pdf`\n- **JavaScript**: `application/x-javascript`, `text/javascript`\n- **Python**: `application/x-python`, `text/x-python`\n- **TXT**: `text/plain`\n- **HTML**: `text/html`\n- **CSS**: `text/css`\n- **Markdown**: `text/md`\n- **CSV**: `text/csv`\n- **XML**: `text/xml`\n- **RTF**: `text/rtf`\nEach page consists of **258 tokens**.\n\nTo achieve optimal results:\n\nEnsure pages are oriented correctly before uploading. Use **high-quality images** without blurring. If uploading a single page, add the text prompt following the page.\n\nThere aren’t any strict pixel limits for documents beyond the model’s context capacity. Larger pages are scaled down to a maximum of **3072x3072 pixels** while keeping their aspect ratio, whereas smaller pages are scaled up to **768x768 pixels**. However, there’s no cost savings for using smaller images, other than reduced bandwidth, nor any performance boost for higher-resolution pages.\n\n\u003cbr/\u003e\n\n### Upload a document and generate content\n\nYou can upload documents of any size by using the File API. Always rely on the File API whenever the combined size of the request—including files, text prompt, system instructions, and any other data—exceeds 20 MB.\n\n\u003e [!NOTE]\n\u003e You can use the File API to store files for up to 48 hours, with a storage limit of 20 GB per project and a maximum of 2 GB per file. During this time, files are accessible with your API key but are not downloadable through the API. The File API is free to use and available in all regions where the Gemini API operates.\n\u003e\n\nUse the synchronous method `Gemini.Files.Upload` or then asynchronous method `Gemini.Files.AsyncUpload` to upload a file with the File API. The following code uploads a document file and then uses it in a call to `models.generateContent`.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Files;\n\n  var FileUri := '';\n  {--- Upload file and get its uri }\n  var MyFile := Gemini.Files.UpLoad('Z:\\my_folder\\document\\My_document.PDF', 'MyFile');\n  try\n    FileUri := MyFile.\u0026File.URI;\n    Display(Memo1, FileUri);\n  finally\n    MyFile.Free;\n  end;\n \n  {--- Generate text from a document using its URI. }\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Summarize the document.', [FileUri])]);\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Get metadata for a file\n\nYou can confirm that the API successfully saved the uploaded file and retrieve its metadata by using `Gemini.Files.Retrieve` or `Gemini.Files.AsynRetrieve`. Only the name (and therefore, the URI) is unique.\n\n```Pascal\n// uses Gemini, Gemini.Files;\n\n  var FileCode := 'files/{code}'  //e.g. 'files/yrsihy2hdyz7'\n  var GetFile := Gemini.Files.Retrieve(FileCode);\n\n  try\n    Display(Memo1, GetFile.Name + ' : ' + GetFile.MimeType + ' : ' + GetFile.DisplayName);\n  finally\n    GetFile.Free;\n  end;\n```\n\n\u003cbr/\u003e\n\n### List files\n\nYou can list all files uploaded using the File API and their URIs using `Gemini.Files.List` or `Gemini.Files.AsynList`.\n\nDeclare this method for displaying.\n\u003e [!TIP]\n\u003e ```Pascal\n\u003e   procedure Display(Sender: TObject; Files: TFiles); overload;\n\u003e   begin\n\u003e     var M := Sender as TMemo;\n\u003e     for var Item in Files.Files do\n\u003e       begin\n\u003e         M.Text := M.Text + sLineBreak + Item.Name + '   ' + Item.MimeType + '   ' + Item.Uri + sLineBreak;\n\u003e         M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e       end;\n\u003e     M.Text := M.Text + sLineBreak;\n\u003e     M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e   end;\n\u003e ```\n\n```Pascal\n// uses Gemini, Gemini.Files;\n\n  Gemini.Files.AsynList(\n     function : TAsynFiles\n     begin\n       Result.Sender := Memo1;\n       Result.OnSuccess := Display;\n       Result.OnError := Display;\n     end);  \n```\n\nBy default, a list of 10 elements will be retrieved. We can refine the process of obtaining the list of files using the following methods:\n\n- `List(const PageSize: Integer; const PageToken: string);`\n- `AsyncList(const PageSize: Integer; const PageToken: string; Callbacks: TFunc\u003cTAsyncFiles\u003e);`\n\nThese methods allow for more precise control over pagination and callback handling.\n\n\u003cbr/\u003e\n\n### Delete files\n\nFiles uploaded with the File API are automatically removed **after 48 hours**. You can also delete them manually using either `Gemini.Files.Delete` or `Gemini.Files.Delete`.\n\nDeclare this method for displaying.\n\u003e [!TIP]\n\u003e```Pascal\n\u003e  procedure Display(Sender: TObject; Delete: TFileDelete); overload;\n\u003e  begin\n\u003e    Display(Sender, 'deleted');\n\u003e  end;\n\u003e```\n\n```Pascal\n// uses Gemini, Gemini.Files;\n\n  var FileCode := 'files/{code}';  // e.g. files/yrsihy2hdyz7\n  Gemini.Files.AsynDelete(FileCode,\n    function : TAsynFileDelete\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n## System instructions\n\nWhen setting up an AI model, you can define guidelines for how it should respond, like assigning it a specific role `you are a rocket scientist` or instructing it on a particular tone `speak like a pirate`. These parameters are established by configuring the system instructions during the model's initialization.\n\nSystem instructions let you shape the model’s behavior to fit specific needs and use cases. When set, they provide added context that guides the model to perform tasks in a more tailored way, adjusting its responses to meet particular guidelines across the entire interaction. These instructions apply across multiple exchanges with the model.\n\nSystem instructions can be used for various purposes, such as:\n\n- **Defining a persona or role** (e.g., setting the model to act as a customer service chatbot)\n- **Specifying output format** (like Markdown, JSON, or YAML)\n- **Setting output style and tone** (for example, adjusting verbosity, formality, or reading level)\n- **Outlining goals or rules for the task** (for instance, delivering a code snippet without extra explanation)\n- **Providing relevant context** (such as a knowledge cutoff date)\n\nYou can configure these instructions when initializing the model, and they will persist throughout the session, guiding the model’s responses. They form part of the model’s prompts and are governed by standard data use policies.\n\n```Pascal\n// uses Gemini, Gemini.Chat;\n\n  Gemini.Chat.AsynCreateStream('models/gemini-1.5-flash-001',\n    procedure (Params: TChatParams)\n    begin\n      Params.SystemInstruction('you are a rocket scientist');\n      Params.Contents([ TPayload.Add('What are the differences between the Saturn 5 rocket and the Saturn 1 rocket?') ]);\n    end,\n    function : TAsynChatStream\n    begin\n      Result.Sender := Memo1;\n      Result.OnProgress := DisplayStream;\n      Result.OnError := Display;\n    end);\n```\n\n\u003e [!CAUTION]\n\u003e System instructions can guide the model to follow directions but don’t fully safeguard against jailbreaks or leaks. We recommend being cautious about including any sensitive information in these instructions.\n\u003e\n\nSee [More examples](https://ai.google.dev/gemini-api/docs/system-instructions?lang=rest#more-examples) on official site.\n\n\u003cbr/\u003e\n\n## Vision\n\nThe Gemini API can perform inference on both images and videos provided to it. When given a single image, a sequence of images, or a video, Gemini can:\n\n- Describe or respond to questions about the content,\n- Provide a summary of the content,\n- Make inferences based on the content.\n\nAll outputs are text-based only.\n\n\u003cbr/\u003e\n\n### Prompting with images\n\nThe Gemini 1.5 Pro and 1.5 Flash models can support up to **3,600 image files**.\n\nSupported image **MIME types** include the following formats:\n\n- **PNG** - `image/png`\n- **JPEG** - `image/jpeg`\n- **WEBP** - `image/webp`\n- **HEIC** - `image/heic`\n- **HEIF** - `image/heif`\n\nEach image counts as **258 tokens**.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Files;\n\n  var FileUri := '';\n  {--- Upload file and get its uri }\n  var MyFile := Gemini.Files.UpLoad('Z:\\my_folder\\image\\my_image.png', 'MyFile');\n  try\n    FileUri := MyFile.\u0026File.URI;\n    Display(Memo1, FileUri);\n  finally\n    MyFile.Free;\n  end;\n \n  {--- Generate text from an image using its Uri. }\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Describe this image.', [FileUri])]);\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Prompting with video\n\nGemini 1.5 Pro and Flash can process up to about one hour of video content.\n\nSupported video formats include the following MIME types:\n\n- `video/mp4`\n- `video/mpeg`\n- `video/mov`\n- `video/avi`\n- `video/x-flv`\n- `video/mpg`\n- `video/webm`\n- `video/wmv`\n- `video/3gpp`\n\nThrough the File API service, frames are extracted from videos at a rate of 1 frame per second (FPS), and audio is extracted at 1Kbps in single-channel mode, with timestamps marked every second. These rates may be adjusted in the future to enhance processing capabilities.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Files;\n\n  var FileUri := '';\n  {--- Upload file and get its uri }\n  var MyFile := Gemini.Files.UpLoad('Z:\\my_folder\\video\\my_video.mp4', 'MyFile');\n  try\n    FileUri := MyFile.\u0026File.URI;\n    Display(Memo1, FileUri);\n  finally\n    MyFile.Free;\n  end;\n \n  {--- Generate text from a video using its Uri. }\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Describe this video clip.', [FileUri])]);\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n## Audio\n\nGemini can handle audio prompts by:\n\n- Describing, summarizing, or answering questions about audio content\n- Providing a transcription of the audio\n- Offering answers or a transcription for a specific part of the audio\n\n\u003e [!IMPORTANT]\n\u003e The Gemini API doesn't support audio output generation.\n\u003e\n\nGemini is compatible with the following audio format MIME types:\n\n- **WAV**: `audio/wav`\n- **MP3**: `audio/mp3`\n- **AIFF**: `audio/aiff`\n- **AAC**: `audio/aac`\n- **OGG** `Vorbis: audio/ogg`\n- **FLAC**: `audio/flac`\n\nGemini processes audio by breaking it down into **25 tokens per second**, so one minute of audio translates to **1,500 tokens**. The system currently only interprets spoken English but can recognize non-verbal sounds like birdsong or sirens. For a single input, Gemini supports a maximum audio length of **9.5 hours**. While there’s no restriction on the number of files per prompt, their total length combined cannot exceed 9.5 hours. All audio is downsampled to a **16 Kbps data rate**, and if the audio has multiple channels, they’re merged into a single channel.\n\n\u003cbr/\u003e\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Files;\n\n  var FileUri := '';\n  {--- Upload file and get its uri }\n  var MyFile := Gemini.Files.UpLoad('Z:\\my_folder\\sound\\my_sound.wav', 'MyFile');\n  try\n    FileUri := MyFile.\u0026File.URI;\n    Display(Memo1, FileUri);\n  finally\n    MyFile.Free;\n  end;\n \n  {--- Generate text from an audio record using its Uri. }\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Describe this audio clip.', [FileUri])]);\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Speech-to-text\n\nThe primary purpose of speech-to-text technology is to provide a text transcription of a voice recording, which is inherently temporary in nature. Therefore, uploading this audio file is unnecessary, as it will be used only once for transcription.\n\nTo perform the transcription, simply follow the example below, assuming the audio file has already been provided through a prior recording process.\n\n```Pascal\n// uses Gemini, Gemini.Chat;\n\n  var SpeechSource := 'Z:\\my_folder\\sound\\my_speech.wav';\n  {--- Transcribe the audio recording into a text. }\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('Transcribe the audio recording into English.', [SpeechSource])]);\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Text-to-speech\n\nAs stated above, the Gemini API doesn't support audio output generation, and the Gemini APIs do not provide any method to transcribe text into an audio file. On the other hand, Google Cloud offers an alternative, which you can find [here](https://cloud.google.com/text-to-speech/?utm_source=google\u0026utm_medium=cpc\u0026utm_campaign=emea-gb-all-en-dr-bkws-all-all-trial-%7Bmatchtype%7D-gcp-1707574\u0026utm_content=text-ad-none-any-DEV_%7Bdevice%7D-CRE_%7Bcreative%7D-ADGP_%7B_dsadgroup%7D-KWID_%7B_dstrackerid%7D-%7Btargetid%7D-userloc_%7Bloc_physical_ms%7D\u0026utm_term=KW_%7Bkeyword%7D-NET_%7Bnetwork%7D-PLAC_%7Bplacement%7D\u0026%7B_dsmrktparam%7D%7Bignore%7D\u0026%7B_dsmrktparam%7D\u0026gclsrc=aw.ds\u0026gad_source=1\u0026gclid=Cj0KCQjw1Yy5BhD-ARIsAI0RbXZf2NNU_LQ_rYqNEeTpm3Q0QPI83Jap8PAIl6ZFzulFAD3cY-z487oaAvk0EALw_wcB\u0026gclsrc=aw.ds\u0026hl=en).\n\n\u003cbr/\u003e\n\n## Long context\n\nSee the [official documentation](https://ai.google.dev/gemini-api/docs/long-context).\n\n\u003cbr/\u003e\n\n## Code execution\n\nThe Gemini API’s code execution feature allows the model to generate and execute Python code, enabling it to learn iteratively from the results until it reaches a final output. This capability can be applied to build applications that benefit from code-based reasoning and produce text-based results. For instance, code execution could be utilized in applications designed for solving equations or text processing.\n\nCode execution is available in both AI Studio and the Gemini API. In AI Studio, it can be enabled within Advanced settings. With the Gemini API, code execution functions as a tool similar to function calling, allowing the model to decide when to use it.\n\n\u003e [!NOTE]\n\u003e The code execution environment has the NumPy and SymPy libraries available. You aren’t able to install additional libraries.\n\u003e\n\u003cbr/\u003e\n\nDeclare this method for displaying.\n\u003e [!TIP]\n\u003e ```Pascal\n\u003e  procedure DisplayCode(Sender: TObject; Chat: TChat); \n\u003e  begin\n\u003e  for var Candidate in Chat.Candidates do\n\u003e    begin\n\u003e      for var Part in Candidate.Content.Parts do\n\u003e        begin\n\u003e          if Assigned(Part.ExecutableCode) then\n\u003e            DisplayStream(Sender, Part.ExecutableCode.Code)\n\u003e          else\n\u003e            DisplayStream(Sender, Part.Text);\n\u003e        end;\n\u003e    end;\n\u003e  end;\n\u003e ```\n\n```Pascal\n// uses Gemini, Gemini.Chat;\n\n  Gemini.Chat.ASynCreateStream('models/gemini-1.5-flash',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50.')]);\n      Params.Tools(CodeExecution);  // Enable code execution\n    end,\n    function : TAsynChatStream\n    begin\n      Result.Sender := Memo1;\n      Result.OnProgress := DisplayCode;\n      Result.OnError := Display;\n    end);\n```\n\nCode execution and function calling are similar features with distinct use cases:\n\nCode execution allows the model to run code directly in the API backend within a controlled, isolated environment. Function calling enables running functions that the model requests in a separate, customizable environment of your choice.\n\nGenerally, code execution is preferable if it meets your requirements, as it’s simpler to enable and completes within a single GenerateContent request, resulting in a single charge. In contrast, function calling requires an additional GenerateContent request to return each function’s output, leading to multiple charges.\n\nTypically, use function calling if you need to run custom functions locally. For cases where the API should generate and execute Python code and deliver results, code execution is often the best fit.\n\n\u003cbr/\u003e\n\n## Function calling\n\nThe Gemini API’s function calling feature allows you to define custom functions that the model can suggest, providing structured output that includes the function name and recommended arguments. While the model doesn’t execute these functions directly, it outputs suggestions, allowing you to trigger an external API call with those parameters. This approach enables you to bring real-time data from external sources, such as databases, CRM systems, or document repositories, into the conversation, allowing the model to deliver more contextually relevant and actionable responses.\n\nPlease refer to the [official documentation](https://ai.google.dev/gemini-api/docs/function-calling#how_it_works) for more information.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.tools, Gemini.Functions.Core, Gemini.Functions.Example;\n\n  var Weather := TWeatherReportFunction.CreateInstance;\n\n  var Chat := Gemini.Chat.Create('models/gemini-1.5-flash',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.User('What is the weather like in Paris?')]);\n      Params.Tools([Weather]);\n      Params.ToolConfig(AUTO);\n    end);\n  try\n    for var Item in Chat.Candidates do\n      begin\n        for var SubItem in Item.Content.Parts do\n          begin\n            if Assigned(SubItem.FunctionCall) then\n              CallFunction(SubItem.FunctionCall, Weather) else\n              DisplayStream(Memo1, SubItem.Text);\n          end;\n      end;\n  finally\n    Chat.Free;\n  end;\n\n...\n\n  procedure TForm.CallFunction(const Value: TFunctionCall; Func: IFunctionCore);\n  begin\n    var ArgResult := Func.Execute(Value.Args);\n    Gemini.Chat.ASynCreateStream('models/gemini-1.5-flash',\n      procedure (Params: TChatParams)\n      begin\n        Params.Contents([TPayload.Add(ArgResult)]);\n      end,\n      function : TAsynChatStream\n      begin\n        Result.Sender := Memo1;\n        Result.OnProgress := DisplayStream;\n        Result.OnError := Display;\n      end);\n  end;\n```\n\n\u003cbr/\u003e\n\n## Context caching\n\nIn many AI workflows, you may need to send the same input tokens repeatedly to a model. With the Gemini API’s context caching feature, you can submit content once, store the input tokens in a cache, and reference these cached tokens for future requests. At certain usage volumes, this method is more cost-effective than repeatedly submitting the same tokens.\n\nWhen you cache tokens, you can specify a duration for how long they remain stored before automatic deletion. This duration is known as the time to live `TTL`, and if not specified, it defaults to 1 hour. The cost of caching varies based on the input token size and the desired `TTL`.\n\n\u003e [!NOTE]\n\u003e Context caching is available only for stable models with fixed versions (such as `gemini-1.5-pro-001`). Be sure to include the version suffix (like the -001 in `gemini-1.5-pro-001`).\n\u003e\n\nTo utilize the code examples, please download the file titled Apollo 11 Conversation available at the following link: https://storage.googleapis.com/generativeai-downloads/data/a11.txt.\n\n\u003cbr/\u003e\n\n### Set the context to cache\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Caching;\n\n  var CacheName := '';  // Variable to store the name of the obtained cache\n\n  var a11 := 'Z:\\Download\\Text\\a11.txt';\n\n  Gemini.Caching.ASynCreate(\n    procedure (Params: TCacheParams)\n    begin\n      Params.Contents([TPayload.User([a11])]);\n      Params.SystemInstruction('You are an expert on the history of space exploration.');\n      Params.ttl('800s');\n      Params.Model('models/gemini-1.5-flash-001');\n    end,\n\n    function : TAsynCache\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess :=\n        procedure (Sender: TObject; Cache: TCache)\n        begin\n          CacheName := Cache.Name;\n          DisplayStream(Sender, Cache.Name)\n        end;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Use cached context\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Caching;\n\n  Gemini.Chat.AsynCreateStream('models/gemini-1.5-flash-001',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([ TPayload.User('Please summarize this transcript') ]);\n      Params.CachedContent(CacheName);  // cachedContents/{code} e.g. cachedContents/phd5r5zz767u\n    end,\n    function : TAsynChatStream\n    begin\n      Result.Sender := Memo1;\n      Result.OnProgress := DisplayStream;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);  \n```\n\n\u003cbr/\u003e\n\n### List caches\n\n**It's not possible to access or view cached content directly**, but you can retrieve cache metadata, including the name, model, display name, usage metadata, creation time, update time, and expiration time.\n\nDeclare this method for displaying.\n\u003e [!TIP]\n\u003e ```Pascal\n\u003e  procedure Display(Sender: TObject; Cache: TCacheContents); overload;\n\u003e  begin\n\u003e    var M := Sender as TMemo;\n\u003e    if Length(Cache.CachedContents) \u003e 0 then\n\u003e      begin\n\u003e        for var Item in Cache.CachedContents do\n\u003e          begin\n\u003e            M.Text := M.Text + Item.Name + '  Expire at : ' +  Item.expireTime + sLineBreak;\n\u003e            M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e          end;\n\u003e      end\n\u003e    else\n\u003e      M.Text := M.Text + 'No items cached' + sLineBreak;\n\u003e    M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e  end;\n\u003e``` \n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Caching;\n\n  // Declare Next as string\n\n  Gemini.Caching.ASynList(20, Next,\n    function : TAsynCacheContents\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);  \n```\n\n\u003cbr/\u003e\n\n### Retrieve a cache\n\nReads CachedContent resource.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Caching;\n\n  var CacheName := 'cachedContents/{code}';  //e.g. cachedContents/phd5r5zz767u\n\n  Gemini.Caching.ASynRetrieve(CacheName,\n    function : TAsynCache\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess :=\n        procedure (Sender: TObject; Cache: TCache)\n        begin\n          Display(Sender, Cache.Name + '  Expire at : ' + Cache.ExpireTime);\n        end;\n      Result.OnError := Display;\n    end);\n```\n\n\n\u003cbr/\u003e\n\n### Update a cache\n\nYou can update the `TTL` or expiration time for a cache, but modifying any other cache settings isn’t allowed.\n\nHere’s an example of how to update a cache’s `TTL`.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Caching;\n\n  var CacheName := 'cachedContents/{code}';  //e.g. cachedContents/phd5r5zz767u\n\n  Gemini.Caching.ASynUpdate(CacheName, '2300s',\n    function : TAsynCache\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess :=\n        procedure (Sender: TObject; Cache: TCache)\n        begin\n          Display(Sender, Cache.Name + '  Expire at : ' + Cache.ExpireTime);\n        end;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n### Delete a cache\n\nThe caching service includes a delete function that allows users to manually remove content from the cache. The example below demonstrates how to delete a cache.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.Caching;\n\n  var CacheName := 'cachedContents/{code}';  //e.g. cachedContents/phd5r5zz767u\n\n  Gemini.Caching.ASynDelete(CacheName,\n    function : TAsynCacheDelete\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess :=\n        procedure (Sender: TObject; EmptyCache: TCacheDelete)\n        begin\n          Display(Sender, CacheName + ' deleted');\n        end;\n      Result.OnError := Display;\n    end);\n```\n\n\u003cbr/\u003e\n\n## Safety\n\nThe Gemini API offers adjustable safety settings, allowing you to tailor the level of restriction during the prototyping phase. You can modify these settings across four filtering categories to control the types of content allowed or restricted, depending on your application's needs.\n\nRefer to [Safety filters](https://ai.google.dev/gemini-api/docs/safety-settings#safety-filters) in the officiel documentation.\n\n\u003cbr/\u003e\n\nGenerative AI models are highly versatile tools, yet they come with certain limitations. While their broad applicability offers great potential, it can also lead to unpredictable outcomes, including outputs that may be inaccurate, biased, or even offensive. To mitigate these risks, careful post-processing and thorough manual evaluation are crucial steps in ensuring the safety and reliability of these models.\n\nRefer to [Safety guidance](https://ai.google.dev/gemini-api/docs/safety-guidance) in the officiel documentation.\n\n\u003cbr/\u003e\n\n### TSafety record\n\nThe `TSafety` record is defined in the `Gemini.Safety.pas` unit is designed to configure safety rules by setting blocking thresholds for various categories of potentially harmful content. Here’s a summary of its capabilities:\n\n\u003cbr/\u003e\n\n1. Safety Categories Configuration:\n     \n     The record allows setting specific blocking rules for categories of content, including:\n     - `HARM_CATEGORY_HARASSMENT` (Harassment)\n     - `HARM_CATEGORY_HATE_SPEECH` (Hate Speech)\n     - `HARM_CATEGORY_SEXUALLY_EXPLICIT` (Sexually Explicit Content)\n     - `HARM_CATEGORY_DANGEROUS_CONTENT` (Dangerous Content)\n     - `HARM_CATEGORY_CIVIC_INTEGRITY` (Civic Integrity)\n\n\u003cbr/\u003e\n\n2. Blocking Thresholds (THarmBlockThreshold):\n     \n     You can specify different blocking levels based on the probability of content being harmful:\n     - `BLOCK_LOW_AND_ABOVE`: Blocks content with a low probability of harm or higher.\n     - `BLOCK_MEDIUM_AND_ABOVE`: Blocks content with a medium probability of harm or higher.\n     - `BLOCK_ONLY_HIGH`: Only blocks content with a high probability of harm.\n     - `BLOCK_NONE`: Does not block any content.\n     - `OFF`: Completely disables the safety filter.\n\n\u003cbr/\u003e\n\n3. Methods for Setting Specific Rules:\n     \n     - `SexuallyExplicit`, `HateSpeech`, `Harassment`, `DangerousContent`, `CivicIntegrity`: These methods create a TSafety object for each content category with a specified blocking threshold.\n     - `DontBlock`: Returns an array of `TSafety` configurations where each category is set to not block any content (`BLOCK_NONE`).\n\n\u003cbr/\u003e\n\n4. JSON Conversion:\n     \n     The `ToJson` method converts the defined safety settings in a `TSafety` object to JSON format, with fields `category` (content category) and `threshold` (blocking threshold), facilitating export and storage.\n\n\u003cbr/\u003e\n\n5. Fluent Creation Methods:\n     \n     Category and `Threshold`: These methods allow updating the category and blocking threshold for the current instance, enabling a fluent API style for chainable configuration.\n\n\u003cbr/\u003e\n\nIn summary, `TSafety` provides a flexible interface for setting up and adjusting safety filters in a Delphi application, based on different harm categories and probability thresholds, with convenient methods for category-specific configuration and easy JSON conversion.\n\n\u003cbr/\u003e\n\n## Fine-tuning\n\nWhen **few-shot prompting** does not yield the desired results, **fine-tuning** can enhance model performance on specific tasks. This process allows the model to better adhere to particular output requirements by using a curated set of examples that demonstrate the desired outcomes when instructions alone are insufficient. **Fine-tuning** thus helps to align the model's responses more closely with specific expectations.\n\nRefer to [official documentation](https://ai.google.dev/gemini-api/docs/model-tuning#how-model).\n\n\u003cbr/\u003e\n\n### Create tuning task\n\nA training task comprises [***hyperparameter***](https://ai.google.dev/gemini-api/docs/model-tuning#advanced-settings)  values and ***training data*** represented as a list of input texts and corresponding response texts. \n\nThe hyperparameters include `LearningRate`, `EpochCount`, and `BatchSize`. Training values can be directly specified within the dataset or imported from a `JSONL` or `CSV` file (using a semicolon as a separator).\n\n\u003e [!NOTE]\n\u003e For a comprehensive introduction to these hyperparameters, refer to the section [\"Hyperparameters in Linear Regression\"](https://developers.google.com/machine-learning/crash-course/linear-regression/hyperparameters?hl=fr) in the [Machine Learning Crash Course](https://developers.google.com/machine-learning/crash-course?hl=fr).\n\u003e\n\n\u003cbr/\u003e\n\n- Example 1 :\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var TuningTask := TTuningTaskParams.Create\n    .Hyperparameters(\n       procedure (var Params : THyperparametersParams)\n       begin\n         Params.LearningRate(0.001);\n         Params.EpochCount(4);\n         Params.BatchSize(2);\n       end)\n    .TrainingData([\n       Example.AddItem('1', '2'),\n       Example.AddItem('2', '3'),\n       Example.AddItem('-3', '-2'),\n       Example.AddItem('twenty two', 'twenty three'),\n       Example.AddItem('two hundred', 'two hundred one'),\n       Example.AddItem('ninety nine', 'one hundred'),\n       Example.AddItem('8', '9'),\n       Example.AddItem('-98', '-97'),\n       Example.AddItem('1,000', '1,001'),\n       Example.AddItem('10,100,000', '10,100,001'),\n       Example.AddItem('thirteen', 'fourteen'),\n       Example.AddItem('eighty', 'eighty one'),\n       Example.AddItem('one', 'two'),\n       Example.AddItem('three', 'four'),\n       Example.AddItem('seven', 'eight')\n     ]);\n  Display(Memo1, TuningTask.ToFormat(True));\n```\n\n- Example 2 : You have chosen to implement a ***TrainingData.jsonl*** file in `JSONL` format, structured as follows.\n\n```Jsonl\n{\"text_input\": \"1\",\"output\": \"2\"}\n{\"text_input\": \"3\",\"output\": \"4\"}\n{\"text_input\": \"-3\",\"output\": \"-2\"}\n{\"text_input\": \"twenty two\",\"output\": \"twenty three\"}\n{\"text_input\": \"two hundred\",\"output\": \"two hundred one\"}\n{\"text_input\": \"ninety nine\",\"output\": \"one hundred\"}\n{\"text_input\": \"8\",\"output\": \"9\"}\n{\"text_input\": \"-98\",\"output\": \"-97\"}\n{\"text_input\": \"1,000\",\"output\": \"1,001\"}\n{\"text_input\": \"10,100,000\",\"output\": \"10,100,001\"}\n{\"text_input\": \"thirteen\",\"output\": \"fourteen\"}\n{\"text_input\": \"eighty\",\"output\": \"eighty one\"}\n{\"text_input\": \"one\",\"output\": \"two\"}\n{\"text_input\": \"three\",\"output\": \"four\"}\n{\"text_input\": \"seven\",\"output\": \"eight\"}\n```\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var TuningTask := TTuningTaskParams.Create\n    .Hyperparameters(\n       procedure (var Params : THyperparametersParams)\n       begin\n         Params.LearningRate(0.001);\n         Params.EpochCount(4);\n         Params.BatchSize(2);\n       end)\n    .TrainingData('TrainingData.jsonl');\n  Display(Memo1, TuningTask.ToFormat(True));\n```\n\n- Example 3 : You have chosen to implement a ***TrainingData.csv*** file in `csv` format, structured as follows.\n\n```Csv\ntext_input;output\n1;2\n3;4\n-3;-2\ntwenty two;twenty three\ntwo hundred;two hundred one\nninety nine;one hundred\n8;9\n-98;-97\n\"1,000\";\"1,001\"\n\"10,100,000\";\"10,100,001\"\nthirteen;fourteen\neighty;eighty one\none;two hundred one\nthree;fourteen\nseven;eight\n```\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var TuningTask := TTuningTaskParams.Create\n    .Hyperparameters(\n       procedure (var Params : THyperparametersParams)\n       begin\n         Params.LearningRate(0.001);\n         Params.EpochCount(4);\n         Params.BatchSize(2);\n       end)\n    .TrainingData('TrainingData.csv');\n  Display(Memo1, TuningTask.ToFormat(True));\n```\n\n\u003cbr/\u003e\n\n### Upload tuning dataset\n\nThis example shows how to create a tuned model. Check intermediate tuning progress (if any) through the google.longrunning.Operations service.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var TuningTask := TTuningTaskParams.Create\n    .Hyperparameters(\n       procedure (var Params : THyperparametersParams)\n       begin\n         Params.LearningRate(0.001);\n         Params.EpochCount(4);\n         Params.BatchSize(2);\n       end)\n    .TrainingData('TrainingData.jsonl');\n\n  var TuningDataSet := TTunedModelParams.Create\n    .DisplayName('number generator model')\n    .BaseModel('models/gemini-1.0-pro-001')\n    .TuningTask(TuningTask);\n\n  var Tuning := Gemini.FineTune.Create(TuningDataSet.Detach);\n  try\n    Display(Memo1, Tuning.Name + sLineBreak + Tuning.Metadata);\n  finally\n    Tuning.Free;\n  end;\n```\n\n\u003cbr/\u003e\n\n### Try the model\n\nYou can utilize methods defined in the `Gemini.Chat.pas` unit and specify the name of the fine-tuned model to evaluate its performance.\n\n\u003cbr/\u003e\n\n### List tuned models\n\nThis example shows how to create a list of tuned models.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var List := Gemini.FineTune.List(20, Next, '');\n  try\n    for var Item in List.TunedModels do\n      begin\n        Display(Memo1, Item.Name + ' - ' + Item.State.ToString);\n      end;\n  finally\n    List.Free;\n  end;\n```\n\n\u003cbr/\u003e\n\n### Retrieve tuned model\n\nThis example shows how to get information about a specific TunedModel.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var TunedModelName := 'tunedModels/{code}'; //e.g. tunedModels/number-generator-model-fc2ml58m7qc8\n\n  var Retrieved := Gemini.FineTune.Retrieve(TunedModelName);\n  try\n    Display(Memo1, Retrieved.Name + ' - ' + Retrieved.BaseModel);\n  finally\n    Retrieved.Free;\n  end;\n```\n\n\u003cbr/\u003e\n\n### Update tuned model\n\nThis example shows how to update a tuned model.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var TunedModelName := 'tunedModels/{code}'; //e.g. tunedModels/number-generator-model-fc2ml58m7qc8\n\n  var TuningTask := TTuningTaskParams.Create\n    .Hyperparameters(\n       procedure (var Params : THyperparametersParams)\n       begin\n         Params.LearningRate(0.001);\n         Params.EpochCount(4);\n         Params.BatchSize(2);\n       end)\n    .TrainingData('TrainingData.csv');\n\n  var TuningDataSet := TTunedModelParams.Create\n    .DisplayName('new number generator model')\n    .Description('Update test de nouveau')\n    .BaseModel('models/gemini-1.0-pro-001')\n    .TuningTask(TuningTask);\n\n  var Updated := Gemini.FineTune.Update(TunedModelName, 'displayName,description', TuningDataSet.Detach);\n  try\n    Display(Memo1, Updated.DisplayName + ' - ' + Updated.Description);\n  finally\n    Updated.Free;\n  end;\n```\n\n\u003cbr/\u003e\n\n### Delete tuned model\n\nThis example shows how to delete a tuned model.\n\n```Pascal\n// uses Gemini, Gemini.Chat, Gemini.FineTunings;\n\n  var TunedModelName := 'tunedModels/{code}'; //e.g. tunedModels/number-generator-model-fc2ml58m7qc8\n\n  var Deleted := Gemini.FineTune.Delete(TunedModelName);\n  try\n    Display(Memo1, TunedModelName + ' - Deleted');\n  finally\n    Deleted.Free;\n  end;\n```\n\n\u003cbr/\u003e\n\n## Grounding with Google Search\n\n\u003e [!IMPORTANT]\n\u003e **Note from Google**\u003cbr/\u003e\n\u003e We're launching Grounding with Google Search! This is an initial launch. The EEA, UK, and CH regions will be supported at a later date. \u003cbr/\u003e\n\u003e Please review the updated [Gemini API Additional Terms of Service](https://ai.google.dev/gemini-api/terms), which include new feature terms and updates for clarity. \n\u003e\n\nThe Grounding with Google Search feature in the Gemini API and AI Studio can enhance the accuracy and timeliness of model responses. When this feature is enabled, the Gemini API provides more factual responses along with grounding sources (online supporting links) and [Google Search suggestions](https://ai.google.dev/gemini-api/docs/grounding?lang=rest#search-suggestions) alongside the content of the response. These search suggestions guide users to search results related to the grounded response.\n\nGrounding with Google Search supports only text-based prompts; it does not accommodate multimodal prompts, such as those combining text with images or audio. Additionally, Grounding with Google Search is available in all [languages supported](https://ai.google.dev/gemini-api/docs/models/gemini#available-languages) by Gemini models.\n\nThe following example demonstrates how to set up a model to utilize grounding through Google Search:\n\nDeclare this method for displaying.\n\u003e [!TIP]\n\u003e```Pascal\n\u003e  procedure DisplayGoogleSearch(Sender: TObject; Chat: TChat);\n\u003e  begin\n\u003e  var M := Sender as TMemo;\n\u003e  for var Item in Chat.Candidates do\n\u003e    begin\n\u003e      if Item.FinishReason = STOP then\n\u003e        begin\n\u003e          for var SubItem in Item.Content.Parts do\n\u003e            begin\n\u003e              M.Lines.Text := M.Text + sLineBreak + SubItem.Text;\n\u003e            end;\n\u003e          if Assigned(Item.GroundingMetadata) then\n\u003e            begin\n\u003e              for var Chunk in Item.GroundingMetadata.GroundingChunks do\n\u003e                begin\n\u003e                  M.Lines.Text := M.Text + sLineBreak + Chunk.Web.Title + sLineBreak;\n\u003e                  M.Lines.Text := M.Text + sLineBreak + Chunk.Web.Uri + sLineBreak;\n\u003e                end;\n\u003e              M.Lines.Text := M.Text + sLineBreak + Item.GroundingMetadata.WebSearchQueries[0];\n\u003e            end;\n\u003e        end;\n\u003e      M.Perform(WM_VSCROLL, SB_BOTTOM, 0);\n\u003e    end;\n\u003e  end;\n\u003e```\n\n\n```Pascal\n// uses Gemini, Gemini.Chat;\n\n  Gemini.Chat.AsynCreate('models/gemini-1.5-pro',\n    procedure (Params: TChatParams)\n    begin\n      Params.Contents([TPayload.Add('What is the current Google stock price?')]);\n      Params.Tools(GoogleSearch, 0.1);\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := Memo1;\n      Result.OnSuccess := DisplayGoogleSearch;\n      Result.OnError := Display;\n    end);\n```\n\n`Params.Tools(GoogleSearch, Threshold)` : **Threshold** is a floating-point number between 0 and 1, with a default value of 0.7. When the threshold is set to zero, the response is always based on Google Search grounding.\n\nFor any other threshold value, the following applies:\n- If the prediction score meets or exceeds the threshold, the response is grounded with Google Search.\n- Lower thresholds mean that more prompts will be answered using Google Search grounding.\n-If the prediction score is below the threshold, the model may still generate a response, but it won't be grounded with Google Search.\n\n\n\u003cbr/\u003e\n\n### Why is Grounding with Google Search useful\n\nRefer to the [official documentation](https://ai.google.dev/gemini-api/docs/grounding?lang=rest#why-grounding).\n\n\u003cbr/\u003e\n\n### Important note\n\n\u003e [!CAUTION]\n\u003e The provided URIs must be directly accessible by the end users and must not be queried programmatically through automated means. If automated access is detected, the grounded answer generation service might stop providing the redirection URIs.\n\u003e\n\n\u003cbr/\u003e\n\n# Methods for the Tutorial Display\n\n\u003e [!TIP]\n\u003e```Pascal\n\u003e  interface \n\u003e\n\u003e    procedure Display(Sender: TObject); overload;\n\u003e\n\u003e    procedure Display(Sender: TObject; Chat: TChat); overload;\n\u003e    procedure Display(Sender: TObject; S: string); overload;\n\u003e    procedure Display(Sender: TObject; Candidate: TChatCandidate); overload;\n\u003e    procedure Display(Sender: TObject; Embed: TEmbeddingValues); overload;\n\u003e    procedure Display(Sender: TObject; Embed: TEmbeddings); overload;\n\u003e    procedure Display(Sender: TObject; Files: TFiles); overload;\n\u003e    procedure Display(Sender: TObject; Delete: TFileDelete); overload;\n\u003e    procedure Display(Sender: TObject; Cache: TCacheContents); overload;\n\u003e\n\u003e    procedure DisplayStream(Sender: TObject; Buffer: string); overload;\n\u003e    procedure DisplayStream(Sender: TObject; Chat: TChat); overload;\n\u003e\n\u003e    procedure DisplayCode(Sender: TObject; Chat: TChat);\n\u003e\n\u003e    procedure DisplayGoogleSearch(Sender: TObject; Chat: TChat);\n\u003e...\n\u003e```\n\n\u003cbr/\u003e\n\n# Contributing\n\nPull requests are welcome. If you're planning to make a major change, please open an issue first to discuss your proposed changes.\n\n# License\n\nThis project is licensed under the [MIT](https://choosealicense.com/licenses/mit/) License.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxidonkey%2Fdelphigemini","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxidonkey%2Fdelphigemini","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxidonkey%2Fdelphigemini/lists"}