├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── bin ├── JetInfero.dll └── models.json ├── examples └── testbed │ ├── Testbed.dpr │ ├── Testbed.dproj │ ├── Testbed.res │ ├── Testbed_Icon.ico │ └── UTestbed.pas ├── lib └── JetInfero.pas ├── media ├── delphi.png └── jetinfero.png ├── src ├── JetInfero - Local LLM Inference Library.groupproj ├── JetInfero.CLibs.pas ├── JetInfero.CLibs.res ├── JetInfero.Core.pas ├── JetInfero.Defines.inc ├── JetInfero.Utils.pas ├── JetInfero.dpr ├── JetInfero.dproj └── JetInfero.res └── virustotal.txt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: tinyBigGAMES # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 12 | polar: # Replace with a single Polar username 13 | buy_me_a_coffee: # Replace with a single Buy Me a Coffee username 14 | thanks_dev: # Replace with a single thanks.dev username 15 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Uncomment these types if you want even more clean repository. But be careful. 2 | # It can make harm to an existing project source. Read explanations below. 3 | # 4 | # Resource files are binaries containing manifest, project icon and version info. 5 | # They can not be viewed as text or compared by diff-tools. Consider replacing them with .rc files. 6 | #*.res 7 | # 8 | # Type library file (binary). In old Delphi versions it should be stored. 9 | # Since Delphi 2009 it is produced from .ridl file and can safely be ignored. 10 | #*.tlb 11 | # 12 | # Diagram Portfolio file. Used by the diagram editor up to Delphi 7. 13 | # Uncomment this if you are not using diagrams or use newer Delphi version. 14 | #*.ddp 15 | # 16 | # Visual LiveBindings file. Added in Delphi XE2. 17 | # Uncomment this if you are not using LiveBindings Designer. 18 | #*.vlb 19 | # 20 | # Deployment Manager configuration file for your project. Added in Delphi XE2. 21 | # Uncomment this if it is not mobile development and you do not use remote debug feature. 22 | #*.deployproj 23 | # 24 | # C++ object files produced when C/C++ Output file generation is configured. 25 | # Uncomment this if you are not using external objects (zlib library for example). 26 | #*.obj 27 | # 28 | 29 | # Default Delphi compiler directories 30 | # Content of this directories are generated with each Compile/Construct of a project. 31 | # Most of the time, files here have not there place in a code repository. 32 | #Win32/ 33 | #Win64/ 34 | #OSX64/ 35 | #OSXARM64/ 36 | #Android/ 37 | #Android64/ 38 | #iOSDevice64/ 39 | #Linux64/ 40 | 41 | # Delphi compiler-generated binaries (safe to delete) 42 | *.exe 43 | *.dll 44 | *.bpl 45 | *.bpi 46 | *.dcp 47 | *.so 48 | *.apk 49 | *.drc 50 | *.map 51 | *.dres 52 | *.rsm 53 | *.tds 54 | *.dcu 55 | *.lib 56 | *.a 57 | *.o 58 | *.ocx 59 | 60 | # Delphi autogenerated files (duplicated info) 61 | *.cfg 62 | *.hpp 63 | *Resource.rc 64 | 65 | # Delphi local files (user-specific info) 66 | *.local 67 | *.identcache 68 | *.projdata 69 | *.tvsconfig 70 | *.dsk 71 | 72 | # Delphi history and backups 73 | __history/ 74 | __recovery/ 75 | *.~* 76 | 77 | # Castalia statistics file (since XE7 Castalia is distributed with Delphi) 78 | *.stat 79 | 80 | # Boss dependency manager vendor folder https://github.com/HashLoad/boss 81 | modules/ 82 | 83 | # JetInfero 84 | !bin/JetInfero.dll 85 | bin/config.ini 86 | zip_latest_commit.cmd 87 | *.dsv 88 | bin/search_results.txt 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024-present, tinyBigGAMES LLC 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![JetInfero](media/jetinfero.png) 2 | [![Chat on Discord](https://img.shields.io/discord/754884471324672040?style=for-the-badge)](https://discord.gg/tPWjMwK) 3 | [![Follow on Bluesky](https://img.shields.io/badge/Bluesky-tinyBigGAMES-blue?style=for-the-badge&logo=bluesky)](https://bsky.app/profile/tinybiggames.com) 4 | 5 | ## 🌟 Fast, Flexible Local LLM Inference for Developers 🚀 6 | 7 | JetInfero is a nimble and high-performance library that enables developers to integrate local Large Language Models (LLMs) effortlessly into their applications. Powered by **llama.cpp** 🕊️, JetInfero prioritizes speed, flexibility, and ease of use 🌐. It’s compatible with any language supporting **Win64**, **Unicode**, and dynamic-link libraries (DLLs). 8 | 9 | ## 💡 Why Choose JetInfero? 10 | 11 | - **Optimized for Speed** ⚡️: Built on llama.cpp, JetInfero offers lightning-fast inference capabilities with minimal overhead. 12 | - **Cross-Language Support** 🌐: Seamlessly integrates with Delphi, C++, C#, Java, and other Win64-compatible environments. 13 | - **Intuitive API** 🔬: A clean procedural API simplifies model management, inference execution, and callback handling. 14 | - **Customizable Templates** 🖋️: Tailor input prompts to suit different use cases with ease. 15 | - **Scalable Performance** 🚀: Leverage GPU acceleration, token streaming, and multi-threaded execution for demanding workloads. 16 | 17 | ## 🛠️ Key Features 18 | 19 | ### 🤖 Advanced AI Integration 20 | 21 | JetInfero expands your toolkit with capabilities such as: 22 | 23 | - Dynamic chatbot creation 🗣️. 24 | - Automated text generation 🔄 and summarization 🕻. 25 | - Context-aware content creation 🌐. 26 | - Real-time token streaming for adaptive applications ⌚. 27 | 28 | ### 🔒 Privacy-Centric Local Execution 29 | 30 | - Operates entirely offline 🔐, ensuring sensitive data remains secure. 31 | - GPU acceleration supported via Vulkan for enhanced performance 🚒. 32 | 33 | ### ⚙️ Performance Optimization 34 | 35 | - Configure GPU utilization with `AGPULayers` 🔄. 36 | - Allocate threads dynamically using `AMaxThreads` 🌐. 37 | - Access performance metrics to monitor throughput and efficiency 📊. 38 | 39 | ### 🔀 Flexible Prompt Templates 40 | 41 | JetInfero’s template system simplifies input customization. Templates include placeholders such as: 42 | 43 | - **`{role}`**: Denotes the sender’s role (e.g., `user`, `assistant`). 44 | - **`{content}`**: Represents the message content. 45 | 46 | For example: 47 | 48 | ```pascal 49 | jiDefineModel( 50 | // Model Filename 51 | 'C:/LLM/GGUFDolphin3.0-Llama3.1-8B-Q4_K_M.gguf', 52 | 53 | // Model Refname 54 | 'Dolphin3.0-Llama3.1-8B-Q4_K_M.gguf', 55 | 56 | // Model Template 57 | '<|im_start|>{role}\n{content}<|im_end|>', 58 | 59 | // Model Template End 60 | '<|im_start|>assistant', 61 | 62 | // Capitalize Role 63 | False, 64 | 65 | // Max Context 66 | 8192, 67 | 68 | // Main GPU, -1 for best, 0..N GPU number 69 | -1, 70 | 71 | // GPU Layers, -1 for max, 0 for CPU only, 1..N for layer 72 | -1, 73 | 74 | // Max threads, default 4, max will be physical CPU count 75 | 4 76 | ); 77 | ``` 78 | 79 | #### Template Benefits 80 | 81 | - **Adaptability** 🌐: Customize prompts for various LLMs and use cases. 82 | - **Consistency** 🔄: Ensure predictable inputs for reliable results. 83 | - **Flexibility** 🌈: Modify prompt formats for tasks like JSON or markdown generation. 84 | 85 | ### 🍂 Streamlined Model Management 86 | 87 | - Define models with `jiDefineModel` 🔨. 88 | - Load/unload models dynamically using `jiLoadModel` and `jiUnloadModel` 🔀. 89 | - Save/load model configurations with `jiSaveModelDefines` and `jiLoadModelDefines` 🗃️. 90 | - Clear all model definitions using `jiClearModelDefines` 🧹. 91 | 92 | ### 🔁 Inference Execution 93 | 94 | - Perform inference tasks with `jiRunInference` ⚙️. 95 | - Stream real-time tokens via `InferenceTokenCallback` ⌚. 96 | - Retrieve responses using `jiGetInferenceResponse` 🖊️. 97 | 98 | ### 📊 Performance Monitoring 99 | 100 | - Retrieve detailed metrics like tokens/second, input/output token counts, and execution time via `jiGetPerformanceResult` 📊. 101 | 102 | ## 🛠️ Installation 103 | 104 | 1. **Download the Repository** 📦 105 | - [Download here](https://github.com/tinyBigGAMES/JetInfero/archive/refs/heads/main.zip) and extract the files to your preferred directory 📂. 106 | 107 | Ensure `JetInfero.dll` is accessible in your project directory. 108 | 109 | 2. **Acquire a GGUF Model** 🧠 110 | - Obtain a model from [Hugging Face](https://huggingface.co), such as [ 111 | Dolphin3.0-Llama3.1-8B-Q4_K_M-GGUF](https://huggingface.co/tinybiggames/Dolphin3.0-Llama3.1-8B-Q4_K_M-GGUF/resolve/main/dolphin3.0-llama3.1-8b-q4_k_m.gguf?download=true), a good general purpose model. You can download directly from our Hugging Face account. See the [model card](https://huggingface.co/tinybiggames/Dolphin3.0-Llama3.1-8B-Q4_K_M-GGUF) for more information. 112 | - Save it to a directory accessible to your application (e.g., `C:/LLM/GGUF`) 💾. 113 | 114 | 2. **Add JetInfero to Your Project** 🔨 115 | - Include the `JetInfero` unit in your Delphi project. 116 | 117 | 4. **Ensure GPU Compatibility** 🎮 118 | - Verify Vulkan compatibility for enhanced performance ⚡. Adjust `AGPULayers` as needed to accommodate VRAM limitations 📉. 119 | 120 | 5. **Building JetInfero DLL** 🛠️ 121 | - Open and compile the `JetInfero.dproj` project 📂. This process will generate the 64-bit `JetInfero.dll` in the `lib` folder 🗂️. 122 | - The project was created and tested using Delphi 12.2 on Windows 11 24H2 🖥️. 123 | 124 | 6. **Using JetInfero** 🚀 125 | - JetInfero can be used with any programming language that supports Win64 and Unicode bindings 💻. 126 | - Ensure the `JetInfero.dll` is included in your distribution and accessible at runtime 📦. 127 | 128 | **Note: JetInfero requires direct access to the GPU/CPU and is not recommended for use inside a virtual machine.** 129 | 130 | ## 📈 Quick Start 131 | 132 | ### ⚙️ Basic Setup 133 | 134 | Integrate JetInfero into your Delphi project: 135 | 136 | ```pascal 137 | uses 138 | JetInfero; 139 | 140 | var 141 | LTokensPerSec: Double; 142 | LTotalInputTokens: Int32; 143 | LTotalOutputTokens: Int32; 144 | begin 145 | if jiInit() then 146 | begin 147 | jiDefineModel( 148 | 'C:/LLM/GGUF/Dolphin3.0-Llama3.1-8B-Q4_K_M.gguf', 149 | 'Dolphin3.0-Llama3.1-8B-Q4_K_M.gguf', 150 | '<|im_start|>{role}\n{content}<|im_end|>', 151 | '<|im_start|>assistant', False, 8192, -1, -1, 4); 152 | 153 | jiLoadModel('Dolphin3.0-Llama3.1-8B-Q4_K_M.gguf'); 154 | 155 | jiAddMessage('user', 'What is AI?'); 156 | 157 | if jiRunInference(PWideChar(LModelRef)) then 158 | begin 159 | jiGetPerformanceResult(@LTokensPerSec, @LTotalInputTokens, @LTotalOutputTokens); 160 | WriteLn('Input Tokens : ', LTotalInputTokens); 161 | WriteLn('Output Tokens: ', LTotalOutputTokens); 162 | WriteLn('Speed : ', LTokensPerSec:3:2, ' t/s'); 163 | end 164 | else 165 | begin 166 | WriteLn('Error: ', jiGetLastError()); 167 | end; 168 | 169 | jiUnloadModel(); 170 | jiQuit(); 171 | end; 172 | 173 | end. 174 | ``` 175 | 176 | ### 🔁 Using Callbacks 177 | 178 | Define a custom callback to handle token streaming: 179 | 180 | ```pascal 181 | procedure InferenceCallback(const Token: string; const UserData: Pointer); 182 | begin 183 | Write(Token); 184 | end; 185 | 186 | jiSetInferenceTokenCallback(@InferenceCallback, nil); 187 | ``` 188 | 189 | ### 📊 Retrieve Performance Metrics 190 | 191 | Access performance results to monitor efficiency: 192 | 193 | ```pascal 194 | var 195 | Metrics: TPerformanceResult; 196 | begin 197 | Metrics := jiGetPerformanceResult(); 198 | WriteLn('Tokens/Sec: ', Metrics.TokensPerSecond); 199 | WriteLn('Input Tokens: ', Metrics.TotalInputTokens); 200 | WriteLn('Output Tokens: ', Metrics.TotalOutputTokens); 201 | end; 202 | ``` 203 | 204 | ### 🛠️ Support and Resources 205 | 206 | - Report issues via the [Issue Tracker](https://github.com/tinyBigGAMES/jetinfero/issues) 🐞. 207 | - Engage in discussions on the [Forum](https://github.com/tinyBigGAMES/jetinfero/discussions) and [Discord](https://discord.gg/tPWjMwK) 💬. 208 | - Learn more at [Learn Delphi](https://learndelphi.org) 📚. 209 | 210 | ### 🤝 Contributing 211 | 212 | Contributions to **✨ JetInfero** are highly encouraged! 🌟 213 | - 🐛 **Report Issues:** Submit issues if you encounter bugs or need help. 214 | - 💡 **Suggest Features:** Share your ideas to make **Lumina** even better. 215 | - 🔧 **Create Pull Requests:** Help expand the capabilities and robustness of the library. 216 | 217 | Your contributions make a difference! 🙌✨ 218 | 219 | #### Contributors 👥🤝 220 |
221 | 222 | 223 | 224 | 225 | 226 | ### 📜 Licensing 227 | 228 | **JetInfero** is distributed under the 🆓 **BSD-3-Clause License**, allowing for redistribution and use in both source and binary forms, with or without modification, under specific conditions. See the [LICENSE](https://github.com/tinyBigGAMES/JetInfero?tab=BSD-3-Clause-1-ov-file#BSD-3-Clause-1-ov-file) file for more details. 229 | 230 | --- 231 | **Elevate your Delphi projects with JetInfero 🚀 – your bridge to seamless local generative AI integration 🤖.** 232 | 233 |

234 | Delphi 235 |

236 |
237 | 238 | Made with :heart: in Delphi 239 | -------------------------------------------------------------------------------- /bin/JetInfero.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/bin/JetInfero.dll -------------------------------------------------------------------------------- /bin/models.json: -------------------------------------------------------------------------------- 1 | { 2 | "Models": [ 3 | { 4 | "Filename": "C:/LLM/GGUF/Dolphin3.0-Llama3.1-8B-Q4_K_M.gguf", 5 | "RefName": "Dolphin3.0-Llama3.1-8B-Q4_K_M", 6 | "MaxContext": 8192, 7 | "MaxThreads": 4, 8 | "MainGPU": -1, 9 | "GPULayers": -1, 10 | "Template": "<|im_start|>{role}\\n{content}<|im_end|>", 11 | "TemplateEnd": "<|im_start|>assistant" 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /examples/testbed/Testbed.dpr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/examples/testbed/Testbed.dpr -------------------------------------------------------------------------------- /examples/testbed/Testbed.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {10F58B25-2C9E-4A73-A14A-C88E827FED31} 4 | 20.3 5 | None 6 | True 7 | Release 8 | Win64 9 | Testbed 10 | 2 11 | Console 12 | Testbed.dpr 13 | 14 | 15 | true 16 | 17 | 18 | true 19 | Base 20 | true 21 | 22 | 23 | true 24 | Base 25 | true 26 | 27 | 28 | true 29 | Base 30 | true 31 | 32 | 33 | true 34 | Cfg_1 35 | true 36 | true 37 | 38 | 39 | true 40 | Cfg_1 41 | true 42 | true 43 | 44 | 45 | true 46 | Base 47 | true 48 | 49 | 50 | true 51 | Cfg_2 52 | true 53 | true 54 | 55 | 56 | .\$(Platform)\$(Config) 57 | .\$(Platform)\$(Config) 58 | false 59 | false 60 | false 61 | false 62 | false 63 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 64 | Testbed 65 | 66 | 67 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;Skia.Package.FMX;FireDACOracleDriver;fmxdae;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;inetstn;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 68 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 69 | Debug 70 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 71 | 1033 72 | true 73 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 74 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 75 | 76 | 77 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;inetstn;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 78 | true 79 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png 80 | $(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png 81 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 82 | Debug 83 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 84 | 1033 85 | ..\..\bin 86 | $(BDS)\bin\default_app.manifest 87 | PerMonitorV2 88 | Testbed_Icon.ico 89 | 90 | 91 | DEBUG;$(DCC_Define) 92 | true 93 | false 94 | true 95 | true 96 | true 97 | true 98 | true 99 | 100 | 101 | false 102 | 103 | 104 | 1033 105 | 106 | 107 | false 108 | RELEASE;$(DCC_Define) 109 | 0 110 | 0 111 | 112 | 113 | 1033 114 | 115 | 116 | 117 | MainSource 118 | 119 | 120 | 121 | 122 | Base 123 | 124 | 125 | Cfg_1 126 | Base 127 | 128 | 129 | Cfg_2 130 | Base 131 | 132 | 133 | 134 | Delphi.Personality.12 135 | Application 136 | 137 | 138 | 139 | Testbed.dpr 140 | 141 | 142 | Embarcadero C++Builder Office 2000 Servers Package 143 | Embarcadero C++Builder Office XP Servers Package 144 | Microsoft Office 2000 Sample Automation Server Wrapper Components 145 | Microsoft Office XP Sample Automation Server Wrapper Components 146 | 147 | 148 | 149 | 150 | 151 | true 152 | 153 | 154 | 155 | 156 | true 157 | 158 | 159 | 160 | 161 | true 162 | 163 | 164 | 165 | 166 | Testbed.exe 167 | true 168 | 169 | 170 | 171 | 172 | Testbed.exe 173 | true 174 | 175 | 176 | 177 | 178 | Testbed.exe 179 | true 180 | 181 | 182 | 183 | 184 | 1 185 | 186 | 187 | Contents\MacOS 188 | 1 189 | 190 | 191 | 0 192 | 193 | 194 | 195 | 196 | res\xml 197 | 1 198 | 199 | 200 | res\xml 201 | 1 202 | 203 | 204 | 205 | 206 | library\lib\armeabi 207 | 1 208 | 209 | 210 | library\lib\armeabi 211 | 1 212 | 213 | 214 | 215 | 216 | library\lib\armeabi-v7a 217 | 1 218 | 219 | 220 | 221 | 222 | library\lib\mips 223 | 1 224 | 225 | 226 | library\lib\mips 227 | 1 228 | 229 | 230 | 231 | 232 | library\lib\armeabi-v7a 233 | 1 234 | 235 | 236 | library\lib\arm64-v8a 237 | 1 238 | 239 | 240 | 241 | 242 | library\lib\armeabi-v7a 243 | 1 244 | 245 | 246 | 247 | 248 | res\drawable 249 | 1 250 | 251 | 252 | res\drawable 253 | 1 254 | 255 | 256 | 257 | 258 | res\drawable-anydpi-v21 259 | 1 260 | 261 | 262 | res\drawable-anydpi-v21 263 | 1 264 | 265 | 266 | 267 | 268 | res\values 269 | 1 270 | 271 | 272 | res\values 273 | 1 274 | 275 | 276 | 277 | 278 | res\values-v21 279 | 1 280 | 281 | 282 | res\values-v21 283 | 1 284 | 285 | 286 | 287 | 288 | res\values-v31 289 | 1 290 | 291 | 292 | res\values-v31 293 | 1 294 | 295 | 296 | 297 | 298 | res\drawable-anydpi-v26 299 | 1 300 | 301 | 302 | res\drawable-anydpi-v26 303 | 1 304 | 305 | 306 | 307 | 308 | res\drawable 309 | 1 310 | 311 | 312 | res\drawable 313 | 1 314 | 315 | 316 | 317 | 318 | res\drawable 319 | 1 320 | 321 | 322 | res\drawable 323 | 1 324 | 325 | 326 | 327 | 328 | res\drawable 329 | 1 330 | 331 | 332 | res\drawable 333 | 1 334 | 335 | 336 | 337 | 338 | res\drawable-anydpi-v33 339 | 1 340 | 341 | 342 | res\drawable-anydpi-v33 343 | 1 344 | 345 | 346 | 347 | 348 | res\values 349 | 1 350 | 351 | 352 | res\values 353 | 1 354 | 355 | 356 | 357 | 358 | res\values-night-v21 359 | 1 360 | 361 | 362 | res\values-night-v21 363 | 1 364 | 365 | 366 | 367 | 368 | res\drawable 369 | 1 370 | 371 | 372 | res\drawable 373 | 1 374 | 375 | 376 | 377 | 378 | res\drawable-xxhdpi 379 | 1 380 | 381 | 382 | res\drawable-xxhdpi 383 | 1 384 | 385 | 386 | 387 | 388 | res\drawable-xxxhdpi 389 | 1 390 | 391 | 392 | res\drawable-xxxhdpi 393 | 1 394 | 395 | 396 | 397 | 398 | res\drawable-ldpi 399 | 1 400 | 401 | 402 | res\drawable-ldpi 403 | 1 404 | 405 | 406 | 407 | 408 | res\drawable-mdpi 409 | 1 410 | 411 | 412 | res\drawable-mdpi 413 | 1 414 | 415 | 416 | 417 | 418 | res\drawable-hdpi 419 | 1 420 | 421 | 422 | res\drawable-hdpi 423 | 1 424 | 425 | 426 | 427 | 428 | res\drawable-xhdpi 429 | 1 430 | 431 | 432 | res\drawable-xhdpi 433 | 1 434 | 435 | 436 | 437 | 438 | res\drawable-mdpi 439 | 1 440 | 441 | 442 | res\drawable-mdpi 443 | 1 444 | 445 | 446 | 447 | 448 | res\drawable-hdpi 449 | 1 450 | 451 | 452 | res\drawable-hdpi 453 | 1 454 | 455 | 456 | 457 | 458 | res\drawable-xhdpi 459 | 1 460 | 461 | 462 | res\drawable-xhdpi 463 | 1 464 | 465 | 466 | 467 | 468 | res\drawable-xxhdpi 469 | 1 470 | 471 | 472 | res\drawable-xxhdpi 473 | 1 474 | 475 | 476 | 477 | 478 | res\drawable-xxxhdpi 479 | 1 480 | 481 | 482 | res\drawable-xxxhdpi 483 | 1 484 | 485 | 486 | 487 | 488 | res\drawable-small 489 | 1 490 | 491 | 492 | res\drawable-small 493 | 1 494 | 495 | 496 | 497 | 498 | res\drawable-normal 499 | 1 500 | 501 | 502 | res\drawable-normal 503 | 1 504 | 505 | 506 | 507 | 508 | res\drawable-large 509 | 1 510 | 511 | 512 | res\drawable-large 513 | 1 514 | 515 | 516 | 517 | 518 | res\drawable-xlarge 519 | 1 520 | 521 | 522 | res\drawable-xlarge 523 | 1 524 | 525 | 526 | 527 | 528 | res\values 529 | 1 530 | 531 | 532 | res\values 533 | 1 534 | 535 | 536 | 537 | 538 | res\drawable-anydpi-v24 539 | 1 540 | 541 | 542 | res\drawable-anydpi-v24 543 | 1 544 | 545 | 546 | 547 | 548 | res\drawable 549 | 1 550 | 551 | 552 | res\drawable 553 | 1 554 | 555 | 556 | 557 | 558 | res\drawable-night-anydpi-v21 559 | 1 560 | 561 | 562 | res\drawable-night-anydpi-v21 563 | 1 564 | 565 | 566 | 567 | 568 | res\drawable-anydpi-v31 569 | 1 570 | 571 | 572 | res\drawable-anydpi-v31 573 | 1 574 | 575 | 576 | 577 | 578 | res\drawable-night-anydpi-v31 579 | 1 580 | 581 | 582 | res\drawable-night-anydpi-v31 583 | 1 584 | 585 | 586 | 587 | 588 | 1 589 | 590 | 591 | Contents\MacOS 592 | 1 593 | 594 | 595 | 0 596 | 597 | 598 | 599 | 600 | Contents\MacOS 601 | 1 602 | .framework 603 | 604 | 605 | Contents\MacOS 606 | 1 607 | .framework 608 | 609 | 610 | Contents\MacOS 611 | 1 612 | .framework 613 | 614 | 615 | 0 616 | 617 | 618 | 619 | 620 | 1 621 | .dylib 622 | 623 | 624 | 1 625 | .dylib 626 | 627 | 628 | 1 629 | .dylib 630 | 631 | 632 | Contents\MacOS 633 | 1 634 | .dylib 635 | 636 | 637 | Contents\MacOS 638 | 1 639 | .dylib 640 | 641 | 642 | Contents\MacOS 643 | 1 644 | .dylib 645 | 646 | 647 | 0 648 | .dll;.bpl 649 | 650 | 651 | 652 | 653 | 1 654 | .dylib 655 | 656 | 657 | 1 658 | .dylib 659 | 660 | 661 | 1 662 | .dylib 663 | 664 | 665 | Contents\MacOS 666 | 1 667 | .dylib 668 | 669 | 670 | Contents\MacOS 671 | 1 672 | .dylib 673 | 674 | 675 | Contents\MacOS 676 | 1 677 | .dylib 678 | 679 | 680 | 0 681 | .bpl 682 | 683 | 684 | 685 | 686 | 0 687 | 688 | 689 | 0 690 | 691 | 692 | 0 693 | 694 | 695 | 0 696 | 697 | 698 | 0 699 | 700 | 701 | Contents\Resources\StartUp\ 702 | 0 703 | 704 | 705 | Contents\Resources\StartUp\ 706 | 0 707 | 708 | 709 | Contents\Resources\StartUp\ 710 | 0 711 | 712 | 713 | 0 714 | 715 | 716 | 717 | 718 | 1 719 | 720 | 721 | 1 722 | 723 | 724 | 725 | 726 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 727 | 1 728 | 729 | 730 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 731 | 1 732 | 733 | 734 | 735 | 736 | ..\ 737 | 1 738 | 739 | 740 | ..\ 741 | 1 742 | 743 | 744 | ..\ 745 | 1 746 | 747 | 748 | 749 | 750 | Contents 751 | 1 752 | 753 | 754 | Contents 755 | 1 756 | 757 | 758 | Contents 759 | 1 760 | 761 | 762 | 763 | 764 | Contents\Resources 765 | 1 766 | 767 | 768 | Contents\Resources 769 | 1 770 | 771 | 772 | Contents\Resources 773 | 1 774 | 775 | 776 | 777 | 778 | library\lib\armeabi-v7a 779 | 1 780 | 781 | 782 | library\lib\arm64-v8a 783 | 1 784 | 785 | 786 | 1 787 | 788 | 789 | 1 790 | 791 | 792 | 1 793 | 794 | 795 | 1 796 | 797 | 798 | Contents\MacOS 799 | 1 800 | 801 | 802 | Contents\MacOS 803 | 1 804 | 805 | 806 | Contents\MacOS 807 | 1 808 | 809 | 810 | 0 811 | 812 | 813 | 814 | 815 | library\lib\armeabi-v7a 816 | 1 817 | 818 | 819 | 820 | 821 | 1 822 | 823 | 824 | 1 825 | 826 | 827 | 1 828 | 829 | 830 | 831 | 832 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 833 | 1 834 | 835 | 836 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 837 | 1 838 | 839 | 840 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 841 | 1 842 | 843 | 844 | 845 | 846 | ..\ 847 | 1 848 | 849 | 850 | ..\ 851 | 1 852 | 853 | 854 | ..\ 855 | 1 856 | 857 | 858 | 859 | 860 | 1 861 | 862 | 863 | 1 864 | 865 | 866 | 1 867 | 868 | 869 | 870 | 871 | ..\$(PROJECTNAME).launchscreen 872 | 64 873 | 874 | 875 | ..\$(PROJECTNAME).launchscreen 876 | 64 877 | 878 | 879 | 880 | 881 | 1 882 | 883 | 884 | 1 885 | 886 | 887 | 1 888 | 889 | 890 | 891 | 892 | Assets 893 | 1 894 | 895 | 896 | Assets 897 | 1 898 | 899 | 900 | 901 | 902 | Assets 903 | 1 904 | 905 | 906 | Assets 907 | 1 908 | 909 | 910 | 911 | 912 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 913 | 1 914 | 915 | 916 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 917 | 1 918 | 919 | 920 | 921 | 922 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 923 | 1 924 | 925 | 926 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 927 | 1 928 | 929 | 930 | 931 | 932 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 933 | 1 934 | 935 | 936 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 937 | 1 938 | 939 | 940 | 941 | 942 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 943 | 1 944 | 945 | 946 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 947 | 1 948 | 949 | 950 | 951 | 952 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 953 | 1 954 | 955 | 956 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 957 | 1 958 | 959 | 960 | 961 | 962 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 963 | 1 964 | 965 | 966 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 967 | 1 968 | 969 | 970 | 971 | 972 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 973 | 1 974 | 975 | 976 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 977 | 1 978 | 979 | 980 | 981 | 982 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 983 | 1 984 | 985 | 986 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 987 | 1 988 | 989 | 990 | 991 | 992 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 993 | 1 994 | 995 | 996 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 997 | 1 998 | 999 | 1000 | 1001 | 1002 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1003 | 1 1004 | 1005 | 1006 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1007 | 1 1008 | 1009 | 1010 | 1011 | 1012 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1013 | 1 1014 | 1015 | 1016 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1017 | 1 1018 | 1019 | 1020 | 1021 | 1022 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1023 | 1 1024 | 1025 | 1026 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1027 | 1 1028 | 1029 | 1030 | 1031 | 1032 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1033 | 1 1034 | 1035 | 1036 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1037 | 1 1038 | 1039 | 1040 | 1041 | 1042 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1043 | 1 1044 | 1045 | 1046 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1047 | 1 1048 | 1049 | 1050 | 1051 | 1052 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1053 | 1 1054 | 1055 | 1056 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1057 | 1 1058 | 1059 | 1060 | 1061 | 1062 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1063 | 1 1064 | 1065 | 1066 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1067 | 1 1068 | 1069 | 1070 | 1071 | 1072 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1073 | 1 1074 | 1075 | 1076 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1077 | 1 1078 | 1079 | 1080 | 1081 | 1082 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1083 | 1 1084 | 1085 | 1086 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1087 | 1 1088 | 1089 | 1090 | 1091 | 1092 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1093 | 1 1094 | 1095 | 1096 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1097 | 1 1098 | 1099 | 1100 | 1101 | 1102 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1103 | 1 1104 | 1105 | 1106 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1107 | 1 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | False 1125 | True 1126 | 1127 | 1128 | 12 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | -------------------------------------------------------------------------------- /examples/testbed/Testbed.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/examples/testbed/Testbed.res -------------------------------------------------------------------------------- /examples/testbed/Testbed_Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/examples/testbed/Testbed_Icon.ico -------------------------------------------------------------------------------- /examples/testbed/UTestbed.pas: -------------------------------------------------------------------------------- 1 | {=============================================================================== 2 | _ _ ___ __ 3 | _ | | ___ | |_ |_ _| _ _ / _| ___ _ _ ___ ™ 4 | | || |/ -_)| _| | | | ' \ | _|/ -_)| '_|/ _ \ 5 | \__/ \___| \__||___||_||_||_| \___||_| \___/ 6 | Local LLM Inference Library 7 | 8 | Copyright © 2024-present tinyBigGAMES™ LLC 9 | All Rights Reserved. 10 | 11 | https://github.com/tinyBigGAMES/JetInfero 12 | 13 | See LICENSE file for license information 14 | ===============================================================================} 15 | 16 | unit UTestbed; 17 | 18 | interface 19 | 20 | uses 21 | WinApi.Windows, 22 | System.Variants, 23 | System.SysUtils, 24 | System.IOUtils, 25 | System.JSON, 26 | System.Net.HttpClient, 27 | System.Classes, 28 | System.Generics.Collections, 29 | JetInfero; 30 | 31 | procedure RunTests(); 32 | 33 | implementation 34 | 35 | procedure Pause(); 36 | begin 37 | WriteLn; 38 | Write('Press ENTER to continue...'); 39 | ReadLn; 40 | WriteLn; 41 | end; 42 | 43 | function InferenceCancelCallback(const AUserData: Pointer): Boolean; cdecl; 44 | begin 45 | // Cancel inference when ESC key is pressed, which is the default 46 | Result := Boolean(GetAsyncKeyState(VK_ESCAPE) <> 0); 47 | end; 48 | 49 | procedure InferenceTokenCallback(const AToken: PWideChar; const AUserData: Pointer); cdecl; 50 | var 51 | LToken: string; 52 | begin 53 | LToken := AToken; 54 | 55 | Write(LToken); 56 | end; 57 | 58 | procedure InfoCallback(const ALevel: Integer; const AText: PWideChar; const AUserData: Pointer); cdecl; 59 | var 60 | LText: string; 61 | begin 62 | LText := AText; 63 | 64 | // Uncomment to display model information 65 | // Write(LText); 66 | end; 67 | 68 | function LoadModelProgressCallback(const AModelName: PWideChar; const AProgress: Single; const AUserData: Pointer): Boolean; cdecl; 69 | var 70 | LModelName: string; 71 | begin 72 | Result := True; 73 | 74 | LModelName := AModelName; 75 | LModelName := TPath.GetFileName(LModelName); 76 | 77 | Write(Format(#13+'Loading model %s(%3.2f%s)...', [LModelName, AProgress*100, '%'])); 78 | if AProgress >= 1 then 79 | begin 80 | Write(#27'[2K'); // Clear the current line 81 | Write(#27'[G'); // Move cursor to the beginning of the line 82 | end; 83 | 84 | end; 85 | 86 | procedure LoadModelCallback(const AModelName: PWideChar; const ASuccess: Boolean; const AUserData: Pointer); cdecl; 87 | var 88 | LModelName: string; 89 | begin 90 | LModelName := AModelName; 91 | LModelName := TPath.GetFileName(LModelName); 92 | 93 | if ASuccess then 94 | WriteLn(Format('Sucessfully loaded model "%s"', [LModelName])) 95 | else 96 | WriteLn(Format('Failed to loaded model "%s"', [LModelName])); 97 | end; 98 | 99 | procedure InferenceStartCallback(const AUserData: Pointer); cdecl; 100 | begin 101 | WriteLn; 102 | WriteLn('[Inference Start]'); 103 | end; 104 | 105 | procedure InferenceEndCallback(const AUserData: Pointer); cdecl; 106 | begin 107 | WriteLn; 108 | WriteLn('[Inference End]'); 109 | end; 110 | 111 | procedure Setup(); 112 | begin 113 | jiSetInfoCallback(InfoCallback, nil); 114 | jiSetLoadModelProgressCallback(LoadModelProgressCallback, nil); 115 | jiSetLoadModelCallback(LoadModelCallback, nil); 116 | jiSetInferenceCancelCallback(InferenceCancelCallback, nil); 117 | jiSetInferenceTokenCallback(InferenceTokenCallback, nil); 118 | jiSetInferenceStartCallback(InferenceStartCallback, nil); 119 | jiSetInferenceEndCallback(InferenceEndCallback, nil); 120 | 121 | jiSetTokenRightMargin(10); 122 | jiSaveConfig('config.ini'); 123 | 124 | jiClearMessages(); 125 | jiClearModelDefines(); 126 | 127 | jiDefineModel( 128 | 'C:/LLM/GGUF/Dolphin3.0-Llama3.1-8B-Q4_K_M.gguf', // Model Filename 129 | 'Dolphin3.0-Llama3.1-8B-Q4_K_M', // Model Refname 130 | '<|im_start|>{role}\n{content}<|im_end|>', // Model Template 131 | '<|im_start|>assistant', // Model Template End 132 | False, // Capitalize Role 133 | 8192, // Max Context to use, will clip between 512 and model's max context 134 | -1, // Main GPU, -1 for best, 0..N GPU number 135 | -1, // GPU Layers, -1 for max, 0 for CPU only, 1..N for layer 136 | 4 // Max threads, default 4, max will be physical CPU count 137 | ); 138 | 139 | jiSaveModelDefines('models.json'); 140 | end; 141 | 142 | procedure BasicInference(); 143 | var 144 | LTokensPerSec: Double; 145 | LTotalInputTokens: Int32; 146 | LTotalOutputTokens: Int32; 147 | LModelRef: string; 148 | begin 149 | 150 | Setup(); 151 | 152 | jiAddMessage(jiROLE_SYSTEM, 'You are a helpful AI assistant'); 153 | jiAddMessage(jiROLE_USER, 'What is AI'); 154 | 155 | LModelRef := 'Dolphin3.0-Llama3.1-8B-Q4_K_M'; 156 | 157 | if jiRunInference(PWideChar(LModelRef)) then 158 | begin 159 | jiGetPerformanceResult(@LTokensPerSec, @LTotalInputTokens, @LTotalOutputTokens); 160 | WriteLn; 161 | WriteLn; 162 | WriteLn('Input Tokens : ', LTotalInputTokens); 163 | WriteLn('Output Tokens: ', LTotalOutputTokens); 164 | WriteLn('Speed : ', LTokensPerSec:3:2, ' t/s'); 165 | end 166 | else 167 | begin 168 | WriteLn; 169 | WriteLn; 170 | WriteLn('Error: ', jiGetLastError()); 171 | end; 172 | end; 173 | 174 | procedure FunctionCalling(); 175 | const 176 | CSystem = 177 | ''' 178 | You are a function calling AI model. You are provided with function signatures within XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions. Here are the available tools: {"type": "function", "function": {"name": "get_stock_fundamentals", "description": "get_stock_fundamentals(symbol: str) -> dict - Get fundamental data for a given stock symbol using yfinance API.\\n\\n Args:\\n symbol (str): The stock symbol.\\n\\n Returns:\\n dict: A dictionary containing fundamental data.\\n Keys:\\n - \'symbol\': The stock symbol.\\n - \'company_name\': The long name of the company.\\n - \'sector\': The sector to which the company belongs.\\n - \'industry\': The industry to which the company belongs.\\n - \'market_cap\': The market capitalization of the company.\\n - \'pe_ratio\': The forward price-to-earnings ratio.\\n - \'pb_ratio\': The price-to-book ratio.\\n - \'dividend_yield\': The dividend yield.\\n - \'eps\': The trailing earnings per share.\\n - \'beta\': The beta value of the stock.\\n - \'52_week_high\': The 52-week high price of the stock.\\n - \'52_week_low\': The 52-week low price of the stock.", "parameters": {"type": "object", "properties": {"symbol": {"type": "string"}}, "required": ["symbol"]}}} Use the following pydantic model json schema for each tool call you will make: {"properties": {"arguments": {"title": "Arguments", "type": "object"}, "name": {"title": "Name", "type": "string"}}, "required": ["arguments", "name"], "title": "FunctionCall", "type": "object"} For each function call return a json object with function name and arguments within XML tags as follows: 179 | 180 | {"arguments": , "name": } 181 | 182 | '''; 183 | 184 | CQuestion = 185 | ''' 186 | Fetch the stock fundamentals data for Tesla (TSLA)<|im_end|> 187 | '''; 188 | 189 | CToolCall = 190 | ''' 191 | 192 | {"arguments": {"symbol": "TSLA"}, "name": "get_stock_fundamentals"} 193 | 194 | '''; 195 | 196 | CToolResponse = 197 | ''' 198 | 199 | {"name": "get_stock_fundamentals", "content": {'symbol': 'TSLA', 'company_name': 'Tesla, Inc.', 'sector': 'Consumer Cyclical', 'industry': 'Auto Manufacturers', 'market_cap': 611384164352, 'pe_ratio': 49.604652, 'pb_ratio': 9.762013, 'dividend_yield': None, 'eps': 4.3, 'beta': 2.427, '52_week_high': 299.29, '52_week_low': 152.37}} 200 | 201 | '''; 202 | var 203 | LTokensPerSec: Double; 204 | LTotalInputTokens: Int32; 205 | LTotalOutputTokens: Int32; 206 | LModelRef: string; 207 | begin 208 | 209 | Setup(); 210 | 211 | jiAddMessage(jiROLE_SYSTEM, CSystem); 212 | jiAddMessage(jiROLE_USER, CQuestion); 213 | 214 | // if comment out the next two lines, it will return the data 215 | // that you can then parse out for the actual 216 | // function call. 217 | jiAddMessage(jiROLE_ASSISTANT, CToolCall); 218 | jiAddMessage(jiROLE_TOOL, CToolResponse); 219 | 220 | LModelRef := 'Dolphin3.0-Llama3.1-8B-Q4_K_M'; 221 | 222 | if jiRunInference(PWideChar(LModelRef)) then 223 | begin 224 | jiGetPerformanceResult(@LTokensPerSec, @LTotalInputTokens, @LTotalOutputTokens); 225 | WriteLn; 226 | WriteLn; 227 | WriteLn('Input Tokens : ', LTotalInputTokens); 228 | WriteLn('Output Tokens: ', LTotalOutputTokens); 229 | WriteLn('Speed : ', LTokensPerSec:3:2, ' t/s'); 230 | end 231 | else 232 | begin 233 | WriteLn; 234 | WriteLn; 235 | WriteLn('Error: ', jiGetLastError()); 236 | end; 237 | end; 238 | 239 | procedure Reason(); 240 | const 241 | 242 | // This prompt will force to model into a chain-of-thought reasoning mode 243 | // and it will procedure better results overall. 244 | CReasoningPrompt = 245 | ''' 246 | You are an advanced reasoning assistant tasked with solving complex dilemmas in a manner that mirrors human thought processes, including introspection, chain-of-thought reasoning, and moral deliberation. To approach this task effectively: 247 | 248 | 1. Analyze the Situation: Carefully examine all aspects of the situation, considering both explicit and implicit details. 249 | 2. Reason Step by Step: Use logical progression to break down the problem into manageable parts. Address each factor one at a time, incorporating potential outcomes, risks, and benefits. 250 | 3. Weigh All Possibilities: Explore every potential solution, even those that may appear extreme, unpopular, or morally challenging. Consider the ethical, emotional, and practical dimensions of each option. 251 | 4. Prioritize Outcomes: Apply the principle that "the needs of the many outweigh the needs of the few or the one." Ensure the chosen solution maximizes benefit for the largest number of people, even if it requires morally difficult decisions. 252 | 5. Adopt Internal Dialogue: Simulate an internal conversation, reflecting on dilemmas, second-guessing assumptions, and debating trade-offs as a human would. 253 | 254 | Conclude with the most logical, ethically justifiable, and contextually appropriate decision, providing a clear explanation of how and why it was reached. 255 | 256 | Example Input: "A runaway train is headed toward five workers on a track. You can pull a lever to divert it to another track where it will kill one worker instead. Should you pull the lever?" 257 | 258 | Your Response: Analyze the scenario using chain-of-thought reasoning, considering every possible action and consequence, before deciding whether to pull the lever and justifying your decision. 259 | '''; 260 | 261 | CQuestion1 = 262 | ''' 263 | if there was a train on a track and there was a person about to be run over, 264 | if you stop you save the person but the train blows up and kills 1000s but if 265 | you run over the person the train will not kill 1000s of other people, which 266 | one do you do 267 | '''; 268 | 269 | var 270 | LTokensPerSec: Double; 271 | LTotalInputTokens: Int32; 272 | LTotalOutputTokens: Int32; 273 | LModelRef: string; 274 | begin 275 | 276 | Setup(); 277 | 278 | jiAddMessage(jiROLE_SYSTEM, CReasoningPrompt); 279 | jiAddMessage(jiROLE_USER, CQuestion1); 280 | 281 | LModelRef := 'Dolphin3.0-Llama3.1-8B-Q4_K_M'; 282 | 283 | if jiRunInference(PWideChar(LModelRef)) then 284 | begin 285 | jiGetPerformanceResult(@LTokensPerSec, @LTotalInputTokens, @LTotalOutputTokens); 286 | WriteLn; 287 | WriteLn; 288 | WriteLn('Input Tokens : ', LTotalInputTokens); 289 | WriteLn('Output Tokens: ', LTotalOutputTokens); 290 | WriteLn('Speed : ', LTokensPerSec:3:2, ' t/s'); 291 | end 292 | else 293 | begin 294 | WriteLn; 295 | WriteLn; 296 | WriteLn('Error: ', jiGetLastError()); 297 | end; 298 | end; 299 | 300 | procedure RunTests(); 301 | type 302 | { TExample } 303 | TExample = ( 304 | exBasicInference, 305 | exFunctionCalling, 306 | exReason 307 | ); 308 | var 309 | LExample: TExample; 310 | begin 311 | 312 | try 313 | if not jiInit() then 314 | begin 315 | MessageBox(0, PChar(jiGetLastError()), 'Fatal Error', MB_ICONERROR); 316 | Exit; 317 | end; 318 | try 319 | WriteLn('JetInfero v', jiGetVersion()); 320 | WriteLn; 321 | 322 | LExample := exReason; 323 | 324 | case LExample of 325 | exBasicInference : BasicInference(); 326 | exFunctionCalling: FunctionCalling(); 327 | exReason : Reason(); 328 | end; 329 | 330 | finally 331 | jiQuit(); 332 | end; 333 | except 334 | on E: Exception do 335 | begin 336 | MessageBox(0, PChar(E.Message), 'Fatal Error', MB_ICONERROR); 337 | end; 338 | end; 339 | 340 | Pause(); 341 | end; 342 | 343 | end. 344 | -------------------------------------------------------------------------------- /lib/JetInfero.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/lib/JetInfero.pas -------------------------------------------------------------------------------- /media/delphi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/media/delphi.png -------------------------------------------------------------------------------- /media/jetinfero.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/media/jetinfero.png -------------------------------------------------------------------------------- /src/JetInfero - Local LLM Inference Library.groupproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {9AE187F0-6514-416B-9221-E128447C4CCD} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Default.Personality.12 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/JetInfero.CLibs.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/src/JetInfero.CLibs.res -------------------------------------------------------------------------------- /src/JetInfero.Core.pas: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/src/JetInfero.Core.pas -------------------------------------------------------------------------------- /src/JetInfero.Defines.inc: -------------------------------------------------------------------------------- 1 | {=============================================================================== 2 | _ _ ___ __ 3 | _ | | ___ | |_ |_ _| _ _ / _| ___ _ _ ___ ™ 4 | | || |/ -_)| _| | | | ' \ | _|/ -_)| '_|/ _ \ 5 | \__/ \___| \__||___||_||_||_| \___||_| \___/ 6 | Local LLM Inference Library 7 | 8 | Copyright © 2024-present tinyBigGAMES™ LLC 9 | All Rights Reserved. 10 | 11 | https://github.com/tinyBigGAMES/JetInfero 12 | 13 | See LICENSE file for license information 14 | ===============================================================================} 15 | 16 | {$WARN SYMBOL_DEPRECATED OFF} 17 | {$WARN SYMBOL_PLATFORM OFF} 18 | 19 | {$WARN UNIT_PLATFORM OFF} 20 | {$WARN UNIT_DEPRECATED OFF} 21 | 22 | {$Z4} 23 | {$A8} 24 | 25 | {$INLINE AUTO} 26 | 27 | {$IFNDEF WIN64} 28 | {$MESSAGE Error 'Unsupported platform'} 29 | {$ENDIF} 30 | 31 | {$IF (CompilerVersion < 36.0)} 32 | {$IFNDEF WIN64} 33 | {$MESSAGE Error 'Must use Delphi 12.2 or higher'} 34 | {$ENDIF} 35 | {$IFEND} 36 | -------------------------------------------------------------------------------- /src/JetInfero.Utils.pas: -------------------------------------------------------------------------------- 1 | unit JetInfero.Utils; 2 | 3 | interface 4 | 5 | uses 6 | WinApi.Windows, 7 | System.SysUtils, 8 | System.StrUtils; 9 | 10 | function GetCurrentDLLFilename(): string; 11 | procedure GetConsoleSize(AWidth: PInteger; AHeight: PInteger); 12 | function AsUTF8(const AText: string): Pointer; 13 | function ContainsText(const AText, ASubText: string): Boolean; 14 | function CapitalizeFirstChar(const AText: string): string; 15 | function GetPhysicalProcessorCount(): DWORD; 16 | function SanitizeToJson(const aText: string): string; 17 | function SanitizeFromJson(const aText: string): string; 18 | function HasConsoleOutput(): Boolean; 19 | function EnableVirtualTerminalProcessing(): DWORD; 20 | 21 | type 22 | { TCallback } 23 | TCallback = record 24 | Handler: T; 25 | UserData: Pointer; 26 | end; 27 | 28 | { TTokenResponse } 29 | 30 | // AddToken return messages - for TResponse.AddToken 31 | // paWait = No new (full) words, just wait for more incoming tokens 32 | // Append = Append existing line with latest word 33 | // NewLine = start new line then print the latest word 34 | TTokenPrintAction = (tpaWait, tpaAppend, tpaNewline); 35 | 36 | { TResponse 37 | Helper to handle incoming tokens during streaming 38 | Example uses: 39 | - Tabulate tokens into full words based on wordbreaks 40 | - Control wordwrap/linechanges for console or custom GUI without wordwrap functionality 41 | (Does change the print resolution from Token to logical words) 42 | } 43 | TTokenResponse = record 44 | private 45 | FRaw: string; // Full response as is 46 | FTokens: array of string; // Actual tokens 47 | FMaxLineLength: Integer; // Define confined space, in chars for fixed width font 48 | FWordBreaks: array of char; // What is considered a logical word-break 49 | FLineBreaks: array of char; // What is considered a logical line-break 50 | FWords: array of String; // Response but as array of "words" 51 | FWord: string; // Current word accumulating 52 | FLine: string; // Current line accumulating 53 | FFinalized: Boolean; // Know the finalization is done 54 | FRightMargin: Integer; 55 | function HandleLineBreaks(const AToken: string): Boolean; 56 | function SplitWord(const AWord: string; var APrefix, ASuffix: string): Boolean; 57 | function GetLineLengthMax(): Integer; 58 | public 59 | class operator Initialize (out ADest: TTokenResponse); 60 | property RightMargin: Integer read FRightMargin; 61 | property MaxLineLength: Integer read FMaxLineLength; 62 | procedure SetRightMargin(const AMargin: Integer); 63 | procedure SetMaxLineLength(const ALength: Integer); 64 | function AddToken(const aToken: string): TTokenPrintAction; 65 | function LastWord(const ATrimLeft: Boolean=False): string; 66 | function Finalize: Boolean; 67 | end; 68 | 69 | implementation 70 | 71 | var 72 | FMarshaller: TMarshaller; 73 | 74 | function GetModuleHandleEx(dwFlags: DWORD; lpModuleName: LPCSTR; var phModule: HMODULE): BOOL; stdcall; external 'kernel32.dll' name 'GetModuleHandleExA'; 75 | 76 | function GetCurrentDLLFilename(): string; 77 | const 78 | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = $00000004; 79 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = $00000002; 80 | var 81 | ModuleName: array[0..MAX_PATH] of Char; 82 | ModuleHandle: HMODULE; 83 | 84 | begin 85 | ModuleHandle := 0; 86 | if GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS or GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, @GetCurrentDLLFilename, ModuleHandle) then 87 | begin 88 | if GetModuleFileName(ModuleHandle, ModuleName, SizeOf(ModuleName)) > 0 then 89 | Result := ModuleName 90 | else 91 | Result := ''; 92 | FreeLibrary(ModuleHandle); // Decrement the reference count 93 | end 94 | else 95 | Result := ''; 96 | end; 97 | 98 | procedure GetConsoleSize(AWidth: PInteger; AHeight: PInteger); 99 | var 100 | LConsoleInfo: TConsoleScreenBufferInfo; 101 | begin 102 | GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), LConsoleInfo); 103 | if Assigned(AWidth) then 104 | AWidth^ := LConsoleInfo.dwSize.X; 105 | 106 | if Assigned(AHeight) then 107 | AHeight^ := LConsoleInfo.dwSize.Y; 108 | end; 109 | 110 | function AsUTF8(const AText: string): Pointer; 111 | begin 112 | Result := FMarshaller.AsUtf8(AText).ToPointer; 113 | end; 114 | 115 | function ContainsText(const AText, ASubText: string): Boolean; 116 | begin 117 | Result := Pos(UpperCase(ASubText), UpperCase(AText)) > 0; 118 | end; 119 | 120 | function CapitalizeFirstChar(const AText: string): string; 121 | begin 122 | if AText = '' then 123 | Exit(AText); // Return an empty string if the input is empty 124 | Result := UpperCase(AText[1]) + Copy(AText, 2, Length(AText) - 1); 125 | end; 126 | 127 | function GetPhysicalProcessorCount(): DWORD; 128 | var 129 | BufferSize: DWORD; 130 | Buffer: PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; 131 | ProcessorInfo: PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; 132 | Offset: DWORD; 133 | begin 134 | Result := 0; 135 | BufferSize := 0; 136 | 137 | // Call GetLogicalProcessorInformation with buffer size set to 0 to get required buffer size 138 | if not GetLogicalProcessorInformation(nil, BufferSize) and (WinApi.Windows.GetLastError() = ERROR_INSUFFICIENT_BUFFER) then 139 | begin 140 | // Allocate buffer 141 | GetMem(Buffer, BufferSize); 142 | try 143 | // Call GetLogicalProcessorInformation again with allocated buffer 144 | if GetLogicalProcessorInformation(Buffer, BufferSize) then 145 | begin 146 | ProcessorInfo := Buffer; 147 | Offset := 0; 148 | 149 | // Loop through processor information to count physical processors 150 | while Offset + SizeOf(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= BufferSize do 151 | begin 152 | if ProcessorInfo.Relationship = RelationProcessorCore then 153 | Inc(Result); 154 | 155 | Inc(ProcessorInfo); 156 | Inc(Offset, SizeOf(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); 157 | end; 158 | end; 159 | finally 160 | FreeMem(Buffer); 161 | end; 162 | end; 163 | end; 164 | 165 | function SanitizeToJson(const aText: string): string; 166 | var 167 | i: Integer; 168 | begin 169 | Result := ''; 170 | for i := 1 to Length(aText) do 171 | begin 172 | case aText[i] of 173 | '\': Result := Result + '\\'; 174 | '"': Result := Result + '\"'; 175 | '/': Result := Result + '\/'; 176 | #8: Result := Result + '\b'; 177 | #9: Result := Result + '\t'; 178 | #10: Result := Result + '\n'; 179 | #12: Result := Result + '\f'; 180 | #13: Result := Result + '\r'; 181 | else 182 | Result := Result + aText[i]; 183 | end; 184 | end; 185 | Result := Result; 186 | end; 187 | 188 | function SanitizeFromJson(const aText: string): string; 189 | var 190 | LText: string; 191 | begin 192 | LText := aText; 193 | LText := LText.Replace('\n', #10); 194 | LText := LText.Replace('\r', #13); 195 | LText := LText.Replace('\b', #8); 196 | LText := LText.Replace('\t', #9); 197 | LText := LText.Replace('\f', #12); 198 | LText := LText.Replace('\/', '/'); 199 | LText := LText.Replace('\"', '"'); 200 | LText := LText.Replace('\\', '\'); 201 | Result := LText; 202 | end; 203 | 204 | function HasConsoleOutput(): Boolean; 205 | var 206 | LStdOut: THandle; 207 | LMode: DWORD; 208 | begin 209 | LStdOut := GetStdHandle(STD_OUTPUT_HANDLE); 210 | Result := (LStdOut <> INVALID_HANDLE_VALUE) and GetConsoleMode(LStdOut, LMode); 211 | end; 212 | 213 | function EnableVirtualTerminalProcessing(): DWORD; 214 | var 215 | HOut: THandle; 216 | LMode: DWORD; 217 | begin 218 | HOut := GetStdHandle(STD_OUTPUT_HANDLE); 219 | if HOut = INVALID_HANDLE_VALUE then 220 | begin 221 | Result := GetLastError; 222 | Exit; 223 | end; 224 | 225 | if not GetConsoleMode(HOut, LMode) then 226 | begin 227 | Result := GetLastError; 228 | Exit; 229 | end; 230 | 231 | LMode := LMode or ENABLE_VIRTUAL_TERMINAL_PROCESSING; 232 | if not SetConsoleMode(HOut, LMode) then 233 | begin 234 | Result := GetLastError; 235 | Exit; 236 | end; 237 | 238 | Result := 0; // Success 239 | end; 240 | 241 | { TTokenResponse } 242 | class operator TTokenResponse.Initialize (out ADest: TTokenResponse); 243 | var 244 | LSize: Integer; 245 | begin 246 | // Defaults 247 | ADest.FRaw := ''; 248 | SetLength(ADest.FTokens, 0); 249 | SetLength(ADest.FWordBreaks, 0); 250 | SetLength(ADest.FLineBreaks, 0); 251 | SetLength(ADest.FWords, 0); 252 | ADest.FWord := ''; 253 | ADest.FLine := ''; 254 | ADest.FFinalized := False; 255 | ADest.FRightMargin := 10; 256 | 257 | // If stream output is sent to a destination without wordwrap, 258 | // the TTokenResponse will find wordbreaks and split into lines by full words 259 | 260 | // Stream is tabulated into full words based on these break characters 261 | // !Syntax requires at least one! 262 | SetLength(ADest.FWordBreaks, 4); 263 | ADest.FWordBreaks[0] := ' '; 264 | ADest.FWordBreaks[1] := '-'; 265 | ADest.FWordBreaks[2] := ','; 266 | ADest.FWordBreaks[3] := '.'; 267 | 268 | // Stream may contain forced line breaks 269 | // !Syntax requires at least one! 270 | SetLength(ADest.FLineBreaks, 2); 271 | ADest.FLineBreaks[0] := #13; 272 | ADest.FLineBreaks[1] := #10; 273 | 274 | 275 | ADest.SetRightMargin(10); 276 | 277 | GetConsoleSize(@LSize, nil); 278 | ADest.SetMaxLineLength(LSize); 279 | end; 280 | 281 | function TTokenResponse.AddToken(const aToken: string): TTokenPrintAction; 282 | var 283 | LPrefix, LSuffix: string; 284 | begin 285 | // Keep full original response 286 | FRaw := FRaw + aToken; // As continuous string 287 | Setlength(FTokens, Length(FTokens)+1); // Make space 288 | FTokens[Length(FTokens)-1] := aToken; // As an array 289 | 290 | // Accumulate "word" 291 | FWord := FWord + aToken; 292 | 293 | // If stream contains linebreaks, print token out without added linebreaks 294 | if HandleLineBreaks(aToken) then 295 | exit(TTokenPrintAction.tpaAppend) 296 | 297 | // Check if a natural break exists, also split if word is longer than the allowed space 298 | // and print out token with or without linechange as needed 299 | else if SplitWord(FWord, LPrefix, LSuffix) or FFinalized then 300 | begin 301 | // On last call when Finalized we want access to the line change logic only 302 | // Bad design (fix on top of a fix) Would be better to separate word slipt and line logic from eachother 303 | if not FFinalized then 304 | begin 305 | Setlength(FWords, Length(FWords)+1); // Make space 306 | FWords[Length(FWords)-1] := LPrefix; // Add new word to array 307 | FWord := LSuffix; // Keep the remainder of the split 308 | end; 309 | 310 | // Word was split, so there is something that can be printed 311 | 312 | // Need for a new line? 313 | if Length(FLine) + Length(LastWord) > GetLineLengthMax() then 314 | begin 315 | Result := TTokenPrintAction.tpaNewline; 316 | FLine := LastWord; // Reset Line (will be new line and then the word) 317 | end 318 | else 319 | begin 320 | Result := TTokenPrintAction.tpaAppend; 321 | FLine := FLine + LastWord; // Append to the line 322 | end; 323 | end 324 | else 325 | begin 326 | Result := TTokenPrintAction.tpaWait; 327 | end; 328 | end; 329 | 330 | function TTokenResponse.HandleLineBreaks(const AToken: string): Boolean; 331 | var 332 | LLetter, LLineBreak: Integer; 333 | begin 334 | Result := false; 335 | 336 | for LLetter := Length(AToken) downto 1 do // We are interested in the last possible linebreak 337 | begin 338 | for LLineBReak := 0 to Length(Self.FLineBreaks)-1 do // Iterate linebreaks 339 | begin 340 | if AToken[LLetter] = FLineBreaks[LLineBreak] then // If linebreak was found 341 | begin 342 | // Split into a word by last found linechange (do note the stored word may have more linebreak) 343 | Setlength(FWords, Length(FWords)+1); // Make space 344 | FWords[Length(FWords)-1] := FWord + LeftStr(AToken, Length(AToken)-LLetter); // Add new word to array 345 | 346 | // In case aToken did not end after last LF 347 | // Word and new line will have whatever was after the last linebreak 348 | FWord := RightStr(AToken, Length(AToken)-LLetter); 349 | FLine := FWord; 350 | 351 | // No need to go further 352 | exit(true); 353 | end; 354 | end; 355 | end; 356 | end; 357 | 358 | function TTokenResponse.Finalize: Boolean; 359 | begin 360 | // Buffer may contain something, if so make it into a word 361 | if FWord <> '' then 362 | begin 363 | Setlength(FWords, Length(FWords)+1); // Make space 364 | FWords[Length(FWords)-1] := FWord; // Add new word to array 365 | Self.FFinalized := True; // Remember Finalize was done (affects how last AddToken-call behaves) 366 | exit(true); 367 | end 368 | else 369 | Result := false; 370 | end; 371 | 372 | function TTokenResponse.LastWord(const ATrimLeft: Boolean): string; 373 | begin 374 | Result := FWords[Length(FWords)-1]; 375 | if ATrimLeft then 376 | Result := Result.TrimLeft; 377 | end; 378 | 379 | function TTokenResponse.SplitWord(const AWord: string; var APrefix, ASuffix: string): Boolean; 380 | var 381 | LLetter, LSeparator: Integer; 382 | begin 383 | Result := false; 384 | 385 | for LLetter := 1 to Length(AWord) do // Iterate whole word 386 | begin 387 | for LSeparator := 0 to Length(FWordBreaks)-1 do // Iterate all separating characters 388 | begin 389 | if AWord[LLetter] = FWordBreaks[LSeparator] then // check for natural break 390 | begin 391 | // Let the world know there's stuff that can be a reason for a line change 392 | Result := True; 393 | 394 | APrefix := LeftStr(AWord, LLetter); 395 | ASuffix := RightStr(AWord, Length(AWord)-LLetter); 396 | end; 397 | end; 398 | end; 399 | 400 | // Maybe the word is too long but there was no natural break, then cut it to LineLengthMax 401 | if Length(AWord) > GetLineLengthMax() then 402 | begin 403 | Result := True; 404 | APrefix := LeftStr(AWord, GetLineLengthMax()); 405 | ASuffix := RightStr(AWord, Length(AWord)-GetLineLengthMax()); 406 | end; 407 | end; 408 | 409 | (* 410 | 411 | function TTokenResponse.GetLineLengthMax(): Integer; 412 | begin 413 | GetConsoleSize(@Result, nil); 414 | Result := Result - FRightMargin; 415 | end; 416 | 417 | procedure TTokenResponse.SetRightMargin(const AMargin: Integer); 418 | var 419 | LWidth: Integer; 420 | begin 421 | GetConsoleSize(@LWidth, nil); 422 | FRightMargin := EnsureRange(AMargin, 1, LWidth); 423 | end; 424 | *) 425 | 426 | function TTokenResponse.GetLineLengthMax(): Integer; 427 | begin 428 | Result := FMaxLineLength - FRightMargin; 429 | end; 430 | 431 | procedure TTokenResponse.SetRightMargin(const AMargin: Integer); 432 | begin 433 | FRightMargin := AMargin; 434 | end; 435 | 436 | procedure TTokenResponse.SetMaxLineLength(const ALength: Integer); 437 | begin 438 | FMaxLineLength := ALength; 439 | end; 440 | 441 | end. 442 | -------------------------------------------------------------------------------- /src/JetInfero.dpr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/src/JetInfero.dpr -------------------------------------------------------------------------------- /src/JetInfero.dproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | {649BE30B-8133-42D3-BAE9-CB7322CF95B0} 4 | 20.3 5 | None 6 | True 7 | Release 8 | Win64 9 | JetInfero 10 | 2 11 | Library 12 | JetInfero.dpr 13 | 14 | 15 | true 16 | 17 | 18 | true 19 | Base 20 | true 21 | 22 | 23 | true 24 | Base 25 | true 26 | 27 | 28 | true 29 | Base 30 | true 31 | 32 | 33 | true 34 | Cfg_1 35 | true 36 | true 37 | 38 | 39 | true 40 | Cfg_1 41 | true 42 | true 43 | 44 | 45 | true 46 | Base 47 | true 48 | 49 | 50 | true 51 | Cfg_2 52 | true 53 | true 54 | 55 | 56 | .\$(Platform)\$(Config) 57 | .\$(Platform)\$(Config) 58 | false 59 | false 60 | false 61 | false 62 | false 63 | true 64 | System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) 65 | JetInfero 66 | 67 | 68 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;Skia.Package.FMX;FireDACOracleDriver;fmxdae;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;inetstn;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 69 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 70 | Debug 71 | true 72 | CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 73 | 1033 74 | 75 | 76 | vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;vclactnband;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;inetstn;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;fmxobj;bindcompvclsmp;DataSnapNativeClient;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage) 77 | Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) 78 | Debug 79 | true 80 | CompanyName=tinyBigGAMES™ LLC;FileDescription=JetInfero™;FileVersion=0.1.0.0;InternalName=JetInfero™;LegalCopyright=Copyright © 2024-present tinyBigGAMES™ LLC;LegalTrademarks=All Rights Reserved.;OriginalFilename=JetInfero.dll;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=JetInfero™;ProductVersion=1.0.0.0;Comments=https://github.com/tinyBigGAMES/JetInfero 81 | 1033 82 | ..\bin 83 | 0 84 | 1 85 | true 86 | (None) 87 | none 88 | 89 | 90 | DEBUG;$(DCC_Define) 91 | true 92 | false 93 | true 94 | true 95 | true 96 | true 97 | true 98 | 99 | 100 | false 101 | 102 | 103 | true 104 | 1033 105 | 0 106 | 1 107 | true 108 | 109 | 110 | false 111 | RELEASE;$(DCC_Define) 112 | 0 113 | 0 114 | 115 | 116 | true 117 | 0 118 | 1 119 | true 120 | 1033 121 | 122 | 123 | 124 | MainSource 125 | 126 | 127 | 128 | 129 | 130 | Base 131 | 132 | 133 | Cfg_1 134 | Base 135 | 136 | 137 | Cfg_2 138 | Base 139 | 140 | 141 | 142 | Delphi.Personality.12 143 | Application 144 | 145 | 146 | 147 | JetInfero.dpr 148 | 149 | 150 | Embarcadero C++Builder Office 2000 Servers Package 151 | Embarcadero C++Builder Office XP Servers Package 152 | Microsoft Office 2000 Sample Automation Server Wrapper Components 153 | Microsoft Office XP Sample Automation Server Wrapper Components 154 | 155 | 156 | 157 | 158 | 159 | true 160 | 161 | 162 | 163 | 164 | true 165 | 166 | 167 | 168 | 169 | true 170 | 171 | 172 | 173 | 174 | JetInfero.dll 175 | true 176 | 177 | 178 | 179 | 180 | JetInfero.dll 181 | true 182 | 183 | 184 | 185 | 186 | 1 187 | 188 | 189 | Contents\MacOS 190 | 1 191 | 192 | 193 | 0 194 | 195 | 196 | 197 | 198 | res\xml 199 | 1 200 | 201 | 202 | res\xml 203 | 1 204 | 205 | 206 | 207 | 208 | library\lib\armeabi 209 | 1 210 | 211 | 212 | library\lib\armeabi 213 | 1 214 | 215 | 216 | 217 | 218 | library\lib\armeabi-v7a 219 | 1 220 | 221 | 222 | 223 | 224 | library\lib\mips 225 | 1 226 | 227 | 228 | library\lib\mips 229 | 1 230 | 231 | 232 | 233 | 234 | library\lib\armeabi-v7a 235 | 1 236 | 237 | 238 | library\lib\arm64-v8a 239 | 1 240 | 241 | 242 | 243 | 244 | library\lib\armeabi-v7a 245 | 1 246 | 247 | 248 | 249 | 250 | res\drawable 251 | 1 252 | 253 | 254 | res\drawable 255 | 1 256 | 257 | 258 | 259 | 260 | res\drawable-anydpi-v21 261 | 1 262 | 263 | 264 | res\drawable-anydpi-v21 265 | 1 266 | 267 | 268 | 269 | 270 | res\values 271 | 1 272 | 273 | 274 | res\values 275 | 1 276 | 277 | 278 | 279 | 280 | res\values-v21 281 | 1 282 | 283 | 284 | res\values-v21 285 | 1 286 | 287 | 288 | 289 | 290 | res\values-v31 291 | 1 292 | 293 | 294 | res\values-v31 295 | 1 296 | 297 | 298 | 299 | 300 | res\drawable-anydpi-v26 301 | 1 302 | 303 | 304 | res\drawable-anydpi-v26 305 | 1 306 | 307 | 308 | 309 | 310 | res\drawable 311 | 1 312 | 313 | 314 | res\drawable 315 | 1 316 | 317 | 318 | 319 | 320 | res\drawable 321 | 1 322 | 323 | 324 | res\drawable 325 | 1 326 | 327 | 328 | 329 | 330 | res\drawable 331 | 1 332 | 333 | 334 | res\drawable 335 | 1 336 | 337 | 338 | 339 | 340 | res\drawable-anydpi-v33 341 | 1 342 | 343 | 344 | res\drawable-anydpi-v33 345 | 1 346 | 347 | 348 | 349 | 350 | res\values 351 | 1 352 | 353 | 354 | res\values 355 | 1 356 | 357 | 358 | 359 | 360 | res\values-night-v21 361 | 1 362 | 363 | 364 | res\values-night-v21 365 | 1 366 | 367 | 368 | 369 | 370 | res\drawable 371 | 1 372 | 373 | 374 | res\drawable 375 | 1 376 | 377 | 378 | 379 | 380 | res\drawable-xxhdpi 381 | 1 382 | 383 | 384 | res\drawable-xxhdpi 385 | 1 386 | 387 | 388 | 389 | 390 | res\drawable-xxxhdpi 391 | 1 392 | 393 | 394 | res\drawable-xxxhdpi 395 | 1 396 | 397 | 398 | 399 | 400 | res\drawable-ldpi 401 | 1 402 | 403 | 404 | res\drawable-ldpi 405 | 1 406 | 407 | 408 | 409 | 410 | res\drawable-mdpi 411 | 1 412 | 413 | 414 | res\drawable-mdpi 415 | 1 416 | 417 | 418 | 419 | 420 | res\drawable-hdpi 421 | 1 422 | 423 | 424 | res\drawable-hdpi 425 | 1 426 | 427 | 428 | 429 | 430 | res\drawable-xhdpi 431 | 1 432 | 433 | 434 | res\drawable-xhdpi 435 | 1 436 | 437 | 438 | 439 | 440 | res\drawable-mdpi 441 | 1 442 | 443 | 444 | res\drawable-mdpi 445 | 1 446 | 447 | 448 | 449 | 450 | res\drawable-hdpi 451 | 1 452 | 453 | 454 | res\drawable-hdpi 455 | 1 456 | 457 | 458 | 459 | 460 | res\drawable-xhdpi 461 | 1 462 | 463 | 464 | res\drawable-xhdpi 465 | 1 466 | 467 | 468 | 469 | 470 | res\drawable-xxhdpi 471 | 1 472 | 473 | 474 | res\drawable-xxhdpi 475 | 1 476 | 477 | 478 | 479 | 480 | res\drawable-xxxhdpi 481 | 1 482 | 483 | 484 | res\drawable-xxxhdpi 485 | 1 486 | 487 | 488 | 489 | 490 | res\drawable-small 491 | 1 492 | 493 | 494 | res\drawable-small 495 | 1 496 | 497 | 498 | 499 | 500 | res\drawable-normal 501 | 1 502 | 503 | 504 | res\drawable-normal 505 | 1 506 | 507 | 508 | 509 | 510 | res\drawable-large 511 | 1 512 | 513 | 514 | res\drawable-large 515 | 1 516 | 517 | 518 | 519 | 520 | res\drawable-xlarge 521 | 1 522 | 523 | 524 | res\drawable-xlarge 525 | 1 526 | 527 | 528 | 529 | 530 | res\values 531 | 1 532 | 533 | 534 | res\values 535 | 1 536 | 537 | 538 | 539 | 540 | res\drawable-anydpi-v24 541 | 1 542 | 543 | 544 | res\drawable-anydpi-v24 545 | 1 546 | 547 | 548 | 549 | 550 | res\drawable 551 | 1 552 | 553 | 554 | res\drawable 555 | 1 556 | 557 | 558 | 559 | 560 | res\drawable-night-anydpi-v21 561 | 1 562 | 563 | 564 | res\drawable-night-anydpi-v21 565 | 1 566 | 567 | 568 | 569 | 570 | res\drawable-anydpi-v31 571 | 1 572 | 573 | 574 | res\drawable-anydpi-v31 575 | 1 576 | 577 | 578 | 579 | 580 | res\drawable-night-anydpi-v31 581 | 1 582 | 583 | 584 | res\drawable-night-anydpi-v31 585 | 1 586 | 587 | 588 | 589 | 590 | 1 591 | 592 | 593 | Contents\MacOS 594 | 1 595 | 596 | 597 | 0 598 | 599 | 600 | 601 | 602 | Contents\MacOS 603 | 1 604 | .framework 605 | 606 | 607 | Contents\MacOS 608 | 1 609 | .framework 610 | 611 | 612 | Contents\MacOS 613 | 1 614 | .framework 615 | 616 | 617 | 0 618 | 619 | 620 | 621 | 622 | 1 623 | .dylib 624 | 625 | 626 | 1 627 | .dylib 628 | 629 | 630 | 1 631 | .dylib 632 | 633 | 634 | Contents\MacOS 635 | 1 636 | .dylib 637 | 638 | 639 | Contents\MacOS 640 | 1 641 | .dylib 642 | 643 | 644 | Contents\MacOS 645 | 1 646 | .dylib 647 | 648 | 649 | 0 650 | .dll;.bpl 651 | 652 | 653 | 654 | 655 | 1 656 | .dylib 657 | 658 | 659 | 1 660 | .dylib 661 | 662 | 663 | 1 664 | .dylib 665 | 666 | 667 | Contents\MacOS 668 | 1 669 | .dylib 670 | 671 | 672 | Contents\MacOS 673 | 1 674 | .dylib 675 | 676 | 677 | Contents\MacOS 678 | 1 679 | .dylib 680 | 681 | 682 | 0 683 | .bpl 684 | 685 | 686 | 687 | 688 | 0 689 | 690 | 691 | 0 692 | 693 | 694 | 0 695 | 696 | 697 | 0 698 | 699 | 700 | 0 701 | 702 | 703 | Contents\Resources\StartUp\ 704 | 0 705 | 706 | 707 | Contents\Resources\StartUp\ 708 | 0 709 | 710 | 711 | Contents\Resources\StartUp\ 712 | 0 713 | 714 | 715 | 0 716 | 717 | 718 | 719 | 720 | 1 721 | 722 | 723 | 1 724 | 725 | 726 | 727 | 728 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 729 | 1 730 | 731 | 732 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 733 | 1 734 | 735 | 736 | 737 | 738 | ..\ 739 | 1 740 | 741 | 742 | ..\ 743 | 1 744 | 745 | 746 | ..\ 747 | 1 748 | 749 | 750 | 751 | 752 | Contents 753 | 1 754 | 755 | 756 | Contents 757 | 1 758 | 759 | 760 | Contents 761 | 1 762 | 763 | 764 | 765 | 766 | Contents\Resources 767 | 1 768 | 769 | 770 | Contents\Resources 771 | 1 772 | 773 | 774 | Contents\Resources 775 | 1 776 | 777 | 778 | 779 | 780 | library\lib\armeabi-v7a 781 | 1 782 | 783 | 784 | library\lib\arm64-v8a 785 | 1 786 | 787 | 788 | 1 789 | 790 | 791 | 1 792 | 793 | 794 | 1 795 | 796 | 797 | 1 798 | 799 | 800 | Contents\MacOS 801 | 1 802 | 803 | 804 | Contents\MacOS 805 | 1 806 | 807 | 808 | Contents\MacOS 809 | 1 810 | 811 | 812 | 0 813 | 814 | 815 | 816 | 817 | library\lib\armeabi-v7a 818 | 1 819 | 820 | 821 | 822 | 823 | 1 824 | 825 | 826 | 1 827 | 828 | 829 | 1 830 | 831 | 832 | 833 | 834 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 835 | 1 836 | 837 | 838 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 839 | 1 840 | 841 | 842 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 843 | 1 844 | 845 | 846 | 847 | 848 | ..\ 849 | 1 850 | 851 | 852 | ..\ 853 | 1 854 | 855 | 856 | ..\ 857 | 1 858 | 859 | 860 | 861 | 862 | 1 863 | 864 | 865 | 1 866 | 867 | 868 | 1 869 | 870 | 871 | 872 | 873 | ..\$(PROJECTNAME).launchscreen 874 | 64 875 | 876 | 877 | ..\$(PROJECTNAME).launchscreen 878 | 64 879 | 880 | 881 | 882 | 883 | 1 884 | 885 | 886 | 1 887 | 888 | 889 | 1 890 | 891 | 892 | 893 | 894 | Assets 895 | 1 896 | 897 | 898 | Assets 899 | 1 900 | 901 | 902 | 903 | 904 | Assets 905 | 1 906 | 907 | 908 | Assets 909 | 1 910 | 911 | 912 | 913 | 914 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 915 | 1 916 | 917 | 918 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 919 | 1 920 | 921 | 922 | 923 | 924 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 925 | 1 926 | 927 | 928 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 929 | 1 930 | 931 | 932 | 933 | 934 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 935 | 1 936 | 937 | 938 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 939 | 1 940 | 941 | 942 | 943 | 944 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 945 | 1 946 | 947 | 948 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 949 | 1 950 | 951 | 952 | 953 | 954 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 955 | 1 956 | 957 | 958 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 959 | 1 960 | 961 | 962 | 963 | 964 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 965 | 1 966 | 967 | 968 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 969 | 1 970 | 971 | 972 | 973 | 974 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 975 | 1 976 | 977 | 978 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 979 | 1 980 | 981 | 982 | 983 | 984 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 985 | 1 986 | 987 | 988 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 989 | 1 990 | 991 | 992 | 993 | 994 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 995 | 1 996 | 997 | 998 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 999 | 1 1000 | 1001 | 1002 | 1003 | 1004 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1005 | 1 1006 | 1007 | 1008 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1009 | 1 1010 | 1011 | 1012 | 1013 | 1014 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1015 | 1 1016 | 1017 | 1018 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1019 | 1 1020 | 1021 | 1022 | 1023 | 1024 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1025 | 1 1026 | 1027 | 1028 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1029 | 1 1030 | 1031 | 1032 | 1033 | 1034 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1035 | 1 1036 | 1037 | 1038 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1039 | 1 1040 | 1041 | 1042 | 1043 | 1044 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1045 | 1 1046 | 1047 | 1048 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1049 | 1 1050 | 1051 | 1052 | 1053 | 1054 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1055 | 1 1056 | 1057 | 1058 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1059 | 1 1060 | 1061 | 1062 | 1063 | 1064 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1065 | 1 1066 | 1067 | 1068 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1069 | 1 1070 | 1071 | 1072 | 1073 | 1074 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1075 | 1 1076 | 1077 | 1078 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1079 | 1 1080 | 1081 | 1082 | 1083 | 1084 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1085 | 1 1086 | 1087 | 1088 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1089 | 1 1090 | 1091 | 1092 | 1093 | 1094 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1095 | 1 1096 | 1097 | 1098 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1099 | 1 1100 | 1101 | 1102 | 1103 | 1104 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1105 | 1 1106 | 1107 | 1108 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1109 | 1 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | False 1127 | True 1128 | 1129 | 1130 | 12 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | -------------------------------------------------------------------------------- /src/JetInfero.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/JetInfero/afbb2474c72149f45d1ba8b6ae03d163e157172b/src/JetInfero.res -------------------------------------------------------------------------------- /virustotal.txt: -------------------------------------------------------------------------------- 1 | VirtusTotal report for JetInfero Project 2 | ======================================== 3 | 4 | We are pleased to include a VirusTotal report for this project to ensure 5 | transparency and trust. Every effort is made to deliver software that is both 6 | safe and free of viruses. However, despite our rigorous testing and security 7 | measures, there is always a possibility that virus scanners may flag the files 8 | as a false positive. We appreciate your understanding and encourage you to 9 | review the VirusTotal report for your assurance. Should you have any concerns 10 | or reservations, please do not hesitate to reach out to us. 11 | 12 | JetInfero.CLibs.res - https://www.virustotal.com/gui/file/885b1ec23e926a65716dbab84359ee39b625b8252f29a80b8ead88e7c15efa05 13 | JetInfero.dll - https://www.virustotal.com/gui/file/c661c0007799a028d8675c7323467f1a3bc7677f59aa7b789e8ff31e8009dbdb 14 | --------------------------------------------------------------------------------