{"id":24680526,"url":"https://github.com/maxidonkey/delphideepseek","last_synced_at":"2026-01-26T20:12:44.171Z","repository":{"id":272021359,"uuid":"915293054","full_name":"MaxiDonkey/DelphiDeepseek","owner":"MaxiDonkey","description":"The Deepseek API wrapper for Delphi leverages Deepseek’s advanced models to deliver powerful capabilities for seamless and dynamic conversational interactions, including a model optimized for reasoning, and now also supports running local models through an LM Studio server.","archived":false,"fork":false,"pushed_at":"2025-11-28T19:53:09.000Z","size":596,"stargazers_count":92,"open_issues_count":1,"forks_count":32,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-11-29T10:34:26.730Z","etag":null,"topics":["api-wrapper","chat","deepseek","deepseek-chat","deepseek-coder","deepseek-reasoner","delphi","llm","lm-studio","lmstudio"],"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":"Changelog.md","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-11T13:28:27.000Z","updated_at":"2025-11-28T19:53:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"3eb87196-a2e9-4a01-9a36-2ba5068a4bc5","html_url":"https://github.com/MaxiDonkey/DelphiDeepseek","commit_stats":null,"previous_names":["maxidonkey/delphideepseek"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/MaxiDonkey/DelphiDeepseek","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiDeepseek","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiDeepseek/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiDeepseek/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiDeepseek/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MaxiDonkey","download_url":"https://codeload.github.com/MaxiDonkey/DelphiDeepseek/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MaxiDonkey%2FDelphiDeepseek/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28787206,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T13:55:28.044Z","status":"ssl_error","status_checked_at":"2026-01-26T13:55:26.068Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["api-wrapper","chat","deepseek","deepseek-chat","deepseek-coder","deepseek-reasoner","delphi","llm","lm-studio","lmstudio"],"created_at":"2025-01-26T14:13:40.563Z","updated_at":"2026-01-26T20:12:44.162Z","avatar_url":"https://github.com/MaxiDonkey.png","language":"Pascal","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Delphi Deepseek\n\n___\n![Delphi async/await supported](https://img.shields.io/badge/Delphi%20async%2Fawait-supported-blue)\n![GitHub](https://img.shields.io/badge/IDE%20Version-Delphi%2010.3/11/12-ffffba)\n[![GetIt – Available](https://img.shields.io/badge/GetIt-Available-baffc9?logo=delphi\u0026logoColor=white)](https://getitnow.embarcadero.com/genai-optimized-openai-integration-wrapper/)\n![GitHub](https://img.shields.io/badge/platform-all%20platforms-baffc9)\n[![LS Studio supported](https://img.shields.io/badge/LM%20Studio-supported-blue)](https://lmstudio.ai/)\n\n\u003cbr/\u003e\n\nNEW: \n- GetIt current version: 1.0.4\n- [Changelog](https://github.com/MaxiDonkey/DelphiDeepseek/blob/main/Changelog.md) updated on November 26, 2025\n- [Local model support via LM Studio (OpenAI-compatible server)](#run-models-locally-with-lm-studio)\n\n___\n\n- [Introduction](#introduction)\n- [Wrapper Tools Info](#wrapper-tools-info)\n    - [Tools for simplifying this tutorial](#tools-for-simplifying-this-tutorial)\n    - [Use the FMX or VCL app examples](#use-the-fmx-or-vcl-app-examples)\n    - [Simplified Unit Declaration](#simplified-unit-declaration) \n- [Usage](#usage)\n    - [Initialization](#initialization)\n    - [Run models locally with LM Studio](#run-models-locally-with-lm-studio)\n    - [Deepseek Models Overview](#deepseek-models-overview)\n    - [Chats](#chats)\n        - [Create a message](#create-a-message)\n        - [Streaming messages](#streaming-messages)\n        - [Multi-turn conversation](#multi-turn-conversation)\n        - [Deepseek-reasoner](#deepseek-reasoner)\n        - [Parallel method for generating text](#parallel-method-for-generating-text)\n        - [Multiple queries with chaining](#multiple-queries-with-chaining)\n    - [Function calling](#function-calling)\n        - [Use case](#use-case)\n    - [JSON Output](#json-output)\n    - [Context Caching](#context-caching)\n    - [Get user balance](#get-user-balance)\n- [Beta version](#beta-version)\n    - [FIM Completion](#fim-completion)\n        - [Completion](#completion)\n        - [Streamed completion](#streamed-completion)\n    - [Chat prefix completion](#chat-prefix-completion)\n- [Tips and tricks](#tips-and-tricks)\n- [Contributing](#contributing)\n- [License](#license)\n\n\u003cbr/\u003e\n\u003cbr/\u003e\n\n# Introduction\n\n\u003e **Built with Delphi 12 Community Edition** (v12.1 Patch 1)  \n\u003eThe wrapper itself is MIT-licensed.  \n\u003eYou can compile and test it free of charge with Delphi CE; any recent commercial Delphi edition works as well.\n\n\n**Deepseek for Delphi** is a powerful Delphi library that brings the latest Deepseek APIs to your desktop, mobile, and server apps.\n\n**Core capabilities**  \n- Unified access to text endpoints  \n- Supports state-of-the-art models, including ***deepseek-chat*** and the reasoning-centric *deepseek-reasoner* series  \n\n**Developer tooling**  \n- Ready-made `Sync`, `Async`, and `Await` code snippets (TutorialHUB compatible)  \n- Mock-friendly design: the HTTP layer is injected via dependency injection, so you can swap in stubs or fakes for testing  \n\nIntegrate Deepseek into Delphi—no boilerplate, just results.\n\n\u003cbr/\u003e\n\n\u003e [!IMPORTANT]\n\u003e\n\u003e This is an unofficial library. **Deepseek** does not provide any official library for `Delphi`.\n\u003e This repository contains `Delphi` implementation over [Deepseek](https://api-docs.deepseek.com/) public API.\n\n\u003cbr/\u003e\n\n# Wrapper Tools Info\n\nThis section offers concise notifications and explanations about the tools designed to streamline the presentation and clarify the wrapper's functions throughout the tutorial.\n\n\u003cbr/\u003e\n\n## Tools for simplifying this tutorial\n\n### Use the FMX or VCL app examples\n\nYou can simply use code examples provided in this tutorial, two support units have been included in the source code: `Deepseek.Tutorial.VCL` and `Deepseek.Tutorial.FMX` Based on the platform selected for testing the provided examples, you will need to initialize either the `TVCLTutorialHub` or `TFMXTutorialHub` class within the application's OnCreate event, as illustrated below:\n\n\u003e[!IMPORTANT]\n\u003eIn this repository, you will find in the [`sample`](https://github.com/MaxiDonkey/DelphiDeepseek/tree/main/sample) folder two ***ZIP archives***, each containing a template to easily test all the code examples provided in this tutorial. \n\u003eExtract the `VCL` or `FMX` version depending on your target platform for testing. \n\u003eNext, add the path to the Deepseek library in your project’s options, then copy and paste the code examples for immediate execution. \n\u003e\n\u003eThese two archives have been designed to fully leverage the TutorialHub middleware and enable rapid upskilling with Deepseek.\n\n- [**`VCL`**](https://github.com/MaxiDonkey/DelphiDeepseek/tree/main/sample) support with TutorialHUB: ***TTestDeepseek_VCL.zip***\n\n- [**`FMX`**](https://github.com/MaxiDonkey/DelphiDeepseek/tree/main/sample) support with TutorialHUB: ***TestDeepseek_FMX.zip***\n\n\u003cbr/\u003e\n\n## Simplified Unit Declaration\n\nTo streamline the use of the API wrapper, the process for declaring units has been simplified. Regardless of the methods being utilized, you only need to reference the following two core units:\n\n```Pascal\n  uses\n    Deepseek, Deepseek.Types;\n```\n\nIf required, you may also include the `Deepseek.Schema` unit or any plugin units developed for specific function calls (e.g., `Deepseek.Functions.Example`). This simplification ensures a more intuitive and efficient integration process for developers.\n\n\u003cbr/\u003e\n\n# Usage\n\n## Initialization\n\nTo initialize the API instance, you need to [obtain an API key from Deepseek](https://platform.deepseek.com/api_keys).\n\nOnce you have a token, you can initialize `IDeepseek` interface, which is an entry point to the API.\n\n\n\u003e [!NOTE]\n\u003e```Pascal\n\u003euses Deepseek;\n\u003e\n\u003e// Cloud clients\n\u003evar Deepseek     := TDeepseekFactory.CreateInstance(API_KEY);\n\u003evar DeepseekBeta := TDeepseekFactory.CreateBetaInstance(API_KEY);\n\u003e\n\u003e// Local client (LM Studio – OpenAI compatible server)\n\u003evar DeepseekLMS  := TDeepseekFactory.CreateLMSInstance;  // default: http://127.0.0.1:1234/v1\n\u003e// or:\n\u003e// var DeepseekLMS := TDeepseekFactory.CreateLMSInstance('http://192.168.1.10:1234');\n\u003e```\n\nThe DeepseekBeta client must be used to access APIs that are currently provided in beta version.\n\n\u003e[!Warning]\n\u003e To effectively use the examples in this tutorial, particularly when working with asynchronous methods, it is recommended to define the Deepseek and DeepseekBeta interfaces with the broadest possible scope. For optimal implementation, these clients should be declared in the application's OnCreate method.\n\n\u003cbr/\u003e\n\n## Run models locally with LM Studio\n\n### Using non-DeepSeek models in LM Studio\n\n- Download LM Studio: https://lmstudio.ai/\n\n- This section assumes you are already familiar with LM Studio (loading models, starting the local OpenAI server, selecting the port, etc.).\n\n\u003cbr\u003e\n\nThe LM Studio backend exposes a fully OpenAI-compatible HTTP server.  \nBecause the Delphi Deepseek wrapper forwards raw OpenAI-format requests to the server, **you can load and run any model supported by LM Studio**, even if it does not belong to the DeepSeek ecosystem.\n\nExamples of models you can use transparently:\n\n- **openai/gpt-oss-20b** (OpenAI)\n- **mistralai/mistral-7b-instruct-v0.3** (Mistral AI)\n- **NousResearch, Qwen, Falcon, Llama, Gemma**, etc.\n\nAll these models work seamlessly with:\n\n- `Chat` (sync, async, streaming, promises)  \n- `FIM` (if the model supports it)  \n- `Parallel prompts`  \n- `Tools / function calling` (if the model supports it)\n\nYou simply need to set:\n```pascal\nParams.Model('model-name-as-exposed-by-LM-Studio');\n```\n\n\u003e[!NOTE]\n\u003eLM Studio may rename models when exposing them via the OpenAI server.\n\u003eUse the LM Studio UI → OpenAI Server panel to check the exact model identifier.\n\n\u003cbr\u003e\n\n### Embedding models not supported\n\nThis wrapper intentionally does not include an Embeddings API, because:\n\nDeepSeek does not provide embedding endpoints in its official REST API.\n\nThe LM Studio server exposes embeddings only for models designed for that purpose, but supporting an embeddings client API here would create an inconsistent mismatch between the remote and the local DeepSeek feature set.\n\nTherefore:\n\n- **Local embeddings via LM Studio = NOT supported.**\n- **Cloud embeddings via Deepseek = NOT available.**\n\nThis guarantees that the wrapper remains a strict, coherent implementation of DeepSeek’s documented API surface, while still allowing LM Studio for local LLM inference.\n\n\u003cbr\u003e\n\n### Local chat example (non-streaming)\n \n```pascal\n  TutorialHub.Clear;\n  DeepseekLMS.ClientHttp.ResponseTimeout := 120000;\n\n  //Asynchronous promise example\n  Start(TutorialHub);\n  var Promise := DeepseekLMS.Chat.AsyncAwaitCreate(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek/deepseek-r1-0528-qwen3-8b');\n      Params.Messages([\n        FromUser('What is the capital of France, and then the capital of champagne?')\n      ]);\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end);\n\n  Promise\n    .\u0026Then\u003cTChat\u003e(\n      function (Value: TChat): TChat\n      begin\n        Result := Value;\n        Display(TutorialHub, Value);\n      end)\n    .\u0026Catch(\n      procedure (E: Exception)\n      begin\n        Display(TutorialHub, E.Message);\n      end);\n```\n\n\u003cbr\u003e\n\n### Local streaming example\n\n```pascal\n  TutorialHub.Clear;\n\n  //Asynchronous promise example\n  var Promise := DeepseekLMS.Chat.AsyncAwaitCreateStream(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek/deepseek-r1-0528-qwen3-8b');\n      Params.Messages([\n        FromUser('Does art belong to the artist or to his audience?')\n      ]);\n      Params.Stream;\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TPromiseChatStream\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnProgress :=\n        procedure (Sender: TObject; Chunk: TChat)\n        begin\n          DisplayStream(Sender, Chunk);\n        end;\n    end);\n\n  promise\n    .\u0026Then\u003cTPromiseBuffer\u003e(\n      function (Value: TPromiseBuffer): TPromiseBuffer\n      begin\n        Result := Value;\n        ShowMessage(Value.Content);\n      end)\n    .\u0026Catch(\n      procedure (E: Exception)\n      begin\n        Display(TutorialHub, E.Message);\n      end);\n```\n\n\u003cbr\u003e\n\n## Deepseek Models Overview\n\nTwo models are currently available:\n- [deepseek-chat](https://huggingface.co/deepseek-ai/deepseek-llm-67b-chat) \n- [deepseek-coder](https://deepseekcoder.github.io/). also available on [HuggingFace](https://huggingface.co/deepseek-ai) \n\nRegarding the APIs, only version 3 appears to be available, although the documentation lacks clarity on this point.\n\nTo retrieve the list of available models, you can use the following code example:\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeek.Models.AsynList(\n    function : TAsynModels\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n\n  //Synchronous example\n//  var Value := DeepSeek.Models.List;\n//  try\n//    Display(TutorialHub, Value);\n//  finally\n//    Value.Free;\n//  end;\n```\n\n\u003cbr/\u003e\n\n## Chats\n\nYou can send a structured list of input messages containing only text content, and the model will generate the next message in the conversation.\n\nThe Messages API can be used for both single-turn requests and multi-turn, stateless conversations.\n\n### Create a message\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n  Deepseek.ClientHttp.ResponseTimeout := 120000;\n\n  //Asynchronous example\n  DeepSeek.Chat.AsynCreate(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Messages([\n        FromUser('What is the capital of France, and then the capital of champagne?')\n      ]);\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n\n  //Synchronous example\n//  var Value := DeepSeek.Chat.Create(\n//    procedure (Params: TChatParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Messages([\n//        FromUser('What is the capital of France, and then the capital of champagne?')\n//      ]);\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end);\n//  try\n//    Display(TutorialHub, Value);\n//  finally\n//    Value.Free;\n//  end;\n\n  //Asynchronous promise example\n//  Start(TutorialHub);\n//  var Promise := Deepseek.Chat.AsyncAwaitCreate(\n//    procedure (Params: TChatParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Messages([\n//        FromUser('What is the capital of France, and then the capital of champagne?')\n//      ]);\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end);\n//\n//  Promise\n//    .\u0026Then\u003cTChat\u003e(\n//      function (Value: TChat): TChat\n//      begin\n//        Result := Value;\n//        Display(TutorialHub, Value);\n//      end)\n//    .\u0026Catch(\n//      procedure (E: Exception)\n//      begin\n//        Display(TutorialHub, E.Message);\n//      end);\n```\n\n\u003cbr/\u003e\n\n### Streaming messages\n\nWhen generating a Message, you can enable `\"stream\": true` to progressively receive the response through server-sent events (SSE).\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n  \n  //Asynchronous example\n  DeepSeek.Chat.ASynCreateStream(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Messages([\n        FromUser('Are there accumulation points in a discrete topology?')\n      ]);\n      Params.MaxTokens(1024);\n      Params.Stream;\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynChatStream\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnProgress := DisplayStream;\n      Result.OnError := Display;\n      Result.OnDoCancel := DoCancellation;\n      Result.OnCancellation := Cancellation;\n    end);\n\n  //Synchronous example\n//  DeepSeek.Chat.CreateStream(\n//    procedure (Params: TChatParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Messages([\n//        FromUser('Are there accumulation points in a discrete topology?')\n//      ]);\n//      Params.MaxTokens(1024);\n//      Params.Stream;\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end,\n//    procedure (var Chat: TChat; IsDone: Boolean; var Cancel: Boolean)\n//    begin\n//      if Assigned(Chat) and not IsDone then\n//        DisplayStream(TutorialHub, Chat);\n//    end);\n\n  //Asynchronous promise example\n//  var Promise := Deepseek.Chat.AsyncAwaitCreateStream(\n//    procedure (Params: TChatParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Messages([\n//        FromUser('Are there accumulation points in a discrete topology?')\n//      ]);\n//      Params.Stream;\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end,\n//    function : TPromiseChatStream\n//    begin\n//      Result.Sender := TutorialHub;\n//      Result.OnProgress :=\n//        procedure (Sender: TObject; Chunk: TChat)\n//        begin\n//          DisplayStream(Sender, Chunk);\n//        end;\n//    end);\n//\n//  promise\n//    .\u0026Then\u003cTPromiseBuffer\u003e(\n//      function (Value: TPromiseBuffer): TPromiseBuffer\n//      begin\n//        Result := Value;\n//        ShowMessage(Value.Content);\n//      end)\n//    .\u0026Catch(\n//      procedure (E: Exception)\n//      begin\n//        Display(TutorialHub, E.Message);\n//      end);\n```\n\n\u003cbr/\u003e\n\n### Multi-turn conversation\n\nThe `Deepseek API` enables the creation of interactive chat experiences tailored to your users' needs. Its chat functionality supports multiple rounds of questions and answers, allowing users to gradually work toward solutions or receive help with complex, multi-step issues. This capability is especially useful for applications requiring ongoing interaction, such as:\n- **Chatbots**\n- **Educational tools**\n- **Customer support assistants.**\n\nRefer to the [official documentation](https://api-docs.deepseek.com/guides/multi_round_chat)\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeek.Chat.ASynCreateStream(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Messages([\n        FromSystem('You are a funny domestic assistant.'),\n        FromUser('Hello'),\n        FromAssistant('Great to meet you. What would you like to know?'),\n        FromUser('I have two dogs in my house. How many paws are in my house?')\n      ]);\n      Params.MaxTokens(1024);\n      Params.Stream;\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynChatStream\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnProgress := DisplayStream;\n      Result.OnError := Display;\n      Result.OnDoCancel := DoCancellation;\n      Result.OnCancellation := Cancellation;\n    end);\n\n  //Synchronous example\n//  DeepSeek.Chat.CreateStream(\n//    procedure (Params: TChatParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Messages([\n//        FromSystem('You are a funny domestic assistant.'),\n//        FromUser('Hello'),\n//        FromAssistant('Great to meet you. What would you like to know?'),\n//        FromUser('I have two dogs in my house. How many paws are in my house?')\n//      ]);\n//      Params.MaxTokens(1024);\n//      Params.Stream;\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end,\n//    procedure (var Chat: TChat; IsDone: Boolean; var Cancel: Boolean)\n//    begin\n//      if Assigned(Chat) and not IsDone then\n//        DisplayStream(TutorialHub, Chat);\n//    end);\n\n  //Asynchronous promise example\n//  var Promise := Deepseek.Chat.AsyncAwaitCreateStream(\n//      Params.Model('deepseek-chat');\n//      Params.Messages([\n//        FromSystem('You are a funny domestic assistant.'),\n//        FromUser('Hello'),\n//        FromAssistant('Great to meet you. What would you like to know?'),\n//        FromUser('I have two dogs in my house. How many paws are in my house?')\n//      ]);\n//      Params.MaxTokens(1024);\n//      Params.Stream;\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    function : TPromiseChatStream\n//    begin\n//      Result.Sender := TutorialHub;\n//      Result.OnProgress :=\n//        procedure (Sender: TObject; Chunk: TChat)\n//        begin\n//          DisplayStream(Sender, Chunk);\n//        end;\n//    end);\n//\n//  promise\n//    .\u0026Then\u003cTPromiseBuffer\u003e(\n//      function (Value: TPromiseBuffer): TPromiseBuffer\n//      begin\n//        Result := Value;\n//        ShowMessage(Value.Content);\n//      end)\n//    .\u0026Catch(\n//      procedure (E: Exception)\n//      begin\n//        Display(TutorialHub, E.Message);\n//      end);\n```\n\n\u003cbr/\u003e\n\n### Deepseek-reasoner\n\nSince January 25, 2025, Deepseek has released a new model called `deepseek-reasoner`, designed to provide advanced reasoning capabilities similar to `OpenAI's O1` model.\n\nPlease refer to the [dedicated page](https://api-docs.deepseek.com/guides/reasoning_model) on the official website.\n\n\u003e[!WARNING]\n\u003e**Important Note:** This model does not support *function calls, JSON-formatted outputs, or the fill-in-the-middle (FIM) method*.\n\u003e The parameter to control the CoT length (reasoning_effort) will be available soon.\n\n**Unsupported parameters:**\n- *temperature, top_p, presence_penalty, frequency_penalty, logprobs, top_logprobs.*\n\nTo ensure compatibility with existing software, using *temperature, top_p, presence_penalty, and frequency_penalty* will not trigger an error but will have no effect on the model. However, using logprobs and top_logprobs will result in an error.\n\n\u003e[!TIP]\n\u003e This model is accessible through the APIs available in this wrapper. However, due to the processing time required for its reasoning methods, it is recommended to use asynchronous approaches to prevent potential application blocking.\n\u003e\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeek.Chat.ASynCreateStream(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-reasoner');\n      Params.Messages([\n        FromUser('What does the ability to reason bring to language models?')\n      ]);\n      Params.Stream;\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynChatStream\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnProgress := DisplayStream;\n      Result.OnError := Display;\n      Result.OnDoCancel := DoCancellation;\n      Result.OnCancellation := Cancellation;\n    end);\n\n  //Asynchronous promise example\n//  var Promise := Deepseek.Chat.AsyncAwaitCreateStream(\n//    procedure (Params: TChatParams)\n//    begin\n//      Params.Model('deepseek-reasoner');\n//      Params.Messages([\n//        FromUser('Does art belong to the artist or to his audience?')\n//      ]);\n//      Params.Stream;\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end,\n//    function : TPromiseChatStream\n//    begin\n//      Result.Sender := TutorialHub;\n//      Result.OnProgress :=\n//        procedure (Sender: TObject; Chunk: TChat)\n//        begin\n//          DisplayStream(Sender, Chunk);\n//        end;\n//    end);\n//\n//  promise\n//    .\u0026Then\u003cTPromiseBuffer\u003e(\n//      function (Value: TPromiseBuffer): TPromiseBuffer\n//      begin\n//        Result := Value;\n//        ShowMessage(Value.Content);\n//      end)\n//    .\u0026Catch(\n//      procedure (E: Exception)\n//      begin\n//        Display(TutorialHub, E.Message);\n//      end);\n```\n\nIn the sample code provided with the DisplayStream method, you can see how to handle the reasoning portion separately from the final response generation:\n\n```Delphi\nprocedure DisplayStream(Sender: TObject; Value: TChat);\nbegin\n  if Assigned(Value) then\n    begin\n      DisplayChunk(Value);\n      if not Value.Choices[0].Delta.ReasoningContent.IsEmpty then\n        {--- Display reasoning chunk }\n        DisplayStream(TutorialHub.Reasoning, Value.Choices[0].Delta.ReasoningContent)\n      else\n        {--- Display responses chunk }\n        DisplayStream(Sender, Value.Choices[0].Delta.Content.Replace('\\n', #10));\n    end;\nend;  \n```\n\n\n![Preview](/../main/images/ReasoningStream.png?raw=true \"Preview\")\n\n\n\u003cbr/\u003e\n\n### Parallel method for generating text\n\nThis approach enables the simultaneous execution of multiple prompts, provided they are all processed by the same model.\n\n#### Example 1 : Two prompts processed in parallel.\n\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  DeepSeek.Chat.CreateParallel(\n    procedure (Params: TBundleParams)\n    begin\n      Params.Prompts([\n        'How many television channels were there in France in 1980?',\n        'How many TV channels were there in Germany in 1980?.'\n      ]);\n      Params.System('Write the response in capital letters.');\n      Params.Model('deepseek-chat');\n    end,\n    function : TAsynBundleList\n    begin\n      Result.Sender := TutorialHub;\n\n      Result.OnStart :=\n        procedure (Sender: TObject)\n        begin\n          Display(Sender, 'Start the job' + sLineBreak);\n        end;\n\n      Result.OnSuccess :=\n        procedure (Sender: TObject; Bundle: TBundleList)\n        begin\n          // Background bundle processing\n          for var Item in Bundle.Items do\n            begin\n              Display(Sender, 'Index : ' + Item.Index.ToString);\n              Display(Sender, 'FinishIndex : ' + Item.FinishIndex.ToString);\n              Display(Sender, Item.Prompt + sLineBreak);\n              Display(Sender, Item.Response + sLineBreak + sLineBreak);\n              // or Display(Sender, TChat(Item.Chat).Choices[0].Message.Content);\n            end;\n        end;\n\n      Result.OnError := Display;\n    end)\n\n  //Asynchronous promise example\n//  Start(TutorialHub);\n//  var Promise := DeepSeek.Chat.AsyncAwaitParallel(\n//    procedure (Params: TBundleParams)\n//    begin\n//      Params.Prompts([\n//        'How many television channels were there in France in 1980?',\n//        'How many TV channels were there in Germany in 1980?.'\n//      ]);\n//      Params.System('Write the response in capital letters.');\n//      Params.Model('deepseek-chat');\n//    end);\n//\n//  Promise\n//    .\u0026Then\u003cTBundleList\u003e(\n//      function (Value: TBundleList): TBundleList\n//      begin\n//        for var Item in Value.Items do\n//        begin\n//          Display(TutorialHub, TChat(Item.Chat).Choices[0].Message.Content);\n//        end;\n//      end)\n//    .\u0026Catch(\n//      procedure (E: Exception)\n//      begin\n//        Display(TutorialHub, E.Message);\n//      end);\n```\n\nResult\n\n![Preview](/../main/images/Parallel.png?raw=true \"Preview\")\n\n\u003cbr\u003e\n\n### Multiple queries with chaining\n\nIn some cases, you need to chain multiple requests so that each step’s output feeds into the next. The Promise pattern is ideal for orchestrating this kind of workflow: it lets you build complex processing that a single prompt—no matter how sophisticated—couldn’t achieve on its own.\n \n**Implementation:** \u003cbr\u003e\n- Be sure to include the `Deepseek.Async.Promise` unit in your `uses` clause.\n- Each Promise runs asynchronously and non-blockingly in the background, freeing the main thread for other operations.\n\n#### Process\n\nWe’ll use a simple, educational scenario with three steps:\n\n 1. Send a prompt to the deepseek-chat model.\n\n 2. Process the received response to extract and reformat the relevant information.\n\n 3. Generate the next prompt from the enriched result.\n\nThis minimal example is designed to help you get comfortable with asynchronous execution and promise chaining. You can then customize each step to suit your specific business needs.\n\n\u003cbr\u003e\n\n#### We will use the following 3 prompts\n\n```Delphi\nconst\n  Step1 =\n    '# Do not answer the question directly.'#10 +\n    '# Consider possible lines of thought'#10 +\n    '# Break the main problem down into subproblems.'#10 +\n    '## For each subproblem: Develop a strategy to address that point.'#10 +\n    '## For each subproblem: Evaluate and then critique the strategy established.'#10 +\n    '## For each subproblem: Assess the relevance and effectiveness of the strategy.'#10 +\n    '# Formatting'#10 +\n    '## – Use everyday language to explain the reasoning.'#10 +\n    '## – Avoid lists and markdown formatting.'#10 +\n    '## – Write as if you were explaining to a third party.';\n\n  Step2 =\n    '# Build an effective outline to answer the question based on the analysis.'#10 +\n    '## Do not go into detail on each point of the outline but rather discuss its relevance.'#10 +\n    '## Identify the points that should be addressed in the thesis.'#10 +\n    '## Identify the points that should be addressed in the antithesis.'#10 +\n    '## Identify the points that should be addressed in the synthesis.'#10 +\n    '## Determine the points to cover for a powerful introduction.'#10 +\n    '## Determine the points to cover for a memorable conclusion.'#10 +\n    '# Formatting'#10 +\n    '## – Use everyday language to explain the reasoning.'#10 +\n    '## – Avoid lists and markdown formatting.'#10 +\n    '## – Write as if you were explaining to a third party.’';\n\n  Step3 =\n    '# Answer the following question in a teaching style'#10 +\n    '## Use all the information provided in the system section.';\n```\n\n\u003cbr\u003e\n\n#### The code enabling chaining using the promise pattern\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL, Deepseek.Async.Promise;\n\nvar\n  Analysis: string;\nbegin\n  TutorialHub.Clear;\n\n  var Request := 'Does personal data belong to the individuals who generate it or to the platforms that collect it?';\n  var System := Step1;\n\n  TutorialHub.PromiseStep('Reasoning'#10, Request, System)\n    .\u0026Then\u003cstring\u003e(\n      function(Value: string): string\n      begin\n        Analysis := Value;\n        Result := 'Request : '#10 + Request + #10 + 'Analysis : ' + Analysis;\n        System := Step2;\n      end)\n    .\u0026Then(\n      function (Value: string): TPromise\u003cstring\u003e\n      begin\n        Result := TutorialHub.PromiseStep(#10#10'Develop a plan'#10, Value, System);\n      end)\n    .\u0026Then\u003cstring\u003e(\n      function(Value: string): string\n      begin\n        Result := Request + #10 + Step3 + #10 + Request;\n        System := Analysis + #10 + Value;\n      end)\n    .\u0026Then(\n      function (Value: string): TPromise\u003cstring\u003e\n      begin\n        Result := TutorialHub.PromiseStep(#10#10'Response'#10, Value, System);\n      end)\n    .\u0026Catch(\n      procedure(E: Exception)\n      begin\n        Display(Memo1, 'Error : ' + E.Message);\n      end);\nend;\n```\n\nThis code answers the question provided in the `Request` variable by using two intermediate steps. We will now review the body of the Promise used at each stage.\n\n![Preview](/../main/images/Promise.png?raw=true \"Preview\")\n\n\u003e[!NOTE]\n\u003eThe corresponding code is available in the `Deepseek.Tutorial.VCL` and `Deepseek.Tutorial.FMX` units, depending on the platform on which you are running the test.\n\n```Pascal\nfunction TFMXTutorialHub.PromiseStep(const StepName, Prompt,\n  System: string): TPromise\u003cstring\u003e;\nvar\n  Buffer: string;\nbegin\n  Result := TPromise\u003cstring\u003e.Create(\n    procedure(Resolve: TProc\u003cstring\u003e; Reject: TProc\u003cException\u003e)\n    begin\n      Client.Chat.AsynCreateStream(\n        procedure (Params: TChatParams)\n        begin\n          Params.Model('deepseek-chat');\n          Params.Messages([\n            FromSystem(system),\n            FromUser(Prompt)\n          ]);\n          Params.Stream;\n        end,\n        function : TAsynChatStream\n        begin\n          Result.Sender := TutorialHub;\n\n          Result.OnStart :=\n            procedure (Sender: TObject)\n            begin\n              Display(Sender, StepName + #10);\n            end;\n\n          Result.OnProgress :=\n            procedure (Sender: TObject; Chat: TChat)\n            begin\n              DisplayStream(Sender, Chat);\n              Buffer := Buffer + Chat.Choices[0].Delta.Content;\n            end;\n\n          Result.OnSuccess :=\n            procedure (Sender: TObject)\n            begin\n              Resolve(Buffer); //The promise is resolved --\u003e \u0026Then\u003cstring\u003e\n            end;\n\n          Result.OnError :=\n            procedure (Sender: TObject; Error: string)\n            begin\n              Reject(Exception.Create(Error));  //The promise is rejected --\u003e \u0026Catch\n            end;\n\n          Result.OnDoCancel := DoCancellation;\n\n          Result.OnCancellation :=\n            procedure (Sender: TObject)\n            begin\n              Reject(Exception.Create('Aborted'));  //The promise is rejected --\u003e \u0026Catch\n            end;\n\n        end);\n    end);\nend;\n \n```\n\n\u003cbr\u003e\n\n#### Note\n\nThis approach proves to be particularly powerful for handling asynchronous mechanisms. However, when a process involves a large number of steps, the resulting code can quickly become difficult to maintain, leading to what is commonly referred to as a \"pyramid of doom.\"\n\nTo avoid this, it is recommended to adopt a Pipeline mechanism, which organizes and chains the steps in a clear, streamlined, and structured way.\n\n[An example implementation](https://github.com/MaxiDonkey/SynkFlowAI) based on the [GenAI wrapper for OpenAI](https://github.com/MaxiDonkey/DelphiGenAI) is available. With a few minor adjustments, it can also be used with Deepseek, except for the web search functionality.\n\n\u003cbr\u003e\n\n## Function calling\n\n\u003e[!CAUTION]\n\u003e Note from DeepSeek in their [official documentation](https://api-docs.deepseek.com/guides/function_calling)\n\u003e *\"The current version of the deepseek-chat model's Function Calling capabilitity is unstable, which may result in looped calls or empty responses. We are actively working on a fix, and it is expected to be resolved in the next version.\"*\n\nFurthermore, function calls cannot be made in the context of a streaming request. Regarding the APIs, `Delta` does not support the `tool_calls object`.\n\n\u003cbr/\u003e\n\n### Use case\n\n**What’s the weather in Paris?**\n\nIn the `Deepseek.Functions.Example` unit, there is a class that defines a function which `Deepseek` can choose to use or not, depending on the options provided. This class inherits from a parent class defined in the `Deepseek.Functions.Core` unit. To create new functions, you can derive from the `TFunctionCore class` and define a new plugin.\n\nIn this unit, this schema will be used for function calls.\n\n```Json\n{\n    \"type\": \"object\",\n    \"properties\": {\n         \"location\": {\n             \"type\": \"string\",\n             \"description\": \"The city and department, e.g. Marseille, 13\"\n         },\n         \"unit\": {\n             \"type\": \"string\",\n             \"enum\": [\"celsius\", \"fahrenheit\"]\n         }\n     },\n     \"required\": [\"location\"]\n  }\n```\n\n\u003cbr/\u003e\n\n1. We will use the TWeatherReportFunction plugin defined in the [`Deepseek.Functions.Example`](https://github.com/MaxiDonkey/DelphiDeepseek/blob/main/source/Deepseek.Functions.Example.pas) unit.\n\n```Pascal\n  var Weather := TWeatherReportFunction.CreateInstance;\n  //See step 3\n```\n\n\u003cbr/\u003e\n\n2. We then define a method to display the **result** of the query using the **Weather tool**.\n\n```Pascal\nprocedure TMy_Form.DisplayWeather(const Value: string);\nbegin\n  //Asynchronous example\n  DeepSeek.Chat.ASynCreateStream(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Messages([\n        FromSystem('You are a star weather presenter on a national TV channel.'),\n        FromUser(Value)\n      ]);\n      Params.Stream;\n    end,\n    function : TAsynChatStream\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnProgress := DisplayStream;\n      Result.OnError := Display;\n      Result.OnDoCancel := DoCancellation;\n      Result.OnCancellation := Cancellation;\n    end);\nend;\n```\n\n\u003cbr/\u003e\n\n3. Building the query using the Weather tool\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Functions.Example, Deepseek.Tutorial.VCL;\n  \n  TutorialHub.Clear;\n  var Weather := TWeatherReportFunction.CreateInstance;\n  TutorialHub.Tool := Weather;\n  TutorialHub.ToolCall := DisplayWeather;\n\n  //Asynchronous example\n  DeepSeek.Chat.AsynCreate(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Messages([\n        TContentParams.User('What is the weather in Paris?')\n      ]);\n      Params.Tools([Weather]);\n      Params.ToolChoice(auto);\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnSuccess := Display;\n      Result.OnError\n  end;\n```\n\n\u003cbr/\u003e\n\n## JSON Output\n\nIn many scenarios, users require the model to produce output in strictly JSON format to ensure structured data, facilitating seamless downstream processing.\n\nDeepSeek provides a JSON Output feature to guarantee the generation of valid JSON strings.\n\n**Key Considerations:**\n1. **Enabling JSON Output:**\n     - Set the response_format parameter to `{'type': 'json_object'}`.\n     - Include the word \"json\" in the system or user prompt, and provide an example of the desired JSON format to guide the model in producing compliant outputs.\n\n2. **Adjusting Output Length:**\n     - Configure the max_tokens parameter appropriately to prevent the JSON string from being truncated.\n\n3. **Handling Potential Issues:**\n     - The API may occasionally return empty content. This issue is under active optimization. Adjusting the prompt can help mitigate such occurrences.\n\nRefer to [official documentation](https://api-docs.deepseek.com/guides/json_mode)\n\n\u003cbr/\u003e\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeek.Chat.AsynCreate(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Messages([\n        TContentParams.System('The user will provide some exam text. Please parse the \"question\" and \"answer\" and output them in JSON format. EXAMPLE INPUT: Which is the highest mountain in the world? Mount Everest. EXAMPLE JSON OUTPUT: {     \"question\": \"Which is the highest mountain in the world?\",     \"answer\": \"Mount Everest\" }'),\n        TContentParams.User('Which is the longest river in the world? The Nile River')\n      ]);\n      Params.ResponseFormat(TResponseFormat.json_object);\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n\n  //Synchronous example\n//  var Value := DeepSeek.Chat.Create(\n//    procedure (Params: TChatParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Messages([\n//        TContentParams.System('The user will provide some exam text. Please parse the \"question\" and \"answer\" and output them in JSON format. EXAMPLE INPUT: Which is the highest mountain in the world? Mount Everest. EXAMPLE JSON OUTPUT: {     \"question\": \"Which is the highest mountain in the world?\",     \"answer\": \"Mount Everest\" }'),\n//        TContentParams.User('Which is the longest river in the world? The Nile River')\n//      ]);\n//      Params.ResponseFormat(TResponseFormat.json_object);\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end);\n//  try\n//    Display(TutorialHub, Value);\n//  finally\n//    Value.Free;\n//  end;\n```\n\nThe model will output:\n\n```Json\n{\n    \"question\": \"Which is the longest river in the world?\",\n    \"answer\": \"The Nile River\"\n}  \n```\n\n\u003cbr/\u003e\n\n## Context Caching\n\nRefer to the [official documentation](https://api-docs.deepseek.com/guides/kv_cache)\n\nThe automatic enforcement of caching has the effect of limiting the diversity of generated responses. While adjusting the temperature parameter can provide some flexibility, it is not an optimal solution in all cases.\n\nAdditionally, users are unable to directly intervene to perform a manual \"cache clearing.\" In this regard, I refer you to the official documentation, which states: \n\n- *\"Cache construction takes seconds. Once the cache is no longer in use, it will be automatically cleared, usually within a few hours to a **`few days`**..\"*\n\n\u003cbr/\u003e\n\n## Get user balance\n\nView account details, including available credit balance.\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeek.User.AsynBalance(\n    function : TAsynBalance\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n\n  //Synchronous example\n//  var Value := DeepSeek.User.Balance;\n//  try\n//    Display(TutorialHub, Value);\n//  finally\n//    Value.Free;\n//  end;\n```\n\n\u003cbr/\u003e\n\n# Beta version\n\n## FIM Completion\n\nIn Fill-In-the-Middle (FIM) completion, users can specify a prefix and optionally a suffix, allowing the model to generate content that seamlessly fills the gap between them. This approach is particularly useful for tasks such as content and code completion.\n\n**Important Notes:**\n- Token Limit: FIM completion supports a maximum token limit of 4,000.\n- Enabling the Beta Feature: Users must set base_url=https://api.deepseek.com/beta to activate this functionality.\n\n\u003e[!TIP]\n\u003e In this case, we will use the [DeepseekBeta](#initialization) client in our code examples.\n\n\u003cbr/\u003e\n\n### Completion\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeekBeta.FIM.AsynCreate(\n    procedure (Params: TFIMParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Prompt('def fib(a):');\n      Params.Suffix('    return fib(a-1) + fib(a-2)');\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynFIM\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n\n  //Synchronous example\n//  var Value := DeepSeekBeta.FIM.Create(\n//    procedure (Params: TFIMParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Prompt('def fib(a):');\n//      Params.Suffix('    return fib(a-1) + fib(a-2)');\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end);\n//  try\n//    Display(TutorialHub, Value);\n//  finally\n//    Value.Free;\n//  end;\n```\n\u003cbr/\u003e\n\nThe model will output:\n\n``` \n    if a == 0:\n        return 0\n    elif a == 1:\n        return 1\n    else:  \n```\n\n\u003cbr/\u003e\n\n### Streamed completion\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeekBeta.FIM.AsynCreateStream(\n    procedure (Params: TFIMParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Prompt('def fib(a):');\n      Params.Suffix('  return fib(a-1) + fib(a-2)');\n      Params.Stream;\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynFIMStream\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnProgress := DisplayStream;\n      Result.OnError := Display;\n      Result.OnDoCancel := DoCancellation;\n      Result.OnCancellation := Cancellation;\n    end);\n\n  //Synchronous example\n//  DeepSeekBeta.FIM.CreateStream(\n//    procedure (Params: TFIMParams)\n//    begin\n//      Params.Model('deepseek-chat');\n//      Params.Prompt('def fib(a):');\n//      Params.Suffix('  return fib(a-1) + fib(a-2)');\n//      Params.Stream;\n//      TutorialHub.JSONRequest := Params.ToFormat();\n//    end,\n//    procedure (var FIM: TFIM; IsDone: Boolean; var Cancel: Boolean)\n//    begin\n//      if Assigned(FIM) and not IsDone then\n//        DisplayStream(TutorialHub, FIM);\n//    end);\n```\n\n## Chat prefix completion\n\nTo utilize the chat prefix completion feature, users must provide a message prefix for the assistant, allowing the model to complete the rest of the message.\n\n**Important Note**\nWhen using prefix completion, it is essential to ensure that the role of the last message in the message list is set to \"assistant\" and that the `prefix` parameter for this message is enabled (set to `True`). Additionally, users must configure `base_url=\"https://api.deepseek.com/beta\"` to activate the Beta feature.\n\n\u003e[!TIP]\n\u003e In this case, we will use the [DeepseekBeta](#initialization) client in our code examples.\n\n```Pascal\n// uses Deepseek, Deepseek.Types, Deepseek.Tutorial.VCL;\n\n  TutorialHub.Clear;\n\n  //Asynchronous example\n  DeepSeekBeta.Chat.AsynCreate(\n    procedure (Params: TChatParams)\n    begin\n      Params.Model('deepseek-chat');\n      Params.Messages([\n        FromUser('Please write quick sort code'),\n        FromAssistant('```python\\n', True)\n      ]);\n      Params.Stop('```');\n      TutorialHub.JSONRequest := Params.ToFormat();\n    end,\n    function : TAsynChat\n    begin\n      Result.Sender := TutorialHub;\n      Result.OnStart := Start;\n      Result.OnSuccess := Display;\n      Result.OnError := Display;\n    end);\n```\n\nThe model will output:\n\n```Python\n# Quick Sort implementation in Python\n\ndef quick_sort(arr):\n    if len(arr) \u003c= 1:\n        return arr\n    pivot = arr[len(arr) // 2]\n    left = [x for x in arr if x \u003c pivot]\n    middle = [x for x in arr if x == pivot]\n    right = [x for x in arr if x \u003e pivot]\n    return quick_sort(left) + middle + quick_sort(right)\n\n# Example usage:\narr = [3, 6, 8, 10, 1, 2, 1]\nsorted_arr = quick_sort(arr)\nprint(\"Sorted array:\", sorted_arr)\n```\n\n\u003cbr\u003e\n\n# Tips and tricks\n\n## How to prevent an error when closing an application while requests are still in progress?\n\nStarting from version 1.0.2 of Deepseek, the Deepseek.Monitoring unit is responsible for monitoring ongoing HTTP requests.\n\nThe Monitoring interface is accessible by including the Deepseek.Monitoring unit in the uses clause.\nAlternatively, you can access it via the HttpMonitoring function, declared in the Deepseek unit.\n\n### Usage example\n\n```Delphi\nprocedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);\nbegin\n  CanClose := not HttpMonitoring.IsBusy;\n  if not CanClose then\n    MessageDLG(\n      'Requests are still in progress. Please wait for them to complete before closing the application.\"',\n      TMsgDlgType.mtInformation, [TMsgDlgBtn.mbOK], 0);\nend;\n```\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.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxidonkey%2Fdelphideepseek","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxidonkey%2Fdelphideepseek","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxidonkey%2Fdelphideepseek/lists"}