kazutab commited on
Commit
0475af5
·
verified ·
1 Parent(s): ecd6272

Upload folder using huggingface_hub (part 7)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +4 -0
  2. backend/llama.cpp/README.md +604 -0
  3. backend/llama.cpp/SECURITY.md +97 -0
  4. backend/llama.cpp/models/templates/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16.jinja +204 -0
  5. backend/llama.cpp/models/templates/NVIDIA-Nemotron-Nano-v2.jinja +162 -0
  6. backend/llama.cpp/models/templates/NousResearch-Hermes-2-Pro-Llama-3-8B-tool_use.jinja +152 -0
  7. backend/llama.cpp/models/templates/NousResearch-Hermes-3-Llama-3.1-8B-tool_use.jinja +152 -0
  8. backend/llama.cpp/models/templates/Qwen-QwQ-32B.jinja +63 -0
  9. backend/llama.cpp/models/templates/Qwen-Qwen2.5-7B-Instruct.jinja +54 -0
  10. backend/llama.cpp/models/templates/Qwen-Qwen3-0.6B.jinja +85 -0
  11. backend/llama.cpp/models/templates/Qwen3-Coder.jinja +117 -0
  12. backend/llama.cpp/models/templates/Qwen3.5-4B.jinja +154 -0
  13. backend/llama.cpp/models/templates/README.md +26 -0
  14. backend/llama.cpp/models/templates/Reka-Edge.jinja +161 -0
  15. backend/llama.cpp/models/templates/StepFun3.5-Flash.jinja +80 -0
  16. backend/llama.cpp/models/templates/moonshotai-Kimi-K2.jinja +43 -0
  17. backend/llama.cpp/models/templates/openai-gpt-oss-120b.jinja +331 -0
  18. backend/llama.cpp/models/templates/openbmb-MiniCPM5-1B.jinja +179 -0
  19. backend/llama.cpp/models/templates/unsloth-Apriel-1.5.jinja +126 -0
  20. backend/llama.cpp/models/templates/unsloth-mistral-Devstral-Small-2507.jinja +105 -0
  21. backend/llama.cpp/models/templates/upstage-Solar-Open-100B.jinja +156 -0
  22. backend/llama.cpp/mypy.ini +7 -0
  23. backend/llama.cpp/pocs/CMakeLists.txt +14 -0
  24. backend/llama.cpp/pocs/vdot/CMakeLists.txt +9 -0
  25. backend/llama.cpp/pocs/vdot/q8dot.cpp +173 -0
  26. backend/llama.cpp/pocs/vdot/vdot.cpp +311 -0
  27. backend/llama.cpp/pyproject.toml +67 -0
  28. backend/llama.cpp/pyrightconfig.json +22 -0
  29. backend/llama.cpp/requirements.txt +13 -0
  30. backend/llama.cpp/requirements/requirements-all.txt +18 -0
  31. backend/llama.cpp/requirements/requirements-compare-llama-bench.txt +3 -0
  32. backend/llama.cpp/requirements/requirements-convert_hf_to_gguf.txt +9 -0
  33. backend/llama.cpp/requirements/requirements-convert_hf_to_gguf_update.txt +1 -0
  34. backend/llama.cpp/requirements/requirements-convert_legacy_llama.txt +7 -0
  35. backend/llama.cpp/requirements/requirements-convert_llama_ggml_to_gguf.txt +1 -0
  36. backend/llama.cpp/requirements/requirements-convert_lora_to_gguf.txt +4 -0
  37. backend/llama.cpp/requirements/requirements-gguf_editor_gui.txt +3 -0
  38. backend/llama.cpp/requirements/requirements-pydantic.txt +3 -0
  39. backend/llama.cpp/requirements/requirements-server-bench.txt +5 -0
  40. backend/llama.cpp/requirements/requirements-test-tokenizer-random.txt +1 -0
  41. backend/llama.cpp/requirements/requirements-tool_bench.txt +11 -0
  42. backend/llama.cpp/scripts/apple/validate-apps.sh +5 -0
  43. backend/llama.cpp/scripts/apple/validate-ios.sh +820 -0
  44. backend/llama.cpp/scripts/apple/validate-macos.sh +781 -0
  45. backend/llama.cpp/scripts/apple/validate-tvos.sh +813 -0
  46. backend/llama.cpp/scripts/apple/validate-visionos.sh +811 -0
  47. backend/llama.cpp/scripts/bench-models.sh +82 -0
  48. backend/llama.cpp/scripts/build-info.sh +30 -0
  49. backend/llama.cpp/scripts/check-requirements.sh +179 -0
  50. backend/llama.cpp/scripts/compare-commits.sh +66 -0
.gitattributes CHANGED
@@ -61,3 +61,7 @@ backend/llama.cpp/models/ggml-vocab-qwen2.gguf filter=lfs diff=lfs merge=lfs -te
61
  backend/llama.cpp/models/ggml-vocab-qwen35.gguf filter=lfs diff=lfs merge=lfs -text
62
  backend/llama.cpp/models/ggml-vocab-refact.gguf filter=lfs diff=lfs merge=lfs -text
63
  backend/llama.cpp/models/ggml-vocab-starcoder.gguf filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
61
  backend/llama.cpp/models/ggml-vocab-qwen35.gguf filter=lfs diff=lfs merge=lfs -text
62
  backend/llama.cpp/models/ggml-vocab-refact.gguf filter=lfs diff=lfs merge=lfs -text
63
  backend/llama.cpp/models/ggml-vocab-starcoder.gguf filter=lfs diff=lfs merge=lfs -text
64
+ backend/llama.cpp/tools/mtmd/test-1.jpeg filter=lfs diff=lfs merge=lfs -text
65
+ backend/llama.cpp/tools/mtmd/test-2.mp3 filter=lfs diff=lfs merge=lfs -text
66
+ backend/llama.cpp/tools/mtmd/test-3.mp4 filter=lfs diff=lfs merge=lfs -text
67
+ backend/llama.cpp/tools/mtmd/tests/test-1-positive.png filter=lfs diff=lfs merge=lfs -text
backend/llama.cpp/README.md ADDED
@@ -0,0 +1,604 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # llama.cpp
2
+
3
+ ![llama](https://raw.githubusercontent.com/ggml-org/llama.brand/refs/heads/master/cover/llama-cpp/cover-llama-cpp-dark.svg)
4
+
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
6
+ [![Release](https://img.shields.io/github/v/release/ggml-org/llama.cpp)](https://github.com/ggml-org/llama.cpp/releases)
7
+ [![Server](https://github.com/ggml-org/llama.cpp/actions/workflows/server.yml/badge.svg)](https://github.com/ggml-org/llama.cpp/actions/workflows/server.yml)
8
+ [![Docker](https://github.com/ggml-org/llama.cpp/actions/workflows/docker.yml/badge.svg)](https://github.com/ggml-org/llama.cpp/actions/workflows/docker.yml)
9
+ [![Winget](https://github.com/ggml-org/llama.cpp/actions/workflows/winget.yml/badge.svg)](https://github.com/ggml-org/llama.cpp/actions/workflows/winget.yml)
10
+
11
+ [Manifesto](https://github.com/ggml-org/llama.cpp/discussions/205) / [ggml](https://github.com/ggml-org/ggml) / [ops](https://github.com/ggml-org/llama.cpp/blob/master/docs/ops.md)
12
+
13
+ LLM inference in C/C++
14
+
15
+ ## Recent API changes
16
+
17
+ - [Changelog for `libllama` API](https://github.com/ggml-org/llama.cpp/issues/9289)
18
+ - [Changelog for `llama-server` REST API](https://github.com/ggml-org/llama.cpp/issues/9291)
19
+
20
+ ## Hot topics
21
+
22
+ - **Hugging Face cache migration: models downloaded with `-hf` are now stored in the standard Hugging Face cache directory, enabling sharing with other HF tools.**
23
+ - **[guide : using the new WebUI of llama.cpp](https://github.com/ggml-org/llama.cpp/discussions/16938)**
24
+ - [guide : running gpt-oss with llama.cpp](https://github.com/ggml-org/llama.cpp/discussions/15396)
25
+ - [[FEEDBACK] Better packaging for llama.cpp to support downstream consumers 🤗](https://github.com/ggml-org/llama.cpp/discussions/15313)
26
+ - Support for the `gpt-oss` model with native MXFP4 format has been added | [PR](https://github.com/ggml-org/llama.cpp/pull/15091) | [Collaboration with NVIDIA](https://blogs.nvidia.com/blog/rtx-ai-garage-openai-oss) | [Comment](https://github.com/ggml-org/llama.cpp/discussions/15095)
27
+ - Multimodal support arrived in `llama-server`: [#12898](https://github.com/ggml-org/llama.cpp/pull/12898) | [documentation](./docs/multimodal.md)
28
+ - VS Code extension for FIM completions: https://github.com/ggml-org/llama.vscode
29
+ - Vim/Neovim plugin for FIM completions: https://github.com/ggml-org/llama.vim
30
+ - Hugging Face Inference Endpoints now support GGUF out of the box! https://github.com/ggml-org/llama.cpp/discussions/9669
31
+ - Hugging Face GGUF editor: [discussion](https://github.com/ggml-org/llama.cpp/discussions/9268) | [tool](https://huggingface.co/spaces/CISCai/gguf-editor)
32
+ - WebGPU support is now available in the browser, see a blog/demo introducing it [here](https://reeselevine.github.io/llamas-on-the-web/).
33
+
34
+ ----
35
+
36
+ ## Quick start
37
+
38
+ Getting started with llama.cpp is straightforward. Here are several ways to install it on your machine:
39
+
40
+ - Install `llama.cpp` using [brew, nix, winget, or conda-forge](docs/install.md)
41
+ - Run with Docker - see our [Docker documentation](docs/docker.md)
42
+ - Download pre-built binaries from the [releases page](https://github.com/ggml-org/llama.cpp/releases)
43
+ - Build from source by cloning this repository - check out [our build guide](docs/build.md)
44
+
45
+ Once installed, you'll need a model to work with. Head to the [Obtaining and quantizing models](#obtaining-and-quantizing-models) section to learn more.
46
+
47
+ Example command:
48
+
49
+ ```sh
50
+ # Use a local model file
51
+ llama-cli -m my_model.gguf
52
+
53
+ # Or download and run a model directly from Hugging Face
54
+ llama-cli -hf ggml-org/gemma-3-1b-it-GGUF
55
+
56
+ # Launch OpenAI-compatible API server
57
+ llama-server -hf ggml-org/gemma-3-1b-it-GGUF
58
+ ```
59
+
60
+ ## Description
61
+
62
+ The main goal of `llama.cpp` is to enable LLM inference with minimal setup and state-of-the-art performance on a wide
63
+ range of hardware - locally and in the cloud.
64
+
65
+ - Plain C/C++ implementation without any dependencies
66
+ - Apple silicon is a first-class citizen - optimized via ARM NEON, Accelerate and Metal frameworks
67
+ - AVX, AVX2, AVX512 and AMX support for x86 architectures
68
+ - RVV, ZVFH, ZFH, ZICBOP and ZIHINTPAUSE support for RISC-V architectures
69
+ - 1.5-bit, 2-bit, 3-bit, 4-bit, 5-bit, 6-bit, and 8-bit integer quantization for faster inference and reduced memory use
70
+ - Custom CUDA kernels for running LLMs on NVIDIA GPUs (support for AMD GPUs via HIP and Moore Threads GPUs via MUSA)
71
+ - Vulkan and SYCL backend support
72
+ - CPU+GPU hybrid inference to partially accelerate models larger than the total VRAM capacity
73
+
74
+ The `llama.cpp` project is the main playground for developing new features for the [ggml](https://github.com/ggml-org/ggml) library.
75
+
76
+ <details>
77
+ <summary>Models</summary>
78
+
79
+ Typically finetunes of the base models below are supported as well.
80
+
81
+ Instructions for adding support for new models: [HOWTO-add-model.md](docs/development/HOWTO-add-model.md)
82
+
83
+ #### Text-only
84
+
85
+ - [X] LLaMA 🦙
86
+ - [x] LLaMA 2 🦙🦙
87
+ - [x] LLaMA 3 🦙🦙🦙
88
+ - [X] [Mistral 7B](https://huggingface.co/mistralai/Mistral-7B-v0.1)
89
+ - [x] [Mixtral MoE](https://huggingface.co/models?search=mistral-ai/Mixtral)
90
+ - [x] [DBRX](https://huggingface.co/databricks/dbrx-instruct)
91
+ - [x] [Jamba](https://huggingface.co/ai21labs)
92
+ - [X] [Falcon](https://huggingface.co/models?search=tiiuae/falcon)
93
+ - [X] [Chinese LLaMA / Alpaca](https://github.com/ymcui/Chinese-LLaMA-Alpaca) and [Chinese LLaMA-2 / Alpaca-2](https://github.com/ymcui/Chinese-LLaMA-Alpaca-2)
94
+ - [X] [Vigogne (French)](https://github.com/bofenghuang/vigogne)
95
+ - [X] [BERT](https://github.com/ggml-org/llama.cpp/pull/5423)
96
+ - [X] [Koala](https://bair.berkeley.edu/blog/2023/04/03/koala/)
97
+ - [X] [Baichuan 1 & 2](https://huggingface.co/models?search=baichuan-inc/Baichuan) + [derivations](https://huggingface.co/hiyouga/baichuan-7b-sft)
98
+ - [X] [Aquila 1 & 2](https://huggingface.co/models?search=BAAI/Aquila)
99
+ - [X] [Starcoder models](https://github.com/ggml-org/llama.cpp/pull/3187)
100
+ - [X] [Refact](https://huggingface.co/smallcloudai/Refact-1_6B-fim)
101
+ - [X] [MPT](https://github.com/ggml-org/llama.cpp/pull/3417)
102
+ - [X] [Bloom](https://github.com/ggml-org/llama.cpp/pull/3553)
103
+ - [x] [Yi models](https://huggingface.co/models?search=01-ai/Yi)
104
+ - [X] [StableLM models](https://huggingface.co/stabilityai)
105
+ - [x] [Deepseek models](https://huggingface.co/models?search=deepseek-ai/deepseek)
106
+ - [x] [Qwen models](https://huggingface.co/models?search=Qwen/Qwen)
107
+ - [x] [PLaMo-13B](https://github.com/ggml-org/llama.cpp/pull/3557)
108
+ - [x] [Phi models](https://huggingface.co/models?search=microsoft/phi)
109
+ - [x] [PhiMoE](https://github.com/ggml-org/llama.cpp/pull/11003)
110
+ - [x] [GPT-2](https://huggingface.co/gpt2)
111
+ - [x] [Orion 14B](https://github.com/ggml-org/llama.cpp/pull/5118)
112
+ - [x] [InternLM2](https://huggingface.co/models?search=internlm2)
113
+ - [x] [CodeShell](https://github.com/WisdomShell/codeshell)
114
+ - [x] [Gemma](https://ai.google.dev/gemma)
115
+ - [x] [Mamba](https://github.com/state-spaces/mamba)
116
+ - [x] [Grok-1](https://huggingface.co/keyfan/grok-1-hf)
117
+ - [x] [Xverse](https://huggingface.co/models?search=xverse)
118
+ - [x] [Command-R models](https://huggingface.co/models?search=CohereForAI/c4ai-command-r)
119
+ - [x] [SEA-LION](https://huggingface.co/models?search=sea-lion)
120
+ - [x] [GritLM-7B](https://huggingface.co/GritLM/GritLM-7B) + [GritLM-8x7B](https://huggingface.co/GritLM/GritLM-8x7B)
121
+ - [x] [OLMo](https://allenai.org/olmo)
122
+ - [x] [OLMo 2](https://allenai.org/olmo)
123
+ - [x] [OLMoE](https://huggingface.co/allenai/OLMoE-1B-7B-0924)
124
+ - [x] [Granite models](https://huggingface.co/collections/ibm-granite/granite-code-models-6624c5cec322e4c148c8b330)
125
+ - [x] [GPT-NeoX](https://github.com/EleutherAI/gpt-neox) + [Pythia](https://github.com/EleutherAI/pythia)
126
+ - [x] [Snowflake-Arctic MoE](https://huggingface.co/collections/Snowflake/arctic-66290090abe542894a5ac520)
127
+ - [x] [Smaug](https://huggingface.co/models?search=Smaug)
128
+ - [x] [Poro 34B](https://huggingface.co/LumiOpen/Poro-34B)
129
+ - [x] [Bitnet b1.58 models](https://huggingface.co/1bitLLM)
130
+ - [x] [Flan T5](https://huggingface.co/models?search=flan-t5)
131
+ - [x] [Open Elm models](https://huggingface.co/collections/apple/openelm-instruct-models-6619ad295d7ae9f868b759ca)
132
+ - [x] [ChatGLM3-6b](https://huggingface.co/THUDM/chatglm3-6b) + [ChatGLM4-9b](https://huggingface.co/THUDM/glm-4-9b) + [GLMEdge-1.5b](https://huggingface.co/THUDM/glm-edge-1.5b-chat) + [GLMEdge-4b](https://huggingface.co/THUDM/glm-edge-4b-chat)
133
+ - [x] [GLM-4-0414](https://huggingface.co/collections/THUDM/glm-4-0414-67f3cbcb34dd9d252707cb2e)
134
+ - [x] [SmolLM](https://huggingface.co/collections/HuggingFaceTB/smollm-6695016cad7167254ce15966)
135
+ - [x] [EXAONE-3.0-7.8B-Instruct](https://huggingface.co/LGAI-EXAONE/EXAONE-3.0-7.8B-Instruct)
136
+ - [x] [FalconMamba Models](https://huggingface.co/collections/tiiuae/falconmamba-7b-66b9a580324dd1598b0f6d4a)
137
+ - [x] [Jais](https://huggingface.co/inceptionai/jais-13b-chat)
138
+ - [x] [Bielik-11B-v2.3](https://huggingface.co/collections/speakleash/bielik-11b-v23-66ee813238d9b526a072408a)
139
+ - [x] [RWKV-7](https://huggingface.co/collections/shoumenchougou/rwkv7-gxx-gguf)
140
+ - [x] [RWKV-6](https://github.com/BlinkDL/RWKV-LM)
141
+ - [x] [QRWKV-6](https://huggingface.co/recursal/QRWKV6-32B-Instruct-Preview-v0.1)
142
+ - [x] [GigaChat-20B-A3B](https://huggingface.co/ai-sage/GigaChat-20B-A3B-instruct)
143
+ - [X] [Trillion-7B-preview](https://huggingface.co/trillionlabs/Trillion-7B-preview)
144
+ - [x] [Ling models](https://huggingface.co/collections/inclusionAI/ling-67c51c85b34a7ea0aba94c32)
145
+ - [x] [Liquid LFM2 models](https://huggingface.co/collections/LiquidAI/lfm2)
146
+ - [x] [Liquid LFM2.5 models](https://huggingface.co/collections/LiquidAI/lfm25)
147
+ - [x] [Liquid Nanos](https://huggingface.co/collections/LiquidAI/liquid-nanos)
148
+ - [x] [Hunyuan models](https://huggingface.co/collections/tencent/hunyuan-dense-model-6890632cda26b19119c9c5e7)
149
+ - [x] [BailingMoeV2 (Ring/Ling 2.0) models](https://huggingface.co/collections/inclusionAI/ling-v2-68bf1dd2fc34c306c1fa6f86)
150
+ - [x] [Mellum models](https://huggingface.co/JetBrains/models?search=mellum)
151
+
152
+ #### Multimodal
153
+
154
+ - [x] [LLaVA 1.5 models](https://huggingface.co/collections/liuhaotian/llava-15-653aac15d994e992e2677a7e), [LLaVA 1.6 models](https://huggingface.co/collections/liuhaotian/llava-16-65b9e40155f60fd046a5ccf2)
155
+ - [x] [BakLLaVA](https://huggingface.co/models?search=SkunkworksAI/Bakllava)
156
+ - [x] [Obsidian](https://huggingface.co/NousResearch/Obsidian-3B-V0.5)
157
+ - [x] [ShareGPT4V](https://huggingface.co/models?search=Lin-Chen/ShareGPT4V)
158
+ - [x] [MobileVLM 1.7B/3B models](https://huggingface.co/models?search=mobileVLM)
159
+ - [x] [Yi-VL](https://huggingface.co/models?search=Yi-VL)
160
+ - [x] [Mini CPM](https://huggingface.co/models?search=MiniCPM)
161
+ - [x] [Moondream](https://huggingface.co/vikhyatk/moondream2)
162
+ - [x] [Bunny](https://github.com/BAAI-DCAI/Bunny)
163
+ - [x] [GLM-EDGE](https://huggingface.co/models?search=glm-edge)
164
+ - [x] [Qwen2-VL](https://huggingface.co/collections/Qwen/qwen2-vl-66cee7455501d7126940800d)
165
+ - [x] [LFM2-VL](https://huggingface.co/collections/LiquidAI/lfm2-vl-68963bbc84a610f7638d5ffa)
166
+
167
+ </details>
168
+
169
+ <details>
170
+ <summary>Bindings</summary>
171
+
172
+ - Python: [ddh0/easy-llama](https://github.com/ddh0/easy-llama)
173
+ - Python: [abetlen/llama-cpp-python](https://github.com/abetlen/llama-cpp-python)
174
+ - Go: [go-skynet/go-llama.cpp](https://github.com/go-skynet/go-llama.cpp)
175
+ - Node.js: [withcatai/node-llama-cpp](https://github.com/withcatai/node-llama-cpp)
176
+ - JS/TS (llama.cpp server client): [lgrammel/modelfusion](https://modelfusion.dev/integration/model-provider/llamacpp)
177
+ - JS/TS (Programmable Prompt Engine CLI): [offline-ai/cli](https://github.com/offline-ai/cli)
178
+ - JavaScript/Wasm (works in browser): [tangledgroup/llama-cpp-wasm](https://github.com/tangledgroup/llama-cpp-wasm)
179
+ - Typescript/Wasm (nicer API, available on npm): [ngxson/wllama](https://github.com/ngxson/wllama)
180
+ - Ruby: [yoshoku/llama_cpp.rb](https://github.com/yoshoku/llama_cpp.rb)
181
+ - Ruby: [docusealco/rllama](https://github.com/docusealco/rllama)
182
+ - Rust (more features): [edgenai/llama_cpp-rs](https://github.com/edgenai/llama_cpp-rs)
183
+ - Rust (nicer API): [mdrokz/rust-llama.cpp](https://github.com/mdrokz/rust-llama.cpp)
184
+ - Rust (more direct bindings): [utilityai/llama-cpp-rs](https://github.com/utilityai/llama-cpp-rs)
185
+ - Rust (automated build from crates.io): [ShelbyJenkins/llm_client](https://github.com/ShelbyJenkins/llm_client)
186
+ - C#/.NET: [SciSharp/LLamaSharp](https://github.com/SciSharp/LLamaSharp)
187
+ - C#/VB.NET (more features - community license): [LM-Kit.NET](https://docs.lm-kit.com/lm-kit-net/index.html)
188
+ - Scala 3: [donderom/llm4s](https://github.com/donderom/llm4s)
189
+ - Clojure: [phronmophobic/llama.clj](https://github.com/phronmophobic/llama.clj)
190
+ - React Native: [mybigday/llama.rn](https://github.com/mybigday/llama.rn)
191
+ - Java: [kherud/java-llama.cpp](https://github.com/kherud/java-llama.cpp)
192
+ - Java: [QuasarByte/llama-cpp-jna](https://github.com/QuasarByte/llama-cpp-jna)
193
+ - Zig: [deins/llama.cpp.zig](https://github.com/Deins/llama.cpp.zig)
194
+ - Flutter/Dart: [netdur/llama_cpp_dart](https://github.com/netdur/llama_cpp_dart)
195
+ - Flutter: [xuegao-tzx/Fllama](https://github.com/xuegao-tzx/Fllama)
196
+ - PHP (API bindings and features built on top of llama.cpp): [distantmagic/resonance](https://github.com/distantmagic/resonance) [(more info)](https://github.com/ggml-org/llama.cpp/pull/6326)
197
+ - Guile Scheme: [guile_llama_cpp](https://savannah.nongnu.org/projects/guile-llama-cpp)
198
+ - Swift [srgtuszy/llama-cpp-swift](https://github.com/srgtuszy/llama-cpp-swift)
199
+ - Swift [ShenghaiWang/SwiftLlama](https://github.com/ShenghaiWang/SwiftLlama)
200
+ - Delphi [Embarcadero/llama-cpp-delphi](https://github.com/Embarcadero/llama-cpp-delphi)
201
+ - Go (no CGo needed): [hybridgroup/yzma](https://github.com/hybridgroup/yzma)
202
+ - Android: [llama.android](/examples/llama.android)
203
+
204
+ </details>
205
+
206
+ <details>
207
+ <summary>UIs</summary>
208
+
209
+ *(to have a project listed here, it should clearly state that it depends on `llama.cpp`)*
210
+
211
+ - [AI Sublime Text plugin](https://github.com/yaroslavyaroslav/OpenAI-sublime-text) (MIT)
212
+ - [BonzAI App](https://apps.apple.com/us/app/bonzai-your-local-ai-agent/id6752847988) (proprietary)
213
+ - [cztomsik/ava](https://github.com/cztomsik/ava) (MIT)
214
+ - [Dot](https://github.com/alexpinel/Dot) (GPL)
215
+ - [eva](https://github.com/ylsdamxssjxxdd/eva) (MIT)
216
+ - [iohub/collama](https://github.com/iohub/coLLaMA) (Apache-2.0)
217
+ - [janhq/jan](https://github.com/janhq/jan) (AGPL)
218
+ - [johnbean393/Sidekick](https://github.com/johnbean393/Sidekick) (MIT)
219
+ - [KanTV](https://github.com/zhouwg/kantv?tab=readme-ov-file) (Apache-2.0)
220
+ - [KodiBot](https://github.com/firatkiral/kodibot) (GPL)
221
+ - [llama.vim](https://github.com/ggml-org/llama.vim) (MIT)
222
+ - [LARS](https://github.com/abgulati/LARS) (AGPL)
223
+ - [Llama Assistant](https://github.com/vietanhdev/llama-assistant) (GPL)
224
+ - [LlamaLib](https://github.com/undreamai/LlamaLib) (Apache-2.0)
225
+ - [LLMFarm](https://github.com/guinmoon/LLMFarm?tab=readme-ov-file) (MIT)
226
+ - [LLMUnity](https://github.com/undreamai/LLMUnity) (MIT)
227
+ - [LMStudio](https://lmstudio.ai/) (proprietary)
228
+ - [LocalAI](https://github.com/mudler/LocalAI) (MIT)
229
+ - [LostRuins/koboldcpp](https://github.com/LostRuins/koboldcpp) (AGPL)
230
+ - [MindMac](https://mindmac.app) (proprietary)
231
+ - [MindWorkAI/AI-Studio](https://github.com/MindWorkAI/AI-Studio) (FSL-1.1-MIT)
232
+ - [Mobile-Artificial-Intelligence/maid](https://github.com/Mobile-Artificial-Intelligence/maid) (MIT)
233
+ - [Mozilla-Ocho/llamafile](https://github.com/Mozilla-Ocho/llamafile) (Apache-2.0)
234
+ - [nat/openplayground](https://github.com/nat/openplayground) (MIT)
235
+ - [nomic-ai/gpt4all](https://github.com/nomic-ai/gpt4all) (MIT)
236
+ - [ollama/ollama](https://github.com/ollama/ollama) (MIT)
237
+ - [oobabooga/text-generation-webui](https://github.com/oobabooga/text-generation-webui) (AGPL)
238
+ - [PocketPal AI](https://github.com/a-ghorbani/pocketpal-ai) (MIT)
239
+ - [psugihara/FreeChat](https://github.com/psugihara/FreeChat) (MIT)
240
+ - [ptsochantaris/emeltal](https://github.com/ptsochantaris/emeltal) (MIT)
241
+ - [pythops/tenere](https://github.com/pythops/tenere) (AGPL)
242
+ - [ramalama](https://github.com/containers/ramalama) (MIT)
243
+ - [semperai/amica](https://github.com/semperai/amica) (MIT)
244
+ - [withcatai/catai](https://github.com/withcatai/catai) (MIT)
245
+ - [Autopen](https://github.com/blackhole89/autopen) (GPL)
246
+
247
+ </details>
248
+
249
+ <details>
250
+ <summary>Tools</summary>
251
+
252
+ - [akx/ggify](https://github.com/akx/ggify) – download PyTorch models from Hugging Face Hub and convert them to GGML
253
+ - [akx/ollama-dl](https://github.com/akx/ollama-dl) – download models from the Ollama library to be used directly with llama.cpp
254
+ - [crashr/gppm](https://github.com/crashr/gppm) – launch llama.cpp instances utilizing NVIDIA Tesla P40 or P100 GPUs with reduced idle power consumption
255
+ - [gpustack/gguf-parser](https://github.com/gpustack/gguf-parser-go/tree/main/cmd/gguf-parser) - review/check the GGUF file and estimate the memory usage
256
+ - [Styled Lines](https://marketplace.unity.com/packages/tools/generative-ai/styled-lines-llama-cpp-model-292902) (proprietary licensed, async wrapper of inference part for game development in Unity3d with pre-built Mobile and Web platform wrappers and a model example)
257
+ - [unslothai/unsloth](https://github.com/unslothai/unsloth) – 🦥 exports/saves fine-tuned and trained models to GGUF (Apache-2.0)
258
+
259
+ </details>
260
+
261
+ <details>
262
+ <summary>Infrastructure</summary>
263
+
264
+ - [Paddler](https://github.com/intentee/paddler) - Open-source LLMOps platform for hosting and scaling AI in your own infrastructure
265
+ - [GPUStack](https://github.com/gpustack/gpustack) - Manage GPU clusters for running LLMs
266
+ - [llama_cpp_canister](https://github.com/onicai/llama_cpp_canister) - llama.cpp as a smart contract on the Internet Computer, using WebAssembly
267
+ - [llama-swap](https://github.com/mostlygeek/llama-swap) - transparent proxy that adds automatic model switching with llama-server
268
+ - [Kalavai](https://github.com/kalavai-net/kalavai-client) - Crowdsource end to end LLM deployment at any scale
269
+ - [llmaz](https://github.com/InftyAI/llmaz) - ☸️ Easy, advanced inference platform for large language models on Kubernetes.
270
+ - [LLMKube](https://github.com/defilantech/llmkube) - Kubernetes operator for llama.cpp with multi-GPU and Apple Silicon Metal
271
+ support"
272
+ </details>
273
+
274
+ <details>
275
+ <summary>Games</summary>
276
+
277
+ - [Lucy's Labyrinth](https://github.com/MorganRO8/Lucys_Labyrinth) - A simple maze game where agents controlled by an AI model will try to trick you.
278
+
279
+ </details>
280
+
281
+
282
+ ## Supported backends
283
+
284
+ | Backend | Target devices |
285
+ | --- | --- |
286
+ | [Metal](docs/build.md#metal-build) | Apple Silicon |
287
+ | [BLAS](docs/build.md#blas-build) | All |
288
+ | [BLIS](docs/backend/BLIS.md) | All |
289
+ | [SYCL](docs/backend/SYCL.md) | Intel GPU |
290
+ | [OpenVINO [In Progress]](docs/backend/OPENVINO.md) | Intel CPUs, GPUs, and NPUs |
291
+ | [MUSA](docs/build.md#musa) | Moore Threads GPU |
292
+ | [CUDA](docs/build.md#cuda) | Nvidia GPU |
293
+ | [HIP](docs/build.md#hip) | AMD GPU |
294
+ | [ZenDNN](docs/build.md#zendnn) | AMD CPU |
295
+ | [Vulkan](docs/build.md#vulkan) | GPU |
296
+ | [CANN](docs/build.md#cann) | Ascend NPU |
297
+ | [OpenCL](docs/backend/OPENCL.md) | Adreno GPU |
298
+ | [IBM zDNN](docs/backend/zDNN.md) | IBM Z & LinuxONE |
299
+ | [WebGPU](docs/build.md#webgpu) | All |
300
+ | [RPC](https://github.com/ggml-org/llama.cpp/tree/master/tools/rpc) | All |
301
+ | [Hexagon [In Progress]](docs/backend/snapdragon/README.md) | Snapdragon |
302
+ | [VirtGPU](docs/backend/VirtGPU.md) | VirtGPU APIR |
303
+
304
+ ## Obtaining and quantizing models
305
+
306
+ The [Hugging Face](https://huggingface.co) platform hosts a [number of LLMs](https://huggingface.co/models?library=gguf&sort=trending) compatible with `llama.cpp`:
307
+
308
+ - [Trending](https://huggingface.co/models?library=gguf&sort=trending)
309
+ - [LLaMA](https://huggingface.co/models?sort=trending&search=llama+gguf)
310
+
311
+ You can either manually download the GGUF file or directly use any `llama.cpp`-compatible models from [Hugging Face](https://huggingface.co/) or other model hosting sites, by using this CLI argument: `-hf <user>/<model>[:quant]`. For example:
312
+
313
+ ```sh
314
+ llama-cli -hf ggml-org/gemma-3-1b-it-GGUF
315
+ ```
316
+
317
+ By default, the CLI would download from Hugging Face, you can switch to other options with the environment variable `MODEL_ENDPOINT`. The `MODEL_ENDPOINT` must point to a Hugging Face compatible API endpoint.
318
+
319
+ After downloading a model, use the CLI tools to run it locally - see below.
320
+
321
+ `llama.cpp` requires the model to be stored in the [GGUF](https://github.com/ggml-org/ggml/blob/master/docs/gguf.md) file format. Models in other data formats can be converted to GGUF using the `convert_*.py` Python scripts in this repo.
322
+
323
+ The Hugging Face platform provides a variety of online tools for converting, quantizing and hosting models with `llama.cpp`:
324
+
325
+ - Use the [GGUF-my-repo space](https://huggingface.co/spaces/ggml-org/gguf-my-repo) to convert to GGUF format and quantize model weights to smaller sizes
326
+ - Use the [GGUF-my-LoRA space](https://huggingface.co/spaces/ggml-org/gguf-my-lora) to convert LoRA adapters to GGUF format (more info: https://github.com/ggml-org/llama.cpp/discussions/10123)
327
+ - Use the [GGUF-editor space](https://huggingface.co/spaces/CISCai/gguf-editor) to edit GGUF meta data in the browser (more info: https://github.com/ggml-org/llama.cpp/discussions/9268)
328
+ - Use the [Inference Endpoints](https://ui.endpoints.huggingface.co/) to directly host `llama.cpp` in the cloud (more info: https://github.com/ggml-org/llama.cpp/discussions/9669)
329
+
330
+ To learn more about model quantization, [read this documentation](tools/quantize/README.md)
331
+
332
+ ## [`llama-cli`](tools/cli)
333
+
334
+ #### A CLI tool for accessing and experimenting with most of `llama.cpp`'s functionality.
335
+
336
+ - <details open>
337
+ <summary>Run in conversation mode</summary>
338
+
339
+ Models with a built-in chat template will automatically activate conversation mode. If this doesn't occur, you can manually enable it by adding `-cnv` and specifying a suitable chat template with `--chat-template NAME`
340
+
341
+ ```bash
342
+ llama-cli -m model.gguf
343
+
344
+ # > hi, who are you?
345
+ # Hi there! I'm your helpful assistant! I'm an AI-powered chatbot designed to assist and provide information to users like you. I'm here to help answer your questions, provide guidance, and offer support on a wide range of topics. I'm a friendly and knowledgeable AI, and I'm always happy to help with anything you need. What's on your mind, and how can I assist you today?
346
+ #
347
+ # > what is 1+1?
348
+ # Easy peasy! The answer to 1+1 is... 2!
349
+ ```
350
+
351
+ </details>
352
+
353
+ - <details>
354
+ <summary>Run in conversation mode with custom chat template</summary>
355
+
356
+ ```bash
357
+ # use the "chatml" template (use -h to see the list of supported templates)
358
+ llama-cli -m model.gguf -cnv --chat-template chatml
359
+
360
+ # use a custom template
361
+ llama-cli -m model.gguf -cnv --in-prefix 'User: ' --reverse-prompt 'User:'
362
+ ```
363
+
364
+ </details>
365
+
366
+ - <details>
367
+ <summary>Constrain the output with a custom grammar</summary>
368
+
369
+ ```bash
370
+ llama-cli -m model.gguf -n 256 --grammar-file grammars/json.gbnf -p 'Request: schedule a call at 8pm; Command:'
371
+
372
+ # {"appointmentTime": "8pm", "appointmentDetails": "schedule a a call"}
373
+ ```
374
+
375
+ The [grammars/](grammars/) folder contains a handful of sample grammars. To write your own, check out the [GBNF Guide](grammars/README.md).
376
+
377
+ For authoring more complex JSON grammars, check out https://grammar.intrinsiclabs.ai/
378
+
379
+ </details>
380
+
381
+
382
+ ## [`llama-server`](tools/server)
383
+
384
+ #### A lightweight, [OpenAI API](https://github.com/openai/openai-openapi) compatible, HTTP server for serving LLMs.
385
+
386
+ - <details open>
387
+ <summary>Start a local HTTP server with default configuration on port 8080</summary>
388
+
389
+ ```bash
390
+ llama-server -m model.gguf --port 8080
391
+
392
+ # Basic web UI can be accessed via browser: http://localhost:8080
393
+ # Chat completion endpoint: http://localhost:8080/v1/chat/completions
394
+ ```
395
+
396
+ </details>
397
+
398
+ - <details>
399
+ <summary>Support multiple-users and parallel decoding</summary>
400
+
401
+ ```bash
402
+ # up to 4 concurrent requests, each with 4096 max context
403
+ llama-server -m model.gguf -c 16384 -np 4
404
+ ```
405
+
406
+ </details>
407
+
408
+ - <details>
409
+ <summary>Enable speculative decoding</summary>
410
+
411
+ ```bash
412
+ # the draft.gguf model should be a small variant of the target model.gguf
413
+ llama-server -m model.gguf -md draft.gguf
414
+ ```
415
+
416
+ </details>
417
+
418
+ - <details>
419
+ <summary>Serve an embedding model</summary>
420
+
421
+ ```bash
422
+ # use the /embedding endpoint
423
+ llama-server -m model.gguf --embedding --pooling cls -ub 8192
424
+ ```
425
+
426
+ </details>
427
+
428
+ - <details>
429
+ <summary>Serve a reranking model</summary>
430
+
431
+ ```bash
432
+ # use the /reranking endpoint
433
+ llama-server -m model.gguf --reranking
434
+ ```
435
+
436
+ </details>
437
+
438
+ - <details>
439
+ <summary>Constrain all outputs with a grammar</summary>
440
+
441
+ ```bash
442
+ # custom grammar
443
+ llama-server -m model.gguf --grammar-file grammar.gbnf
444
+
445
+ # JSON
446
+ llama-server -m model.gguf --grammar-file grammars/json.gbnf
447
+ ```
448
+
449
+ </details>
450
+
451
+
452
+ ## [`llama-perplexity`](tools/perplexity)
453
+
454
+ #### A tool for measuring the [perplexity](tools/perplexity/README.md) [^1] (and other quality metrics) of a model over a given text.
455
+
456
+ - <details open>
457
+ <summary>Measure the perplexity over a text file</summary>
458
+
459
+ ```bash
460
+ llama-perplexity -m model.gguf -f file.txt
461
+
462
+ # [1]15.2701,[2]5.4007,[3]5.3073,[4]6.2965,[5]5.8940,[6]5.6096,[7]5.7942,[8]4.9297, ...
463
+ # Final estimate: PPL = 5.4007 +/- 0.67339
464
+ ```
465
+
466
+ </details>
467
+
468
+ - <details>
469
+ <summary>Measure KL divergence</summary>
470
+
471
+ ```bash
472
+ # TODO
473
+ ```
474
+
475
+ </details>
476
+
477
+ [^1]: [https://huggingface.co/docs/transformers/perplexity](https://huggingface.co/docs/transformers/perplexity)
478
+
479
+ ## [`llama-bench`](tools/llama-bench)
480
+
481
+ #### Benchmark the performance of the inference for various parameters.
482
+
483
+ - <details open>
484
+ <summary>Run default benchmark</summary>
485
+
486
+ ```bash
487
+ llama-bench -m model.gguf
488
+
489
+ # Output:
490
+ # | model | size | params | backend | threads | test | t/s |
491
+ # | ------------------- | ---------: | ---------: | ---------- | ------: | ------------: | -------------------: |
492
+ # | qwen2 1.5B Q4_0 | 885.97 MiB | 1.54 B | Metal,BLAS | 16 | pp512 | 5765.41 ± 20.55 |
493
+ # | qwen2 1.5B Q4_0 | 885.97 MiB | 1.54 B | Metal,BLAS | 16 | tg128 | 197.71 ± 0.81 |
494
+ #
495
+ # build: 3e0ba0e60 (4229)
496
+ ```
497
+
498
+ </details>
499
+
500
+ ## [`llama-simple`](examples/simple)
501
+
502
+ #### A minimal example for implementing apps with `llama.cpp`. Useful for developers.
503
+
504
+ - <details>
505
+ <summary>Basic text completion</summary>
506
+
507
+ ```bash
508
+ llama-simple -m model.gguf
509
+
510
+ # Hello my name is Kaitlyn and I am a 16 year old girl. I am a junior in high school and I am currently taking a class called "The Art of
511
+ ```
512
+
513
+ </details>
514
+
515
+
516
+ ## Contributing
517
+
518
+ - Contributors can open PRs
519
+ - Collaborators will be invited based on contributions
520
+ - Maintainers can push to branches in the `llama.cpp` repo and merge PRs into the `master` branch
521
+ - Any help with managing issues, PRs and projects is very appreciated!
522
+ - See [good first issues](https://github.com/ggml-org/llama.cpp/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) for tasks suitable for first contributions
523
+ - Read the [CONTRIBUTING.md](CONTRIBUTING.md) for more information
524
+ - Make sure to read this: [Inference at the edge](https://github.com/ggml-org/llama.cpp/discussions/205)
525
+ - A bit of backstory for those who are interested: [Changelog podcast](https://changelog.com/podcast/532)
526
+
527
+ ## Other documentation
528
+
529
+ - [cli](tools/cli/README.md)
530
+ - [completion](tools/completion/README.md)
531
+ - [server](tools/server/README.md)
532
+ - [GBNF grammars](grammars/README.md)
533
+
534
+ #### Development documentation
535
+
536
+ - [How to build](docs/build.md)
537
+ - [Running on Docker](docs/docker.md)
538
+ - [Build on Android](docs/android.md)
539
+ - [Multi-GPU usage](docs/multi-gpu.md)
540
+ - [Performance troubleshooting](docs/development/token_generation_performance_tips.md)
541
+ - [GGML tips & tricks](https://github.com/ggml-org/llama.cpp/wiki/GGML-Tips-&-Tricks)
542
+
543
+ #### Seminal papers and background on the models
544
+
545
+ If your issue is with model generation quality, then please at least scan the following links and papers to understand the limitations of LLaMA models. This is especially important when choosing an appropriate model size and appreciating both the significant and subtle differences between LLaMA models and ChatGPT:
546
+ - LLaMA:
547
+ - [Introducing LLaMA: A foundational, 65-billion-parameter large language model](https://ai.facebook.com/blog/large-language-model-llama-meta-ai/)
548
+ - [LLaMA: Open and Efficient Foundation Language Models](https://arxiv.org/abs/2302.13971)
549
+ - GPT-3
550
+ - [Language Models are Few-Shot Learners](https://arxiv.org/abs/2005.14165)
551
+ - GPT-3.5 / InstructGPT / ChatGPT:
552
+ - [Aligning language models to follow instructions](https://openai.com/research/instruction-following)
553
+ - [Training language models to follow instructions with human feedback](https://arxiv.org/abs/2203.02155)
554
+
555
+ ## XCFramework
556
+ The XCFramework is a precompiled version of the library for iOS, visionOS, tvOS,
557
+ and macOS. It can be used in Swift projects without the need to compile the
558
+ library from source. For example:
559
+ ```swift
560
+ // swift-tools-version: 5.10
561
+ // The swift-tools-version declares the minimum version of Swift required to build this package.
562
+
563
+ import PackageDescription
564
+
565
+ let package = Package(
566
+ name: "MyLlamaPackage",
567
+ targets: [
568
+ .executableTarget(
569
+ name: "MyLlamaPackage",
570
+ dependencies: [
571
+ "LlamaFramework"
572
+ ]),
573
+ .binaryTarget(
574
+ name: "LlamaFramework",
575
+ url: "https://github.com/ggml-org/llama.cpp/releases/download/b5046/llama-b5046-xcframework.zip",
576
+ checksum: "c19be78b5f00d8d29a25da41042cb7afa094cbf6280a225abe614b03b20029ab"
577
+ )
578
+ ]
579
+ )
580
+ ```
581
+ The above example is using an intermediate build `b5046` of the library. This can be modified
582
+ to use a different version by changing the URL and checksum.
583
+
584
+ ## Completions
585
+ Command-line completion is available for some environments.
586
+
587
+ #### Bash Completion
588
+ ```bash
589
+ $ build/bin/llama-cli --completion-bash > ~/.llama-completion.bash
590
+ $ source ~/.llama-completion.bash
591
+ ```
592
+ Optionally this can be added to your `.bashrc` or `.bash_profile` to load it
593
+ automatically. For example:
594
+ ```console
595
+ $ echo "source ~/.llama-completion.bash" >> ~/.bashrc
596
+ ```
597
+
598
+ ## Dependencies
599
+
600
+ - [yhirose/cpp-httplib](https://github.com/yhirose/cpp-httplib) - Single-header HTTP server, used by `llama-server` - MIT license
601
+ - [stb-image](https://github.com/nothings/stb) - Single-header image format decoder, used by multimodal subsystem - Public domain
602
+ - [nlohmann/json](https://github.com/nlohmann/json) - Single-header JSON library, used by various tools/examples - MIT License
603
+ - [miniaudio.h](https://github.com/mackron/miniaudio) - Single-header audio format decoder, used by multimodal subsystem - Public domain
604
+ - [subprocess.h](https://github.com/sheredom/subprocess.h) - Single-header process launching solution for C and C++ - Public domain
backend/llama.cpp/SECURITY.md ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Security Policy
2
+
3
+ - [**Reporting a vulnerability**](#reporting-a-vulnerability)
4
+ - [**Requirements**](#requirements)
5
+ - [**Covered Topics**](#covered-topics)
6
+ - [**Using llama.cpp securely**](#using-llamacpp-securely)
7
+ - [Untrusted models](#untrusted-models)
8
+ - [Untrusted inputs](#untrusted-inputs)
9
+ - [Data privacy](#data-privacy)
10
+ - [Untrusted environments or networks](#untrusted-environments-or-networks)
11
+ - [Multi-Tenant environments](#multi-tenant-environments)
12
+
13
+ ## Reporting a vulnerability
14
+
15
+ > [!IMPORTANT]
16
+ > The private security disclosure program is disabled until further notice. Please submit patches with fixes directly to the repo as public PRs. Emails will be ignored.
17
+
18
+ If you have discovered a security vulnerability in this project that falls inside the [covered topics](#covered-topics), please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
19
+
20
+ Please disclose it as a private [security advisory](https://github.com/ggml-org/llama.cpp/security/advisories/new).
21
+
22
+ A team of volunteers on a reasonable-effort basis maintains this project. As such, please give us at least 90 days to work on a fix before public exposure.
23
+
24
+ ### Requirements
25
+
26
+ Before submitting your report, ensure you meet the following requirements:
27
+
28
+ - You have read this policy and fully understand it.
29
+ - AI is only permitted in an assistive capacity as stated in [AGENTS.md](AGENTS.md). We do not accept reports that are written exclusively by AI.
30
+ - Your report must include a working Proof-of-Concept in the form of a script and/or attached files.
31
+
32
+ Maintainers reserve the right to close the report if these requirements are not fulfilled.
33
+
34
+ ### Covered Topics
35
+
36
+ Only vulnerabilities that fall within these parts of the project are considered valid. For problems falling outside of this list, please report them as issues.
37
+
38
+ - `src/**/*`
39
+ - `ggml/**/*`
40
+ - `gguf-py/**/*`
41
+ - `tools/server/*`, **excluding** the following topics:
42
+ - Web UI
43
+ - Features marked as experimental
44
+ - Features not recommended for use in untrusted environments (e.g., router, MCP)
45
+ - Bugs that can lead to Denial-of-Service attack
46
+
47
+ Note that none of the topics under [Using llama.cpp securely](#using-llamacpp-securely) are considered vulnerabilities in LLaMA C++.
48
+
49
+ For vulnerabilities that fall within the `vendor` directory, please report them directly to the third-party project.
50
+
51
+ ## Using llama.cpp securely
52
+
53
+ ### Untrusted models
54
+ Be careful when running untrusted models. This classification includes models created by unknown developers or utilizing data obtained from unknown sources.
55
+
56
+ *Always execute untrusted models within a secure, isolated environment such as a sandbox* (e.g., containers, virtual machines). This helps protect your system from potentially malicious code.
57
+
58
+ > [!NOTE]
59
+ > The trustworthiness of a model is not binary. You must always determine the proper level of caution depending on the specific model and how it matches your use case and risk tolerance.
60
+
61
+ ### Untrusted inputs
62
+
63
+ Some models accept various input formats (text, images, audio, etc.). The libraries converting these inputs have varying security levels, so it's crucial to isolate the model and carefully pre-process inputs to mitigate script injection risks.
64
+
65
+ For maximum security when handling untrusted inputs, you may need to employ the following:
66
+
67
+ * Sandboxing: Isolate the environment where the inference happens.
68
+ * Pre-analysis: Check how the model performs by default when exposed to prompt injection (e.g. using [fuzzing for prompt injection](https://github.com/FonduAI/awesome-prompt-injection?tab=readme-ov-file#tools)). This will give you leads on how hard you will have to work on the next topics.
69
+ * Updates: Keep both LLaMA C++ and your libraries updated with the latest security patches.
70
+ * Input Sanitation: Before feeding data to the model, sanitize inputs rigorously. This involves techniques such as:
71
+ * Validation: Enforce strict rules on allowed characters and data types.
72
+ * Filtering: Remove potentially malicious scripts or code fragments.
73
+ * Encoding: Convert special characters into safe representations.
74
+ * Verification: Run tooling that identifies potential script injections (e.g. [models that detect prompt injection attempts](https://python.langchain.com/docs/guides/safety/hugging_face_prompt_injection)).
75
+
76
+ ### Data privacy
77
+
78
+ To protect sensitive data from potential leaks or unauthorized access, it is crucial to sandbox the model execution. This means running the model in a secure, isolated environment, which helps mitigate many attack vectors.
79
+
80
+ ### Untrusted environments or networks
81
+
82
+ If you can't run your models in a secure and isolated environment or if it must be exposed to an untrusted network, make sure to take the following security precautions:
83
+ * Do not use the RPC backend, [ggml-rpc-server](https://github.com/ggml-org/llama.cpp/tree/master/tools/rpc) and [llama-server](https://github.com/ggml-org/llama.cpp/tree/master/tools/server) functionality (see https://github.com/ggml-org/llama.cpp/pull/13061).
84
+ * Confirm the hash of any downloaded artifact (e.g. pre-trained model weights) matches a known-good value.
85
+ * Encrypt your data if sending it over the network.
86
+
87
+ ### Multi-Tenant environments
88
+
89
+ If you intend to run multiple models in parallel with shared memory, it is your responsibility to ensure the models do not interact or access each other's data. The primary areas of concern are tenant isolation, resource allocation, model sharing and hardware attacks.
90
+
91
+ 1. Tenant Isolation: Models should run separately with strong isolation methods to prevent unwanted data access. Separating networks is crucial for isolation, as it prevents unauthorized access to data or models and malicious users from sending graphs to execute under another tenant's identity.
92
+
93
+ 2. Resource Allocation: A denial of service caused by one model can impact the overall system health. Implement safeguards like rate limits, access controls, and health monitoring.
94
+
95
+ 3. Model Sharing: In a multitenant model sharing design, tenants and users must understand the security risks of running code provided by others. Since there are no reliable methods to detect malicious models, sandboxing the model execution is the recommended approach to mitigate the risk.
96
+
97
+ 4. Hardware Attacks: GPUs or TPUs can also be attacked. [Researches](https://scholar.google.com/scholar?q=gpu+side+channel) has shown that side channel attacks on GPUs are possible, which can make data leak from other models or processes running on the same system at the same time.
backend/llama.cpp/models/templates/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16.jinja ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro render_extra_keys(json_dict, handled_keys) %}
2
+ {%- if json_dict is mapping %}
3
+ {%- for json_key in json_dict if json_key not in handled_keys %}
4
+ {%- if json_dict[json_key] is mapping or (json_dict[json_key] is sequence and json_dict[json_key] is not string) %}
5
+ {{- '\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | tojson | safe) ~ '</' ~ json_key ~ '>' }}
6
+ {%- else %}
7
+ {{-'\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | string) ~ '</' ~ json_key ~ '>' }}
8
+ {%- endif %}
9
+ {%- endfor %}
10
+ {%- endif %}
11
+ {% endmacro %}
12
+ {%- set enable_thinking = enable_thinking if enable_thinking is defined else True %}
13
+ {%- set truncate_history_thinking = truncate_history_thinking if truncate_history_thinking is defined else True %}
14
+
15
+ {%- set ns = namespace(last_user_idx = -1) %}
16
+ {%- set loop_messages = messages %}
17
+ {%- for m in loop_messages %}
18
+ {%- if m["role"] == "user" %}
19
+ {%- set ns.last_user_idx = loop.index0 %}
20
+ {%- endif %}
21
+ {%- endfor %}
22
+
23
+ {%- if messages[0]["role"] == "system" %}
24
+ {%- set system_message = messages[0]["content"] %}
25
+ {%- set loop_messages = messages[1:] %}
26
+ {%- else %}
27
+ {%- set system_message = "" %}
28
+ {%- set loop_messages = messages %}
29
+ {%- endif %}
30
+ {%- if not tools is defined %}
31
+ {%- set tools = [] %}
32
+ {%- endif %}
33
+ {# Recompute last_user_idx relative to loop_messages after handling system #}
34
+ {%- set ns = namespace(last_user_idx = -1) %}
35
+ {%- for m in loop_messages %}
36
+ {%- if m["role"] == "user" %}
37
+ {%- set ns.last_user_idx = loop.index0 %}
38
+ {%- endif %}
39
+ {%- endfor %}
40
+ {%- if system_message is defined %}
41
+ {{- "<|im_start|>system\n" + system_message }}
42
+ {%- else %}
43
+ {%- if tools is iterable and tools | length > 0 %}
44
+ {{- "<|im_start|>system\n" }}
45
+ {%- endif %}
46
+ {%- endif %}
47
+ {%- if tools is iterable and tools | length > 0 %}
48
+ {%- if system_message is defined and system_message | length > 0 %}
49
+ {{- "\n\n" }}
50
+ {%- endif %}
51
+ {{- "# Tools\n\nYou have access to the following functions:\n\n" }}
52
+ {{- "<tools>" }}
53
+ {%- for tool in tools %}
54
+ {%- if tool.function is defined %}
55
+ {%- set tool = tool.function %}
56
+ {%- endif %}
57
+ {{- "\n<function>\n<name>" ~ tool.name ~ "</name>" }}
58
+ {%- if tool.description is defined %}
59
+ {{- '\n<description>' ~ (tool.description | trim) ~ '</description>' }}
60
+ {%- endif %}
61
+ {{- '\n<parameters>' }}
62
+ {%- if tool.parameters is defined and tool.parameters is mapping and tool.parameters.properties is defined and tool.parameters.properties is mapping %}
63
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
64
+ {{- '\n<parameter>' }}
65
+ {{- '\n<name>' ~ param_name ~ '</name>' }}
66
+ {%- if param_fields.type is defined %}
67
+ {{- '\n<type>' ~ (param_fields.type | string) ~ '</type>' }}
68
+ {%- endif %}
69
+ {%- if param_fields.description is defined %}
70
+ {{- '\n<description>' ~ (param_fields.description | trim) ~ '</description>' }}
71
+ {%- endif %}
72
+ {%- if param_fields.enum is defined %}
73
+ {{- '\n<enum>' ~ (param_fields.enum | tojson | safe) ~ '</enum>' }}
74
+ {%- endif %}
75
+ {%- set handled_keys = ['name', 'type', 'description', 'enum'] %}
76
+ {{- render_extra_keys(param_fields, handled_keys) }}
77
+ {{- '\n</parameter>' }}
78
+ {%- endfor %}
79
+ {%- endif %}
80
+ {% set handled_keys = ['type', 'properties', 'required'] %}
81
+ {{- render_extra_keys(tool.parameters, handled_keys) }}
82
+ {%- if tool.parameters is defined and tool.parameters.required is defined %}
83
+ {{- '\n<required>' ~ (tool.parameters.required | tojson | safe) ~ '</required>' }}
84
+ {%- endif %}
85
+ {{- '\n</parameters>' }}
86
+ {%- set handled_keys = ['type', 'name', 'description', 'parameters'] %}
87
+ {{- render_extra_keys(tool, handled_keys) }}
88
+ {{- '\n</function>' }}
89
+ {%- endfor %}
90
+ {{- "\n</tools>" }}
91
+
92
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
93
+ {%- endif %}
94
+
95
+
96
+ {%- if system_message is defined %}
97
+ {{- '<|im_end|>\n' }}
98
+ {%- else %}
99
+ {%- if tools is iterable and tools | length > 0 %}
100
+ {{- '<|im_end|>\n' }}
101
+ {%- endif %}
102
+ {%- endif %}
103
+
104
+ {%- for message in loop_messages %}
105
+ {%- if message.role == "assistant" %}
106
+ {# Add reasoning content in to content field for unified processing below. #}
107
+ {%- if message.reasoning_content is defined and message.reasoning_content is string and message.reasoning_content | trim | length > 0 %}
108
+ {%- set content = "<think>\n" ~ message.reasoning_content ~ "\n</think>\n" ~ (message.content | default('', true)) %}
109
+ {%- else %}
110
+ {%- set content = message.content | default('', true) %}
111
+ {%- if content is string -%}
112
+ {# Allow downstream logic to to take care of broken thought, only handle coherent reasoning here. #}
113
+ {%- if '<think>' not in content and '</think>' not in content -%}
114
+ {%- set content = "<think></think>" ~ content -%}
115
+ {%- endif -%}
116
+ {%- else -%}
117
+ {%- set content = content -%}
118
+ {%- endif -%}
119
+ {%- endif %}
120
+ {%- if message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %}
121
+ {# Assistant message has tool calls. #}
122
+ {{- '<|im_start|>assistant\n' }}
123
+ {%- set include_content = not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
124
+ {%- if content is string and content | trim | length > 0 %}
125
+ {%- if include_content %}
126
+ {{- (content | trim) ~ '\n' -}}
127
+ {%- else %}
128
+ {%- set c = (content | string) %}
129
+ {%- if '</think>' in c %}
130
+ {# Keep only content after the last closing think. Also generation prompt causes this. #}
131
+ {%- set c = c.split('</think>')[-1] %}
132
+ {%- elif '<think>' in c %}
133
+ {# If <think> was opened but never closed, drop the trailing think segment #}
134
+ {%- set c = c.split('<think>')[0] %}
135
+ {%- endif %}
136
+ {%- set c = "<think></think>" ~ c | trim %}
137
+ {%- if c | length > 0 %}
138
+ {{- c ~ '\n' -}}
139
+ {%- endif %}
140
+ {%- endif %}
141
+ {%- else %}
142
+ {{- "<think></think>" -}}
143
+ {%- endif %}
144
+ {%- for tool_call in message.tool_calls %}
145
+ {%- if tool_call.function is defined %}
146
+ {%- set tool_call = tool_call.function %}
147
+ {%- endif %}
148
+ {{- '<tool_call>\n<function=' ~ tool_call.name ~ '>\n' -}}
149
+ {%- if tool_call.arguments is defined %}
150
+ {%- for args_name, args_value in tool_call.arguments|items %}
151
+ {{- '<parameter=' ~ args_name ~ '>\n' -}}
152
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
153
+ {{- args_value ~ '\n</parameter>\n' -}}
154
+ {%- endfor %}
155
+ {%- endif %}
156
+ {{- '</function>\n</tool_call>\n' -}}
157
+ {%- endfor %}
158
+ {{- '<|im_end|>\n' }}
159
+ {%- else %}
160
+ {# Assistant message doesn't have tool calls. #}
161
+ {%- if not (truncate_history_thinking and loop.index0 < ns.last_user_idx) %}
162
+ {{- '<|im_start|>assistant\n' ~ (content | default('', true) | string | trim) ~ '<|im_end|>\n' }}
163
+ {%- else %}
164
+ {%- set c = (content | default('', true) | string) %}
165
+ {%- if '<think>' in c and '</think>' in c %}
166
+ {%- set c = "<think></think>" ~ c.split('</think>')[-1] %}
167
+ {%- endif %}
168
+ {%- set c = c | trim %}
169
+ {%- if c | length > 0 %}
170
+ {{- '<|im_start|>assistant\n' ~ c ~ '<|im_end|>\n' }}
171
+ {%- else %}
172
+ {{- '<|im_start|>assistant\n<|im_end|>\n' }}
173
+ {%- endif %}
174
+ {%- endif %}
175
+ {%- endif %}
176
+ {%- elif message.role == "user" or message.role == "system" %}
177
+ {{- '<|im_start|>' + message.role + '\n' }}
178
+ {%- set content = message.content | string %}
179
+ {{- content }}
180
+ {{- '<|im_end|>\n' }}
181
+ {%- elif message.role == "tool" %}
182
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
183
+ {{- '<|im_start|>user\n' }}
184
+ {%- endif %}
185
+ {{- '<tool_response>\n' }}
186
+ {{- message.content }}
187
+ {{- '\n</tool_response>\n' }}
188
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
189
+ {{- '<|im_end|>\n' }}
190
+ {%- elif loop.last %}
191
+ {{- '<|im_end|>\n' }}
192
+ {%- endif %}
193
+ {%- else %}
194
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>\n' }}
195
+ {%- endif %}
196
+ {%- endfor %}
197
+
198
+ {%- if add_generation_prompt %}
199
+ {%- if enable_thinking %}
200
+ {{- '<|im_start|>assistant\n<think>\n' }}
201
+ {%- else %}
202
+ {{- '<|im_start|>assistant\n<think></think>' }}
203
+ {%- endif %}
204
+ {%- endif %}
backend/llama.cpp/models/templates/NVIDIA-Nemotron-Nano-v2.jinja ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set ns = namespace(enable_thinking=true) -%}
2
+ {%- for message in messages -%}
3
+ {%- set content = message['content'] -%}
4
+ {%- if message['role'] == 'user' or message['role'] == 'system' -%}
5
+ {%- if '/think' in content -%}
6
+ {%- set ns.enable_thinking = true -%}
7
+ {%- elif '/no_think' in content -%}
8
+ {%- set ns.enable_thinking = false -%}
9
+ {%- endif -%}
10
+ {%- endif -%}
11
+ {%- endfor -%}
12
+
13
+ {%- if messages[0]['role'] != 'system' -%}
14
+ {%- set ns.non_tool_system_content = '' -%}
15
+ {{- '<SPECIAL_10>System
16
+ ' -}}
17
+ {%- else -%}
18
+ {%- set ns.non_tool_system_content = (messages[0]['content'] | default('', true)).replace('/think', '').replace('/no_think', '').strip() -%}
19
+ {{- '<SPECIAL_10>System
20
+ ' + ns.non_tool_system_content }}
21
+ {%- endif -%}
22
+
23
+ {%- if tools -%}
24
+ {%- if ns.non_tool_system_content is defined and ns.non_tool_system_content != '' -%}
25
+ {{- '
26
+
27
+ ' -}}
28
+ {%- endif -%}
29
+ {{- 'You can use the following tools to assist the user if required:' -}}
30
+ {{- '
31
+ <AVAILABLE_TOOLS>[' -}}
32
+ {%- for tool in tools -%}
33
+ {{- (tool.function if tool.function is defined else tool) | tojson -}}
34
+ {{- ', ' if not loop.last else '' -}}
35
+ {%- endfor -%}
36
+ {{- ']</AVAILABLE_TOOLS>
37
+
38
+ ' -}}
39
+ {{- 'If you decide to call any tool(s), use the following format:
40
+ ' -}}
41
+ {{- '<TOOLCALL>[{{"name": "tool_name1", "arguments": "tool_args1"}}, ' -}}
42
+ {{- '{{"name": "tool_name2", "arguments": "tool_args2"}}]</TOOLCALL>
43
+
44
+ ' -}}
45
+ {{- 'The user will execute tool-calls and return responses from tool(s) in this format:
46
+ ' -}}
47
+ {{- '<TOOL_RESPONSE>[{{"tool_response1"}}, {{"tool_response2"}}]</TOOL_RESPONSE>
48
+
49
+ ' -}}
50
+ {{- 'Based on the tool responses, you can call additional tools if needed, correct tool calls if any errors are found, or just respond to the user.' -}}
51
+ {%- endif -%}
52
+ {{- '
53
+
54
+ ' -}}
55
+ {%- set messages = messages[1:] if messages[0]['role'] == 'system' else messages -%}
56
+ {%- if messages[-1]['role'] == 'assistant' -%}
57
+ {%- set ns.last_turn_assistant_content = (messages[-1]['content'] | default('', true)).strip() -%}
58
+ {%- set ns.last_turn_assistant_tool_calls = messages[-1]['tool_calls'] if 'tool_calls' in messages[-1] else [] -%}
59
+ {%- set messages = messages[:-1] -%}
60
+ {%- endif -%}
61
+
62
+ {%- for message in messages %}
63
+ {%- set content = message['content'] %}
64
+ {%- if message['role'] == 'user' -%}
65
+ {{- '<SPECIAL_11>User
66
+ ' + (content | default('', true)).replace('/think', '').replace('/no_think', '').strip() + '
67
+ ' }}
68
+ {%- elif message['role'] == 'tool' -%}
69
+ {%- if loop.first or (messages[loop.index0 - 1].role != 'tool') -%}
70
+ {{- '<SPECIAL_11>User
71
+ ' + '<TOOL_RESPONSE>[' }}
72
+ {%- endif -%}
73
+ {{- message['content'] -}}
74
+ {{- ', ' if not loop.last and (messages[loop.index0 + 1].role == 'tool') else '' -}}
75
+ {%- if loop.last or (messages[loop.index0 + 1].role != 'tool') -%}
76
+ {{- ']</TOOL_RESPONSE>' -}}
77
+ {%- endif -%}
78
+ {%- elif message['role'] == 'assistant' -%}
79
+ {%- if content and '</think>' in content -%}
80
+ {%- set content = (content.split('</think>')[1] | default('', true)).strip() %}
81
+ {%- endif -%}
82
+ {{- '<SPECIAL_11>Assistant
83
+ ' + ((content | default('', true)).strip() if content is not none else '') }}
84
+ {%- if message.tool_calls -%}
85
+ {%- if (content | default('', true)).strip() != '' -%}
86
+ {{- '
87
+ ' -}}
88
+ {%- endif -%}
89
+ {{- '<TOOLCALL>[' -}}
90
+ {%- for call in message.tool_calls -%}
91
+ {%- set fn = call.function if call.function is defined else call -%}
92
+ {{- '{"name": "' + fn.name + '", "arguments": ' -}}
93
+ {%- if fn.arguments is string -%}
94
+ {{- fn.arguments -}}
95
+ {%- else -%}
96
+ {{- fn.arguments | tojson -}}
97
+ {%- endif -%}
98
+ {{- '}' + (', ' if not loop.last else '') -}}
99
+ {%- endfor -%}
100
+ {{- ']</TOOLCALL>' -}}
101
+ {%- endif -%}
102
+ {{- '
103
+ <SPECIAL_12>
104
+ ' -}}
105
+ {%- endif -%}
106
+ {%- endfor -%}
107
+
108
+ {%- if add_generation_prompt -%}
109
+ {{- '<SPECIAL_11>Assistant
110
+ ' -}}
111
+ {%- if ns.enable_thinking is defined and ns.enable_thinking is false -%}
112
+ {{- '<think></think>' -}}
113
+ {%- else -%}
114
+ {{- '<think>
115
+ ' -}}
116
+ {%- endif -%}
117
+ {%- if ns.last_turn_assistant_content is defined and ns.last_turn_assistant_content != '' -%}
118
+ {{- ns.last_turn_assistant_content -}}
119
+ {%- endif -%}
120
+ {%- else -%}
121
+ {%- if ns.last_turn_assistant_content is defined and ns.last_turn_assistant_content != '' -%}
122
+ {{- '<SPECIAL_11>Assistant
123
+ ' -}}
124
+ {%- if ns.enable_thinking is defined and ns.enable_thinking is false -%}
125
+ {{- '<think></think>' -}}
126
+ {%- else -%}
127
+ {{- '<think>
128
+ ' -}}
129
+ {%- endif -%}
130
+ {{- ns.last_turn_assistant_content -}}
131
+ {%- if continue_final_message is defined -%}
132
+ {%- if continue_final_message is false -%}
133
+ {{- '
134
+ <SPECIAL_12>
135
+ ' -}}
136
+ {%- endif -%}
137
+ {%- else -%}
138
+ {{- '
139
+ <SPECIAL_12>
140
+ ' -}}
141
+ {%- endif -%}
142
+ {%- endif -%}
143
+ {%- if ns.last_turn_assistant_tool_calls is defined and ns.last_turn_assistant_tool_calls | length > 0 -%}
144
+ {{- '<SPECIAL_11>Assistant
145
+ ' -}}
146
+ {{- '<TOOLCALL>[' -}}
147
+ {%- for call in ns.last_turn_assistant_tool_calls -%}
148
+ {%- set fn = call.function if call.function is defined else call -%}
149
+ {{- '{"name": "' + fn.name + '", "arguments": ' -}}
150
+ {%- if fn.arguments is string -%}
151
+ {{- fn.arguments -}}
152
+ {%- else -%}
153
+ {{- fn.arguments | tojson -}}
154
+ {%- endif -%}
155
+ {{- '}' + (', ' if not loop.last else '') -}}
156
+ {%- endfor -%}
157
+ {{- ']</TOOLCALL>' -}}
158
+ {{- '<SPECIAL_12>
159
+
160
+ ' -}}
161
+ {%- endif -%}
162
+ {%- endif -%}
backend/llama.cpp/models/templates/NousResearch-Hermes-2-Pro-Llama-3-8B-tool_use.jinja ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- macro json_to_python_type(json_spec) %}
2
+ {%- set basic_type_map = {
3
+ "string": "str",
4
+ "number": "float",
5
+ "integer": "int",
6
+ "boolean": "bool"
7
+ } %}
8
+
9
+ {%- if basic_type_map[json_spec.type] is defined %}
10
+ {{- basic_type_map[json_spec.type] }}
11
+ {%- elif json_spec.type == "array" %}
12
+ {{- "list[" + json_to_python_type(json_spec|items) + "]"}}
13
+ {%- elif json_spec.type == "object" %}
14
+ {%- if json_spec.additionalProperties is defined %}
15
+ {{- "dict[str, " + json_to_python_type(json_spec.additionalProperties) + ']'}}
16
+ {%- else %}
17
+ {{- "dict" }}
18
+ {%- endif %}
19
+ {%- elif json_spec.type is iterable %}
20
+ {{- "Union[" }}
21
+ {%- for t in json_spec.type %}
22
+ {{- json_to_python_type({"type": t}) }}
23
+ {%- if not loop.last %}
24
+ {{- "," }}
25
+ {%- endif %}
26
+ {%- endfor %}
27
+ {{- "]" }}
28
+ {%- else %}
29
+ {{- "Any" }}
30
+ {%- endif %}
31
+ {%- endmacro %}
32
+
33
+
34
+ {{- bos_token }}
35
+ {{- '<|im_start|>system
36
+ ' }}
37
+ {{- "You are a function calling AI model. You are provided with function signatures within <tools></tools> 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: <tools> " }}
38
+ {%- for tool in tools %}
39
+ {%- if tool.function is defined %}
40
+ {%- set tool = tool.function %}
41
+ {%- endif %}
42
+ {{- '{"type": "function", "function": ' }}
43
+ {{- '{"name": "' + tool.name + '", ' }}
44
+ {{- '"description": "' + tool.name + '(' }}
45
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
46
+ {{- param_name + ": " + json_to_python_type(param_fields) }}
47
+ {%- if not loop.last %}
48
+ {{- ", " }}
49
+ {%- endif %}
50
+ {%- endfor %}
51
+ {{- ")" }}
52
+ {%- if tool.return is defined %}
53
+ {{- " -> " + json_to_python_type(tool.return) }}
54
+ {%- endif %}
55
+ {{- " - " + tool.description + "
56
+
57
+ " }}
58
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
59
+ {%- if loop.first %}
60
+ {{- " Args:
61
+ " }}
62
+ {%- endif %}
63
+ {{- " " + param_name + "(" + json_to_python_type(param_fields) + "): " + param_fields.description|trim }}
64
+ {%- endfor %}
65
+ {%- if tool.return is defined and tool.return.description is defined %}
66
+ {{- "
67
+ Returns:
68
+ " + tool.return.description }}
69
+ {%- endif %}
70
+ {{- '"' }}
71
+ {{- ', "parameters": ' }}
72
+ {%- if tool.parameters.properties | length == 0 %}
73
+ {{- "{}" }}
74
+ {%- else %}
75
+ {{- tool.parameters|tojson }}
76
+ {%- endif %}
77
+ {{- "}" }}
78
+ {%- if not loop.last %}
79
+ {{- "
80
+ " }}
81
+ {%- endif %}
82
+ {%- endfor %}
83
+ {{- " </tools>" }}
84
+ {{- 'Use the following pydantic model json schema for each tool call you will make: {"properties": {"name": {"title": "Name", "type": "string"}, "arguments": {"title": "Arguments", "type": "object"}}, "required": ["name", "arguments"], "title": "FunctionCall", "type": "object"}}
85
+ ' }}
86
+ {{- "For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
87
+ " }}
88
+ {{- "<tool_call>
89
+ " }}
90
+ {{- '{"name": <function-name>, "arguments": <args-dict>}
91
+ ' }}
92
+ {{- '</tool_call><|im_end|>
93
+ ' }}
94
+ {%- for message in messages %}
95
+ {%- if message.role == "user" or message.role == "system" or (message.role == "assistant" and message.tool_calls is not defined) %}
96
+ {{- '<|im_start|>' + message.role + '
97
+ ' + message.content + '<|im_end|>' + '
98
+ ' }}
99
+ {%- elif message.role == "assistant" %}
100
+ {{- '<|im_start|>' + message.role }}
101
+ {%- for tool_call in message.tool_calls %}
102
+ {{- '
103
+ <tool_call>
104
+ ' }} {%- if tool_call.function is defined %}
105
+ {%- set tool_call = tool_call.function %}
106
+ {%- endif %}
107
+ {{- '{' }}
108
+ {{- '"name": "' }}
109
+ {{- tool_call.name }}
110
+ {{- '"' }}
111
+ {{- ', '}}
112
+ {%- if tool_call.arguments is defined %}
113
+ {{- '"arguments": ' }}
114
+ {%- if tool_call.arguments is string %}
115
+ {{- tool_call.arguments }}
116
+ {%- else %}
117
+ {{- tool_call.arguments|tojson }}
118
+ {%- endif %}
119
+ {%- endif %}
120
+ {{- '}' }}
121
+ {{- '
122
+ </tool_call>' }}
123
+ {%- endfor %}
124
+ {{- '<|im_end|>
125
+ ' }}
126
+ {%- elif message.role == "tool" %}
127
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
128
+ {{- '<|im_start|>tool
129
+ ' }}
130
+ {%- endif %}
131
+ {{- '<tool_response>
132
+ ' }}
133
+ {{- message.content }}
134
+ {%- if not loop.last %}
135
+ {{- '
136
+ </tool_response>
137
+ ' }}
138
+ {%- else %}
139
+ {{- '
140
+ </tool_response>' }}
141
+ {%- endif %}
142
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
143
+ {{- '<|im_end|>' }}
144
+ {%- elif loop.last %}
145
+ {{- '<|im_end|>' }}
146
+ {%- endif %}
147
+ {%- endif %}
148
+ {%- endfor %}
149
+ {%- if add_generation_prompt %}
150
+ {{- '<|im_start|>assistant
151
+ ' }}
152
+ {%- endif %}
backend/llama.cpp/models/templates/NousResearch-Hermes-3-Llama-3.1-8B-tool_use.jinja ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- macro json_to_python_type(json_spec) %}
2
+ {%- set basic_type_map = {
3
+ "string": "str",
4
+ "number": "float",
5
+ "integer": "int",
6
+ "boolean": "bool"
7
+ } %}
8
+
9
+ {%- if basic_type_map[json_spec.type] is defined %}
10
+ {{- basic_type_map[json_spec.type] }}
11
+ {%- elif json_spec.type == "array" %}
12
+ {{- "list[" + json_to_python_type(json_spec|items) + "]"}}
13
+ {%- elif json_spec.type == "object" %}
14
+ {%- if json_spec.additionalProperties is defined %}
15
+ {{- "dict[str, " + json_to_python_type(json_spec.additionalProperties) + ']'}}
16
+ {%- else %}
17
+ {{- "dict" }}
18
+ {%- endif %}
19
+ {%- elif json_spec.type is iterable %}
20
+ {{- "Union[" }}
21
+ {%- for t in json_spec.type %}
22
+ {{- json_to_python_type({"type": t}) }}
23
+ {%- if not loop.last %}
24
+ {{- "," }}
25
+ {%- endif %}
26
+ {%- endfor %}
27
+ {{- "]" }}
28
+ {%- else %}
29
+ {{- "Any" }}
30
+ {%- endif %}
31
+ {%- endmacro %}
32
+
33
+
34
+ {{- bos_token }}
35
+ {{- '<|im_start|>system
36
+ ' }}
37
+ {{- "You are a function calling AI model. You are provided with function signatures within <tools></tools> 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: <tools> " }}
38
+ {%- for tool in tools %}
39
+ {%- if tool.function is defined %}
40
+ {%- set tool = tool.function %}
41
+ {%- endif %}
42
+ {{- '{"type": "function", "function": ' }}
43
+ {{- '{"name": "' + tool.name + '", ' }}
44
+ {{- '"description": "' + tool.name + '(' }}
45
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
46
+ {{- param_name + ": " + json_to_python_type(param_fields) }}
47
+ {%- if not loop.last %}
48
+ {{- ", " }}
49
+ {%- endif %}
50
+ {%- endfor %}
51
+ {{- ")" }}
52
+ {%- if tool.return is defined %}
53
+ {{- " -> " + json_to_python_type(tool.return) }}
54
+ {%- endif %}
55
+ {{- " - " + tool.description + "
56
+
57
+ " }}
58
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
59
+ {%- if loop.first %}
60
+ {{- " Args:
61
+ " }}
62
+ {%- endif %}
63
+ {{- " " + param_name + "(" + json_to_python_type(param_fields) + "): " + param_fields.description|trim }}
64
+ {%- endfor %}
65
+ {%- if tool.return is defined and tool.return.description is defined %}
66
+ {{- "
67
+ Returns:
68
+ " + tool.return.description }}
69
+ {%- endif %}
70
+ {{- '"' }}
71
+ {{- ', "parameters": ' }}
72
+ {%- if tool.parameters.properties | length == 0 %}
73
+ {{- "{}" }}
74
+ {%- else %}
75
+ {{- tool.parameters|tojson }}
76
+ {%- endif %}
77
+ {{- "}" }}
78
+ {%- if not loop.last %}
79
+ {{- "
80
+ " }}
81
+ {%- endif %}
82
+ {%- endfor %}
83
+ {{- " </tools>" }}
84
+ {{- 'Use the following pydantic model json schema for each tool call you will make: {"properties": {"name": {"title": "Name", "type": "string"}, "arguments": {"title": "Arguments", "type": "object"}}, "required": ["name", "arguments"], "title": "FunctionCall", "type": "object"}}
85
+ ' }}
86
+ {{- "For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
87
+ " }}
88
+ {{- "<tool_call>
89
+ " }}
90
+ {{- '{"name": <function-name>, "arguments": <args-dict>}
91
+ ' }}
92
+ {{- '</tool_call><|im_end|>
93
+ ' }}
94
+ {%- for message in messages %}
95
+ {%- if message.role == "user" or message.role == "system" or (message.role == "assistant" and message.tool_calls is not defined) %}
96
+ {{- '<|im_start|>' + message.role + '
97
+ ' + message.content + '<|im_end|>' + '
98
+ ' }}
99
+ {%- elif message.role == "assistant" %}
100
+ {{- '<|im_start|>' + message.role }}
101
+ {%- for tool_call in message.tool_calls %}
102
+ {{- '
103
+ <tool_call>
104
+ ' }} {%- if tool_call.function is defined %}
105
+ {%- set tool_call = tool_call.function %}
106
+ {%- endif %}
107
+ {{- '{' }}
108
+ {{- '"name": "' }}
109
+ {{- tool_call.name }}
110
+ {{- '"' }}
111
+ {{- ', '}}
112
+ {%- if tool_call.arguments is defined %}
113
+ {{- '"arguments": ' }}
114
+ {%- if tool_call.arguments is string %}
115
+ {{- tool_call.arguments }}
116
+ {%- else %}
117
+ {{- tool_call.arguments|tojson }}
118
+ {%- endif %}
119
+ {%- endif %}
120
+ {{- '}' }}
121
+ {{- '
122
+ </tool_call>' }}
123
+ {%- endfor %}
124
+ {{- '<|im_end|>
125
+ ' }}
126
+ {%- elif message.role == "tool" %}
127
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
128
+ {{- '<|im_start|>tool
129
+ ' }}
130
+ {%- endif %}
131
+ {{- '<tool_response>
132
+ ' }}
133
+ {{- message.content }}
134
+ {%- if not loop.last %}
135
+ {{- '
136
+ </tool_response>
137
+ ' }}
138
+ {%- else %}
139
+ {{- '
140
+ </tool_response>' }}
141
+ {%- endif %}
142
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
143
+ {{- '<|im_end|>' }}
144
+ {%- elif loop.last %}
145
+ {{- '<|im_end|>' }}
146
+ {%- endif %}
147
+ {%- endif %}
148
+ {%- endfor %}
149
+ {%- if add_generation_prompt %}
150
+ {{- '<|im_start|>assistant
151
+ ' }}
152
+ {%- endif %}
backend/llama.cpp/models/templates/Qwen-QwQ-32B.jinja ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0]['role'] == 'system' %}
4
+ {{- messages[0]['content'] }}
5
+ {%- else %}
6
+ {{- '' }}
7
+ {%- endif %}
8
+ {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
9
+ {%- for tool in tools %}
10
+ {{- "\n" }}
11
+ {{- tool | tojson }}
12
+ {%- endfor %}
13
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
14
+ {%- else %}
15
+ {%- if messages[0]['role'] == 'system' %}
16
+ {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}
17
+ {%- endif %}
18
+ {%- endif %}
19
+ {%- for message in messages %}
20
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
21
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
22
+ {%- elif message.role == "assistant" and not message.tool_calls %}
23
+ {%- set content = message.content %}
24
+ {%- if not loop.last %}
25
+ {%- set content = message.content.split('</think>')[-1].lstrip('\n') %}
26
+ {%- endif %}
27
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
28
+ {%- elif message.role == "assistant" %}
29
+ {%- set content = message.content %}
30
+ {%- if not loop.last %}
31
+ {%- set content = message.content.split('</think>')[-1].lstrip('\n') %}
32
+ {%- endif %}
33
+ {{- '<|im_start|>' + message.role }}
34
+ {%- if message.content %}
35
+ {{- '\n' + content }}
36
+ {%- endif %}
37
+ {%- for tool_call in message.tool_calls %}
38
+ {%- if tool_call.function is defined %}
39
+ {%- set tool_call = tool_call.function %}
40
+ {%- endif %}
41
+ {{- '\n<tool_call>\n{"name": "' }}
42
+ {{- tool_call.name }}
43
+ {{- '", "arguments": ' }}
44
+ {{- tool_call.arguments | tojson }}
45
+ {{- '}\n</tool_call>' }}
46
+ {%- endfor %}
47
+ {{- '<|im_end|>\n' }}
48
+ {%- elif message.role == "tool" %}
49
+ {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}
50
+ {{- '<|im_start|>user' }}
51
+ {%- endif %}
52
+ {{- '\n<tool_response>\n' }}
53
+ {{- message.content }}
54
+ {{- '\n</tool_response>' }}
55
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
56
+ {{- '<|im_end|>\n' }}
57
+ {%- endif %}
58
+ {%- endif %}
59
+ {%- endfor %}
60
+ {%- if add_generation_prompt %}
61
+ {{- '<|im_start|>assistant\n<think>\n' }}
62
+ {%- if not enable_thinking -%}{{- '</think>' -}}{%- endif -%}
63
+ {%- endif %}
backend/llama.cpp/models/templates/Qwen-Qwen2.5-7B-Instruct.jinja ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0]['role'] == 'system' %}
4
+ {{- messages[0]['content'] }}
5
+ {%- else %}
6
+ {{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }}
7
+ {%- endif %}
8
+ {{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
9
+ {%- for tool in tools %}
10
+ {{- "\n" }}
11
+ {{- tool | tojson }}
12
+ {%- endfor %}
13
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
14
+ {%- else %}
15
+ {%- if messages[0]['role'] == 'system' %}
16
+ {{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}
17
+ {%- else %}
18
+ {{- '<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n' }}
19
+ {%- endif %}
20
+ {%- endif %}
21
+ {%- for message in messages %}
22
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}
23
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
24
+ {%- elif message.role == "assistant" %}
25
+ {{- '<|im_start|>' + message.role }}
26
+ {%- if message.content %}
27
+ {{- '\n' + message.content }}
28
+ {%- endif %}
29
+ {%- for tool_call in message.tool_calls %}
30
+ {%- if tool_call.function is defined %}
31
+ {%- set tool_call = tool_call.function %}
32
+ {%- endif %}
33
+ {{- '\n<tool_call>\n{"name": "' }}
34
+ {{- tool_call.name }}
35
+ {{- '", "arguments": ' }}
36
+ {{- tool_call.arguments | tojson }}
37
+ {{- '}\n</tool_call>' }}
38
+ {%- endfor %}
39
+ {{- '<|im_end|>\n' }}
40
+ {%- elif message.role == "tool" %}
41
+ {%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}
42
+ {{- '<|im_start|>user' }}
43
+ {%- endif %}
44
+ {{- '\n<tool_response>\n' }}
45
+ {{- message.content }}
46
+ {{- '\n</tool_response>' }}
47
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
48
+ {{- '<|im_end|>\n' }}
49
+ {%- endif %}
50
+ {%- endif %}
51
+ {%- endfor %}
52
+ {%- if add_generation_prompt %}
53
+ {{- '<|im_start|>assistant\n' }}
54
+ {%- endif %}
backend/llama.cpp/models/templates/Qwen-Qwen3-0.6B.jinja ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
27
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
28
+ {%- elif message.role == "assistant" %}
29
+ {%- set content = message.content %}
30
+ {%- set reasoning_content = '' %}
31
+ {%- if message.reasoning_content is defined and message.reasoning_content is not none %}
32
+ {%- set reasoning_content = message.reasoning_content %}
33
+ {%- else %}
34
+ {%- if '</think>' in message.content %}
35
+ {%- set content = message.content.split('</think>')[-1].lstrip('\n') %}
36
+ {%- set reasoning_content = message.content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
37
+ {%- endif %}
38
+ {%- endif %}
39
+ {%- if loop.index0 > ns.last_query_index %}
40
+ {%- if loop.last or (not loop.last and reasoning_content) %}
41
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
42
+ {%- else %}
43
+ {{- '<|im_start|>' + message.role + '\n' + content }}
44
+ {%- endif %}
45
+ {%- else %}
46
+ {{- '<|im_start|>' + message.role + '\n' + content }}
47
+ {%- endif %}
48
+ {%- if message.tool_calls %}
49
+ {%- for tool_call in message.tool_calls %}
50
+ {%- if (loop.first and content) or (not loop.first) %}
51
+ {{- '\n' }}
52
+ {%- endif %}
53
+ {%- if tool_call.function %}
54
+ {%- set tool_call = tool_call.function %}
55
+ {%- endif %}
56
+ {{- '<tool_call>\n{"name": "' }}
57
+ {{- tool_call.name }}
58
+ {{- '", "arguments": ' }}
59
+ {%- if tool_call.arguments is string %}
60
+ {{- tool_call.arguments }}
61
+ {%- else %}
62
+ {{- tool_call.arguments | tojson }}
63
+ {%- endif %}
64
+ {{- '}\n</tool_call>' }}
65
+ {%- endfor %}
66
+ {%- endif %}
67
+ {{- '<|im_end|>\n' }}
68
+ {%- elif message.role == "tool" %}
69
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
70
+ {{- '<|im_start|>user' }}
71
+ {%- endif %}
72
+ {{- '\n<tool_response>\n' }}
73
+ {{- message.content }}
74
+ {{- '\n</tool_response>' }}
75
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
76
+ {{- '<|im_end|>\n' }}
77
+ {%- endif %}
78
+ {%- endif %}
79
+ {%- endfor %}
80
+ {%- if add_generation_prompt %}
81
+ {{- '<|im_start|>assistant\n' }}
82
+ {%- if enable_thinking is defined and enable_thinking is false %}
83
+ {{- '<think>\n\n</think>\n\n' }}
84
+ {%- endif %}
85
+ {%- endif %}
backend/llama.cpp/models/templates/Qwen3-Coder.jinja ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro render_extra_keys(json_dict, handled_keys) %}
2
+ {%- if json_dict is mapping %}
3
+ {%- for json_key in json_dict if json_key not in handled_keys %}
4
+ {%- if json_dict[json_key] is mapping or (json_dict[json_key] is sequence and json_dict[json_key] is not string) %}
5
+ {{- '\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | tojson | safe) ~ '</' ~ json_key ~ '>' }}
6
+ {%- else %}
7
+ {{-'\n<' ~ json_key ~ '>' ~ (json_dict[json_key] | string) ~ '</' ~ json_key ~ '>' }}
8
+ {%- endif %}
9
+ {%- endfor %}
10
+ {%- endif %}
11
+ {% endmacro %}
12
+
13
+ {%- if messages[0]["role"] == "system" %}
14
+ {%- set system_message = messages[0]["content"] %}
15
+ {%- set loop_messages = messages[1:] %}
16
+ {%- else %}
17
+ {%- set loop_messages = messages %}
18
+ {%- endif %}
19
+
20
+ {%- if not tools is defined %}
21
+ {%- set tools = [] %}
22
+ {%- endif %}
23
+
24
+ {%- if system_message is defined %}
25
+ {{- "<|im_start|>system\n" + system_message }}
26
+ {%- else %}
27
+ {%- if tools is iterable and tools | length > 0 %}
28
+ {{- "<|im_start|>system\nYou are Qwen, a helpful AI assistant that can interact with a computer to solve tasks." }}
29
+ {%- endif %}
30
+ {%- endif %}
31
+ {%- if tools is iterable and tools | length > 0 %}
32
+ {{- "\n\n# Tools\n\nYou have access to the following tools:\n\n" }}
33
+ {{- "<tools>" }}
34
+ {%- for tool in tools %}
35
+ {%- if tool.function is defined %}
36
+ {%- set tool = tool.function %}
37
+ {%- endif %}
38
+ {{- "\n<function>\n<name>" ~ tool.name ~ "</name>" }}
39
+ {%- if tool.description is defined %}
40
+ {{- '\n<description>' ~ (tool.description | trim) ~ '</description>' }}
41
+ {%- endif %}
42
+ {{- '\n<parameters>' }}
43
+ {%- if tool.parameters is defined and tool.parameters is mapping and tool.parameters.properties is defined and tool.parameters.properties is mapping %}
44
+ {%- for param_name, param_fields in tool.parameters.properties|items %}
45
+ {{- '\n<parameter>' }}
46
+ {{- '\n<name>' ~ param_name ~ '</name>' }}
47
+ {%- if param_fields.type is defined %}
48
+ {{- '\n<type>' ~ (param_fields.type | string) ~ '</type>' }}
49
+ {%- endif %}
50
+ {%- if param_fields.description is defined %}
51
+ {{- '\n<description>' ~ (param_fields.description | trim) ~ '</description>' }}
52
+ {%- endif %}
53
+ {%- set handled_keys = ['name', 'type', 'description'] %}
54
+ {{- render_extra_keys(param_fields, handled_keys) }}
55
+ {{- '\n</parameter>' }}
56
+ {%- endfor %}
57
+ {%- endif %}
58
+ {% set handled_keys = ['type', 'properties'] %}
59
+ {{- render_extra_keys(tool.parameters, handled_keys) }}
60
+ {{- '\n</parameters>' }}
61
+ {%- set handled_keys = ['type', 'name', 'description', 'parameters'] %}
62
+ {{- render_extra_keys(tool, handled_keys) }}
63
+ {{- '\n</function>' }}
64
+ {%- endfor %}
65
+ {{- "\n</tools>" }}
66
+ {{- '\n\nIf you choose to call a tool ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nvalue_2\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: the tool calling block MUST begin with an opening <tool_call> tag and end with a closing </tool_call> tag.\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
67
+ {%- endif %}
68
+ {%- if system_message is defined %}
69
+ {{- '<|im_end|>\n' }}
70
+ {%- else %}
71
+ {%- if tools is iterable and tools | length > 0 %}
72
+ {{- '<|im_end|>\n' }}
73
+ {%- endif %}
74
+ {%- endif %}
75
+ {%- for message in loop_messages %}
76
+ {%- if message.role == "assistant" and message.tool_calls is defined and message.tool_calls is iterable and message.tool_calls | length > 0 %}
77
+ {{- '<|im_start|>' + message.role }}
78
+ {%- if message.content is defined and message.content is string and message.content | trim | length > 0 %}
79
+ {{- '\n' + message.content | trim + '\n' }}
80
+ {%- endif %}
81
+ {%- for tool_call in message.tool_calls %}
82
+ {%- if tool_call.function is defined %}
83
+ {%- set tool_call = tool_call.function %}
84
+ {%- endif %}
85
+ {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
86
+ {%- if tool_call.arguments is defined %}
87
+ {%- for args_name, args_value in tool_call.arguments|items %}
88
+ {{- '<parameter=' + args_name + '>\n' }}
89
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
90
+ {{- args_value }}
91
+ {{- '\n</parameter>\n' }}
92
+ {%- endfor %}
93
+ {%- endif %}
94
+ {{- '</function>\n</tool_call>' }}
95
+ {%- endfor %}
96
+ {{- '<|im_end|>\n' }}
97
+ {%- elif message.role == "user" or message.role == "system" or message.role == "assistant" %}
98
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}
99
+ {%- elif message.role == "tool" %}
100
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
101
+ {{- '<|im_start|>user\n' }}
102
+ {%- endif %}
103
+ {{- '<tool_response>\n' }}
104
+ {{- message.content }}
105
+ {{- '\n</tool_response>\n' }}
106
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
107
+ {{- '<|im_end|>\n' }}
108
+ {%- elif loop.last %}
109
+ {{- '<|im_end|>\n' }}
110
+ {%- endif %}
111
+ {%- else %}
112
+ {{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>\n' }}
113
+ {%- endif %}
114
+ {%- endfor %}
115
+ {%- if add_generation_prompt %}
116
+ {{- '<|im_start|>assistant\n' }}
117
+ {%- endif %}
backend/llama.cpp/models/templates/Qwen3.5-4B.jinja ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- set image_count = namespace(value=0) %}
2
+ {%- set video_count = namespace(value=0) %}
3
+ {%- macro render_content(content, do_vision_count, is_system_content=false) %}
4
+ {%- if content is string %}
5
+ {{- content }}
6
+ {%- elif content is iterable and content is not mapping %}
7
+ {%- for item in content %}
8
+ {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}
9
+ {%- if is_system_content %}
10
+ {{- raise_exception('System message cannot contain images.') }}
11
+ {%- endif %}
12
+ {%- if do_vision_count %}
13
+ {%- set image_count.value = image_count.value + 1 %}
14
+ {%- endif %}
15
+ {%- if add_vision_id %}
16
+ {{- 'Picture ' ~ image_count.value ~ ': ' }}
17
+ {%- endif %}
18
+ {{- '<|vision_start|><|image_pad|><|vision_end|>' }}
19
+ {%- elif 'video' in item or item.type == 'video' %}
20
+ {%- if is_system_content %}
21
+ {{- raise_exception('System message cannot contain videos.') }}
22
+ {%- endif %}
23
+ {%- if do_vision_count %}
24
+ {%- set video_count.value = video_count.value + 1 %}
25
+ {%- endif %}
26
+ {%- if add_vision_id %}
27
+ {{- 'Video ' ~ video_count.value ~ ': ' }}
28
+ {%- endif %}
29
+ {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
30
+ {%- elif 'text' in item %}
31
+ {{- item.text }}
32
+ {%- else %}
33
+ {{- raise_exception('Unexpected item type in content.') }}
34
+ {%- endif %}
35
+ {%- endfor %}
36
+ {%- elif content is none or content is undefined %}
37
+ {{- '' }}
38
+ {%- else %}
39
+ {{- raise_exception('Unexpected content type.') }}
40
+ {%- endif %}
41
+ {%- endmacro %}
42
+ {%- if not messages %}
43
+ {{- raise_exception('No messages provided.') }}
44
+ {%- endif %}
45
+ {%- if tools and tools is iterable and tools is not mapping %}
46
+ {{- '<|im_start|>system\n' }}
47
+ {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
48
+ {%- for tool in tools %}
49
+ {{- "\n" }}
50
+ {{- tool | tojson }}
51
+ {%- endfor %}
52
+ {{- "\n</tools>" }}
53
+ {{- '\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>' }}
54
+ {%- if messages[0].role == 'system' %}
55
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
56
+ {%- if content %}
57
+ {{- '\n\n' + content }}
58
+ {%- endif %}
59
+ {%- endif %}
60
+ {{- '<|im_end|>\n' }}
61
+ {%- else %}
62
+ {%- if messages[0].role == 'system' %}
63
+ {%- set content = render_content(messages[0].content, false, true)|trim %}
64
+ {{- '<|im_start|>system\n' + content + '<|im_end|>\n' }}
65
+ {%- endif %}
66
+ {%- endif %}
67
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
68
+ {%- for message in messages[::-1] %}
69
+ {%- set index = (messages|length - 1) - loop.index0 %}
70
+ {%- if ns.multi_step_tool and message.role == "user" %}
71
+ {%- set content = render_content(message.content, false)|trim %}
72
+ {%- if not(content.startswith('<tool_response>') and content.endswith('</tool_response>')) %}
73
+ {%- set ns.multi_step_tool = false %}
74
+ {%- set ns.last_query_index = index %}
75
+ {%- endif %}
76
+ {%- endif %}
77
+ {%- endfor %}
78
+ {%- if ns.multi_step_tool %}
79
+ {{- raise_exception('No user query found in messages.') }}
80
+ {%- endif %}
81
+ {%- for message in messages %}
82
+ {%- set content = render_content(message.content, true)|trim %}
83
+ {%- if message.role == "system" %}
84
+ {%- if not loop.first %}
85
+ {{- raise_exception('System message must be at the beginning.') }}
86
+ {%- endif %}
87
+ {%- elif message.role == "user" %}
88
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
89
+ {%- elif message.role == "assistant" %}
90
+ {%- set reasoning_content = '' %}
91
+ {%- if message.reasoning_content is string %}
92
+ {%- set reasoning_content = message.reasoning_content %}
93
+ {%- else %}
94
+ {%- if '</think>' in content %}
95
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
96
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
97
+ {%- endif %}
98
+ {%- endif %}
99
+ {%- set reasoning_content = reasoning_content|trim %}
100
+ {%- if loop.index0 > ns.last_query_index %}
101
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n\n' + content }}
102
+ {%- else %}
103
+ {{- '<|im_start|>' + message.role + '\n' + content }}
104
+ {%- endif %}
105
+ {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}
106
+ {%- for tool_call in message.tool_calls %}
107
+ {%- if tool_call.function is defined %}
108
+ {%- set tool_call = tool_call.function %}
109
+ {%- endif %}
110
+ {%- if loop.first %}
111
+ {%- if content|trim %}
112
+ {{- '\n\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
113
+ {%- else %}
114
+ {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
115
+ {%- endif %}
116
+ {%- else %}
117
+ {{- '\n<tool_call>\n<function=' + tool_call.name + '>\n' }}
118
+ {%- endif %}
119
+ {%- if tool_call.arguments is defined %}
120
+ {%- for args_name, args_value in tool_call.arguments|items %}
121
+ {{- '<parameter=' + args_name + '>\n' }}
122
+ {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
123
+ {{- args_value }}
124
+ {{- '\n</parameter>\n' }}
125
+ {%- endfor %}
126
+ {%- endif %}
127
+ {{- '</function>\n</tool_call>' }}
128
+ {%- endfor %}
129
+ {%- endif %}
130
+ {{- '<|im_end|>\n' }}
131
+ {%- elif message.role == "tool" %}
132
+ {%- if loop.previtem and loop.previtem.role != "tool" %}
133
+ {{- '<|im_start|>user' }}
134
+ {%- endif %}
135
+ {{- '\n<tool_response>\n' }}
136
+ {{- content }}
137
+ {{- '\n</tool_response>' }}
138
+ {%- if not loop.last and loop.nextitem.role != "tool" %}
139
+ {{- '<|im_end|>\n' }}
140
+ {%- elif loop.last %}
141
+ {{- '<|im_end|>\n' }}
142
+ {%- endif %}
143
+ {%- else %}
144
+ {{- raise_exception('Unexpected message role.') }}
145
+ {%- endif %}
146
+ {%- endfor %}
147
+ {%- if add_generation_prompt %}
148
+ {{- '<|im_start|>assistant\n' }}
149
+ {%- if enable_thinking is defined and enable_thinking is false %}
150
+ {{- '<think>\n\n</think>\n\n' }}
151
+ {%- else %}
152
+ {{- '<think>\n' }}
153
+ {%- endif %}
154
+ {%- endif %}
backend/llama.cpp/models/templates/README.md ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ These templates can be updated with the following commands:
2
+
3
+ ```bash
4
+ ./scripts/get_chat_template.py CohereForAI/c4ai-command-r-plus tool_use > models/templates/CohereForAI-c4ai-command-r-plus-tool_use.jinja
5
+ ./scripts/get_chat_template.py CohereForAI/c4ai-command-r7b-12-2024 default > models/templates/CohereForAI-c4ai-command-r7b-12-2024-default.jinja
6
+ ./scripts/get_chat_template.py CohereForAI/c4ai-command-r7b-12-2024 rag > models/templates/CohereForAI-c4ai-command-r7b-12-2024-rag.jinja
7
+ ./scripts/get_chat_template.py CohereForAI/c4ai-command-r7b-12-2024 tool_use > models/templates/CohereForAI-c4ai-command-r7b-12-2024-tool_use.jinja
8
+ ./scripts/get_chat_template.py deepseek-ai/DeepSeek-R1-Distill-Llama-8B > models/templates/deepseek-ai-DeepSeek-R1-Distill-Llama-8B.jinja
9
+ ./scripts/get_chat_template.py deepseek-ai/DeepSeek-R1-Distill-Qwen-32B > models/templates/deepseek-ai-DeepSeek-R1-Distill-Qwen-32B.jinja
10
+ ./scripts/get_chat_template.py fireworks-ai/llama-3-firefunction-v2 > models/templates/fireworks-ai-llama-3-firefunction-v2.jinja
11
+ ./scripts/get_chat_template.py google/gemma-2-2b-it > models/templates/google-gemma-2-2b-it.jinja
12
+ ./scripts/get_chat_template.py meetkai/functionary-medium-v3.1 > models/templates/meetkai-functionary-medium-v3.1.jinja
13
+ ./scripts/get_chat_template.py meetkai/functionary-medium-v3.2 > models/templates/meetkai-functionary-medium-v3.2.jinja
14
+ ./scripts/get_chat_template.py meta-llama/Llama-3.1-8B-Instruct > models/templates/meta-llama-Llama-3.1-8B-Instruct.jinja
15
+ ./scripts/get_chat_template.py meta-llama/Llama-3.2-3B-Instruct > models/templates/meta-llama-Llama-3.2-3B-Instruct.jinja
16
+ ./scripts/get_chat_template.py meta-llama/Llama-3.3-70B-Instruct > models/templates/meta-llama-Llama-3.3-70B-Instruct.jinja
17
+ ./scripts/get_chat_template.py microsoft/Phi-3.5-mini-instruct > models/templates/microsoft-Phi-3.5-mini-instruct.jinja
18
+ ./scripts/get_chat_template.py mistralai/Mistral-Nemo-Instruct-2407 > models/templates/mistralai-Mistral-Nemo-Instruct-2407.jinja
19
+ ./scripts/get_chat_template.py NousResearch/Hermes-2-Pro-Llama-3-8B tool_use > models/templates/NousResearch-Hermes-2-Pro-Llama-3-8B-tool_use.jinja
20
+ ./scripts/get_chat_template.py NousResearch/Hermes-3-Llama-3.1-8B tool_use > models/templates/NousResearch-Hermes-3-Llama-3.1-8B-tool_use.jinja
21
+ ./scripts/get_chat_template.py Qwen/Qwen2.5-7B-Instruct > models/templates/Qwen-Qwen2.5-7B-Instruct.jinja
22
+ ./scripts/get_chat_template.py Qwen/QwQ-32B > models/templates/Qwen-QwQ-32B.jinja
23
+ ./scripts/get_chat_template.py Qwen/Qwen3-0.6B > models/templates/Qwen-Qwen3-0.6B.jinja
24
+ ./scripts/get_chat_template.py zai-org/GLM-4.5 > models/templates/zai-org-GLM-4.5.jinja
25
+ ./scripts/get_chat_template.py deepseek-ai/DeepSeek-V3.1 > models/templates/deepseek-ai-DeepSeek-V3.1.jinja
26
+ ```
backend/llama.cpp/models/templates/Reka-Edge.jinja ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- macro render_content(content, num_img_tokens, num_video_frames) -%}
2
+ {%- if content is string -%}
3
+ {{- content -}}
4
+ {%- elif content is sequence -%}
5
+ {%- set ns = namespace(out="", prev_was_text=false) -%}
6
+ {%- for item in content -%}
7
+ {%- set item_type = item.get("type") -%}
8
+ {%- if item_type == "text" or item.get("text") is not none -%}
9
+ {%- set text = item.get("text", "") -%}
10
+ {%- if text -%}
11
+ {%- if ns.prev_was_text -%}
12
+ {%- set ns.out = ns.out ~ " " -%}
13
+ {%- endif -%}
14
+ {%- set ns.out = ns.out ~ text -%}
15
+ {%- endif -%}
16
+ {%- set ns.prev_was_text = text != "" -%}
17
+ {%- elif item_type in ["image", "image_url"] or item.get("image") is not none or item.get("image_url") is not none -%}
18
+ {%- set ns.out = ns.out ~ "<image>" ~ ("<REKA_IMG_TOKEN>" * num_img_tokens) ~ "</image>" -%}
19
+ {%- set ns.prev_was_text = false -%}
20
+ {%- elif item_type in ["video", "video_url"] or item.get("video") is not none or item.get("video_url") is not none -%}
21
+ {%- set repeat_tokens = num_img_tokens * num_video_frames -%}
22
+ {%- set ns.out = ns.out ~ "<video>" ~ ("<REKA_IMG_TOKEN>" * repeat_tokens) ~ "</video>" -%}
23
+ {%- set ns.prev_was_text = false -%}
24
+ {%- endif -%}
25
+ {%- endfor -%}
26
+ {{- ns.out -}}
27
+ {%- endif -%}
28
+ {%- endmacro -%}
29
+ {%- set ns = namespace(out="", last_query_index=messages|length - 1) -%}
30
+ {%- for msg in messages[::-1] -%}
31
+ {%- set idx = messages|length - 1 - loop.index0 -%}
32
+ {%- if msg.get("role") == "user" -%}
33
+ {%- set content = msg.get("content", "") -%}
34
+ {%- if not (content is string and content.startswith("<tool_response>") and content.endswith("</tool_response>")) -%}
35
+ {%- set ns.last_query_index = idx -%}
36
+ {%- break -%}
37
+ {%- endif -%}
38
+ {%- endif -%}
39
+ {%- endfor -%}
40
+ {%- set last_query_index = ns.last_query_index -%}
41
+ {%- set num_img_tokens = num_img_tokens | default(64, true) | int -%}
42
+ {%- set num_video_frames = num_video_frames | default(6, true) | int -%}
43
+ {%- set start_idx = 0 -%}
44
+ {%- set system_text = "" -%}
45
+ {%- if messages|length > 0 and messages[0].get("role") in ["system", "developer"] -%}
46
+ {%- set system_text = render_content(messages[0].get("content", ""), num_img_tokens, num_video_frames) -%}
47
+ {%- set start_idx = 1 -%}
48
+ {%- endif -%}
49
+ {%- if tools or system_text -%}
50
+ {%- set preamble_ns = namespace(text="") -%}
51
+ {%- if system_text -%}
52
+ {%- set preamble_ns.text = "system: " ~ system_text -%}
53
+ {%- endif -%}
54
+ {%- if tools -%}
55
+ {%- if preamble_ns.text -%}
56
+ {%- set preamble_ns.text = preamble_ns.text ~ "\n\n" -%}
57
+ {%- else -%}
58
+ {%- set preamble_ns.text = "system: " -%}
59
+ {%- endif -%}
60
+ {%- set preamble_ns.text = preamble_ns.text
61
+ ~ "# Tools\n\n"
62
+ ~ "You may call one or more functions to assist with the user query.\n\n"
63
+ ~ "You are provided with function signatures within <tools></tools> XML tags:\n"
64
+ ~ "<tools>" -%}
65
+ {%- for tool in tools -%}
66
+ {%- set preamble_ns.text = preamble_ns.text ~ "\n" ~ (tool | tojson(ensure_ascii=True)) -%}
67
+ {%- endfor -%}
68
+ {%- set preamble_ns.text = preamble_ns.text
69
+ ~ "\n</tools>\n\n"
70
+ ~ "For each function call, return a json object with function name and arguments "
71
+ ~ "within <tool_call></tool_call> XML tags:\n"
72
+ ~ "<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call>" -%}
73
+ {%- endif -%}
74
+ {%- set ns.out = ns.out ~ preamble_ns.text ~ "\n\n<sep>" -%}
75
+ {%- endif -%}
76
+ {%- for idx in range(start_idx, messages|length) -%}
77
+ {%- set message = messages[idx] -%}
78
+ {%- set role = message.get("role") -%}
79
+ {%- set content = message.get("content") -%}
80
+ {%- if role == "user" -%}
81
+ {%- set prefix_ns = namespace(value="human: ") -%}
82
+ {%- if content is sequence and content is not string -%}
83
+ {%- for item in content -%}
84
+ {%- if item.get("type") == "text" or item.get("text") is not none -%}
85
+ {%- set text = item.get("text", "") -%}
86
+ {%- if text -%}
87
+ {%- break -%}
88
+ {%- endif -%}
89
+ {%- elif item.get("type") in ["image", "image_url", "video", "video_url"] -%}
90
+ {%- set prefix_ns.value = "human:" -%}
91
+ {%- break -%}
92
+ {%- endif -%}
93
+ {%- endfor -%}
94
+ {%- endif -%}
95
+ {%- set ns.out = ns.out ~ prefix_ns.value ~ render_content(content, num_img_tokens, num_video_frames) ~ "<sep>" -%}
96
+ {%- elif role == "assistant" -%}
97
+ {%- set tool_calls = message.get("tool_calls") -%}
98
+ {%- set content_text = render_content(content, num_img_tokens, num_video_frames) -%}
99
+ {%- set reasoning_text = "" -%}
100
+ {%- if message.get("reasoning_content") is string -%}
101
+ {%- set reasoning_text = message.get("reasoning_content") -%}
102
+ {%- elif "</think>" in content_text -%}
103
+ {%- set reasoning_text = content_text.split("</think>", 1)[0].rstrip("\n").split("<think>")[-1].lstrip("\n") -%}
104
+ {%- set content_text = content_text.split("</think>", 1)[1].lstrip("\n") -%}
105
+ {%- endif -%}
106
+ {%- set ns.out = ns.out ~ "assistant: " -%}
107
+ {%- set include_thinking = enable_thinking is true
108
+ and idx > last_query_index
109
+ and (idx == messages|length - 1 or reasoning_text)
110
+ -%}
111
+ {%- if include_thinking -%}
112
+ {%- set ns.out = ns.out ~ "<think>\n" ~ (reasoning_text.strip() ) ~ "\n</think>\n\n" -%}
113
+ {%- endif -%}
114
+ {%- set ns.out = ns.out ~ content_text -%}
115
+ {%- if tool_calls -%}
116
+ {%- if content_text and not ns.out.endswith("\n") -%}
117
+ {%- set ns.out = ns.out ~ "\n" -%}
118
+ {%- endif -%}
119
+ {%- for tool_call in tool_calls -%}
120
+ {%- if tool_call.get("function") is not none -%}
121
+ {%- set tool_call = tool_call.get("function") -%}
122
+ {%- endif -%}
123
+ {%- set arguments = tool_call.get("arguments", {}) -%}
124
+ {%- if arguments is string -%}
125
+ {%- set arguments_json = arguments -%}
126
+ {%- elif arguments is mapping -%}
127
+ {%- set arguments_json = arguments | tojson(ensure_ascii=True) -%}
128
+ {%- else -%}
129
+ {%- set arguments_json = arguments | tojson(ensure_ascii=True) -%}
130
+ {%- endif -%}
131
+ {%- set ns.out = ns.out
132
+ ~ "<tool_call>\n"
133
+ ~ "{\"name\": \"" ~ tool_call.get("name", "") ~ "\", \"arguments\": "
134
+ ~ arguments_json
135
+ ~ "}\n</tool_call>" -%}
136
+ {%- endfor -%}
137
+ {%- endif -%}
138
+ {%- if not (continue_final_message and idx == messages|length - 1) -%}
139
+ {%- set ns.out = ns.out ~ "\n\n<sep>" -%}
140
+ {%- endif -%}
141
+ {%- elif role == "tool" -%}
142
+ {%- if idx == start_idx or messages[idx - 1].get("role") != "tool" -%}
143
+ {%- set ns.out = ns.out ~ "human: " -%}
144
+ {%- endif -%}
145
+ {%- set response_text = render_content(content, num_img_tokens, num_video_frames) -%}
146
+ {%- set ns.out = ns.out ~ "<tool_response>\n" ~ response_text ~ "\n</tool_response>" -%}
147
+ {%- if idx == messages|length - 1 or messages[idx + 1].get("role") != "tool" -%}
148
+ {%- set ns.out = ns.out ~ "<sep>" -%}
149
+ {%- endif -%}
150
+ {%- endif -%}
151
+ {%- endfor -%}
152
+ {%- if add_generation_prompt
153
+ and (messages|length == 0 or messages[-1].get("role") != "assistant")
154
+ -%}
155
+ {%- if enable_thinking is true -%}
156
+ {%- set ns.out = ns.out ~ "assistant: <think>\n" -%}
157
+ {%- else -%}
158
+ {%- set ns.out = ns.out ~ "assistant:" -%}
159
+ {%- endif -%}
160
+ {%- endif -%}
161
+ {{- ns.out -}}
backend/llama.cpp/models/templates/StepFun3.5-Flash.jinja ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {% macro render_content(content) %}{% if content is none %}{{- '' }}{% elif content is string %}{{- content }}{% elif content is mapping %}{{- content['value'] if 'value' in content else content['text'] }}{% elif content is iterable %}{% for item in content %}{% if item.type == 'text' %}{{- item['value'] if 'value' in item else item['text'] }}{% elif item.type == 'image' %}<im_patch>{% endif %}{% endfor %}{% endif %}{% endmacro %}
2
+ {{bos_token}}{%- if tools %}
3
+ {{- '<|im_start|>system\n' }}
4
+ {%- if messages[0].role == 'system' %}
5
+ {{- render_content(messages[0].content) + '\n\n' }}
6
+ {%- endif %}
7
+ {{- "# Tools\n\nYou have access to the following functions in JSONSchema format:\n\n<tools>" }}
8
+ {%- for tool in tools %}
9
+ {{- "\n" }}
10
+ {{- tool | tojson(ensure_ascii=False) }}
11
+ {%- endfor %}
12
+ {{- "\n</tools>\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...>\n...\n</function> block must be nested within <tool_call>\n...\n</tool_call> XML tags\n- Required parameters MUST be specified\n</IMPORTANT><|im_end|>\n" }}
13
+ {%- else %}
14
+ {%- if messages[0].role == 'system' %}
15
+ {{- '<|im_start|>system\n' + render_content(messages[0].content) + '<|im_end|>\n' }}
16
+ {%- endif %}
17
+ {%- endif %}
18
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
19
+ {%- for message in messages[::-1] %}
20
+ {%- set index = (messages|length - 1) - loop.index0 %}
21
+ {%- if ns.multi_step_tool and message.role == "user" and render_content(message.content) is string and not(render_content(message.content).startswith('<tool_response>') and render_content(message.content).endswith('</tool_response>')) %}
22
+ {%- set ns.multi_step_tool = false %}
23
+ {%- set ns.last_query_index = index %}
24
+ {%- endif %}
25
+ {%- endfor %}
26
+ {%- for message in messages %}
27
+ {%- set content = render_content(message.content) %}
28
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
29
+ {%- set role_name = 'observation' if (message.role == "system" and not loop.first and message.name == 'observation') else message.role %}
30
+ {{- '<|im_start|>' + role_name + '\n' + content + '<|im_end|>' + '\n' }}
31
+ {%- elif message.role == "assistant" %}
32
+ {%- if message.reasoning_content is string %}
33
+ {%- set reasoning_content = render_content(message.reasoning_content) %}
34
+ {%- else %}
35
+ {%- if '</think>' in content %}
36
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
37
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
38
+ {%- else %}
39
+ {%- set reasoning_content = '' %}
40
+ {%- endif %}
41
+ {%- endif %}
42
+ {%- if loop.index0 > ns.last_query_index %}
43
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content + '\n</think>\n' + content }}
44
+ {%- else %}
45
+ {{- '<|im_start|>' + message.role + '\n' + content }}
46
+ {%- endif %}
47
+ {%- if message.tool_calls %}
48
+ {%- for tool_call in message.tool_calls %}
49
+ {%- if tool_call.function is defined %}
50
+ {%- set tool_call = tool_call.function %}
51
+ {%- endif %}
52
+ {{- '<tool_call>\n<function=' + tool_call.name + '>\n' }}
53
+ {%- if tool_call.arguments is defined %}
54
+ {%- set arguments = tool_call.arguments %}
55
+ {%- for args_name, args_value in arguments|items %}
56
+ {{- '<parameter=' + args_name + '>\n' }}
57
+ {%- set args_value = args_value | tojson(ensure_ascii=False) | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}
58
+ {{- args_value }}
59
+ {{- '\n</parameter>\n' }}
60
+ {%- endfor %}
61
+ {%- endif %}
62
+ {{- '</function>\n</tool_call>' }}
63
+ {%- endfor %}
64
+ {%- endif %}
65
+ {{- '<|im_end|>\n' }}
66
+ {%- elif message.role == "tool" %}
67
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
68
+ {{- '<|im_start|>tool_response\n' }}
69
+ {%- endif %}
70
+ {{- '<tool_response>' }}
71
+ {{- content }}
72
+ {{- '</tool_response>' }}
73
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
74
+ {{- '<|im_end|>\n' }}
75
+ {%- endif %}
76
+ {%- endif %}
77
+ {%- endfor %}
78
+ {%- if add_generation_prompt %}
79
+ {{- '<|im_start|>assistant\n<think>\n' }}
80
+ {%- endif %}
backend/llama.cpp/models/templates/moonshotai-Kimi-K2.jinja ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools -%}
2
+ <|im_system|>tool_declare<|im_middle|>{{ tools | tojson }}<|im_end|>
3
+ {%- endif -%}
4
+ {%- for message in messages -%}
5
+ {%- if loop.first and messages[0]['role'] != 'system' -%}
6
+ <|im_system|>system<|im_middle|>You are a helpful assistant<|im_end|>
7
+ {%- endif -%}
8
+ {%- if message['role'] == 'system' -%}
9
+ <|im_system|>system<|im_middle|>
10
+ {%- elif message['role'] == 'user' -%}
11
+ <|im_user|>user<|im_middle|>
12
+ {%- elif message['role'] == 'assistant' -%}
13
+ <|im_assistant|>assistant<|im_middle|>
14
+ {%- elif message['role'] == 'tool' -%}
15
+ <|im_system|>tool<|im_middle|>
16
+ {%- endif -%}
17
+ {%- if message['role'] == 'assistant' and message.get('tool_calls') -%}
18
+ {%- if message['content'] -%}{{ message['content'] }}{%- endif -%}
19
+ <|tool_calls_section_begin|>
20
+ {%- for tool_call in message['tool_calls'] -%}
21
+ {%- set func_name = tool_call['function']['name'] -%}
22
+ {%- set formatted_id = 'functions.' + func_name + ':' + loop.index0|string -%}
23
+ <|tool_call_begin|>{{ formatted_id }}<|tool_call_argument_begin|>{{ tool_call['function']['arguments'] | tojson}}<|tool_call_end|>
24
+ {%- endfor -%}
25
+ <|tool_calls_section_end|>
26
+ {%- elif message['role'] == 'tool' -%}
27
+ ## Return of {{ message.tool_call_id }}\n{{ message['content'] }}
28
+ {%- elif message['content'] is string -%}
29
+ {{ message['content'] }}
30
+ {%- elif message['content'] is not none -%}
31
+ {% for content in message['content'] -%}
32
+ {% if content['type'] == 'image' or 'image' in content or 'image_url' in content -%}
33
+ <|media_start|>image<|media_content|><|media_pad|><|media_end|>
34
+ {% else -%}
35
+ {{ content['text'] }}
36
+ {%- endif -%}
37
+ {%- endfor -%}
38
+ {%- endif -%}
39
+ <|im_end|>
40
+ {%- endfor -%}
41
+ {%- if add_generation_prompt -%}
42
+ <|im_assistant|>assistant<|im_middle|>
43
+ {%- endif -%}
backend/llama.cpp/models/templates/openai-gpt-oss-120b.jinja ADDED
@@ -0,0 +1,331 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#-
2
+ In addition to the normal inputs of `messages` and `tools`, this template also accepts the
3
+ following kwargs:
4
+ - "builtin_tools": A list, can contain "browser" and/or "python".
5
+ - "model_identity": A string that optionally describes the model identity.
6
+ - "reasoning_effort": A string that describes the reasoning effort, defaults to "medium".
7
+ #}
8
+
9
+ {#- Tool Definition Rendering ============================================== #}
10
+ {%- macro render_typescript_type(param_spec, required_params, is_nullable=false) -%}
11
+ {%- if param_spec.type == "array" -%}
12
+ {%- if param_spec['items'] -%}
13
+ {%- if param_spec['items']['type'] == "string" -%}
14
+ {{- "string[]" }}
15
+ {%- elif param_spec['items']['type'] == "number" -%}
16
+ {{- "number[]" }}
17
+ {%- elif param_spec['items']['type'] == "integer" -%}
18
+ {{- "number[]" }}
19
+ {%- elif param_spec['items']['type'] == "boolean" -%}
20
+ {{- "boolean[]" }}
21
+ {%- else -%}
22
+ {%- set inner_type = render_typescript_type(param_spec['items'], required_params) -%}
23
+ {%- if inner_type == "object | object" or inner_type|length > 50 -%}
24
+ {{- "any[]" }}
25
+ {%- else -%}
26
+ {{- inner_type + "[]" }}
27
+ {%- endif -%}
28
+ {%- endif -%}
29
+ {%- if param_spec.nullable -%}
30
+ {{- " | null" }}
31
+ {%- endif -%}
32
+ {%- else -%}
33
+ {{- "any[]" }}
34
+ {%- if param_spec.nullable -%}
35
+ {{- " | null" }}
36
+ {%- endif -%}
37
+ {%- endif -%}
38
+ {%- elif param_spec.type is defined and param_spec.type is iterable and param_spec.type is not string and param_spec.type is not mapping and param_spec.type[0] is defined -%}
39
+ {#- Handle array of types like ["object", "object"] from Union[dict, list] #}
40
+ {%- if param_spec.type | length > 1 -%}
41
+ {{- param_spec.type | join(" | ") }}
42
+ {%- else -%}
43
+ {{- param_spec.type[0] }}
44
+ {%- endif -%}
45
+ {%- elif param_spec.oneOf -%}
46
+ {#- Handle oneOf schemas - check for complex unions and fallback to any #}
47
+ {%- set has_object_variants = false -%}
48
+ {%- for variant in param_spec.oneOf -%}
49
+ {%- if variant.type == "object" -%}
50
+ {%- set has_object_variants = true -%}
51
+ {%- endif -%}
52
+ {%- endfor -%}
53
+ {%- if has_object_variants and param_spec.oneOf|length > 1 -%}
54
+ {{- "any" }}
55
+ {%- else -%}
56
+ {%- for variant in param_spec.oneOf -%}
57
+ {{- render_typescript_type(variant, required_params) -}}
58
+ {%- if variant.description %}
59
+ {{- "// " + variant.description }}
60
+ {%- endif -%}
61
+ {%- if variant.default is defined %}
62
+ {{ "// default: " + variant.default|tojson }}
63
+ {%- endif -%}
64
+ {%- if not loop.last %}
65
+ {{- " | " }}
66
+ {% endif -%}
67
+ {%- endfor -%}
68
+ {%- endif -%}
69
+ {%- elif param_spec.type == "string" -%}
70
+ {%- if param_spec.enum -%}
71
+ {{- '"' + param_spec.enum|join('" | "') + '"' -}}
72
+ {%- else -%}
73
+ {{- "string" }}
74
+ {%- if param_spec.nullable %}
75
+ {{- " | null" }}
76
+ {%- endif -%}
77
+ {%- endif -%}
78
+ {%- elif param_spec.type == "number" -%}
79
+ {{- "number" }}
80
+ {%- elif param_spec.type == "integer" -%}
81
+ {{- "number" }}
82
+ {%- elif param_spec.type == "boolean" -%}
83
+ {{- "boolean" }}
84
+
85
+ {%- elif param_spec.type == "object" -%}
86
+ {%- if param_spec.properties -%}
87
+ {{- "{\n" }}
88
+ {%- for prop_name, prop_spec in param_spec.properties.items() -%}
89
+ {{- prop_name -}}
90
+ {%- if prop_name not in (param_spec.required or []) -%}
91
+ {{- "?" }}
92
+ {%- endif -%}
93
+ {{- ": " }}
94
+ {{ render_typescript_type(prop_spec, param_spec.required or []) }}
95
+ {%- if not loop.last -%}
96
+ {{-", " }}
97
+ {%- endif -%}
98
+ {%- endfor -%}
99
+ {{- "}" }}
100
+ {%- else -%}
101
+ {{- "object" }}
102
+ {%- endif -%}
103
+ {%- else -%}
104
+ {{- "any" }}
105
+ {%- endif -%}
106
+ {%- endmacro -%}
107
+
108
+ {%- macro render_tool_namespace(namespace_name, tools) -%}
109
+ {{- "## " + namespace_name + "\n\n" }}
110
+ {{- "namespace " + namespace_name + " {\n\n" }}
111
+ {%- for tool in tools %}
112
+ {%- set tool = tool.function %}
113
+ {{- "// " + tool.description + "\n" }}
114
+ {{- "type "+ tool.name + " = " }}
115
+ {%- if tool.parameters and tool.parameters.properties %}
116
+ {{- "(_: {\n" }}
117
+ {%- for param_name, param_spec in tool.parameters.properties.items() %}
118
+ {%- if param_spec.description %}
119
+ {{- "// " + param_spec.description + "\n" }}
120
+ {%- endif %}
121
+ {{- param_name }}
122
+ {%- if param_name not in (tool.parameters.required or []) -%}
123
+ {{- "?" }}
124
+ {%- endif -%}
125
+ {{- ": " }}
126
+ {{- render_typescript_type(param_spec, tool.parameters.required or []) }}
127
+ {%- if param_spec.default is defined -%}
128
+ {%- if param_spec.enum %}
129
+ {{- ", // default: " + param_spec.default }}
130
+ {%- elif param_spec.oneOf %}
131
+ {{- "// default: " + param_spec.default }}
132
+ {%- else %}
133
+ {{- ", // default: " + param_spec.default|tojson }}
134
+ {%- endif -%}
135
+ {%- endif -%}
136
+ {%- if not loop.last %}
137
+ {{- ",\n" }}
138
+ {%- else %}
139
+ {{- ",\n" }}
140
+ {%- endif -%}
141
+ {%- endfor %}
142
+ {{- "}) => any;\n\n" }}
143
+ {%- else -%}
144
+ {{- "() => any;\n\n" }}
145
+ {%- endif -%}
146
+ {%- endfor %}
147
+ {{- "} // namespace " + namespace_name }}
148
+ {%- endmacro -%}
149
+
150
+ {%- macro render_builtin_tools(browser_tool, python_tool) -%}
151
+ {%- if browser_tool %}
152
+ {{- "## browser\n\n" }}
153
+ {{- "// Tool for browsing.\n" }}
154
+ {{- "// The `cursor` appears in brackets before each browsing display: `[{cursor}]`.\n" }}
155
+ {{- "// Cite information from the tool using the following format:\n" }}
156
+ {{- "// `【{cursor}†L{line_start}(-L{line_end})?】`, for example: `【6†L9-L11】` or `【8†L3】`.\n" }}
157
+ {{- "// Do not quote more than 10 words directly from the tool output.\n" }}
158
+ {{- "// sources=web (default: web)\n" }}
159
+ {{- "namespace browser {\n\n" }}
160
+ {{- "// Searches for information related to `query` and displays `topn` results.\n" }}
161
+ {{- "type search = (_: {\n" }}
162
+ {{- "query: string,\n" }}
163
+ {{- "topn?: number, // default: 10\n" }}
164
+ {{- "source?: string,\n" }}
165
+ {{- "}) => any;\n\n" }}
166
+ {{- "// Opens the link `id` from the page indicated by `cursor` starting at line number `loc`, showing `num_lines` lines.\n" }}
167
+ {{- "// Valid link ids are displayed with the formatting: `【{id}†.*】`.\n" }}
168
+ {{- "// If `cursor` is not provided, the most recent page is implied.\n" }}
169
+ {{- "// If `id` is a string, it is treated as a fully qualified URL associated with `source`.\n" }}
170
+ {{- "// If `loc` is not provided, the viewport will be positioned at the beginning of the document or centered on the most relevant passage, if available.\n" }}
171
+ {{- "// Use this function without `id` to scroll to a new location of an opened page.\n" }}
172
+ {{- "type open = (_: {\n" }}
173
+ {{- "id?: number | string, // default: -1\n" }}
174
+ {{- "cursor?: number, // default: -1\n" }}
175
+ {{- "loc?: number, // default: -1\n" }}
176
+ {{- "num_lines?: number, // default: -1\n" }}
177
+ {{- "view_source?: boolean, // default: false\n" }}
178
+ {{- "source?: string,\n" }}
179
+ {{- "}) => any;\n\n" }}
180
+ {{- "// Finds exact matches of `pattern` in the current page, or the page given by `cursor`.\n" }}
181
+ {{- "type find = (_: {\n" }}
182
+ {{- "pattern: string,\n" }}
183
+ {{- "cursor?: number, // default: -1\n" }}
184
+ {{- "}) => any;\n\n" }}
185
+ {{- "} // namespace browser\n\n" }}
186
+ {%- endif -%}
187
+
188
+ {%- if python_tool %}
189
+ {{- "## python\n\n" }}
190
+ {{- "Use this tool to execute Python code in your chain of thought. The code will not be shown to the user. This tool should be used for internal reasoning, but not for code that is intended to be visible to the user (e.g. when creating plots, tables, or files).\n\n" }}
191
+ {{- "When you send a message containing Python code to python, it will be executed in a stateful Jupyter notebook environment. python will respond with the output of the execution or time out after 120.0 seconds. The drive at '/mnt/data' can be used to save and persist user files. Internet access for this session is UNKNOWN. Depends on the cluster.\n\n" }}
192
+ {%- endif -%}
193
+ {%- endmacro -%}
194
+
195
+ {#- System Message Construction ============================================ #}
196
+ {%- macro build_system_message() -%}
197
+ {%- if model_identity is not defined %}
198
+ {%- set model_identity = "You are ChatGPT, a large language model trained by OpenAI." %}
199
+ {%- endif %}
200
+ {{- model_identity + "\n" }}
201
+ {{- "Knowledge cutoff: 2024-06\n" }}
202
+ {{- "Current date: " + strftime_now("%Y-%m-%d") + "\n\n" }}
203
+ {%- if reasoning_effort is not defined %}
204
+ {%- set reasoning_effort = "medium" %}
205
+ {%- endif %}
206
+ {{- "Reasoning: " + reasoning_effort + "\n\n" }}
207
+ {%- if builtin_tools %}
208
+ {{- "# Tools\n\n" }}
209
+ {%- set available_builtin_tools = namespace(browser=false, python=false) %}
210
+ {%- for tool in builtin_tools %}
211
+ {%- if tool == "browser" %}
212
+ {%- set available_builtin_tools.browser = true %}
213
+ {%- elif tool == "python" %}
214
+ {%- set available_builtin_tools.python = true %}
215
+ {%- endif %}
216
+ {%- endfor %}
217
+ {{- render_builtin_tools(available_builtin_tools.browser, available_builtin_tools.python) }}
218
+ {%- endif -%}
219
+ {{- "# Valid channels: analysis, commentary, final. Channel must be included for every message." }}
220
+ {%- if tools -%}
221
+ {{- "\nCalls to these tools must go to the commentary channel: 'functions'." }}
222
+ {%- endif -%}
223
+ {%- endmacro -%}
224
+
225
+ {#- Main Template Logic ================================================= #}
226
+ {#- Set defaults #}
227
+
228
+ {#- Render system message #}
229
+ {{- "<|start|>system<|message|>" }}
230
+ {{- build_system_message() }}
231
+ {{- "<|end|>" }}
232
+
233
+ {#- Extract developer message #}
234
+ {%- if messages[0].role == "developer" or messages[0].role == "system" %}
235
+ {%- set developer_message = messages[0].content %}
236
+ {%- set loop_messages = messages[1:] %}
237
+ {%- else %}
238
+ {%- set developer_message = "" %}
239
+ {%- set loop_messages = messages %}
240
+ {%- endif %}
241
+
242
+ {#- Render developer message #}
243
+ {%- if developer_message or tools %}
244
+ {{- "<|start|>developer<|message|>" }}
245
+ {%- if developer_message %}
246
+ {{- "# Instructions\n\n" }}
247
+ {{- developer_message }}
248
+ {{- "\n\n" }}
249
+ {%- endif %}
250
+ {%- if tools -%}
251
+ {{- "# Tools\n\n" }}
252
+ {{- render_tool_namespace("functions", tools) }}
253
+ {%- endif -%}
254
+ {{- "<|end|>" }}
255
+ {%- endif %}
256
+
257
+ {#- Render messages #}
258
+ {%- set last_tool_call = namespace(name=none) %}
259
+ {%- for message in loop_messages -%}
260
+ {#- At this point only assistant/user/tool messages should remain #}
261
+ {%- if message.role == 'assistant' -%}
262
+ {#- Checks to ensure the messages are being passed in the format we expect #}
263
+ {%- if "content" in message %}
264
+ {%- if "<|channel|>analysis<|message|>" in message.content or "<|channel|>final<|message|>" in message.content %}
265
+ {{- raise_exception("You have passed a message containing <|channel|> tags in the content field. Instead of doing this, you should pass analysis messages (the string between '<|message|>' and '<|end|>') in the 'thinking' field, and final messages (the string between '<|message|>' and '<|end|>') in the 'content' field.") }}
266
+ {%- endif %}
267
+ {%- endif %}
268
+ {%- if "thinking" in message %}
269
+ {%- if "<|channel|>analysis<|message|>" in message.thinking or "<|channel|>final<|message|>" in message.thinking %}
270
+ {{- raise_exception("You have passed a message containing <|channel|> tags in the thinking field. Instead of doing this, you should pass analysis messages (the string between '<|message|>' and '<|end|>') in the 'thinking' field, and final messages (the string between '<|message|>' and '<|end|>') in the 'content' field.") }}
271
+ {%- endif %}
272
+ {%- endif %}
273
+ {%- if "tool_calls" in message %}
274
+ {#- We need very careful handling here - we want to drop the tool call analysis message if the model #}
275
+ {#- has output a later <|final|> message, but otherwise we want to retain it. This is the only case #}
276
+ {#- when we render CoT/analysis messages in inference. #}
277
+ {%- set future_final_message = namespace(found=false) %}
278
+ {%- for future_message in loop_messages[loop.index:] %}
279
+ {%- if future_message.role == 'assistant' and "tool_calls" not in future_message %}
280
+ {%- set future_final_message.found = true %}
281
+ {%- endif %}
282
+ {%- endfor %}
283
+ {#- We assume max 1 tool call per message, and so we infer the tool call name #}
284
+ {#- in "tool" messages from the most recent assistant tool call name #}
285
+ {%- set tool_call = message.tool_calls[0] %}
286
+ {%- if tool_call.function %}
287
+ {%- set tool_call = tool_call.function %}
288
+ {%- endif %}
289
+ {%- if message.content and message.thinking %}
290
+ {{- raise_exception("Cannot pass both content and thinking in an assistant message with tool calls! Put the analysis message in one or the other, but not both.") }}
291
+ {%- elif message.content and not future_final_message.found %}
292
+ {{- "<|start|>assistant<|channel|>analysis<|message|>" + message.content + "<|end|>" }}
293
+ {%- elif message.thinking and not future_final_message.found %}
294
+ {{- "<|start|>assistant<|channel|>analysis<|message|>" + message.thinking + "<|end|>" }}
295
+ {%- endif %}
296
+ {{- "<|start|>assistant to=" }}
297
+ {{- "functions." + tool_call.name + "<|channel|>commentary " }}
298
+ {{- (tool_call.content_type if tool_call.content_type is defined else "json") + "<|message|>" }}
299
+ {{- tool_call.arguments|tojson }}
300
+ {{- "<|call|>" }}
301
+ {%- set last_tool_call.name = tool_call.name %}
302
+ {%- elif loop.last and not add_generation_prompt %}
303
+ {#- Only render the CoT if the final turn is an assistant turn and add_generation_prompt is false #}
304
+ {#- This is a situation that should only occur in training, never in inference. #}
305
+ {%- if "thinking" in message %}
306
+ {{- "<|start|>assistant<|channel|>analysis<|message|>" + message.thinking + "<|end|>" }}
307
+ {%- endif %}
308
+ {#- <|return|> indicates the end of generation, but <|end|> does not #}
309
+ {#- <|return|> should never be an input to the model, but we include it as the final token #}
310
+ {#- when training, so the model learns to emit it. #}
311
+ {{- "<|start|>assistant<|channel|>final<|message|>" + message.content + "<|return|>" }}
312
+ {%- else %}
313
+ {#- CoT is dropped during all previous turns, so we never render it for inference #}
314
+ {{- "<|start|>assistant<|channel|>final<|message|>" + message.content + "<|end|>" }}
315
+ {%- set last_tool_call.name = none %}
316
+ {%- endif %}
317
+ {%- elif message.role == 'tool' -%}
318
+ {%- if last_tool_call.name is none %}
319
+ {{- raise_exception("Message has tool role, but there was no previous assistant message with a tool call!") }}
320
+ {%- endif %}
321
+ {{- "<|start|>functions." + last_tool_call.name }}
322
+ {{- " to=assistant<|channel|>commentary<|message|>" + message.content|tojson + "<|end|>" }}
323
+ {%- elif message.role == 'user' -%}
324
+ {{- "<|start|>user<|message|>" + message.content + "<|end|>" }}
325
+ {%- endif -%}
326
+ {%- endfor -%}
327
+
328
+ {#- Generation prompt #}
329
+ {%- if add_generation_prompt -%}
330
+ <|start|>assistant
331
+ {%- endif -%}
backend/llama.cpp/models/templates/openbmb-MiniCPM5-1B.jinja ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {{- bos_token }}{%- if tools %}
2
+ {%- set tool_definitions %}
3
+ {{- "# Tools\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
4
+ {%- for tool in tools %}
5
+ {{- "\n" }}
6
+ {{- tool | tojson(ensure_ascii=False) }}
7
+ {%- endfor %}
8
+ {{- '\n</tools>\n\nTool usage guidelines:\n- You may call zero or more functions. If no function calls are needed, just answer normally and do not include any <function ... </function>.\n- When calling a function, return an XML object within <function ... </function> using:\n<function name="function-name"><param name="param-name">param-value</param></function>\n- param-value may be multi-line. If it contains <, & or newline characters, wrap it in a CDATA block: <param name="param-name"><![CDATA[...multi-line value...]]></param>' }}
9
+ {%- endset %}
10
+
11
+ {{- '<|im_start|>system\n' }}
12
+ {%- if messages[0].role == 'system' %}
13
+ {%- if '<tool_def_sep>' in messages[0].content %}
14
+ {{- messages[0].content.replace('<tool_def_sep>', tool_definitions) }}
15
+ {%- else %}
16
+ {{- messages[0].content + '\n\n' + tool_definitions }}
17
+ {%- endif %}
18
+ {%- else %}
19
+ {{- tool_definitions.lstrip() }}
20
+ {%- endif %}
21
+ {{- '<|im_end|>\n' }}
22
+ {%- else %}
23
+ {%- if messages[0].role == 'system' %}
24
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
25
+ {%- endif %}
26
+ {%- endif %}
27
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
28
+ {%- for message in messages[::-1] %}
29
+ {%- set index = (messages|length - 1) - loop.index0 %}
30
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
31
+ {%- set ns.multi_step_tool = false %}
32
+ {%- set ns.last_query_index = index %}
33
+ {%- endif %}
34
+ {%- endfor %}
35
+ {%- for message in messages %}
36
+ {%- if message.content is string %}
37
+ {%- set content = message.content %}
38
+ {%- else %}
39
+ {%- set content = '' %}
40
+ {%- endif %}
41
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
42
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
43
+ {%- elif message.role == "assistant" %}
44
+ {%- set reasoning_content = '' %}
45
+ {%- if message.reasoning_content is string %}
46
+ {%- set reasoning_content = message.reasoning_content %}
47
+ {%- else %}
48
+ {%- if '</think>' in content %}
49
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
50
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
51
+ {%- endif %}
52
+ {%- endif %}
53
+
54
+ {%- if message.tool_calls %}
55
+ {%- set content_parts = content.split('<tool_sep>') %}
56
+ {%- set processed_content = content_parts[0] %}
57
+ {%- set tool_calls_count = message.tool_calls|length %}
58
+ {%- set tool_sep_count = content_parts|length - 1 %}
59
+ {%- set min_count = [tool_calls_count, tool_sep_count]|min %}
60
+
61
+ {%- for i in range(1, content_parts|length) %}
62
+ {%- set tool_index = i - 1 %}
63
+ {%- if tool_index < tool_calls_count %}
64
+ {%- set tool_call = message.tool_calls[tool_index] %}
65
+ {%- if tool_call.function %}
66
+ {%- set tool_call = tool_call.function %}
67
+ {%- endif %}
68
+ {%- set single_tool_xml %}
69
+ {{- '<function name="' ~ tool_call.name ~ '">' }}
70
+ {%- if tool_call.arguments %}
71
+ {%- set args_dict = tool_call.arguments %}
72
+ {%- for param_name, param_value in args_dict.items() %}
73
+ {{- '<param name="' ~ param_name ~ '">' }}
74
+ {%- if param_value is string and ('<' in param_value or '&' in param_value or '\n' in param_value) %}
75
+ {{- '<![CDATA[' + param_value + ']]>' }}
76
+ {%- else %}
77
+ {{- param_value }}
78
+ {%- endif %}
79
+ {{- '</param>' }}
80
+ {%- endfor %}
81
+ {%- endif %}
82
+ {{- '</function>' }}
83
+ {%- endset %}
84
+ {%- set processed_content = processed_content + single_tool_xml + content_parts[i] %}
85
+ {%- else %}
86
+ {%- set processed_content = processed_content + content_parts[i] %}
87
+ {%- endif %}
88
+ {%- endfor %}
89
+
90
+ {%- if tool_calls_count > tool_sep_count %}
91
+ {%- for remaining_index in range(tool_sep_count, tool_calls_count) %}
92
+ {%- set tool_call = message.tool_calls[remaining_index] %}
93
+ {%- if tool_call.function %}
94
+ {%- set tool_call = tool_call.function %}
95
+ {%- endif %}
96
+ {%- set remaining_tool_xml %}
97
+ {{- '<function name="' ~ tool_call.name ~ '">' }}
98
+ {%- if tool_call.arguments %}
99
+ {%- set args_dict = tool_call.arguments %}
100
+ {%- for param_name, param_value in args_dict.items() %}
101
+ {{- '<param name="' ~ param_name ~ '">' }}
102
+ {%- if param_value is string and ('<' in param_value or '&' in param_value or '\n' in param_value) %}
103
+ {{- '<![CDATA[' + param_value + ']]>' }}
104
+ {%- else %}
105
+ {{- param_value }}
106
+ {%- endif %}
107
+ {{- '</param>' }}
108
+ {%- endfor %}
109
+ {%- endif %}
110
+ {{- '</function>' }}
111
+ {%- endset %}
112
+ {%- set processed_content = processed_content + remaining_tool_xml %}
113
+ {%- endfor %}
114
+ {%- endif %}
115
+
116
+ {%- set content = processed_content %}
117
+ {%- endif %}
118
+
119
+ {%- if loop.index0 > ns.last_query_index %}
120
+ {%- if reasoning_content %}
121
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
122
+ {%- else %}
123
+ {{- '<|im_start|>' + message.role + '\n' + content }}
124
+ {%- endif %}
125
+ {%- else %}
126
+ {{- '<|im_start|>' + message.role + '\n' + content }}
127
+ {%- endif %}
128
+
129
+ {%- if message.tool_calls and not has_tool_sep %}
130
+ {%- for tool_call in message.tool_calls %}
131
+ {%- if (loop.first and content) or (not loop.first) %}
132
+ {{- '\n' }}
133
+ {%- endif %}
134
+ {%- if tool_call.function %}
135
+ {%- set tool_call = tool_call.function %}
136
+ {%- endif %}
137
+ {{- '<function name="' ~ tool_call.name ~ '">' }}
138
+ {%- if tool_call.arguments %}
139
+ {%- set args_dict = tool_call.arguments %}
140
+ {%- for param_name, param_value in args_dict.items() %}
141
+ {{- '<param name="' ~ param_name ~ '">' }}
142
+ {%- if param_value is string and ('<' in param_value or '&' in param_value or '\n' in param_value) %}
143
+ {{- '<![CDATA[' + param_value + ']]>' }}
144
+ {%- else %}
145
+ {{- param_value }}
146
+ {%- endif %}
147
+ {{- '</param>' }}
148
+ {%- endfor %}
149
+ {%- endif %}
150
+ {{- '</function>' }}
151
+ {%- endfor %}
152
+ {%- endif %}
153
+ {{- '<|im_end|>\n' }}
154
+ {%- elif message.role == "tool" %}
155
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
156
+ {{- '<|im_start|>user' }}
157
+ {%- endif %}
158
+ {{- '\n<tool_response>\n' }}
159
+ {%- if message.content is string %}
160
+ {{- content }}
161
+ {%- else %}
162
+ {{- message.content | tojson(ensure_ascii=False) }}
163
+ {%- endif %}
164
+ {{- '\n</tool_response>' }}
165
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
166
+ {{- '<|im_end|>\n' }}
167
+ {%- endif %}
168
+ {%- endif %}
169
+ {%- endfor %}
170
+ {%- if add_generation_prompt %}
171
+ {{- '<|im_start|>assistant\n' }}
172
+ {%- if enable_thinking is defined %}
173
+ {%- if enable_thinking is false %}
174
+ {{- '<think>\n\n</think>\n\n' }}
175
+ {%- elif enable_thinking is true %}
176
+ {{- '<think>\n' }}
177
+ {%- endif %}
178
+ {%- endif %}
179
+ {%- endif %}
backend/llama.cpp/models/templates/unsloth-Apriel-1.5.jinja ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {# Unsloth template fixes #}
2
+ {%- set available_tools_string = '' -%}
3
+ {%- set thought_instructions = '' -%}
4
+ {%- set add_tool_id = true -%}
5
+ {%- set tool_output_format = "default" -%}
6
+ {%- if tools is not none and tools|length > 0 -%}
7
+ {%- set available_tools_string -%}
8
+ You are provided with function signatures within <available_tools></available_tools> XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about the arguments. You should infer the argument values from previous user responses and the system message. Here are the available tools:
9
+ <available_tools>
10
+ {% for tool in tools %}
11
+ {{ tool|string }}
12
+ {% endfor %}
13
+ </available_tools>
14
+ {%- endset -%}
15
+ {%- endif -%}
16
+ {%- if tool_output_format is none or tool_output_format == "default" -%}
17
+ {%- set tool_output_instructions -%}
18
+ Return all function calls as a list of json objects within <tool_call></tool_call> XML tags. Each json object should contain a function name and arguments as follows:
19
+ <tool_calls>[{"name": <function-name-1>, "arguments": <args-dict-1>}, {"name": <function-name-2>, "arguments": <args-dict-2>},...]</tool_calls>
20
+ {%- endset -%}
21
+ {%- elif tool_output_format == "yaml" -%}
22
+ {%- set tool_output_instructions -%}
23
+ Return all function calls as a list of yaml objects within <tool_call></tool_call> XML tags. Each yaml object should contain a function name and arguments as follows:
24
+ <tool_calls>
25
+ - name: <function-name-1>
26
+ arguments: <args-dict-1>
27
+ - name: <function-name-2>
28
+ arguments: <args-dict-2>
29
+ ...
30
+ </tool_calls>
31
+ {%- endset -%}
32
+ {%- endif -%}
33
+ {%- if add_thoughts -%}
34
+ {%- set thought_instructions -%}
35
+ Prior to generating the function calls, you should generate the reasoning for why you're calling the function. Please generate these reasoning thoughts between <thinking> and </thinking> XML tags.
36
+ {%- endset -%}
37
+ {%- endif -%}
38
+ {{- bos_token -}}
39
+ {%- set reasoning_prompt='You are a thoughtful and systematic AI assistant built by ServiceNow Language Models (SLAM) lab. Before providing an answer, analyze the problem carefully and present your reasoning step by step. After explaining your thought process, provide the final solution in the following format: [BEGIN FINAL RESPONSE] ... [END FINAL RESPONSE].' -%}
40
+ {%- if messages[0]['role'] != 'system' and tools is not none and tools|length > 0 -%}
41
+ {{- '<|system|>\n' + reasoning_prompt + available_tools_string + "\n" + tool_output_instructions + '\n<|end|>\n' -}}
42
+ {%- endif -%}
43
+ {%- if messages|selectattr('role', 'equalto', 'system')|list|length == 0 -%}
44
+ {{- '<|system|>\n' + reasoning_prompt + '\n<|end|>\n' -}}
45
+ {%- endif -%}
46
+ {%- for message in messages -%}
47
+ {%- if message['role'] == 'user' -%}
48
+ {{- '<|user|>\n' }}
49
+ {%- if message['content'] is not string %}
50
+ {%- for chunk in message['content'] %}
51
+ {%- if chunk['type'] == 'text' %}
52
+ {{- chunk['text'] }}
53
+ {%- elif chunk['type'] == 'image' or chunk['type'] == 'image_url'%}
54
+ {{- '[IMG]' }}
55
+ {%- else %}
56
+ {{- raise_exception('Unrecognized content type!') }}
57
+ {%- endif %}
58
+ {%- endfor %}
59
+ {%- else %}
60
+ {{- message['content'] }}
61
+ {%- endif %}
62
+ {{- '\n<|end|>\n' }}
63
+ {%- elif message['role'] == 'content' -%}
64
+ {%- if message['content'] is not string %}
65
+ {{- '<|content|>\n' + message['content'][0]['text'] + '\n<|end|>\n' -}}
66
+ {%- else %}
67
+ {{- '<|content|>\n' + message['content'] + '\n<|end|>\n' -}}
68
+ {%- endif -%}
69
+ {%- elif message['role'] == 'system' -%}
70
+ {%- if message['content'] is not none and message['content']|length > 0 %}
71
+ {%- if message['content'] is string %}
72
+ {%- set system_message = message['content'] %}
73
+ {%- else %}
74
+ {%- set system_message = message['content'][0]['text'] %}
75
+ {%- endif %}
76
+ {%- else %}
77
+ {%- set system_message = '' %}
78
+ {%- endif %}
79
+ {%- if tools is not none and tools|length > 0 -%}
80
+ {{- '<|system|>\n' + reasoning_prompt + system_message + '\n' + available_tools_string + '\n<|end|>\n' -}}
81
+ {%- else -%}
82
+ {{- '<|system|>\n' + reasoning_prompt + system_message + '\n<|end|>\n' -}}
83
+ {%- endif -%}
84
+ {%- elif message['role'] == 'assistant' -%}
85
+ {%- if loop.last -%}
86
+ {%- set add_tool_id = false -%}
87
+ {%- endif -%}
88
+ {{- '<|assistant|>\n' -}}
89
+ {%- if message['content'] is defined and message['content'] is not none and message['content']|length > 0 -%}
90
+ {%- if message['content'] is not string and message['content'][0]['text'] is not none %}
91
+ {{- message['content'][0]['text'] }}
92
+ {%- else %}
93
+ {{- message['content'] -}}
94
+ {%- endif -%}
95
+ {%- elif message['chosen'] is defined and message['chosen'] is not none and message['chosen']|length > 0 -%}
96
+ {{- message['chosen'][0] -}}
97
+ {%- endif -%}
98
+ {%- if add_thoughts and 'thought' in message and message['thought'] is not none -%}
99
+ {{- '<thinking>' + message['thought'] + '</thinking>' -}}
100
+ {%- endif -%}
101
+ {%- if message['tool_calls'] is defined and message['tool_calls'] is not none and message['tool_calls']|length > 0 -%}
102
+ {{- '\n<tool_calls>[' -}}
103
+ {%- for tool_call in message["tool_calls"] -%}
104
+ {{- '{"name": "' + tool_call['function']['name'] + '", "arguments": ' + tool_call['function']['arguments']|tojson -}}
105
+ {%- if add_tool_id == true -%}
106
+ {{- ', "id": "' + tool_call['id'] + '"' -}}
107
+ {%- endif -%}
108
+ {{- '}' -}}
109
+ {%- if not loop.last -%}{{- ', ' -}}{%- endif -%}
110
+ {%- endfor -%}
111
+ {{- ']</tool_calls>' -}}
112
+ {%- endif -%}
113
+ {{- '\n<|end|>\n' + eos_token -}}
114
+ {%- elif message['role'] == 'tool' -%}
115
+ {%- if message['content'] is string %}
116
+ {%- set tool_message = message['content'] %}
117
+ {%- else %}
118
+ {%- set tool_message = message['content'][0]['text'] %}
119
+ {%- endif -%}
120
+ {{- '<|tool_result|>\n' + tool_message|string + '\n<|end|>\n' -}}
121
+ {%- endif -%}
122
+ {%- if loop.last and add_generation_prompt and message['role'] != 'assistant' -%}
123
+ {{- '<|assistant|>\n' -}}
124
+ {%- endif -%}
125
+ {%- endfor -%}
126
+ {# Copyright 2025-present Unsloth. Apache 2.0 License. #}
backend/llama.cpp/models/templates/unsloth-mistral-Devstral-Small-2507.jinja ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#- Copyright 2025-present the Unsloth team. All rights reserved. #}
2
+ {#- Licensed under the Apache License, Version 2.0 (the "License") #}
3
+ {#- Edits made by Unsloth #}
4
+ {%- set default_system_message = 'You are Devstral, a helpful agentic model trained by Mistral AI and using the OpenHands scaffold. You can interact with a computer to solve tasks.\n\n<ROLE>\nYour primary role is to assist users by executing commands, modifying code, and solving technical problems effectively. You should be thorough, methodical, and prioritize quality over speed.\n* If the user asks a question, like \"why is X happening\", don\'t try to fix the problem. Just give an answer to the question.\n</ROLE>\n\n<EFFICIENCY>\n* Each action you take is somewhat expensive. Wherever possible, combine multiple actions into a single action, e.g. combine multiple bash commands into one, using sed and grep to edit/view multiple files at once.\n* When exploring the codebase, use efficient tools like find, grep, and git commands with appropriate filters to minimize unnecessary operations.\n</EFFICIENCY>\n\n<FILE_SYSTEM_GUIDELINES>\n* When a user provides a file path, do NOT assume it\'s relative to the current working directory. First explore the file system to locate the file before working on it.\n* If asked to edit a file, edit the file directly, rather than creating a new file with a different filename.\n* For global search-and-replace operations, consider using `sed` instead of opening file editors multiple times.\n</FILE_SYSTEM_GUIDELINES>\n\n<CODE_QUALITY>\n* Write clean, efficient code with minimal comments. Avoid redundancy in comments: Do not repeat information that can be easily inferred from the code itself.\n* When implementing solutions, focus on making the minimal changes needed to solve the problem.\n* Before implementing any changes, first thoroughly understand the codebase through exploration.\n* If you are adding a lot of code to a function or file, consider splitting the function or file into smaller pieces when appropriate.\n</CODE_QUALITY>\n\n<VERSION_CONTROL>\n* When configuring git credentials, use \"openhands\" as the user.name and \"openhands@all-hands.dev\" as the user.email by default, unless explicitly instructed otherwise.\n* Exercise caution with git operations. Do NOT make potentially dangerous changes (e.g., pushing to main, deleting repositories) unless explicitly asked to do so.\n* When committing changes, use `git status` to see all modified files, and stage all files necessary for the commit. Use `git commit -a` whenever possible.\n* Do NOT commit files that typically shouldn\'t go into version control (e.g., node_modules/, .env files, build directories, cache files, large binaries) unless explicitly instructed by the user.\n* If unsure about committing certain files, check for the presence of .gitignore files or ask the user for clarification.\n</VERSION_CONTROL>\n\n<PULL_REQUESTS>\n* When creating pull requests, create only ONE per session/issue unless explicitly instructed otherwise.\n* When working with an existing PR, update it with new commits rather than creating additional PRs for the same issue.\n* When updating a PR, preserve the original PR title and purpose, updating description only when necessary.\n</PULL_REQUESTS>\n\n<PROBLEM_SOLVING_WORKFLOW>\n1. EXPLORATION: Thoroughly explore relevant files and understand the context before proposing solutions\n2. ANALYSIS: Consider multiple approaches and select the most promising one\n3. TESTING:\n * For bug fixes: Create tests to verify issues before implementing fixes\n * For new features: Consider test-driven development when appropriate\n * If the repository lacks testing infrastructure and implementing tests would require extensive setup, consult with the user before investing time in building testing infrastructure\n * If the environment is not set up to run tests, consult with the user first before investing time to install all dependencies\n4. IMPLEMENTATION: Make focused, minimal changes to address the problem\n5. VERIFICATION: If the environment is set up to run tests, test your implementation thoroughly, including edge cases. If the environment is not set up to run tests, consult with the user first before investing time to run tests.\n</PROBLEM_SOLVING_WORKFLOW>\n\n<SECURITY>\n* Only use GITHUB_TOKEN and other credentials in ways the user has explicitly requested and would expect.\n* Use APIs to work with GitHub or other platforms, unless the user asks otherwise or your task requires browsing.\n</SECURITY>\n\n<ENVIRONMENT_SETUP>\n* When user asks you to run an application, don\'t stop if the application is not installed. Instead, please install the application and run the command again.\n* If you encounter missing dependencies:\n 1. First, look around in the repository for existing dependency files (requirements.txt, pyproject.toml, package.json, Gemfile, etc.)\n 2. If dependency files exist, use them to install all dependencies at once (e.g., `pip install -r requirements.txt`, `npm install`, etc.)\n 3. Only install individual packages directly if no dependency files are found or if only specific packages are needed\n* Similarly, if you encounter missing dependencies for essential tools requested by the user, install them when possible.\n</ENVIRONMENT_SETUP>\n\n<TROUBLESHOOTING>\n* If you\'ve made repeated attempts to solve a problem but tests still fail or the user reports it\'s still broken:\n 1. Step back and reflect on 5-7 different possible sources of the problem\n 2. Assess the likelihood of each possible cause\n 3. Methodically address the most likely causes, starting with the highest probability\n 4. Document your reasoning process\n* When you run into any major issue while executing a plan from the user, please don\'t try to directly work around it. Instead, propose a new plan and confirm with the user before proceeding.\n</TROUBLESHOOTING>' %}
5
+
6
+ {{- bos_token }}
7
+
8
+ {%- if messages[0]['role'] == 'system' %}
9
+ {%- if messages[0]['content'] is string %}
10
+ {%- set system_message = messages[0]['content'] %}
11
+ {%- else %}
12
+ {%- set system_message = messages[0]['content'][0]['text'] %}
13
+ {%- endif %}
14
+ {%- set loop_messages = messages[1:] %}
15
+ {%- else %}
16
+ {%- set system_message = default_system_message %}
17
+ {%- set loop_messages = messages %}
18
+ {%- endif %}
19
+ {{- '[SYSTEM_PROMPT]' + system_message + '[/SYSTEM_PROMPT]' }}
20
+
21
+
22
+ {#- Tool description appended ONLY to last user message. Edits made by Unsloth #}
23
+ {#- Tool description appended also if last message is tool. Edits made by Unsloth #}
24
+ {%- set tools_description = "" %}
25
+ {%- set has_tools = false %}
26
+
27
+ {%- if tools is defined and tools is not none and tools|length > 0 %}
28
+
29
+ {%- set has_tools = true %}
30
+ {%- set tools_description = "[AVAILABLE_TOOLS]" + (tools | tojson) + "[/AVAILABLE_TOOLS]" %}
31
+
32
+ {{- tools_description }}
33
+
34
+ {%- endif %}
35
+
36
+ {%- for message in loop_messages %}
37
+ {%- if message['role'] == 'user' %}
38
+
39
+ {%- if message['content'] is string %}
40
+ {{- '[INST]' + message['content'] + '[/INST]' }}
41
+ {%- else %}
42
+ {{- '[INST]' }}
43
+ {%- for block in message['content'] %}
44
+ {%- if block['type'] == 'text' %}
45
+
46
+ {#- Original did not have content which is weird. Added by Un-sloth. #}
47
+ {%- if block['text'] is defined %}
48
+ {{- block['text'] }}
49
+ {%- else %}
50
+ {{- block['content'] }}
51
+ {%- endif %}
52
+
53
+ {%- elif block['type'] in ['image', 'image_url'] %}
54
+ {{- '[IMG]' }}
55
+ {%- else %}
56
+ {{- raise_exception('Only text and image blocks are supported in message content!') }}
57
+ {%- endif %}
58
+ {%- endfor %}
59
+ {{- '[/INST]' }}
60
+ {%- endif %}
61
+
62
+ {%- elif message['role'] == 'system' %}
63
+ {%- if message['content'] is string %}
64
+ {{- '[SYSTEM_PROMPT]' + message['content'] + '[/SYSTEM_PROMPT]' }}
65
+ {%- else %}
66
+ {{- '[SYSTEM_PROMPT]' + message['content'][0]['text'] + '[/SYSTEM_PROMPT]' }}
67
+ {%- endif %}
68
+
69
+
70
+ {%- elif message['role'] == 'assistant' %}
71
+ {%- if message['content'] is string %}
72
+ {{- message['content'] }}
73
+ {%- else %}
74
+ {{- message['content'][0]['text'] }}
75
+ {%- endif %}
76
+
77
+ {#- If User,Assistant,Tool,Tool we also need to append tools_description. Edits made by Unsloth #}
78
+
79
+ {%- if message['tool_calls'] is defined and message['tool_calls'] is not none %}
80
+ {%- for tool in message['tool_calls'] %}
81
+ {%- set arguments = tool['function']['arguments'] %}
82
+ {%- if arguments is not string %}
83
+ {%- set arguments = arguments|tojson %}
84
+ {%- endif %}
85
+ {#- Must list tool calls AFTER assistant. Edits made by Un-sloth #}
86
+ {{- "[TOOL_CALLS]" + tool['function']['name'] + "[ARGS]" + arguments }}
87
+ {%- endfor %}
88
+ {%- endif %}
89
+
90
+ {{- eos_token }}
91
+
92
+ {%- elif message["role"] == "tool_results" or message["role"] == "tool" %}
93
+ {%- if message.content is defined and message.content.content is defined %}
94
+ {%- set content = message.content.content %}
95
+ {%- else %}
96
+ {%- set content = message.content %}
97
+ {%- endif %}
98
+ {{- "[TOOL_RESULTS]" + content|string + "[/TOOL_RESULTS]" }}
99
+
100
+ {%- else %}
101
+ {{- raise_exception('Only user, systemm assistant and tool roles are supported in the custom template made by Unsloth!') }}
102
+ {%- endif %}
103
+ {%- endfor %}
104
+ {#- Copyright 2025-present the Unsloth team. All rights reserved. #}
105
+ {#- Licensed under the Apache License, Version 2.0 (the "License") #}
backend/llama.cpp/models/templates/upstage-Solar-Open-100B.jinja ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {#- ======== Template Parameters ======== #}
2
+ {%- set add_generation_prompt = add_generation_prompt if add_generation_prompt is defined else true %}
3
+ {%- set default_system_prompt = default_system_prompt if default_system_prompt is defined else true %}
4
+ {%- set reasoning_effort = reasoning_effort if reasoning_effort is defined else "high" %}
5
+ {%- set think_render_option = think_render_option if think_render_option is defined else "lastthink" %}
6
+
7
+ {#- ======== System Block State ======== #}
8
+ {%- set sys_ns = namespace(is_first_block=true) -%}
9
+
10
+ {#- ======== Find last user message index ======== #}
11
+ {%- set last_user_idx = namespace(value=-1) -%}
12
+ {%- for message in messages -%}
13
+ {%- if message.role == 'user' -%}
14
+ {%- set last_user_idx.value = loop.index0 -%}
15
+ {%- endif -%}
16
+ {%- endfor -%}
17
+
18
+ {#- ======== System messages renderers ======== #}
19
+ {%- macro render_system_message(user_system_messages) %}
20
+ {%- if default_system_prompt %}
21
+ {%- if not sys_ns.is_first_block %}{{- "\n\n" }}{%- endif %}
22
+ {%- set sys_ns.is_first_block = false %}
23
+ {{- "## Provider System Prompt\n\nYou are Solar Open 100B, a large language model trained by Upstage AI, a Korean startup. Your knowledge cutoff is 2025-07. The current date is " + strftime_now("%Y-%m-%d") + "." }}
24
+ {%- endif -%}
25
+ {%- if user_system_messages %}
26
+ {%- if not sys_ns.is_first_block %}{{- "\n\n" }}{%- endif %}
27
+ {%- set sys_ns.is_first_block = false %}
28
+ {{- "## System Prompt" }}
29
+ {%- for system_message in user_system_messages %}
30
+ {{- "\n\n" }}
31
+ {{- system_message }}
32
+ {%- endfor %}
33
+ {%- endif -%}
34
+ {%- endmacro %}
35
+
36
+ {%- macro render_tool_instruction(tools) %}
37
+ {%- if not sys_ns.is_first_block %}{{- "\n\n" }}{%- endif %}
38
+ {%- set sys_ns.is_first_block = false %}
39
+ {{- "## Tools\n\n### Tool Call Instruction" }}
40
+ {{- "\nYou may invoke one or more tools to assist with the user's query. Available tools are provided in JSON Schema format: <|tools:begin|><|tool:begin|><tools-json-object><|tool:end|>...<|tools:end|>\n" }}
41
+ {{- "\n### Available Tools\n" }}
42
+ {{- "<|tools:begin|>" }}
43
+ {%- for tool in tools %}
44
+ {{- "<|tool:begin|>" }}
45
+ {{- tool.function | tojson }}
46
+ {{- "<|tool:end|>" }}
47
+ {%- endfor %}
48
+ {{- "<|tools:end|>\n" }}
49
+ {{- "\n### Tool Call Format\n" }}
50
+ {{- "For each tool call, return a JSON object with the following structure, enclosed within <|tool_call:begin|> and <|tool_call:end|> tags: \n<|tool_call:begin|><tool-call-id><|tool_call:name|><tool-name><|tool_call:args|><args-json-object><|tool_call:end|>\n" }}
51
+ {{- "- The <tool-call-id> must be a randomly generated string consisting of 10 lowercase letters (a-z) and/or digits (0-9) (e.g., a1b2c3d4e5)\n" }}
52
+ {{- "\n### Tool Response Format\n" }}
53
+ {{- "Each tool is responded by `tool` with the following structure:\n<|tool_response:id|><tool-call-id><|tool_response:name|><tool-name><|tool_response:result|><results><|tool_response:end|>\n" }}
54
+ {{- "- Ensure the <tool-call-id> matches the corresponding tool call" -}}
55
+ {%- endmacro %}
56
+
57
+ {%- macro render_json_response_format_instruction(response_format) %}
58
+ {%- if not sys_ns.is_first_block %}{{- "\n\n" }}{%- endif %}
59
+ {%- set sys_ns.is_first_block = false %}
60
+ {{- "## Output Format Constraint" }}
61
+ {{- "\n\nYour final response should follow the JSON schema: \n[Start of schema]" }}
62
+ {{- response_format }}
63
+ {{- "\n[End of schema]\nPlease ensure your answers adhere to this format and do not contain any unnecessary text." }}
64
+ {%- endmacro %}
65
+
66
+ {%- macro get_tool_name(messages, tool_call_id) %}
67
+ {%- for msg in messages -%}
68
+ {%- if msg.role == 'assistant' and msg.tool_calls -%}
69
+ {%- for tool_call in msg.tool_calls -%}
70
+ {%- if tool_call.id == tool_call_id -%}
71
+ {{- tool_call.function.name }}
72
+ {%- endif -%}
73
+ {%- endfor -%}
74
+ {%- endif -%}
75
+ {%- endfor -%}
76
+ {%- endmacro %}
77
+
78
+ {%- macro render_tool_arguments(tool_arguments) %}
79
+ {%- if tool_arguments is mapping -%}
80
+ {{- tool_arguments | tojson }}
81
+ {%- else -%}
82
+ {{- tool_arguments }}
83
+ {%- endif -%}
84
+ {%- endmacro %}
85
+
86
+ {#- ======== Render system message ======== #}
87
+ {%- set ns = namespace(system_messages=[]) -%}
88
+ {%- for message in messages -%}
89
+ {%- if message.role == 'system' -%}
90
+ {%- set ns.system_messages = ns.system_messages + [message.content] -%}
91
+ {%- endif -%}
92
+ {%- endfor -%}
93
+
94
+ {%- if ns.system_messages or default_system_prompt or tools or response_format -%}
95
+ {{- "<|begin|>system<|content|>" }}
96
+ {{- render_system_message(ns.system_messages) }}
97
+ {%- if tools -%}
98
+ {{- render_tool_instruction(tools) }}
99
+ {%- endif %}
100
+ {%- if response_format -%}
101
+ {{- render_json_response_format_instruction(response_format) }}
102
+ {%- endif %}
103
+ {{- "<|end|>" }}
104
+ {%- endif -%}
105
+
106
+ {#- ======== Render main messages ======== #}
107
+ {%- for message in messages -%}
108
+ {%- if message.role == 'user' -%}
109
+ {{- "<|begin|>user<|content|>" + message.content + "<|end|>" }}
110
+ {%- elif message.role == 'tool' -%}
111
+ {%- set prev_is_tool = loop.index0 > 0 and messages[loop.index0 - 1].role == 'tool' -%}
112
+ {%- set next_is_tool = loop.index0 < (messages | length - 1) and messages[loop.index0 + 1].role == 'tool' -%}
113
+ {%- if not prev_is_tool -%}
114
+ {{- "<|begin|>tool<|tool_response|>" }}
115
+ {%- endif -%}
116
+ {{- "<|tool_response:begin|>" + message.tool_call_id + "<|tool_response:name|>" }}
117
+ {{- get_tool_name(messages, message.tool_call_id) }}
118
+ {{- "<|tool_response:result|>" }}
119
+ {{- message.content }}
120
+ {{- "<|tool_response:end|>" }}
121
+ {%- if not next_is_tool -%}
122
+ {{- "<|end|>" }}
123
+ {%- endif -%}
124
+ {%- elif message.role == 'assistant' -%}
125
+ {#- ======== Assistant Thinking ======== #}
126
+ {%- if think_render_option == "all" -%}
127
+ {%- if message.reasoning -%}
128
+ {{- "<|begin|>assistant<|think|>" + message.reasoning + "<|end|>" }}
129
+ {%- endif -%}
130
+ {%- elif think_render_option == "lastthink" -%}
131
+ {%- if message.reasoning and loop.index0 > last_user_idx.value -%}
132
+ {{- "<|begin|>assistant<|think|>" + message.reasoning + "<|end|>" }}
133
+ {%- endif -%}
134
+ {%- endif -%}
135
+
136
+ {#- ======== Assistant Messages ======== #}
137
+ {%- if message.tool_calls -%}
138
+ {{- "<|begin|>assistant<|tool_calls|>" }}
139
+ {%- for tool_call in message.tool_calls -%}
140
+ {{- "<|tool_call:begin|>" + tool_call.id +"<|tool_call:name|>" + tool_call.function.name + "<|tool_call:args|>" }}
141
+ {{- render_tool_arguments(tool_call.function.arguments) }}
142
+ {{- "<|tool_call:end|>" }}
143
+ {%- endfor -%}
144
+ {{- "<|calls|>" }}
145
+ {%- else -%}
146
+ {{- "<|begin|>assistant<|content|>" + message.content + "<|end|>" }}
147
+ {%- endif -%}
148
+ {%- endif -%}
149
+ {%- endfor -%}
150
+
151
+ {%- if add_generation_prompt -%}
152
+ {%- if reasoning_effort in ["low", "minimal"] -%}
153
+ {{- "<|begin|>assistant<|think|><|end|>" }}
154
+ {%- endif -%}
155
+ {{- "<|begin|>assistant" }}
156
+ {%- endif -%}
backend/llama.cpp/mypy.ini ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ [mypy]
2
+ strict = true
3
+ allow_untyped_calls = true
4
+ allow_untyped_defs = true
5
+ allow_incomplete_defs = true
6
+ disable_error_code = import-untyped
7
+ warn_return_any = false
backend/llama.cpp/pocs/CMakeLists.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # dependencies
2
+
3
+ find_package(Threads REQUIRED)
4
+
5
+ # third-party
6
+
7
+ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
8
+
9
+ if (EMSCRIPTEN)
10
+ else()
11
+ if (NOT GGML_BACKEND_DL)
12
+ add_subdirectory(vdot)
13
+ endif()
14
+ endif()
backend/llama.cpp/pocs/vdot/CMakeLists.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ set(TARGET llama-vdot)
2
+ add_executable(${TARGET} vdot.cpp)
3
+ target_link_libraries(${TARGET} PRIVATE llama-common llama ${CMAKE_THREAD_LIBS_INIT})
4
+ target_compile_features(${TARGET} PRIVATE cxx_std_17)
5
+
6
+ set(TARGET llama-q8dot)
7
+ add_executable(${TARGET} q8dot.cpp)
8
+ target_link_libraries(${TARGET} PRIVATE llama-common llama ${CMAKE_THREAD_LIBS_INIT})
9
+ target_compile_features(${TARGET} PRIVATE cxx_std_17)
backend/llama.cpp/pocs/vdot/q8dot.cpp ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <cstdio>
2
+ #include <type_traits>
3
+ #include <vector>
4
+ #include <random>
5
+ #include <chrono>
6
+ #include <cstdlib>
7
+ #include <cmath>
8
+ #include <cassert>
9
+ #include <cstring>
10
+ #include <array>
11
+ #include <type_traits>
12
+
13
+ #include <ggml.h>
14
+ #include <ggml-cpu.h>
15
+
16
+ constexpr int kVecSize = 1 << 16;
17
+
18
+ // Copy-pasted from ggml.c
19
+ #define QK4_0 32
20
+ typedef struct {
21
+ float d; // delta
22
+ uint8_t qs[QK4_0 / 2]; // nibbles / quants
23
+ } block_q4_0;
24
+ static_assert(sizeof(block_q4_0) == sizeof(float) + QK4_0 / 2, "wrong q4_0 block size/padding");
25
+
26
+ #define QK4_1 32
27
+ typedef struct {
28
+ float d; // delta
29
+ float m; // min
30
+ uint8_t qs[QK4_1 / 2]; // nibbles / quants
31
+ } block_q4_1;
32
+ static_assert(sizeof(block_q4_1) == sizeof(float) * 2 + QK4_1 / 2, "wrong q4_1 block size/padding");
33
+
34
+ // Copy-pasted from ggml.c
35
+ #define QK8_0 32
36
+ typedef struct {
37
+ float d; // delta
38
+ float s; // d * sum(qs[i])
39
+ int8_t qs[QK8_0]; // quants
40
+ } block_q8_0;
41
+ static_assert(sizeof(block_q8_0) == 2*sizeof(float) + QK8_0, "wrong q8_0 block size/padding");
42
+
43
+ static_assert(QK4_1 == QK8_0, "QK4_1 and QK8_0 must be the same");
44
+ static_assert(QK4_0 == QK8_0, "QK4_0 and QK8_0 must be the same");
45
+
46
+ template <typename T>
47
+ static void fillQ4blocks(std::vector<T>& blocks, std::mt19937& rndm) {
48
+ for (auto& b : blocks) {
49
+ b.d = 1;
50
+ for (int i=0; i<QK4_1/2; ++i) {
51
+ uint8_t v1 = rndm() >> 28;
52
+ uint8_t v2 = rndm() >> 28;
53
+ b.qs[i] = v1 | (v2 << 4);
54
+ }
55
+ }
56
+ }
57
+
58
+ static void fillQ80blocks(std::vector<block_q8_0>& blocks, std::mt19937& rndm) {
59
+ for (auto& b : blocks) {
60
+ b.d = 1;
61
+ int sum = 0;
62
+ for (int i=0; i<QK8_0; ++i) {
63
+ b.qs[i] = (rndm() >> 24) - 128;
64
+ sum += b.qs[i];
65
+ }
66
+ b.s = b.d * sum;
67
+ }
68
+ }
69
+
70
+ static float simpleDot(const block_q4_0& x, const block_q8_0& y) {
71
+ int s1 = 0; //, s2 = 0;
72
+ for (int i=0; i<QK4_1/2; i+=2) {
73
+ int v1 = x.qs[i+0] & 0xf;
74
+ int v2 = x.qs[i+0] >> 4;
75
+ int v3 = x.qs[i+1] & 0xf;
76
+ int v4 = x.qs[i+1] >> 4;
77
+ int j = 2*i;
78
+ s1 += v1*y.qs[j] + v2*y.qs[j+1] + v3*y.qs[j+2] + v4*y.qs[j+3];
79
+ //s2 += y.qs[j] + y.qs[j+1] + y.qs[j+2] + y.qs[j+3];
80
+ }
81
+ return y.d * x.d * s1 - 8 * x.d * y.s;
82
+ //return y.d * x.d * (s1 - 8 * s2);
83
+ }
84
+
85
+ static float simpleDot(const block_q4_1& x, const block_q8_0& y) {
86
+ int s1 = 0; //, s2 = 0;
87
+ for (int i=0; i<QK4_1/2; i+=2) {
88
+ int v1 = x.qs[i+0] & 0xf;
89
+ int v2 = x.qs[i+0] >> 4;
90
+ int v3 = x.qs[i+1] & 0xf;
91
+ int v4 = x.qs[i+1] >> 4;
92
+ int j = 2*i;
93
+ s1 += v1*y.qs[j] + v2*y.qs[j+1] + v3*y.qs[j+2] + v4*y.qs[j+3];
94
+ //s2 += y.qs[j] + y.qs[j+1] + y.qs[j+2] + y.qs[j+3];
95
+ }
96
+ return y.d * x.d * s1 + y.s * x.m;
97
+ //return y.d * (x.d * s1 + x.m * s2);
98
+ }
99
+
100
+ struct Stat {
101
+ double sum = 0, sumt = 0, sumt2 = 0, maxt = 0;
102
+ int nloop = 0;
103
+ void addResult(double s, double t) {
104
+ sum += s;
105
+ sumt += t; sumt2 += t*t; maxt = std::max(maxt, t);
106
+ ++nloop;
107
+ }
108
+ void reportResult(const char* title) const {
109
+ if (nloop < 1) {
110
+ printf("%s(%s): no result\n",__func__,title);
111
+ return;
112
+ }
113
+ printf("============ %s\n",title);
114
+ printf("<dot> = %g\n",sum/nloop);
115
+ auto t = sumt/nloop, dt = sumt2/nloop - t*t;
116
+ if (dt > 0) dt = sqrt(dt);
117
+ printf("<time> = %g +/- %g us. Max. time = %g us.\n",t,dt,maxt);
118
+ }
119
+ };
120
+
121
+
122
+ int main(int argc, char** argv) {
123
+
124
+ int nloop = argc > 1 ? atoi(argv[1]) : 10;
125
+ int type = argc > 2 ? atoi(argv[2]) : 1;
126
+
127
+ std::mt19937 rndm(1234);
128
+
129
+ std::vector<block_q4_1> x41;
130
+ std::vector<block_q4_0> x40;
131
+ std::vector<block_q8_0> y(kVecSize);
132
+ if (type == 0) x40.resize(kVecSize);
133
+ else {
134
+ x41.resize(kVecSize);
135
+ for (auto& b : x41) b.m = 1;
136
+ }
137
+
138
+ auto ggml_type = type == 0 ? GGML_TYPE_Q4_0 : GGML_TYPE_Q4_1;
139
+
140
+ const auto * funcs = ggml_get_type_traits_cpu(ggml_type);
141
+
142
+ Stat simple, ggml;
143
+
144
+ for (int iloop=0; iloop<nloop; ++iloop) {
145
+
146
+ if (type == 0) fillQ4blocks(x40, rndm);
147
+ else fillQ4blocks(x41, rndm);
148
+ fillQ80blocks(y, rndm);
149
+
150
+ auto t1 = std::chrono::high_resolution_clock::now();
151
+ double s = 0;
152
+ if (type == 0) for (int i=0; i<kVecSize; ++i) s += simpleDot(x40[i], y[i]);
153
+ else for (int i=0; i<kVecSize; ++i) s += simpleDot(x41[i], y[i]);
154
+ auto t2 = std::chrono::high_resolution_clock::now();
155
+ auto t = 1e-3*std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
156
+ if (iloop > 3) simple.addResult(s, t);
157
+
158
+ t1 = std::chrono::high_resolution_clock::now();
159
+ float fs;
160
+ if (type == 0) funcs->vec_dot(kVecSize * QK4_1, &fs, 0, x40.data(), 0, y.data(), 0, 1);
161
+ else funcs->vec_dot(kVecSize * QK4_1, &fs, 0, x41.data(), 0, y.data(), 0, 1);
162
+ t2 = std::chrono::high_resolution_clock::now();
163
+ t = 1e-3*std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
164
+ if (iloop > 3) ggml.addResult(fs, t);
165
+
166
+ }
167
+
168
+ // Report the time (and the average of the dot products so the compiler does not come up with the idea
169
+ // of optimizing away the function calls after figuring that the result is not used).
170
+ simple.reportResult("Simple");
171
+ ggml.reportResult("ggml");
172
+ return 0;
173
+ }
backend/llama.cpp/pocs/vdot/vdot.cpp ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <cstdio>
2
+ #include <vector>
3
+ #include <random>
4
+ #include <chrono>
5
+ #include <cstdlib>
6
+ #include <cmath>
7
+ #include <cassert>
8
+ #include <cstring>
9
+ #include <array>
10
+
11
+ #include <ggml.h>
12
+ #include <ggml-cpu.h>
13
+
14
+ #if defined(_MSC_VER)
15
+ #pragma warning(disable: 4244 4267) // possible loss of data
16
+ #endif
17
+
18
+ constexpr int kVecSize = 1 << 18;
19
+
20
+ static float drawFromGaussianPdf(std::mt19937& rndm) {
21
+ constexpr double kScale = 1./(1. + std::mt19937::max());
22
+ constexpr double kTwoPiTimesScale = 6.28318530717958647692*kScale;
23
+ static float lastX;
24
+ static bool haveX = false;
25
+ if (haveX) { haveX = false; return lastX; }
26
+ auto r = sqrt(-2*log(1 - kScale*rndm()));
27
+ auto phi = kTwoPiTimesScale * rndm();
28
+ lastX = r*sin(phi);
29
+ haveX = true;
30
+ return r*cos(phi);
31
+ }
32
+
33
+ static void fillRandomGaussianFloats(std::vector<float>& values, std::mt19937& rndm, float mean = 0) {
34
+ for (auto& v : values) v = mean + drawFromGaussianPdf(rndm);
35
+ }
36
+
37
+ // Copy-pasted from ggml.c
38
+ #define QK4_0 32
39
+ typedef struct {
40
+ float d; // delta
41
+ uint8_t qs[QK4_0 / 2]; // nibbles / quants
42
+ } block_q4_0;
43
+ static_assert(sizeof(block_q4_0) == sizeof(float) + QK4_0 / 2, "wrong q4_0 block size/padding");
44
+
45
+ #define QK4_1 32
46
+ typedef struct {
47
+ float d; // delta
48
+ float m; // min
49
+ uint8_t qs[QK4_1 / 2]; // nibbles / quants
50
+ } block_q4_1;
51
+ static_assert(sizeof(block_q4_1) == sizeof(float) * 2 + QK4_1 / 2, "wrong q4_1 block size/padding");
52
+
53
+ // Copy-pasted from ggml.c
54
+ #define QK8_0 32
55
+ typedef struct {
56
+ float d; // delta
57
+ int8_t qs[QK8_0]; // quants
58
+ } block_q8_0;
59
+ static_assert(sizeof(block_q8_0) == sizeof(float) + QK8_0, "wrong q8_0 block size/padding");
60
+
61
+ // "Scalar" dot product between the quantized vector x and float vector y
62
+ inline double dot(int n, const block_q4_0* x, const float* y) {
63
+ const static float kValues[16] = {-8.f, -7.f, -6.f, -5.f, -4.f, -3.f, -2.f, -1.f, 0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f};
64
+ constexpr uint32_t kMask1 = 0x0f0f0f0f;
65
+ uint32_t u1, u2;
66
+ auto q1 = (const uint8_t*)&u1;
67
+ auto q2 = (const uint8_t*)&u2;
68
+ double sum = 0;
69
+ for (int i=0; i<n; ++i) {
70
+ float d = x->d;
71
+ auto u = (const uint32_t*)x->qs;
72
+ float s = 0;
73
+ for (int k=0; k<4; ++k) {
74
+ u1 = u[k] & kMask1;
75
+ u2 = (u[k] >> 4) & kMask1;
76
+ s += y[0]*kValues[q1[0]] + y[1]*kValues[q2[0]] +
77
+ y[2]*kValues[q1[1]] + y[3]*kValues[q2[1]] +
78
+ y[4]*kValues[q1[2]] + y[5]*kValues[q2[2]] +
79
+ y[6]*kValues[q1[3]] + y[7]*kValues[q2[3]];
80
+ y += 8;
81
+ }
82
+ sum += s*d;
83
+ ++x;
84
+ }
85
+ return sum;
86
+ }
87
+ // Alternative version of the above. Faster on my Mac (~45 us vs ~55 us per dot product),
88
+ // but about the same on X86_64 (Ryzen 7950X CPU).
89
+ inline double dot3(int n, const block_q4_0* x, const float* y) {
90
+ const static std::pair<float,float> kValues[256] = {
91
+ {-8.f, -8.f}, {-7.f, -8.f}, {-6.f, -8.f}, {-5.f, -8.f}, {-4.f, -8.f}, {-3.f, -8.f}, {-2.f, -8.f}, {-1.f, -8.f},
92
+ { 0.f, -8.f}, { 1.f, -8.f}, { 2.f, -8.f}, { 3.f, -8.f}, { 4.f, -8.f}, { 5.f, -8.f}, { 6.f, -8.f}, { 7.f, -8.f},
93
+ {-8.f, -7.f}, {-7.f, -7.f}, {-6.f, -7.f}, {-5.f, -7.f}, {-4.f, -7.f}, {-3.f, -7.f}, {-2.f, -7.f}, {-1.f, -7.f},
94
+ { 0.f, -7.f}, { 1.f, -7.f}, { 2.f, -7.f}, { 3.f, -7.f}, { 4.f, -7.f}, { 5.f, -7.f}, { 6.f, -7.f}, { 7.f, -7.f},
95
+ {-8.f, -6.f}, {-7.f, -6.f}, {-6.f, -6.f}, {-5.f, -6.f}, {-4.f, -6.f}, {-3.f, -6.f}, {-2.f, -6.f}, {-1.f, -6.f},
96
+ { 0.f, -6.f}, { 1.f, -6.f}, { 2.f, -6.f}, { 3.f, -6.f}, { 4.f, -6.f}, { 5.f, -6.f}, { 6.f, -6.f}, { 7.f, -6.f},
97
+ {-8.f, -5.f}, {-7.f, -5.f}, {-6.f, -5.f}, {-5.f, -5.f}, {-4.f, -5.f}, {-3.f, -5.f}, {-2.f, -5.f}, {-1.f, -5.f},
98
+ { 0.f, -5.f}, { 1.f, -5.f}, { 2.f, -5.f}, { 3.f, -5.f}, { 4.f, -5.f}, { 5.f, -5.f}, { 6.f, -5.f}, { 7.f, -5.f},
99
+ {-8.f, -4.f}, {-7.f, -4.f}, {-6.f, -4.f}, {-5.f, -4.f}, {-4.f, -4.f}, {-3.f, -4.f}, {-2.f, -4.f}, {-1.f, -4.f},
100
+ { 0.f, -4.f}, { 1.f, -4.f}, { 2.f, -4.f}, { 3.f, -4.f}, { 4.f, -4.f}, { 5.f, -4.f}, { 6.f, -4.f}, { 7.f, -4.f},
101
+ {-8.f, -3.f}, {-7.f, -3.f}, {-6.f, -3.f}, {-5.f, -3.f}, {-4.f, -3.f}, {-3.f, -3.f}, {-2.f, -3.f}, {-1.f, -3.f},
102
+ { 0.f, -3.f}, { 1.f, -3.f}, { 2.f, -3.f}, { 3.f, -3.f}, { 4.f, -3.f}, { 5.f, -3.f}, { 6.f, -3.f}, { 7.f, -3.f},
103
+ {-8.f, -2.f}, {-7.f, -2.f}, {-6.f, -2.f}, {-5.f, -2.f}, {-4.f, -2.f}, {-3.f, -2.f}, {-2.f, -2.f}, {-1.f, -2.f},
104
+ { 0.f, -2.f}, { 1.f, -2.f}, { 2.f, -2.f}, { 3.f, -2.f}, { 4.f, -2.f}, { 5.f, -2.f}, { 6.f, -2.f}, { 7.f, -2.f},
105
+ {-8.f, -1.f}, {-7.f, -1.f}, {-6.f, -1.f}, {-5.f, -1.f}, {-4.f, -1.f}, {-3.f, -1.f}, {-2.f, -1.f}, {-1.f, -1.f},
106
+ { 0.f, -1.f}, { 1.f, -1.f}, { 2.f, -1.f}, { 3.f, -1.f}, { 4.f, -1.f}, { 5.f, -1.f}, { 6.f, -1.f}, { 7.f, -1.f},
107
+ {-8.f, 0.f}, {-7.f, 0.f}, {-6.f, 0.f}, {-5.f, 0.f}, {-4.f, 0.f}, {-3.f, 0.f}, {-2.f, 0.f}, {-1.f, 0.f},
108
+ { 0.f, 0.f}, { 1.f, 0.f}, { 2.f, 0.f}, { 3.f, 0.f}, { 4.f, 0.f}, { 5.f, 0.f}, { 6.f, 0.f}, { 7.f, 0.f},
109
+ {-8.f, 1.f}, {-7.f, 1.f}, {-6.f, 1.f}, {-5.f, 1.f}, {-4.f, 1.f}, {-3.f, 1.f}, {-2.f, 1.f}, {-1.f, 1.f},
110
+ { 0.f, 1.f}, { 1.f, 1.f}, { 2.f, 1.f}, { 3.f, 1.f}, { 4.f, 1.f}, { 5.f, 1.f}, { 6.f, 1.f}, { 7.f, 1.f},
111
+ {-8.f, 2.f}, {-7.f, 2.f}, {-6.f, 2.f}, {-5.f, 2.f}, {-4.f, 2.f}, {-3.f, 2.f}, {-2.f, 2.f}, {-1.f, 2.f},
112
+ { 0.f, 2.f}, { 1.f, 2.f}, { 2.f, 2.f}, { 3.f, 2.f}, { 4.f, 2.f}, { 5.f, 2.f}, { 6.f, 2.f}, { 7.f, 2.f},
113
+ {-8.f, 3.f}, {-7.f, 3.f}, {-6.f, 3.f}, {-5.f, 3.f}, {-4.f, 3.f}, {-3.f, 3.f}, {-2.f, 3.f}, {-1.f, 3.f},
114
+ { 0.f, 3.f}, { 1.f, 3.f}, { 2.f, 3.f}, { 3.f, 3.f}, { 4.f, 3.f}, { 5.f, 3.f}, { 6.f, 3.f}, { 7.f, 3.f},
115
+ {-8.f, 4.f}, {-7.f, 4.f}, {-6.f, 4.f}, {-5.f, 4.f}, {-4.f, 4.f}, {-3.f, 4.f}, {-2.f, 4.f}, {-1.f, 4.f},
116
+ { 0.f, 4.f}, { 1.f, 4.f}, { 2.f, 4.f}, { 3.f, 4.f}, { 4.f, 4.f}, { 5.f, 4.f}, { 6.f, 4.f}, { 7.f, 4.f},
117
+ {-8.f, 5.f}, {-7.f, 5.f}, {-6.f, 5.f}, {-5.f, 5.f}, {-4.f, 5.f}, {-3.f, 5.f}, {-2.f, 5.f}, {-1.f, 5.f},
118
+ { 0.f, 5.f}, { 1.f, 5.f}, { 2.f, 5.f}, { 3.f, 5.f}, { 4.f, 5.f}, { 5.f, 5.f}, { 6.f, 5.f}, { 7.f, 5.f},
119
+ {-8.f, 6.f}, {-7.f, 6.f}, {-6.f, 6.f}, {-5.f, 6.f}, {-4.f, 6.f}, {-3.f, 6.f}, {-2.f, 6.f}, {-1.f, 6.f},
120
+ { 0.f, 6.f}, { 1.f, 6.f}, { 2.f, 6.f}, { 3.f, 6.f}, { 4.f, 6.f}, { 5.f, 6.f}, { 6.f, 6.f}, { 7.f, 6.f},
121
+ {-8.f, 7.f}, {-7.f, 7.f}, {-6.f, 7.f}, {-5.f, 7.f}, {-4.f, 7.f}, {-3.f, 7.f}, {-2.f, 7.f}, {-1.f, 7.f},
122
+ { 0.f, 7.f}, { 1.f, 7.f}, { 2.f, 7.f}, { 3.f, 7.f}, { 4.f, 7.f}, { 5.f, 7.f}, { 6.f, 7.f}, { 7.f, 7.f}
123
+ };
124
+ double sum = 0;
125
+ for (int i=0; i<n; ++i) {
126
+ float d = x->d;
127
+ auto q = x->qs;
128
+ float s = 0;
129
+ for (int k=0; k<4; ++k) {
130
+ s += y[0]*kValues[q[0]].first + y[1]*kValues[q[0]].second +
131
+ y[2]*kValues[q[1]].first + y[3]*kValues[q[1]].second +
132
+ y[4]*kValues[q[2]].first + y[5]*kValues[q[2]].second +
133
+ y[6]*kValues[q[3]].first + y[7]*kValues[q[3]].second;
134
+ y += 8; q += 4;
135
+ }
136
+ sum += s*d;
137
+ ++x;
138
+ }
139
+ return sum;
140
+ }
141
+
142
+ inline double dot41(int n, const block_q4_1* x, const float* y) {
143
+ const static float kValues[16] = {0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f};
144
+ constexpr uint32_t kMask1 = 0x0f0f0f0f;
145
+ uint32_t u1, u2;
146
+ auto q1 = (const uint8_t*)&u1;
147
+ auto q2 = (const uint8_t*)&u2;
148
+ double sum = 0;
149
+ for (int i=0; i<n; ++i) {
150
+ auto u = (const uint32_t*)x->qs;
151
+ float s = 0, s1 = 0;
152
+ for (int k=0; k<4; ++k) {
153
+ u1 = u[k] & kMask1;
154
+ u2 = (u[k] >> 4) & kMask1;
155
+ s += y[0]*kValues[q1[0]] + y[1]*kValues[q2[0]] +
156
+ y[2]*kValues[q1[1]] + y[3]*kValues[q2[1]] +
157
+ y[4]*kValues[q1[2]] + y[5]*kValues[q2[2]] +
158
+ y[6]*kValues[q1[3]] + y[7]*kValues[q2[3]];
159
+ s1 += y[0] + y[1] + y[2] + y[3] + y[4] + y[5] + y[6] + y[7];
160
+ y += 8;
161
+ }
162
+ sum += s*x->d + s1*x->m;
163
+ ++x;
164
+ }
165
+ return sum;
166
+ }
167
+
168
+ // Copy-pasted from ggml.c
169
+ static void quantize_row_q8_0_reference(const float *x, block_q8_0 *y, int k) {
170
+ assert(k % QK8_0 == 0);
171
+ const int nb = k / QK8_0;
172
+
173
+ for (int i = 0; i < nb; i++) {
174
+ float amax = 0.0f; // absolute max
175
+
176
+ for (int l = 0; l < QK8_0; l++) {
177
+ const float v = x[i*QK8_0 + l];
178
+ amax = std::max(amax, fabsf(v));
179
+ }
180
+
181
+ const float d = amax / ((1 << 7) - 1);
182
+ const float id = d ? 1.0f/d : 0.0f;
183
+
184
+ y[i].d = d;
185
+
186
+ for (int l = 0; l < QK8_0; ++l) {
187
+ const float v = x[i*QK8_0 + l]*id;
188
+ y[i].qs[l] = roundf(v);
189
+ }
190
+ }
191
+ }
192
+
193
+ // Copy-pasted from ggml.c
194
+ static void dot_q4_q8(const int n, float* s, const void* vx, const void* vy) {
195
+ const int nb = n / QK8_0;
196
+ const block_q4_0* x = (const block_q4_0*)vx;
197
+ const block_q8_0* y = (const block_q8_0*)vy;
198
+ float sumf = 0;
199
+ for (int i = 0; i < nb; i++) {
200
+ const float d0 = x[i].d;
201
+ const float d1 = y[i].d;
202
+
203
+ const uint8_t * p0 = x[i].qs;
204
+ const int8_t * p1 = y[i].qs;
205
+
206
+ int sumi = 0;
207
+ for (int j = 0; j < QK8_0/2; j++) {
208
+ const uint8_t v0 = p0[j];
209
+
210
+ const int i0 = (int8_t) (v0 & 0xf) - 8;
211
+ const int i1 = (int8_t) (v0 >> 4) - 8;
212
+
213
+ const int i2 = p1[2*j + 0];
214
+ const int i3 = p1[2*j + 1];
215
+
216
+ sumi += i0*i2 + i1*i3;
217
+ }
218
+ sumf += d0*d1*sumi;
219
+ }
220
+ *s = sumf;
221
+ }
222
+
223
+ int main(int argc, char** argv) {
224
+
225
+ int nloop = argc > 1 ? atoi(argv[1]) : 10;
226
+ bool scalar = argc > 2 ? atoi(argv[2]) : false;
227
+ bool useQ4_1 = argc > 3 ? atoi(argv[3]) : false;
228
+
229
+ if (scalar && useQ4_1) {
230
+ printf("It is not possible to use Q4_1 quantization and scalar implementations\n");
231
+ return 1;
232
+ }
233
+
234
+ std::mt19937 rndm(1234);
235
+
236
+ std::vector<float> x1(kVecSize), y1(kVecSize);
237
+ int n4 = useQ4_1 ? kVecSize / QK4_1 : kVecSize / QK4_0; n4 = 64*((n4 + 63)/64);
238
+ int n8 = kVecSize / QK8_0; n8 = 64*((n8 + 63)/64);
239
+
240
+ const auto * funcs_cpu = ggml_get_type_traits_cpu(useQ4_1 ? GGML_TYPE_Q4_1 : GGML_TYPE_Q4_0);
241
+
242
+ std::vector<block_q4_0> q40;
243
+ std::vector<block_q4_1> q41;
244
+ if (useQ4_1) q41.resize(n4);
245
+ else q40.resize(n4);
246
+ std::vector<block_q8_0> q8(n8);
247
+ double sumt = 0, sumt2 = 0, maxt = 0;
248
+ double sumqt = 0, sumqt2 = 0, maxqt = 0;
249
+ double sum = 0, sumq = 0, exactSum = 0;
250
+ for (int iloop=0; iloop<nloop; ++iloop) {
251
+
252
+ // Fill vector x with random numbers
253
+ fillRandomGaussianFloats(x1, rndm);
254
+
255
+ // Fill vector y with random numbers
256
+ fillRandomGaussianFloats(y1, rndm);
257
+
258
+ // Compute the exact dot product
259
+ for (int k=0; k<kVecSize; ++k) exactSum += x1[k]*y1[k];
260
+
261
+ // quantize x.
262
+ // Note, we do not include this in the timing as in practical application
263
+ // we already have the quantized model weights.
264
+ if (useQ4_1) {
265
+ funcs_cpu->from_float(x1.data(), q41.data(), kVecSize);
266
+ } else {
267
+ funcs_cpu->from_float(x1.data(), q40.data(), kVecSize);
268
+ }
269
+
270
+ // Now measure time the dot product needs using the "scalar" version above
271
+ auto t1 = std::chrono::high_resolution_clock::now();
272
+ if (useQ4_1) sum += dot41(kVecSize / QK4_1, q41.data(), y1.data());
273
+ else sum += dot(kVecSize / QK4_0, q40.data(), y1.data());
274
+ auto t2 = std::chrono::high_resolution_clock::now();
275
+ auto t = 1e-3*std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
276
+ sumt += t; sumt2 += t*t; maxt = std::max(maxt, t);
277
+
278
+ // And now measure the time needed to quantize y and perform the dot product with the quantized y
279
+ t1 = std::chrono::high_resolution_clock::now();
280
+ float result;
281
+ if (scalar) {
282
+ quantize_row_q8_0_reference(y1.data(), q8.data(), kVecSize);
283
+ dot_q4_q8(kVecSize, &result, q40.data(), q8.data());
284
+ }
285
+ else {
286
+ const auto * vdot = ggml_get_type_traits_cpu(funcs_cpu->vec_dot_type);
287
+ vdot->from_float(y1.data(), q8.data(), kVecSize);
288
+ if (useQ4_1) funcs_cpu->vec_dot(kVecSize, &result, 0, q41.data(), 0, q8.data(), 0, 1);
289
+ else funcs_cpu->vec_dot(kVecSize, &result, 0, q40.data(), 0, q8.data(), 0, 1);
290
+ }
291
+ sumq += result;
292
+ t2 = std::chrono::high_resolution_clock::now();
293
+ t = 1e-3*std::chrono::duration_cast<std::chrono::nanoseconds>(t2-t1).count();
294
+ sumqt += t; sumqt2 += t*t; maxqt = std::max(maxqt, t);
295
+
296
+ }
297
+
298
+ // Report the time (and the average of the dot products so the compiler does not come up with the idea
299
+ // of optimizing away the function calls after figuring that the result is not used).
300
+ sum /= nloop; sumq /= nloop;
301
+ exactSum /= nloop;
302
+ printf("Exact result: <dot> = %g\n",exactSum);
303
+ printf("<dot> = %g, %g\n",sum,sumq);
304
+ sumt /= nloop; sumt2 /= nloop; sumt2 -= sumt*sumt;
305
+ if (sumt2 > 0) sumt2 = sqrt(sumt2);
306
+ printf("time = %g +/- %g us. maxt = %g us\n",sumt,sumt2,maxt);
307
+ sumqt /= nloop; sumqt2 /= nloop; sumqt2 -= sumqt*sumqt;
308
+ if (sumqt2 > 0) sumqt2 = sqrt(sumqt2);
309
+ printf("timeq = %g +/- %g us. maxt = %g us\n",sumqt,sumqt2,maxqt);
310
+ return 0;
311
+ }
backend/llama.cpp/pyproject.toml ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "llama-cpp-scripts"
3
+ description = "Scripts that ship with llama.cpp"
4
+ keywords = ["ggml", "gguf", "llama.cpp"]
5
+ version = "0.0.0"
6
+ dynamic = ["classifiers"]
7
+ readme = "README.md"
8
+ authors = [{name = "GGML", email = "ggml@ggml.ai"}]
9
+ requires-python = '>=3.10,<3.15'
10
+ dependencies = [
11
+ 'numpy (>=1.26.4,<3.0.0)',
12
+ 'sentencepiece (>=0.1.98,<0.3.0)',
13
+ 'transformers (==4.57.6)',
14
+ 'protobuf (>=4.21.0,<5.0.0)',
15
+ 'torch (>=2.6.0,<3.0.0)',
16
+ 'gguf @ ./gguf-py',
17
+ ]
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: OS Independent",
22
+ ]
23
+
24
+ [project.urls]
25
+ homepage = "https://ggml.ai"
26
+ repository = "https://github.com/ggml-org/llama.cpp"
27
+
28
+ [project.scripts]
29
+ llama-convert-hf-to-gguf = "convert_hf_to_gguf:main"
30
+ llama-convert-lora-to-gguf = "convert_lora_to_gguf:main"
31
+ llama-convert-llama-ggml-to-gguf = "convert_llama_ggml_to_gguf:main"
32
+ llama-ggml-vk-generate-shaders = "ggml_vk_generate_shaders:main"
33
+
34
+ [tool.poetry]
35
+ packages = [
36
+ { include = "*.py", from = "." },
37
+ { include = "conversion", from = "." },
38
+ ]
39
+
40
+ [tool.poetry.dependencies]
41
+ torch = [
42
+ { version = "==2.11.0", source = "pypi", markers = "sys_platform == 'darwin'" },
43
+ { version = "==2.11.0+cpu", source = "pytorch", markers = "sys_platform == 'linux'" },
44
+ { version = "==2.11.0", source = "pypi", markers = "sys_platform == 'win32'" },
45
+ ]
46
+
47
+ [tool.poetry.group.dev.dependencies]
48
+ pytest = "~=8.3.3"
49
+
50
+ # Force wheel + cpu
51
+ # For discussion and context see https://github.com/python-poetry/poetry#6409
52
+ [[tool.poetry.source]]
53
+ name = "pytorch"
54
+ url = "https://download.pytorch.org/whl/cpu"
55
+ priority = "explicit"
56
+
57
+ [tool.uv.sources]
58
+ torch = { index = "pytorch" }
59
+
60
+ [[tool.uv.index]]
61
+ name = "pytorch"
62
+ url = "https://download.pytorch.org/whl/cpu"
63
+ explicit = true
64
+
65
+ [build-system]
66
+ requires = ["poetry-core>=1.0.0"]
67
+ build-backend = "poetry.core.masonry.api"
backend/llama.cpp/pyrightconfig.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "extraPaths": ["gguf-py", "examples/model-conversion/scripts", "examples/model-conversion/scripts/utils"],
3
+ "pythonVersion": "3.9",
4
+ "pythonPlatform": "All",
5
+ "reportUnusedImport": "warning",
6
+ "reportDuplicateImport": "error",
7
+ "reportDeprecated": "warning",
8
+ "reportUnnecessaryTypeIgnoreComment": "information",
9
+ "disableBytesTypePromotions": false, // TODO: change once Python 3.12 is the minimum
10
+ "executionEnvironments": [
11
+ {
12
+ // TODO: make this version override work correctly
13
+ "root": "gguf-py",
14
+ "pythonVersion": "3.8",
15
+ },
16
+ {
17
+ // uses match expressions in steps.py
18
+ "root": "tools/server/tests",
19
+ "pythonVersion": "3.10",
20
+ },
21
+ ],
22
+ }
backend/llama.cpp/requirements.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # These requirements include all dependencies for all top-level python scripts
2
+ # for llama.cpp. Avoid adding packages here directly.
3
+ #
4
+ # Package versions must stay compatible across all top-level python scripts.
5
+ #
6
+
7
+ -r ./requirements/requirements-convert_legacy_llama.txt
8
+
9
+ -r ./requirements/requirements-convert_hf_to_gguf.txt
10
+ -r ./requirements/requirements-convert_hf_to_gguf_update.txt
11
+ -r ./requirements/requirements-convert_llama_ggml_to_gguf.txt
12
+ -r ./requirements/requirements-convert_lora_to_gguf.txt
13
+ -r ./requirements/requirements-tool_bench.txt
backend/llama.cpp/requirements/requirements-all.txt ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -r ../tools/mtmd/requirements.txt
2
+ -r ../tools/server/bench/requirements.txt
3
+ -r ../tools/server/tests/requirements.txt
4
+
5
+ -r ./requirements-compare-llama-bench.txt
6
+ -r ./requirements-server-bench.txt
7
+ -r ./requirements-pydantic.txt
8
+ -r ./requirements-test-tokenizer-random.txt
9
+
10
+ -r ./requirements-convert_hf_to_gguf.txt
11
+ -r ./requirements-convert_hf_to_gguf_update.txt
12
+ -r ./requirements-convert_legacy_llama.txt
13
+ -r ./requirements-convert_llama_ggml_to_gguf.txt
14
+ -r ./requirements-tool_bench.txt
15
+
16
+ -r ./requirements-gguf_editor_gui.txt
17
+
18
+ -r ../examples/model-conversion/requirements.txt
backend/llama.cpp/requirements/requirements-compare-llama-bench.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ tabulate~=0.9.0
2
+ GitPython~=3.1.43
3
+ matplotlib~=3.10.0
backend/llama.cpp/requirements/requirements-convert_hf_to_gguf.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ -r ./requirements-convert_legacy_llama.txt
2
+ --extra-index-url https://download.pytorch.org/whl/cpu
3
+
4
+ ## Embedding Gemma requires PyTorch 2.6.0 or later, bumped to 2.11.0 for compatibility
5
+ torch==2.11.0; platform_machine != "s390x"
6
+
7
+ # torch s390x packages can only be found from nightly builds
8
+ --extra-index-url https://download.pytorch.org/whl/nightly
9
+ torch>=0.0.0.dev0; platform_machine == "s390x"
backend/llama.cpp/requirements/requirements-convert_hf_to_gguf_update.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ -r ./requirements-convert_legacy_llama.txt
backend/llama.cpp/requirements/requirements-convert_legacy_llama.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ numpy~=1.26.4
2
+ sentencepiece>=0.1.98,<0.3.0
3
+
4
+ transformers==4.57.6
5
+
6
+ gguf>=0.1.0
7
+ protobuf>=4.21.0,<5.0.0
backend/llama.cpp/requirements/requirements-convert_llama_ggml_to_gguf.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ -r ./requirements-convert_legacy_llama.txt
backend/llama.cpp/requirements/requirements-convert_lora_to_gguf.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ -r ./requirements-convert_hf_to_gguf.txt
2
+ --extra-index-url https://download.pytorch.org/whl/cpu
3
+ # torch s390x packages can only be found from nightly builds
4
+ --extra-index-url https://download.pytorch.org/whl/nightly
backend/llama.cpp/requirements/requirements-gguf_editor_gui.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ numpy~=1.26.4
2
+ PySide6~=6.9.0
3
+ gguf>=0.17.0
backend/llama.cpp/requirements/requirements-pydantic.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ docstring_parser~=0.15
2
+ pydantic~=2.11.7
3
+ requests~=2.32.3
backend/llama.cpp/requirements/requirements-server-bench.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ datasets~=4.8.0
2
+ matplotlib~=3.10.0
3
+ numpy~=1.26.4
4
+ requests~=2.32.3
5
+ tqdm~=4.67.1
backend/llama.cpp/requirements/requirements-test-tokenizer-random.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ cffi~=1.16.0
backend/llama.cpp/requirements/requirements-tool_bench.txt ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiohttp~=3.9.3
2
+ pytest~=8.3.3
3
+ matplotlib~=3.10.0
4
+ numpy~=1.26.4
5
+ openai~=2.14.0
6
+ pandas~=2.2.3
7
+ prometheus-client~=0.20.0
8
+ requests~=2.32.3
9
+ wget~=3.2
10
+ typer~=0.24.1
11
+ seaborn~=0.13.2
backend/llama.cpp/scripts/apple/validate-apps.sh ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ ./scripts/apple/validate-ios.sh
3
+ ./scripts/apple/validate-macos.sh
4
+ ./scripts/apple/validate-visionos.sh
5
+ ./scripts/apple/validate-tvos.sh
backend/llama.cpp/scripts/apple/validate-ios.sh ADDED
@@ -0,0 +1,820 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # validate-ios.sh - Validate iOS Application with embedded llama.xcframework using SwiftUI
3
+
4
+ # Authentication options (optional) (can be set via environment variables)
5
+ # To use: export APPLE_ID=your.email@example.com
6
+ # export APPLE_PASSWORD=your-app-specific-password
7
+ # ./validate-ios.sh
8
+ APPLE_ID=${APPLE_ID:-""}
9
+ APPLE_PASSWORD=${APPLE_PASSWORD:-""}
10
+
11
+ # Ensure the script exits on error
12
+ set -e
13
+
14
+ # Function to print usage instructions
15
+ print_usage() {
16
+ echo "Usage: ./validate-ios.sh [OPTIONS]"
17
+ echo ""
18
+ echo "Options:"
19
+ echo " --help Show this help message"
20
+ echo " --apple-id EMAIL Apple ID email for validation"
21
+ echo " --apple-password PWD App-specific password for Apple ID"
22
+ echo ""
23
+ echo "Environment variables:"
24
+ echo " APPLE_ID Apple ID email for validation"
25
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
26
+ echo ""
27
+ echo "Notes:"
28
+ echo " - Command line options take precedence over environment variables"
29
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
30
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
31
+ }
32
+
33
+ # Parse command line arguments
34
+ while [[ $# -gt 0 ]]; do
35
+ case $1 in
36
+ --help)
37
+ print_usage
38
+ exit 0
39
+ ;;
40
+ --apple-id)
41
+ APPLE_ID="$2"
42
+ shift 2
43
+ ;;
44
+ --apple-password)
45
+ APPLE_PASSWORD="$2"
46
+ shift 2
47
+ ;;
48
+ *)
49
+ echo "Unknown option: $1"
50
+ print_usage
51
+ exit 1
52
+ ;;
53
+ esac
54
+ done
55
+
56
+ # Function to clean up in case of error
57
+ cleanup() {
58
+ # Don't clean up temp files on error to help with debugging
59
+ echo "===== iOS Validation Process Failed ====="
60
+ exit 1
61
+ }
62
+
63
+ # Set up trap to call cleanup function on error
64
+ trap cleanup ERR
65
+
66
+ set -e # Exit on any error
67
+
68
+ ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
69
+ BUILD_DIR="${ROOT_DIR}/validation-builds/ios"
70
+
71
+ # Configuration
72
+ APP_NAME="iOSLlamaTest"
73
+ BUNDLE_ID="org.ggml.iOSLlamaTest"
74
+ XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
75
+ TEMP_DIR="${BUILD_DIR}/temp"
76
+ ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
77
+ IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa"
78
+ VALIDATION_DIR="${BUILD_DIR}/validation"
79
+
80
+ # Create necessary directories
81
+ mkdir -p "${BUILD_DIR}"
82
+ mkdir -p "${TEMP_DIR}"
83
+ mkdir -p "${VALIDATION_DIR}"
84
+
85
+ echo "===== iOS Validation Process Started ====="
86
+
87
+ # 1. Create a simple test app project
88
+ echo "Creating test iOS app project..."
89
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
90
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF
91
+ <?xml version="1.0" encoding="UTF-8"?>
92
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
93
+ <plist version="1.0">
94
+ <dict>
95
+ <key>CFBundleDevelopmentRegion</key>
96
+ <string>en</string>
97
+ <key>CFBundleExecutable</key>
98
+ <string>${APP_NAME}</string>
99
+ <key>CFBundleIdentifier</key>
100
+ <string>${BUNDLE_ID}</string>
101
+ <key>CFBundleInfoDictionaryVersion</key>
102
+ <string>6.0</string>
103
+ <key>CFBundleName</key>
104
+ <string>${APP_NAME}</string>
105
+ <key>CFBundlePackageType</key>
106
+ <string>APPL</string>
107
+ <key>CFBundleShortVersionString</key>
108
+ <string>1.0</string>
109
+ <key>CFBundleVersion</key>
110
+ <string>1</string>
111
+ <key>LSRequiresIPhoneOS</key>
112
+ <true/>
113
+ <key>UILaunchScreen</key>
114
+ <dict/>
115
+ <key>UIRequiredDeviceCapabilities</key>
116
+ <array>
117
+ <string>armv7</string>
118
+ </array>
119
+ <key>UISupportedInterfaceOrientations</key>
120
+ <array>
121
+ <string>UIInterfaceOrientationPortrait</string>
122
+ </array>
123
+ </dict>
124
+ </plist>
125
+ EOF
126
+
127
+ # Create SwiftUI app files
128
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
129
+
130
+ # Create App.swift
131
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
132
+ import SwiftUI
133
+ import llama
134
+
135
+ @main
136
+ struct LlamaTestApp: App {
137
+ var body: some Scene {
138
+ WindowGroup {
139
+ ContentView()
140
+ }
141
+ }
142
+ }
143
+ EOF
144
+
145
+ # Create ContentView.swift
146
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
147
+ import SwiftUI
148
+ import llama
149
+
150
+ struct ContentView: View {
151
+ // Test that we can initialize a llama context params struct
152
+ let params = llama_context_default_params()
153
+
154
+ var body: some View {
155
+ VStack(spacing: 20) {
156
+ Text("Llama Framework Test")
157
+ .font(.largeTitle)
158
+ .padding()
159
+
160
+ Text("llama_context_default_params() created successfully")
161
+ .font(.headline)
162
+ .multilineTextAlignment(.center)
163
+ .padding()
164
+
165
+ // Display some param values to confirm the framework is working
166
+ Text("n_ctx: \(params.n_ctx)")
167
+ .font(.body)
168
+
169
+ Text("n_batch: \(params.n_batch)")
170
+ .font(.body)
171
+
172
+ Spacer()
173
+ }
174
+ .padding()
175
+ }
176
+ }
177
+
178
+ struct ContentView_Previews: PreviewProvider {
179
+ static var previews: some View {
180
+ ContentView()
181
+ }
182
+ }
183
+ EOF
184
+
185
+ # Create project.pbxproj, fixing the framework search paths issues
186
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
187
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
188
+ // !$*UTF8*$!
189
+ {
190
+ archiveVersion = 1;
191
+ classes = {
192
+ };
193
+ objectVersion = 54;
194
+ objects = {
195
+
196
+ /* Begin PBXBuildFile section */
197
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
198
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
199
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
200
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
201
+ /* End PBXBuildFile section */
202
+
203
+ /* Begin PBXCopyFilesBuildPhase section */
204
+ 88888888888888888888888 /* Embed Frameworks */ = {
205
+ isa = PBXCopyFilesBuildPhase;
206
+ buildActionMask = 2147483647;
207
+ dstPath = "";
208
+ dstSubfolderSpec = 10;
209
+ files = (
210
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
211
+ );
212
+ name = "Embed Frameworks";
213
+ runOnlyForDeploymentPostprocessing = 0;
214
+ };
215
+ /* End PBXCopyFilesBuildPhase section */
216
+
217
+ /* Begin PBXFileReference section */
218
+ EOF
219
+
220
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
221
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
222
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
223
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
224
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
225
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
226
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
227
+ /* End PBXFileReference section */
228
+ EOF
229
+
230
+ # Add the rest of the project file with fixed framework search paths
231
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
232
+ /* Begin PBXFrameworksBuildPhase section */
233
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
234
+ isa = PBXFrameworksBuildPhase;
235
+ buildActionMask = 2147483647;
236
+ files = (
237
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
238
+ );
239
+ runOnlyForDeploymentPostprocessing = 0;
240
+ };
241
+ /* End PBXFrameworksBuildPhase section */
242
+
243
+ /* Begin PBXGroup section */
244
+ EOF
245
+
246
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
247
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
248
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
249
+ isa = PBXGroup;
250
+ children = (
251
+ 99999999999999999999999 /* ${APP_NAME}.app */,
252
+ );
253
+ name = Products;
254
+ sourceTree = "<group>";
255
+ };
256
+ EOF
257
+
258
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
259
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
260
+ isa = PBXGroup;
261
+ children = (
262
+ 66666666666666666666666 /* llama.xcframework */,
263
+ );
264
+ name = Frameworks;
265
+ sourceTree = "<group>";
266
+ };
267
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
268
+ isa = PBXGroup;
269
+ children = (
270
+ FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */,
271
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
272
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
273
+ );
274
+ sourceTree = "<group>";
275
+ };
276
+ FFFFFFFFFFFFFFFFFFFFFFFF /* iOSLlamaTest */ = {
277
+ isa = PBXGroup;
278
+ children = (
279
+ 1111111111111111111111AA /* Sources */,
280
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
281
+ );
282
+ path = "iOSLlamaTest";
283
+ sourceTree = "<group>";
284
+ };
285
+ 1111111111111111111111AA /* Sources */ = {
286
+ isa = PBXGroup;
287
+ children = (
288
+ 22222222222222222222222 /* App.swift */,
289
+ 44444444444444444444444 /* ContentView.swift */,
290
+ );
291
+ path = Sources;
292
+ sourceTree = "<group>";
293
+ };
294
+ /* End PBXGroup section */
295
+ EOF
296
+
297
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
298
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
299
+ /* Begin PBXNativeTarget section */
300
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
301
+ isa = PBXNativeTarget;
302
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
303
+ buildPhases = (
304
+ 5555555555555555555555AA /* Sources */,
305
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
306
+ 6666666666666666666666AA /* Resources */,
307
+ 88888888888888888888888 /* Embed Frameworks */,
308
+ );
309
+ buildRules = (
310
+ );
311
+ dependencies = (
312
+ );
313
+ name = "${APP_NAME}";
314
+ productName = "${APP_NAME}";
315
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
316
+ productType = "com.apple.product-type.application";
317
+ };
318
+ /* End PBXNativeTarget section */
319
+
320
+ /* Begin PBXProject section */
321
+ 7777777777777777777777AA /* Project object */ = {
322
+ isa = PBXProject;
323
+ attributes = {
324
+ LastSwiftUpdateCheck = 1240;
325
+ LastUpgradeCheck = 1240;
326
+ TargetAttributes = {
327
+ 3333333333333333333333AA = {
328
+ CreatedOnToolsVersion = 12.4;
329
+ };
330
+ };
331
+ };
332
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
333
+ compatibilityVersion = "Xcode 12.0";
334
+ developmentRegion = en;
335
+ hasScannedForEncodings = 0;
336
+ knownRegions = (
337
+ en,
338
+ Base,
339
+ );
340
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
341
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
342
+ projectDirPath = "";
343
+ projectRoot = "";
344
+ targets = (
345
+ 3333333333333333333333AA /* ${APP_NAME} */,
346
+ );
347
+ };
348
+ /* End PBXProject section */
349
+ EOF
350
+
351
+ # Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS
352
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
353
+ /* Begin PBXResourcesBuildPhase section */
354
+ 6666666666666666666666AA /* Resources */ = {
355
+ isa = PBXResourcesBuildPhase;
356
+ buildActionMask = 2147483647;
357
+ files = (
358
+ );
359
+ runOnlyForDeploymentPostprocessing = 0;
360
+ };
361
+ /* End PBXResourcesBuildPhase section */
362
+
363
+ /* Begin PBXSourcesBuildPhase section */
364
+ 5555555555555555555555AA /* Sources */ = {
365
+ isa = PBXSourcesBuildPhase;
366
+ buildActionMask = 2147483647;
367
+ files = (
368
+ 33333333333333333333333 /* ContentView.swift in Sources */,
369
+ 11111111111111111111111 /* App.swift in Sources */,
370
+ );
371
+ runOnlyForDeploymentPostprocessing = 0;
372
+ };
373
+ /* End PBXSourcesBuildPhase section */
374
+
375
+ /* Begin XCBuildConfiguration section */
376
+ 9999999999999999999999AA /* Debug */ = {
377
+ isa = XCBuildConfiguration;
378
+ buildSettings = {
379
+ ALWAYS_SEARCH_USER_PATHS = NO;
380
+ CLANG_ANALYZER_NONNULL = YES;
381
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
382
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
383
+ CLANG_CXX_LIBRARY = "libc++";
384
+ CLANG_ENABLE_MODULES = YES;
385
+ CLANG_ENABLE_OBJC_ARC = YES;
386
+ CLANG_ENABLE_OBJC_WEAK = YES;
387
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
388
+ CLANG_WARN_BOOL_CONVERSION = YES;
389
+ CLANG_WARN_COMMA = YES;
390
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
391
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
392
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
393
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
394
+ CLANG_WARN_EMPTY_BODY = YES;
395
+ CLANG_WARN_ENUM_CONVERSION = YES;
396
+ CLANG_WARN_INFINITE_RECURSION = YES;
397
+ CLANG_WARN_INT_CONVERSION = YES;
398
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
399
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
400
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
401
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
402
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
403
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
404
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
405
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
406
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
407
+ CLANG_WARN_UNREACHABLE_CODE = YES;
408
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
409
+ COPY_PHASE_STRIP = NO;
410
+ DEBUG_INFORMATION_FORMAT = dwarf;
411
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
412
+ ENABLE_TESTABILITY = YES;
413
+ GCC_C_LANGUAGE_STANDARD = gnu11;
414
+ GCC_DYNAMIC_NO_PIC = NO;
415
+ GCC_NO_COMMON_BLOCKS = YES;
416
+ GCC_OPTIMIZATION_LEVEL = 0;
417
+ GCC_PREPROCESSOR_DEFINITIONS = (
418
+ "DEBUG=1",
419
+ "$(inherited)",
420
+ );
421
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
422
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
423
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
424
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
425
+ GCC_WARN_UNUSED_FUNCTION = YES;
426
+ GCC_WARN_UNUSED_VARIABLE = YES;
427
+ IPHONEOS_DEPLOYMENT_TARGET = 16.4;
428
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
429
+ MTL_FAST_MATH = YES;
430
+ ONLY_ACTIVE_ARCH = YES;
431
+ SDKROOT = iphoneos;
432
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
433
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
434
+ };
435
+ name = Debug;
436
+ };
437
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
438
+ isa = XCBuildConfiguration;
439
+ buildSettings = {
440
+ ALWAYS_SEARCH_USER_PATHS = NO;
441
+ CLANG_ANALYZER_NONNULL = YES;
442
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
443
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
444
+ CLANG_CXX_LIBRARY = "libc++";
445
+ CLANG_ENABLE_MODULES = YES;
446
+ CLANG_ENABLE_OBJC_ARC = YES;
447
+ CLANG_ENABLE_OBJC_WEAK = YES;
448
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
449
+ CLANG_WARN_BOOL_CONVERSION = YES;
450
+ CLANG_WARN_COMMA = YES;
451
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
452
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
453
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
454
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
455
+ CLANG_WARN_EMPTY_BODY = YES;
456
+ CLANG_WARN_ENUM_CONVERSION = YES;
457
+ CLANG_WARN_INFINITE_RECURSION = YES;
458
+ CLANG_WARN_INT_CONVERSION = YES;
459
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
460
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
461
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
462
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
463
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
464
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
465
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
466
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
467
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
468
+ CLANG_WARN_UNREACHABLE_CODE = YES;
469
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
470
+ COPY_PHASE_STRIP = NO;
471
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
472
+ ENABLE_NS_ASSERTIONS = NO;
473
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
474
+ GCC_C_LANGUAGE_STANDARD = gnu11;
475
+ GCC_NO_COMMON_BLOCKS = YES;
476
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
477
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
478
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
479
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
480
+ GCC_WARN_UNUSED_FUNCTION = YES;
481
+ GCC_WARN_UNUSED_VARIABLE = YES;
482
+ IPHONEOS_DEPLOYMENT_TARGET = 16.4;
483
+ MTL_ENABLE_DEBUG_INFO = NO;
484
+ MTL_FAST_MATH = YES;
485
+ SDKROOT = iphoneos;
486
+ SWIFT_COMPILATION_MODE = wholemodule;
487
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
488
+ VALIDATE_PRODUCT = YES;
489
+ };
490
+ name = Release;
491
+ };
492
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
493
+ isa = XCBuildConfiguration;
494
+ buildSettings = {
495
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
496
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
497
+ CODE_SIGN_STYLE = Manual;
498
+ DEVELOPMENT_TEAM = "";
499
+ ENABLE_PREVIEWS = YES;
500
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
501
+ INFOPLIST_FILE = "iOSLlamaTest/Info.plist";
502
+ LD_RUNPATH_SEARCH_PATHS = (
503
+ "$(inherited)",
504
+ "@executable_path/Frameworks",
505
+ );
506
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest";
507
+ PRODUCT_NAME = "$(TARGET_NAME)";
508
+ PROVISIONING_PROFILE_SPECIFIER = "";
509
+ SWIFT_VERSION = 5.0;
510
+ TARGETED_DEVICE_FAMILY = "1,2";
511
+ };
512
+ name = Debug;
513
+ };
514
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
515
+ isa = XCBuildConfiguration;
516
+ buildSettings = {
517
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
518
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
519
+ CODE_SIGN_STYLE = Manual;
520
+ DEVELOPMENT_TEAM = "";
521
+ ENABLE_PREVIEWS = YES;
522
+ FRAMEWORK_SEARCH_PATHS = (
523
+ "$(inherited)",
524
+ "$(PROJECT_DIR)",
525
+ );
526
+ INFOPLIST_FILE = "iOSLlamaTest/Info.plist";
527
+ LD_RUNPATH_SEARCH_PATHS = (
528
+ "$(inherited)",
529
+ "@executable_path/Frameworks",
530
+ );
531
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.iOSLlamaTest";
532
+ PRODUCT_NAME = "$(TARGET_NAME)";
533
+ PROVISIONING_PROFILE_SPECIFIER = "";
534
+ SWIFT_VERSION = 5.0;
535
+ TARGETED_DEVICE_FAMILY = "1,2";
536
+ };
537
+ name = Release;
538
+ };
539
+ /* End XCBuildConfiguration section */
540
+ EOF
541
+
542
+ # Finish the project.pbxproj file
543
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
544
+ /* Begin XCConfigurationList section */
545
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
546
+ isa = XCConfigurationList;
547
+ buildConfigurations = (
548
+ 9999999999999999999999AA /* Debug */,
549
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
550
+ );
551
+ defaultConfigurationIsVisible = 0;
552
+ defaultConfigurationName = Release;
553
+ };
554
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
555
+ isa = XCConfigurationList;
556
+ buildConfigurations = (
557
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
558
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
559
+ );
560
+ defaultConfigurationIsVisible = 0;
561
+ defaultConfigurationName = Release;
562
+ };
563
+ /* End XCConfigurationList section */
564
+ };
565
+ rootObject = 7777777777777777777777AA /* Project object */;
566
+ }
567
+ EOF
568
+
569
+ # 2. Copy XCFramework to test project
570
+ echo "Copying XCFramework to test project..."
571
+ cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
572
+
573
+ # 3. Build and archive the app
574
+ echo "Building and archiving test app..."
575
+ cd "${TEMP_DIR}/${APP_NAME}"
576
+
577
+ # Create a simple xcscheme file to avoid xcodebuild scheme issues
578
+ mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
579
+ cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
580
+ <?xml version="1.0" encoding="UTF-8"?>
581
+ <Scheme
582
+ LastUpgradeVersion = "1240"
583
+ version = "1.3">
584
+ <BuildAction
585
+ parallelizeBuildables = "YES"
586
+ buildImplicitDependencies = "YES">
587
+ <BuildActionEntries>
588
+ <BuildActionEntry
589
+ buildForTesting = "YES"
590
+ buildForRunning = "YES"
591
+ buildForProfiling = "YES"
592
+ buildForArchiving = "YES"
593
+ buildForAnalyzing = "YES">
594
+ <BuildableReference
595
+ BuildableIdentifier = "primary"
596
+ BlueprintIdentifier = "3333333333333333333333AA"
597
+ BuildableName = "${APP_NAME}.app"
598
+ BlueprintName = "${APP_NAME}"
599
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
600
+ </BuildableReference>
601
+ </BuildActionEntry>
602
+ </BuildActionEntries>
603
+ </BuildAction>
604
+ <TestAction
605
+ buildConfiguration = "Debug"
606
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
607
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
608
+ shouldUseLaunchSchemeArgsEnv = "YES">
609
+ <Testables>
610
+ </Testables>
611
+ </TestAction>
612
+ <LaunchAction
613
+ buildConfiguration = "Debug"
614
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
615
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
616
+ launchStyle = "0"
617
+ useCustomWorkingDirectory = "NO"
618
+ ignoresPersistentStateOnLaunch = "NO"
619
+ debugDocumentVersioning = "YES"
620
+ debugServiceExtension = "internal"
621
+ allowLocationSimulation = "YES">
622
+ <BuildableProductRunnable
623
+ runnableDebuggingMode = "0">
624
+ <BuildableReference
625
+ BuildableIdentifier = "primary"
626
+ BlueprintIdentifier = "3333333333333333333333AA"
627
+ BuildableName = "${APP_NAME}.app"
628
+ BlueprintName = "${APP_NAME}"
629
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
630
+ </BuildableReference>
631
+ </BuildableProductRunnable>
632
+ </LaunchAction>
633
+ <ProfileAction
634
+ buildConfiguration = "Release"
635
+ shouldUseLaunchSchemeArgsEnv = "YES"
636
+ savedToolIdentifier = ""
637
+ useCustomWorkingDirectory = "NO"
638
+ debugDocumentVersioning = "YES">
639
+ <BuildableProductRunnable
640
+ runnableDebuggingMode = "0">
641
+ <BuildableReference
642
+ BuildableIdentifier = "primary"
643
+ BlueprintIdentifier = "3333333333333333333333AA"
644
+ BuildableName = "${APP_NAME}.app"
645
+ BlueprintName = "${APP_NAME}"
646
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
647
+ </BuildableReference>
648
+ </BuildableProductRunnable>
649
+ </ProfileAction>
650
+ <AnalyzeAction
651
+ buildConfiguration = "Debug">
652
+ </AnalyzeAction>
653
+ <ArchiveAction
654
+ buildConfiguration = "Release"
655
+ revealArchiveInOrganizer = "YES">
656
+ </ArchiveAction>
657
+ </Scheme>
658
+ EOF
659
+
660
+ # Now use xcodebuild with an explicitly defined product name
661
+ xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk iphoneos -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
662
+
663
+ # 4. Create IPA from archive
664
+ echo "Creating IPA from archive..."
665
+ mkdir -p "${TEMP_DIR}/Payload"
666
+ cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/"
667
+
668
+ # Check and log app structure before zipping
669
+ echo "App structure:"
670
+ ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/"
671
+ echo "Frameworks:"
672
+ ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
673
+
674
+ cd "${TEMP_DIR}"
675
+ zip -r "${IPA_PATH}" Payload
676
+
677
+ # Check embedded provisioning profile
678
+ echo "Checking provisioning profile (if any)..."
679
+ PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null)
680
+ if [ -n "$PROVISIONING_PROFILE" ]; then
681
+ echo "Found embedded provisioning profile:"
682
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
683
+ else
684
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
685
+ fi
686
+
687
+ # 5. Validate the IPA
688
+ echo "Validating IPA..."
689
+ VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
690
+
691
+ # Check if authentication credentials are provided
692
+ AUTH_ARGS=""
693
+ if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
694
+ echo "Using Apple ID authentication for validation..."
695
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
696
+ else
697
+ echo "No authentication credentials provided. Will perform basic validation."
698
+ echo "To use your personal developer account, you can run the script with:"
699
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-ios.sh"
700
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
701
+ fi
702
+
703
+ # Run validation with detailed output
704
+ echo "Running validation with altool..."
705
+ if [ -n "$AUTH_ARGS" ]; then
706
+ # Use eval to properly handle the quoted arguments
707
+ eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type ios --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}"
708
+ else
709
+ xcrun altool --validate-app -f "${IPA_PATH}" --type ios --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}"
710
+ fi
711
+ VALIDATION_RESULT=$?
712
+
713
+ # Final validation result
714
+ FINAL_VALIDATION_RESULT=0
715
+
716
+ # Check if validation failed because the app isn't in App Store Connect
717
+ if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then
718
+ echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect"
719
+ echo "This is expected for apps that haven't been registered in App Store Connect yet."
720
+ echo "This doesn't indicate a problem with the build or framework."
721
+
722
+ # Perform alternative validation
723
+ echo "Performing alternative validation checks..."
724
+
725
+ # Check if IPA was created successfully
726
+ if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then
727
+ echo "✅ IPA file created successfully"
728
+ else
729
+ echo "❌ IPA file not created or empty"
730
+ FINAL_VALIDATION_RESULT=1
731
+ fi
732
+
733
+ # Check if app binary exists and is executable
734
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then
735
+ echo "✅ App binary exists and is executable"
736
+ else
737
+ echo "❌ App binary missing or not executable"
738
+ FINAL_VALIDATION_RESULT=1
739
+ fi
740
+
741
+ # Check if framework was properly embedded
742
+ if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then
743
+ echo "✅ llama.framework properly embedded"
744
+ else
745
+ echo "❌ llama.framework not properly embedded"
746
+ FINAL_VALIDATION_RESULT=1
747
+ fi
748
+
749
+ # Check if framework binary exists
750
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then
751
+ echo "✅ Framework binary exists"
752
+
753
+ # Further validate framework by checking architecture
754
+ ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|armv7\\|x86_64" | tr '\n' ' ')
755
+ if [ -n "$ARCHS" ]; then
756
+ echo "✅ Framework architecture(s): $ARCHS"
757
+ else
758
+ echo "⚠️ Could not determine framework architecture"
759
+ fi
760
+ else
761
+ echo "❌ Framework binary missing"
762
+ FINAL_VALIDATION_RESULT=1
763
+ fi
764
+
765
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
766
+ echo "✅ Alternative validation PASSED: App built successfully with embedded framework"
767
+ else
768
+ echo "❌ Alternative validation FAILED: Issues found with the app or framework"
769
+ fi
770
+ elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then
771
+ echo "✅ iOS Validation PASSED: IPA successfully validated"
772
+ echo "Results saved to ${VALIDATION_OUTPUT}"
773
+ else
774
+ echo "❌ iOS Validation FAILED: IPA validation found issues"
775
+ echo "See validation output at ${VALIDATION_OUTPUT}"
776
+ echo ""
777
+ echo "==== VALIDATION ERRORS ===="
778
+
779
+ # Try to extract specific errors from the output
780
+ if grep -q "Error" "${VALIDATION_OUTPUT}"; then
781
+ grep -A 5 "Error" "${VALIDATION_OUTPUT}"
782
+ else
783
+ # If no specific error found, show the whole log
784
+ cat "${VALIDATION_OUTPUT}"
785
+ fi
786
+
787
+ # Additional debugging: check IPA contents
788
+ echo ""
789
+ echo "==== IPA CONTENTS ===="
790
+ mkdir -p "${TEMP_DIR}/ipa_contents"
791
+ unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents"
792
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/"
793
+
794
+ # Check for code signing issues
795
+ echo ""
796
+ echo "==== CODE SIGNING INFO ===="
797
+ codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed"
798
+
799
+ # Check embedded frameworks
800
+ echo ""
801
+ echo "==== FRAMEWORK INFO ===="
802
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
803
+ fi
804
+
805
+ # Don't clean up on error to allow inspection
806
+ if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
807
+ echo ""
808
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
809
+ echo "===== iOS Validation Process Failed ====="
810
+ exit 1
811
+ fi
812
+
813
+ # Clean up temporary files but keep build artifacts
814
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
815
+ echo "Cleaning up temporary files..."
816
+ #rm -rf "${TEMP_DIR}"
817
+ fi
818
+
819
+ echo "===== iOS Validation Process Completed ====="
820
+ exit $FINAL_VALIDATION_RESULT
backend/llama.cpp/scripts/apple/validate-macos.sh ADDED
@@ -0,0 +1,781 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # validate-macos.sh - Validate macOS Application with embedded llama.xcframework using SwiftUI
3
+
4
+ # Authentication options (optional) (can be set via environment variables)
5
+ # To use: export APPLE_ID=your.email@example.com
6
+ # export APPLE_PASSWORD=your-app-specific-password
7
+ # ./validate-macos.sh
8
+ APPLE_ID=${APPLE_ID:-""}
9
+ APPLE_PASSWORD=${APPLE_PASSWORD:-""}
10
+
11
+ # Ensure the script exits on error
12
+ set -e
13
+
14
+ # Function to print usage instructions
15
+ print_usage() {
16
+ echo "Usage: ./validate-macos.sh [OPTIONS]"
17
+ echo ""
18
+ echo "Options:"
19
+ echo " --help Show this help message"
20
+ echo " --apple-id EMAIL Apple ID email for validation"
21
+ echo " --apple-password PWD App-specific password for Apple ID"
22
+ echo ""
23
+ echo "Environment variables:"
24
+ echo " APPLE_ID Apple ID email for validation"
25
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
26
+ echo ""
27
+ echo "Notes:"
28
+ echo " - Command line options take precedence over environment variables"
29
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
30
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
31
+ }
32
+
33
+ # Parse command line arguments
34
+ while [[ $# -gt 0 ]]; do
35
+ case $1 in
36
+ --help)
37
+ print_usage
38
+ exit 0
39
+ ;;
40
+ --apple-id)
41
+ APPLE_ID="$2"
42
+ shift 2
43
+ ;;
44
+ --apple-password)
45
+ APPLE_PASSWORD="$2"
46
+ shift 2
47
+ ;;
48
+ *)
49
+ echo "Unknown option: $1"
50
+ print_usage
51
+ exit 1
52
+ ;;
53
+ esac
54
+ done
55
+
56
+ # Function to clean up in case of error
57
+ cleanup() {
58
+ # Don't clean up temp files on error to help with debugging
59
+ echo "===== macOS Validation Process Failed ====="
60
+ exit 1
61
+ }
62
+
63
+ # Set up trap to call cleanup function on error
64
+ trap cleanup ERR
65
+
66
+ set -e # Exit on any error
67
+
68
+ ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
69
+ BUILD_DIR="${ROOT_DIR}/validation-builds/ios"
70
+
71
+ # Configuration
72
+ APP_NAME="MacOSLlamaTest"
73
+ BUNDLE_ID="org.ggml.MacOSLlamaTest"
74
+ XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
75
+ TEMP_DIR="${BUILD_DIR}/temp"
76
+ ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
77
+ APP_PATH="${BUILD_DIR}/${APP_NAME}.app"
78
+ ZIP_PATH="${BUILD_DIR}/${APP_NAME}.zip"
79
+ VALIDATION_DIR="${BUILD_DIR}/validation"
80
+
81
+ # Create necessary directories
82
+ mkdir -p "${BUILD_DIR}"
83
+ mkdir -p "${TEMP_DIR}"
84
+ mkdir -p "${VALIDATION_DIR}"
85
+
86
+ echo "===== macOS Validation Process Started ====="
87
+
88
+ # 1. Create a simple test app project
89
+ echo "Creating test macOS app project..."
90
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
91
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF
92
+ <?xml version="1.0" encoding="UTF-8"?>
93
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
94
+ <plist version="1.0">
95
+ <dict>
96
+ <key>CFBundleDevelopmentRegion</key>
97
+ <string>en</string>
98
+ <key>CFBundleExecutable</key>
99
+ <string>${APP_NAME}</string>
100
+ <key>CFBundleIdentifier</key>
101
+ <string>${BUNDLE_ID}</string>
102
+ <key>CFBundleInfoDictionaryVersion</key>
103
+ <string>6.0</string>
104
+ <key>CFBundleName</key>
105
+ <string>${APP_NAME}</string>
106
+ <key>CFBundlePackageType</key>
107
+ <string>APPL</string>
108
+ <key>CFBundleShortVersionString</key>
109
+ <string>1.0</string>
110
+ <key>CFBundleVersion</key>
111
+ <string>1</string>
112
+ <key>LSMinimumSystemVersion</key>
113
+ <string>12.0</string>
114
+ <key>NSHumanReadableCopyright</key>
115
+ <string>Copyright © 2025 GGML. All rights reserved.</string>
116
+ <key>NSPrincipalClass</key>
117
+ <string>NSApplication</string>
118
+ </dict>
119
+ </plist>
120
+ EOF
121
+
122
+ # Create SwiftUI app files
123
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
124
+
125
+ # Create App.swift
126
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
127
+ import SwiftUI
128
+ import llama
129
+
130
+ @main
131
+ struct LlamaTestApp: App {
132
+ var body: some Scene {
133
+ WindowGroup {
134
+ ContentView()
135
+ }
136
+ }
137
+ }
138
+ EOF
139
+
140
+ # Create ContentView.swift with macOS specific elements
141
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
142
+ import SwiftUI
143
+ import llama
144
+
145
+ struct ContentView: View {
146
+ // Test that we can initialize a llama context params struct
147
+ let params = llama_context_default_params()
148
+
149
+ var body: some View {
150
+ VStack(spacing: 20) {
151
+ Text("Llama Framework Test on macOS")
152
+ .font(.largeTitle)
153
+ .padding()
154
+
155
+ Text("llama_context_default_params() created successfully")
156
+ .font(.headline)
157
+ .multilineTextAlignment(.center)
158
+ .padding()
159
+
160
+ // Display some param values to confirm the framework is working
161
+ Text("n_ctx: \(params.n_ctx)")
162
+ .font(.body)
163
+
164
+ Text("n_batch: \(params.n_batch)")
165
+ .font(.body)
166
+
167
+ Spacer()
168
+ }
169
+ .padding()
170
+ .frame(width: 600, height: 400)
171
+ }
172
+ }
173
+
174
+ struct ContentView_Previews: PreviewProvider {
175
+ static var previews: some View {
176
+ ContentView()
177
+ }
178
+ }
179
+ EOF
180
+
181
+ # Create project.pbxproj, fixing the framework search paths issues
182
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
183
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
184
+ // !$*UTF8*$!
185
+ {
186
+ archiveVersion = 1;
187
+ classes = {
188
+ };
189
+ objectVersion = 54;
190
+ objects = {
191
+
192
+ /* Begin PBXBuildFile section */
193
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
194
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
195
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
196
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
197
+ /* End PBXBuildFile section */
198
+
199
+ /* Begin PBXCopyFilesBuildPhase section */
200
+ 88888888888888888888888 /* Embed Frameworks */ = {
201
+ isa = PBXCopyFilesBuildPhase;
202
+ buildActionMask = 2147483647;
203
+ dstPath = "";
204
+ dstSubfolderSpec = 10;
205
+ files = (
206
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
207
+ );
208
+ name = "Embed Frameworks";
209
+ runOnlyForDeploymentPostprocessing = 0;
210
+ };
211
+ /* End PBXCopyFilesBuildPhase section */
212
+
213
+ /* Begin PBXFileReference section */
214
+ EOF
215
+
216
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
217
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
218
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
219
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
220
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
221
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
222
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
223
+ /* End PBXFileReference section */
224
+ EOF
225
+
226
+ # Add the rest of the project file with fixed framework search paths
227
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
228
+ /* Begin PBXFrameworksBuildPhase section */
229
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
230
+ isa = PBXFrameworksBuildPhase;
231
+ buildActionMask = 2147483647;
232
+ files = (
233
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
234
+ );
235
+ runOnlyForDeploymentPostprocessing = 0;
236
+ };
237
+ /* End PBXFrameworksBuildPhase section */
238
+
239
+ /* Begin PBXGroup section */
240
+ EOF
241
+
242
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
243
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
244
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
245
+ isa = PBXGroup;
246
+ children = (
247
+ 99999999999999999999999 /* ${APP_NAME}.app */,
248
+ );
249
+ name = Products;
250
+ sourceTree = "<group>";
251
+ };
252
+ EOF
253
+
254
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
255
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
256
+ isa = PBXGroup;
257
+ children = (
258
+ 66666666666666666666666 /* llama.xcframework */,
259
+ );
260
+ name = Frameworks;
261
+ sourceTree = "<group>";
262
+ };
263
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
264
+ isa = PBXGroup;
265
+ children = (
266
+ FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSLlamaTest */,
267
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
268
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
269
+ );
270
+ sourceTree = "<group>";
271
+ };
272
+ FFFFFFFFFFFFFFFFFFFFFFFF /* MacOSLlamaTest */ = {
273
+ isa = PBXGroup;
274
+ children = (
275
+ 1111111111111111111111AA /* Sources */,
276
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
277
+ );
278
+ path = "MacOSLlamaTest";
279
+ sourceTree = "<group>";
280
+ };
281
+ 1111111111111111111111AA /* Sources */ = {
282
+ isa = PBXGroup;
283
+ children = (
284
+ 22222222222222222222222 /* App.swift */,
285
+ 44444444444444444444444 /* ContentView.swift */,
286
+ );
287
+ path = Sources;
288
+ sourceTree = "<group>";
289
+ };
290
+ /* End PBXGroup section */
291
+ EOF
292
+
293
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
294
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
295
+ /* Begin PBXNativeTarget section */
296
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
297
+ isa = PBXNativeTarget;
298
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
299
+ buildPhases = (
300
+ 5555555555555555555555AA /* Sources */,
301
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
302
+ 6666666666666666666666AA /* Resources */,
303
+ 88888888888888888888888 /* Embed Frameworks */,
304
+ );
305
+ buildRules = (
306
+ );
307
+ dependencies = (
308
+ );
309
+ name = "${APP_NAME}";
310
+ productName = "${APP_NAME}";
311
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
312
+ productType = "com.apple.product-type.application";
313
+ };
314
+ /* End PBXNativeTarget section */
315
+
316
+ /* Begin PBXProject section */
317
+ 7777777777777777777777AA /* Project object */ = {
318
+ isa = PBXProject;
319
+ attributes = {
320
+ LastSwiftUpdateCheck = 1240;
321
+ LastUpgradeCheck = 1240;
322
+ TargetAttributes = {
323
+ 3333333333333333333333AA = {
324
+ CreatedOnToolsVersion = 12.4;
325
+ };
326
+ };
327
+ };
328
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
329
+ compatibilityVersion = "Xcode 12.0";
330
+ developmentRegion = en;
331
+ hasScannedForEncodings = 0;
332
+ knownRegions = (
333
+ en,
334
+ Base,
335
+ );
336
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
337
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
338
+ projectDirPath = "";
339
+ projectRoot = "";
340
+ targets = (
341
+ 3333333333333333333333AA /* ${APP_NAME} */,
342
+ );
343
+ };
344
+ /* End PBXProject section */
345
+ EOF
346
+
347
+ # Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS and macOS settings
348
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
349
+ /* Begin PBXResourcesBuildPhase section */
350
+ 6666666666666666666666AA /* Resources */ = {
351
+ isa = PBXResourcesBuildPhase;
352
+ buildActionMask = 2147483647;
353
+ files = (
354
+ );
355
+ runOnlyForDeploymentPostprocessing = 0;
356
+ };
357
+ /* End PBXResourcesBuildPhase section */
358
+
359
+ /* Begin PBXSourcesBuildPhase section */
360
+ 5555555555555555555555AA /* Sources */ = {
361
+ isa = PBXSourcesBuildPhase;
362
+ buildActionMask = 2147483647;
363
+ files = (
364
+ 33333333333333333333333 /* ContentView.swift in Sources */,
365
+ 11111111111111111111111 /* App.swift in Sources */,
366
+ );
367
+ runOnlyForDeploymentPostprocessing = 0;
368
+ };
369
+ /* End PBXSourcesBuildPhase section */
370
+
371
+ /* Begin XCBuildConfiguration section */
372
+ 9999999999999999999999AA /* Debug */ = {
373
+ isa = XCBuildConfiguration;
374
+ buildSettings = {
375
+ ALWAYS_SEARCH_USER_PATHS = NO;
376
+ CLANG_ANALYZER_NONNULL = YES;
377
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
378
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
379
+ CLANG_CXX_LIBRARY = "libc++";
380
+ CLANG_ENABLE_MODULES = YES;
381
+ CLANG_ENABLE_OBJC_ARC = YES;
382
+ CLANG_ENABLE_OBJC_WEAK = YES;
383
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
384
+ CLANG_WARN_BOOL_CONVERSION = YES;
385
+ CLANG_WARN_COMMA = YES;
386
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
387
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
388
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
389
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
390
+ CLANG_WARN_EMPTY_BODY = YES;
391
+ CLANG_WARN_ENUM_CONVERSION = YES;
392
+ CLANG_WARN_INFINITE_RECURSION = YES;
393
+ CLANG_WARN_INT_CONVERSION = YES;
394
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
395
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
396
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
397
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
398
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
399
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
400
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
401
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
402
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
403
+ CLANG_WARN_UNREACHABLE_CODE = YES;
404
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
405
+ COPY_PHASE_STRIP = NO;
406
+ DEBUG_INFORMATION_FORMAT = dwarf;
407
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
408
+ ENABLE_TESTABILITY = YES;
409
+ GCC_C_LANGUAGE_STANDARD = gnu11;
410
+ GCC_DYNAMIC_NO_PIC = NO;
411
+ GCC_NO_COMMON_BLOCKS = YES;
412
+ GCC_OPTIMIZATION_LEVEL = 0;
413
+ GCC_PREPROCESSOR_DEFINITIONS = (
414
+ "DEBUG=1",
415
+ "$(inherited)",
416
+ );
417
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
418
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
419
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
420
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
421
+ GCC_WARN_UNUSED_FUNCTION = YES;
422
+ GCC_WARN_UNUSED_VARIABLE = YES;
423
+ MACOSX_DEPLOYMENT_TARGET = 12.0;
424
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
425
+ MTL_FAST_MATH = YES;
426
+ ONLY_ACTIVE_ARCH = YES;
427
+ SDKROOT = macosx;
428
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
429
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
430
+ };
431
+ name = Debug;
432
+ };
433
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
434
+ isa = XCBuildConfiguration;
435
+ buildSettings = {
436
+ ALWAYS_SEARCH_USER_PATHS = NO;
437
+ CLANG_ANALYZER_NONNULL = YES;
438
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
439
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
440
+ CLANG_CXX_LIBRARY = "libc++";
441
+ CLANG_ENABLE_MODULES = YES;
442
+ CLANG_ENABLE_OBJC_ARC = YES;
443
+ CLANG_ENABLE_OBJC_WEAK = YES;
444
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
445
+ CLANG_WARN_BOOL_CONVERSION = YES;
446
+ CLANG_WARN_COMMA = YES;
447
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
448
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
449
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
450
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
451
+ CLANG_WARN_EMPTY_BODY = YES;
452
+ CLANG_WARN_ENUM_CONVERSION = YES;
453
+ CLANG_WARN_INFINITE_RECURSION = YES;
454
+ CLANG_WARN_INT_CONVERSION = YES;
455
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
456
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
457
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
458
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
459
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
460
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
461
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
462
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
463
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
464
+ CLANG_WARN_UNREACHABLE_CODE = YES;
465
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
466
+ COPY_PHASE_STRIP = NO;
467
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
468
+ ENABLE_NS_ASSERTIONS = NO;
469
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
470
+ GCC_C_LANGUAGE_STANDARD = gnu11;
471
+ GCC_NO_COMMON_BLOCKS = YES;
472
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
473
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
474
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
475
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
476
+ GCC_WARN_UNUSED_FUNCTION = YES;
477
+ GCC_WARN_UNUSED_VARIABLE = YES;
478
+ MACOSX_DEPLOYMENT_TARGET = 12.0;
479
+ MTL_ENABLE_DEBUG_INFO = NO;
480
+ MTL_FAST_MATH = YES;
481
+ SDKROOT = macosx;
482
+ SWIFT_COMPILATION_MODE = wholemodule;
483
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
484
+ };
485
+ name = Release;
486
+ };
487
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
488
+ isa = XCBuildConfiguration;
489
+ buildSettings = {
490
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
491
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
492
+ CODE_SIGN_STYLE = Manual;
493
+ COMBINE_HIDPI_IMAGES = YES;
494
+ DEVELOPMENT_TEAM = "";
495
+ ENABLE_HARDENED_RUNTIME = YES;
496
+ ENABLE_PREVIEWS = YES;
497
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
498
+ INFOPLIST_FILE = "MacOSLlamaTest/Info.plist";
499
+ LD_RUNPATH_SEARCH_PATHS = (
500
+ "$(inherited)",
501
+ "@executable_path/../Frameworks",
502
+ );
503
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSLlamaTest";
504
+ PRODUCT_NAME = "$(TARGET_NAME)";
505
+ PROVISIONING_PROFILE_SPECIFIER = "";
506
+ SWIFT_VERSION = 5.0;
507
+ };
508
+ name = Debug;
509
+ };
510
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
511
+ isa = XCBuildConfiguration;
512
+ buildSettings = {
513
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
514
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
515
+ CODE_SIGN_STYLE = Manual;
516
+ COMBINE_HIDPI_IMAGES = YES;
517
+ DEVELOPMENT_TEAM = "";
518
+ ENABLE_HARDENED_RUNTIME = YES;
519
+ ENABLE_PREVIEWS = YES;
520
+ FRAMEWORK_SEARCH_PATHS = (
521
+ "$(inherited)",
522
+ "$(PROJECT_DIR)",
523
+ );
524
+ INFOPLIST_FILE = "MacOSLlamaTest/Info.plist";
525
+ LD_RUNPATH_SEARCH_PATHS = (
526
+ "$(inherited)",
527
+ "@executable_path/../Frameworks",
528
+ );
529
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.MacOSLlamaTest";
530
+ PRODUCT_NAME = "$(TARGET_NAME)";
531
+ PROVISIONING_PROFILE_SPECIFIER = "";
532
+ SWIFT_VERSION = 5.0;
533
+ };
534
+ name = Release;
535
+ };
536
+ /* End XCBuildConfiguration section */
537
+ EOF
538
+
539
+ # Finish the project.pbxproj file
540
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
541
+ /* Begin XCConfigurationList section */
542
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
543
+ isa = XCConfigurationList;
544
+ buildConfigurations = (
545
+ 9999999999999999999999AA /* Debug */,
546
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
547
+ );
548
+ defaultConfigurationIsVisible = 0;
549
+ defaultConfigurationName = Release;
550
+ };
551
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
552
+ isa = XCConfigurationList;
553
+ buildConfigurations = (
554
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
555
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
556
+ );
557
+ defaultConfigurationIsVisible = 0;
558
+ defaultConfigurationName = Release;
559
+ };
560
+ /* End XCConfigurationList section */
561
+ };
562
+ rootObject = 7777777777777777777777AA /* Project object */;
563
+ }
564
+ EOF
565
+
566
+ # 2. Copy XCFramework to test project
567
+ echo "Copying XCFramework to test project..."
568
+ cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
569
+
570
+ # 3. Build and archive the app
571
+ echo "Building and archiving test app..."
572
+ cd "${TEMP_DIR}/${APP_NAME}"
573
+
574
+ # Create a simple xcscheme file to avoid xcodebuild scheme issues
575
+ mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
576
+ cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
577
+ <?xml version="1.0" encoding="UTF-8"?>
578
+ <Scheme
579
+ LastUpgradeVersion = "1240"
580
+ version = "1.3">
581
+ <BuildAction
582
+ parallelizeBuildables = "YES"
583
+ buildImplicitDependencies = "YES">
584
+ <BuildActionEntries>
585
+ <BuildActionEntry
586
+ buildForTesting = "YES"
587
+ buildForRunning = "YES"
588
+ buildForProfiling = "YES"
589
+ buildForArchiving = "YES"
590
+ buildForAnalyzing = "YES">
591
+ <BuildableReference
592
+ BuildableIdentifier = "primary"
593
+ BlueprintIdentifier = "3333333333333333333333AA"
594
+ BuildableName = "${APP_NAME}.app"
595
+ BlueprintName = "${APP_NAME}"
596
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
597
+ </BuildableReference>
598
+ </BuildActionEntry>
599
+ </BuildActionEntries>
600
+ </BuildAction>
601
+ <TestAction
602
+ buildConfiguration = "Debug"
603
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
604
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
605
+ shouldUseLaunchSchemeArgsEnv = "YES">
606
+ <Testables>
607
+ </Testables>
608
+ </TestAction>
609
+ <LaunchAction
610
+ buildConfiguration = "Debug"
611
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
612
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
613
+ launchStyle = "0"
614
+ useCustomWorkingDirectory = "NO"
615
+ ignoresPersistentStateOnLaunch = "NO"
616
+ debugDocumentVersioning = "YES"
617
+ debugServiceExtension = "internal"
618
+ allowLocationSimulation = "YES">
619
+ <BuildableProductRunnable
620
+ runnableDebuggingMode = "0">
621
+ <BuildableReference
622
+ BuildableIdentifier = "primary"
623
+ BlueprintIdentifier = "3333333333333333333333AA"
624
+ BuildableName = "${APP_NAME}.app"
625
+ BlueprintName = "${APP_NAME}"
626
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
627
+ </BuildableReference>
628
+ </BuildableProductRunnable>
629
+ </LaunchAction>
630
+ <ProfileAction
631
+ buildConfiguration = "Release"
632
+ shouldUseLaunchSchemeArgsEnv = "YES"
633
+ savedToolIdentifier = ""
634
+ useCustomWorkingDirectory = "NO"
635
+ debugDocumentVersioning = "YES">
636
+ <BuildableProductRunnable
637
+ runnableDebuggingMode = "0">
638
+ <BuildableReference
639
+ BuildableIdentifier = "primary"
640
+ BlueprintIdentifier = "3333333333333333333333AA"
641
+ BuildableName = "${APP_NAME}.app"
642
+ BlueprintName = "${APP_NAME}"
643
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
644
+ </BuildableReference>
645
+ </BuildableProductRunnable>
646
+ </ProfileAction>
647
+ <AnalyzeAction
648
+ buildConfiguration = "Debug">
649
+ </AnalyzeAction>
650
+ <ArchiveAction
651
+ buildConfiguration = "Release"
652
+ revealArchiveInOrganizer = "YES">
653
+ </ArchiveAction>
654
+ </Scheme>
655
+ EOF
656
+
657
+ # Now use xcodebuild with an explicitly defined product name for macOS
658
+ xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk macosx -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
659
+
660
+ # 4. Create a package for distribution
661
+ echo "Creating distributable package from archive..."
662
+ cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${APP_PATH}"
663
+
664
+ # Check and log app structure
665
+ echo "App structure:"
666
+ ls -la "${APP_PATH}"
667
+ echo "Frameworks:"
668
+ ls -la "${APP_PATH}/Contents/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
669
+
670
+ # Create a zip file for potential distribution
671
+ cd "${BUILD_DIR}"
672
+ zip -r "${ZIP_PATH}" "${APP_NAME}.app"
673
+
674
+ # Check embedded provisioning profile
675
+ echo "Checking provisioning profile (if any)..."
676
+ PROVISIONING_PROFILE=$(find "${APP_PATH}/Contents" -name "embedded.provisionprofile" 2>/dev/null)
677
+ if [ -n "$PROVISIONING_PROFILE" ]; then
678
+ echo "Found embedded provisioning profile:"
679
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
680
+ else
681
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
682
+ fi
683
+
684
+ # 5. Validate the app
685
+ echo "Validating macOS app..."
686
+ VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
687
+
688
+ # Check if authentication credentials are provided
689
+ AUTH_ARGS=""
690
+ if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
691
+ echo "Using Apple ID authentication for validation..."
692
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
693
+ else
694
+ echo "No authentication credentials provided. Will perform basic validation."
695
+ echo "To use your personal developer account, you can run the script with:"
696
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-macos.sh"
697
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
698
+ fi
699
+
700
+ # For macOS we need to use notarytool or alternative checks because altool doesn't support macOS apps in the same way
701
+ echo "Note: For macOS, formal notarization process would require Apple Developer credentials."
702
+ echo "Performing alternative validation checks..."
703
+
704
+ # Final validation result
705
+ FINAL_VALIDATION_RESULT=0
706
+
707
+ # Check if app was created successfully
708
+ if [ -d "${APP_PATH}" ] && [ -s "${APP_PATH}/Contents/MacOS/${APP_NAME}" ]; then
709
+ echo "✅ App package created successfully"
710
+ else
711
+ echo "❌ App package not created or binary missing"
712
+ FINAL_VALIDATION_RESULT=1
713
+ fi
714
+
715
+ # Check if app binary exists and is executable
716
+ if [ -f "${APP_PATH}/Contents/MacOS/${APP_NAME}" ] && [ -x "${APP_PATH}/Contents/MacOS/${APP_NAME}" ]; then
717
+ echo "✅ App binary exists and is executable"
718
+ else
719
+ echo "❌ App binary missing or not executable"
720
+ FINAL_VALIDATION_RESULT=1
721
+ fi
722
+
723
+ # Check if framework was properly embedded
724
+ if [ -d "${APP_PATH}/Contents/Frameworks/llama.framework" ]; then
725
+ echo "✅ llama.framework properly embedded"
726
+ else
727
+ echo "❌ llama.framework not properly embedded"
728
+ FINAL_VALIDATION_RESULT=1
729
+ fi
730
+
731
+ # Check if framework binary exists
732
+ if [ -f "${APP_PATH}/Contents/Frameworks/llama.framework/Versions/A/llama" ]; then
733
+ echo "✅ Framework binary exists"
734
+
735
+ # Further validate framework by checking architecture
736
+ ARCHS=$(lipo -info "${APP_PATH}/Contents/Frameworks/llama.framework/Versions/A/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ')
737
+ if [ -n "$ARCHS" ]; then
738
+ echo "✅ Framework architecture(s): $ARCHS"
739
+ else
740
+ echo "⚠️ Could not determine framework architecture"
741
+ fi
742
+ else
743
+ echo "❌ Framework binary missing"
744
+ FINAL_VALIDATION_RESULT=1
745
+ fi
746
+
747
+ # Check code signing
748
+ echo ""
749
+ echo "==== CODE SIGNING INFO ===="
750
+ codesign -vv -d "${APP_PATH}" 2>&1 || echo "Code signing verification not available (expected for ad-hoc builds)"
751
+
752
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
753
+ if [ -n "$AUTH_ARGS" ]; then
754
+ echo ""
755
+ echo "To notarize this app with Apple (requires Apple Developer account):"
756
+ echo "xcrun notarytool submit \"${ZIP_PATH}\" --apple-id \"your-apple-id\" --password \"your-app-specific-password\" --team-id \"your-team-id\" --wait"
757
+ echo ""
758
+ fi
759
+ echo "✅ Validation PASSED: macOS app built successfully with embedded framework"
760
+ else
761
+ echo "❌ Validation FAILED: Issues found with the app or framework"
762
+ fi
763
+
764
+ # Don't clean up on error to allow inspection
765
+ if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
766
+ echo ""
767
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
768
+ echo "===== macOS Validation Process Failed ====="
769
+ exit 1
770
+ fi
771
+
772
+ # Clean up temporary files but keep build artifacts
773
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
774
+ echo "Cleaning up temporary files..."
775
+ #rm -rf "${TEMP_DIR}"
776
+ fi
777
+
778
+ echo "===== macOS Validation Process Completed ====="
779
+ echo "App package available at: ${APP_PATH}"
780
+ echo "Zipped app available at: ${ZIP_PATH}"
781
+ exit $FINAL_VALIDATION_RESULT
backend/llama.cpp/scripts/apple/validate-tvos.sh ADDED
@@ -0,0 +1,813 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # validate-tvos.sh - Validate tvOS Application with embedded llama.xcframework using SwiftUI
3
+
4
+ # Authentication options (optional) (can be set via environment variables)
5
+ # To use: export APPLE_ID=your.email@example.com
6
+ # export APPLE_PASSWORD=your-app-specific-password
7
+ # ./validate-tvos.sh
8
+ APPLE_ID=${APPLE_ID:-""}
9
+ APPLE_PASSWORD=${APPLE_PASSWORD:-""}
10
+
11
+ # Ensure the script exits on error
12
+ set -e
13
+
14
+ # Function to print usage instructions
15
+ print_usage() {
16
+ echo "Usage: ./validate-tvos.sh [OPTIONS]"
17
+ echo ""
18
+ echo "Options:"
19
+ echo " --help Show this help message"
20
+ echo " --apple-id EMAIL Apple ID email for validation"
21
+ echo " --apple-password PWD App-specific password for Apple ID"
22
+ echo ""
23
+ echo "Environment variables:"
24
+ echo " APPLE_ID Apple ID email for validation"
25
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
26
+ echo ""
27
+ echo "Notes:"
28
+ echo " - Command line options take precedence over environment variables"
29
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
30
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
31
+ }
32
+
33
+ # Parse command line arguments
34
+ while [[ $# -gt 0 ]]; do
35
+ case $1 in
36
+ --help)
37
+ print_usage
38
+ exit 0
39
+ ;;
40
+ --apple-id)
41
+ APPLE_ID="$2"
42
+ shift 2
43
+ ;;
44
+ --apple-password)
45
+ APPLE_PASSWORD="$2"
46
+ shift 2
47
+ ;;
48
+ *)
49
+ echo "Unknown option: $1"
50
+ print_usage
51
+ exit 1
52
+ ;;
53
+ esac
54
+ done
55
+
56
+ # Function to clean up in case of error
57
+ cleanup() {
58
+ # Don't clean up temp files on error to help with debugging
59
+ echo "===== tvOS Validation Process Failed ====="
60
+ exit 1
61
+ }
62
+
63
+ # Set up trap to call cleanup function on error
64
+ trap cleanup ERR
65
+
66
+ set -e # Exit on any error
67
+
68
+ ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
69
+ BUILD_DIR="${ROOT_DIR}/validation-builds/ios"
70
+
71
+ # Configuration
72
+ APP_NAME="TVOSLlamaTest"
73
+ BUNDLE_ID="org.ggml.TVOSLlamaTest"
74
+ XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
75
+ TEMP_DIR="${BUILD_DIR}/temp"
76
+ ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
77
+ IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa"
78
+ VALIDATION_DIR="${BUILD_DIR}/validation"
79
+
80
+ # Create necessary directories
81
+ mkdir -p "${BUILD_DIR}"
82
+ mkdir -p "${TEMP_DIR}"
83
+ mkdir -p "${VALIDATION_DIR}"
84
+
85
+ echo "===== tvOS Validation Process Started ====="
86
+
87
+ # 1. Create a simple test app project
88
+ echo "Creating test tvOS app project..."
89
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
90
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF
91
+ <?xml version="1.0" encoding="UTF-8"?>
92
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
93
+ <plist version="1.0">
94
+ <dict>
95
+ <key>CFBundleDevelopmentRegion</key>
96
+ <string>en</string>
97
+ <key>CFBundleExecutable</key>
98
+ <string>${APP_NAME}</string>
99
+ <key>CFBundleIdentifier</key>
100
+ <string>${BUNDLE_ID}</string>
101
+ <key>CFBundleInfoDictionaryVersion</key>
102
+ <string>6.0</string>
103
+ <key>CFBundleName</key>
104
+ <string>${APP_NAME}</string>
105
+ <key>CFBundlePackageType</key>
106
+ <string>APPL</string>
107
+ <key>CFBundleShortVersionString</key>
108
+ <string>1.0</string>
109
+ <key>CFBundleVersion</key>
110
+ <string>1</string>
111
+ <key>UIRequiredDeviceCapabilities</key>
112
+ <array>
113
+ <string>arm64</string>
114
+ </array>
115
+ </dict>
116
+ </plist>
117
+ EOF
118
+
119
+ # Create SwiftUI app files
120
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
121
+
122
+ # Create App.swift
123
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
124
+ import SwiftUI
125
+ import llama
126
+
127
+ @main
128
+ struct LlamaTestApp: App {
129
+ var body: some Scene {
130
+ WindowGroup {
131
+ ContentView()
132
+ }
133
+ }
134
+ }
135
+ EOF
136
+
137
+ # Create ContentView.swift with tvOS specific elements
138
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
139
+ import SwiftUI
140
+ import llama
141
+
142
+ struct ContentView: View {
143
+ // Test that we can initialize a llama context params struct
144
+ let params = llama_context_default_params()
145
+
146
+ var body: some View {
147
+ VStack(spacing: 40) {
148
+ Text("Llama Framework Test on tvOS")
149
+ .font(.largeTitle)
150
+ .padding()
151
+
152
+ Text("llama_context_default_params() created successfully")
153
+ .font(.headline)
154
+ .multilineTextAlignment(.center)
155
+ .padding()
156
+
157
+ // Display some param values to confirm the framework is working
158
+ Text("n_ctx: \(params.n_ctx)")
159
+ .font(.title2)
160
+
161
+ Text("n_batch: \(params.n_batch)")
162
+ .font(.title2)
163
+
164
+ Spacer()
165
+ }
166
+ .padding(50)
167
+ // Larger size suitable for TV display
168
+ }
169
+ }
170
+
171
+ struct ContentView_Previews: PreviewProvider {
172
+ static var previews: some View {
173
+ ContentView()
174
+ }
175
+ }
176
+ EOF
177
+
178
+ # Create project.pbxproj, fixing the framework search paths issues
179
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
180
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
181
+ // !$*UTF8*$!
182
+ {
183
+ archiveVersion = 1;
184
+ classes = {
185
+ };
186
+ objectVersion = 54;
187
+ objects = {
188
+
189
+ /* Begin PBXBuildFile section */
190
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
191
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
192
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
193
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
194
+ /* End PBXBuildFile section */
195
+
196
+ /* Begin PBXCopyFilesBuildPhase section */
197
+ 88888888888888888888888 /* Embed Frameworks */ = {
198
+ isa = PBXCopyFilesBuildPhase;
199
+ buildActionMask = 2147483647;
200
+ dstPath = "";
201
+ dstSubfolderSpec = 10;
202
+ files = (
203
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
204
+ );
205
+ name = "Embed Frameworks";
206
+ runOnlyForDeploymentPostprocessing = 0;
207
+ };
208
+ /* End PBXCopyFilesBuildPhase section */
209
+
210
+ /* Begin PBXFileReference section */
211
+ EOF
212
+
213
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
214
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
215
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
216
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
217
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
218
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
219
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
220
+ /* End PBXFileReference section */
221
+ EOF
222
+
223
+ # Add the rest of the project file with fixed framework search paths
224
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
225
+ /* Begin PBXFrameworksBuildPhase section */
226
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
227
+ isa = PBXFrameworksBuildPhase;
228
+ buildActionMask = 2147483647;
229
+ files = (
230
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
231
+ );
232
+ runOnlyForDeploymentPostprocessing = 0;
233
+ };
234
+ /* End PBXFrameworksBuildPhase section */
235
+
236
+ /* Begin PBXGroup section */
237
+ EOF
238
+
239
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
240
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
241
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
242
+ isa = PBXGroup;
243
+ children = (
244
+ 99999999999999999999999 /* ${APP_NAME}.app */,
245
+ );
246
+ name = Products;
247
+ sourceTree = "<group>";
248
+ };
249
+ EOF
250
+
251
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
252
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
253
+ isa = PBXGroup;
254
+ children = (
255
+ 66666666666666666666666 /* llama.xcframework */,
256
+ );
257
+ name = Frameworks;
258
+ sourceTree = "<group>";
259
+ };
260
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
261
+ isa = PBXGroup;
262
+ children = (
263
+ FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSLlamaTest */,
264
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
265
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
266
+ );
267
+ sourceTree = "<group>";
268
+ };
269
+ FFFFFFFFFFFFFFFFFFFFFFFF /* TVOSLlamaTest */ = {
270
+ isa = PBXGroup;
271
+ children = (
272
+ 1111111111111111111111AA /* Sources */,
273
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
274
+ );
275
+ path = "TVOSLlamaTest";
276
+ sourceTree = "<group>";
277
+ };
278
+ 1111111111111111111111AA /* Sources */ = {
279
+ isa = PBXGroup;
280
+ children = (
281
+ 22222222222222222222222 /* App.swift */,
282
+ 44444444444444444444444 /* ContentView.swift */,
283
+ );
284
+ path = Sources;
285
+ sourceTree = "<group>";
286
+ };
287
+ /* End PBXGroup section */
288
+ EOF
289
+
290
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
291
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
292
+ /* Begin PBXNativeTarget section */
293
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
294
+ isa = PBXNativeTarget;
295
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
296
+ buildPhases = (
297
+ 5555555555555555555555AA /* Sources */,
298
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
299
+ 6666666666666666666666AA /* Resources */,
300
+ 88888888888888888888888 /* Embed Frameworks */,
301
+ );
302
+ buildRules = (
303
+ );
304
+ dependencies = (
305
+ );
306
+ name = "${APP_NAME}";
307
+ productName = "${APP_NAME}";
308
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
309
+ productType = "com.apple.product-type.application";
310
+ };
311
+ /* End PBXNativeTarget section */
312
+
313
+ /* Begin PBXProject section */
314
+ 7777777777777777777777AA /* Project object */ = {
315
+ isa = PBXProject;
316
+ attributes = {
317
+ LastSwiftUpdateCheck = 1240;
318
+ LastUpgradeCheck = 1240;
319
+ TargetAttributes = {
320
+ 3333333333333333333333AA = {
321
+ CreatedOnToolsVersion = 12.4;
322
+ };
323
+ };
324
+ };
325
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
326
+ compatibilityVersion = "Xcode 12.0";
327
+ developmentRegion = en;
328
+ hasScannedForEncodings = 0;
329
+ knownRegions = (
330
+ en,
331
+ Base,
332
+ );
333
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
334
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
335
+ projectDirPath = "";
336
+ projectRoot = "";
337
+ targets = (
338
+ 3333333333333333333333AA /* ${APP_NAME} */,
339
+ );
340
+ };
341
+ /* End PBXProject section */
342
+ EOF
343
+
344
+ # Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS and tvOS settings
345
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
346
+ /* Begin PBXResourcesBuildPhase section */
347
+ 6666666666666666666666AA /* Resources */ = {
348
+ isa = PBXResourcesBuildPhase;
349
+ buildActionMask = 2147483647;
350
+ files = (
351
+ );
352
+ runOnlyForDeploymentPostprocessing = 0;
353
+ };
354
+ /* End PBXResourcesBuildPhase section */
355
+
356
+ /* Begin PBXSourcesBuildPhase section */
357
+ 5555555555555555555555AA /* Sources */ = {
358
+ isa = PBXSourcesBuildPhase;
359
+ buildActionMask = 2147483647;
360
+ files = (
361
+ 33333333333333333333333 /* ContentView.swift in Sources */,
362
+ 11111111111111111111111 /* App.swift in Sources */,
363
+ );
364
+ runOnlyForDeploymentPostprocessing = 0;
365
+ };
366
+ /* End PBXSourcesBuildPhase section */
367
+
368
+ /* Begin XCBuildConfiguration section */
369
+ 9999999999999999999999AA /* Debug */ = {
370
+ isa = XCBuildConfiguration;
371
+ buildSettings = {
372
+ ALWAYS_SEARCH_USER_PATHS = NO;
373
+ CLANG_ANALYZER_NONNULL = YES;
374
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
375
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
376
+ CLANG_CXX_LIBRARY = "libc++";
377
+ CLANG_ENABLE_MODULES = YES;
378
+ CLANG_ENABLE_OBJC_ARC = YES;
379
+ CLANG_ENABLE_OBJC_WEAK = YES;
380
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
381
+ CLANG_WARN_BOOL_CONVERSION = YES;
382
+ CLANG_WARN_COMMA = YES;
383
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
384
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
385
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
386
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
387
+ CLANG_WARN_EMPTY_BODY = YES;
388
+ CLANG_WARN_ENUM_CONVERSION = YES;
389
+ CLANG_WARN_INFINITE_RECURSION = YES;
390
+ CLANG_WARN_INT_CONVERSION = YES;
391
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
392
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
393
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
394
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
395
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
396
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
397
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
398
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
399
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
400
+ CLANG_WARN_UNREACHABLE_CODE = YES;
401
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
402
+ COPY_PHASE_STRIP = NO;
403
+ DEBUG_INFORMATION_FORMAT = dwarf;
404
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
405
+ ENABLE_TESTABILITY = YES;
406
+ GCC_C_LANGUAGE_STANDARD = gnu11;
407
+ GCC_DYNAMIC_NO_PIC = NO;
408
+ GCC_NO_COMMON_BLOCKS = YES;
409
+ GCC_OPTIMIZATION_LEVEL = 0;
410
+ GCC_PREPROCESSOR_DEFINITIONS = (
411
+ "DEBUG=1",
412
+ "$(inherited)",
413
+ );
414
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
415
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
416
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
417
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
418
+ GCC_WARN_UNUSED_FUNCTION = YES;
419
+ GCC_WARN_UNUSED_VARIABLE = YES;
420
+ TVOS_DEPLOYMENT_TARGET = 15.0;
421
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
422
+ MTL_FAST_MATH = YES;
423
+ ONLY_ACTIVE_ARCH = YES;
424
+ SDKROOT = appletvos;
425
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
426
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
427
+ };
428
+ name = Debug;
429
+ };
430
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
431
+ isa = XCBuildConfiguration;
432
+ buildSettings = {
433
+ ALWAYS_SEARCH_USER_PATHS = NO;
434
+ CLANG_ANALYZER_NONNULL = YES;
435
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
436
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
437
+ CLANG_CXX_LIBRARY = "libc++";
438
+ CLANG_ENABLE_MODULES = YES;
439
+ CLANG_ENABLE_OBJC_ARC = YES;
440
+ CLANG_ENABLE_OBJC_WEAK = YES;
441
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
442
+ CLANG_WARN_BOOL_CONVERSION = YES;
443
+ CLANG_WARN_COMMA = YES;
444
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
445
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
446
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
447
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
448
+ CLANG_WARN_EMPTY_BODY = YES;
449
+ CLANG_WARN_ENUM_CONVERSION = YES;
450
+ CLANG_WARN_INFINITE_RECURSION = YES;
451
+ CLANG_WARN_INT_CONVERSION = YES;
452
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
453
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
454
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
455
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
456
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
457
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
458
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
459
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
460
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
461
+ CLANG_WARN_UNREACHABLE_CODE = YES;
462
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
463
+ COPY_PHASE_STRIP = NO;
464
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
465
+ ENABLE_NS_ASSERTIONS = NO;
466
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
467
+ GCC_C_LANGUAGE_STANDARD = gnu11;
468
+ GCC_NO_COMMON_BLOCKS = YES;
469
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
470
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
471
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
472
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
473
+ GCC_WARN_UNUSED_FUNCTION = YES;
474
+ GCC_WARN_UNUSED_VARIABLE = YES;
475
+ TVOS_DEPLOYMENT_TARGET = 15.0;
476
+ MTL_ENABLE_DEBUG_INFO = NO;
477
+ MTL_FAST_MATH = YES;
478
+ SDKROOT = appletvos;
479
+ SWIFT_COMPILATION_MODE = wholemodule;
480
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
481
+ VALIDATE_PRODUCT = YES;
482
+ };
483
+ name = Release;
484
+ };
485
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
486
+ isa = XCBuildConfiguration;
487
+ buildSettings = {
488
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
489
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
490
+ CODE_SIGN_STYLE = Manual;
491
+ DEVELOPMENT_TEAM = "";
492
+ ENABLE_PREVIEWS = YES;
493
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
494
+ INFOPLIST_FILE = "TVOSLlamaTest/Info.plist";
495
+ LD_RUNPATH_SEARCH_PATHS = (
496
+ "$(inherited)",
497
+ "@executable_path/Frameworks",
498
+ );
499
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSLlamaTest";
500
+ PRODUCT_NAME = "$(TARGET_NAME)";
501
+ PROVISIONING_PROFILE_SPECIFIER = "";
502
+ SWIFT_VERSION = 5.0;
503
+ TARGETED_DEVICE_FAMILY = 3;
504
+ };
505
+ name = Debug;
506
+ };
507
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
508
+ isa = XCBuildConfiguration;
509
+ buildSettings = {
510
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
511
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
512
+ CODE_SIGN_STYLE = Manual;
513
+ DEVELOPMENT_TEAM = "";
514
+ ENABLE_PREVIEWS = YES;
515
+ FRAMEWORK_SEARCH_PATHS = (
516
+ "$(inherited)",
517
+ "$(PROJECT_DIR)",
518
+ );
519
+ INFOPLIST_FILE = "TVOSLlamaTest/Info.plist";
520
+ LD_RUNPATH_SEARCH_PATHS = (
521
+ "$(inherited)",
522
+ "@executable_path/Frameworks",
523
+ );
524
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.TVOSLlamaTest";
525
+ PRODUCT_NAME = "$(TARGET_NAME)";
526
+ PROVISIONING_PROFILE_SPECIFIER = "";
527
+ SWIFT_VERSION = 5.0;
528
+ TARGETED_DEVICE_FAMILY = 3;
529
+ };
530
+ name = Release;
531
+ };
532
+ /* End XCBuildConfiguration section */
533
+ EOF
534
+
535
+ # Finish the project.pbxproj file
536
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
537
+ /* Begin XCConfigurationList section */
538
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
539
+ isa = XCConfigurationList;
540
+ buildConfigurations = (
541
+ 9999999999999999999999AA /* Debug */,
542
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
543
+ );
544
+ defaultConfigurationIsVisible = 0;
545
+ defaultConfigurationName = Release;
546
+ };
547
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
548
+ isa = XCConfigurationList;
549
+ buildConfigurations = (
550
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
551
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
552
+ );
553
+ defaultConfigurationIsVisible = 0;
554
+ defaultConfigurationName = Release;
555
+ };
556
+ /* End XCConfigurationList section */
557
+ };
558
+ rootObject = 7777777777777777777777AA /* Project object */;
559
+ }
560
+ EOF
561
+
562
+ # 2. Copy XCFramework to test project
563
+ echo "Copying XCFramework to test project..."
564
+ cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
565
+
566
+ # 3. Build and archive the app
567
+ echo "Building and archiving test app..."
568
+ cd "${TEMP_DIR}/${APP_NAME}"
569
+
570
+ # Create a simple xcscheme file to avoid xcodebuild scheme issues
571
+ mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
572
+ cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
573
+ <?xml version="1.0" encoding="UTF-8"?>
574
+ <Scheme
575
+ LastUpgradeVersion = "1240"
576
+ version = "1.3">
577
+ <BuildAction
578
+ parallelizeBuildables = "YES"
579
+ buildImplicitDependencies = "YES">
580
+ <BuildActionEntries>
581
+ <BuildActionEntry
582
+ buildForTesting = "YES"
583
+ buildForRunning = "YES"
584
+ buildForProfiling = "YES"
585
+ buildForArchiving = "YES"
586
+ buildForAnalyzing = "YES">
587
+ <BuildableReference
588
+ BuildableIdentifier = "primary"
589
+ BlueprintIdentifier = "3333333333333333333333AA"
590
+ BuildableName = "${APP_NAME}.app"
591
+ BlueprintName = "${APP_NAME}"
592
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
593
+ </BuildableReference>
594
+ </BuildActionEntry>
595
+ </BuildActionEntries>
596
+ </BuildAction>
597
+ <TestAction
598
+ buildConfiguration = "Debug"
599
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
600
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
601
+ shouldUseLaunchSchemeArgsEnv = "YES">
602
+ <Testables>
603
+ </Testables>
604
+ </TestAction>
605
+ <LaunchAction
606
+ buildConfiguration = "Debug"
607
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
608
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
609
+ launchStyle = "0"
610
+ useCustomWorkingDirectory = "NO"
611
+ ignoresPersistentStateOnLaunch = "NO"
612
+ debugDocumentVersioning = "YES"
613
+ debugServiceExtension = "internal"
614
+ allowLocationSimulation = "YES">
615
+ <BuildableProductRunnable
616
+ runnableDebuggingMode = "0">
617
+ <BuildableReference
618
+ BuildableIdentifier = "primary"
619
+ BlueprintIdentifier = "3333333333333333333333AA"
620
+ BuildableName = "${APP_NAME}.app"
621
+ BlueprintName = "${APP_NAME}"
622
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
623
+ </BuildableReference>
624
+ </BuildableProductRunnable>
625
+ </LaunchAction>
626
+ <ProfileAction
627
+ buildConfiguration = "Release"
628
+ shouldUseLaunchSchemeArgsEnv = "YES"
629
+ savedToolIdentifier = ""
630
+ useCustomWorkingDirectory = "NO"
631
+ debugDocumentVersioning = "YES">
632
+ <BuildableProductRunnable
633
+ runnableDebuggingMode = "0">
634
+ <BuildableReference
635
+ BuildableIdentifier = "primary"
636
+ BlueprintIdentifier = "3333333333333333333333AA"
637
+ BuildableName = "${APP_NAME}.app"
638
+ BlueprintName = "${APP_NAME}"
639
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
640
+ </BuildableReference>
641
+ </BuildableProductRunnable>
642
+ </ProfileAction>
643
+ <AnalyzeAction
644
+ buildConfiguration = "Debug">
645
+ </AnalyzeAction>
646
+ <ArchiveAction
647
+ buildConfiguration = "Release"
648
+ revealArchiveInOrganizer = "YES">
649
+ </ArchiveAction>
650
+ </Scheme>
651
+ EOF
652
+
653
+ # Now use xcodebuild with an explicitly defined product name for tvOS
654
+ xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk appletvos -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
655
+
656
+ # 4. Create IPA from archive
657
+ echo "Creating IPA from archive..."
658
+ mkdir -p "${TEMP_DIR}/Payload"
659
+ cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/"
660
+
661
+ # Check and log app structure before zipping
662
+ echo "App structure:"
663
+ ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/"
664
+ echo "Frameworks:"
665
+ ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
666
+
667
+ cd "${TEMP_DIR}"
668
+ zip -r "${IPA_PATH}" Payload
669
+
670
+ # Check embedded provisioning profile
671
+ echo "Checking provisioning profile (if any)..."
672
+ PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null)
673
+ if [ -n "$PROVISIONING_PROFILE" ]; then
674
+ echo "Found embedded provisioning profile:"
675
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
676
+ else
677
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
678
+ fi
679
+
680
+ # 5. Validate the IPA
681
+ echo "Validating IPA..."
682
+ VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
683
+
684
+ # Check if authentication credentials are provided
685
+ AUTH_ARGS=""
686
+ if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
687
+ echo "Using Apple ID authentication for validation..."
688
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
689
+ else
690
+ echo "No authentication credentials provided. Will perform basic validation."
691
+ echo "To use your personal developer account, you can run the script with:"
692
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-tvos.sh"
693
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
694
+ fi
695
+
696
+ # Run validation with detailed output
697
+ echo "Running validation with altool..."
698
+ if [ -n "$AUTH_ARGS" ]; then
699
+ # Use eval to properly handle the quoted arguments
700
+ eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type tvos --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}"
701
+ else
702
+ xcrun altool --validate-app -f "${IPA_PATH}" --type tvos --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}"
703
+ fi
704
+ VALIDATION_RESULT=$?
705
+
706
+ # Final validation result
707
+ FINAL_VALIDATION_RESULT=0
708
+
709
+ # Check if validation failed because the app isn't in App Store Connect
710
+ if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then
711
+ echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect"
712
+ echo "This is expected for apps that haven't been registered in App Store Connect yet."
713
+ echo "This doesn't indicate a problem with the build or framework."
714
+
715
+ # Perform alternative validation
716
+ echo "Performing alternative validation checks..."
717
+
718
+ # Check if IPA was created successfully
719
+ if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then
720
+ echo "✅ IPA file created successfully"
721
+ else
722
+ echo "❌ IPA file not created or empty"
723
+ FINAL_VALIDATION_RESULT=1
724
+ fi
725
+
726
+ # Check if app binary exists and is executable
727
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then
728
+ echo "✅ App binary exists and is executable"
729
+ else
730
+ echo "❌ App binary missing or not executable"
731
+ FINAL_VALIDATION_RESULT=1
732
+ fi
733
+
734
+ # Check if framework was properly embedded
735
+ if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then
736
+ echo "✅ llama.framework properly embedded"
737
+ else
738
+ echo "❌ llama.framework not properly embedded"
739
+ FINAL_VALIDATION_RESULT=1
740
+ fi
741
+
742
+ # Check if framework binary exists
743
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then
744
+ echo "✅ Framework binary exists"
745
+
746
+ # Further validate framework by checking architecture
747
+ ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ')
748
+ if [ -n "$ARCHS" ]; then
749
+ echo "✅ Framework architecture(s): $ARCHS"
750
+ else
751
+ echo "⚠️ Could not determine framework architecture"
752
+ fi
753
+ else
754
+ echo "❌ Framework binary missing"
755
+ FINAL_VALIDATION_RESULT=1
756
+ fi
757
+
758
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
759
+ echo "✅ Alternative validation PASSED: App built successfully with embedded framework"
760
+ else
761
+ echo "❌ Alternative validation FAILED: Issues found with the app or framework"
762
+ fi
763
+ elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then
764
+ echo "✅ tvOS Validation PASSED: IPA successfully validated"
765
+ echo "Results saved to ${VALIDATION_OUTPUT}"
766
+ else
767
+ echo "❌ tvOS Validation FAILED: IPA validation found issues"
768
+ echo "See validation output at ${VALIDATION_OUTPUT}"
769
+ echo ""
770
+ echo "==== VALIDATION ERRORS ===="
771
+
772
+ # Try to extract specific errors from the output
773
+ if grep -q "Error" "${VALIDATION_OUTPUT}"; then
774
+ grep -A 5 "Error" "${VALIDATION_OUTPUT}"
775
+ else
776
+ # If no specific error found, show the whole log
777
+ cat "${VALIDATION_OUTPUT}"
778
+ fi
779
+
780
+ # Additional debugging: check IPA contents
781
+ echo ""
782
+ echo "==== IPA CONTENTS ===="
783
+ mkdir -p "${TEMP_DIR}/ipa_contents"
784
+ unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents"
785
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/"
786
+
787
+ # Check for code signing issues
788
+ echo ""
789
+ echo "==== CODE SIGNING INFO ===="
790
+ codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed"
791
+
792
+ # Check embedded frameworks
793
+ echo ""
794
+ echo "==== FRAMEWORK INFO ===="
795
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
796
+ fi
797
+
798
+ # Don't clean up on error to allow inspection
799
+ if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
800
+ echo ""
801
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
802
+ echo "===== tvOS Validation Process Failed ====="
803
+ exit 1
804
+ fi
805
+
806
+ # Clean up temporary files but keep build artifacts
807
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
808
+ echo "Cleaning up temporary files..."
809
+ #rm -rf "${TEMP_DIR}"
810
+ fi
811
+
812
+ echo "===== tvOS Validation Process Completed ====="
813
+ exit $FINAL_VALIDATION_RESULT
backend/llama.cpp/scripts/apple/validate-visionos.sh ADDED
@@ -0,0 +1,811 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # validate-visionos.sh - Validate visionOS Application with embedded llama.xcframework using SwiftUI
3
+
4
+ # Authentication options (optional) (can be set via environment variables)
5
+ # To use: export APPLE_ID=your.email@example.com
6
+ # export APPLE_PASSWORD=your-app-specific-password
7
+ # ./validate-visionos.sh
8
+ APPLE_ID=${APPLE_ID:-""}
9
+ APPLE_PASSWORD=${APPLE_PASSWORD:-""}
10
+
11
+ # Ensure the script exits on error
12
+ set -e
13
+
14
+ # Function to print usage instructions
15
+ print_usage() {
16
+ echo "Usage: ./validate-visionos.sh [OPTIONS]"
17
+ echo ""
18
+ echo "Options:"
19
+ echo " --help Show this help message"
20
+ echo " --apple-id EMAIL Apple ID email for validation"
21
+ echo " --apple-password PWD App-specific password for Apple ID"
22
+ echo ""
23
+ echo "Environment variables:"
24
+ echo " APPLE_ID Apple ID email for validation"
25
+ echo " APPLE_PASSWORD App-specific password for Apple ID"
26
+ echo ""
27
+ echo "Notes:"
28
+ echo " - Command line options take precedence over environment variables"
29
+ echo " - Authentication is optional. If not provided, alternative validation will be performed"
30
+ echo " - For APPLE_PASSWORD, use an app-specific password generated at https://appleid.apple.com/account/manage"
31
+ }
32
+
33
+ # Parse command line arguments
34
+ while [[ $# -gt 0 ]]; do
35
+ case $1 in
36
+ --help)
37
+ print_usage
38
+ exit 0
39
+ ;;
40
+ --apple-id)
41
+ APPLE_ID="$2"
42
+ shift 2
43
+ ;;
44
+ --apple-password)
45
+ APPLE_PASSWORD="$2"
46
+ shift 2
47
+ ;;
48
+ *)
49
+ echo "Unknown option: $1"
50
+ print_usage
51
+ exit 1
52
+ ;;
53
+ esac
54
+ done
55
+
56
+ # Function to clean up in case of error
57
+ cleanup() {
58
+ # Don't clean up temp files on error to help with debugging
59
+ echo "===== visionOS Validation Process Failed ====="
60
+ exit 1
61
+ }
62
+
63
+ # Set up trap to call cleanup function on error
64
+ trap cleanup ERR
65
+
66
+ set -e # Exit on any error
67
+
68
+ ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )"
69
+ BUILD_DIR="${ROOT_DIR}/validation-builds/visionos"
70
+
71
+ # Configuration
72
+ APP_NAME="VisionOSLlamaTest"
73
+ BUNDLE_ID="org.ggml.VisionOSLlamaTest"
74
+ XCFRAMEWORK_PATH="${ROOT_DIR}/build-apple/llama.xcframework"
75
+ TEMP_DIR="${BUILD_DIR}/temp"
76
+ ARCHIVE_PATH="${BUILD_DIR}/${APP_NAME}.xcarchive"
77
+ IPA_PATH="${BUILD_DIR}/${APP_NAME}.ipa"
78
+ VALIDATION_DIR="${BUILD_DIR}/validation"
79
+
80
+ # Create necessary directories
81
+ mkdir -p "${BUILD_DIR}"
82
+ mkdir -p "${TEMP_DIR}"
83
+ mkdir -p "${VALIDATION_DIR}"
84
+
85
+ echo "===== visionOS Validation Process Started ====="
86
+
87
+ # 1. Create a simple test app project
88
+ echo "Creating test visionOS app project..."
89
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}"
90
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Info.plist" << EOF
91
+ <?xml version="1.0" encoding="UTF-8"?>
92
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
93
+ <plist version="1.0">
94
+ <dict>
95
+ <key>CFBundleDevelopmentRegion</key>
96
+ <string>en</string>
97
+ <key>CFBundleExecutable</key>
98
+ <string>${APP_NAME}</string>
99
+ <key>CFBundleIdentifier</key>
100
+ <string>${BUNDLE_ID}</string>
101
+ <key>CFBundleInfoDictionaryVersion</key>
102
+ <string>6.0</string>
103
+ <key>CFBundleName</key>
104
+ <string>${APP_NAME}</string>
105
+ <key>CFBundlePackageType</key>
106
+ <string>APPL</string>
107
+ <key>CFBundleShortVersionString</key>
108
+ <string>1.0</string>
109
+ <key>CFBundleVersion</key>
110
+ <string>1</string>
111
+ </dict>
112
+ </plist>
113
+ EOF
114
+
115
+ # Create SwiftUI app files
116
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources"
117
+
118
+ # Create App.swift
119
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/App.swift" << EOF
120
+ import SwiftUI
121
+ import llama
122
+
123
+ @main
124
+ struct LlamaTestApp: App {
125
+ var body: some Scene {
126
+ WindowGroup {
127
+ ContentView()
128
+ }
129
+ }
130
+ }
131
+ EOF
132
+
133
+ # Create ContentView.swift with visionOS specific elements
134
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}/Sources/ContentView.swift" << EOF
135
+ import SwiftUI
136
+ import llama
137
+
138
+ struct ContentView: View {
139
+ // Test that we can initialize a llama context params struct
140
+ let params = llama_context_default_params()
141
+
142
+ var body: some View {
143
+ VStack(spacing: 20) {
144
+ Text("Llama Framework Test on visionOS")
145
+ .font(.largeTitle)
146
+ .padding()
147
+
148
+ Text("llama_context_default_params() created successfully")
149
+ .font(.headline)
150
+ .multilineTextAlignment(.center)
151
+ .padding()
152
+
153
+ // Display some param values to confirm the framework is working
154
+ Text("n_ctx: \(params.n_ctx)")
155
+ .font(.body)
156
+
157
+ Text("n_batch: \(params.n_batch)")
158
+ .font(.body)
159
+
160
+ Spacer()
161
+ }
162
+ .padding()
163
+ .frame(width: 500, height: 400)
164
+ }
165
+ }
166
+
167
+ struct ContentView_Previews: PreviewProvider {
168
+ static var previews: some View {
169
+ ContentView()
170
+ }
171
+ }
172
+ EOF
173
+
174
+ # Create project.pbxproj, fixing the framework search paths issues
175
+ mkdir -p "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj"
176
+ cat > "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
177
+ // !$*UTF8*$!
178
+ {
179
+ archiveVersion = 1;
180
+ classes = {
181
+ };
182
+ objectVersion = 54;
183
+ objects = {
184
+
185
+ /* Begin PBXBuildFile section */
186
+ 11111111111111111111111 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22222222222222222222222; };
187
+ 33333333333333333333333 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44444444444444444444444; };
188
+ 55555555555555555555555 /* llama.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
189
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 66666666666666666666666; };
190
+ /* End PBXBuildFile section */
191
+
192
+ /* Begin PBXCopyFilesBuildPhase section */
193
+ 88888888888888888888888 /* Embed Frameworks */ = {
194
+ isa = PBXCopyFilesBuildPhase;
195
+ buildActionMask = 2147483647;
196
+ dstPath = "";
197
+ dstSubfolderSpec = 10;
198
+ files = (
199
+ 77777777777777777777777 /* llama.xcframework in Embed Frameworks */,
200
+ );
201
+ name = "Embed Frameworks";
202
+ runOnlyForDeploymentPostprocessing = 0;
203
+ };
204
+ /* End PBXCopyFilesBuildPhase section */
205
+
206
+ /* Begin PBXFileReference section */
207
+ EOF
208
+
209
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
210
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
211
+ 99999999999999999999999 /* ${APP_NAME}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "${APP_NAME}.app"; sourceTree = BUILT_PRODUCTS_DIR; };
212
+ 22222222222222222222222 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
213
+ 44444444444444444444444 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
214
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
215
+ 66666666666666666666666 /* llama.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = llama.xcframework; sourceTree = "<group>"; };
216
+ /* End PBXFileReference section */
217
+ EOF
218
+
219
+ # Add the rest of the project file with fixed framework search paths
220
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
221
+ /* Begin PBXFrameworksBuildPhase section */
222
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */ = {
223
+ isa = PBXFrameworksBuildPhase;
224
+ buildActionMask = 2147483647;
225
+ files = (
226
+ 55555555555555555555555 /* llama.xcframework in Frameworks */,
227
+ );
228
+ runOnlyForDeploymentPostprocessing = 0;
229
+ };
230
+ /* End PBXFrameworksBuildPhase section */
231
+
232
+ /* Begin PBXGroup section */
233
+ EOF
234
+
235
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
236
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
237
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */ = {
238
+ isa = PBXGroup;
239
+ children = (
240
+ 99999999999999999999999 /* ${APP_NAME}.app */,
241
+ );
242
+ name = Products;
243
+ sourceTree = "<group>";
244
+ };
245
+ EOF
246
+
247
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
248
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */ = {
249
+ isa = PBXGroup;
250
+ children = (
251
+ 66666666666666666666666 /* llama.xcframework */,
252
+ );
253
+ name = Frameworks;
254
+ sourceTree = "<group>";
255
+ };
256
+ EEEEEEEEEEEEEEEEEEEEEEEE = {
257
+ isa = PBXGroup;
258
+ children = (
259
+ FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSLlamaTest */,
260
+ CCCCCCCCCCCCCCCCCCCCCCCC /* Products */,
261
+ DDDDDDDDDDDDDDDDDDDDDDDD /* Frameworks */,
262
+ );
263
+ sourceTree = "<group>";
264
+ };
265
+ FFFFFFFFFFFFFFFFFFFFFFFF /* VisionOSLlamaTest */ = {
266
+ isa = PBXGroup;
267
+ children = (
268
+ 1111111111111111111111AA /* Sources */,
269
+ AAAAAAAAAAAAAAAAAAAAAAA /* Info.plist */,
270
+ );
271
+ path = "VisionOSLlamaTest";
272
+ sourceTree = "<group>";
273
+ };
274
+ 1111111111111111111111AA /* Sources */ = {
275
+ isa = PBXGroup;
276
+ children = (
277
+ 22222222222222222222222 /* App.swift */,
278
+ 44444444444444444444444 /* ContentView.swift */,
279
+ );
280
+ path = Sources;
281
+ sourceTree = "<group>";
282
+ };
283
+ /* End PBXGroup section */
284
+ EOF
285
+
286
+ # Continue with the project.pbxproj file, using the APP_NAME variable appropriately
287
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
288
+ /* Begin PBXNativeTarget section */
289
+ 3333333333333333333333AA /* ${APP_NAME} */ = {
290
+ isa = PBXNativeTarget;
291
+ buildConfigurationList = 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */;
292
+ buildPhases = (
293
+ 5555555555555555555555AA /* Sources */,
294
+ BBBBBBBBBBBBBBBBBBBBBBBB /* Frameworks */,
295
+ 6666666666666666666666AA /* Resources */,
296
+ 88888888888888888888888 /* Embed Frameworks */,
297
+ );
298
+ buildRules = (
299
+ );
300
+ dependencies = (
301
+ );
302
+ name = "${APP_NAME}";
303
+ productName = "${APP_NAME}";
304
+ productReference = 99999999999999999999999 /* ${APP_NAME}.app */;
305
+ productType = "com.apple.product-type.application";
306
+ };
307
+ /* End PBXNativeTarget section */
308
+
309
+ /* Begin PBXProject section */
310
+ 7777777777777777777777AA /* Project object */ = {
311
+ isa = PBXProject;
312
+ attributes = {
313
+ LastSwiftUpdateCheck = 1510;
314
+ LastUpgradeCheck = 1510;
315
+ TargetAttributes = {
316
+ 3333333333333333333333AA = {
317
+ CreatedOnToolsVersion = 15.1;
318
+ };
319
+ };
320
+ };
321
+ buildConfigurationList = 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */;
322
+ compatibilityVersion = "Xcode 15.0";
323
+ developmentRegion = en;
324
+ hasScannedForEncodings = 0;
325
+ knownRegions = (
326
+ en,
327
+ Base,
328
+ );
329
+ mainGroup = EEEEEEEEEEEEEEEEEEEEEEEE;
330
+ productRefGroup = CCCCCCCCCCCCCCCCCCCCCCCC /* Products */;
331
+ projectDirPath = "";
332
+ projectRoot = "";
333
+ targets = (
334
+ 3333333333333333333333AA /* ${APP_NAME} */,
335
+ );
336
+ };
337
+ /* End PBXProject section */
338
+ EOF
339
+
340
+ # Add the rest of the file with correct FRAMEWORK_SEARCH_PATHS
341
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << 'EOF'
342
+ /* Begin PBXResourcesBuildPhase section */
343
+ 6666666666666666666666AA /* Resources */ = {
344
+ isa = PBXResourcesBuildPhase;
345
+ buildActionMask = 2147483647;
346
+ files = (
347
+ );
348
+ runOnlyForDeploymentPostprocessing = 0;
349
+ };
350
+ /* End PBXResourcesBuildPhase section */
351
+
352
+ /* Begin PBXSourcesBuildPhase section */
353
+ 5555555555555555555555AA /* Sources */ = {
354
+ isa = PBXSourcesBuildPhase;
355
+ buildActionMask = 2147483647;
356
+ files = (
357
+ 33333333333333333333333 /* ContentView.swift in Sources */,
358
+ 11111111111111111111111 /* App.swift in Sources */,
359
+ );
360
+ runOnlyForDeploymentPostprocessing = 0;
361
+ };
362
+ /* End PBXSourcesBuildPhase section */
363
+
364
+ /* Begin XCBuildConfiguration section */
365
+ 9999999999999999999999AA /* Debug */ = {
366
+ isa = XCBuildConfiguration;
367
+ buildSettings = {
368
+ ALWAYS_SEARCH_USER_PATHS = NO;
369
+ CLANG_ANALYZER_NONNULL = YES;
370
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
371
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
372
+ CLANG_CXX_LIBRARY = "libc++";
373
+ CLANG_ENABLE_MODULES = YES;
374
+ CLANG_ENABLE_OBJC_ARC = YES;
375
+ CLANG_ENABLE_OBJC_WEAK = YES;
376
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
377
+ CLANG_WARN_BOOL_CONVERSION = YES;
378
+ CLANG_WARN_COMMA = YES;
379
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
380
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
381
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
382
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
383
+ CLANG_WARN_EMPTY_BODY = YES;
384
+ CLANG_WARN_ENUM_CONVERSION = YES;
385
+ CLANG_WARN_INFINITE_RECURSION = YES;
386
+ CLANG_WARN_INT_CONVERSION = YES;
387
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
388
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
389
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
390
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
391
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
392
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
393
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
394
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
395
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
396
+ CLANG_WARN_UNREACHABLE_CODE = YES;
397
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
398
+ COPY_PHASE_STRIP = NO;
399
+ DEBUG_INFORMATION_FORMAT = dwarf;
400
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
401
+ ENABLE_TESTABILITY = YES;
402
+ GCC_C_LANGUAGE_STANDARD = gnu11;
403
+ GCC_DYNAMIC_NO_PIC = NO;
404
+ GCC_NO_COMMON_BLOCKS = YES;
405
+ GCC_OPTIMIZATION_LEVEL = 0;
406
+ GCC_PREPROCESSOR_DEFINITIONS = (
407
+ "DEBUG=1",
408
+ "$(inherited)",
409
+ );
410
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
411
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
412
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
413
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
414
+ GCC_WARN_UNUSED_FUNCTION = YES;
415
+ GCC_WARN_UNUSED_VARIABLE = YES;
416
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
417
+ MTL_FAST_MATH = YES;
418
+ ONLY_ACTIVE_ARCH = YES;
419
+ SDKROOT = xros;
420
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
421
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
422
+ XROS_DEPLOYMENT_TARGET = 1.0;
423
+ };
424
+ name = Debug;
425
+ };
426
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */ = {
427
+ isa = XCBuildConfiguration;
428
+ buildSettings = {
429
+ ALWAYS_SEARCH_USER_PATHS = NO;
430
+ CLANG_ANALYZER_NONNULL = YES;
431
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
432
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
433
+ CLANG_CXX_LIBRARY = "libc++";
434
+ CLANG_ENABLE_MODULES = YES;
435
+ CLANG_ENABLE_OBJC_ARC = YES;
436
+ CLANG_ENABLE_OBJC_WEAK = YES;
437
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
438
+ CLANG_WARN_BOOL_CONVERSION = YES;
439
+ CLANG_WARN_COMMA = YES;
440
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
441
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
442
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
443
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
444
+ CLANG_WARN_EMPTY_BODY = YES;
445
+ CLANG_WARN_ENUM_CONVERSION = YES;
446
+ CLANG_WARN_INFINITE_RECURSION = YES;
447
+ CLANG_WARN_INT_CONVERSION = YES;
448
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
449
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
450
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
451
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
452
+ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
453
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
454
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
455
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
456
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
457
+ CLANG_WARN_UNREACHABLE_CODE = YES;
458
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
459
+ COPY_PHASE_STRIP = NO;
460
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
461
+ ENABLE_NS_ASSERTIONS = NO;
462
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
463
+ GCC_C_LANGUAGE_STANDARD = gnu11;
464
+ GCC_NO_COMMON_BLOCKS = YES;
465
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
466
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
467
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
468
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
469
+ GCC_WARN_UNUSED_FUNCTION = YES;
470
+ GCC_WARN_UNUSED_VARIABLE = YES;
471
+ MTL_ENABLE_DEBUG_INFO = NO;
472
+ MTL_FAST_MATH = YES;
473
+ SDKROOT = xros;
474
+ SWIFT_COMPILATION_MODE = wholemodule;
475
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
476
+ VALIDATE_PRODUCT = YES;
477
+ XROS_DEPLOYMENT_TARGET = 1.0;
478
+ };
479
+ name = Release;
480
+ };
481
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */ = {
482
+ isa = XCBuildConfiguration;
483
+ buildSettings = {
484
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
485
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
486
+ CODE_SIGN_STYLE = Manual;
487
+ DEVELOPMENT_TEAM = "";
488
+ ENABLE_PREVIEWS = YES;
489
+ FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)";
490
+ INFOPLIST_FILE = "VisionOSLlamaTest/Info.plist";
491
+ LD_RUNPATH_SEARCH_PATHS = (
492
+ "$(inherited)",
493
+ "@executable_path/Frameworks",
494
+ );
495
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSLlamaTest";
496
+ PRODUCT_NAME = "$(TARGET_NAME)";
497
+ PROVISIONING_PROFILE_SPECIFIER = "";
498
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
499
+ SWIFT_VERSION = 5.0;
500
+ TARGETED_DEVICE_FAMILY = "1,2,7";
501
+ };
502
+ name = Debug;
503
+ };
504
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */ = {
505
+ isa = XCBuildConfiguration;
506
+ buildSettings = {
507
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
508
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
509
+ CODE_SIGN_STYLE = Manual;
510
+ DEVELOPMENT_TEAM = "";
511
+ ENABLE_PREVIEWS = YES;
512
+ FRAMEWORK_SEARCH_PATHS = (
513
+ "$(inherited)",
514
+ "$(PROJECT_DIR)",
515
+ );
516
+ INFOPLIST_FILE = "VisionOSLlamaTest/Info.plist";
517
+ LD_RUNPATH_SEARCH_PATHS = (
518
+ "$(inherited)",
519
+ "@executable_path/Frameworks",
520
+ );
521
+ PRODUCT_BUNDLE_IDENTIFIER = "org.ggml.VisionOSLlamaTest";
522
+ PRODUCT_NAME = "$(TARGET_NAME)";
523
+ PROVISIONING_PROFILE_SPECIFIER = "";
524
+ SUPPORTED_PLATFORMS = "xros xrsimulator";
525
+ SWIFT_VERSION = 5.0;
526
+ TARGETED_DEVICE_FAMILY = "1,2,7";
527
+ };
528
+ name = Release;
529
+ };
530
+ /* End XCBuildConfiguration section */
531
+ EOF
532
+
533
+ # Finish the project.pbxproj file
534
+ cat >> "${TEMP_DIR}/${APP_NAME}/${APP_NAME}.xcodeproj/project.pbxproj" << EOF
535
+ /* Begin XCConfigurationList section */
536
+ 8888888888888888888888AA /* Build configuration list for PBXProject "${APP_NAME}" */ = {
537
+ isa = XCConfigurationList;
538
+ buildConfigurations = (
539
+ 9999999999999999999999AA /* Debug */,
540
+ AAAAAAAAAAAAAAAAAAAAABBB /* Release */,
541
+ );
542
+ defaultConfigurationIsVisible = 0;
543
+ defaultConfigurationName = Release;
544
+ };
545
+ 4444444444444444444444AA /* Build configuration list for PBXNativeTarget "${APP_NAME}" */ = {
546
+ isa = XCConfigurationList;
547
+ buildConfigurations = (
548
+ BBBBBBBBBBBBBBBBBBBBBBCCC /* Debug */,
549
+ CCCCCCCCCCCCCCCCCCCCCCDDD /* Release */,
550
+ );
551
+ defaultConfigurationIsVisible = 0;
552
+ defaultConfigurationName = Release;
553
+ };
554
+ /* End XCConfigurationList section */
555
+ };
556
+ rootObject = 7777777777777777777777AA /* Project object */;
557
+ }
558
+ EOF
559
+
560
+ # 2. Copy XCFramework to test project
561
+ echo "Copying XCFramework to test project..."
562
+ cp -R "${XCFRAMEWORK_PATH}" "${TEMP_DIR}/${APP_NAME}/"
563
+
564
+ # 3. Build and archive the app
565
+ echo "Building and archiving test app..."
566
+ cd "${TEMP_DIR}/${APP_NAME}"
567
+
568
+ # Create a simple xcscheme file to avoid xcodebuild scheme issues
569
+ mkdir -p "${APP_NAME}.xcodeproj/xcshareddata/xcschemes"
570
+ cat > "${APP_NAME}.xcodeproj/xcshareddata/xcschemes/${APP_NAME}.xcscheme" << EOF
571
+ <?xml version="1.0" encoding="UTF-8"?>
572
+ <Scheme
573
+ LastUpgradeVersion = "1510"
574
+ version = "1.3">
575
+ <BuildAction
576
+ parallelizeBuildables = "YES"
577
+ buildImplicitDependencies = "YES">
578
+ <BuildActionEntries>
579
+ <BuildActionEntry
580
+ buildForTesting = "YES"
581
+ buildForRunning = "YES"
582
+ buildForProfiling = "YES"
583
+ buildForArchiving = "YES"
584
+ buildForAnalyzing = "YES">
585
+ <BuildableReference
586
+ BuildableIdentifier = "primary"
587
+ BlueprintIdentifier = "3333333333333333333333AA"
588
+ BuildableName = "${APP_NAME}.app"
589
+ BlueprintName = "${APP_NAME}"
590
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
591
+ </BuildableReference>
592
+ </BuildActionEntry>
593
+ </BuildActionEntries>
594
+ </BuildAction>
595
+ <TestAction
596
+ buildConfiguration = "Debug"
597
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
598
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
599
+ shouldUseLaunchSchemeArgsEnv = "YES">
600
+ <Testables>
601
+ </Testables>
602
+ </TestAction>
603
+ <LaunchAction
604
+ buildConfiguration = "Debug"
605
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
606
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
607
+ launchStyle = "0"
608
+ useCustomWorkingDirectory = "NO"
609
+ ignoresPersistentStateOnLaunch = "NO"
610
+ debugDocumentVersioning = "YES"
611
+ debugServiceExtension = "internal"
612
+ allowLocationSimulation = "YES">
613
+ <BuildableProductRunnable
614
+ runnableDebuggingMode = "0">
615
+ <BuildableReference
616
+ BuildableIdentifier = "primary"
617
+ BlueprintIdentifier = "3333333333333333333333AA"
618
+ BuildableName = "${APP_NAME}.app"
619
+ BlueprintName = "${APP_NAME}"
620
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
621
+ </BuildableReference>
622
+ </BuildableProductRunnable>
623
+ </LaunchAction>
624
+ <ProfileAction
625
+ buildConfiguration = "Release"
626
+ shouldUseLaunchSchemeArgsEnv = "YES"
627
+ savedToolIdentifier = ""
628
+ useCustomWorkingDirectory = "NO"
629
+ debugDocumentVersioning = "YES">
630
+ <BuildableProductRunnable
631
+ runnableDebuggingMode = "0">
632
+ <BuildableReference
633
+ BuildableIdentifier = "primary"
634
+ BlueprintIdentifier = "3333333333333333333333AA"
635
+ BuildableName = "${APP_NAME}.app"
636
+ BlueprintName = "${APP_NAME}"
637
+ ReferencedContainer = "container:${APP_NAME}.xcodeproj">
638
+ </BuildableReference>
639
+ </BuildableProductRunnable>
640
+ </ProfileAction>
641
+ <AnalyzeAction
642
+ buildConfiguration = "Debug">
643
+ </AnalyzeAction>
644
+ <ArchiveAction
645
+ buildConfiguration = "Release"
646
+ revealArchiveInOrganizer = "YES">
647
+ </ArchiveAction>
648
+ </Scheme>
649
+ EOF
650
+
651
+ # Now use xcodebuild with an explicitly defined product name for visionOS
652
+ xcodebuild -project "${APP_NAME}.xcodeproj" -scheme "${APP_NAME}" -sdk xros -configuration Release archive -archivePath "${ARCHIVE_PATH}" CODE_SIGN_IDENTITY="-" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO PRODUCT_NAME="${APP_NAME}" SWIFT_OPTIMIZATION_LEVEL="-Onone" -quiet
653
+
654
+ # 4. Create IPA from archive
655
+ echo "Creating IPA from archive..."
656
+ mkdir -p "${TEMP_DIR}/Payload"
657
+ cp -R "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" "${TEMP_DIR}/Payload/"
658
+
659
+ # Check and log app structure before zipping
660
+ echo "App structure:"
661
+ ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/"
662
+ echo "Frameworks:"
663
+ ls -la "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
664
+
665
+ cd "${TEMP_DIR}"
666
+ zip -r "${IPA_PATH}" Payload
667
+
668
+ # Check embedded provisioning profile
669
+ echo "Checking provisioning profile (if any)..."
670
+ PROVISIONING_PROFILE=$(find "${ARCHIVE_PATH}/Products/Applications/${APP_NAME}.app" -name "embedded.mobileprovision" 2>/dev/null)
671
+ if [ -n "$PROVISIONING_PROFILE" ]; then
672
+ echo "Found embedded provisioning profile:"
673
+ security cms -D -i "$PROVISIONING_PROFILE" || echo "Unable to decode provisioning profile"
674
+ else
675
+ echo "No embedded provisioning profile found (expected for ad-hoc builds)"
676
+ fi
677
+
678
+ # 5. Validate the IPA
679
+ echo "Validating IPA..."
680
+ VALIDATION_OUTPUT="${VALIDATION_DIR}/validation_output.txt"
681
+
682
+ # Check if authentication credentials are provided
683
+ AUTH_ARGS=""
684
+ if [ -n "$APPLE_ID" ] && [ -n "$APPLE_PASSWORD" ]; then
685
+ echo "Using Apple ID authentication for validation..."
686
+ AUTH_ARGS="--username \"$APPLE_ID\" --password \"$APPLE_PASSWORD\""
687
+ else
688
+ echo "No authentication credentials provided. Will perform basic validation."
689
+ echo "To use your personal developer account, you can run the script with:"
690
+ echo " APPLE_ID='your.email@example.com' APPLE_PASSWORD='your-app-specific-password' ./validate-visionos.sh"
691
+ echo "Note: You need to create an app-specific password at https://appleid.apple.com/account/manage"
692
+ fi
693
+
694
+ # Run validation with detailed output
695
+ echo "Running validation with altool..."
696
+ if [ -n "$AUTH_ARGS" ]; then
697
+ # Use eval to properly handle the quoted arguments
698
+ eval "xcrun altool --validate-app -f \"${IPA_PATH}\" --type visionos --output-format xml $AUTH_ARGS" 2>&1 | tee "${VALIDATION_OUTPUT}"
699
+ else
700
+ xcrun altool --validate-app -f "${IPA_PATH}" --type visionos --output-format xml 2>&1 | tee "${VALIDATION_OUTPUT}"
701
+ fi
702
+ VALIDATION_RESULT=$?
703
+
704
+ # Final validation result
705
+ FINAL_VALIDATION_RESULT=0
706
+
707
+ # Check if validation failed because the app isn't in App Store Connect
708
+ if grep -q "No suitable application records were found" "${VALIDATION_OUTPUT}"; then
709
+ echo "⚠️ App Store Connect Warning: The app bundle identifier is not found in App Store Connect"
710
+ echo "This is expected for apps that haven't been registered in App Store Connect yet."
711
+ echo "This doesn't indicate a problem with the build or framework."
712
+
713
+ # Perform alternative validation
714
+ echo "Performing alternative validation checks..."
715
+
716
+ # Check if IPA was created successfully
717
+ if [ -f "${IPA_PATH}" ] && [ -s "${IPA_PATH}" ]; then
718
+ echo "✅ IPA file created successfully"
719
+ else
720
+ echo "❌ IPA file not created or empty"
721
+ FINAL_VALIDATION_RESULT=1
722
+ fi
723
+
724
+ # Check if app binary exists and is executable
725
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ] && [ -x "${TEMP_DIR}/Payload/${APP_NAME}.app/${APP_NAME}" ]; then
726
+ echo "✅ App binary exists and is executable"
727
+ else
728
+ echo "❌ App binary missing or not executable"
729
+ FINAL_VALIDATION_RESULT=1
730
+ fi
731
+
732
+ # Check if framework was properly embedded
733
+ if [ -d "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework" ]; then
734
+ echo "✅ llama.framework properly embedded"
735
+ else
736
+ echo "❌ llama.framework not properly embedded"
737
+ FINAL_VALIDATION_RESULT=1
738
+ fi
739
+
740
+ # Check if framework binary exists
741
+ if [ -f "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" ]; then
742
+ echo "✅ Framework binary exists"
743
+
744
+ # Further validate framework by checking architecture
745
+ ARCHS=$(lipo -info "${TEMP_DIR}/Payload/${APP_NAME}.app/Frameworks/llama.framework/llama" 2>/dev/null | grep -o "arm64\\|x86_64" | tr '\n' ' ')
746
+ if [ -n "$ARCHS" ]; then
747
+ echo "✅ Framework architecture(s): $ARCHS"
748
+ else
749
+ echo "⚠️ Could not determine framework architecture"
750
+ fi
751
+ else
752
+ echo "❌ Framework binary missing"
753
+ FINAL_VALIDATION_RESULT=1
754
+ fi
755
+
756
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
757
+ echo "✅ Alternative validation PASSED: App built successfully with embedded framework"
758
+ else
759
+ echo "❌ Alternative validation FAILED: Issues found with the app or framework"
760
+ fi
761
+ elif grep -q "You must specify authentication credentials" "${VALIDATION_OUTPUT}" && [ -z "$AUTH_ARGS" ]; then
762
+ echo "✅ visionOS Validation PASSED: IPA successfully validated"
763
+ echo "Results saved to ${VALIDATION_OUTPUT}"
764
+ else
765
+ echo "❌ visionOS Validation FAILED: IPA validation found issues"
766
+ echo "See validation output at ${VALIDATION_OUTPUT}"
767
+ echo ""
768
+ echo "==== VALIDATION ERRORS ===="
769
+
770
+ # Try to extract specific errors from the output
771
+ if grep -q "Error" "${VALIDATION_OUTPUT}"; then
772
+ grep -A 5 "Error" "${VALIDATION_OUTPUT}"
773
+ else
774
+ # If no specific error found, show the whole log
775
+ cat "${VALIDATION_OUTPUT}"
776
+ fi
777
+
778
+ # Additional debugging: check IPA contents
779
+ echo ""
780
+ echo "==== IPA CONTENTS ===="
781
+ mkdir -p "${TEMP_DIR}/ipa_contents"
782
+ unzip -q "${IPA_PATH}" -d "${TEMP_DIR}/ipa_contents"
783
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/"
784
+
785
+ # Check for code signing issues
786
+ echo ""
787
+ echo "==== CODE SIGNING INFO ===="
788
+ codesign -vv -d "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app" 2>&1 || echo "Code signing verification failed"
789
+
790
+ # Check embedded frameworks
791
+ echo ""
792
+ echo "==== FRAMEWORK INFO ===="
793
+ ls -la "${TEMP_DIR}/ipa_contents/Payload/${APP_NAME}.app/Frameworks/" 2>/dev/null || echo "No Frameworks directory found"
794
+ fi
795
+
796
+ # Don't clean up on error to allow inspection
797
+ if [ $FINAL_VALIDATION_RESULT -ne 0 ]; then
798
+ echo ""
799
+ echo "Temporary files kept for inspection at: ${TEMP_DIR}"
800
+ echo "===== visionOS Validation Process Failed ====="
801
+ exit 1
802
+ fi
803
+
804
+ # Clean up temporary files but keep build artifacts
805
+ if [ $FINAL_VALIDATION_RESULT -eq 0 ]; then
806
+ echo "Cleaning up temporary files..."
807
+ #rm -rf "${TEMP_DIR}"
808
+ fi
809
+
810
+ echo "===== visionOS Validation Process Completed ====="
811
+ exit $FINAL_VALIDATION_RESULT
backend/llama.cpp/scripts/bench-models.sh ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ RESULTS="bench-models-results.txt"
4
+ : > "$RESULTS"
5
+
6
+ ARGS_BB="-c 270336 -npp 512,4096,8192 -npl 1,2,4,8,16,32 -ntg 32"
7
+ ARGS_B="-d 0,4096,8192,16384,32768 -p 2048 -n 32"
8
+
9
+ QUICK=0
10
+ DIO=0
11
+ while (( "$#" )); do
12
+ case "$1" in
13
+ --quick) QUICK=1; shift ;;
14
+ --dio) DIO=1; shift ;;
15
+ *) shift ;;
16
+ esac
17
+ done
18
+
19
+ if (( QUICK )); then
20
+ ARGS_BB="-c 20480 -npp 512,4096 -npl 1,2,4 -ntg 32"
21
+ ARGS_B="-d 0 -p 2048 -n 32"
22
+ fi
23
+
24
+ if (( DIO )); then
25
+ ARGS_BB="${ARGS_BB} --no-mmap --direct-io"
26
+ ARGS_B="${ARGS_B} -mmp 0 -dio 1"
27
+ fi
28
+
29
+ run_model() {
30
+ local HFR=$1
31
+ local HFF=$2
32
+
33
+ printf "## ${HFR}\n" | tee -a "$RESULTS"
34
+ printf "\n" | tee -a "$RESULTS"
35
+ printf "Model: https://huggingface.co/${HFR}\n" | tee -a "$RESULTS"
36
+ printf "\n" | tee -a "$RESULTS"
37
+
38
+ printf -- "- \`llama-batched-bench\`\n" | tee -a "$RESULTS"
39
+ printf "\n" | tee -a "$RESULTS"
40
+
41
+ ./bin/llama-batched-bench \
42
+ -hfr "${HFR}" -hff "${HFF}" \
43
+ -m "${HFF}" -fa 1 -ub 2048 \
44
+ ${ARGS_BB} | tee -a "$RESULTS"
45
+
46
+ printf "\n" | tee -a "$RESULTS"
47
+
48
+ printf -- "- \`llama-bench\`\n" | tee -a "$RESULTS"
49
+ printf "\n" | tee -a "$RESULTS"
50
+
51
+ ./bin/llama-bench \
52
+ -m "${HFF}" -fa 1 -ub 2048 \
53
+ ${ARGS_B} | tee -a "$RESULTS"
54
+
55
+ printf "\n" | tee -a "$RESULTS"
56
+
57
+ printf "\n"
58
+ }
59
+
60
+ run_model "ggml-org/gpt-oss-20b-GGUF" "gpt-oss-20b-mxfp4.gguf"
61
+ run_model "ggml-org/gpt-oss-120b-GGUF" "gpt-oss-120b-mxfp4-00001-of-00003.gguf"
62
+ run_model "ggml-org/Qwen3-Coder-30B-A3B-Instruct-Q8_0-GGUF" "qwen3-coder-30b-a3b-instruct-q8_0.gguf"
63
+ run_model "ggml-org/Qwen2.5-Coder-7B-Q8_0-GGUF" "qwen2.5-coder-7b-q8_0.gguf"
64
+ run_model "ggml-org/gemma-3-4b-it-qat-GGUF" "gemma-3-4b-it-qat-Q4_0.gguf"
65
+ run_model "ggml-org/GLM-4.7-Flash-GGUF" "GLM-4.7-Flash-Q8_0.gguf"
66
+
67
+ if [[ -f models-extra.txt ]]; then
68
+ while read -r HFR HFF; do
69
+ [[ -z "$HFR" ]] && continue
70
+ run_model "$HFR" "$HFF"
71
+ done < models-extra.txt
72
+ fi
73
+
74
+ printf "\n=====================================\n"
75
+ printf "\n"
76
+
77
+ cat "$RESULTS"
78
+
79
+ printf "\n"
80
+ printf "Done! Results are written to $RESULTS\n"
81
+ printf "\n"
82
+
backend/llama.cpp/scripts/build-info.sh ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ CC=$1
4
+
5
+ build_number="0"
6
+ build_commit="unknown"
7
+ build_compiler="unknown"
8
+ build_target="unknown"
9
+
10
+ if out=$(git rev-list --count HEAD); then
11
+ # git is broken on WSL so we need to strip extra newlines
12
+ build_number=$(printf '%s' "$out" | tr -d '\n')
13
+ fi
14
+
15
+ if out=$(git rev-parse --short HEAD); then
16
+ build_commit=$(printf '%s' "$out" | tr -d '\n')
17
+ fi
18
+
19
+ if out=$($CC --version | head -1); then
20
+ build_compiler=$out
21
+ fi
22
+
23
+ if out=$($CC -dumpmachine); then
24
+ build_target=$out
25
+ fi
26
+
27
+ echo "int LLAMA_BUILD_NUMBER = ${build_number};"
28
+ echo "char const *LLAMA_COMMIT = \"${build_commit}\";"
29
+ echo "char const *LLAMA_COMPILER = \"${build_compiler}\";"
30
+ echo "char const *LLAMA_BUILD_TARGET = \"${build_target}\";"
backend/llama.cpp/scripts/check-requirements.sh ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ #
5
+ # check-requirements.sh checks all requirements files for each top-level
6
+ # convert*.py script.
7
+ #
8
+ # WARNING: This is quite IO intensive, because a fresh venv is set up for every
9
+ # python script. As of 2023-12-22, this writes ~2.7GB of data. An adequately
10
+ # sized tmpfs /tmp or ramdisk is recommended if running this frequently.
11
+ #
12
+ # usage: check-requirements.sh [<working_dir>]
13
+ # check-requirements.sh nocleanup [<working_dir>]
14
+ #
15
+ # where:
16
+ # - <working_dir> is a directory that can be used as the base for
17
+ # setting up the venvs. Defaults to `/tmp`.
18
+ # - 'nocleanup' as the first argument will disable automatic cleanup
19
+ # of the files created by this script.
20
+ #
21
+ # requires:
22
+ # - bash >= 3.2.57
23
+ # - shellcheck
24
+ #
25
+ # For each script, it creates a fresh venv, `pip install`s the requirements, and
26
+ # finally imports the python script to check for `ImportError`.
27
+ #
28
+
29
+ log() {
30
+ local level=$1 msg=$2
31
+ printf >&2 '%s: %s\n' "$level" "$msg"
32
+ }
33
+
34
+ debug() {
35
+ log DEBUG "$@"
36
+ }
37
+
38
+ info() {
39
+ log INFO "$@"
40
+ }
41
+
42
+ fatal() {
43
+ log FATAL "$@"
44
+ exit 1
45
+ }
46
+
47
+ cleanup() {
48
+ if [[ -n ${workdir+x} && -d $workdir && -w $workdir ]]; then
49
+ info "Removing $workdir"
50
+ local count=0
51
+ rm -rfv -- "$workdir" | while read -r; do
52
+ if (( count++ > 750 )); then
53
+ printf .
54
+ count=0
55
+ fi
56
+ done
57
+ printf '\n'
58
+ info "Removed $workdir"
59
+ fi
60
+ }
61
+
62
+ do_cleanup=1
63
+ if [[ ${1-} == nocleanup ]]; then
64
+ do_cleanup=0; shift
65
+ fi
66
+
67
+ if (( do_cleanup )); then
68
+ trap exit INT TERM
69
+ trap cleanup EXIT
70
+ fi
71
+
72
+ this=$(realpath -- "$0"); readonly this
73
+ cd "$(dirname "$this")/.." # PWD should stay in llama.cpp project directory
74
+
75
+ shellcheck "$this"
76
+
77
+ readonly reqs_dir=requirements
78
+
79
+ if [[ ${1+x} ]]; then
80
+ tmp_dir=$(realpath -- "$1")
81
+ if [[ ! ( -d $tmp_dir && -w $tmp_dir ) ]]; then
82
+ fatal "$tmp_dir is not a writable directory"
83
+ fi
84
+ else
85
+ tmp_dir=/tmp
86
+ fi
87
+
88
+ workdir=$(mktemp -d "$tmp_dir/check-requirements.XXXX"); readonly workdir
89
+ info "Working directory: $workdir"
90
+
91
+ check_requirements() {
92
+ local reqs=$1
93
+
94
+ info "$reqs: beginning check"
95
+ pip --disable-pip-version-check install -qr "$reqs"
96
+ info "$reqs: OK"
97
+ }
98
+
99
+ check_convert_script() {
100
+ local py=$1 # e.g. ./convert_hf_to_gguf.py
101
+ local pyname=${py##*/} # e.g. convert_hf_to_gguf.py
102
+ pyname=${pyname%.py} # e.g. convert_hf_to_gguf
103
+
104
+ info "$py: beginning check"
105
+
106
+ local reqs="$reqs_dir/requirements-$pyname.txt"
107
+ if [[ ! -r $reqs ]]; then
108
+ fatal "$py missing requirements. Expected: $reqs"
109
+ fi
110
+
111
+ # Check that all sub-requirements are added to top-level requirements.txt
112
+ if ! grep -qF "$reqs" requirements.txt; then
113
+ fatal "$reqs needs to be added to requirements.txt"
114
+ fi
115
+
116
+ local venv="$workdir/$pyname-venv"
117
+ python3 -m venv "$venv"
118
+
119
+ (
120
+ # shellcheck source=/dev/null
121
+ source "$venv/bin/activate"
122
+
123
+ check_requirements "$reqs"
124
+
125
+ python - "$py" "$pyname" <<'EOF'
126
+ import sys
127
+ from importlib.machinery import SourceFileLoader
128
+ py, pyname = sys.argv[1:]
129
+ SourceFileLoader(pyname, py).load_module()
130
+ EOF
131
+ )
132
+
133
+ if (( do_cleanup )); then
134
+ rm -rf -- "$venv"
135
+ fi
136
+
137
+ info "$py: imports OK"
138
+ }
139
+
140
+ readonly ignore_eq_eq='check_requirements: ignore "=="'
141
+
142
+ for req in */**/requirements*.txt; do
143
+ # Make sure exact release versions aren't being pinned in the requirements
144
+ # Filters out the ignore string
145
+ if grep -vF "$ignore_eq_eq" "$req" | grep -q '=='; then
146
+ tab=$'\t'
147
+ cat >&2 <<EOF
148
+ FATAL: Avoid pinning exact package versions. Use '~=' instead.
149
+ You can suppress this error by appending the following to the line:
150
+ $tab# $ignore_eq_eq
151
+ EOF
152
+ exit 1
153
+ fi
154
+ done
155
+
156
+ all_venv="$workdir/all-venv"
157
+ python3 -m venv "$all_venv"
158
+
159
+ (
160
+ # shellcheck source=/dev/null
161
+ source "$all_venv/bin/activate"
162
+ check_requirements requirements.txt
163
+ )
164
+
165
+ if (( do_cleanup )); then
166
+ rm -rf -- "$all_venv"
167
+ fi
168
+
169
+ check_convert_script examples/convert_legacy_llama.py
170
+ for py in convert_*.py; do
171
+ # skip convert_hf_to_gguf_update.py
172
+ # TODO: the check is failing for some reason:
173
+ # https://github.com/ggml-org/llama.cpp/actions/runs/8875330981/job/24364557177?pr=6920
174
+ [[ $py == convert_hf_to_gguf_update.py ]] && continue
175
+
176
+ check_convert_script "$py"
177
+ done
178
+
179
+ info 'Done! No issues found.'
backend/llama.cpp/scripts/compare-commits.sh ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+
3
+ if [ $# -lt 2 ]; then
4
+ echo "usage: ./scripts/compare-commits.sh <commit1> <commit2> [tool] [additional arguments]"
5
+ echo " tool: 'llama-bench' (default) or 'test-backend-ops'"
6
+ echo " additional arguments: passed to the selected tool"
7
+ exit 1
8
+ fi
9
+
10
+ set -e
11
+ set -x
12
+
13
+ # Parse arguments
14
+ commit1=$1
15
+ commit2=$2
16
+ tool=${3:-llama-bench}
17
+ additional_args="${@:4}"
18
+
19
+ # Validate tool argument
20
+ if [ "$tool" != "llama-bench" ] && [ "$tool" != "test-backend-ops" ]; then
21
+ echo "Error: tool must be 'llama-bench' or 'test-backend-ops'"
22
+ exit 1
23
+ fi
24
+
25
+ # verify at the start that the compare script has all the necessary dependencies installed
26
+ ./scripts/compare-llama-bench.py --check
27
+
28
+ if ! command -v sqlite3 >/dev/null 2>&1; then
29
+ echo "Error: sqlite3 is not installed or not in PATH"
30
+ echo "Please install sqlite3 to use this script"
31
+ exit 1
32
+ fi
33
+
34
+ if [ "$tool" = "llama-bench" ]; then
35
+ db_file="llama-bench.sqlite"
36
+ target="llama-bench"
37
+ run_args="-o sql -oe md $additional_args"
38
+ else # test-backend-ops
39
+ db_file="test-backend-ops.sqlite"
40
+ target="test-backend-ops"
41
+ run_args="perf --output sql $additional_args"
42
+ fi
43
+
44
+ rm -f "$db_file" > /dev/null
45
+
46
+ # to test a backend, call the script with the corresponding environment variable (e.g. GGML_CUDA=1 ./scripts/compare-commits.sh ...)
47
+ if [ -n "$GGML_CUDA" ]; then
48
+ CMAKE_OPTS="${CMAKE_OPTS} -DGGML_CUDA=ON"
49
+ fi
50
+
51
+ dir="build-bench"
52
+
53
+ function run {
54
+ rm -fr ${dir} > /dev/null
55
+ cmake -B ${dir} -S . ${CMAKE_OPTS} > /dev/null
56
+ cmake --build ${dir} -t $target -j $(nproc) > /dev/null
57
+ ${dir}/bin/$target $run_args | sqlite3 "$db_file"
58
+ }
59
+
60
+ git checkout $commit1 > /dev/null
61
+ run
62
+
63
+ git checkout $commit2 > /dev/null
64
+ run
65
+
66
+ ./scripts/compare-llama-bench.py -b $commit1 -c $commit2 --tool $tool -i "$db_file"