├── src ├── Lumina.res └── Lumina - Local Generative AI.groupproj ├── media ├── delphi.png └── lumina.png ├── examples └── testbed │ ├── Testbed.dpr │ ├── Testbed.res │ ├── Testbed_Icon.ico │ ├── UTestbed.pas │ └── Testbed.dproj ├── virustotal.txt ├── .github └── FUNDING.yml ├── LICENSE ├── .gitignore └── README.md /src/Lumina.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/Lumina/HEAD/src/Lumina.res -------------------------------------------------------------------------------- /media/delphi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/Lumina/HEAD/media/delphi.png -------------------------------------------------------------------------------- /media/lumina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/Lumina/HEAD/media/lumina.png -------------------------------------------------------------------------------- /examples/testbed/Testbed.dpr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/Lumina/HEAD/examples/testbed/Testbed.dpr -------------------------------------------------------------------------------- /examples/testbed/Testbed.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/Lumina/HEAD/examples/testbed/Testbed.res -------------------------------------------------------------------------------- /examples/testbed/Testbed_Icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tinyBigGAMES/Lumina/HEAD/examples/testbed/Testbed_Icon.ico -------------------------------------------------------------------------------- /virustotal.txt: -------------------------------------------------------------------------------- 1 | VirtusTotal report for Lumina Project 2 | ===================================== 3 | 4 | Lumina.res: https://www.virustotal.com/gui/file/09dc6958d085c412dd8c6ec31f610700795f051f684fedff1cfe47096da70879 5 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /src/Lumina - Local Generative AI.groupproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {4EA3BFB9-BDA4-4113-883A-17BBCD36DA33} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Default.Personality.12 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /.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 | zip_latest_commit.cmd 83 | Lumina.zip 84 | *.dsv 85 | examples/testbed/Testbed.dsv 86 | bin/example.db 87 | bin/test02.db 88 | 89 | bin/test04.db 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Lumina](media/lumina.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 | # 🌟 Lumina: Advanced Local Generative AI for Delphi Developers 💻🤖 6 | 7 | Lumina offers a cutting-edge 🛠️ for Delphi developers to seamlessly integrate advanced generative AI capabilities into their 📱. Built on the computational backbone of **llama.cpp** 🐪, Lumina prioritizes data privacy 🔒, performance ⚡, and a user-friendly API 📚, making it a powerful tool for local AI inference 🤖. 8 | 9 | ## 🧐 Why Choose Lumina? 10 | 11 | - **Localized Processing** 🏠: Operates entirely offline, ensuring sensitive data remains confidential 🛡️ while offering complete computational control 🧠. 12 | - **Broad Model Compatibility** 🌐: Supports **GGUF models** compliant with llama.cpp standards, granting access to diverse AI architectures 🧩. 13 | - **Intuitive Development Interface** 🎛️: A concise, flexible API simplifies model management 🗂️, inference execution 🧮, and callback customization 🎚️, minimizing implementation complexity. 14 | - **Future-Ready Scalability** 🚀: This release emphasizes stability 🏗️ and foundational features, with plans for multi-turn conversation 💬 and retrieval-augmented generation (RAG) 🔍 in future updates. 15 | 16 | ## 🛠️ Key Functionalities 17 | 18 | ### 🤖 Advanced AI Integration 19 | 20 | Lumina expands your development toolkit 🎒 with capabilities such as: 21 | - Dynamic chatbot creation 💬. 22 | - Automated text generation 📝 and summarization 📰. 23 | - Context-sensitive content generation ✍️. 24 | - Real-time inference for adaptive processes ⚡. 25 | 26 | ### 🔒 Privacy-Driven AI Execution 27 | 28 | - Operates independently of external networks 🛡️, guaranteeing data security. 29 | - Uses Vulkan 🖥️ for optional GPU acceleration to enhance performance. 30 | 31 | ### ⚙️ Performance Optimization 32 | 33 | - Configurable GPU utilization through the `AGPULayers` parameter 🧩. 34 | - Dynamic thread allocation based on hardware capabilities 🖥️ via `AMaxThreads`. 35 | - Comprehensive performance metrics 📊, offering insights into throughput 📈 and efficiency. 36 | 37 | ### 🔗 Streamlined Integration 38 | 39 | - Embedded dependencies eliminate the need for external libraries 📦. 40 | - Lightweight architecture (~2.5MB overhead) ensures broad deployment compatibility 🌍. 41 | 42 | ## 📥 Installation 43 | 44 | 1. **Download the Repository** 📦 45 | - [Download here](https://github.com/tinyBigGAMES/Lumina/archive/refs/heads/main.zip) and extract the files to your preferred directory 📂. 46 | 47 | 2. **Acquire a GGUF Model** 🧠 48 | - Obtain a model from [Hugging Face](https://huggingface.co), such as [Gemma 2.2B GGUF (Q8_0)](https://huggingface.co/bartowski/gemma-2-2b-it-abliterated-GGUF/resolve/main/gemma-2-2b-it-abliterated-Q8_0.gguf?download=true). Save it to a directory accessible to your application (e.g., `C:/LLM/GGUF`) 💾. 49 | 50 | 3. **Ensure GPU Compatibility** 🎮 51 | - Verify Vulkan compatibility for enhanced performance ⚡. Adjust `AGPULayers` as needed to accommodate VRAM limitations 📉. 52 | 53 | 4. **✨ TLumina Class** 54 | - 📜 Add `Lumina` to your `uses` section. 55 | - 🛠️ Create an instance of `TLumina`. 56 | - 🚀 All functionality will then be at your disposal. That simple! 🎉 57 | 58 | 5. **Explore Examples** 🔍 59 | - Check the `examples` directory for detailed usage demonstrations 📚. 60 | 61 | ## 🛠️ Usage 62 | 63 | ### 🔧 Basic Setup 64 | 65 | Integrate Lumina into your Delphi project 🖥️: 66 | 67 | ```delphi 68 | var 69 | Lumina: TLumina; 70 | begin 71 | Lumina := TLumina.Create; 72 | try 73 | if Lumina.LoadModel('C:\LLM\GGUF\gemma-2-2b-it-abliterated-Q8_0.gguf', 74 | '', 8192, -1, 8) then 75 | begin 76 | if Lumina.SimpleInference('What is the capital of Italy?') then 77 | WriteLn('Inference completed successfully.') 78 | else 79 | WriteLn('Error: ', Lumina.GetError); 80 | end; 81 | finally 82 | Lumina.Free; 83 | end; 84 | end; 85 | ``` 86 | 87 | ### 🎚️ Customizing Callbacks 88 | 89 | Define custom behavior using Lumina’s callback functions 🛠️: 90 | 91 | ```delphi 92 | procedure NextTokenCallback(const AToken: string; const AUserData: Pointer); 93 | begin 94 | Write(AToken); 95 | end; 96 | 97 | Lumina.SetNextTokenCallback(NextTokenCallback, nil); 98 | ``` 99 | 100 | ## 📖 API Reference 101 | 102 | ### 🧩 Core Methods 103 | 104 | - **LoadModel** 📂 105 | - Parameters: 106 | - `AModelFilename`: Path to the GGUF model file 📄. 107 | - `ATemplate`: Optional inference template 📝. 108 | - `AMaxContext`: Maximum context size (default: 512) 🧠. 109 | - `AGPULayers`: GPU layer configuration (-1 for maximum) 🎮. 110 | - `AMaxThreads`: Number of CPU threads allocated 🖥️. 111 | - Returns a boolean indicating success ✅. 112 | 113 | - **SimpleInference** 🧠 114 | - Accepts a single query for immediate processing 📝. 115 | - Returns a boolean indicating success ✅. 116 | 117 | - **SetNextTokenCallback** 💬 118 | - Assigns a handler to process tokens during inference 🧩. 119 | 120 | - **UnloadModel** ❌ 121 | - Frees resources allocated during model loading 🗑️. 122 | 123 | - **GetPerformanceResult** 📊 124 | - Provides metrics, including token generation rates 📈. 125 | 126 | ## 🛠️ Advanced Configurations 127 | 128 | ### 🧠 Custom Inference Templates 129 | 130 | Lumina will use the template defined in the model's meta data by default, but you can also define custom templates to match your model’s requirements or change its behavor. These are some common model templates ✍️: 131 | 132 | ```delphi 133 | const 134 | CHATML_TEMPLATE = '<|im_start|>{role} {content}<|im_end|><|im_start|>assistant'; 135 | GEMMA_TEMPLATE = '{role} {content}'; 136 | PHI_TEMPLATE = '<|{role}|> {content}<|end|><|assistant|>'; 137 | ``` 138 | 139 | - **{role}** - will be replaced with the role (user, assistant, etc.) 140 | - **{content}** - will be replaced with the content sent to the model 141 | 142 | ### 🎮 GPU Optimization 143 | 144 | - `AGPULayers` values: 145 | - `-1`: Utilize all available layers (default) 🖥️. 146 | - `0`: CPU-only processing 🖥️. 147 | - Custom values for partial GPU utilization 🎛️. 148 | 149 | ### 📊 Performance Metrics 150 | 151 | Retrieve detailed operational metrics 📈: 152 | 153 | ```delphi 154 | var 155 | Perf: TLumina.PerformanceResult; 156 | begin 157 | Perf := Lumina.GetPerformanceResult; 158 | WriteLn('Tokens/Sec: ', Perf.TokensPerSecond); 159 | WriteLn('Input Tokens: ', Perf.TotalInputTokens); 160 | WriteLn('Output Tokens: ', Perf.TotalOutputTokens); 161 | end; 162 | ``` 163 | 164 | ## 🎙️ Media 165 | 166 | ### 🌊 Deep Dive Podcast 167 | Discover in-depth discussions and insights about **Lumina** and its innovative features. 🚀✨ 168 | 169 | https://github.com/user-attachments/assets/165e3dee-b29f-4478-b9ef-4fb6d2df2485 170 | 171 | 172 | ### 🛠️ Support and Resources 173 | 174 | - Report issues via the [Issue Tracker](https://github.com/tinyBigGAMES/Lumina/issues) 🐞. 175 | - Engage in discussions on the [Forum](https://github.com/tinyBigGAMES/Lumina/discussions) and [Discord](https://discord.gg/tPWjMwK) 💬. 176 | - Learn more at [Learn Delphi](https://learndelphi.org) 📚. 177 | 178 | ### 🤝 Contributing 179 | 180 | Contributions to **✨ Lumina** are highly encouraged! 🌟 181 | - 🐛 **Report Issues:** Submit issues if you encounter bugs or need help. 182 | - 💡 **Suggest Features:** Share your ideas to make **Lumina** even better. 183 | - 🔧 **Create Pull Requests:** Help expand the capabilities and robustness of the library. 184 | 185 | Your contributions make a difference! 🙌✨ 186 | 187 | #### Contributors 👥🤝 188 |
189 | 190 | 191 | 192 | 193 | 194 | ### 📜 Licensing 195 | 196 | **Lumina** 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/Lumina?tab=BSD-3-Clause-1-ov-file#BSD-3-Clause-1-ov-file) file for more details. 197 | 198 | --- 199 | 200 | Advance your Delphi applications with Lumina 🌟 – a sophisticated solution for integrating local generative AI 🤖. 201 | 202 |

203 | Delphi 204 |

205 |
206 | 207 | Made with :heart: in Delphi 208 |
209 | 210 | -------------------------------------------------------------------------------- /examples/testbed/UTestbed.pas: -------------------------------------------------------------------------------- 1 | {=============================================================================== 2 | _ _ 3 | | | _ _ _ __ (_) _ _ __ _ ™ 4 | | |__ | || || ' \ | || ' \ / _` | 5 | |____| \_,_||_|_|_||_||_||_|\__,_| 6 | Local Generative AI 7 | 8 | Copyright © 2024-present tinyBigGAMES™ LLC 9 | All Rights Reserved. 10 | 11 | https://github.com/tinyBigGAMES/Lumina 12 | 13 | ===============================================================================} 14 | 15 | unit UTestbed; 16 | 17 | interface 18 | 19 | procedure RunTests(); 20 | 21 | implementation 22 | 23 | uses 24 | WinApi.Windows, 25 | System.SysUtils, 26 | System.IOUtils, 27 | System.Math, 28 | Lumina; 29 | 30 | procedure Pause(); 31 | begin 32 | WriteLn; 33 | Write('Press ENTER to continue...'); 34 | ReadLn; 35 | WriteLn; 36 | end; 37 | 38 | procedure InfoCallback(const AText: string; const AUserData: Pointer); 39 | var 40 | LLumina: TLumina; 41 | begin 42 | LLumina := TLumina(AUserData); 43 | if not Assigned(LLumina) then Exit; 44 | 45 | // Uncomment to display model info 46 | //LLumina.Print(AText, []); 47 | end; 48 | 49 | procedure ProgressCallback(const AModelFilename: string; const AProgress: Single; const AUserData: Pointer); 50 | var 51 | LLumina: TLumina; 52 | begin 53 | LLumina := TLumina(AUserData); 54 | if not Assigned(LLumina) then Exit; 55 | 56 | LLumina.Print(#13+'Loading %s(%3.2f%%)...', [AModelFilename, AProgress]); 57 | if AProgress >= 100 then 58 | begin 59 | // clear line 60 | LLumina.Print(#13 + #27 + '[K', []); 61 | end; 62 | end; 63 | 64 | function CancelCallback(const AUserData: Pointer): Boolean; 65 | begin 66 | Result := Boolean(GetAsyncKeyState(VK_ESCAPE) <> 0); 67 | end; 68 | 69 | const 70 | function_call1 = 71 | ''' 72 | Cutting Knowledge Date: December 2023 73 | Today Date: 23 July 2024 74 | 75 | When you receive a tool call response, use the output to format an answer to the orginal user question. 76 | 77 | You are a helpful assistant with tool calling capabilities.<|eot_id|><|start_header_id|>user<|end_header_id|> 78 | 79 | Given the following functions, please respond with a JSON for a function call with its proper arguments that best answers the given prompt. 80 | 81 | Respond in the format {"name": function name, "parameters": dictionary of argument name and its value}. Do not use variables. 82 | 83 | { 84 | "type": "function", 85 | "function": { 86 | "name": "get_current_conditions", 87 | "description": "Get the current weather conditions for a specific location", 88 | "parameters": { 89 | "type": "object", 90 | "properties": { 91 | "location": { 92 | "type": "string", 93 | "description": "The city and state, e.g., San Francisco, CA" 94 | }, 95 | "unit": { 96 | "type": "string", 97 | "enum": ["Celsius", "Fahrenheit"], 98 | "description": "The temperature unit to use. Infer this from the user's location." 99 | } 100 | }, 101 | "required": ["location", "unit"] 102 | } 103 | } 104 | } 105 | 106 | Question: what is the weather like in San Fransisco? 107 | '''; 108 | 109 | function_call2 = 110 | ''' 111 | You are an expert in composing functions. You are given a question and a set of possible functions. 112 | Based on the question, you will need to make one or more function/tool calls to achieve the purpose. 113 | If none of the functions can be used, point it out. If the given question lacks the parameters required by the function,also point it out. You should only return the function call in tools call sections. 114 | If you decide to invoke any of the function(s), you MUST respond in the format of [func_name1(params_name1=params_value1, params_name2=params_value2...), func_name2(params)] 115 | 116 | Here is a list of functions in JSON format that you can invoke. 117 | [ 118 | { 119 | "name": "get_user_info", 120 | "description": "Retrieve details for a specific user by their unique identifier. Note that the provided function is in Python 3 syntax.", 121 | "parameters": { 122 | "type": "dict", 123 | "required": [ 124 | "user_id" 125 | ], 126 | "properties": { 127 | "user_id": { 128 | "type": "integer", 129 | "description": "The unique identifier of the user. It is used to fetch the specific user details from the database." 130 | }, 131 | "special": { 132 | "type": "string", 133 | "description": "Any special information or parameters that need to be considered while fetching user details.", 134 | "default": "none" 135 | } 136 | } 137 | } 138 | } 139 | ] 140 | 141 | 142 | Can you retrieve the details for the user with the ID 7890, who has black as their special request? 143 | Can you retrieve the details for the user with the ID 6889, who has white as their special request? 144 | Can you retrieve the details for the user with the ID 1000, who has red as their special request? 145 | 146 | '''; 147 | 148 | procedure Test01(); 149 | var 150 | LLumina: TLumina; 151 | LPerf: TLumina.PerformanceResult; 152 | LQuestion: string; 153 | LModel: string; 154 | LAddAssistant: Boolean; 155 | begin 156 | //LQuestion := function_call2; 157 | LQuestion := 'what is AI?'; 158 | 159 | //LQuestion := 'What happen in feb 2023 according to your knowledge?'; 160 | //LQuestion := 'who is bill gates?'; 161 | //LQuestion := 'what is KNO3?'; 162 | //LQuestion := 'hello in: spanish, japanese, chinese'; 163 | //LQuestion := 'how to make KNO3? (detailed steps)'; 164 | 165 | LModel := 'C:/LLM/GGUF/gemma-2-2b-it-abliterated-Q8_0.gguf'; 166 | LAddAssistant := False; 167 | 168 | //LModel := 'C:\LLM\GGUF\hermes-3-llama-3.2-3b-abliterated-q8_0.gguf'; 169 | //LAddAssistant := True; 170 | 171 | //LModel := 'C:\LLM\GGUF\dolphin3.0-llama3.2-1b-q8_0.gguf'; 172 | //LAddAssistant := True; 173 | 174 | try 175 | LLumina := TLumina.Create(); 176 | try 177 | LLumina.SetInfoCallback(InfoCallback, LLumina); 178 | LLumina.SetProgressCallback(ProgressCallback, LLumina); 179 | LLumina.SetCancelCallback(CancelCallback, LLumina); 180 | 181 | if LLumina.LoadModel(LModel, '', 1024*8, -1, 4, LAddAssistant) then 182 | begin 183 | if LLumina.SimpleInference(LQuestion) then 184 | begin 185 | LPerf := LLumina.GetPerformanceResult(); 186 | writeln; 187 | writeln; 188 | writeln('Input Tokens: ', LPerf.TotalInputTokens); 189 | writeln('Output Tokens: ', LPerf.TotalOutputTokens); 190 | writeln('Tokens/Sec : ', LPerf.TokensPerSecond:3:2); 191 | end 192 | else 193 | begin 194 | WriteLn('Error: ', LLumina.GetError()); 195 | end; 196 | 197 | LLumina.UnloadModel(); 198 | end; 199 | finally 200 | LLumina.Free(); 201 | end; 202 | except 203 | on E: Exception do 204 | Writeln(E.ClassName, ': ', E.Message); 205 | end; 206 | end; 207 | 208 | procedure Test02(); 209 | 210 | var 211 | DB: PSQLite3; 212 | Stmt: Psqlite3_stmt; 213 | SQL: PAnsiChar; 214 | Res: Integer; 215 | 216 | procedure CheckError(Res: Integer; DB: Psqlite3); 217 | begin 218 | if Res = SQLITE_OK then exit; 219 | if Res = SQLITE_DONE then Exit; 220 | raise Exception.CreateFmt('SQLite error %d: %s', [Res, sqlite3_errmsg(DB)]); 221 | end; 222 | 223 | begin 224 | db := nil; 225 | stmt := nil; 226 | 227 | try 228 | // remove existing database 229 | DeleteFile('test02.db'); 230 | 231 | // Open database 232 | Res := sqlite3_open('test02.db', @DB); 233 | CheckError(Res, DB); 234 | 235 | try 236 | // Create table 237 | SQL := 'CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT);'; 238 | Res := sqlite3_exec(DB, SQL, nil, nil, nil); 239 | CheckError(Res, DB); 240 | 241 | // Insert data 242 | SQL := 'INSERT INTO users (name) VALUES (''John Doe'');'; 243 | Res := sqlite3_exec(DB, SQL, nil, nil, nil); 244 | CheckError(Res, DB); 245 | 246 | // Query data 247 | SQL := 'SELECT id, name FROM users;'; 248 | Res := sqlite3_prepare_v2(DB, SQL, -1, @Stmt, nil); 249 | CheckError(Res, DB); 250 | 251 | while sqlite3_step(Stmt) = SQLITE_ROW do 252 | begin 253 | WriteLn('ID: ', sqlite3_column_int(Stmt, 0)); 254 | WriteLn('Name: ', String(AnsiString(PAnsiChar(sqlite3_column_text(Stmt, 1))))); 255 | end; 256 | 257 | // Finalize statement 258 | sqlite3_finalize(Stmt); 259 | finally 260 | // Close database 261 | sqlite3_close(DB); 262 | end; 263 | 264 | except 265 | on E: Exception do 266 | Writeln(E.ClassName, ': ', E.Message); 267 | end; 268 | end; 269 | 270 | procedure Test03(); 271 | type 272 | TVector4 = array[0..3] of Single; 273 | TItem = record 274 | id: sqlite3_int64; 275 | vector: TVector4; 276 | end; 277 | 278 | const 279 | items: array[0..4] of TItem = ( 280 | (id: 1; vector: (0.1, 0.1, 0.1, 0.1)), 281 | (id: 2; vector: (0.2, 0.2, 0.2, 0.2)), 282 | (id: 3; vector: (0.3, 0.3, 0.3, 0.3)), 283 | (id: 4; vector: (0.4, 0.4, 0.4, 0.4)), 284 | (id: 5; vector: (0.5, 0.5, 0.5, 0.5)) 285 | ); 286 | 287 | query: TVector4 = (0.3, 0.3, 0.3, 0.3); 288 | var 289 | DB: Psqlite3; 290 | Stmt: Psqlite3_stmt; 291 | RC: Integer; 292 | I: Integer; 293 | ErrMsg: PAnsiChar; 294 | rowid: Int64; 295 | distance: Double; 296 | 297 | procedure AssertSQLite(rc: Integer); 298 | begin 299 | Assert(rc = SQLITE_OK); 300 | end; 301 | 302 | begin 303 | // Open in-memory database 304 | rc := sqlite3_open(':memory:', @db); 305 | AssertSQLite(rc); 306 | 307 | // Initialize SQLite vector extension 308 | rc := sqlite3_vec_init(db, @ErrMsg, nil); 309 | AssertSQLite(rc); 310 | 311 | // Check versions 312 | rc := sqlite3_prepare_v2(db, 'SELECT sqlite_version(), vec_version()', -1, @stmt, nil); 313 | AssertSQLite(rc); 314 | 315 | rc := sqlite3_step(stmt); 316 | if rc = SQLITE_ROW then 317 | WriteLn(Format('sqlite_version=%s, vec_version=%s', [ 318 | PAnsiChar(sqlite3_column_text(stmt, 0)), 319 | PAnsiChar(sqlite3_column_text(stmt, 1)) 320 | ])); 321 | sqlite3_finalize(stmt); 322 | 323 | // Create virtual table 324 | rc := sqlite3_prepare_v2(db, 325 | 'CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[4])', 326 | -1, @stmt, nil); 327 | AssertSQLite(rc); 328 | rc := sqlite3_step(stmt); 329 | Assert(rc = SQLITE_DONE); 330 | sqlite3_finalize(stmt); 331 | 332 | // Begin transaction 333 | rc := sqlite3_exec(db, 'BEGIN', nil, nil, @errMsg); 334 | AssertSQLite(rc); 335 | 336 | // Insert items 337 | rc := sqlite3_prepare_v2(db, 338 | 'INSERT INTO vec_items(rowid, embedding) VALUES (?, ?)', 339 | -1, @stmt, nil); 340 | AssertSQLite(rc); 341 | 342 | for i := Low(items) to High(items) do 343 | begin 344 | sqlite3_bind_int64(stmt, 1, items[i].id); 345 | sqlite3_bind_blob(stmt, 2, @items[i].vector, SizeOf(items[i].vector), SQLITE_STATIC); 346 | rc := sqlite3_step(stmt); 347 | Assert(rc = SQLITE_DONE); 348 | sqlite3_reset(stmt); 349 | end; 350 | sqlite3_finalize(stmt); 351 | 352 | // Commit transaction 353 | rc := sqlite3_exec(db, 'COMMIT', nil, nil, @errMsg); 354 | AssertSQLite(rc); 355 | 356 | // Query nearest neighbors 357 | rc := sqlite3_prepare_v2(db, 358 | 'SELECT ' + 359 | ' rowid, ' + 360 | ' distance ' + 361 | 'FROM vec_items ' + 362 | 'WHERE embedding MATCH ?1 ' + 363 | 'ORDER BY distance ' + 364 | 'LIMIT 3', 365 | -1, @stmt, nil); 366 | AssertSQLite(rc); 367 | 368 | sqlite3_bind_blob(stmt, 1, @query[0], SizeOf(query), SQLITE_STATIC); 369 | 370 | while True do 371 | begin 372 | rc := sqlite3_step(stmt); 373 | if rc = SQLITE_DONE then 374 | Break; 375 | Assert(rc = SQLITE_ROW); 376 | 377 | rowid := sqlite3_column_int64(stmt, 0); 378 | distance := sqlite3_column_double(stmt, 1); 379 | WriteLn(Format('rowid=%d distance=%f', [rowid, distance])); 380 | end; 381 | sqlite3_finalize(stmt); 382 | 383 | sqlite3_close(db); 384 | end; 385 | 386 | 387 | { 388 | You can download an embedding model here: 389 | https://huggingface.co/asg017/sqlite-lembed-model-examples/resolve/main/all-MiniLM-L6-v2/all-MiniLM-L6-v2.e4ce9877.q8_0.gguf 390 | Place in a desired location, for example "C:/LLM/GGUF/all-MiniLM-L6-v2.e4ce9877.q8_0.gguf" 391 | } 392 | procedure Test04(); 393 | const 394 | { 395 | CSQL1 396 | 397 | Copied from lembed readme - https://github.com/asg017/sqlite-lembed 398 | Sets up lembed to use all-MiniLM-L6-v2.gguf 399 | Creates the articles table 400 | Inserts random NPR headlines 401 | Builds a vector table with embeddings of the headlines 402 | Inserts the data into the vector table 403 | } 404 | CSQL1 = 405 | ''' 406 | INSERT INTO temp.lembed_models(name, model) 407 | select 'all-MiniLM-L6-v2', lembed_model_from_file('C:/LLM/GGUF/all-MiniLM-L6-v2.e4ce9877.q8_0.gguf'); 408 | 409 | create table articles( 410 | headline text 411 | ); 412 | 413 | -- Random NPR headlines from 2024-06-04 414 | insert into articles VALUES 415 | ('Shohei Ohtani''s ex-interpreter pleads guilty to charges related to gambling and theft'), 416 | ('The jury has been selected in Hunter Biden''s gun trial'), 417 | ('Larry Allen, a Super Bowl champion and famed Dallas Cowboy, has died at age 52'), 418 | ('After saying Charlotte, a lone stingray, was pregnant, aquarium now says she''s sick'), 419 | ('An Epoch Times executive is facing money laundering charge'); 420 | 421 | -- Build a vector table with embeddings of article headlines 422 | create virtual table vec_articles using vec0( 423 | headline_embeddings float[384] 424 | ); 425 | 426 | insert into vec_articles(rowid, headline_embeddings) 427 | select rowid, lembed('all-MiniLM-L6-v2', headline) 428 | from articles; 429 | '''; 430 | 431 | { 432 | CSQL2 433 | 434 | Semantic search example from lembed readme. 435 | Searches on "firearm courtroom" and returns results based on the join. 436 | Limits to three returned results. 437 | } 438 | const CSQL2 = 439 | ''' 440 | with matches as ( 441 | select 442 | rowid, 443 | distance 444 | from vec_articles 445 | where headline_embeddings match lembed('all-MiniLM-L6-v2', 'firearm courtroom') 446 | order by distance 447 | limit 3 448 | ) 449 | select 450 | headline, 451 | distance 452 | from matches 453 | left join articles on articles.rowid = matches.rowid; 454 | '''; 455 | 456 | var 457 | DB: PSQLite3; 458 | ErrMsg: PAnsiChar; 459 | Rc: Integer; 460 | RowNumber: Integer; 461 | stmt: Psqlite3_stmt; 462 | 463 | procedure CheckError(ResultCode: Integer; Msg: string=''); 464 | begin 465 | if ResultCode = SQLITE_OK then exit; 466 | if ResultCode = SQLITE_DONE then exit; 467 | Writeln(Msg, ': ', sqlite3_errmsg(DB)); 468 | Halt(1); 469 | end; 470 | 471 | procedure ExecuteSQL(const SQL: string); 472 | var 473 | LSQL: UTF8String; 474 | begin 475 | LSql := PAnsiChar(AnsiString(SQL)); 476 | Rc := sqlite3_exec(DB, PUTF8Char(LSql), nil, nil, @ErrMsg); 477 | if Rc <> SQLITE_OK then 478 | begin 479 | Writeln('SQL error: ', string(ErrMsg)); 480 | sqlite3_free(ErrMsg); 481 | Halt(1); 482 | end; 483 | end; 484 | 485 | begin 486 | try 487 | // Remove old file to keep test idempotent 488 | DeleteFile('test04.db'); 489 | 490 | // Open the database 491 | CheckError(sqlite3_open('test04.db', @DB)); 492 | 493 | // Initialize sqlite vec and lembed addons 494 | CheckError(sqlite3_vec_init(db, @ErrMsg, nil)); 495 | CheckError(sqlite3_lembed_init(DB, @ErrMsg, nil)); 496 | 497 | // Initial SQL, see variable comment for details of what it does 498 | ExecuteSQL(CSQL1); 499 | 500 | // SQL to perform vector search, see variable comment for the details 501 | CheckError(sqlite3_prepare_v2(DB, CSQL2, -1, @Stmt, nil)); 502 | 503 | // Loop the returned rows 504 | RowNumber := 0; 505 | while sqlite3_step(Stmt) = SQLITE_ROW do begin 506 | Write(RowNumber); 507 | Write(': '); 508 | Write(String(PAnsiChar(SQLite3_Column_Name(Stmt, 0)))); // Column name 509 | Write(': '); 510 | WriteLn(String(PAnsiChar(sqlite3_column_text(Stmt, 0)))); // Column data 511 | Inc(RowNumber); 512 | end; 513 | 514 | // Deletes the prepared statement and closes the db, part of cleanup. 515 | sqlite3_finalize(stmt); 516 | sqlite3_close(DB); 517 | 518 | Writeln('Script executed successfully.'); 519 | 520 | except 521 | on E: Exception do 522 | Writeln(E.ClassName, ': ', E.Message); 523 | end; 524 | end; 525 | 526 | procedure RunTests(); 527 | var 528 | LNum: Integer; 529 | begin 530 | LNum := 01; 531 | 532 | case LNum of 533 | 01: Test01(); 534 | 02: Test02(); 535 | 03: Test03(); 536 | 04: Test04(); 537 | end; 538 | 539 | Pause(); 540 | end; 541 | 542 | 543 | end. 544 | -------------------------------------------------------------------------------- /examples/testbed/Testbed.dproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {6293C7B8-E199-43F2-B775-4B23900449A6} 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 | RaizeComponentsVcl;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;RaizeComponentsVclDb;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 | RaizeComponentsVcl;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;RaizeComponentsVclDb;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 | Testbed_Icon.ico 86 | $(BDS)\bin\default_app.manifest 87 | PerMonitorV2 88 | ..\..\bin 89 | ..\..\src;$(DCC_UnitSearchPath) 90 | 91 | 92 | DEBUG;$(DCC_Define) 93 | true 94 | false 95 | true 96 | true 97 | true 98 | true 99 | true 100 | 101 | 102 | false 103 | 104 | 105 | 1033 106 | 107 | 108 | false 109 | RELEASE;$(DCC_Define) 110 | 0 111 | 0 112 | 113 | 114 | 1033 115 | 116 | 117 | 118 | MainSource 119 | 120 | 121 | 122 | 123 | Base 124 | 125 | 126 | Cfg_1 127 | Base 128 | 129 | 130 | Cfg_2 131 | Base 132 | 133 | 134 | 135 | Delphi.Personality.12 136 | Application 137 | 138 | 139 | 140 | Testbed.dpr 141 | 142 | 143 | Embarcadero C++Builder Office 2000 Servers Package 144 | Embarcadero C++Builder Office XP Servers Package 145 | Microsoft Office 2000 Sample Automation Server Wrapper Components 146 | Microsoft Office XP Sample Automation Server Wrapper Components 147 | 148 | 149 | 150 | 151 | 152 | true 153 | 154 | 155 | 156 | 157 | true 158 | 159 | 160 | 161 | 162 | true 163 | 164 | 165 | 166 | 167 | Testbed.exe 168 | true 169 | 170 | 171 | 172 | 173 | Testbed.exe 174 | true 175 | 176 | 177 | 178 | 179 | Testbed.rsm 180 | true 181 | 182 | 183 | 184 | 185 | 1 186 | 187 | 188 | Contents\MacOS 189 | 1 190 | 191 | 192 | 0 193 | 194 | 195 | 196 | 197 | res\xml 198 | 1 199 | 200 | 201 | res\xml 202 | 1 203 | 204 | 205 | 206 | 207 | library\lib\armeabi 208 | 1 209 | 210 | 211 | library\lib\armeabi 212 | 1 213 | 214 | 215 | 216 | 217 | library\lib\armeabi-v7a 218 | 1 219 | 220 | 221 | 222 | 223 | library\lib\mips 224 | 1 225 | 226 | 227 | library\lib\mips 228 | 1 229 | 230 | 231 | 232 | 233 | library\lib\armeabi-v7a 234 | 1 235 | 236 | 237 | library\lib\arm64-v8a 238 | 1 239 | 240 | 241 | 242 | 243 | library\lib\armeabi-v7a 244 | 1 245 | 246 | 247 | 248 | 249 | res\drawable 250 | 1 251 | 252 | 253 | res\drawable 254 | 1 255 | 256 | 257 | 258 | 259 | res\drawable-anydpi-v21 260 | 1 261 | 262 | 263 | res\drawable-anydpi-v21 264 | 1 265 | 266 | 267 | 268 | 269 | res\values 270 | 1 271 | 272 | 273 | res\values 274 | 1 275 | 276 | 277 | 278 | 279 | res\values-v21 280 | 1 281 | 282 | 283 | res\values-v21 284 | 1 285 | 286 | 287 | 288 | 289 | res\values-v31 290 | 1 291 | 292 | 293 | res\values-v31 294 | 1 295 | 296 | 297 | 298 | 299 | res\drawable-anydpi-v26 300 | 1 301 | 302 | 303 | res\drawable-anydpi-v26 304 | 1 305 | 306 | 307 | 308 | 309 | res\drawable 310 | 1 311 | 312 | 313 | res\drawable 314 | 1 315 | 316 | 317 | 318 | 319 | res\drawable 320 | 1 321 | 322 | 323 | res\drawable 324 | 1 325 | 326 | 327 | 328 | 329 | res\drawable 330 | 1 331 | 332 | 333 | res\drawable 334 | 1 335 | 336 | 337 | 338 | 339 | res\drawable-anydpi-v33 340 | 1 341 | 342 | 343 | res\drawable-anydpi-v33 344 | 1 345 | 346 | 347 | 348 | 349 | res\values 350 | 1 351 | 352 | 353 | res\values 354 | 1 355 | 356 | 357 | 358 | 359 | res\values-night-v21 360 | 1 361 | 362 | 363 | res\values-night-v21 364 | 1 365 | 366 | 367 | 368 | 369 | res\drawable 370 | 1 371 | 372 | 373 | res\drawable 374 | 1 375 | 376 | 377 | 378 | 379 | res\drawable-xxhdpi 380 | 1 381 | 382 | 383 | res\drawable-xxhdpi 384 | 1 385 | 386 | 387 | 388 | 389 | res\drawable-xxxhdpi 390 | 1 391 | 392 | 393 | res\drawable-xxxhdpi 394 | 1 395 | 396 | 397 | 398 | 399 | res\drawable-ldpi 400 | 1 401 | 402 | 403 | res\drawable-ldpi 404 | 1 405 | 406 | 407 | 408 | 409 | res\drawable-mdpi 410 | 1 411 | 412 | 413 | res\drawable-mdpi 414 | 1 415 | 416 | 417 | 418 | 419 | res\drawable-hdpi 420 | 1 421 | 422 | 423 | res\drawable-hdpi 424 | 1 425 | 426 | 427 | 428 | 429 | res\drawable-xhdpi 430 | 1 431 | 432 | 433 | res\drawable-xhdpi 434 | 1 435 | 436 | 437 | 438 | 439 | res\drawable-mdpi 440 | 1 441 | 442 | 443 | res\drawable-mdpi 444 | 1 445 | 446 | 447 | 448 | 449 | res\drawable-hdpi 450 | 1 451 | 452 | 453 | res\drawable-hdpi 454 | 1 455 | 456 | 457 | 458 | 459 | res\drawable-xhdpi 460 | 1 461 | 462 | 463 | res\drawable-xhdpi 464 | 1 465 | 466 | 467 | 468 | 469 | res\drawable-xxhdpi 470 | 1 471 | 472 | 473 | res\drawable-xxhdpi 474 | 1 475 | 476 | 477 | 478 | 479 | res\drawable-xxxhdpi 480 | 1 481 | 482 | 483 | res\drawable-xxxhdpi 484 | 1 485 | 486 | 487 | 488 | 489 | res\drawable-small 490 | 1 491 | 492 | 493 | res\drawable-small 494 | 1 495 | 496 | 497 | 498 | 499 | res\drawable-normal 500 | 1 501 | 502 | 503 | res\drawable-normal 504 | 1 505 | 506 | 507 | 508 | 509 | res\drawable-large 510 | 1 511 | 512 | 513 | res\drawable-large 514 | 1 515 | 516 | 517 | 518 | 519 | res\drawable-xlarge 520 | 1 521 | 522 | 523 | res\drawable-xlarge 524 | 1 525 | 526 | 527 | 528 | 529 | res\values 530 | 1 531 | 532 | 533 | res\values 534 | 1 535 | 536 | 537 | 538 | 539 | res\drawable-anydpi-v24 540 | 1 541 | 542 | 543 | res\drawable-anydpi-v24 544 | 1 545 | 546 | 547 | 548 | 549 | res\drawable 550 | 1 551 | 552 | 553 | res\drawable 554 | 1 555 | 556 | 557 | 558 | 559 | res\drawable-night-anydpi-v21 560 | 1 561 | 562 | 563 | res\drawable-night-anydpi-v21 564 | 1 565 | 566 | 567 | 568 | 569 | res\drawable-anydpi-v31 570 | 1 571 | 572 | 573 | res\drawable-anydpi-v31 574 | 1 575 | 576 | 577 | 578 | 579 | res\drawable-night-anydpi-v31 580 | 1 581 | 582 | 583 | res\drawable-night-anydpi-v31 584 | 1 585 | 586 | 587 | 588 | 589 | 1 590 | 591 | 592 | Contents\MacOS 593 | 1 594 | 595 | 596 | 0 597 | 598 | 599 | 600 | 601 | Contents\MacOS 602 | 1 603 | .framework 604 | 605 | 606 | Contents\MacOS 607 | 1 608 | .framework 609 | 610 | 611 | Contents\MacOS 612 | 1 613 | .framework 614 | 615 | 616 | 0 617 | 618 | 619 | 620 | 621 | 1 622 | .dylib 623 | 624 | 625 | 1 626 | .dylib 627 | 628 | 629 | 1 630 | .dylib 631 | 632 | 633 | Contents\MacOS 634 | 1 635 | .dylib 636 | 637 | 638 | Contents\MacOS 639 | 1 640 | .dylib 641 | 642 | 643 | Contents\MacOS 644 | 1 645 | .dylib 646 | 647 | 648 | 0 649 | .dll;.bpl 650 | 651 | 652 | 653 | 654 | 1 655 | .dylib 656 | 657 | 658 | 1 659 | .dylib 660 | 661 | 662 | 1 663 | .dylib 664 | 665 | 666 | Contents\MacOS 667 | 1 668 | .dylib 669 | 670 | 671 | Contents\MacOS 672 | 1 673 | .dylib 674 | 675 | 676 | Contents\MacOS 677 | 1 678 | .dylib 679 | 680 | 681 | 0 682 | .bpl 683 | 684 | 685 | 686 | 687 | 0 688 | 689 | 690 | 0 691 | 692 | 693 | 0 694 | 695 | 696 | 0 697 | 698 | 699 | 0 700 | 701 | 702 | Contents\Resources\StartUp\ 703 | 0 704 | 705 | 706 | Contents\Resources\StartUp\ 707 | 0 708 | 709 | 710 | Contents\Resources\StartUp\ 711 | 0 712 | 713 | 714 | 0 715 | 716 | 717 | 718 | 719 | 1 720 | 721 | 722 | 1 723 | 724 | 725 | 726 | 727 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 728 | 1 729 | 730 | 731 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 732 | 1 733 | 734 | 735 | 736 | 737 | ..\ 738 | 1 739 | 740 | 741 | ..\ 742 | 1 743 | 744 | 745 | ..\ 746 | 1 747 | 748 | 749 | 750 | 751 | Contents 752 | 1 753 | 754 | 755 | Contents 756 | 1 757 | 758 | 759 | Contents 760 | 1 761 | 762 | 763 | 764 | 765 | Contents\Resources 766 | 1 767 | 768 | 769 | Contents\Resources 770 | 1 771 | 772 | 773 | Contents\Resources 774 | 1 775 | 776 | 777 | 778 | 779 | library\lib\armeabi-v7a 780 | 1 781 | 782 | 783 | library\lib\arm64-v8a 784 | 1 785 | 786 | 787 | 1 788 | 789 | 790 | 1 791 | 792 | 793 | 1 794 | 795 | 796 | 1 797 | 798 | 799 | Contents\MacOS 800 | 1 801 | 802 | 803 | Contents\MacOS 804 | 1 805 | 806 | 807 | Contents\MacOS 808 | 1 809 | 810 | 811 | 0 812 | 813 | 814 | 815 | 816 | library\lib\armeabi-v7a 817 | 1 818 | 819 | 820 | 821 | 822 | 1 823 | 824 | 825 | 1 826 | 827 | 828 | 1 829 | 830 | 831 | 832 | 833 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 834 | 1 835 | 836 | 837 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 838 | 1 839 | 840 | 841 | ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF 842 | 1 843 | 844 | 845 | 846 | 847 | ..\ 848 | 1 849 | 850 | 851 | ..\ 852 | 1 853 | 854 | 855 | ..\ 856 | 1 857 | 858 | 859 | 860 | 861 | 1 862 | 863 | 864 | 1 865 | 866 | 867 | 1 868 | 869 | 870 | 871 | 872 | ..\$(PROJECTNAME).launchscreen 873 | 64 874 | 875 | 876 | ..\$(PROJECTNAME).launchscreen 877 | 64 878 | 879 | 880 | 881 | 882 | 1 883 | 884 | 885 | 1 886 | 887 | 888 | 1 889 | 890 | 891 | 892 | 893 | Assets 894 | 1 895 | 896 | 897 | Assets 898 | 1 899 | 900 | 901 | 902 | 903 | Assets 904 | 1 905 | 906 | 907 | Assets 908 | 1 909 | 910 | 911 | 912 | 913 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 914 | 1 915 | 916 | 917 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 918 | 1 919 | 920 | 921 | 922 | 923 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 924 | 1 925 | 926 | 927 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 928 | 1 929 | 930 | 931 | 932 | 933 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 934 | 1 935 | 936 | 937 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 938 | 1 939 | 940 | 941 | 942 | 943 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 944 | 1 945 | 946 | 947 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 948 | 1 949 | 950 | 951 | 952 | 953 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 954 | 1 955 | 956 | 957 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 958 | 1 959 | 960 | 961 | 962 | 963 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 964 | 1 965 | 966 | 967 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 968 | 1 969 | 970 | 971 | 972 | 973 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 974 | 1 975 | 976 | 977 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 978 | 1 979 | 980 | 981 | 982 | 983 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 984 | 1 985 | 986 | 987 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 988 | 1 989 | 990 | 991 | 992 | 993 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 994 | 1 995 | 996 | 997 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 998 | 1 999 | 1000 | 1001 | 1002 | 1003 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1004 | 1 1005 | 1006 | 1007 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1008 | 1 1009 | 1010 | 1011 | 1012 | 1013 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1014 | 1 1015 | 1016 | 1017 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1018 | 1 1019 | 1020 | 1021 | 1022 | 1023 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1024 | 1 1025 | 1026 | 1027 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1028 | 1 1029 | 1030 | 1031 | 1032 | 1033 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1034 | 1 1035 | 1036 | 1037 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1038 | 1 1039 | 1040 | 1041 | 1042 | 1043 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1044 | 1 1045 | 1046 | 1047 | ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset 1048 | 1 1049 | 1050 | 1051 | 1052 | 1053 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1054 | 1 1055 | 1056 | 1057 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1058 | 1 1059 | 1060 | 1061 | 1062 | 1063 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1064 | 1 1065 | 1066 | 1067 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1068 | 1 1069 | 1070 | 1071 | 1072 | 1073 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1074 | 1 1075 | 1076 | 1077 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1078 | 1 1079 | 1080 | 1081 | 1082 | 1083 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1084 | 1 1085 | 1086 | 1087 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1088 | 1 1089 | 1090 | 1091 | 1092 | 1093 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1094 | 1 1095 | 1096 | 1097 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1098 | 1 1099 | 1100 | 1101 | 1102 | 1103 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1104 | 1 1105 | 1106 | 1107 | ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset 1108 | 1 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | False 1126 | True 1127 | 1128 | 1129 | 12 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | --------------------------------------------------------------------------------