llama-cpp-pro 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (310) hide show
  1. package/CHANGELOG.md +295 -0
  2. package/LICENSE +21 -0
  3. package/LlamaCpp.podspec +33 -0
  4. package/LlamaCppCapacitor.podspec +33 -0
  5. package/Package.swift +29 -0
  6. package/README.md +93 -0
  7. package/android/build.gradle +88 -0
  8. package/android/src/main/AndroidManifest.xml +4 -0
  9. package/android/src/main/CMakeLists-arm64.txt +138 -0
  10. package/android/src/main/CMakeLists-x86_64.txt +141 -0
  11. package/android/src/main/CMakeLists.txt +138 -0
  12. package/android/src/main/java/ai/annadata/plugin/capacitor/LlamaCpp.java +1340 -0
  13. package/android/src/main/java/ai/annadata/plugin/capacitor/LlamaCppPlugin.java +814 -0
  14. package/android/src/main/java/ai/annadata/plugin/capacitor/ModelAdmissionController.java +214 -0
  15. package/android/src/main/jni-chat-session.cpp +261 -0
  16. package/android/src/main/jni-lora.cpp +197 -0
  17. package/android/src/main/jni-multimodal.cpp +167 -0
  18. package/android/src/main/jni-tts.cpp +290 -0
  19. package/android/src/main/jni-utils.h +148 -0
  20. package/android/src/main/jni.cpp +1808 -0
  21. package/android/src/main/jniLibs/arm64-v8a/libllama-cpp-arm64.so +0 -0
  22. package/android/src/main/res/.gitkeep +0 -0
  23. package/build-native.sh +280 -0
  24. package/cmake/desktop-metal-embed.cmake +30 -0
  25. package/cmake/desktop-sources.cmake +100 -0
  26. package/cmake/ggml-backends.cmake +44 -0
  27. package/cpp/LICENSE +21 -0
  28. package/cpp/README.md +15 -0
  29. package/cpp/anyascii.c +22223 -0
  30. package/cpp/anyascii.h +42 -0
  31. package/cpp/cap-completion.cpp +942 -0
  32. package/cpp/cap-completion.h +127 -0
  33. package/cpp/cap-embedding.cpp +193 -0
  34. package/cpp/cap-embedding.h +35 -0
  35. package/cpp/cap-ios-bridge.cpp +1810 -0
  36. package/cpp/cap-ios-bridge.h +61 -0
  37. package/cpp/cap-llama.cpp +412 -0
  38. package/cpp/cap-llama.h +161 -0
  39. package/cpp/cap-mtmd.hpp +602 -0
  40. package/cpp/cap-native-server.cpp +1095 -0
  41. package/cpp/cap-native-server.h +40 -0
  42. package/cpp/cap-tts.cpp +591 -0
  43. package/cpp/cap-tts.h +59 -0
  44. package/cpp/cap-wasm-fs.cpp +156 -0
  45. package/cpp/cap-wasm-jspi.cpp +19 -0
  46. package/cpp/cap-wasm-jspi.h +30 -0
  47. package/cpp/cap-wasm-vfs.cpp +22 -0
  48. package/cpp/chat-parser.cpp +393 -0
  49. package/cpp/chat-parser.h +120 -0
  50. package/cpp/chat.cpp +2315 -0
  51. package/cpp/chat.h +221 -0
  52. package/cpp/common.cpp +1664 -0
  53. package/cpp/common.h +744 -0
  54. package/cpp/ggml-alloc.c +1028 -0
  55. package/cpp/ggml-alloc.h +76 -0
  56. package/cpp/ggml-backend-impl.h +255 -0
  57. package/cpp/ggml-backend-reg.cpp +600 -0
  58. package/cpp/ggml-backend.cpp +2121 -0
  59. package/cpp/ggml-backend.h +354 -0
  60. package/cpp/ggml-common.h +1878 -0
  61. package/cpp/ggml-cpp.h +39 -0
  62. package/cpp/ggml-cpu/amx/amx.cpp +221 -0
  63. package/cpp/ggml-cpu/amx/amx.h +8 -0
  64. package/cpp/ggml-cpu/amx/common.h +91 -0
  65. package/cpp/ggml-cpu/amx/mmq.cpp +2512 -0
  66. package/cpp/ggml-cpu/amx/mmq.h +10 -0
  67. package/cpp/ggml-cpu/arch/arm/cpu-feats.cpp +94 -0
  68. package/cpp/ggml-cpu/arch/arm/quants.c +3650 -0
  69. package/cpp/ggml-cpu/arch/arm/repack.cpp +1891 -0
  70. package/cpp/ggml-cpu/arch/x86/cpu-feats.cpp +327 -0
  71. package/cpp/ggml-cpu/arch/x86/quants.c +3820 -0
  72. package/cpp/ggml-cpu/arch/x86/repack.cpp +6307 -0
  73. package/cpp/ggml-cpu/arch-fallback.h +215 -0
  74. package/cpp/ggml-cpu/binary-ops.cpp +158 -0
  75. package/cpp/ggml-cpu/binary-ops.h +16 -0
  76. package/cpp/ggml-cpu/common.h +73 -0
  77. package/cpp/ggml-cpu/ggml-cpu-impl.h +559 -0
  78. package/cpp/ggml-cpu/ggml-cpu.c +3578 -0
  79. package/cpp/ggml-cpu/ggml-cpu.cpp +672 -0
  80. package/cpp/ggml-cpu/ops.cpp +10587 -0
  81. package/cpp/ggml-cpu/ops.h +114 -0
  82. package/cpp/ggml-cpu/quants.c +1193 -0
  83. package/cpp/ggml-cpu/quants.h +97 -0
  84. package/cpp/ggml-cpu/repack.cpp +1982 -0
  85. package/cpp/ggml-cpu/repack.h +120 -0
  86. package/cpp/ggml-cpu/simd-mappings.h +1184 -0
  87. package/cpp/ggml-cpu/traits.cpp +36 -0
  88. package/cpp/ggml-cpu/traits.h +38 -0
  89. package/cpp/ggml-cpu/unary-ops.cpp +186 -0
  90. package/cpp/ggml-cpu/unary-ops.h +28 -0
  91. package/cpp/ggml-cpu/vec.cpp +348 -0
  92. package/cpp/ggml-cpu/vec.h +1121 -0
  93. package/cpp/ggml-cpu.h +145 -0
  94. package/cpp/ggml-impl.h +622 -0
  95. package/cpp/ggml-metal-impl.h +688 -0
  96. package/cpp/ggml-metal.h +66 -0
  97. package/cpp/ggml-metal.m +6833 -0
  98. package/cpp/ggml-metal.metal +10754 -0
  99. package/cpp/ggml-opt.cpp +1093 -0
  100. package/cpp/ggml-opt.h +256 -0
  101. package/cpp/ggml-quants.c +5324 -0
  102. package/cpp/ggml-quants.h +106 -0
  103. package/cpp/ggml-threading.cpp +12 -0
  104. package/cpp/ggml-threading.h +14 -0
  105. package/cpp/ggml.c +7108 -0
  106. package/cpp/ggml.h +2492 -0
  107. package/cpp/gguf.cpp +1358 -0
  108. package/cpp/gguf.h +202 -0
  109. package/cpp/json-partial.cpp +256 -0
  110. package/cpp/json-partial.h +38 -0
  111. package/cpp/json-schema-to-grammar.cpp +985 -0
  112. package/cpp/json-schema-to-grammar.h +21 -0
  113. package/cpp/llama-adapter.cpp +388 -0
  114. package/cpp/llama-adapter.h +76 -0
  115. package/cpp/llama-arch.cpp +2355 -0
  116. package/cpp/llama-arch.h +499 -0
  117. package/cpp/llama-batch.cpp +875 -0
  118. package/cpp/llama-batch.h +160 -0
  119. package/cpp/llama-chat.cpp +783 -0
  120. package/cpp/llama-chat.h +65 -0
  121. package/cpp/llama-context.cpp +2788 -0
  122. package/cpp/llama-context.h +306 -0
  123. package/cpp/llama-cparams.cpp +5 -0
  124. package/cpp/llama-cparams.h +41 -0
  125. package/cpp/llama-cpp.h +30 -0
  126. package/cpp/llama-grammar.cpp +1229 -0
  127. package/cpp/llama-grammar.h +173 -0
  128. package/cpp/llama-graph.cpp +1891 -0
  129. package/cpp/llama-graph.h +810 -0
  130. package/cpp/llama-hparams.cpp +180 -0
  131. package/cpp/llama-hparams.h +233 -0
  132. package/cpp/llama-impl.cpp +167 -0
  133. package/cpp/llama-impl.h +61 -0
  134. package/cpp/llama-io.cpp +15 -0
  135. package/cpp/llama-io.h +35 -0
  136. package/cpp/llama-kv-cache-iswa.cpp +318 -0
  137. package/cpp/llama-kv-cache-iswa.h +135 -0
  138. package/cpp/llama-kv-cache.cpp +2059 -0
  139. package/cpp/llama-kv-cache.h +374 -0
  140. package/cpp/llama-kv-cells.h +491 -0
  141. package/cpp/llama-memory-hybrid.cpp +258 -0
  142. package/cpp/llama-memory-hybrid.h +137 -0
  143. package/cpp/llama-memory-recurrent.cpp +1146 -0
  144. package/cpp/llama-memory-recurrent.h +179 -0
  145. package/cpp/llama-memory.cpp +59 -0
  146. package/cpp/llama-memory.h +119 -0
  147. package/cpp/llama-mmap.cpp +609 -0
  148. package/cpp/llama-mmap.h +68 -0
  149. package/cpp/llama-model-loader.cpp +1166 -0
  150. package/cpp/llama-model-loader.h +170 -0
  151. package/cpp/llama-model-saver.cpp +282 -0
  152. package/cpp/llama-model-saver.h +37 -0
  153. package/cpp/llama-model.cpp +19061 -0
  154. package/cpp/llama-model.h +491 -0
  155. package/cpp/llama-sampling.cpp +2575 -0
  156. package/cpp/llama-sampling.h +32 -0
  157. package/cpp/llama-vocab.cpp +3792 -0
  158. package/cpp/llama-vocab.h +176 -0
  159. package/cpp/llama.cpp +358 -0
  160. package/cpp/llama.h +1373 -0
  161. package/cpp/log.cpp +428 -0
  162. package/cpp/log.h +103 -0
  163. package/cpp/minja/chat-template.hpp +550 -0
  164. package/cpp/minja/minja.hpp +3009 -0
  165. package/cpp/nlohmann/json.hpp +25526 -0
  166. package/cpp/nlohmann/json_fwd.hpp +187 -0
  167. package/cpp/regex-partial.cpp +204 -0
  168. package/cpp/regex-partial.h +56 -0
  169. package/cpp/sampling.cpp +579 -0
  170. package/cpp/sampling.h +107 -0
  171. package/cpp/tools/mtmd/clip-impl.h +473 -0
  172. package/cpp/tools/mtmd/clip.cpp +4322 -0
  173. package/cpp/tools/mtmd/clip.h +106 -0
  174. package/cpp/tools/mtmd/miniaudio/miniaudio.h +93468 -0
  175. package/cpp/tools/mtmd/mtmd-audio.cpp +769 -0
  176. package/cpp/tools/mtmd/mtmd-audio.h +47 -0
  177. package/cpp/tools/mtmd/mtmd-helper.cpp +460 -0
  178. package/cpp/tools/mtmd/mtmd-helper.h +95 -0
  179. package/cpp/tools/mtmd/mtmd.cpp +1066 -0
  180. package/cpp/tools/mtmd/mtmd.h +302 -0
  181. package/cpp/tools/mtmd/stb/stb_image.h +7988 -0
  182. package/cpp/unicode-data.cpp +7034 -0
  183. package/cpp/unicode-data.h +20 -0
  184. package/cpp/unicode.cpp +1061 -0
  185. package/cpp/unicode.h +68 -0
  186. package/cpp/vendor/cpp-httplib/httplib.cpp +16509 -0
  187. package/cpp/vendor/cpp-httplib/httplib.h +3883 -0
  188. package/desktop/electron-builder.config.cjs +157 -0
  189. package/desktop/entitlements.mac.plist +12 -0
  190. package/desktop/package.json +11 -0
  191. package/desktop/resolve-package-root.cjs +88 -0
  192. package/desktop/src/main/backend-selector.cjs +148 -0
  193. package/desktop/src/main/gpu-probe.cjs +142 -0
  194. package/desktop/src/main/index.cjs +58 -0
  195. package/desktop/src/main/ipc-handlers.cjs +212 -0
  196. package/desktop/src/main/model-store.cjs +50 -0
  197. package/desktop/src/main/preload.cjs +39 -0
  198. package/desktop/src/main/sidecar-client.cjs +76 -0
  199. package/desktop/src/main/sidecar-manager.cjs +364 -0
  200. package/dist/docs.json +14357 -0
  201. package/dist/esm/definitions.d.ts +731 -0
  202. package/dist/esm/definitions.js +2 -0
  203. package/dist/esm/definitions.js.map +1 -0
  204. package/dist/esm/desktop.d.ts +37 -0
  205. package/dist/esm/desktop.js +133 -0
  206. package/dist/esm/desktop.js.map +1 -0
  207. package/dist/esm/index.d.ts +200 -0
  208. package/dist/esm/index.js +612 -0
  209. package/dist/esm/index.js.map +1 -0
  210. package/dist/esm/isomorphic/desktop.runtime.d.ts +37 -0
  211. package/dist/esm/isomorphic/desktop.runtime.js +36 -0
  212. package/dist/esm/isomorphic/desktop.runtime.js.map +1 -0
  213. package/dist/esm/isomorphic/errors.d.ts +6 -0
  214. package/dist/esm/isomorphic/errors.js +9 -0
  215. package/dist/esm/isomorphic/errors.js.map +1 -0
  216. package/dist/esm/isomorphic/model.admission.d.ts +17 -0
  217. package/dist/esm/isomorphic/model.admission.js +27 -0
  218. package/dist/esm/isomorphic/model.admission.js.map +1 -0
  219. package/dist/esm/isomorphic/model.scheduler.d.ts +31 -0
  220. package/dist/esm/isomorphic/model.scheduler.js +95 -0
  221. package/dist/esm/isomorphic/model.scheduler.js.map +1 -0
  222. package/dist/esm/isomorphic/provider.desktop.d.ts +40 -0
  223. package/dist/esm/isomorphic/provider.desktop.js +411 -0
  224. package/dist/esm/isomorphic/provider.desktop.js.map +1 -0
  225. package/dist/esm/isomorphic/provider.factory.d.ts +2 -0
  226. package/dist/esm/isomorphic/provider.factory.js +16 -0
  227. package/dist/esm/isomorphic/provider.factory.js.map +1 -0
  228. package/dist/esm/isomorphic/provider.interface.d.ts +76 -0
  229. package/dist/esm/isomorphic/provider.interface.js +2 -0
  230. package/dist/esm/isomorphic/provider.interface.js.map +1 -0
  231. package/dist/esm/isomorphic/provider.native.d.ts +18 -0
  232. package/dist/esm/isomorphic/provider.native.js +173 -0
  233. package/dist/esm/isomorphic/provider.native.js.map +1 -0
  234. package/dist/esm/isomorphic/provider.web.d.ts +88 -0
  235. package/dist/esm/isomorphic/provider.web.js +573 -0
  236. package/dist/esm/isomorphic/provider.web.js.map +1 -0
  237. package/dist/esm/isomorphic/sidecar-sse.d.ts +14 -0
  238. package/dist/esm/isomorphic/sidecar-sse.js +76 -0
  239. package/dist/esm/isomorphic/sidecar-sse.js.map +1 -0
  240. package/dist/esm/isomorphic/wasmMemoryCalibration.d.ts +26 -0
  241. package/dist/esm/isomorphic/wasmMemoryCalibration.js +60 -0
  242. package/dist/esm/isomorphic/wasmMemoryCalibration.js.map +1 -0
  243. package/dist/esm/isomorphic/wasmMemoryPolicy.d.ts +55 -0
  244. package/dist/esm/isomorphic/wasmMemoryPolicy.js +93 -0
  245. package/dist/esm/isomorphic/wasmMemoryPolicy.js.map +1 -0
  246. package/dist/esm/storage/manifest.d.ts +13 -0
  247. package/dist/esm/storage/manifest.js +87 -0
  248. package/dist/esm/storage/manifest.js.map +1 -0
  249. package/dist/esm/storage/opfs.store.d.ts +31 -0
  250. package/dist/esm/storage/opfs.store.js +241 -0
  251. package/dist/esm/storage/opfs.store.js.map +1 -0
  252. package/dist/esm/web.d.ts +206 -0
  253. package/dist/esm/web.js +521 -0
  254. package/dist/esm/web.js.map +1 -0
  255. package/dist/esm/workers/async-file.d.ts +13 -0
  256. package/dist/esm/workers/async-file.js +12 -0
  257. package/dist/esm/workers/async-file.js.map +1 -0
  258. package/dist/esm/workers/heapfs.d.ts +55 -0
  259. package/dist/esm/workers/heapfs.js +115 -0
  260. package/dist/esm/workers/heapfs.js.map +1 -0
  261. package/dist/esm/workers/wasm.engine.d.ts +86 -0
  262. package/dist/esm/workers/wasm.engine.js +504 -0
  263. package/dist/esm/workers/wasm.engine.js.map +1 -0
  264. package/dist/esm/workers/worker.protocol.d.ts +160 -0
  265. package/dist/esm/workers/worker.protocol.js +2 -0
  266. package/dist/esm/workers/worker.protocol.js.map +1 -0
  267. package/dist/plugin.cjs +3179 -0
  268. package/dist/plugin.cjs.map +1 -0
  269. package/dist/plugin.js +3181 -0
  270. package/dist/plugin.js.map +1 -0
  271. package/dist/wasm/llama_engine.d.ts +74 -0
  272. package/dist/wasm/llama_engine.js +1829 -0
  273. package/dist/wasm/llama_engine.wasm +0 -0
  274. package/dist/wasm/llama_engine_emscripten.mjs +2 -0
  275. package/dist/wasm/package.json +16 -0
  276. package/dist/workers/llm.worker.js +1226 -0
  277. package/dist/workers/llm.worker.js.map +7 -0
  278. package/extraResources/llama-wasm/llama_engine.d.ts +74 -0
  279. package/extraResources/llama-wasm/llama_engine.js +1829 -0
  280. package/extraResources/llama-wasm/llama_engine.wasm +0 -0
  281. package/extraResources/llama-wasm/llama_engine_emscripten.mjs +2 -0
  282. package/extraResources/llama-wasm/package.json +16 -0
  283. package/extraResources/sidecar/README.md +11 -0
  284. package/extraResources/sidecar/darwin-arm64 +0 -0
  285. package/extraResources/sidecar/darwin-x64 +0 -0
  286. package/ios/CMakeLists-arm64.txt +161 -0
  287. package/ios/CMakeLists-x86_64.txt +188 -0
  288. package/ios/CMakeLists.txt +161 -0
  289. package/ios/Frameworks/llama-cpp.framework/Info.plist +28 -0
  290. package/ios/Frameworks/llama-cpp.framework/llama-cpp +0 -0
  291. package/ios/Sources/LlamaCppCapacitor/LlamaCpp.swift +1365 -0
  292. package/ios/Sources/LlamaCppCapacitor/LlamaCppPlugin.swift +694 -0
  293. package/ios/Sources/LlamaCppCapacitor/LlamaNativeBridge.swift +349 -0
  294. package/ios/Sources/LlamaCppCapacitor/ModelAdmissionController.swift +177 -0
  295. package/ios/embed-metal-shaders.sh +24 -0
  296. package/ios/metal-embed.cmake +29 -0
  297. package/package.json +281 -0
  298. package/scripts/build-js-preserve-wasm.cjs +53 -0
  299. package/scripts/build-sidecar-linux.sh +6 -0
  300. package/scripts/build-sidecar-win.bat +19 -0
  301. package/scripts/build-sidecar.sh +184 -0
  302. package/scripts/embed-llama-ios-app-framework.sh +63 -0
  303. package/scripts/ensure-desktop-sidecar-bundle.cjs +103 -0
  304. package/scripts/ensure-llama-ios-xcframework.sh +108 -0
  305. package/scripts/fix-esm-extensions.cjs +45 -0
  306. package/scripts/prepare-js-dist.cjs +28 -0
  307. package/scripts/stage-desktop-resources.cjs +116 -0
  308. package/sidecar/CMakeLists.txt +192 -0
  309. package/sidecar/cap-sidecar-main.cpp +68 -0
  310. package/types/llama-cpp-pro.d.ts +441 -0
@@ -0,0 +1,47 @@
1
+ #pragma once
2
+
3
+ #include "ggml.h"
4
+
5
+ #include <cstdint>
6
+ #include <vector>
7
+ #include <string>
8
+
9
+ #define WHISPER_ASSERT LM_GGML_ASSERT
10
+
11
+ #define WHISPER_SAMPLE_RATE 16000
12
+ #define WHISPER_N_FFT 400
13
+ #define WHISPER_HOP_LENGTH 160
14
+ #define WHISPER_CHUNK_SIZE 30
15
+
16
+ #define COMMON_SAMPLE_RATE 16000
17
+
18
+ namespace whisper_preprocessor {
19
+
20
+ struct whisper_mel {
21
+ int n_len;
22
+ int n_len_org;
23
+ int n_mel;
24
+
25
+ std::vector<float> data;
26
+ };
27
+
28
+ struct whisper_filters {
29
+ int32_t n_mel;
30
+ int32_t n_fft;
31
+
32
+ std::vector<float> data;
33
+ };
34
+
35
+ bool preprocess_audio(
36
+ const float * samples,
37
+ size_t n_samples,
38
+ const whisper_filters & filters,
39
+ std::vector<whisper_mel> & output);
40
+
41
+ } // namespace whisper_preprocessor
42
+
43
+ namespace whisper_precalc_filters {
44
+
45
+ whisper_preprocessor::whisper_filters get_128_bins();
46
+
47
+ } // namespace whisper_precalc_filters
@@ -0,0 +1,460 @@
1
+ // fix problem with std::min and std::max
2
+ #if defined(_WIN32)
3
+ #define WIN32_LEAN_AND_MEAN
4
+ #ifndef NOMINMAX
5
+ # define NOMINMAX
6
+ #endif
7
+ #include <windows.h>
8
+ #endif
9
+
10
+ #include "mtmd.h"
11
+ #include "mtmd-helper.h"
12
+ #include "llama.h"
13
+
14
+ #include <algorithm>
15
+ #include <cinttypes>
16
+ #include <vector>
17
+
18
+ //#define MTMD_AUDIO_DEBUG
19
+
20
+ #define MINIAUDIO_IMPLEMENTATION
21
+ #ifndef MTMD_AUDIO_DEBUG
22
+ # define MA_NO_ENCODING
23
+ #endif
24
+ #define MA_NO_DEVICE_IO
25
+ #define MA_NO_RESOURCE_MANAGER
26
+ #define MA_NO_NODE_GRAPH
27
+ #define MA_NO_ENGINE
28
+ #define MA_NO_GENERATION
29
+ #define MA_API static
30
+ #include "miniaudio/miniaudio.h"
31
+
32
+ #define STB_IMAGE_IMPLEMENTATION
33
+ #include "stb/stb_image.h"
34
+
35
+ #define LOG_INF(...) fprintf(stdout, __VA_ARGS__)
36
+ #define LOG_ERR(...) fprintf(stderr, __VA_ARGS__)
37
+
38
+ size_t mtmd_helper_get_n_tokens(const mtmd_input_chunks * chunks) {
39
+ size_t n_tokens = 0;
40
+ for (size_t i = 0; i < mtmd_input_chunks_size(chunks); i++) {
41
+ auto chunk = mtmd_input_chunks_get(chunks, i);
42
+ n_tokens += mtmd_input_chunk_get_n_tokens(chunk);
43
+ }
44
+ return n_tokens;
45
+ }
46
+
47
+ llama_pos mtmd_helper_get_n_pos(const mtmd_input_chunks * chunks) {
48
+ llama_pos n_pos = 0;
49
+ for (size_t i = 0; i < mtmd_input_chunks_size(chunks); i++) {
50
+ auto chunk = mtmd_input_chunks_get(chunks, i);
51
+ n_pos += mtmd_input_chunk_get_n_pos(chunk);
52
+ }
53
+ return n_pos;
54
+ }
55
+
56
+ // helper struct to make working with embd batch easier
57
+ // note: this will be removed after llama_batch_ext refactoring
58
+ struct decode_embd_batch {
59
+ int n_pos_per_embd;
60
+ int n_mmproj_embd;
61
+ std::vector<llama_pos> pos;
62
+ std::vector<llama_pos> pos_view; // used by mrope
63
+ std::vector<int32_t> n_seq_id;
64
+ std::vector<llama_seq_id> seq_id_0;
65
+ std::vector<llama_seq_id *> seq_ids;
66
+ std::vector<int8_t> logits;
67
+ llama_batch batch;
68
+ decode_embd_batch(float * embd, int32_t n_tokens, int n_pos_per_embd, int n_mmproj_embd) : n_pos_per_embd(n_pos_per_embd), n_mmproj_embd(n_mmproj_embd) {
69
+ pos .resize(n_tokens * n_pos_per_embd);
70
+ n_seq_id.resize(n_tokens);
71
+ seq_ids .resize(n_tokens + 1);
72
+ logits .resize(n_tokens);
73
+ seq_id_0.resize(1);
74
+ seq_ids [n_tokens] = nullptr;
75
+ batch = {
76
+ /*n_tokens =*/ n_tokens,
77
+ /*tokens =*/ nullptr,
78
+ /*embd =*/ embd,
79
+ /*pos =*/ pos.data(),
80
+ /*n_seq_id =*/ n_seq_id.data(),
81
+ /*seq_id =*/ seq_ids.data(),
82
+ /*logits =*/ logits.data(),
83
+ };
84
+ }
85
+
86
+ void set_position_normal(llama_pos pos_0, llama_seq_id seq_id) {
87
+ seq_id_0[0] = seq_id;
88
+ for (int i = 0; i < batch.n_tokens; i++) {
89
+ batch.pos [i] = pos_0 + i;
90
+ batch.n_seq_id[i] = 1;
91
+ batch.seq_id [i] = seq_id_0.data();
92
+ batch.logits [i] = false;
93
+ }
94
+ }
95
+
96
+ // M-RoPE for image
97
+ void set_position_mrope_2d(llama_pos pos_0, int nx, int ny, llama_seq_id seq_id) {
98
+ LM_GGML_ASSERT(n_pos_per_embd == 4);
99
+ seq_id_0[0] = seq_id;
100
+ for (int y = 0; y < ny; y++) {
101
+ for (int x = 0; x < nx; x++) {
102
+ int i = y * nx + x;
103
+ pos[i ] = pos_0;
104
+ pos[i + batch.n_tokens ] = pos_0 + y;
105
+ pos[i + batch.n_tokens * 2] = pos_0 + x;
106
+ pos[i + batch.n_tokens * 3] = 0; // last pos dim is unused
107
+ }
108
+ }
109
+ for (int i = 0; i < batch.n_tokens; i++) {
110
+ batch.n_seq_id[i] = 1;
111
+ batch.seq_id [i] = seq_id_0.data();
112
+ batch.logits [i] = false;
113
+ }
114
+ }
115
+
116
+ // M-RoPE for audio
117
+ void set_position_mrope_1d(llama_pos pos_0, llama_seq_id seq_id) {
118
+ LM_GGML_ASSERT(n_pos_per_embd == 4);
119
+ seq_id_0[0] = seq_id;
120
+ for (int i = 0; i < batch.n_tokens; i++) {
121
+ pos[i ] = pos_0 + i;
122
+ pos[i + batch.n_tokens ] = pos_0 + i;
123
+ pos[i + batch.n_tokens * 2] = pos_0 + i;
124
+ pos[i + batch.n_tokens * 3] = 0; // last pos dim is unused
125
+ }
126
+ for (int i = 0; i < batch.n_tokens; i++) {
127
+ batch.n_seq_id[i] = 1;
128
+ batch.seq_id [i] = seq_id_0.data();
129
+ batch.logits [i] = false;
130
+ }
131
+ }
132
+
133
+ llama_batch get_view(int offset, int n_tokens) {
134
+ llama_pos * pos_ptr;
135
+ pos_view.clear();
136
+ pos_view.reserve(n_tokens * n_pos_per_embd);
137
+ if (n_pos_per_embd > 1) {
138
+ // mrope
139
+ // for example, with layout of src: 1234...1234...1234...1234...
140
+ // offset 2 will give us dst: 34...34...34...34...
141
+ for (int i = 0; i < n_pos_per_embd; i++) {
142
+ // assume n_tokens is less than or equal to batch.n_tokens
143
+ // batch.n_tokens is number of **total** tokens
144
+ // n_tokens is number of viewed token
145
+ size_t src_idx = i * batch.n_tokens + offset;
146
+ pos_view.insert(pos_view.end(),
147
+ pos.data() + src_idx,
148
+ pos.data() + src_idx + n_tokens);
149
+ }
150
+ pos_ptr = pos_view.data();
151
+ } else {
152
+ // normal
153
+ pos_ptr = pos.data() + offset;
154
+ }
155
+ return {
156
+ /*n_tokens =*/ n_tokens,
157
+ /*tokens =*/ nullptr,
158
+ /*embd =*/ batch.embd + offset * n_mmproj_embd,
159
+ /*pos =*/ pos_ptr,
160
+ /*n_seq_id =*/ batch.n_seq_id + offset,
161
+ /*seq_id =*/ batch.seq_id + offset,
162
+ /*logits =*/ batch.logits + offset,
163
+ };
164
+ }
165
+ };
166
+
167
+ // Helper function for decoding an image whose embeddings have already been calculated
168
+ int32_t mtmd_helper_decode_image_chunk(
169
+ mtmd_context * ctx,
170
+ struct llama_context * lctx,
171
+ const mtmd_input_chunk * chunk,
172
+ float * encoded_embd,
173
+ llama_pos n_past,
174
+ llama_seq_id seq_id,
175
+ int32_t n_batch,
176
+ llama_pos * new_n_past) {
177
+ auto chunk_type = mtmd_input_chunk_get_type(chunk);
178
+ const char * name = chunk_type == MTMD_INPUT_CHUNK_TYPE_IMAGE ? "image" : "audio";
179
+ if (chunk_type == MTMD_INPUT_CHUNK_TYPE_TEXT) {
180
+ LOG_ERR("failed to decode chunk: input chunk not of image/audio type\n");
181
+ return -1;
182
+ }
183
+
184
+ const llama_model * model = llama_get_model(lctx);
185
+ int n_mmproj_embd = llama_model_n_embd(model);
186
+ int n_pos_per_embd = mtmd_decode_use_mrope(ctx) ? 4 : 1;
187
+
188
+ int32_t n_tokens = mtmd_input_chunk_get_n_tokens(chunk);
189
+ int32_t i_batch = 0;
190
+ int32_t n_img_batches = LM_GGML_PAD(n_tokens, n_batch) / n_batch;
191
+ decode_embd_batch batch_embd(encoded_embd, n_tokens, n_pos_per_embd, n_mmproj_embd);
192
+
193
+ if (mtmd_decode_use_mrope(ctx)) {
194
+ if (chunk_type == MTMD_INPUT_CHUNK_TYPE_IMAGE) {
195
+ const auto image_tokens = mtmd_input_chunk_get_tokens_image(chunk);
196
+ if (!image_tokens) {
197
+ LOG_ERR("failed to decode chunk: image tokens are null\n");
198
+ return -1;
199
+ }
200
+ const int nx = mtmd_image_tokens_get_nx(image_tokens);
201
+ const int ny = mtmd_image_tokens_get_ny(image_tokens);
202
+ batch_embd.set_position_mrope_2d(n_past, nx, ny, seq_id);
203
+ } else if (chunk_type == MTMD_INPUT_CHUNK_TYPE_AUDIO) {
204
+ batch_embd.set_position_mrope_1d(n_past, seq_id);
205
+ } else {
206
+ LM_GGML_ABORT("invalid chunk type for M-RoPE");
207
+ }
208
+ } else {
209
+ batch_embd.set_position_normal(n_past, seq_id);
210
+ }
211
+
212
+ if (mtmd_decode_use_non_causal(ctx)) {
213
+ llama_set_causal_attn(lctx, false);
214
+ // TODO @ngxson : need to make sure only one image is processed at a time, and n_ubatch must be enough to hold the image
215
+ }
216
+
217
+ while (i_batch < n_img_batches) { // split into batches
218
+ int pos_offset = i_batch*n_batch;
219
+ int n_tokens_batch = std::min(n_batch, n_tokens - pos_offset);
220
+ llama_batch batch_embd_view = batch_embd.get_view(pos_offset, n_tokens_batch);
221
+
222
+ LOG_INF("decoding %s batch %d/%d, n_tokens_batch = %d\n", name, i_batch+1, n_img_batches, n_tokens_batch);
223
+
224
+ int64_t t1 = lm_ggml_time_ms();
225
+ int32_t ret = llama_decode(lctx, batch_embd_view);
226
+ if (ret != 0) {
227
+ LOG_ERR("failed to decode %s\n", name);
228
+ llama_set_causal_attn(lctx, true); // restore causal attn
229
+ return ret;
230
+ }
231
+
232
+ LOG_INF("%s decoded (batch %d/%d) in %" PRId64 " ms\n", name, i_batch+1, n_img_batches, lm_ggml_time_ms() - t1);
233
+
234
+ i_batch++;
235
+ }
236
+
237
+ n_past += mtmd_input_chunk_get_n_pos(chunk);
238
+ *new_n_past = n_past;
239
+
240
+ if (mtmd_decode_use_non_causal(ctx)) {
241
+ llama_set_causal_attn(lctx, true);
242
+ }
243
+ return 0;
244
+ }
245
+
246
+ int32_t mtmd_helper_eval_chunk_single(mtmd_context * ctx,
247
+ struct llama_context * lctx,
248
+ const mtmd_input_chunk * chunk,
249
+ llama_pos n_past,
250
+ llama_seq_id seq_id,
251
+ int32_t n_batch,
252
+ bool logits_last,
253
+ llama_pos * new_n_past) {
254
+ int32_t ret;
255
+ llama_batch text_batch = llama_batch_init(n_batch, 0, 1);
256
+ auto chunk_type = mtmd_input_chunk_get_type(chunk);
257
+
258
+ if (chunk_type == MTMD_INPUT_CHUNK_TYPE_TEXT) {
259
+ size_t n_tokens;
260
+ const auto tokens = mtmd_input_chunk_get_tokens_text(chunk, &n_tokens);
261
+ // LOG_INF("decoding text chunk, n_tokens = %zu\n", n_tokens);
262
+ size_t i = 0;
263
+ while (i < n_tokens) { // split into batches
264
+ text_batch.n_tokens = 0; // clear the batch
265
+ for (; i < n_tokens && text_batch.n_tokens < n_batch; i++) {
266
+ int32_t j = text_batch.n_tokens;
267
+ text_batch.token [j] = tokens[i];
268
+ text_batch.pos [j] = n_past++;
269
+ text_batch.n_seq_id[j] = 1;
270
+ text_batch.seq_id [j][0] = seq_id;
271
+ text_batch.logits [j] = false;
272
+
273
+ text_batch.n_tokens++;
274
+ }
275
+ bool is_last_token = (i == n_tokens);
276
+ if (logits_last && is_last_token) {
277
+ text_batch.logits[text_batch.n_tokens - 1] = true;
278
+ }
279
+ ret = llama_decode(lctx, text_batch);
280
+ if (ret != 0) {
281
+ LOG_ERR("failed to decode text\n");
282
+ llama_batch_free(text_batch);
283
+ return ret;
284
+ }
285
+ *new_n_past += text_batch.n_tokens;
286
+ }
287
+
288
+ } else if (chunk_type == MTMD_INPUT_CHUNK_TYPE_IMAGE || chunk_type == MTMD_INPUT_CHUNK_TYPE_AUDIO) {
289
+ const char * name = chunk_type == MTMD_INPUT_CHUNK_TYPE_IMAGE ? "image" : "audio";
290
+ int64_t t0 = lm_ggml_time_ms();
291
+
292
+ LOG_INF("encoding %s slice...\n", name);
293
+
294
+ ret = mtmd_encode_chunk(ctx, chunk);
295
+ if (ret != 0) {
296
+ LOG_ERR("failed to encode %s slice\n", name);
297
+ llama_batch_free(text_batch);
298
+ return ret;
299
+ }
300
+
301
+ LOG_INF("%s slice encoded in %" PRId64 " ms\n", name, lm_ggml_time_ms() - t0);
302
+
303
+ float * embd = mtmd_get_output_embd(ctx);
304
+ ret = mtmd_helper_decode_image_chunk(ctx, lctx, chunk, embd, n_past, seq_id, n_batch, new_n_past);
305
+ if (ret != 0) {
306
+ LOG_ERR("failed to decode %s\n", name);
307
+ llama_batch_free(text_batch);
308
+ return ret;
309
+ }
310
+ } else {
311
+ LM_GGML_ABORT("chunk type not supported");
312
+ }
313
+
314
+ llama_batch_free(text_batch);
315
+ return 0;
316
+ }
317
+
318
+ int32_t mtmd_helper_eval_chunks(mtmd_context * ctx,
319
+ struct llama_context * lctx,
320
+ const mtmd_input_chunks * chunks,
321
+ llama_pos n_past,
322
+ llama_seq_id seq_id,
323
+ int32_t n_batch,
324
+ bool logits_last,
325
+ llama_pos * new_n_past) {
326
+ size_t n_chunks = mtmd_input_chunks_size(chunks);
327
+ if (n_chunks == 0) {
328
+ LOG_ERR("no chunks to eval\n");
329
+ return 0;
330
+ }
331
+
332
+ for (size_t i = 0; i < n_chunks; i++) {
333
+ bool chunk_logits_last = (i == n_chunks - 1) && logits_last;
334
+ auto chunk = mtmd_input_chunks_get(chunks, i);
335
+
336
+ int32_t res = mtmd_helper_eval_chunk_single(ctx, lctx, chunk, n_past, seq_id, n_batch, chunk_logits_last, &n_past);
337
+ if (res != 0) {
338
+ LOG_ERR("failed to eval chunk %zu\n", i);
339
+ return res;
340
+ }
341
+ *new_n_past = n_past;
342
+ }
343
+
344
+ return 0;
345
+ }
346
+
347
+ namespace audio_helpers {
348
+
349
+ static bool is_audio_file(const char * buf, size_t len) {
350
+ if (len < 12) {
351
+ return false;
352
+ }
353
+
354
+ // RIFF ref: https://en.wikipedia.org/wiki/Resource_Interchange_File_Format
355
+ // WAV ref: https://www.mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
356
+ bool is_wav = memcmp(buf, "RIFF", 4) == 0 && memcmp(buf + 8, "WAVE", 4) == 0;
357
+ bool is_mp3 = len >= 3 && (
358
+ memcmp(buf, "ID3", 3) == 0 ||
359
+ // Check for MPEG sync word (simplified check)
360
+ ((unsigned char)buf[0] == 0xFF && ((unsigned char)buf[1] & 0xE0) == 0xE0)
361
+ );
362
+ bool is_flac = memcmp(buf, "fLaC", 4) == 0;
363
+
364
+ return is_wav || is_mp3 || is_flac;
365
+ }
366
+
367
+ // returns true if the buffer is a valid audio file
368
+ static bool decode_audio_from_buf(const unsigned char * buf_in, size_t len, int target_sampler_rate, std::vector<float> & pcmf32_mono) {
369
+ ma_result result;
370
+ const int channels = 1;
371
+ ma_decoder_config decoder_config = ma_decoder_config_init(ma_format_f32, channels, target_sampler_rate);
372
+ ma_decoder decoder;
373
+
374
+ result = ma_decoder_init_memory(buf_in, len, &decoder_config, &decoder);
375
+ if (result != MA_SUCCESS) {
376
+ return false;
377
+ }
378
+
379
+ ma_uint64 frame_count;
380
+ ma_uint64 frames_read;
381
+ result = ma_decoder_get_length_in_pcm_frames(&decoder, &frame_count);
382
+ if (result != MA_SUCCESS) {
383
+ ma_decoder_uninit(&decoder);
384
+ return false;
385
+ }
386
+
387
+ pcmf32_mono.resize(frame_count);
388
+ result = ma_decoder_read_pcm_frames(&decoder, pcmf32_mono.data(), frame_count, &frames_read);
389
+ if (result != MA_SUCCESS) {
390
+ ma_decoder_uninit(&decoder);
391
+ return false;
392
+ }
393
+
394
+ #ifdef MTMD_AUDIO_DEBUG
395
+ // save audio to wav file
396
+ ma_encoder_config config = ma_encoder_config_init(ma_encoding_format_wav, ma_format_f32, 1, target_sampler_rate);
397
+ ma_encoder encoder;
398
+ ma_encoder_init_file("output.wav", &config, &encoder);
399
+ ma_encoder_write_pcm_frames(&encoder, pcmf32_mono.data(), pcmf32_mono.size(), &frames_read);
400
+ ma_encoder_uninit(&encoder);
401
+ #endif
402
+
403
+ ma_decoder_uninit(&decoder);
404
+ return true;
405
+ }
406
+
407
+ } // namespace audio_helpers
408
+
409
+ mtmd_bitmap * mtmd_helper_bitmap_init_from_buf(mtmd_context * ctx, const unsigned char * buf, size_t len) {
410
+ if (audio_helpers::is_audio_file((const char *)buf, len)) {
411
+ std::vector<float> pcmf32;
412
+ int bitrate = mtmd_get_audio_bitrate(ctx);
413
+ if (bitrate < 0) {
414
+ LOG_ERR("This model does not support audio input\n");
415
+ return nullptr;
416
+ }
417
+ if (!audio_helpers::decode_audio_from_buf(buf, len, bitrate, pcmf32)) {
418
+ LOG_ERR("Unable to read WAV audio file from buffer\n");
419
+ return nullptr;
420
+ }
421
+ return mtmd_bitmap_init_from_audio(pcmf32.size(), pcmf32.data());
422
+ }
423
+
424
+ // otherwise, we assume it's an image
425
+ mtmd_bitmap * result = nullptr;
426
+ {
427
+ int nx, ny, nc;
428
+ auto * data = stbi_load_from_memory(buf, len, &nx, &ny, &nc, 3);
429
+ if (!data) {
430
+ LOG_ERR("%s: failed to decode image bytes\n", __func__);
431
+ return nullptr;
432
+ }
433
+ result = mtmd_bitmap_init(nx, ny, data);
434
+ stbi_image_free(data);
435
+ }
436
+ return result;
437
+ }
438
+
439
+ mtmd_bitmap * mtmd_helper_bitmap_init_from_file(mtmd_context * ctx, const char * fname) {
440
+ std::vector<unsigned char> buf;
441
+ FILE * f = fopen(fname, "rb");
442
+ if (!f) {
443
+ LOG_ERR("Unable to open file %s: %s\n", fname, strerror(errno));
444
+ return nullptr;
445
+ }
446
+
447
+ fseek(f, 0, SEEK_END);
448
+ long file_size = ftell(f);
449
+ fseek(f, 0, SEEK_SET);
450
+ buf.resize(file_size);
451
+
452
+ size_t n_read = fread(buf.data(), 1, file_size, f);
453
+ fclose(f);
454
+ if (n_read != (size_t)file_size) {
455
+ LOG_ERR("Failed to read entire file %s", fname);
456
+ return nullptr;
457
+ }
458
+
459
+ return mtmd_helper_bitmap_init_from_buf(ctx, buf.data(), buf.size());
460
+ }
@@ -0,0 +1,95 @@
1
+ #ifndef MTMD_HELPER_H
2
+ #define MTMD_HELPER_H
3
+
4
+ #include "ggml.h"
5
+ #include "llama.h"
6
+ #include "mtmd.h"
7
+
8
+ #include <stddef.h>
9
+ #include <stdint.h>
10
+ #include <stdbool.h>
11
+
12
+ // NOTE:
13
+ // The original header wrapped these declarations in extern "C" when included
14
+ // from C++:
15
+ // #ifdef __cplusplus
16
+ // extern "C" { ... }
17
+ // #endif
18
+ // However, the implementations in mtmd-helper.cpp are compiled as C++ functions
19
+ // (no extern "C"), so using C linkage here causes the linker to look for plain
20
+ // C symbols like `_mtmd_helper_eval_chunk_single` which do not exist.
21
+ // For this plugin we only use these helpers from C++, so we keep C++ linkage
22
+ // and remove the extern \"C\" block to make declarations and definitions match.
23
+
24
+ //
25
+ // libmtmd helper functions
26
+ //
27
+ // Please note that these helpers are not guaranteed to be stable.
28
+ // BREAKING CHANGES are expected.
29
+ //
30
+
31
+ // helper function to construct a mtmd_bitmap from a file
32
+ // it calls mtmd_helper_bitmap_init_from_buf() internally
33
+ // returns nullptr on failure
34
+ // this function is thread-safe
35
+ MTMD_API mtmd_bitmap * mtmd_helper_bitmap_init_from_file(mtmd_context * ctx, const char * fname);
36
+
37
+ // helper function to construct a mtmd_bitmap from a buffer containing a file
38
+ // supported formats:
39
+ // image: formats supported by stb_image: jpg, png, bmp, gif, etc.
40
+ // audio: formats supported by miniaudio: wav, mp3, flac
41
+ // note: audio files will be auto-detected based on magic bytes
42
+ // returns nullptr on failure
43
+ // this function is thread-safe
44
+ MTMD_API mtmd_bitmap * mtmd_helper_bitmap_init_from_buf(mtmd_context * ctx, const unsigned char * buf, size_t len);
45
+
46
+ // helper to count the total number of tokens from a list of chunks, useful to keep track of KV cache
47
+ MTMD_API size_t mtmd_helper_get_n_tokens(const mtmd_input_chunks * chunks);
48
+
49
+ // helper to count the total position of tokens from a list of chunks, useful to keep track of n_past
50
+ // normally, n_pos is equal to n_tokens, but for M-RoPE it is different
51
+ MTMD_API llama_pos mtmd_helper_get_n_pos(const mtmd_input_chunks * chunks);
52
+
53
+ // helper function that automatically:
54
+ // 1. run llama_decode() on text chunks
55
+ // 2. run mtmd_encode() on image chunks, then mtmd_get_output_embd() and then llama_decode()
56
+ // if any of the mtmd_encode() or llama_decode() calls return non-zero, stop and forward the error
57
+ // otherwise, returns 0 on success
58
+ // this function is NOT thread-safe
59
+ MTMD_API int32_t mtmd_helper_eval_chunks(mtmd_context * ctx,
60
+ struct llama_context * lctx,
61
+ const mtmd_input_chunks * chunks,
62
+ llama_pos n_past,
63
+ llama_seq_id seq_id,
64
+ int32_t n_batch,
65
+ bool logits_last,
66
+ llama_pos * new_n_past);
67
+
68
+ // works like mtmd_helper_eval_chunks(), but only for a single chunk
69
+ // this function is NOT thread-safe
70
+ MTMD_API int32_t mtmd_helper_eval_chunk_single(mtmd_context * ctx,
71
+ struct llama_context * lctx,
72
+ const mtmd_input_chunk * chunk,
73
+ llama_pos n_past,
74
+ llama_seq_id seq_id,
75
+ int32_t n_batch,
76
+ bool logits_last,
77
+ llama_pos * new_n_past);
78
+
79
+ // helper function to decode an image whose embeddings have already been calculated
80
+ // this helper will handle batching and pre/post decoding setup (for ex. gemma 3 requires non-causal attention)
81
+ // ret 0 on success, -1 on chunk not being a valid image chunk, 1 on decode failure
82
+ MTMD_API int32_t mtmd_helper_decode_image_chunk(mtmd_context * ctx,
83
+ struct llama_context * lctx,
84
+ const mtmd_input_chunk * chunk,
85
+ float * encoded_embd,
86
+ llama_pos n_past,
87
+ llama_seq_id seq_id,
88
+ int32_t n_batch,
89
+ llama_pos * new_n_past);
90
+
91
+ //
92
+ // C++ wrappers
93
+ //
94
+
95
+ #endif