local-llm-rn 1.0.0 → 1.0.3

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 (477) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +321 -0
  3. package/android/build.gradle.kts +169 -0
  4. package/android/proguard-rules.pro +14 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/cpp/CMakeLists.txt +71 -0
  7. package/android/src/main/cpp/LocalLLM.cpp +1412 -0
  8. package/android/src/main/java/com/hilum/localllm/LocalLLMModule.kt +656 -0
  9. package/android/src/main/java/com/hilum/localllm/LocalLLMPackage.kt +26 -0
  10. package/cpp/CMakeLists.txt +10 -0
  11. package/cpp/LICENSE +21 -0
  12. package/cpp/cmake/arm64-apple-clang.cmake +16 -0
  13. package/cpp/cmake/arm64-windows-llvm.cmake +16 -0
  14. package/cpp/cmake/build-info.cmake +48 -0
  15. package/cpp/cmake/common.cmake +58 -0
  16. package/cpp/cmake/download-models.cmake +21 -0
  17. package/cpp/cmake/git-vars.cmake +22 -0
  18. package/cpp/cmake/license.cmake +40 -0
  19. package/cpp/cmake/llama-config.cmake.in +30 -0
  20. package/cpp/cmake/llama.pc.in +10 -0
  21. package/cpp/cmake/riscv64-spacemit-linux-gnu-gcc.cmake +29 -0
  22. package/cpp/cmake/x64-windows-llvm.cmake +5 -0
  23. package/cpp/common/CMakeLists.txt +1 -1
  24. package/cpp/common/build-info.cpp +4 -0
  25. package/cpp/common/jinja/README.md +1 -1
  26. package/cpp/common/jinja/string.cpp +1 -1
  27. package/cpp/common/jinja/value.h +1 -1
  28. package/cpp/ggml/src/ggml-cpu/CMakeLists.txt +49 -39
  29. package/cpp/ggml/src/ggml-cpu/kleidiai/kernels.cpp +21 -20
  30. package/cpp/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp +965 -252
  31. package/cpp/ggml/src/ggml-cpu/llamafile/sgemm.cpp +15 -1
  32. package/cpp/ggml/src/ggml-vulkan/CMakeLists.txt +265 -0
  33. package/cpp/ggml/src/ggml-vulkan/cmake/host-toolchain.cmake.in +16 -0
  34. package/cpp/ggml/src/ggml-vulkan/ggml-vulkan.cpp +16886 -0
  35. package/cpp/ggml/src/ggml-vulkan/vma/vk_mem_alloc.h +19530 -0
  36. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/CMakeLists.txt +35 -0
  37. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/abs.comp +21 -0
  38. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/acc.comp +37 -0
  39. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/add.comp +69 -0
  40. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/add1.comp +28 -0
  41. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/add_id.comp +42 -0
  42. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/arange.comp +20 -0
  43. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/argmax.comp +60 -0
  44. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort.comp +86 -0
  45. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/argsort_large.comp +114 -0
  46. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/ceil.comp +22 -0
  47. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/clamp.comp +17 -0
  48. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/concat.comp +41 -0
  49. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/contig_copy.comp +49 -0
  50. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_dw.comp +105 -0
  51. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +347 -0
  52. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/conv_transpose_1d.comp +98 -0
  53. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy.comp +23 -0
  54. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_from_quant.comp +51 -0
  55. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_to_quant.comp +296 -0
  56. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/copy_transpose.comp +67 -0
  57. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/cos.comp +17 -0
  58. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_equal.comp +31 -0
  59. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/count_experts.comp +51 -0
  60. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum.comp +83 -0
  61. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass1.comp +60 -0
  62. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/cumsum_multipass2.comp +66 -0
  63. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_f32.comp +20 -0
  64. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs.glsl +610 -0
  65. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_funcs_cm2.glsl +734 -0
  66. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_head.glsl +13 -0
  67. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_m.comp +42 -0
  68. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq1_s.comp +35 -0
  69. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq2_s.comp +44 -0
  70. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq2_xs.comp +43 -0
  71. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq2_xxs.comp +49 -0
  72. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq3_s.comp +40 -0
  73. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq3_xxs.comp +51 -0
  74. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq4_nl.comp +32 -0
  75. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_iq4_xs.comp +34 -0
  76. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_mxfp4.comp +32 -0
  77. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q2_k.comp +34 -0
  78. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q3_k.comp +42 -0
  79. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q4_0.comp +30 -0
  80. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q4_1.comp +32 -0
  81. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q4_k.comp +68 -0
  82. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q5_0.comp +34 -0
  83. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q5_1.comp +35 -0
  84. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q5_k.comp +70 -0
  85. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q6_k.comp +33 -0
  86. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/dequant_q8_0.comp +31 -0
  87. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/diag.comp +29 -0
  88. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/diag_mask_inf.comp +34 -0
  89. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/div.comp +27 -0
  90. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/exp.comp +21 -0
  91. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/bfloat16.comp +7 -0
  92. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/coopmat.comp +7 -0
  93. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/coopmat2.comp +7 -0
  94. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/feature-tests/integer_dot.comp +7 -0
  95. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/fill.comp +19 -0
  96. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn.comp +608 -0
  97. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_base.glsl +264 -0
  98. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm1.comp +642 -0
  99. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm2.comp +390 -0
  100. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_mask_opt.comp +162 -0
  101. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_split_k_reduce.comp +121 -0
  102. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/floor.comp +22 -0
  103. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/geglu.comp +13 -0
  104. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/geglu_erf.comp +27 -0
  105. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/geglu_quick.comp +11 -0
  106. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/gelu.comp +25 -0
  107. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/gelu_erf.comp +39 -0
  108. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/gelu_quick.comp +23 -0
  109. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/generic_binary_head.glsl +66 -0
  110. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/generic_head.glsl +11 -0
  111. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.glsl +83 -0
  112. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/get_rows.comp +42 -0
  113. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/get_rows_quant.comp +51 -0
  114. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/glu_head.glsl +19 -0
  115. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/glu_main.glsl +29 -0
  116. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/group_norm.comp +66 -0
  117. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/hardsigmoid.comp +22 -0
  118. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/hardswish.comp +22 -0
  119. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/im2col.comp +116 -0
  120. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/im2col_3d.comp +125 -0
  121. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/l2_norm.comp +44 -0
  122. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/leaky_relu.comp +22 -0
  123. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/log.comp +18 -0
  124. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul.comp +27 -0
  125. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_split_k_reduce.comp +48 -0
  126. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec.comp +169 -0
  127. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_base.glsl +230 -0
  128. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iface.glsl +35 -0
  129. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq1_m.comp +132 -0
  130. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq1_s.comp +95 -0
  131. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq2_s.comp +90 -0
  132. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq2_xs.comp +105 -0
  133. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq2_xxs.comp +87 -0
  134. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq3_s.comp +90 -0
  135. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_iq3_xxs.comp +88 -0
  136. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_nc.comp +124 -0
  137. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_p021.comp +156 -0
  138. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q2_k.comp +128 -0
  139. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q3_k.comp +132 -0
  140. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q4_k.comp +161 -0
  141. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q5_k.comp +165 -0
  142. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vec_q6_k.comp +137 -0
  143. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq.comp +143 -0
  144. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq_funcs.glsl +494 -0
  145. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp +464 -0
  146. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_cm2.comp +624 -0
  147. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_funcs.glsl +606 -0
  148. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_id_funcs.glsl +74 -0
  149. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq.comp +311 -0
  150. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_funcs.glsl +454 -0
  151. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/mul_mmq_shmem_types.glsl +78 -0
  152. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/multi_add.comp +195 -0
  153. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/neg.comp +20 -0
  154. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/norm.comp +44 -0
  155. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/opt_step_adamw.comp +42 -0
  156. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/opt_step_sgd.comp +22 -0
  157. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/pad.comp +64 -0
  158. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/pool2d.comp +74 -0
  159. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/quantize_q8_1.comp +145 -0
  160. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/reglu.comp +9 -0
  161. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/relu.comp +21 -0
  162. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/repeat.comp +26 -0
  163. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/repeat_back.comp +37 -0
  164. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rms_norm.comp +150 -0
  165. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rms_norm_back.comp +55 -0
  166. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rms_norm_partials.comp +65 -0
  167. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/roll.comp +46 -0
  168. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rope_funcs.glsl +207 -0
  169. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rope_head.glsl +20 -0
  170. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rope_multi.comp +17 -0
  171. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rope_neox.comp +17 -0
  172. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rope_norm.comp +17 -0
  173. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rope_params.glsl +33 -0
  174. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rope_vision.comp +17 -0
  175. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/round.comp +29 -0
  176. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/rte.glsl +5 -0
  177. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/scale.comp +24 -0
  178. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/sgn.comp +21 -0
  179. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/sigmoid.comp +20 -0
  180. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/silu.comp +22 -0
  181. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/silu_back.comp +26 -0
  182. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/sin.comp +17 -0
  183. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/soft_max.comp +195 -0
  184. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/soft_max_back.comp +54 -0
  185. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large1.comp +62 -0
  186. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large2.comp +79 -0
  187. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large3.comp +65 -0
  188. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/soft_max_large_common.glsl +53 -0
  189. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/softplus.comp +23 -0
  190. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/solve_tri.comp +81 -0
  191. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/sqrt.comp +17 -0
  192. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/square.comp +17 -0
  193. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/ssm_conv.comp +50 -0
  194. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/ssm_scan.comp +124 -0
  195. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/step.comp +22 -0
  196. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/sub.comp +29 -0
  197. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/sum_rows.comp +47 -0
  198. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/sum_rows.glsl +25 -0
  199. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/swiglu.comp +9 -0
  200. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/swiglu_oai.comp +14 -0
  201. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/tanh.comp +20 -0
  202. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/timestep_embedding.comp +42 -0
  203. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/topk_argsort.comp +118 -0
  204. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/topk_moe.comp +213 -0
  205. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/topk_nary_search.comp +246 -0
  206. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/tri.comp +43 -0
  207. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/trunc.comp +22 -0
  208. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/types.glsl +1784 -0
  209. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/upscale.comp +178 -0
  210. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/utils.glsl +25 -0
  211. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +1318 -0
  212. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/wkv6.comp +87 -0
  213. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/wkv7.comp +91 -0
  214. package/cpp/ggml/src/ggml-vulkan/vulkan-shaders/xielu.comp +35 -0
  215. package/cpp/hilum/CMakeLists.txt +58 -0
  216. package/cpp/hilum/hilum_llm.cpp +2186 -0
  217. package/cpp/hilum/hilum_llm.h +507 -0
  218. package/cpp/licenses/LICENSE-jsonhpp +21 -0
  219. package/cpp/mtmd/CMakeLists.txt +21 -12
  220. package/cpp/vendor/cpp-httplib/CMakeLists.txt +182 -0
  221. package/cpp/vendor/cpp-httplib/LICENSE +22 -0
  222. package/cpp/vendor/cpp-httplib/httplib.cpp +16164 -0
  223. package/cpp/vendor/cpp-httplib/httplib.h +3797 -0
  224. package/cpp/vendor/miniaudio/miniaudio.h +95747 -0
  225. package/ios/LocalLLM.h +5 -0
  226. package/ios/LocalLLM.mm +654 -623
  227. package/local-llm-rn.podspec +38 -8
  228. package/package.json +65 -6
  229. package/src/NativeLocalLLM.ts +32 -20
  230. package/src/cache.ts +149 -0
  231. package/src/device.ts +36 -10
  232. package/src/errors.ts +28 -0
  233. package/src/index.ts +10 -7
  234. package/src/local-llm.ts +147 -0
  235. package/src/model-manager.ts +94 -0
  236. package/src/native-bridge.ts +168 -24
  237. package/src/rn-downloader.ts +23 -4
  238. package/src/vision.ts +60 -0
  239. package/cpp/ggml/src/ggml-hexagon/CMakeLists.txt +0 -117
  240. package/cpp/ggml/src/ggml-hexagon/ggml-hexagon.cpp +0 -3232
  241. package/cpp/ggml/src/ggml-hexagon/htp/CMakeLists.txt +0 -45
  242. package/cpp/ggml/src/ggml-hexagon/htp/act-ops.c +0 -815
  243. package/cpp/ggml/src/ggml-hexagon/htp/argsort-ops.c +0 -281
  244. package/cpp/ggml/src/ggml-hexagon/htp/binary-ops.c +0 -827
  245. package/cpp/ggml/src/ggml-hexagon/htp/cmake-toolchain.cmake +0 -157
  246. package/cpp/ggml/src/ggml-hexagon/htp/cpy-ops.c +0 -251
  247. package/cpp/ggml/src/ggml-hexagon/htp/flash-attn-ops.c +0 -666
  248. package/cpp/ggml/src/ggml-hexagon/htp/get-rows-ops.c +0 -111
  249. package/cpp/ggml/src/ggml-hexagon/htp/hex-dma.c +0 -63
  250. package/cpp/ggml/src/ggml-hexagon/htp/hex-dma.h +0 -182
  251. package/cpp/ggml/src/ggml-hexagon/htp/hex-dump.h +0 -77
  252. package/cpp/ggml/src/ggml-hexagon/htp/hex-fastdiv.h +0 -37
  253. package/cpp/ggml/src/ggml-hexagon/htp/hex-utils.h +0 -51
  254. package/cpp/ggml/src/ggml-hexagon/htp/htp-ctx.h +0 -35
  255. package/cpp/ggml/src/ggml-hexagon/htp/htp-msg.h +0 -154
  256. package/cpp/ggml/src/ggml-hexagon/htp/htp-ops.h +0 -65
  257. package/cpp/ggml/src/ggml-hexagon/htp/htp_iface.idl +0 -16
  258. package/cpp/ggml/src/ggml-hexagon/htp/hvx-arith.h +0 -470
  259. package/cpp/ggml/src/ggml-hexagon/htp/hvx-base.h +0 -173
  260. package/cpp/ggml/src/ggml-hexagon/htp/hvx-copy.h +0 -245
  261. package/cpp/ggml/src/ggml-hexagon/htp/hvx-div.h +0 -116
  262. package/cpp/ggml/src/ggml-hexagon/htp/hvx-dump.h +0 -129
  263. package/cpp/ggml/src/ggml-hexagon/htp/hvx-exp.h +0 -215
  264. package/cpp/ggml/src/ggml-hexagon/htp/hvx-floor.h +0 -100
  265. package/cpp/ggml/src/ggml-hexagon/htp/hvx-inverse.h +0 -176
  266. package/cpp/ggml/src/ggml-hexagon/htp/hvx-reduce.h +0 -266
  267. package/cpp/ggml/src/ggml-hexagon/htp/hvx-scale.h +0 -133
  268. package/cpp/ggml/src/ggml-hexagon/htp/hvx-sigmoid.h +0 -141
  269. package/cpp/ggml/src/ggml-hexagon/htp/hvx-sqrt.h +0 -126
  270. package/cpp/ggml/src/ggml-hexagon/htp/hvx-types.h +0 -36
  271. package/cpp/ggml/src/ggml-hexagon/htp/hvx-utils.h +0 -18
  272. package/cpp/ggml/src/ggml-hexagon/htp/main.c +0 -1150
  273. package/cpp/ggml/src/ggml-hexagon/htp/matmul-ops.c +0 -2595
  274. package/cpp/ggml/src/ggml-hexagon/htp/rope-ops.c +0 -498
  275. package/cpp/ggml/src/ggml-hexagon/htp/set-rows-ops.c +0 -167
  276. package/cpp/ggml/src/ggml-hexagon/htp/softmax-ops.c +0 -421
  277. package/cpp/ggml/src/ggml-hexagon/htp/sum-rows-ops.c +0 -130
  278. package/cpp/ggml/src/ggml-hexagon/htp/unary-ops.c +0 -384
  279. package/cpp/ggml/src/ggml-hexagon/htp/worker-pool.c +0 -293
  280. package/cpp/ggml/src/ggml-hexagon/htp/worker-pool.h +0 -57
  281. package/cpp/ggml/src/ggml-hexagon/htp-drv.cpp +0 -418
  282. package/cpp/ggml/src/ggml-hexagon/htp-drv.h +0 -121
  283. package/cpp/ggml/src/ggml-hexagon/libdl.h +0 -79
  284. package/cpp/ggml/src/ggml-hexagon/libggml-htp.inf +0 -38
  285. package/cpp/ggml/src/ggml-hexagon/op-desc.h +0 -153
  286. package/cpp/ggml/src/ggml-musa/CMakeLists.txt +0 -125
  287. package/cpp/ggml/src/ggml-musa/mudnn.cu +0 -112
  288. package/cpp/ggml/src/ggml-musa/mudnn.cuh +0 -12
  289. package/cpp/ggml/src/ggml-opencl/CMakeLists.txt +0 -150
  290. package/cpp/ggml/src/ggml-opencl/ggml-opencl.cpp +0 -11553
  291. package/cpp/ggml/src/ggml-opencl/kernels/add.cl +0 -190
  292. package/cpp/ggml/src/ggml-opencl/kernels/add_id.cl +0 -42
  293. package/cpp/ggml/src/ggml-opencl/kernels/argsort.cl +0 -86
  294. package/cpp/ggml/src/ggml-opencl/kernels/clamp.cl +0 -20
  295. package/cpp/ggml/src/ggml-opencl/kernels/concat.cl +0 -51
  296. package/cpp/ggml/src/ggml-opencl/kernels/conv2d.cl +0 -185
  297. package/cpp/ggml/src/ggml-opencl/kernels/conv2d_f16_f32.cl +0 -176
  298. package/cpp/ggml/src/ggml-opencl/kernels/cpy.cl +0 -184
  299. package/cpp/ggml/src/ggml-opencl/kernels/cvt.cl +0 -417
  300. package/cpp/ggml/src/ggml-opencl/kernels/diag_mask_inf.cl +0 -58
  301. package/cpp/ggml/src/ggml-opencl/kernels/div.cl +0 -138
  302. package/cpp/ggml/src/ggml-opencl/kernels/embed_kernel.py +0 -26
  303. package/cpp/ggml/src/ggml-opencl/kernels/expm1.cl +0 -113
  304. package/cpp/ggml/src/ggml-opencl/kernels/fill.cl +0 -17
  305. package/cpp/ggml/src/ggml-opencl/kernels/flash_attn_f16.cl +0 -370
  306. package/cpp/ggml/src/ggml-opencl/kernels/flash_attn_f32.cl +0 -371
  307. package/cpp/ggml/src/ggml-opencl/kernels/flash_attn_f32_f16.cl +0 -373
  308. package/cpp/ggml/src/ggml-opencl/kernels/gelu.cl +0 -89
  309. package/cpp/ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32.cl +0 -162
  310. package/cpp/ggml/src/ggml-opencl/kernels/gemv_moe_mxfp4_f32.cl +0 -156
  311. package/cpp/ggml/src/ggml-opencl/kernels/gemv_noshuffle.cl +0 -268
  312. package/cpp/ggml/src/ggml-opencl/kernels/gemv_noshuffle_general.cl +0 -274
  313. package/cpp/ggml/src/ggml-opencl/kernels/gemv_noshuffle_general_q8_0_f32.cl +0 -195
  314. package/cpp/ggml/src/ggml-opencl/kernels/get_rows.cl +0 -187
  315. package/cpp/ggml/src/ggml-opencl/kernels/glu.cl +0 -378
  316. package/cpp/ggml/src/ggml-opencl/kernels/group_norm.cl +0 -121
  317. package/cpp/ggml/src/ggml-opencl/kernels/im2col_f16.cl +0 -57
  318. package/cpp/ggml/src/ggml-opencl/kernels/im2col_f32.cl +0 -57
  319. package/cpp/ggml/src/ggml-opencl/kernels/mean.cl +0 -140
  320. package/cpp/ggml/src/ggml-opencl/kernels/mul.cl +0 -152
  321. package/cpp/ggml/src/ggml-opencl/kernels/mul_mat_Ab_Bi_8x4.cl +0 -139
  322. package/cpp/ggml/src/ggml-opencl/kernels/mul_mat_f16_f32.cl +0 -130
  323. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_f16_f32_kq_kqv.cl +0 -273
  324. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_f16_f32_l4_lm.cl +0 -146
  325. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_f32_f32_l4_lm.cl +0 -147
  326. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_q4_0_f32_l4_lm.cl +0 -163
  327. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_q4_1_f32_l4_lm.cl +0 -165
  328. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_q6_k_f32_l4_lm.cl +0 -158
  329. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_q8_0_f32_8x4.cl +0 -129
  330. package/cpp/ggml/src/ggml-opencl/kernels/mul_mm_q8_0_f32_l4_lm.cl +0 -154
  331. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_f16_f16.cl +0 -118
  332. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32.cl +0 -118
  333. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_1row.cl +0 -94
  334. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +0 -84
  335. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_f32_f32.cl +0 -118
  336. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_id_mxfp4_f32.cl +0 -189
  337. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_id_mxfp4_f32_flat.cl +0 -176
  338. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_id_q4_0_f32_8x_flat.cl +0 -283
  339. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_id_q8_0_f32.cl +0 -140
  340. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_id_q8_0_f32_flat.cl +0 -222
  341. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_mxfp4_f32.cl +0 -144
  342. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_mxfp4_f32_flat.cl +0 -167
  343. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32.cl +0 -192
  344. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_1d_16x_flat.cl +0 -307
  345. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_1d_8x_flat.cl +0 -265
  346. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_8x_flat.cl +0 -272
  347. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_0_f32_v.cl +0 -254
  348. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_1_f32.cl +0 -219
  349. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_1_f32_flat.cl +0 -229
  350. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32.cl +0 -180
  351. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q6_k_f32.cl +0 -194
  352. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q6_k_f32_flat.cl +0 -194
  353. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q8_0_f32.cl +0 -125
  354. package/cpp/ggml/src/ggml-opencl/kernels/mul_mv_q8_0_f32_flat.cl +0 -202
  355. package/cpp/ggml/src/ggml-opencl/kernels/norm.cl +0 -161
  356. package/cpp/ggml/src/ggml-opencl/kernels/pad.cl +0 -39
  357. package/cpp/ggml/src/ggml-opencl/kernels/relu.cl +0 -16
  358. package/cpp/ggml/src/ggml-opencl/kernels/repeat.cl +0 -38
  359. package/cpp/ggml/src/ggml-opencl/kernels/rms_norm.cl +0 -190
  360. package/cpp/ggml/src/ggml-opencl/kernels/rope.cl +0 -747
  361. package/cpp/ggml/src/ggml-opencl/kernels/scale.cl +0 -27
  362. package/cpp/ggml/src/ggml-opencl/kernels/set_rows.cl +0 -208
  363. package/cpp/ggml/src/ggml-opencl/kernels/sigmoid.cl +0 -29
  364. package/cpp/ggml/src/ggml-opencl/kernels/silu.cl +0 -30
  365. package/cpp/ggml/src/ggml-opencl/kernels/softmax_4_f16.cl +0 -108
  366. package/cpp/ggml/src/ggml-opencl/kernels/softmax_4_f32.cl +0 -108
  367. package/cpp/ggml/src/ggml-opencl/kernels/softmax_f16.cl +0 -107
  368. package/cpp/ggml/src/ggml-opencl/kernels/softmax_f32.cl +0 -107
  369. package/cpp/ggml/src/ggml-opencl/kernels/softplus.cl +0 -116
  370. package/cpp/ggml/src/ggml-opencl/kernels/solve_tri.cl +0 -51
  371. package/cpp/ggml/src/ggml-opencl/kernels/sqr.cl +0 -53
  372. package/cpp/ggml/src/ggml-opencl/kernels/sqrt.cl +0 -53
  373. package/cpp/ggml/src/ggml-opencl/kernels/ssm_conv.cl +0 -77
  374. package/cpp/ggml/src/ggml-opencl/kernels/sub.cl +0 -138
  375. package/cpp/ggml/src/ggml-opencl/kernels/sum_rows.cl +0 -140
  376. package/cpp/ggml/src/ggml-opencl/kernels/tanh.cl +0 -109
  377. package/cpp/ggml/src/ggml-opencl/kernels/transpose.cl +0 -117
  378. package/cpp/ggml/src/ggml-opencl/kernels/tri.cl +0 -32
  379. package/cpp/ggml/src/ggml-opencl/kernels/tsembd.cl +0 -48
  380. package/cpp/ggml/src/ggml-opencl/kernels/upscale.cl +0 -120
  381. package/cpp/ggml/src/ggml-rpc/CMakeLists.txt +0 -9
  382. package/cpp/ggml/src/ggml-rpc/ggml-rpc.cpp +0 -2118
  383. package/cpp/ggml/src/ggml-virtgpu/CMakeLists.txt +0 -70
  384. package/cpp/ggml/src/ggml-virtgpu/apir_cs_ggml-rpc-front.cpp +0 -87
  385. package/cpp/ggml/src/ggml-virtgpu/backend/CMakeLists.txt +0 -21
  386. package/cpp/ggml/src/ggml-virtgpu/backend/apir_cs_ggml-rpc-back.cpp +0 -115
  387. package/cpp/ggml/src/ggml-virtgpu/backend/backend-convert.h +0 -13
  388. package/cpp/ggml/src/ggml-virtgpu/backend/backend-dispatched-backend.cpp +0 -102
  389. package/cpp/ggml/src/ggml-virtgpu/backend/backend-dispatched-buffer-type.cpp +0 -105
  390. package/cpp/ggml/src/ggml-virtgpu/backend/backend-dispatched-buffer.cpp +0 -179
  391. package/cpp/ggml/src/ggml-virtgpu/backend/backend-dispatched-device.cpp +0 -148
  392. package/cpp/ggml/src/ggml-virtgpu/backend/backend-dispatched.cpp +0 -51
  393. package/cpp/ggml/src/ggml-virtgpu/backend/backend-dispatched.gen.h +0 -73
  394. package/cpp/ggml/src/ggml-virtgpu/backend/backend-dispatched.h +0 -27
  395. package/cpp/ggml/src/ggml-virtgpu/backend/backend-virgl-apir.h +0 -32
  396. package/cpp/ggml/src/ggml-virtgpu/backend/backend.cpp +0 -144
  397. package/cpp/ggml/src/ggml-virtgpu/backend/shared/api_remoting.h +0 -95
  398. package/cpp/ggml/src/ggml-virtgpu/backend/shared/apir_backend.gen.h +0 -94
  399. package/cpp/ggml/src/ggml-virtgpu/backend/shared/apir_backend.h +0 -50
  400. package/cpp/ggml/src/ggml-virtgpu/backend/shared/apir_cs.h +0 -378
  401. package/cpp/ggml/src/ggml-virtgpu/backend/shared/apir_cs_ggml.h +0 -232
  402. package/cpp/ggml/src/ggml-virtgpu/backend/shared/apir_cs_rpc.h +0 -58
  403. package/cpp/ggml/src/ggml-virtgpu/ggml-backend-buffer-type.cpp +0 -81
  404. package/cpp/ggml/src/ggml-virtgpu/ggml-backend-buffer.cpp +0 -119
  405. package/cpp/ggml/src/ggml-virtgpu/ggml-backend-device.cpp +0 -158
  406. package/cpp/ggml/src/ggml-virtgpu/ggml-backend-reg.cpp +0 -213
  407. package/cpp/ggml/src/ggml-virtgpu/ggml-backend.cpp +0 -69
  408. package/cpp/ggml/src/ggml-virtgpu/ggml-remoting.h +0 -71
  409. package/cpp/ggml/src/ggml-virtgpu/ggmlremoting_functions.yaml +0 -166
  410. package/cpp/ggml/src/ggml-virtgpu/include/apir_hw.h +0 -9
  411. package/cpp/ggml/src/ggml-virtgpu/regenerate_remoting.py +0 -333
  412. package/cpp/ggml/src/ggml-virtgpu/virtgpu-apir.h +0 -15
  413. package/cpp/ggml/src/ggml-virtgpu/virtgpu-forward-backend.cpp +0 -58
  414. package/cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer-type.cpp +0 -110
  415. package/cpp/ggml/src/ggml-virtgpu/virtgpu-forward-buffer.cpp +0 -173
  416. package/cpp/ggml/src/ggml-virtgpu/virtgpu-forward-device.cpp +0 -192
  417. package/cpp/ggml/src/ggml-virtgpu/virtgpu-forward-impl.h +0 -36
  418. package/cpp/ggml/src/ggml-virtgpu/virtgpu-forward.gen.h +0 -53
  419. package/cpp/ggml/src/ggml-virtgpu/virtgpu-shm.cpp +0 -98
  420. package/cpp/ggml/src/ggml-virtgpu/virtgpu-shm.h +0 -23
  421. package/cpp/ggml/src/ggml-virtgpu/virtgpu-utils.cpp +0 -179
  422. package/cpp/ggml/src/ggml-virtgpu/virtgpu-utils.h +0 -86
  423. package/cpp/ggml/src/ggml-virtgpu/virtgpu.cpp +0 -544
  424. package/cpp/ggml/src/ggml-virtgpu/virtgpu.h +0 -117
  425. package/cpp/ggml/src/ggml-webgpu/CMakeLists.txt +0 -80
  426. package/cpp/ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp +0 -1231
  427. package/cpp/ggml/src/ggml-webgpu/ggml-webgpu.cpp +0 -3150
  428. package/cpp/ggml/src/ggml-webgpu/pre_wgsl.hpp +0 -778
  429. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/argmax.wgsl +0 -72
  430. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/argsort.wgsl +0 -106
  431. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/argsort_merge.wgsl +0 -134
  432. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/binary.wgsl +0 -107
  433. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl +0 -923
  434. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/cpy.tmpl.wgsl +0 -107
  435. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/cumsum.wgsl +0 -66
  436. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/embed_wgsl.py +0 -182
  437. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn.wgsl +0 -636
  438. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/get_rows.wgsl +0 -668
  439. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/glu.tmpl.wgsl +0 -323
  440. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/memset.wgsl +0 -40
  441. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat.wgsl +0 -713
  442. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_decls.tmpl +0 -103
  443. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_reg_tile.wgsl +0 -138
  444. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_subgroup_matrix.wgsl +0 -188
  445. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl +0 -194
  446. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/pad.wgsl +0 -86
  447. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/rms_norm.wgsl +0 -123
  448. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/rope.tmpl.wgsl +0 -295
  449. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/scale.wgsl +0 -63
  450. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/set_rows.wgsl +0 -109
  451. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/soft_max.tmpl.wgsl +0 -345
  452. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/sum_rows.wgsl +0 -55
  453. package/cpp/ggml/src/ggml-webgpu/wgsl-shaders/unary.wgsl +0 -193
  454. package/cpp/ggml/src/ggml-zdnn/CMakeLists.txt +0 -36
  455. package/cpp/ggml/src/ggml-zdnn/common.hpp +0 -59
  456. package/cpp/ggml/src/ggml-zdnn/ggml-zdnn.cpp +0 -633
  457. package/cpp/ggml/src/ggml-zdnn/mmf.cpp +0 -80
  458. package/cpp/ggml/src/ggml-zdnn/mmf.hpp +0 -12
  459. package/cpp/ggml/src/ggml-zdnn/utils.cpp +0 -79
  460. package/cpp/ggml/src/ggml-zdnn/utils.hpp +0 -19
  461. package/cpp/ggml/src/ggml-zendnn/CMakeLists.txt +0 -92
  462. package/cpp/ggml/src/ggml-zendnn/ggml-zendnn.cpp +0 -469
  463. package/cpp/mtmd/README.md +0 -63
  464. package/cpp/mtmd/legacy-models/convert_image_encoder_to_gguf.py +0 -412
  465. package/cpp/mtmd/legacy-models/glmedge-convert-image-encoder-to-gguf.py +0 -280
  466. package/cpp/mtmd/legacy-models/glmedge-surgery.py +0 -33
  467. package/cpp/mtmd/legacy-models/llava_surgery.py +0 -38
  468. package/cpp/mtmd/legacy-models/llava_surgery_v2.py +0 -180
  469. package/cpp/mtmd/legacy-models/minicpmv-convert-image-encoder-to-gguf.py +0 -892
  470. package/cpp/mtmd/legacy-models/minicpmv-surgery.py +0 -47
  471. package/cpp/mtmd/mtmd-cli.cpp +0 -437
  472. package/cpp/mtmd/requirements.txt +0 -5
  473. package/cpp/mtmd/test-1.jpeg +0 -0
  474. package/cpp/mtmd/test-2.mp3 +0 -0
  475. package/cpp/mtmd/tests.sh +0 -192
  476. package/src/download-adapter.ts +0 -17
  477. /package/cpp/common/jinja/{string.h → jinja_string.h} +0 -0
@@ -0,0 +1,1412 @@
1
+ /*
2
+ * LocalLLM.cpp — JNI bridge for local-llm-rn (Android).
3
+ *
4
+ * Mirrors ios/LocalLLM.mm exactly: same handle maps, same hilum_llm.h C API
5
+ * calls, same stream cancellation pattern. The only differences are JNI
6
+ * marshalling instead of Obj-C types, and Android-specific device capabilities.
7
+ */
8
+
9
+ #include <jni.h>
10
+ #include <android/log.h>
11
+
12
+ #include <string>
13
+ #include <memory>
14
+ #include <unordered_map>
15
+ #include <mutex>
16
+ #include <atomic>
17
+ #include <vector>
18
+ #include <cstring>
19
+ #include <cstdlib>
20
+ #include <fstream>
21
+ #include <sstream>
22
+ #include <chrono>
23
+
24
+ #include "hilum_llm.h"
25
+ #include "ggml.h"
26
+ #include "ggml-backend.h"
27
+
28
+ #define TAG "LocalLLM"
29
+ #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
30
+ #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
31
+
32
+ // ── UUID generation ──────────────────────────────────────────────────────────
33
+
34
+ static std::string generate_uuid() {
35
+ static std::atomic<uint64_t> counter{0};
36
+ // Simple pseudo-UUID: timestamp + counter
37
+ auto now = std::chrono::steady_clock::now().time_since_epoch();
38
+ auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
39
+ uint64_t c = counter.fetch_add(1);
40
+ char buf[64];
41
+ snprintf(buf, sizeof(buf), "%llx-%llx",
42
+ (unsigned long long)ms, (unsigned long long)c);
43
+ return buf;
44
+ }
45
+
46
+ // ── Handle maps ──────────────────────────────────────────────────────────────
47
+
48
+ static std::mutex g_mutex;
49
+
50
+ static std::unordered_map<std::string, hilum_model *> g_models;
51
+ static std::unordered_map<std::string, hilum_context *> g_contexts;
52
+ static std::unordered_map<std::string, hilum_mtmd *> g_mtmd_contexts;
53
+ static std::unordered_map<std::string, hilum_emb_ctx *> g_emb_contexts;
54
+
55
+ using ModelOwner = std::shared_ptr<hilum_model>;
56
+ static std::unordered_map<std::string, ModelOwner> g_model_owners;
57
+ static std::unordered_map<std::string, std::vector<ModelOwner>> g_context_model_owners;
58
+ static std::unordered_map<std::string, ModelOwner> g_mtmd_model_owners;
59
+ static std::unordered_map<std::string, ModelOwner> g_emb_model_owners;
60
+
61
+ // ── Log state ────────────────────────────────────────────────────────────────
62
+
63
+ static std::atomic<bool> g_log_events_enabled{false};
64
+ static JavaVM *g_jvm = nullptr;
65
+ static jobject g_module_ref = nullptr; // weak global ref
66
+ static std::mutex g_log_mutex;
67
+
68
+ // ── JNI helpers ──────────────────────────────────────────────────────────────
69
+
70
+ static JNIEnv *get_jni_env(JavaVM *jvm, bool &detach) {
71
+ detach = false;
72
+ if (!jvm) {
73
+ LOGE("Cannot access JNI environment: JavaVM is null");
74
+ return nullptr;
75
+ }
76
+
77
+ JNIEnv *env = nullptr;
78
+ const jint status = jvm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
79
+ if (status == JNI_OK) return env;
80
+ if (status != JNI_EDETACHED) {
81
+ LOGE("Cannot access JNI environment: GetEnv returned %d", status);
82
+ return nullptr;
83
+ }
84
+ if (jvm->AttachCurrentThread(&env, nullptr) != JNI_OK) {
85
+ LOGE("Cannot access JNI environment: AttachCurrentThread failed");
86
+ return nullptr;
87
+ }
88
+
89
+ detach = true;
90
+ return env;
91
+ }
92
+
93
+ static std::string jstring_to_std(JNIEnv *env, jstring jstr) {
94
+ if (!jstr) return "";
95
+ const char *chars = env->GetStringUTFChars(jstr, nullptr);
96
+ std::string result(chars);
97
+ env->ReleaseStringUTFChars(jstr, chars);
98
+ return result;
99
+ }
100
+
101
+ static jstring std_to_jstring(JNIEnv *env, const std::string &str) {
102
+ return env->NewStringUTF(str.c_str());
103
+ }
104
+
105
+ static std::string get_string_from_map(JNIEnv *env, jobject map, const char *key) {
106
+ jclass mapClass = env->GetObjectClass(map);
107
+ jmethodID getId = env->GetMethodID(mapClass, "get",
108
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
109
+ jstring jkey = env->NewStringUTF(key);
110
+ jobject value = env->CallObjectMethod(map, getId, jkey);
111
+ env->DeleteLocalRef(jkey);
112
+ env->DeleteLocalRef(mapClass);
113
+ if (!value) return "";
114
+ jclass strClass = env->FindClass("java/lang/String");
115
+ if (env->IsInstanceOf(value, strClass)) {
116
+ std::string result = jstring_to_std(env, (jstring)value);
117
+ env->DeleteLocalRef(strClass);
118
+ env->DeleteLocalRef(value);
119
+ return result;
120
+ }
121
+ env->DeleteLocalRef(strClass);
122
+ env->DeleteLocalRef(value);
123
+ return "";
124
+ }
125
+
126
+ static bool has_key(JNIEnv *env, jobject map, const char *key) {
127
+ jclass mapClass = env->GetObjectClass(map);
128
+ jmethodID containsKey = env->GetMethodID(mapClass, "containsKey",
129
+ "(Ljava/lang/Object;)Z");
130
+ jstring jkey = env->NewStringUTF(key);
131
+ jboolean result = env->CallBooleanMethod(map, containsKey, jkey);
132
+ env->DeleteLocalRef(jkey);
133
+ env->DeleteLocalRef(mapClass);
134
+ return result;
135
+ }
136
+
137
+ static int get_int_from_map(JNIEnv *env, jobject map, const char *key, int defaultVal) {
138
+ if (!has_key(env, map, key)) return defaultVal;
139
+ jclass mapClass = env->GetObjectClass(map);
140
+ jmethodID getId = env->GetMethodID(mapClass, "get",
141
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
142
+ jstring jkey = env->NewStringUTF(key);
143
+ jobject value = env->CallObjectMethod(map, getId, jkey);
144
+ env->DeleteLocalRef(jkey);
145
+ env->DeleteLocalRef(mapClass);
146
+ if (!value) return defaultVal;
147
+ jclass numClass = env->FindClass("java/lang/Number");
148
+ if (env->IsInstanceOf(value, numClass)) {
149
+ jmethodID intValue = env->GetMethodID(numClass, "intValue", "()I");
150
+ int result = env->CallIntMethod(value, intValue);
151
+ env->DeleteLocalRef(numClass);
152
+ env->DeleteLocalRef(value);
153
+ return result;
154
+ }
155
+ env->DeleteLocalRef(numClass);
156
+ env->DeleteLocalRef(value);
157
+ return defaultVal;
158
+ }
159
+
160
+ static float get_float_from_map(JNIEnv *env, jobject map, const char *key, float defaultVal) {
161
+ if (!has_key(env, map, key)) return defaultVal;
162
+ jclass mapClass = env->GetObjectClass(map);
163
+ jmethodID getId = env->GetMethodID(mapClass, "get",
164
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
165
+ jstring jkey = env->NewStringUTF(key);
166
+ jobject value = env->CallObjectMethod(map, getId, jkey);
167
+ env->DeleteLocalRef(jkey);
168
+ env->DeleteLocalRef(mapClass);
169
+ if (!value) return defaultVal;
170
+ jclass numClass = env->FindClass("java/lang/Number");
171
+ if (env->IsInstanceOf(value, numClass)) {
172
+ jmethodID floatValue = env->GetMethodID(numClass, "floatValue", "()F");
173
+ float result = env->CallFloatMethod(value, floatValue);
174
+ env->DeleteLocalRef(numClass);
175
+ env->DeleteLocalRef(value);
176
+ return result;
177
+ }
178
+ env->DeleteLocalRef(numClass);
179
+ env->DeleteLocalRef(value);
180
+ return defaultVal;
181
+ }
182
+
183
+ static bool get_bool_from_map(JNIEnv *env, jobject map, const char *key, bool defaultVal) {
184
+ if (!has_key(env, map, key)) return defaultVal;
185
+ jclass mapClass = env->GetObjectClass(map);
186
+ jmethodID getId = env->GetMethodID(mapClass, "get",
187
+ "(Ljava/lang/Object;)Ljava/lang/Object;");
188
+ jstring jkey = env->NewStringUTF(key);
189
+ jobject value = env->CallObjectMethod(map, getId, jkey);
190
+ env->DeleteLocalRef(jkey);
191
+ env->DeleteLocalRef(mapClass);
192
+ if (!value) return defaultVal;
193
+ jclass boolClass = env->FindClass("java/lang/Boolean");
194
+ if (env->IsInstanceOf(value, boolClass)) {
195
+ jmethodID boolValue = env->GetMethodID(boolClass, "booleanValue", "()Z");
196
+ bool result = env->CallBooleanMethod(value, boolValue);
197
+ env->DeleteLocalRef(boolClass);
198
+ env->DeleteLocalRef(value);
199
+ return result;
200
+ }
201
+ env->DeleteLocalRef(boolClass);
202
+ env->DeleteLocalRef(value);
203
+ return defaultVal;
204
+ }
205
+
206
+ // ── ReadableArray helpers ────────────────────────────────────────────────────
207
+
208
+ static std::vector<int32_t> jarray_to_int_vec(JNIEnv *env, jobject array) {
209
+ std::vector<int32_t> result;
210
+ if (!array) return result;
211
+
212
+ jclass listClass = env->FindClass("java/util/List");
213
+ jmethodID sizeMethod = env->GetMethodID(listClass, "size", "()I");
214
+ jmethodID getMethod = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
215
+
216
+ int size = env->CallIntMethod(array, sizeMethod);
217
+ result.reserve(size);
218
+
219
+ jclass numClass = env->FindClass("java/lang/Number");
220
+ jmethodID intValue = env->GetMethodID(numClass, "intValue", "()I");
221
+
222
+ for (int i = 0; i < size; i++) {
223
+ jobject elem = env->CallObjectMethod(array, getMethod, i);
224
+ if (elem && env->IsInstanceOf(elem, numClass)) {
225
+ result.push_back(env->CallIntMethod(elem, intValue));
226
+ }
227
+ if (elem) env->DeleteLocalRef(elem);
228
+ }
229
+
230
+ env->DeleteLocalRef(listClass);
231
+ env->DeleteLocalRef(numClass);
232
+ return result;
233
+ }
234
+
235
+ // ── Gen params helper (mirrors iOS parse_gen_params) ─────────────────────────
236
+
237
+ struct GenContext {
238
+ hilum_gen_params params;
239
+ std::string grammar;
240
+ std::string grammar_root;
241
+
242
+ void finalize() {
243
+ params.grammar = grammar.empty() ? nullptr : grammar.c_str();
244
+ params.grammar_root = grammar_root.empty() ? nullptr : grammar_root.c_str();
245
+ }
246
+ };
247
+
248
+ static GenContext parse_gen_context(JNIEnv *env, jobject options) {
249
+ GenContext gc;
250
+ gc.params = hilum_gen_default_params();
251
+
252
+ if (!options) return gc;
253
+
254
+ gc.params.max_tokens = get_int_from_map(env, options, "max_tokens", gc.params.max_tokens);
255
+ gc.params.temperature = get_float_from_map(env, options, "temperature", gc.params.temperature);
256
+ gc.params.top_p = get_float_from_map(env, options, "top_p", gc.params.top_p);
257
+ gc.params.top_k = get_int_from_map(env, options, "top_k", gc.params.top_k);
258
+ gc.params.repeat_penalty = get_float_from_map(env, options, "repeat_penalty", gc.params.repeat_penalty);
259
+ gc.params.frequency_penalty = get_float_from_map(env, options, "frequency_penalty", gc.params.frequency_penalty);
260
+ gc.params.presence_penalty = get_float_from_map(env, options, "presence_penalty", gc.params.presence_penalty);
261
+ gc.params.seed = (uint32_t)get_int_from_map(env, options, "seed", (int)gc.params.seed);
262
+ gc.params.n_past = get_int_from_map(env, options, "n_past", gc.params.n_past);
263
+
264
+ std::string gram = get_string_from_map(env, options, "grammar");
265
+ if (!gram.empty()) gc.grammar = gram;
266
+ std::string gram_root = get_string_from_map(env, options, "grammar_root");
267
+ if (!gram_root.empty()) gc.grammar_root = gram_root;
268
+
269
+ gc.finalize();
270
+ return gc;
271
+ }
272
+
273
+ // ── Base64 decoding ──────────────────────────────────────────────────────────
274
+
275
+ static std::vector<uint8_t> decode_base64(JNIEnv *env, jstring jb64) {
276
+ std::string b64 = jstring_to_std(env, jb64);
277
+ if (b64.empty()) return {};
278
+
279
+ jclass base64Class = env->FindClass("android/util/Base64");
280
+ jmethodID decodeMethod = env->GetStaticMethodID(base64Class, "decode",
281
+ "(Ljava/lang/String;I)[B");
282
+ jbyteArray decoded = (jbyteArray)env->CallStaticObjectMethod(
283
+ base64Class, decodeMethod, jb64, 0 /* DEFAULT */);
284
+ env->DeleteLocalRef(base64Class);
285
+
286
+ if (!decoded) return {};
287
+
288
+ jsize len = env->GetArrayLength(decoded);
289
+ std::vector<uint8_t> result(len);
290
+ env->GetByteArrayRegion(decoded, 0, len, reinterpret_cast<jbyte *>(result.data()));
291
+ env->DeleteLocalRef(decoded);
292
+ return result;
293
+ }
294
+
295
+ // ── JNI callback to Kotlin ───────────────────────────────────────────────────
296
+
297
+ static void call_kotlin_method(JNIEnv *env, jobject module, const char *method,
298
+ const char *sig, ...) {
299
+ jclass cls = env->GetObjectClass(module);
300
+ jmethodID mid = env->GetMethodID(cls, method, sig);
301
+ env->DeleteLocalRef(cls);
302
+ if (!mid) return;
303
+
304
+ va_list args;
305
+ va_start(args, sig);
306
+ env->CallVoidMethodV(module, mid, args);
307
+ va_end(args);
308
+ }
309
+
310
+ // ── JNI_OnLoad ───────────────────────────────────────────────────────────────
311
+
312
+ JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void * /*reserved*/) {
313
+ g_jvm = vm;
314
+ return JNI_VERSION_1_6;
315
+ }
316
+
317
+ // ── JNI exports ──────────────────────────────────────────────────────────────
318
+
319
+ #define JNI_FN(name) Java_com_hilum_locallm_LocalLLMModule_##name
320
+
321
+ extern "C" {
322
+
323
+ // ── Init (load CPU variant .so files) ────────────────────────────────────────
324
+
325
+ JNIEXPORT void JNICALL
326
+ JNI_FN(nativeInit)(JNIEnv *env, jobject thiz, jstring nativeLibDir) {
327
+ std::string libDir = jstring_to_std(env, nativeLibDir);
328
+ LOGI("Loading backends from: %s", libDir.c_str());
329
+ ggml_backend_load_all_from_path(libDir.c_str());
330
+ }
331
+
332
+ // ── Backend info ─────────────────────────────────────────────────────────────
333
+
334
+ JNIEXPORT jstring JNICALL
335
+ JNI_FN(nativeBackendInfo)(JNIEnv *env, jobject thiz) {
336
+ return std_to_jstring(env, hilum_backend_info());
337
+ }
338
+
339
+ JNIEXPORT jstring JNICALL
340
+ JNI_FN(nativeBackendVersion)(JNIEnv *env, jobject thiz) {
341
+ return std_to_jstring(env, hilum_backend_version());
342
+ }
343
+
344
+ JNIEXPORT jint JNICALL
345
+ JNI_FN(nativeApiVersion)(JNIEnv *env, jobject thiz) {
346
+ return static_cast<jint>(hilum_api_version());
347
+ }
348
+
349
+ // ── Model lifecycle ──────────────────────────────────────────────────────────
350
+
351
+ JNIEXPORT jstring JNICALL
352
+ JNI_FN(nativeLoadModel)(JNIEnv *env, jobject thiz, jstring path, jobject options) {
353
+ std::string pathStr = jstring_to_std(env, path);
354
+
355
+ hilum_model_params params = hilum_model_default_params();
356
+ if (options) {
357
+ params.n_gpu_layers = get_int_from_map(env, options, "n_gpu_layers", params.n_gpu_layers);
358
+ params.use_mmap = get_bool_from_map(env, options, "use_mmap", params.use_mmap);
359
+ }
360
+
361
+ hilum_model *model = nullptr;
362
+ hilum_error err = hilum_model_load(pathStr.c_str(), params, &model);
363
+ if (err != HILUM_OK) {
364
+ LOGE("Model load failed: %s", hilum_error_str(err));
365
+ return std_to_jstring(env, "");
366
+ }
367
+
368
+ std::string modelId = generate_uuid();
369
+ {
370
+ std::lock_guard<std::mutex> lock(g_mutex);
371
+ g_models[modelId] = model;
372
+ g_model_owners[modelId] = ModelOwner(model, hilum_model_free);
373
+ }
374
+ LOGI("Model loaded: %s", modelId.c_str());
375
+ return std_to_jstring(env, modelId);
376
+ }
377
+
378
+ JNIEXPORT jdouble JNICALL
379
+ JNI_FN(nativeGetModelSize)(JNIEnv *env, jobject thiz, jstring modelId) {
380
+ std::string id = jstring_to_std(env, modelId);
381
+ std::lock_guard<std::mutex> lock(g_mutex);
382
+ auto it = g_models.find(id);
383
+ if (it == g_models.end()) return 0.0;
384
+ return (jdouble)hilum_model_size(it->second);
385
+ }
386
+
387
+ JNIEXPORT void JNICALL
388
+ JNI_FN(nativeFreeModel)(JNIEnv *env, jobject thiz, jstring modelId) {
389
+ std::string id = jstring_to_std(env, modelId);
390
+ ModelOwner owner;
391
+ {
392
+ std::lock_guard<std::mutex> lock(g_mutex);
393
+ g_models.erase(id);
394
+ auto it = g_model_owners.find(id);
395
+ if (it != g_model_owners.end()) {
396
+ owner = std::move(it->second);
397
+ g_model_owners.erase(it);
398
+ }
399
+ }
400
+ }
401
+
402
+ // ── Context lifecycle ────────────────────────────────────────────────────────
403
+
404
+ JNIEXPORT jstring JNICALL
405
+ JNI_FN(nativeCreateContext)(JNIEnv *env, jobject thiz, jstring modelId, jobject options) {
406
+ std::string mid = jstring_to_std(env, modelId);
407
+ std::lock_guard<std::mutex> lock(g_mutex);
408
+ auto it = g_models.find(mid);
409
+ if (it == g_models.end()) return std_to_jstring(env, "");
410
+
411
+ std::vector<ModelOwner> owners{g_model_owners[mid]};
412
+ hilum_context_params params = hilum_context_default_params();
413
+ if (options) {
414
+ params.n_ctx = (uint32_t)get_int_from_map(env, options, "n_ctx", params.n_ctx);
415
+ params.n_batch = (uint32_t)get_int_from_map(env, options, "n_batch", params.n_batch);
416
+ params.n_threads = (uint32_t)get_int_from_map(env, options, "n_threads", params.n_threads);
417
+ params.n_seq_max = (uint32_t)get_int_from_map(env, options, "n_seq_max", params.n_seq_max);
418
+ params.flash_attn = get_int_from_map(env, options, "flash_attn_type", params.flash_attn);
419
+ params.type_k = get_int_from_map(env, options, "type_k", params.type_k);
420
+ params.type_v = get_int_from_map(env, options, "type_v", params.type_v);
421
+ params.draft_n_max = get_int_from_map(env, options, "draft_n_max", params.draft_n_max);
422
+ std::string draftId = get_string_from_map(env, options, "draft_model_id");
423
+ if (!draftId.empty()) {
424
+ auto dit = g_models.find(draftId);
425
+ if (dit != g_models.end()) {
426
+ params.draft_model = dit->second;
427
+ owners.push_back(g_model_owners[draftId]);
428
+ }
429
+ }
430
+ }
431
+
432
+ hilum_context *ctx = nullptr;
433
+ hilum_error err = hilum_context_create(it->second, params, &ctx);
434
+ if (err != HILUM_OK) return std_to_jstring(env, "");
435
+
436
+ std::string ctxId = generate_uuid();
437
+ g_contexts[ctxId] = ctx;
438
+ g_context_model_owners[ctxId] = std::move(owners);
439
+ return std_to_jstring(env, ctxId);
440
+ }
441
+
442
+ JNIEXPORT jint JNICALL
443
+ JNI_FN(nativeGetContextSize)(JNIEnv *env, jobject thiz, jstring contextId) {
444
+ std::string id = jstring_to_std(env, contextId);
445
+ std::lock_guard<std::mutex> lock(g_mutex);
446
+ auto it = g_contexts.find(id);
447
+ if (it == g_contexts.end()) return 0;
448
+ return (jint)hilum_context_size(it->second);
449
+ }
450
+
451
+ JNIEXPORT void JNICALL
452
+ JNI_FN(nativeFreeContext)(JNIEnv *env, jobject thiz, jstring contextId) {
453
+ std::string id = jstring_to_std(env, contextId);
454
+ hilum_context *context = nullptr;
455
+ std::vector<ModelOwner> owners;
456
+ {
457
+ std::lock_guard<std::mutex> lock(g_mutex);
458
+ auto it = g_contexts.find(id);
459
+ if (it != g_contexts.end()) {
460
+ context = it->second;
461
+ g_contexts.erase(it);
462
+ }
463
+ auto owner = g_context_model_owners.find(id);
464
+ if (owner != g_context_model_owners.end()) {
465
+ owners = std::move(owner->second);
466
+ g_context_model_owners.erase(owner);
467
+ }
468
+ }
469
+ if (context) hilum_context_free(context);
470
+ }
471
+
472
+ // ── Warmup ───────────────────────────────────────────────────────────────────
473
+
474
+ JNIEXPORT void JNICALL
475
+ JNI_FN(nativeWarmup)(JNIEnv *env, jobject thiz, jstring modelId, jstring contextId) {
476
+ std::string mid = jstring_to_std(env, modelId);
477
+ std::string cid = jstring_to_std(env, contextId);
478
+
479
+ hilum_model *model;
480
+ hilum_context *ctx;
481
+ {
482
+ std::lock_guard<std::mutex> lock(g_mutex);
483
+ auto mi = g_models.find(mid);
484
+ auto ci = g_contexts.find(cid);
485
+ if (mi == g_models.end() || ci == g_contexts.end()) {
486
+ jclass ex = env->FindClass("java/lang/RuntimeException");
487
+ env->ThrowNew(ex, "Model or context not found");
488
+ return;
489
+ }
490
+ model = mi->second;
491
+ ctx = ci->second;
492
+ }
493
+
494
+ hilum_error err = hilum_warmup(model, ctx);
495
+ if (err != HILUM_OK) {
496
+ jclass ex = env->FindClass("java/lang/RuntimeException");
497
+ env->ThrowNew(ex, hilum_error_str(err));
498
+ }
499
+ }
500
+
501
+ // ── KV cache ─────────────────────────────────────────────────────────────────
502
+
503
+ JNIEXPORT void JNICALL
504
+ JNI_FN(nativeKvCacheClear)(JNIEnv *env, jobject thiz, jstring contextId, jint fromPos) {
505
+ std::string id = jstring_to_std(env, contextId);
506
+ std::lock_guard<std::mutex> lock(g_mutex);
507
+ auto it = g_contexts.find(id);
508
+ if (it != g_contexts.end()) {
509
+ hilum_context_kv_clear(it->second, (int32_t)fromPos);
510
+ }
511
+ }
512
+
513
+ // ── Tokenization ─────────────────────────────────────────────────────────────
514
+
515
+ JNIEXPORT jobject JNICALL
516
+ JNI_FN(nativeTokenize)(JNIEnv *env, jobject thiz, jstring modelId, jstring text,
517
+ jboolean addSpecial, jboolean parseSpecial) {
518
+ std::string mid = jstring_to_std(env, modelId);
519
+ std::string txt = jstring_to_std(env, text);
520
+
521
+ jclass arrayListClass = env->FindClass("java/util/ArrayList");
522
+ jmethodID initMethod = env->GetMethodID(arrayListClass, "<init>", "()V");
523
+ jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
524
+ jobject result = env->NewObject(arrayListClass, initMethod);
525
+
526
+ std::lock_guard<std::mutex> lock(g_mutex);
527
+ auto it = g_models.find(mid);
528
+ if (it == g_models.end()) {
529
+ env->DeleteLocalRef(arrayListClass);
530
+ return result;
531
+ }
532
+
533
+ int32_t n = hilum_tokenize(it->second, txt.c_str(), (int32_t)txt.size(),
534
+ nullptr, 0, addSpecial, parseSpecial);
535
+ if (n >= 0) {
536
+ env->DeleteLocalRef(arrayListClass);
537
+ return result;
538
+ }
539
+
540
+ int32_t n_tokens = -n;
541
+ std::vector<int32_t> tokens(n_tokens);
542
+ n = hilum_tokenize(it->second, txt.c_str(), (int32_t)txt.size(),
543
+ tokens.data(), n_tokens, addSpecial, parseSpecial);
544
+ if (n < 0) {
545
+ env->DeleteLocalRef(arrayListClass);
546
+ return result;
547
+ }
548
+
549
+ jclass intClass = env->FindClass("java/lang/Integer");
550
+ jmethodID valueOf = env->GetStaticMethodID(intClass, "valueOf", "(I)Ljava/lang/Integer;");
551
+ for (int i = 0; i < n; i++) {
552
+ jobject intObj = env->CallStaticObjectMethod(intClass, valueOf, tokens[i]);
553
+ env->CallBooleanMethod(result, addMethod, intObj);
554
+ env->DeleteLocalRef(intObj);
555
+ }
556
+ env->DeleteLocalRef(intClass);
557
+ env->DeleteLocalRef(arrayListClass);
558
+ return result;
559
+ }
560
+
561
+ JNIEXPORT jstring JNICALL
562
+ JNI_FN(nativeDetokenize)(JNIEnv *env, jobject thiz, jstring modelId, jobject tokens) {
563
+ std::string mid = jstring_to_std(env, modelId);
564
+ std::vector<int32_t> tok_vec = jarray_to_int_vec(env, tokens);
565
+
566
+ std::lock_guard<std::mutex> lock(g_mutex);
567
+ auto it = g_models.find(mid);
568
+ if (it == g_models.end()) return std_to_jstring(env, "");
569
+
570
+ std::vector<char> buf(tok_vec.size() * 16 + 256);
571
+ int32_t n = hilum_detokenize(it->second, tok_vec.data(), (int32_t)tok_vec.size(),
572
+ buf.data(), (int32_t)buf.size());
573
+ if (n < 0) {
574
+ buf.resize(-n);
575
+ n = hilum_detokenize(it->second, tok_vec.data(), (int32_t)tok_vec.size(),
576
+ buf.data(), (int32_t)buf.size());
577
+ }
578
+ if (n <= 0) return std_to_jstring(env, "");
579
+ return env->NewStringUTF(std::string(buf.data(), n).c_str());
580
+ }
581
+
582
+ JNIEXPORT jstring JNICALL
583
+ JNI_FN(nativeApplyChatTemplate)(JNIEnv *env, jobject thiz, jstring modelId,
584
+ jstring messagesJson, jboolean addAssistant) {
585
+ std::string mid = jstring_to_std(env, modelId);
586
+ std::string json = jstring_to_std(env, messagesJson);
587
+
588
+ std::lock_guard<std::mutex> lock(g_mutex);
589
+ auto it = g_models.find(mid);
590
+ if (it == g_models.end()) return std_to_jstring(env, "");
591
+
592
+ std::vector<char> buf(json.size() * 4 + 256);
593
+ int32_t len = hilum_chat_template(it->second, json.c_str(), addAssistant,
594
+ buf.data(), (int32_t)buf.size());
595
+ if (len <= 0) {
596
+ if (len < 0) {
597
+ buf.resize(-len + 1);
598
+ len = hilum_chat_template(it->second, json.c_str(), addAssistant,
599
+ buf.data(), (int32_t)buf.size());
600
+ }
601
+ if (len <= 0) return std_to_jstring(env, "");
602
+ }
603
+ return env->NewStringUTF(std::string(buf.data(), len).c_str());
604
+ }
605
+
606
+ // ── Text inference ───────────────────────────────────────────────────────────
607
+
608
+ JNIEXPORT jstring JNICALL
609
+ JNI_FN(nativeGenerate)(JNIEnv *env, jobject thiz, jstring modelId, jstring contextId,
610
+ jstring prompt, jobject options) {
611
+ std::string mid = jstring_to_std(env, modelId);
612
+ std::string cid = jstring_to_std(env, contextId);
613
+ std::string promptStr = jstring_to_std(env, prompt);
614
+
615
+ hilum_model *model;
616
+ hilum_context *ctx;
617
+ {
618
+ std::lock_guard<std::mutex> lock(g_mutex);
619
+ auto mi = g_models.find(mid);
620
+ auto ci = g_contexts.find(cid);
621
+ if (mi == g_models.end() || ci == g_contexts.end()) {
622
+ return std_to_jstring(env, "");
623
+ }
624
+ model = mi->second;
625
+ ctx = ci->second;
626
+ }
627
+
628
+ GenContext gc = parse_gen_context(env, options);
629
+
630
+ std::vector<char> buf(gc.params.max_tokens * 64 + 1024);
631
+ int32_t generated = 0;
632
+
633
+ hilum_error err = hilum_generate(model, ctx, promptStr.c_str(), gc.params,
634
+ buf.data(), (int32_t)buf.size(), &generated);
635
+ if (err != HILUM_OK) {
636
+ LOGE("Generate failed: %s", hilum_error_str(err));
637
+ return std_to_jstring(env, "");
638
+ }
639
+
640
+ return env->NewStringUTF(buf.data());
641
+ }
642
+
643
+ JNIEXPORT void JNICALL
644
+ JNI_FN(nativeStartStream)(JNIEnv *env, jobject thiz, jstring modelId, jstring contextId,
645
+ jstring prompt, jobject options) {
646
+ std::string mid = jstring_to_std(env, modelId);
647
+ std::string cid = jstring_to_std(env, contextId);
648
+ std::string promptStr = jstring_to_std(env, prompt);
649
+
650
+ hilum_model *model;
651
+ hilum_context *ctx;
652
+ {
653
+ std::lock_guard<std::mutex> lock(g_mutex);
654
+ auto mi = g_models.find(mid);
655
+ auto ci = g_contexts.find(cid);
656
+ if (mi == g_models.end() || ci == g_contexts.end()) {
657
+ // Emit error
658
+ jclass cls = env->GetObjectClass(thiz);
659
+ jmethodID emitMethod = env->GetMethodID(cls, "emitToken",
660
+ "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V");
661
+ jstring jcid = std_to_jstring(env, cid);
662
+ jstring jerr = env->NewStringUTF("Model or context not found");
663
+ env->CallVoidMethod(thiz, emitMethod, jcid, nullptr, JNI_TRUE, jerr);
664
+ env->DeleteLocalRef(jcid);
665
+ env->DeleteLocalRef(jerr);
666
+ env->DeleteLocalRef(cls);
667
+ return;
668
+ }
669
+ model = mi->second;
670
+ ctx = ci->second;
671
+ }
672
+ hilum_cancel_clear(ctx);
673
+
674
+ GenContext gc = parse_gen_context(env, options);
675
+
676
+ // Store module ref for callback
677
+ jobject moduleRef = env->NewGlobalRef(thiz);
678
+
679
+ struct StreamState {
680
+ jobject moduleRef;
681
+ std::string ctxId;
682
+ JavaVM *jvm;
683
+ };
684
+
685
+ StreamState *state = new StreamState{moduleRef, cid, g_jvm};
686
+
687
+ hilum_error err = hilum_generate_stream(model, ctx, promptStr.c_str(), gc.params,
688
+ [](const char *token, int32_t token_len, void *ud) -> bool {
689
+ auto *s = static_cast<StreamState *>(ud);
690
+
691
+ bool detach = false;
692
+ JNIEnv *env = get_jni_env(s->jvm, detach);
693
+ if (!env) return false;
694
+
695
+ jclass cls = env->GetObjectClass(s->moduleRef);
696
+ jmethodID emitMethod = env->GetMethodID(cls, "emitToken",
697
+ "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V");
698
+
699
+ jstring jcid = env->NewStringUTF(s->ctxId.c_str());
700
+ jstring jtok = env->NewStringUTF(std::string(token, token_len).c_str());
701
+ env->CallVoidMethod(s->moduleRef, emitMethod, jcid, jtok, JNI_FALSE, nullptr);
702
+ env->DeleteLocalRef(jcid);
703
+ env->DeleteLocalRef(jtok);
704
+ env->DeleteLocalRef(cls);
705
+
706
+ if (detach) s->jvm->DetachCurrentThread();
707
+ return true;
708
+ }, state);
709
+
710
+ // Emit done
711
+ {
712
+ jclass cls = env->GetObjectClass(thiz);
713
+ jmethodID emitMethod = env->GetMethodID(cls, "emitToken",
714
+ "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V");
715
+ jstring jcid = std_to_jstring(env, cid);
716
+ env->CallVoidMethod(thiz, emitMethod, jcid, nullptr, JNI_TRUE, nullptr);
717
+ env->DeleteLocalRef(jcid);
718
+ env->DeleteLocalRef(cls);
719
+ }
720
+
721
+ env->DeleteGlobalRef(moduleRef);
722
+ delete state;
723
+ }
724
+
725
+ JNIEXPORT void JNICALL
726
+ JNI_FN(nativeStopStream)(JNIEnv *env, jobject thiz, jstring contextId) {
727
+ std::string cid = jstring_to_std(env, contextId);
728
+ std::lock_guard<std::mutex> lock(g_mutex);
729
+ auto ci = g_contexts.find(cid);
730
+ if (ci != g_contexts.end()) {
731
+ hilum_cancel(ci->second);
732
+ }
733
+ }
734
+
735
+ JNIEXPORT jobject JNICALL
736
+ JNI_FN(nativeGetPerf)(JNIEnv *env, jobject thiz, jstring contextId) {
737
+ std::string cid = jstring_to_std(env, contextId);
738
+
739
+ jclass mapClass = env->FindClass("java/util/HashMap");
740
+ jmethodID mapInit = env->GetMethodID(mapClass, "<init>", "()V");
741
+ jmethodID mapPut = env->GetMethodID(mapClass, "put",
742
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
743
+ jobject map = env->NewObject(mapClass, mapInit);
744
+
745
+ jclass doubleClass = env->FindClass("java/lang/Double");
746
+ jmethodID doubleInit = env->GetMethodID(doubleClass, "<init>", "(D)V");
747
+
748
+ hilum_context *ctx = nullptr;
749
+ {
750
+ std::lock_guard<std::mutex> lock(g_mutex);
751
+ auto ci = g_contexts.find(cid);
752
+ if (ci == g_contexts.end()) return map;
753
+ ctx = ci->second;
754
+ }
755
+
756
+ hilum_perf_data perf = hilum_get_perf(ctx);
757
+
758
+ auto putDouble = [&](const char *key, double val) {
759
+ jstring jkey = env->NewStringUTF(key);
760
+ jobject jval = env->NewObject(doubleClass, doubleInit, val);
761
+ env->CallObjectMethod(map, mapPut, jkey, jval);
762
+ env->DeleteLocalRef(jkey);
763
+ env->DeleteLocalRef(jval);
764
+ };
765
+
766
+ putDouble("promptEvalMs", perf.prompt_eval_ms);
767
+ putDouble("generationMs", perf.generation_ms);
768
+ putDouble("promptTokens", (double)perf.prompt_tokens);
769
+ putDouble("generatedTokens", (double)perf.generated_tokens);
770
+ putDouble("promptTokensPerSec", perf.prompt_tokens_per_sec);
771
+ putDouble("generatedTokensPerSec", perf.generated_tokens_per_sec);
772
+
773
+ env->DeleteLocalRef(mapClass);
774
+ env->DeleteLocalRef(doubleClass);
775
+ return map;
776
+ }
777
+
778
+ JNIEXPORT jint JNICALL
779
+ JNI_FN(nativeOptimalThreadCount)(JNIEnv *env, jobject thiz) {
780
+ return (jint)hilum_optimal_thread_count();
781
+ }
782
+
783
+ JNIEXPORT jobject JNICALL
784
+ JNI_FN(nativeBenchmark)(JNIEnv *env, jobject thiz, jstring modelId, jstring contextId,
785
+ jobject options) {
786
+ std::string mid = jstring_to_std(env, modelId);
787
+ std::string cid = jstring_to_std(env, contextId);
788
+
789
+ jclass mapClass = env->FindClass("java/util/HashMap");
790
+ jmethodID mapInit = env->GetMethodID(mapClass, "<init>", "()V");
791
+ jmethodID mapPut = env->GetMethodID(mapClass, "put",
792
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
793
+ jobject map = env->NewObject(mapClass, mapInit);
794
+
795
+ auto putDouble = [&](const char *key, double val) {
796
+ jclass doubleClass = env->FindClass("java/lang/Double");
797
+ jmethodID doubleInit = env->GetMethodID(doubleClass, "<init>", "(D)V");
798
+ jstring jkey = env->NewStringUTF(key);
799
+ jobject jval = env->NewObject(doubleClass, doubleInit, val);
800
+ env->CallObjectMethod(map, mapPut, jkey, jval);
801
+ env->DeleteLocalRef(jkey);
802
+ env->DeleteLocalRef(jval);
803
+ env->DeleteLocalRef(doubleClass);
804
+ };
805
+
806
+ auto putString = [&](const char *key, const char *val) {
807
+ jstring jkey = env->NewStringUTF(key);
808
+ jstring jval = env->NewStringUTF(val);
809
+ env->CallObjectMethod(map, mapPut, jkey, jval);
810
+ env->DeleteLocalRef(jkey);
811
+ env->DeleteLocalRef(jval);
812
+ };
813
+
814
+ hilum_model *model;
815
+ hilum_context *ctx;
816
+ {
817
+ std::lock_guard<std::mutex> lock(g_mutex);
818
+ auto mi = g_models.find(mid);
819
+ auto ci = g_contexts.find(cid);
820
+ if (mi == g_models.end() || ci == g_contexts.end()) {
821
+ env->DeleteLocalRef(mapClass);
822
+ return map;
823
+ }
824
+ model = mi->second;
825
+ ctx = ci->second;
826
+ }
827
+
828
+ hilum_benchmark_params params = hilum_benchmark_default_params();
829
+ params.prompt_tokens = get_int_from_map(env, options, "promptTokens", params.prompt_tokens);
830
+ params.generate_tokens = get_int_from_map(env, options, "generateTokens", params.generate_tokens);
831
+ params.iterations = get_int_from_map(env, options, "iterations", params.iterations);
832
+
833
+ hilum_benchmark_result result{};
834
+ hilum_error err = hilum_benchmark(model, ctx, params, &result);
835
+ if (err != HILUM_OK) {
836
+ putString("error", hilum_error_str(err));
837
+ env->DeleteLocalRef(mapClass);
838
+ return map;
839
+ }
840
+
841
+ putDouble("promptTokensPerSec", result.prompt_tokens_per_sec);
842
+ putDouble("generatedTokensPerSec", result.generated_tokens_per_sec);
843
+ putDouble("ttftMs", result.ttft_ms);
844
+ putDouble("totalMs", result.total_ms);
845
+ putDouble("iterations", (double)result.iterations);
846
+
847
+ env->DeleteLocalRef(mapClass);
848
+ return map;
849
+ }
850
+
851
+ // ── Vision ───────────────────────────────────────────────────────────────────
852
+
853
+ JNIEXPORT jstring JNICALL
854
+ JNI_FN(nativeLoadProjector)(JNIEnv *env, jobject thiz, jstring modelId,
855
+ jstring path, jobject options) {
856
+ std::string mid = jstring_to_std(env, modelId);
857
+ std::string pathStr = jstring_to_std(env, path);
858
+
859
+ std::lock_guard<std::mutex> lock(g_mutex);
860
+ auto it = g_models.find(mid);
861
+ if (it == g_models.end()) return std_to_jstring(env, "");
862
+
863
+ hilum_mtmd_params mparams;
864
+ mparams.use_gpu = get_bool_from_map(env, options, "use_gpu", true);
865
+ mparams.n_threads = (uint32_t)get_int_from_map(env, options, "n_threads", 0);
866
+
867
+ hilum_mtmd *mtmd = nullptr;
868
+ hilum_error err = hilum_mtmd_load(it->second, pathStr.c_str(), mparams, &mtmd);
869
+ if (err != HILUM_OK) return std_to_jstring(env, "");
870
+
871
+ std::string mtmdId = generate_uuid();
872
+ g_mtmd_contexts[mtmdId] = mtmd;
873
+ g_mtmd_model_owners[mtmdId] = g_model_owners[mid];
874
+ return std_to_jstring(env, mtmdId);
875
+ }
876
+
877
+ JNIEXPORT jboolean JNICALL
878
+ JNI_FN(nativeSupportVision)(JNIEnv *env, jobject thiz, jstring mtmdId) {
879
+ std::string id = jstring_to_std(env, mtmdId);
880
+ std::lock_guard<std::mutex> lock(g_mutex);
881
+ auto it = g_mtmd_contexts.find(id);
882
+ if (it == g_mtmd_contexts.end()) return JNI_FALSE;
883
+ return hilum_mtmd_supports_vision(it->second) ? JNI_TRUE : JNI_FALSE;
884
+ }
885
+
886
+ JNIEXPORT void JNICALL
887
+ JNI_FN(nativeFreeMtmdContext)(JNIEnv *env, jobject thiz, jstring mtmdId) {
888
+ std::string id = jstring_to_std(env, mtmdId);
889
+ hilum_mtmd *mtmd = nullptr;
890
+ ModelOwner owner;
891
+ {
892
+ std::lock_guard<std::mutex> lock(g_mutex);
893
+ auto it = g_mtmd_contexts.find(id);
894
+ if (it != g_mtmd_contexts.end()) {
895
+ mtmd = it->second;
896
+ g_mtmd_contexts.erase(it);
897
+ }
898
+ auto modelOwner = g_mtmd_model_owners.find(id);
899
+ if (modelOwner != g_mtmd_model_owners.end()) {
900
+ owner = std::move(modelOwner->second);
901
+ g_mtmd_model_owners.erase(modelOwner);
902
+ }
903
+ }
904
+ if (mtmd) hilum_mtmd_free(mtmd);
905
+ }
906
+
907
+ JNIEXPORT jstring JNICALL
908
+ JNI_FN(nativeGenerateVision)(JNIEnv *env, jobject thiz, jstring modelId,
909
+ jstring contextId, jstring mtmdId, jstring prompt,
910
+ jobjectArray imageBase64s, jobject options) {
911
+ std::string mid = jstring_to_std(env, modelId);
912
+ std::string cid = jstring_to_std(env, contextId);
913
+ std::string vid = jstring_to_std(env, mtmdId);
914
+ std::string promptStr = jstring_to_std(env, prompt);
915
+
916
+ hilum_model *model;
917
+ hilum_context *ctx;
918
+ hilum_mtmd *mctx;
919
+ {
920
+ std::lock_guard<std::mutex> lock(g_mutex);
921
+ auto mi = g_models.find(mid);
922
+ auto ci = g_contexts.find(cid);
923
+ auto vi = g_mtmd_contexts.find(vid);
924
+ if (mi == g_models.end() || ci == g_contexts.end() || vi == g_mtmd_contexts.end()) {
925
+ return std_to_jstring(env, "");
926
+ }
927
+ model = mi->second;
928
+ ctx = ci->second;
929
+ mctx = vi->second;
930
+ }
931
+
932
+ // Decode images
933
+ int n_images = imageBase64s ? env->GetArrayLength(imageBase64s) : 0;
934
+ std::vector<std::vector<uint8_t>> img_data;
935
+ std::vector<hilum_image> images;
936
+ for (int i = 0; i < n_images; i++) {
937
+ jstring jb64 = (jstring)env->GetObjectArrayElement(imageBase64s, i);
938
+ auto data = decode_base64(env, jb64);
939
+ env->DeleteLocalRef(jb64);
940
+ if (!data.empty()) img_data.push_back(std::move(data));
941
+ }
942
+ for (auto &d : img_data) {
943
+ images.push_back({d.data(), d.size()});
944
+ }
945
+
946
+ GenContext gc = parse_gen_context(env, options);
947
+ std::vector<char> buf(gc.params.max_tokens * 64 + 1024);
948
+ int32_t generated = 0;
949
+
950
+ hilum_error err = hilum_generate_vision(model, ctx, mctx, promptStr.c_str(),
951
+ images.data(), (int32_t)images.size(), gc.params,
952
+ buf.data(), (int32_t)buf.size(), &generated);
953
+
954
+ if (err != HILUM_OK) return std_to_jstring(env, "");
955
+ return env->NewStringUTF(buf.data());
956
+ }
957
+
958
+ JNIEXPORT void JNICALL
959
+ JNI_FN(nativeStartStreamVision)(JNIEnv *env, jobject thiz, jstring modelId,
960
+ jstring contextId, jstring mtmdId, jstring prompt,
961
+ jobjectArray imageBase64s, jobject options) {
962
+ std::string mid = jstring_to_std(env, modelId);
963
+ std::string cid = jstring_to_std(env, contextId);
964
+ std::string vid = jstring_to_std(env, mtmdId);
965
+ std::string promptStr = jstring_to_std(env, prompt);
966
+
967
+ hilum_model *model;
968
+ hilum_context *ctx;
969
+ hilum_mtmd *mctx;
970
+ {
971
+ std::lock_guard<std::mutex> lock(g_mutex);
972
+ auto mi = g_models.find(mid);
973
+ auto ci = g_contexts.find(cid);
974
+ auto vi = g_mtmd_contexts.find(vid);
975
+ if (mi == g_models.end() || ci == g_contexts.end() || vi == g_mtmd_contexts.end()) {
976
+ jclass cls = env->GetObjectClass(thiz);
977
+ jmethodID emitMethod = env->GetMethodID(cls, "emitToken",
978
+ "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V");
979
+ jstring jcid = std_to_jstring(env, cid);
980
+ jstring jerr = env->NewStringUTF("Not found");
981
+ env->CallVoidMethod(thiz, emitMethod, jcid, nullptr, JNI_TRUE, jerr);
982
+ env->DeleteLocalRef(jcid);
983
+ env->DeleteLocalRef(jerr);
984
+ env->DeleteLocalRef(cls);
985
+ return;
986
+ }
987
+ model = mi->second;
988
+ ctx = ci->second;
989
+ mctx = vi->second;
990
+ }
991
+ hilum_cancel_clear(ctx);
992
+
993
+ int n_images = imageBase64s ? env->GetArrayLength(imageBase64s) : 0;
994
+ std::vector<std::vector<uint8_t>> img_data;
995
+ std::vector<hilum_image> images;
996
+ for (int i = 0; i < n_images; i++) {
997
+ jstring jb64 = (jstring)env->GetObjectArrayElement(imageBase64s, i);
998
+ auto data = decode_base64(env, jb64);
999
+ env->DeleteLocalRef(jb64);
1000
+ if (!data.empty()) img_data.push_back(std::move(data));
1001
+ }
1002
+ for (auto &d : img_data) {
1003
+ images.push_back({d.data(), d.size()});
1004
+ }
1005
+
1006
+ GenContext gc = parse_gen_context(env, options);
1007
+ jobject moduleRef = env->NewGlobalRef(thiz);
1008
+
1009
+ struct StreamState {
1010
+ jobject moduleRef;
1011
+ std::string ctxId;
1012
+ JavaVM *jvm;
1013
+ };
1014
+ StreamState *state = new StreamState{moduleRef, cid, g_jvm};
1015
+
1016
+ hilum_generate_vision_stream(model, ctx, mctx, promptStr.c_str(),
1017
+ images.data(), (int32_t)images.size(), gc.params,
1018
+ [](const char *token, int32_t token_len, void *ud) -> bool {
1019
+ auto *s = static_cast<StreamState *>(ud);
1020
+
1021
+ bool detach = false;
1022
+ JNIEnv *env = get_jni_env(s->jvm, detach);
1023
+ if (!env) return false;
1024
+
1025
+ jclass cls = env->GetObjectClass(s->moduleRef);
1026
+ jmethodID emitMethod = env->GetMethodID(cls, "emitToken",
1027
+ "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V");
1028
+ jstring jcid = env->NewStringUTF(s->ctxId.c_str());
1029
+ jstring jtok = env->NewStringUTF(std::string(token, token_len).c_str());
1030
+ env->CallVoidMethod(s->moduleRef, emitMethod, jcid, jtok, JNI_FALSE, nullptr);
1031
+ env->DeleteLocalRef(jcid);
1032
+ env->DeleteLocalRef(jtok);
1033
+ env->DeleteLocalRef(cls);
1034
+
1035
+ if (detach) s->jvm->DetachCurrentThread();
1036
+ return true;
1037
+ }, state);
1038
+
1039
+ {
1040
+ jclass cls = env->GetObjectClass(thiz);
1041
+ jmethodID emitMethod = env->GetMethodID(cls, "emitToken",
1042
+ "(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V");
1043
+ jstring jcid = std_to_jstring(env, cid);
1044
+ env->CallVoidMethod(thiz, emitMethod, jcid, nullptr, JNI_TRUE, nullptr);
1045
+ env->DeleteLocalRef(jcid);
1046
+ env->DeleteLocalRef(cls);
1047
+ }
1048
+
1049
+ env->DeleteGlobalRef(moduleRef);
1050
+ delete state;
1051
+ }
1052
+
1053
+ // ── Grammar ──────────────────────────────────────────────────────────────────
1054
+
1055
+ JNIEXPORT jstring JNICALL
1056
+ JNI_FN(nativeJsonSchemaToGrammar)(JNIEnv *env, jobject thiz, jstring schemaJson) {
1057
+ std::string json = jstring_to_std(env, schemaJson);
1058
+ std::vector<char> buf(json.size() * 8 + 4096);
1059
+ int32_t len = hilum_json_schema_to_grammar(json.c_str(), buf.data(), (int32_t)buf.size());
1060
+ if (len <= 0) {
1061
+ if (len < 0) {
1062
+ buf.resize(-len);
1063
+ len = hilum_json_schema_to_grammar(json.c_str(), buf.data(), (int32_t)buf.size());
1064
+ }
1065
+ if (len <= 0) return std_to_jstring(env, "");
1066
+ }
1067
+ return env->NewStringUTF(std::string(buf.data(), len).c_str());
1068
+ }
1069
+
1070
+ // ── Embeddings ───────────────────────────────────────────────────────────────
1071
+
1072
+ JNIEXPORT jint JNICALL
1073
+ JNI_FN(nativeGetEmbeddingDimension)(JNIEnv *env, jobject thiz, jstring modelId) {
1074
+ std::string mid = jstring_to_std(env, modelId);
1075
+ std::lock_guard<std::mutex> lock(g_mutex);
1076
+ auto it = g_models.find(mid);
1077
+ if (it == g_models.end()) return 0;
1078
+ return (jint)hilum_emb_dimension(it->second);
1079
+ }
1080
+
1081
+ JNIEXPORT jstring JNICALL
1082
+ JNI_FN(nativeCreateEmbeddingContext)(JNIEnv *env, jobject thiz, jstring modelId,
1083
+ jobject options) {
1084
+ std::string mid = jstring_to_std(env, modelId);
1085
+ std::lock_guard<std::mutex> lock(g_mutex);
1086
+ auto it = g_models.find(mid);
1087
+ if (it == g_models.end()) return std_to_jstring(env, "");
1088
+
1089
+ hilum_emb_params params;
1090
+ params.n_ctx = (uint32_t)get_int_from_map(env, options, "n_ctx", 0);
1091
+ params.n_batch = (uint32_t)get_int_from_map(env, options, "n_batch", 0);
1092
+ params.n_threads = (uint32_t)get_int_from_map(env, options, "n_threads", 0);
1093
+ params.pooling_type = get_int_from_map(env, options, "pooling_type", -1);
1094
+
1095
+ hilum_emb_ctx *ectx = nullptr;
1096
+ hilum_error err = hilum_emb_context_create(it->second, params, &ectx);
1097
+ if (err != HILUM_OK) return std_to_jstring(env, "");
1098
+
1099
+ std::string ctxId = generate_uuid();
1100
+ g_emb_contexts[ctxId] = ectx;
1101
+ g_emb_model_owners[ctxId] = g_model_owners[mid];
1102
+ return std_to_jstring(env, ctxId);
1103
+ }
1104
+
1105
+ JNIEXPORT void JNICALL
1106
+ JNI_FN(nativeFreeEmbeddingContext)(JNIEnv *env, jobject thiz, jstring contextId) {
1107
+ std::string id = jstring_to_std(env, contextId);
1108
+ hilum_emb_ctx *context = nullptr;
1109
+ ModelOwner owner;
1110
+ {
1111
+ std::lock_guard<std::mutex> lock(g_mutex);
1112
+ auto it = g_emb_contexts.find(id);
1113
+ if (it != g_emb_contexts.end()) {
1114
+ context = it->second;
1115
+ g_emb_contexts.erase(it);
1116
+ }
1117
+ auto modelOwner = g_emb_model_owners.find(id);
1118
+ if (modelOwner != g_emb_model_owners.end()) {
1119
+ owner = std::move(modelOwner->second);
1120
+ g_emb_model_owners.erase(modelOwner);
1121
+ }
1122
+ }
1123
+ if (context) hilum_emb_context_free(context);
1124
+ }
1125
+
1126
+ JNIEXPORT jobject JNICALL
1127
+ JNI_FN(nativeEmbed)(JNIEnv *env, jobject thiz, jstring contextId, jstring modelId,
1128
+ jobject tokens) {
1129
+ std::string cid = jstring_to_std(env, contextId);
1130
+ std::string mid = jstring_to_std(env, modelId);
1131
+ std::vector<int32_t> tok_vec = jarray_to_int_vec(env, tokens);
1132
+
1133
+ jclass arrayListClass = env->FindClass("java/util/ArrayList");
1134
+ jmethodID initMethod = env->GetMethodID(arrayListClass, "<init>", "()V");
1135
+ jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
1136
+ jobject result = env->NewObject(arrayListClass, initMethod);
1137
+
1138
+ std::lock_guard<std::mutex> lock(g_mutex);
1139
+ auto ci = g_emb_contexts.find(cid);
1140
+ auto mi = g_models.find(mid);
1141
+ if (ci == g_emb_contexts.end() || mi == g_models.end()) {
1142
+ env->DeleteLocalRef(arrayListClass);
1143
+ return result;
1144
+ }
1145
+
1146
+ int n_embd = hilum_emb_dimension(mi->second);
1147
+ std::vector<float> emb(n_embd);
1148
+
1149
+ hilum_error err = hilum_embed(ci->second, mi->second, tok_vec.data(),
1150
+ (int32_t)tok_vec.size(), emb.data(), n_embd);
1151
+ if (err != HILUM_OK) {
1152
+ env->DeleteLocalRef(arrayListClass);
1153
+ return result;
1154
+ }
1155
+
1156
+ jclass doubleClass = env->FindClass("java/lang/Double");
1157
+ jmethodID valueOf = env->GetStaticMethodID(doubleClass, "valueOf", "(D)Ljava/lang/Double;");
1158
+ for (int i = 0; i < n_embd; i++) {
1159
+ jobject dObj = env->CallStaticObjectMethod(doubleClass, valueOf, (jdouble)emb[i]);
1160
+ env->CallBooleanMethod(result, addMethod, dObj);
1161
+ env->DeleteLocalRef(dObj);
1162
+ }
1163
+ env->DeleteLocalRef(doubleClass);
1164
+ env->DeleteLocalRef(arrayListClass);
1165
+ return result;
1166
+ }
1167
+
1168
+ JNIEXPORT jobject JNICALL
1169
+ JNI_FN(nativeEmbedBatch)(JNIEnv *env, jobject thiz, jstring contextId, jstring modelId,
1170
+ jobject tokenArrays) {
1171
+ std::string cid = jstring_to_std(env, contextId);
1172
+ std::string mid = jstring_to_std(env, modelId);
1173
+
1174
+ jclass arrayListClass = env->FindClass("java/util/ArrayList");
1175
+ jmethodID initMethod = env->GetMethodID(arrayListClass, "<init>", "()V");
1176
+ jmethodID addMethod = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
1177
+ jobject result = env->NewObject(arrayListClass, initMethod);
1178
+
1179
+ jclass listClass = env->FindClass("java/util/List");
1180
+ jmethodID sizeMethod = env->GetMethodID(listClass, "size", "()I");
1181
+ jmethodID getMethod = env->GetMethodID(listClass, "get", "(I)Ljava/lang/Object;");
1182
+
1183
+ std::lock_guard<std::mutex> lock(g_mutex);
1184
+ auto ci = g_emb_contexts.find(cid);
1185
+ auto mi = g_models.find(mid);
1186
+ if (ci == g_emb_contexts.end() || mi == g_models.end()) {
1187
+ env->DeleteLocalRef(arrayListClass);
1188
+ env->DeleteLocalRef(listClass);
1189
+ return result;
1190
+ }
1191
+
1192
+ int n_seqs = env->CallIntMethod(tokenArrays, sizeMethod);
1193
+ int n_embd = hilum_emb_dimension(mi->second);
1194
+
1195
+ std::vector<std::vector<int32_t>> tok_vecs(n_seqs);
1196
+ std::vector<const int32_t *> tok_ptrs(n_seqs);
1197
+ std::vector<int32_t> tok_counts(n_seqs);
1198
+
1199
+ for (int s = 0; s < n_seqs; s++) {
1200
+ jobject arr = env->CallObjectMethod(tokenArrays, getMethod, s);
1201
+ tok_vecs[s] = jarray_to_int_vec(env, arr);
1202
+ env->DeleteLocalRef(arr);
1203
+ tok_ptrs[s] = tok_vecs[s].data();
1204
+ tok_counts[s] = (int32_t)tok_vecs[s].size();
1205
+ }
1206
+
1207
+ std::vector<std::vector<float>> emb_vecs(n_seqs, std::vector<float>(n_embd));
1208
+ std::vector<float *> emb_ptrs(n_seqs);
1209
+ for (int s = 0; s < n_seqs; s++) emb_ptrs[s] = emb_vecs[s].data();
1210
+
1211
+ hilum_error err = hilum_embed_batch(ci->second, mi->second,
1212
+ tok_ptrs.data(), tok_counts.data(), n_seqs, emb_ptrs.data(), n_embd);
1213
+ if (err != HILUM_OK) {
1214
+ env->DeleteLocalRef(arrayListClass);
1215
+ env->DeleteLocalRef(listClass);
1216
+ return result;
1217
+ }
1218
+
1219
+ jclass doubleClass = env->FindClass("java/lang/Double");
1220
+ jmethodID dblValueOf = env->GetStaticMethodID(doubleClass, "valueOf", "(D)Ljava/lang/Double;");
1221
+ for (int s = 0; s < n_seqs; s++) {
1222
+ jobject vec = env->NewObject(arrayListClass, initMethod);
1223
+ for (int i = 0; i < n_embd; i++) {
1224
+ jobject dObj = env->CallStaticObjectMethod(doubleClass, dblValueOf, (jdouble)emb_vecs[s][i]);
1225
+ env->CallBooleanMethod(vec, addMethod, dObj);
1226
+ env->DeleteLocalRef(dObj);
1227
+ }
1228
+ env->CallBooleanMethod(result, addMethod, vec);
1229
+ env->DeleteLocalRef(vec);
1230
+ }
1231
+ env->DeleteLocalRef(doubleClass);
1232
+ env->DeleteLocalRef(arrayListClass);
1233
+ env->DeleteLocalRef(listClass);
1234
+ return result;
1235
+ }
1236
+
1237
+ // ── Batch inference ──────────────────────────────────────────────────────────
1238
+
1239
+ JNIEXPORT void JNICALL
1240
+ JNI_FN(nativeStartBatch)(JNIEnv *env, jobject thiz, jstring modelId, jstring contextId,
1241
+ jobjectArray prompts, jobject options) {
1242
+ std::string mid = jstring_to_std(env, modelId);
1243
+ std::string cid = jstring_to_std(env, contextId);
1244
+
1245
+ hilum_model *model;
1246
+ hilum_context *ctx;
1247
+ {
1248
+ std::lock_guard<std::mutex> lock(g_mutex);
1249
+ auto mi = g_models.find(mid);
1250
+ auto ci = g_contexts.find(cid);
1251
+ if (mi == g_models.end() || ci == g_contexts.end()) {
1252
+ jclass cls = env->GetObjectClass(thiz);
1253
+ jmethodID emitMethod = env->GetMethodID(cls, "emitBatchToken",
1254
+ "(Ljava/lang/String;ILjava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V");
1255
+ jstring jcid = std_to_jstring(env, cid);
1256
+ jstring jerr = env->NewStringUTF("Not found");
1257
+ env->CallVoidMethod(thiz, emitMethod, jcid, -1, nullptr, JNI_TRUE, nullptr, jerr);
1258
+ env->DeleteLocalRef(jcid);
1259
+ env->DeleteLocalRef(jerr);
1260
+ env->DeleteLocalRef(cls);
1261
+ return;
1262
+ }
1263
+ model = mi->second;
1264
+ ctx = ci->second;
1265
+ }
1266
+ hilum_cancel_clear(ctx);
1267
+
1268
+ int n_seqs = prompts ? env->GetArrayLength(prompts) : 0;
1269
+ std::vector<std::string> prompt_strs(n_seqs);
1270
+ std::vector<const char *> prompt_ptrs(n_seqs);
1271
+ for (int i = 0; i < n_seqs; i++) {
1272
+ jstring jp = (jstring)env->GetObjectArrayElement(prompts, i);
1273
+ prompt_strs[i] = jstring_to_std(env, jp);
1274
+ prompt_ptrs[i] = prompt_strs[i].c_str();
1275
+ env->DeleteLocalRef(jp);
1276
+ }
1277
+
1278
+ GenContext gc = parse_gen_context(env, options);
1279
+ jobject moduleRef = env->NewGlobalRef(thiz);
1280
+
1281
+ struct BatchState {
1282
+ jobject moduleRef;
1283
+ std::string ctxId;
1284
+ JavaVM *jvm;
1285
+ };
1286
+ BatchState *state = new BatchState{moduleRef, cid, g_jvm};
1287
+
1288
+ hilum_error batchErr = hilum_generate_batch(model, ctx, prompt_ptrs.data(), n_seqs, gc.params,
1289
+ [](hilum_batch_event event, void *ud) -> bool {
1290
+ auto *s = static_cast<BatchState *>(ud);
1291
+
1292
+ bool detach = false;
1293
+ JNIEnv *env = get_jni_env(s->jvm, detach);
1294
+ if (!env) return false;
1295
+
1296
+ jclass cls = env->GetObjectClass(s->moduleRef);
1297
+ jmethodID emitMethod = env->GetMethodID(cls, "emitBatchToken",
1298
+ "(Ljava/lang/String;ILjava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V");
1299
+ jstring jcid = env->NewStringUTF(s->ctxId.c_str());
1300
+
1301
+ if (event.done) {
1302
+ jstring reason = event.finish_reason
1303
+ ? env->NewStringUTF(event.finish_reason) : env->NewStringUTF("stop");
1304
+ env->CallVoidMethod(s->moduleRef, emitMethod, jcid, event.seq_index,
1305
+ nullptr, JNI_TRUE, reason, nullptr);
1306
+ env->DeleteLocalRef(reason);
1307
+ } else {
1308
+ jstring jtok = env->NewStringUTF(std::string(event.token, event.token_len).c_str());
1309
+ env->CallVoidMethod(s->moduleRef, emitMethod, jcid, event.seq_index,
1310
+ jtok, JNI_FALSE, nullptr, nullptr);
1311
+ env->DeleteLocalRef(jtok);
1312
+ }
1313
+ env->DeleteLocalRef(jcid);
1314
+ env->DeleteLocalRef(cls);
1315
+
1316
+ if (detach) s->jvm->DetachCurrentThread();
1317
+ return true;
1318
+ }, state);
1319
+ if (batchErr != HILUM_OK) {
1320
+ jclass cls = env->GetObjectClass(thiz);
1321
+ jmethodID emitMethod = env->GetMethodID(cls, "emitBatchToken",
1322
+ "(Ljava/lang/String;ILjava/lang/String;ZLjava/lang/String;Ljava/lang/String;)V");
1323
+ jstring jcid = std_to_jstring(env, cid);
1324
+ jstring jerr = env->NewStringUTF(hilum_error_str(batchErr));
1325
+ env->CallVoidMethod(thiz, emitMethod, jcid, -1, nullptr, JNI_TRUE, nullptr, jerr);
1326
+ env->DeleteLocalRef(jcid);
1327
+ env->DeleteLocalRef(jerr);
1328
+ env->DeleteLocalRef(cls);
1329
+ }
1330
+ env->DeleteGlobalRef(moduleRef);
1331
+ delete state;
1332
+ }
1333
+
1334
+ // ── Quantization ─────────────────────────────────────────────────────────────
1335
+
1336
+ JNIEXPORT void JNICALL
1337
+ JNI_FN(nativeQuantize)(JNIEnv *env, jobject thiz, jstring inputPath,
1338
+ jstring outputPath, jobject options) {
1339
+ std::string inPath = jstring_to_std(env, inputPath);
1340
+ std::string outPath = jstring_to_std(env, outputPath);
1341
+
1342
+ hilum_quantize_params params = hilum_quantize_default_params();
1343
+ if (options) {
1344
+ params.ftype = get_int_from_map(env, options, "ftype", params.ftype);
1345
+ params.nthread = get_int_from_map(env, options, "nthread", params.nthread);
1346
+ params.allow_requantize = get_bool_from_map(env, options, "allow_requantize", params.allow_requantize);
1347
+ params.quantize_output_tensor = get_bool_from_map(env, options, "quantize_output_tensor", params.quantize_output_tensor);
1348
+ params.pure = get_bool_from_map(env, options, "pure", params.pure);
1349
+ }
1350
+
1351
+ hilum_error err = hilum_quantize(inPath.c_str(), outPath.c_str(), params);
1352
+
1353
+ jclass cls = env->GetObjectClass(thiz);
1354
+ jmethodID emitMethod = env->GetMethodID(cls, "emitQuantizeComplete",
1355
+ "(Ljava/lang/String;)V");
1356
+ jstring jerr = (err != HILUM_OK)
1357
+ ? env->NewStringUTF(hilum_error_str(err))
1358
+ : nullptr;
1359
+ env->CallVoidMethod(thiz, emitMethod, jerr);
1360
+ if (jerr) env->DeleteLocalRef(jerr);
1361
+ env->DeleteLocalRef(cls);
1362
+ }
1363
+
1364
+ // ── Logging ──────────────────────────────────────────────────────────────────
1365
+
1366
+ JNIEXPORT void JNICALL
1367
+ JNI_FN(nativeSetLogLevel)(JNIEnv *env, jobject thiz, jint level) {
1368
+ hilum_log_set_level(static_cast<hilum_log_level>(level));
1369
+ }
1370
+
1371
+ JNIEXPORT void JNICALL
1372
+ JNI_FN(nativeEnableLogEvents)(JNIEnv *env, jobject thiz, jboolean enabled) {
1373
+ g_log_events_enabled.store(enabled, std::memory_order_relaxed);
1374
+ if (enabled) {
1375
+ {
1376
+ std::lock_guard<std::mutex> lock(g_log_mutex);
1377
+ if (g_module_ref) {
1378
+ env->DeleteGlobalRef(g_module_ref);
1379
+ }
1380
+ g_module_ref = env->NewGlobalRef(thiz);
1381
+ }
1382
+ hilum_log_set([](hilum_log_level level, const char *text, void *) {
1383
+ if (!g_log_events_enabled.load(std::memory_order_relaxed)) return;
1384
+
1385
+ bool detach = false;
1386
+ JNIEnv *env = get_jni_env(g_jvm, detach);
1387
+ if (!env) return;
1388
+
1389
+ std::lock_guard<std::mutex> lock(g_log_mutex);
1390
+ if (g_module_ref) {
1391
+ jclass cls = env->GetObjectClass(g_module_ref);
1392
+ jmethodID emitMethod = env->GetMethodID(cls, "emitLog",
1393
+ "(ILjava/lang/String;)V");
1394
+ jstring jtext = env->NewStringUTF(text);
1395
+ env->CallVoidMethod(g_module_ref, emitMethod, (jint)level, jtext);
1396
+ env->DeleteLocalRef(jtext);
1397
+ env->DeleteLocalRef(cls);
1398
+ }
1399
+
1400
+ if (detach) g_jvm->DetachCurrentThread();
1401
+ }, nullptr);
1402
+ } else {
1403
+ hilum_log_set(nullptr, nullptr);
1404
+ std::lock_guard<std::mutex> lock(g_log_mutex);
1405
+ if (g_module_ref) {
1406
+ env->DeleteGlobalRef(g_module_ref);
1407
+ g_module_ref = nullptr;
1408
+ }
1409
+ }
1410
+ }
1411
+
1412
+ } // extern "C"