cohere-transcribe 0.1.0

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 (480) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +21 -0
  3. data/LICENSE.txt +201 -0
  4. data/NOTICE +5 -0
  5. data/README.md +265 -0
  6. data/THIRD_PARTY_NOTICES.md +67 -0
  7. data/exe/cohere-transcribe +8 -0
  8. data/exe/cohere-transcribe-doctor +8 -0
  9. data/ext/cohere_transcribe_native/CMakeLists.txt +262 -0
  10. data/ext/cohere_transcribe_native/README.md +26 -0
  11. data/ext/cohere_transcribe_native/audio_abi.cpp +1416 -0
  12. data/ext/cohere_transcribe_native/audio_exports.macos +5 -0
  13. data/ext/cohere_transcribe_native/audio_exports.map +10 -0
  14. data/ext/cohere_transcribe_native/cohere_abi.cpp +1209 -0
  15. data/ext/cohere_transcribe_native/exports.macos +40 -0
  16. data/ext/cohere_transcribe_native/exports.map +45 -0
  17. data/ext/cohere_transcribe_native/extconf.rb +89 -0
  18. data/ext/cohere_transcribe_native/test/abi_smoke.rb +232 -0
  19. data/ext/cohere_transcribe_native/test/audio_matrix_smoke.cpp +121 -0
  20. data/ext/cohere_transcribe_native/test/audio_reliability_smoke.cpp +198 -0
  21. data/ext/cohere_transcribe_native/test/native_abi_reliability_smoke.cpp +186 -0
  22. data/ext/cohere_transcribe_native/test/native_batch_projection_probe.rb +81 -0
  23. data/ext/cohere_transcribe_native/test/native_cancellation_smoke.cpp +194 -0
  24. data/lib/cohere/transcribe/alignment/ATTRIBUTION.md +23 -0
  25. data/lib/cohere/transcribe/alignment/LICENSE.ctc-forced-aligner +407 -0
  26. data/lib/cohere/transcribe/alignment/LICENSE.torchaudio +25 -0
  27. data/lib/cohere/transcribe/alignment/LICENSE.uroman +26 -0
  28. data/lib/cohere/transcribe/alignment/aligner.rb +476 -0
  29. data/lib/cohere/transcribe/alignment/ctc.rb +224 -0
  30. data/lib/cohere/transcribe/alignment/text.rb +237 -0
  31. data/lib/cohere/transcribe/alignment/uroman_data.rb +4950 -0
  32. data/lib/cohere/transcribe/api.rb +173 -0
  33. data/lib/cohere/transcribe/asr/batching.rb +472 -0
  34. data/lib/cohere/transcribe/asr/failure_policy.rb +112 -0
  35. data/lib/cohere/transcribe/asr/native.rb +676 -0
  36. data/lib/cohere/transcribe/audio/ATTRIBUTION.md +8 -0
  37. data/lib/cohere/transcribe/audio/LICENSE.auditok +21 -0
  38. data/lib/cohere/transcribe/audio/decoder.rb +315 -0
  39. data/lib/cohere/transcribe/audio/ffmpeg_native.rb +248 -0
  40. data/lib/cohere/transcribe/audio/segmentation.rb +260 -0
  41. data/lib/cohere/transcribe/cli.rb +727 -0
  42. data/lib/cohere/transcribe/configuration.rb +282 -0
  43. data/lib/cohere/transcribe/constants.rb +14 -0
  44. data/lib/cohere/transcribe/dense_converter.rb +548 -0
  45. data/lib/cohere/transcribe/doctor.rb +576 -0
  46. data/lib/cohere/transcribe/errors.rb +57 -0
  47. data/lib/cohere/transcribe/gguf_writer.rb +268 -0
  48. data/lib/cohere/transcribe/hub.rb +436 -0
  49. data/lib/cohere/transcribe/input.rb +110 -0
  50. data/lib/cohere/transcribe/licenses/crispasr.txt +21 -0
  51. data/lib/cohere/transcribe/loader.rb +128 -0
  52. data/lib/cohere/transcribe/model_identity.rb +440 -0
  53. data/lib/cohere/transcribe/output/publication.rb +1118 -0
  54. data/lib/cohere/transcribe/output/rendering.rb +105 -0
  55. data/lib/cohere/transcribe/output/timing.rb +86 -0
  56. data/lib/cohere/transcribe/python_text.rb +70 -0
  57. data/lib/cohere/transcribe/pytorch_checkpoint.rb +1180 -0
  58. data/lib/cohere/transcribe/runtime/engine.rb +1676 -0
  59. data/lib/cohere/transcribe/runtime/model_provider.rb +390 -0
  60. data/lib/cohere/transcribe/runtime/precision.rb +57 -0
  61. data/lib/cohere/transcribe/runtime/preparation.rb +215 -0
  62. data/lib/cohere/transcribe/runtime/resources.rb +165 -0
  63. data/lib/cohere/transcribe/runtime/word_pipeline.rb +364 -0
  64. data/lib/cohere/transcribe/safetensors.rb +579 -0
  65. data/lib/cohere/transcribe/state/checkpoint.rb +224 -0
  66. data/lib/cohere/transcribe/state/contracts.rb +141 -0
  67. data/lib/cohere/transcribe/state/io.rb +727 -0
  68. data/lib/cohere/transcribe/state/locking.rb +211 -0
  69. data/lib/cohere/transcribe/state/manifest.rb +155 -0
  70. data/lib/cohere/transcribe/state.rb +7 -0
  71. data/lib/cohere/transcribe/types.rb +535 -0
  72. data/lib/cohere/transcribe/vad/ATTRIBUTION.md +14 -0
  73. data/lib/cohere/transcribe/vad/LICENSE.faster-whisper +21 -0
  74. data/lib/cohere/transcribe/vad/LICENSE.silero-vad +21 -0
  75. data/lib/cohere/transcribe/vad/silero.rb +344 -0
  76. data/lib/cohere/transcribe/vad/silero_vad_v6.onnx +0 -0
  77. data/lib/cohere/transcribe/vad/timestamps.rb +219 -0
  78. data/lib/cohere/transcribe/version.rb +7 -0
  79. data/lib/cohere/transcribe.rb +26 -0
  80. data/sig/cohere/transcribe.rbs +250 -0
  81. data/vendor/crispasr/AUTHORS +510 -0
  82. data/vendor/crispasr/LICENSE +21 -0
  83. data/vendor/crispasr/UPSTREAM.md +9 -0
  84. data/vendor/crispasr/VERSION +1 -0
  85. data/vendor/crispasr/ggml/AUTHORS +335 -0
  86. data/vendor/crispasr/ggml/CMakeLists.txt +512 -0
  87. data/vendor/crispasr/ggml/LICENSE +21 -0
  88. data/vendor/crispasr/ggml/README.md +49 -0
  89. data/vendor/crispasr/ggml/cmake/FindNCCL.cmake +36 -0
  90. data/vendor/crispasr/ggml/cmake/GitVars.cmake +22 -0
  91. data/vendor/crispasr/ggml/cmake/common.cmake +50 -0
  92. data/vendor/crispasr/ggml/cmake/ggml-config.cmake.in +191 -0
  93. data/vendor/crispasr/ggml/ggml.pc.in +10 -0
  94. data/vendor/crispasr/ggml/include/ggml-alloc.h +85 -0
  95. data/vendor/crispasr/ggml/include/ggml-backend.h +431 -0
  96. data/vendor/crispasr/ggml/include/ggml-blas.h +25 -0
  97. data/vendor/crispasr/ggml/include/ggml-cann.h +123 -0
  98. data/vendor/crispasr/ggml/include/ggml-cpp.h +39 -0
  99. data/vendor/crispasr/ggml/include/ggml-cpu.h +151 -0
  100. data/vendor/crispasr/ggml/include/ggml-cuda.h +50 -0
  101. data/vendor/crispasr/ggml/include/ggml-hexagon.h +19 -0
  102. data/vendor/crispasr/ggml/include/ggml-metal.h +61 -0
  103. data/vendor/crispasr/ggml/include/ggml-opencl.h +26 -0
  104. data/vendor/crispasr/ggml/include/ggml-openvino.h +37 -0
  105. data/vendor/crispasr/ggml/include/ggml-opt.h +256 -0
  106. data/vendor/crispasr/ggml/include/ggml-rpc.h +35 -0
  107. data/vendor/crispasr/ggml/include/ggml-sycl.h +49 -0
  108. data/vendor/crispasr/ggml/include/ggml-virtgpu.h +14 -0
  109. data/vendor/crispasr/ggml/include/ggml-vulkan.h +29 -0
  110. data/vendor/crispasr/ggml/include/ggml-webgpu.h +19 -0
  111. data/vendor/crispasr/ggml/include/ggml-zdnn.h +17 -0
  112. data/vendor/crispasr/ggml/include/ggml-zendnn.h +22 -0
  113. data/vendor/crispasr/ggml/include/ggml.h +2887 -0
  114. data/vendor/crispasr/ggml/include/gguf.h +204 -0
  115. data/vendor/crispasr/ggml/src/CMakeLists.txt +493 -0
  116. data/vendor/crispasr/ggml/src/ggml-alloc.c +1323 -0
  117. data/vendor/crispasr/ggml/src/ggml-backend-dl.cpp +48 -0
  118. data/vendor/crispasr/ggml/src/ggml-backend-dl.h +44 -0
  119. data/vendor/crispasr/ggml/src/ggml-backend-impl.h +275 -0
  120. data/vendor/crispasr/ggml/src/ggml-backend-meta.cpp +2145 -0
  121. data/vendor/crispasr/ggml/src/ggml-backend-reg.cpp +586 -0
  122. data/vendor/crispasr/ggml/src/ggml-backend.cpp +2437 -0
  123. data/vendor/crispasr/ggml/src/ggml-common.h +1900 -0
  124. data/vendor/crispasr/ggml/src/ggml-cpu/CMakeLists.txt +718 -0
  125. data/vendor/crispasr/ggml/src/ggml-cpu/amx/amx.cpp +249 -0
  126. data/vendor/crispasr/ggml/src/ggml-cpu/amx/amx.h +8 -0
  127. data/vendor/crispasr/ggml/src/ggml-cpu/amx/common.h +115 -0
  128. data/vendor/crispasr/ggml/src/ggml-cpu/amx/mmq.cpp +2512 -0
  129. data/vendor/crispasr/ggml/src/ggml-cpu/amx/mmq.h +10 -0
  130. data/vendor/crispasr/ggml/src/ggml-cpu/arch/arm/cpu-feats.cpp +98 -0
  131. data/vendor/crispasr/ggml/src/ggml-cpu/arch/arm/quants.c +4244 -0
  132. data/vendor/crispasr/ggml/src/ggml-cpu/arch/arm/repack.cpp +5156 -0
  133. data/vendor/crispasr/ggml/src/ggml-cpu/arch/loongarch/quants.c +2158 -0
  134. data/vendor/crispasr/ggml/src/ggml-cpu/arch/powerpc/cpu-feats.cpp +82 -0
  135. data/vendor/crispasr/ggml/src/ggml-cpu/arch/powerpc/quants.c +2304 -0
  136. data/vendor/crispasr/ggml/src/ggml-cpu/arch/riscv/cpu-feats.cpp +38 -0
  137. data/vendor/crispasr/ggml/src/ggml-cpu/arch/riscv/quants.c +4455 -0
  138. data/vendor/crispasr/ggml/src/ggml-cpu/arch/riscv/repack.cpp +1703 -0
  139. data/vendor/crispasr/ggml/src/ggml-cpu/arch/s390/cpu-feats.cpp +50 -0
  140. data/vendor/crispasr/ggml/src/ggml-cpu/arch/s390/quants.c +1465 -0
  141. data/vendor/crispasr/ggml/src/ggml-cpu/arch/wasm/quants.c +1220 -0
  142. data/vendor/crispasr/ggml/src/ggml-cpu/arch/x86/cpu-feats.cpp +327 -0
  143. data/vendor/crispasr/ggml/src/ggml-cpu/arch/x86/quants.c +3970 -0
  144. data/vendor/crispasr/ggml/src/ggml-cpu/arch/x86/repack.cpp +6407 -0
  145. data/vendor/crispasr/ggml/src/ggml-cpu/arch-fallback.h +349 -0
  146. data/vendor/crispasr/ggml/src/ggml-cpu/binary-ops.cpp +154 -0
  147. data/vendor/crispasr/ggml/src/ggml-cpu/binary-ops.h +16 -0
  148. data/vendor/crispasr/ggml/src/ggml-cpu/cmake/FindSIMD.cmake +100 -0
  149. data/vendor/crispasr/ggml/src/ggml-cpu/common.h +95 -0
  150. data/vendor/crispasr/ggml/src/ggml-cpu/ggml-cpu-impl.h +539 -0
  151. data/vendor/crispasr/ggml/src/ggml-cpu/ggml-cpu.c +3791 -0
  152. data/vendor/crispasr/ggml/src/ggml-cpu/ggml-cpu.cpp +703 -0
  153. data/vendor/crispasr/ggml/src/ggml-cpu/hbm.cpp +55 -0
  154. data/vendor/crispasr/ggml/src/ggml-cpu/hbm.h +8 -0
  155. data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kernels.cpp +939 -0
  156. data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kernels.h +90 -0
  157. data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp +1513 -0
  158. data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kleidiai.h +17 -0
  159. data/vendor/crispasr/ggml/src/ggml-cpu/llamafile/sgemm.cpp +4051 -0
  160. data/vendor/crispasr/ggml/src/ggml-cpu/llamafile/sgemm.h +25 -0
  161. data/vendor/crispasr/ggml/src/ggml-cpu/ops.cpp +11662 -0
  162. data/vendor/crispasr/ggml/src/ggml-cpu/ops.h +121 -0
  163. data/vendor/crispasr/ggml/src/ggml-cpu/quants.c +1288 -0
  164. data/vendor/crispasr/ggml/src/ggml-cpu/quants.h +103 -0
  165. data/vendor/crispasr/ggml/src/ggml-cpu/repack.cpp +4836 -0
  166. data/vendor/crispasr/ggml/src/ggml-cpu/repack.h +245 -0
  167. data/vendor/crispasr/ggml/src/ggml-cpu/simd-gemm.h +226 -0
  168. data/vendor/crispasr/ggml/src/ggml-cpu/simd-mappings.h +1329 -0
  169. data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime.cpp +1025 -0
  170. data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime.h +13 -0
  171. data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime1_kernels.cpp +3196 -0
  172. data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime_kernels.h +26 -0
  173. data/vendor/crispasr/ggml/src/ggml-cpu/traits.cpp +36 -0
  174. data/vendor/crispasr/ggml/src/ggml-cpu/traits.h +38 -0
  175. data/vendor/crispasr/ggml/src/ggml-cpu/unary-ops.cpp +336 -0
  176. data/vendor/crispasr/ggml/src/ggml-cpu/unary-ops.h +35 -0
  177. data/vendor/crispasr/ggml/src/ggml-cpu/vec.cpp +681 -0
  178. data/vendor/crispasr/ggml/src/ggml-cpu/vec.h +1606 -0
  179. data/vendor/crispasr/ggml/src/ggml-cuda/CMakeLists.txt +272 -0
  180. data/vendor/crispasr/ggml/src/ggml-cuda/acc.cu +61 -0
  181. data/vendor/crispasr/ggml/src/ggml-cuda/acc.cuh +5 -0
  182. data/vendor/crispasr/ggml/src/ggml-cuda/add-id.cu +58 -0
  183. data/vendor/crispasr/ggml/src/ggml-cuda/add-id.cuh +3 -0
  184. data/vendor/crispasr/ggml/src/ggml-cuda/arange.cu +34 -0
  185. data/vendor/crispasr/ggml/src/ggml-cuda/arange.cuh +5 -0
  186. data/vendor/crispasr/ggml/src/ggml-cuda/argmax.cu +91 -0
  187. data/vendor/crispasr/ggml/src/ggml-cuda/argmax.cuh +3 -0
  188. data/vendor/crispasr/ggml/src/ggml-cuda/argsort.cu +265 -0
  189. data/vendor/crispasr/ggml/src/ggml-cuda/argsort.cuh +19 -0
  190. data/vendor/crispasr/ggml/src/ggml-cuda/binbcast.cu +534 -0
  191. data/vendor/crispasr/ggml/src/ggml-cuda/binbcast.cuh +12 -0
  192. data/vendor/crispasr/ggml/src/ggml-cuda/clamp.cu +45 -0
  193. data/vendor/crispasr/ggml/src/ggml-cuda/clamp.cuh +5 -0
  194. data/vendor/crispasr/ggml/src/ggml-cuda/col2im-1d.cu +81 -0
  195. data/vendor/crispasr/ggml/src/ggml-cuda/col2im-1d.cuh +3 -0
  196. data/vendor/crispasr/ggml/src/ggml-cuda/common.cuh +1489 -0
  197. data/vendor/crispasr/ggml/src/ggml-cuda/concat.cu +204 -0
  198. data/vendor/crispasr/ggml/src/ggml-cuda/concat.cuh +5 -0
  199. data/vendor/crispasr/ggml/src/ggml-cuda/conv-transpose-1d.cu +97 -0
  200. data/vendor/crispasr/ggml/src/ggml-cuda/conv-transpose-1d.cuh +5 -0
  201. data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-dw.cu +161 -0
  202. data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-dw.cuh +5 -0
  203. data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-transpose.cu +115 -0
  204. data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-transpose.cuh +5 -0
  205. data/vendor/crispasr/ggml/src/ggml-cuda/conv2d.cu +166 -0
  206. data/vendor/crispasr/ggml/src/ggml-cuda/conv2d.cuh +5 -0
  207. data/vendor/crispasr/ggml/src/ggml-cuda/convert.cu +892 -0
  208. data/vendor/crispasr/ggml/src/ggml-cuda/convert.cuh +66 -0
  209. data/vendor/crispasr/ggml/src/ggml-cuda/count-equal.cu +64 -0
  210. data/vendor/crispasr/ggml/src/ggml-cuda/count-equal.cuh +5 -0
  211. data/vendor/crispasr/ggml/src/ggml-cuda/cp-async.cuh +57 -0
  212. data/vendor/crispasr/ggml/src/ggml-cuda/cpy-utils.cuh +217 -0
  213. data/vendor/crispasr/ggml/src/ggml-cuda/cpy.cu +581 -0
  214. data/vendor/crispasr/ggml/src/ggml-cuda/cpy.cuh +7 -0
  215. data/vendor/crispasr/ggml/src/ggml-cuda/cross-entropy-loss.cu +177 -0
  216. data/vendor/crispasr/ggml/src/ggml-cuda/cross-entropy-loss.cuh +7 -0
  217. data/vendor/crispasr/ggml/src/ggml-cuda/cumsum.cu +307 -0
  218. data/vendor/crispasr/ggml/src/ggml-cuda/cumsum.cuh +5 -0
  219. data/vendor/crispasr/ggml/src/ggml-cuda/dequantize.cuh +99 -0
  220. data/vendor/crispasr/ggml/src/ggml-cuda/diag.cu +77 -0
  221. data/vendor/crispasr/ggml/src/ggml-cuda/diag.cuh +5 -0
  222. data/vendor/crispasr/ggml/src/ggml-cuda/diagmask.cu +40 -0
  223. data/vendor/crispasr/ggml/src/ggml-cuda/diagmask.cuh +5 -0
  224. data/vendor/crispasr/ggml/src/ggml-cuda/fattn-common.cuh +1212 -0
  225. data/vendor/crispasr/ggml/src/ggml-cuda/fattn-mma-f16.cuh +1860 -0
  226. data/vendor/crispasr/ggml/src/ggml-cuda/fattn-tile.cu +57 -0
  227. data/vendor/crispasr/ggml/src/ggml-cuda/fattn-tile.cuh +1309 -0
  228. data/vendor/crispasr/ggml/src/ggml-cuda/fattn-vec.cuh +600 -0
  229. data/vendor/crispasr/ggml/src/ggml-cuda/fattn-wmma-f16.cu +696 -0
  230. data/vendor/crispasr/ggml/src/ggml-cuda/fattn-wmma-f16.cuh +51 -0
  231. data/vendor/crispasr/ggml/src/ggml-cuda/fattn.cu +620 -0
  232. data/vendor/crispasr/ggml/src/ggml-cuda/fattn.cuh +5 -0
  233. data/vendor/crispasr/ggml/src/ggml-cuda/fill.cu +37 -0
  234. data/vendor/crispasr/ggml/src/ggml-cuda/fill.cuh +3 -0
  235. data/vendor/crispasr/ggml/src/ggml-cuda/gated_delta_net.cu +273 -0
  236. data/vendor/crispasr/ggml/src/ggml-cuda/gated_delta_net.cuh +4 -0
  237. data/vendor/crispasr/ggml/src/ggml-cuda/getrows.cu +332 -0
  238. data/vendor/crispasr/ggml/src/ggml-cuda/getrows.cuh +15 -0
  239. data/vendor/crispasr/ggml/src/ggml-cuda/ggml-cuda.cu +5580 -0
  240. data/vendor/crispasr/ggml/src/ggml-cuda/gla.cu +93 -0
  241. data/vendor/crispasr/ggml/src/ggml-cuda/gla.cuh +3 -0
  242. data/vendor/crispasr/ggml/src/ggml-cuda/im2col.cu +274 -0
  243. data/vendor/crispasr/ggml/src/ggml-cuda/im2col.cuh +6 -0
  244. data/vendor/crispasr/ggml/src/ggml-cuda/mean.cu +75 -0
  245. data/vendor/crispasr/ggml/src/ggml-cuda/mean.cuh +3 -0
  246. data/vendor/crispasr/ggml/src/ggml-cuda/mma.cuh +1333 -0
  247. data/vendor/crispasr/ggml/src/ggml-cuda/mmf.cu +191 -0
  248. data/vendor/crispasr/ggml/src/ggml-cuda/mmf.cuh +908 -0
  249. data/vendor/crispasr/ggml/src/ggml-cuda/mmid.cu +164 -0
  250. data/vendor/crispasr/ggml/src/ggml-cuda/mmid.cuh +5 -0
  251. data/vendor/crispasr/ggml/src/ggml-cuda/mmq.cu +372 -0
  252. data/vendor/crispasr/ggml/src/ggml-cuda/mmq.cuh +4175 -0
  253. data/vendor/crispasr/ggml/src/ggml-cuda/mmvf.cu +862 -0
  254. data/vendor/crispasr/ggml/src/ggml-cuda/mmvf.cuh +14 -0
  255. data/vendor/crispasr/ggml/src/ggml-cuda/mmvq.cu +1161 -0
  256. data/vendor/crispasr/ggml/src/ggml-cuda/mmvq.cuh +16 -0
  257. data/vendor/crispasr/ggml/src/ggml-cuda/norm.cu +756 -0
  258. data/vendor/crispasr/ggml/src/ggml-cuda/norm.cuh +20 -0
  259. data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-adamw.cu +78 -0
  260. data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-adamw.cuh +5 -0
  261. data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-sgd.cu +49 -0
  262. data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-sgd.cuh +5 -0
  263. data/vendor/crispasr/ggml/src/ggml-cuda/out-prod.cu +68 -0
  264. data/vendor/crispasr/ggml/src/ggml-cuda/out-prod.cuh +3 -0
  265. data/vendor/crispasr/ggml/src/ggml-cuda/pad.cu +106 -0
  266. data/vendor/crispasr/ggml/src/ggml-cuda/pad.cuh +5 -0
  267. data/vendor/crispasr/ggml/src/ggml-cuda/pad_reflect_1d.cu +91 -0
  268. data/vendor/crispasr/ggml/src/ggml-cuda/pad_reflect_1d.cuh +5 -0
  269. data/vendor/crispasr/ggml/src/ggml-cuda/pool2d.cu +94 -0
  270. data/vendor/crispasr/ggml/src/ggml-cuda/pool2d.cuh +5 -0
  271. data/vendor/crispasr/ggml/src/ggml-cuda/quantize.cu +443 -0
  272. data/vendor/crispasr/ggml/src/ggml-cuda/quantize.cuh +41 -0
  273. data/vendor/crispasr/ggml/src/ggml-cuda/reduce_rows.cuh +39 -0
  274. data/vendor/crispasr/ggml/src/ggml-cuda/roll.cu +67 -0
  275. data/vendor/crispasr/ggml/src/ggml-cuda/roll.cuh +5 -0
  276. data/vendor/crispasr/ggml/src/ggml-cuda/rope.cu +665 -0
  277. data/vendor/crispasr/ggml/src/ggml-cuda/rope.cuh +9 -0
  278. data/vendor/crispasr/ggml/src/ggml-cuda/scale.cu +34 -0
  279. data/vendor/crispasr/ggml/src/ggml-cuda/scale.cuh +5 -0
  280. data/vendor/crispasr/ggml/src/ggml-cuda/set-rows.cu +330 -0
  281. data/vendor/crispasr/ggml/src/ggml-cuda/set-rows.cuh +7 -0
  282. data/vendor/crispasr/ggml/src/ggml-cuda/set.cu +39 -0
  283. data/vendor/crispasr/ggml/src/ggml-cuda/set.cuh +7 -0
  284. data/vendor/crispasr/ggml/src/ggml-cuda/softcap.cu +34 -0
  285. data/vendor/crispasr/ggml/src/ggml-cuda/softcap.cuh +5 -0
  286. data/vendor/crispasr/ggml/src/ggml-cuda/softmax.cu +472 -0
  287. data/vendor/crispasr/ggml/src/ggml-cuda/softmax.cuh +7 -0
  288. data/vendor/crispasr/ggml/src/ggml-cuda/solve_tri.cu +275 -0
  289. data/vendor/crispasr/ggml/src/ggml-cuda/solve_tri.cuh +3 -0
  290. data/vendor/crispasr/ggml/src/ggml-cuda/ssm-conv.cu +197 -0
  291. data/vendor/crispasr/ggml/src/ggml-cuda/ssm-conv.cuh +3 -0
  292. data/vendor/crispasr/ggml/src/ggml-cuda/ssm-scan.cu +342 -0
  293. data/vendor/crispasr/ggml/src/ggml-cuda/ssm-scan.cuh +3 -0
  294. data/vendor/crispasr/ggml/src/ggml-cuda/sum.cu +41 -0
  295. data/vendor/crispasr/ggml/src/ggml-cuda/sum.cuh +5 -0
  296. data/vendor/crispasr/ggml/src/ggml-cuda/sumrows.cu +43 -0
  297. data/vendor/crispasr/ggml/src/ggml-cuda/sumrows.cuh +4 -0
  298. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_16.cu +5 -0
  299. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_32.cu +6 -0
  300. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_8.cu +11 -0
  301. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_1.cu +10 -0
  302. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu +10 -0
  303. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_4.cu +12 -0
  304. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_16.cu +5 -0
  305. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_32.cu +6 -0
  306. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_4.cu +12 -0
  307. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_8.cu +11 -0
  308. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_1.cu +10 -0
  309. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu +10 -0
  310. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_16.cu +5 -0
  311. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu +10 -0
  312. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_4.cu +12 -0
  313. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_8.cu +11 -0
  314. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_64-ncols2_1.cu +10 -0
  315. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_1.cu +10 -0
  316. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu +10 -0
  317. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_4.cu +12 -0
  318. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_8.cu +11 -0
  319. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq112-dv112.cu +5 -0
  320. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq128-dv128.cu +5 -0
  321. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq256-dv256.cu +5 -0
  322. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq320-dv256.cu +5 -0
  323. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq40-dv40.cu +5 -0
  324. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq512-dv512.cu +5 -0
  325. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq576-dv512.cu +5 -0
  326. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq64-dv64.cu +5 -0
  327. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq72-dv72.cu +5 -0
  328. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq80-dv80.cu +5 -0
  329. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq96-dv96.cu +5 -0
  330. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-bf16.cu +7 -0
  331. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-f16.cu +7 -0
  332. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_0.cu +7 -0
  333. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_1.cu +7 -0
  334. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_0.cu +7 -0
  335. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_1.cu +7 -0
  336. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q8_0.cu +7 -0
  337. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-bf16.cu +7 -0
  338. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-f16.cu +7 -0
  339. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q4_0.cu +7 -0
  340. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q4_1.cu +7 -0
  341. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q5_0.cu +7 -0
  342. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q5_1.cu +7 -0
  343. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q8_0.cu +7 -0
  344. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-bf16.cu +7 -0
  345. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-f16.cu +7 -0
  346. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q4_0.cu +7 -0
  347. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q4_1.cu +7 -0
  348. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q5_0.cu +7 -0
  349. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q5_1.cu +7 -0
  350. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q8_0.cu +7 -0
  351. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-bf16.cu +7 -0
  352. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-f16.cu +7 -0
  353. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q4_0.cu +7 -0
  354. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q4_1.cu +7 -0
  355. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q5_0.cu +7 -0
  356. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q5_1.cu +7 -0
  357. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q8_0.cu +7 -0
  358. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-bf16.cu +7 -0
  359. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-f16.cu +7 -0
  360. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q4_0.cu +7 -0
  361. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q4_1.cu +7 -0
  362. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q5_0.cu +7 -0
  363. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q5_1.cu +7 -0
  364. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q8_0.cu +7 -0
  365. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-bf16.cu +7 -0
  366. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-f16.cu +7 -0
  367. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q4_0.cu +7 -0
  368. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q4_1.cu +7 -0
  369. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q5_0.cu +7 -0
  370. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q5_1.cu +7 -0
  371. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q8_0.cu +7 -0
  372. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-bf16.cu +7 -0
  373. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-f16.cu +7 -0
  374. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q4_0.cu +7 -0
  375. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q4_1.cu +7 -0
  376. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q5_0.cu +7 -0
  377. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q5_1.cu +7 -0
  378. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q8_0.cu +7 -0
  379. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_1.cu +5 -0
  380. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_10.cu +5 -0
  381. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_11.cu +5 -0
  382. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_12.cu +5 -0
  383. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_13.cu +5 -0
  384. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_14.cu +5 -0
  385. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_15.cu +5 -0
  386. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_16.cu +5 -0
  387. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_2.cu +5 -0
  388. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_3.cu +5 -0
  389. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_4.cu +5 -0
  390. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_5.cu +5 -0
  391. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_6.cu +5 -0
  392. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_7.cu +5 -0
  393. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_8.cu +5 -0
  394. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_9.cu +5 -0
  395. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_s.cu +5 -0
  396. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_s.cu +5 -0
  397. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xs.cu +5 -0
  398. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xxs.cu +5 -0
  399. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_s.cu +5 -0
  400. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_xxs.cu +5 -0
  401. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_nl.cu +5 -0
  402. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_xs.cu +5 -0
  403. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-mxfp4.cu +5 -0
  404. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-nvfp4.cu +5 -0
  405. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q1_0.cu +5 -0
  406. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q2_k.cu +5 -0
  407. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q3_k.cu +5 -0
  408. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_0.cu +5 -0
  409. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_1.cu +5 -0
  410. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_k.cu +5 -0
  411. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_0.cu +5 -0
  412. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_1.cu +5 -0
  413. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_k.cu +5 -0
  414. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q6_k.cu +5 -0
  415. data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q8_0.cu +5 -0
  416. data/vendor/crispasr/ggml/src/ggml-cuda/top-k.cu +95 -0
  417. data/vendor/crispasr/ggml/src/ggml-cuda/top-k.cuh +3 -0
  418. data/vendor/crispasr/ggml/src/ggml-cuda/topk-moe.cu +415 -0
  419. data/vendor/crispasr/ggml/src/ggml-cuda/topk-moe.cuh +27 -0
  420. data/vendor/crispasr/ggml/src/ggml-cuda/tri.cu +136 -0
  421. data/vendor/crispasr/ggml/src/ggml-cuda/tri.cuh +5 -0
  422. data/vendor/crispasr/ggml/src/ggml-cuda/tsembd.cu +47 -0
  423. data/vendor/crispasr/ggml/src/ggml-cuda/tsembd.cuh +5 -0
  424. data/vendor/crispasr/ggml/src/ggml-cuda/unary.cu +644 -0
  425. data/vendor/crispasr/ggml/src/ggml-cuda/unary.cuh +116 -0
  426. data/vendor/crispasr/ggml/src/ggml-cuda/upscale.cu +293 -0
  427. data/vendor/crispasr/ggml/src/ggml-cuda/upscale.cuh +5 -0
  428. data/vendor/crispasr/ggml/src/ggml-cuda/vecdotq.cuh +1317 -0
  429. data/vendor/crispasr/ggml/src/ggml-cuda/vendors/cuda.h +28 -0
  430. data/vendor/crispasr/ggml/src/ggml-cuda/vendors/hip.h +306 -0
  431. data/vendor/crispasr/ggml/src/ggml-cuda/vendors/musa.h +148 -0
  432. data/vendor/crispasr/ggml/src/ggml-cuda/wkv.cu +199 -0
  433. data/vendor/crispasr/ggml/src/ggml-cuda/wkv.cuh +7 -0
  434. data/vendor/crispasr/ggml/src/ggml-impl.h +783 -0
  435. data/vendor/crispasr/ggml/src/ggml-metal/CMakeLists.txt +124 -0
  436. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-common.cpp +457 -0
  437. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-common.h +52 -0
  438. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-context.h +41 -0
  439. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-context.m +778 -0
  440. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-device.cpp +2117 -0
  441. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-device.h +299 -0
  442. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-device.m +2093 -0
  443. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-impl.h +1267 -0
  444. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-ops.cpp +5023 -0
  445. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-ops.h +111 -0
  446. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal.cpp +954 -0
  447. data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal.metal +11756 -0
  448. data/vendor/crispasr/ggml/src/ggml-opt.cpp +1094 -0
  449. data/vendor/crispasr/ggml/src/ggml-quants.c +5491 -0
  450. data/vendor/crispasr/ggml/src/ggml-quants.h +112 -0
  451. data/vendor/crispasr/ggml/src/ggml-threading.cpp +12 -0
  452. data/vendor/crispasr/ggml/src/ggml-threading.h +14 -0
  453. data/vendor/crispasr/ggml/src/ggml.c +7925 -0
  454. data/vendor/crispasr/ggml/src/ggml.cpp +26 -0
  455. data/vendor/crispasr/ggml/src/gguf.cpp +1556 -0
  456. data/vendor/crispasr/src/cohere-arch.h +137 -0
  457. data/vendor/crispasr/src/cohere.cpp +5642 -0
  458. data/vendor/crispasr/src/cohere.h +327 -0
  459. data/vendor/crispasr/src/cohere_batch_planner.h +82 -0
  460. data/vendor/crispasr/src/cohere_chunking.h +64 -0
  461. data/vendor/crispasr/src/cohere_decoder_batch_layout.h +60 -0
  462. data/vendor/crispasr/src/cohere_encoder_padded_layout.h +27 -0
  463. data/vendor/crispasr/src/cohere_frontend.cpp +189 -0
  464. data/vendor/crispasr/src/cohere_frontend.h +31 -0
  465. data/vendor/crispasr/src/cohere_ragged_controller.h +149 -0
  466. data/vendor/crispasr/src/cohere_token_renderer.h +181 -0
  467. data/vendor/crispasr/src/core/attention.h +924 -0
  468. data/vendor/crispasr/src/core/audio_chunking.h +97 -0
  469. data/vendor/crispasr/src/core/beam_decode.h +486 -0
  470. data/vendor/crispasr/src/core/cpu_ops.h +135 -0
  471. data/vendor/crispasr/src/core/gguf_loader.cpp +1021 -0
  472. data/vendor/crispasr/src/core/gguf_loader.h +216 -0
  473. data/vendor/crispasr/src/core/gpu_backend_pref.h +119 -0
  474. data/vendor/crispasr/src/core/mel.cpp +519 -0
  475. data/vendor/crispasr/src/core/mel.h +265 -0
  476. data/vendor/crispasr/src/core/ngram_loop_fix.h +173 -0
  477. data/vendor/crispasr/src/core/repetition_loop_guard.h +54 -0
  478. data/vendor/crispasr/src/crispasr_imatrix.cpp +255 -0
  479. data/vendor/crispasr/src/crispasr_imatrix.h +38 -0
  480. metadata +596 -0
@@ -0,0 +1,1021 @@
1
+ // src/core/gguf_loader.cpp — implementation of core_gguf:: helpers.
2
+ // See gguf_loader.h for the interface contract.
3
+
4
+ #include "gguf_loader.h"
5
+
6
+ #include "ggml-backend-impl.h"
7
+ #include "ggml-cpu.h"
8
+ #ifdef GGML_USE_METAL
9
+ #include "ggml-metal.h"
10
+ #endif
11
+
12
+ #include <cerrno>
13
+ #include <cstdarg>
14
+ #include <cstdio>
15
+ #include <cstdlib>
16
+ #include <cstring>
17
+ #include <map>
18
+ #include <mutex>
19
+
20
+ #if defined(_WIN32)
21
+ #include <io.h>
22
+ #ifndef NOMINMAX
23
+ #define NOMINMAX
24
+ #endif
25
+ #include <windows.h>
26
+ #else
27
+ #include <fcntl.h>
28
+ #include <sys/mman.h>
29
+ #include <sys/stat.h>
30
+ #include <unistd.h>
31
+ #endif
32
+
33
+ namespace core_gguf {
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // Pass 1: metadata
37
+ // ---------------------------------------------------------------------------
38
+
39
+ gguf_context* open_metadata(const char* path) {
40
+ gguf_init_params gp = {/*.no_alloc=*/true, /*.ctx=*/nullptr};
41
+ gguf_context* g = gguf_init_from_file(path, gp);
42
+ if (!g) {
43
+ fprintf(stderr, "core_gguf: failed to open '%s' for metadata read\n", path);
44
+ }
45
+ return g;
46
+ }
47
+
48
+ void free_metadata(gguf_context* gctx) {
49
+ if (gctx)
50
+ gguf_free(gctx);
51
+ }
52
+
53
+ // Type-checked scalar readers. The GGUF format stores types explicitly so
54
+ // we can validate; if the file has a mismatched type the reader silently
55
+ // returns the default rather than crashing, matching the existing inline
56
+ // helpers in each model.
57
+
58
+ uint32_t kv_u32(gguf_context* gctx, const char* key, uint32_t default_val) {
59
+ const int k = gguf_find_key(gctx, key);
60
+ if (k < 0)
61
+ return default_val;
62
+ const gguf_type t = gguf_get_kv_type(gctx, k);
63
+ switch (t) {
64
+ case GGUF_TYPE_UINT32:
65
+ return gguf_get_val_u32(gctx, k);
66
+ case GGUF_TYPE_INT32:
67
+ return (uint32_t)gguf_get_val_i32(gctx, k);
68
+ case GGUF_TYPE_UINT64:
69
+ return (uint32_t)gguf_get_val_u64(gctx, k);
70
+ case GGUF_TYPE_INT64:
71
+ return (uint32_t)gguf_get_val_i64(gctx, k);
72
+ case GGUF_TYPE_UINT16:
73
+ return gguf_get_val_u16(gctx, k);
74
+ case GGUF_TYPE_INT16:
75
+ return (uint32_t)gguf_get_val_i16(gctx, k);
76
+ case GGUF_TYPE_UINT8:
77
+ return gguf_get_val_u8(gctx, k);
78
+ case GGUF_TYPE_INT8:
79
+ return (uint32_t)gguf_get_val_i8(gctx, k);
80
+ default:
81
+ return default_val;
82
+ }
83
+ }
84
+
85
+ int32_t kv_i32(gguf_context* gctx, const char* key, int32_t default_val) {
86
+ const int k = gguf_find_key(gctx, key);
87
+ if (k < 0)
88
+ return default_val;
89
+ const gguf_type t = gguf_get_kv_type(gctx, k);
90
+ switch (t) {
91
+ case GGUF_TYPE_INT32:
92
+ return gguf_get_val_i32(gctx, k);
93
+ case GGUF_TYPE_UINT32:
94
+ return (int32_t)gguf_get_val_u32(gctx, k);
95
+ case GGUF_TYPE_INT64:
96
+ return (int32_t)gguf_get_val_i64(gctx, k);
97
+ case GGUF_TYPE_UINT64:
98
+ return (int32_t)gguf_get_val_u64(gctx, k);
99
+ default:
100
+ return default_val;
101
+ }
102
+ }
103
+
104
+ float kv_f32(gguf_context* gctx, const char* key, float default_val) {
105
+ const int k = gguf_find_key(gctx, key);
106
+ if (k < 0)
107
+ return default_val;
108
+ const gguf_type t = gguf_get_kv_type(gctx, k);
109
+ if (t == GGUF_TYPE_FLOAT32)
110
+ return gguf_get_val_f32(gctx, k);
111
+ if (t == GGUF_TYPE_FLOAT64)
112
+ return (float)gguf_get_val_f64(gctx, k);
113
+ return default_val;
114
+ }
115
+
116
+ bool kv_bool(gguf_context* gctx, const char* key, bool default_val) {
117
+ const int k = gguf_find_key(gctx, key);
118
+ if (k < 0)
119
+ return default_val;
120
+ if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_BOOL)
121
+ return default_val;
122
+ return gguf_get_val_bool(gctx, k);
123
+ }
124
+
125
+ std::string kv_str(gguf_context* gctx, const char* key, const char* default_val) {
126
+ const int k = gguf_find_key(gctx, key);
127
+ if (k < 0)
128
+ return default_val ? default_val : "";
129
+ if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_STRING)
130
+ return default_val ? default_val : "";
131
+ const char* s = gguf_get_val_str(gctx, k);
132
+ return s ? std::string(s) : std::string(default_val ? default_val : "");
133
+ }
134
+
135
+ std::vector<std::string> kv_str_array(gguf_context* gctx, const char* key) {
136
+ std::vector<std::string> out;
137
+ const int k = gguf_find_key(gctx, key);
138
+ if (k < 0)
139
+ return out;
140
+ if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_ARRAY)
141
+ return out;
142
+ if (gguf_get_arr_type(gctx, k) != GGUF_TYPE_STRING)
143
+ return out;
144
+ const int n = gguf_get_arr_n(gctx, k);
145
+ out.reserve((size_t)n);
146
+ for (int i = 0; i < n; i++) {
147
+ out.emplace_back(gguf_get_arr_str(gctx, k, i));
148
+ }
149
+ return out;
150
+ }
151
+
152
+ std::vector<float> kv_f32_array(gguf_context* gctx, const char* key) {
153
+ std::vector<float> out;
154
+ const int k = gguf_find_key(gctx, key);
155
+ if (k < 0)
156
+ return out;
157
+ if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_ARRAY)
158
+ return out;
159
+ if (gguf_get_arr_type(gctx, k) != GGUF_TYPE_FLOAT32)
160
+ return out;
161
+ const size_t n = gguf_get_arr_n(gctx, k);
162
+ const float* data = (const float*)gguf_get_arr_data(gctx, k);
163
+ out.assign(data, data + n);
164
+ return out;
165
+ }
166
+
167
+ // ---------------------------------------------------------------------------
168
+ // Pass 2: tensor allocation + weight data copy.
169
+ // ---------------------------------------------------------------------------
170
+
171
+ namespace {
172
+
173
+ // Read a file slice into a backend tensor. Uses mmap on POSIX; falls back
174
+ // to pread/lseek+read when mmap is unavailable (rare in practice).
175
+ //
176
+ // On POSIX the mmap lives for the duration of one load call — we copy via
177
+ // ggml_backend_tensor_set then unmap. No mmap persists past load_weights().
178
+ struct MappedFile {
179
+ int fd = -1;
180
+ void* base = nullptr;
181
+ size_t size = 0;
182
+ bool ok = false;
183
+
184
+ // When `writable` is true, the mapping is created with copy-on-write
185
+ // semantics (POSIX MAP_PRIVATE + PROT_READ|PROT_WRITE / Win32
186
+ // FILE_MAP_COPY). Reads share the file's page cache; writes get a
187
+ // private anonymous duplicate of the touched page. This lets backends
188
+ // that mutate weights post-load (e.g. parakeet's BN-into-conv fold) run
189
+ // unchanged on the zero-copy path without modifying the underlying file.
190
+ explicit MappedFile(const char* path, bool writable = false) {
191
+ #if defined(_WIN32)
192
+ const DWORD page_protect = writable ? PAGE_WRITECOPY : PAGE_READONLY;
193
+ const DWORD view_access = writable ? FILE_MAP_COPY : FILE_MAP_READ;
194
+ HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
195
+ if (hFile == INVALID_HANDLE_VALUE)
196
+ return;
197
+ LARGE_INTEGER fsize;
198
+ if (!GetFileSizeEx(hFile, &fsize)) {
199
+ CloseHandle(hFile);
200
+ return;
201
+ }
202
+ size = (size_t)fsize.QuadPart;
203
+ HANDLE hMap = CreateFileMappingA(hFile, nullptr, page_protect, 0, 0, nullptr);
204
+ CloseHandle(hFile);
205
+ if (!hMap)
206
+ return;
207
+ base = MapViewOfFile(hMap, view_access, 0, 0, 0);
208
+ CloseHandle(hMap);
209
+ if (!base)
210
+ return;
211
+ ok = true;
212
+ #else
213
+ fd = ::open(path, O_RDONLY);
214
+ if (fd < 0)
215
+ return;
216
+ struct stat st;
217
+ if (fstat(fd, &st) != 0) {
218
+ ::close(fd);
219
+ fd = -1;
220
+ return;
221
+ }
222
+ size = (size_t)st.st_size;
223
+ const int prot = writable ? (PROT_READ | PROT_WRITE) : PROT_READ;
224
+ const int flags = writable ? MAP_PRIVATE : MAP_SHARED;
225
+ base = ::mmap(nullptr, size, prot, flags, fd, 0);
226
+ ::close(fd);
227
+ fd = -1;
228
+ if (base == MAP_FAILED) {
229
+ base = nullptr;
230
+ return;
231
+ }
232
+ ok = true;
233
+ #endif
234
+ }
235
+ ~MappedFile() {
236
+ #if defined(_WIN32)
237
+ if (base)
238
+ UnmapViewOfFile(base);
239
+ #else
240
+ if (base)
241
+ ::munmap(base, size);
242
+ #endif
243
+ }
244
+ MappedFile(const MappedFile&) = delete;
245
+ MappedFile& operator=(const MappedFile&) = delete;
246
+
247
+ // Transfer ownership of the mmap region out of the RAII handle so it
248
+ // outlives the destructor. Used by the CRISPASR_GGUF_MMAP=1 path to
249
+ // hand the mapping to a backend buffer that owns it for the model's
250
+ // lifetime.
251
+ void release() {
252
+ base = nullptr;
253
+ size = 0;
254
+ }
255
+ };
256
+
257
+ // PLAN #51a: a CPU backend buffer whose backing memory is an mmap'd file
258
+ // region. On free_buffer the mapping is unmapped — that's the entire
259
+ // reason this buffer type exists. Tensors must be bound with
260
+ // ggml_backend_tensor_alloc(); we do not provide an init_tensor path.
261
+ //
262
+ // We reuse ggml_backend_cpu_buffer_type() so ggml_backend_buffer_is_host()
263
+ // returns true on this buffer (some scheduler paths key off that).
264
+ struct mmap_buffer_ctx {
265
+ void* mmap_base = nullptr; // page-aligned start of the mmap
266
+ size_t mmap_size = 0; // length of the mmap
267
+ void* tensor_base = nullptr; // mmap_base + data_off, 32-byte aligned
268
+ };
269
+
270
+ static void* mmap_buffer_get_base(ggml_backend_buffer_t buffer) {
271
+ GGML_ASSERT(buffer);
272
+ return ((mmap_buffer_ctx*)buffer->context)->tensor_base;
273
+ }
274
+
275
+ static void mmap_buffer_free(ggml_backend_buffer_t buffer) {
276
+ GGML_ASSERT(buffer);
277
+ auto* mctx = (mmap_buffer_ctx*)buffer->context;
278
+ if (mctx->mmap_base) {
279
+ #if defined(_WIN32)
280
+ UnmapViewOfFile(mctx->mmap_base);
281
+ #else
282
+ ::munmap(mctx->mmap_base, mctx->mmap_size);
283
+ #endif
284
+ }
285
+ delete mctx;
286
+ }
287
+
288
+ static void mmap_buffer_memset_tensor(ggml_backend_buffer_t buffer, ggml_tensor* tensor, uint8_t value, size_t offset,
289
+ size_t size) {
290
+ GGML_ASSERT(tensor);
291
+ memset((char*)tensor->data + offset, value, size);
292
+ GGML_UNUSED(buffer);
293
+ }
294
+
295
+ static void mmap_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor* tensor, const void* data, size_t offset,
296
+ size_t size) {
297
+ GGML_ASSERT(tensor);
298
+ memcpy((char*)tensor->data + offset, data, size);
299
+ GGML_UNUSED(buffer);
300
+ }
301
+
302
+ static void mmap_buffer_get_tensor(ggml_backend_buffer_t buffer, const ggml_tensor* tensor, void* data, size_t offset,
303
+ size_t size) {
304
+ GGML_ASSERT(tensor);
305
+ memcpy(data, (const char*)tensor->data + offset, size);
306
+ GGML_UNUSED(buffer);
307
+ }
308
+
309
+ static bool mmap_buffer_cpy_tensor(ggml_backend_buffer_t buffer, const ggml_tensor* src, ggml_tensor* dst) {
310
+ GGML_ASSERT(src);
311
+ if (ggml_backend_buffer_is_host(src->buffer)) {
312
+ memcpy(dst->data, src->data, ggml_nbytes(src));
313
+ return true;
314
+ }
315
+ return false;
316
+ GGML_UNUSED(buffer);
317
+ }
318
+
319
+ static void mmap_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
320
+ auto* mctx = (mmap_buffer_ctx*)buffer->context;
321
+ memset(mctx->tensor_base, value, buffer->size);
322
+ }
323
+
324
+ static const ggml_backend_buffer_i mmap_buffer_iface = {
325
+ /* .free_buffer = */ mmap_buffer_free,
326
+ /* .get_base = */ mmap_buffer_get_base,
327
+ /* .init_tensor = */ nullptr,
328
+ /* .memset_tensor = */ mmap_buffer_memset_tensor,
329
+ /* .set_tensor = */ mmap_buffer_set_tensor,
330
+ /* .get_tensor = */ mmap_buffer_get_tensor,
331
+ /* .set_tensor_2d = */ nullptr,
332
+ /* .get_tensor_2d = */ nullptr,
333
+ /* .cpy_tensor = */ mmap_buffer_cpy_tensor,
334
+ /* .clear = */ mmap_buffer_clear,
335
+ /* .reset = */ nullptr,
336
+ };
337
+
338
+ // PLAN #51a (Metal variant): non-CPU backends use `buffer_from_host_ptr`
339
+ // to wrap our mmap region directly into a backend buffer (e.g. an
340
+ // MTLResourceStorageModeShared MTLBuffer on Apple-Silicon Metal). We
341
+ // CANNOT wrap that inner buffer with our own iface to attach a munmap
342
+ // callback: ggml-metal pierces the iface abstraction and casts
343
+ // `buffer->context` straight to its private `ggml_metal_buffer_t` (see
344
+ // `ggml_metal_get_buffer_id` in ggml-metal-context.m), so any wrapper
345
+ // makes Metal read garbage and emit "tensor 'X' buffer is nil" for
346
+ // every weight — the kokoro Metal gibberish-audio regression.
347
+ //
348
+ // Instead we hand the inner buffer back as-is and track the mmap region
349
+ // in this static side-map. When the buffer is freed elsewhere (model
350
+ // shutdown) the inner backend's free callback releases its device-side
351
+ // reference, but the host mmap stays mapped — Metal's
352
+ // `newBufferWithBytesNoCopy:options:deallocator:nil` doesn't own the
353
+ // host pages, so there's no MTLBuffer-side teardown that could munmap.
354
+ // We deliberately leak the mmap; on macOS the kernel can still evict
355
+ // file-backed pages under pressure (they're not anonymous), and process
356
+ // exit reclaims everything. Address-space-wise this costs nothing past
357
+ // the model's working set, which we'd be holding anyway.
358
+ struct gpu_mmap_handle {
359
+ void* base = nullptr;
360
+ size_t size = 0;
361
+ };
362
+ static std::mutex g_gpu_mmap_mu;
363
+ static std::map<ggml_backend_buffer_t, gpu_mmap_handle> g_gpu_mmap;
364
+
365
+ static void register_gpu_mmap(ggml_backend_buffer_t buf, void* base, size_t size) {
366
+ std::lock_guard<std::mutex> lk(g_gpu_mmap_mu);
367
+ g_gpu_mmap[buf] = {base, size};
368
+ }
369
+ static gpu_mmap_handle lookup_gpu_mmap(ggml_backend_buffer_t buf) {
370
+ std::lock_guard<std::mutex> lk(g_gpu_mmap_mu);
371
+ auto it = g_gpu_mmap.find(buf);
372
+ return it != g_gpu_mmap.end() ? it->second : gpu_mmap_handle{};
373
+ }
374
+
375
+ // Issue #94 (chatterbox-turbo segfault during init on macOS / Apple
376
+ // Silicon): the legacy alloc+copy load path takes 30-60 s for the
377
+ // chatterbox-turbo T3 (658 MB Q8_0) on slow disks and reproducibly
378
+ // fails for some users. The zero-copy mmap path completes the same
379
+ // load in ~5-10 s and uses half the peak RSS. The CPU mmap path has
380
+ // been validated for every backend that goes through this loader
381
+ // (mimo-asr, voxtral, voxtral4b, chatterbox base + turbo, kokoro,
382
+ // qwen3-tts, vibevoice, parakeet, granite, …) since the PLAN #51a
383
+ // rollout in late April; flipping the default after a month of opt-in
384
+ // testing matches llama.cpp's behaviour and resolves the slow-load
385
+ // reports.
386
+ //
387
+ // Opt out with `CRISPASR_GGUF_MMAP=0` for users whose model files live
388
+ // on volumes that may disappear mid-run (network mounts, removable
389
+ // disks); mmap-backed weights SIGBUS if the underlying file vanishes.
390
+ static bool mmap_loader_enabled() {
391
+ const char* v = std::getenv("CRISPASR_GGUF_MMAP");
392
+ if (!v || !*v)
393
+ return true;
394
+ return *v != '0';
395
+ }
396
+
397
+ // PLAN #60c: opt-in preload — page-walk the entire mmap region so every
398
+ // page is resident before we return. Trades cold-start *load* time for
399
+ // cold-start *prefill* time; useful for benchmarking and for users with
400
+ // enough RAM to keep the working set resident. POSIX path uses a 1-byte
401
+ // volatile read per page; Linux MADV_POPULATE_READ would be a cleaner
402
+ // single-syscall version when available.
403
+ static bool preload_enabled() {
404
+ const char* v = std::getenv("CRISPASR_GGUF_PRELOAD");
405
+ return v && *v && *v != '0';
406
+ }
407
+ static void preload_pages(void* base, size_t size) {
408
+ #if !defined(_WIN32)
409
+ const long pg = sysconf(_SC_PAGESIZE);
410
+ if (pg <= 0)
411
+ return;
412
+ volatile const unsigned char* p = (const unsigned char*)base;
413
+ size_t touched = 0;
414
+ for (size_t off = 0; off < size; off += (size_t)pg) {
415
+ (void)p[off];
416
+ touched++;
417
+ }
418
+ (void)touched;
419
+ #else
420
+ (void)base;
421
+ (void)size;
422
+ #endif
423
+ }
424
+
425
+ // PLAN #60f: opt-in mlock — pin the mmap region in physical RAM so the
426
+ // kernel can't evict pages under memory pressure. Risky on RAM-tight
427
+ // hosts (a 16 GB model on a 16 GB box would starve the rest of the
428
+ // system). Useful as opt-in for users with comfortable headroom (32+
429
+ // GB). Failure (typically RLIMIT_MEMLOCK exceeded) prints a warning
430
+ // and continues — mmap'd weights still work, just without the pin.
431
+ static bool mlock_enabled() {
432
+ const char* v = std::getenv("CRISPASR_MLOCK");
433
+ return v && *v && *v != '0';
434
+ }
435
+ static void try_mlock(const char* tag, void* base, size_t size) {
436
+ #if !defined(_WIN32)
437
+ if (::mlock(base, size) != 0) {
438
+ fprintf(stderr,
439
+ "%s: mlock(%zu MiB) failed (errno=%d) — pages may still be evicted under "
440
+ "memory pressure. Raise RLIMIT_MEMLOCK (`ulimit -l unlimited`) if you want "
441
+ "the pin to take effect.\n",
442
+ tag, size / (1024 * 1024), errno);
443
+ }
444
+ #else
445
+ (void)tag;
446
+ (void)base;
447
+ (void)size;
448
+ #endif
449
+ }
450
+
451
+ } // namespace
452
+
453
+ bool load_weights(const char* path, ggml_backend_t backend, const char* model_tag, WeightLoad& out) {
454
+ const char* tag = model_tag ? model_tag : "core_gguf";
455
+
456
+ gguf_init_params gp = {/*.no_alloc=*/true, /*.ctx=*/&out.ctx};
457
+ gguf_context* gctx = gguf_init_from_file(path, gp);
458
+ if (!gctx || !out.ctx) {
459
+ fprintf(stderr, "%s: failed to load tensor metadata from '%s'\n", tag, path);
460
+ if (gctx)
461
+ gguf_free(gctx);
462
+ return false;
463
+ }
464
+
465
+ // PLAN #51a: zero-copy CPU path. Skip ggml_backend_alloc_ctx_tensors
466
+ // (which would allocate a fresh backend-side buffer) and instead bind
467
+ // each tensor directly into the mmap'd file. Saves one full copy of
468
+ // the weights — the difference between a 14.9 GB F16 GGUF loading on
469
+ // a 16 GB Mac and thrashing swap. Default-on as of issue #94 (slow /
470
+ // failing chatterbox-turbo load on macOS); opt out with
471
+ // `CRISPASR_GGUF_MMAP=0`.
472
+ if (mmap_loader_enabled() && ggml_backend_is_cpu(backend)) {
473
+ MappedFile mf(path, /*writable=*/true);
474
+ if (mf.ok) {
475
+ const size_t data_off = gguf_get_data_offset(gctx);
476
+ const size_t mmap_size = mf.size;
477
+ char* tensor_base = (char*)mf.base + data_off;
478
+ const size_t buf_size = mmap_size > data_off ? (mmap_size - data_off) : 0;
479
+
480
+ auto* mctx = new mmap_buffer_ctx{};
481
+ mctx->mmap_base = mf.base;
482
+ mctx->mmap_size = mmap_size;
483
+ mctx->tensor_base = tensor_base;
484
+ mf.release();
485
+ // Hint kernel to start async readahead of the entire weight
486
+ // region. Without this we hit a synchronous page fault on every
487
+ // first access during prefill (~5-10 ms each on the 99%-full
488
+ // external disk we hit during PLAN #51c F16 testing). Mirrors
489
+ // llama.cpp's `llama_mmap` populate path.
490
+ #if !defined(_WIN32)
491
+ ::posix_madvise(mctx->mmap_base, mctx->mmap_size, POSIX_MADV_WILLNEED);
492
+ #endif
493
+ // PLAN #60c / #60f: optional preload + mlock, opt-in via env.
494
+ if (preload_enabled())
495
+ preload_pages(mctx->mmap_base, mctx->mmap_size);
496
+ if (mlock_enabled())
497
+ try_mlock(tag, mctx->mmap_base, mctx->mmap_size);
498
+
499
+ out.buf = ggml_backend_buffer_init(ggml_backend_cpu_buffer_type(), mmap_buffer_iface, mctx, buf_size);
500
+ if (!out.buf) {
501
+ fprintf(stderr, "%s: failed to wrap mmap in backend buffer\n", tag);
502
+ #if defined(_WIN32)
503
+ UnmapViewOfFile(mctx->mmap_base);
504
+ #else
505
+ ::munmap(mctx->mmap_base, mctx->mmap_size);
506
+ #endif
507
+ delete mctx;
508
+ gguf_free(gctx);
509
+ ggml_free(out.ctx);
510
+ out.ctx = nullptr;
511
+ return false;
512
+ }
513
+
514
+ // Pre-validate tensor bounds before calling ggml_backend_tensor_alloc,
515
+ // which fires a hard GGML_ASSERT when any tensor's range exceeds
516
+ // buf_size. Seen on macOS 26.x Tahoe (issue #94) — likely a
517
+ // mismatched or truncated GGUF file. Detect it here and fall back
518
+ // gracefully to the legacy alloc+copy path instead of crashing.
519
+ bool bounds_ok = true;
520
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
521
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
522
+ if (tid < 0)
523
+ continue;
524
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
525
+ if (off + ggml_nbytes(t) > buf_size) {
526
+ fprintf(stderr,
527
+ "%s: mmap bounds check failed for tensor '%s' "
528
+ "(off=%zu + nbytes=%zu > buf_size=%zu) — "
529
+ "falling back to legacy loader\n",
530
+ tag, ggml_get_name(t), off, ggml_nbytes(t), buf_size);
531
+ bounds_ok = false;
532
+ break;
533
+ }
534
+ }
535
+ if (bounds_ok) {
536
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
537
+ out.tensors[ggml_get_name(t)] = t;
538
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
539
+ if (tid < 0)
540
+ continue;
541
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
542
+ ggml_backend_tensor_alloc(out.buf, t, tensor_base + off);
543
+ }
544
+ gguf_free(gctx);
545
+ return true;
546
+ }
547
+ // Bounds check failed — release the mmap buffer and fall through to
548
+ // the legacy alloc+copy path below.
549
+ ggml_backend_buffer_free(out.buf);
550
+ out.buf = nullptr;
551
+ }
552
+ // mmap failed or bounds check failed — fall through to the legacy
553
+ // alloc + copy path. Functionally equivalent, just with more RSS.
554
+ }
555
+
556
+ // PLAN #51a (Metal variant): zero-copy GPU path via the device's
557
+ // `buffer_from_host_ptr` capability. On Apple-Silicon Metal this maps
558
+ // to `[MTLDevice newBufferWithBytesNoCopy:length:options:deallocator:]`
559
+ // wrapping our mmap region in an MTLResourceStorageModeShared buffer
560
+ // — same physical pages the CPU sees thanks to unified memory, no
561
+ // device-side allocation, no copy. On discrete-Metal hosts (Intel +
562
+ // eGPU) this lets the GPU page-fault from the file directly. The
563
+ // device-cap probe means we silently fall through on backends that
564
+ // don't advertise host-pointer support (CUDA without managed memory,
565
+ // Vulkan, etc.).
566
+ //
567
+ // The inner buffer is returned as `out.buf` UNWRAPPED. We used to
568
+ // wrap it to attach a munmap callback to free_buffer, but ggml-metal
569
+ // pierces the iface abstraction and casts `buffer->context` straight
570
+ // to its `ggml_metal_buffer_t` — wrapping made Metal read garbage
571
+ // and emit "tensor 'X' buffer is nil" for every weight (kokoro
572
+ // gibberish-audio regression). The mmap region is registered in
573
+ // g_gpu_mmap and deliberately leaked when the buffer is freed: Metal
574
+ // doesn't own the pages (deallocator=nil), and on macOS file-backed
575
+ // pages can still be evicted under pressure. Process exit cleans up.
576
+ if (mmap_loader_enabled() && !ggml_backend_is_cpu(backend)) {
577
+ ggml_backend_dev_t dev = ggml_backend_get_device(backend);
578
+ ggml_backend_dev_props props{};
579
+ ggml_backend_dev_get_props(dev, &props);
580
+ if (props.caps.buffer_from_host_ptr) {
581
+ MappedFile mf(path, /*writable=*/true);
582
+ if (mf.ok) {
583
+ const size_t data_off = gguf_get_data_offset(gctx);
584
+ char* tensor_base = (char*)mf.base + data_off;
585
+
586
+ // Hand the entire mmap region (including GGUF header) to
587
+ // the device. The backend's `buffer_from_host_ptr` uses
588
+ // the size for its internal MTLBuffer view; tensor binds
589
+ // below offset into this base.
590
+ ggml_backend_buffer_t inner = ggml_backend_dev_buffer_from_host_ptr(dev, mf.base, mf.size,
591
+ /*max_tensor_size=*/0);
592
+ if (inner) {
593
+ void* leaked_base = mf.base;
594
+ size_t leaked_size = mf.size;
595
+ mf.release();
596
+ // Hint kernel async readahead — same rationale as the
597
+ // CPU branch above. On Apple Silicon the unified-memory
598
+ // shared-storage MTLBuffer reads the same physical
599
+ // pages, so this readahead benefits both CPU and GPU
600
+ // accesses with one call.
601
+ #if !defined(_WIN32)
602
+ ::posix_madvise(leaked_base, leaked_size, POSIX_MADV_WILLNEED);
603
+ #endif
604
+ // PLAN #60c / #60f: optional preload + mlock, opt-in
605
+ // via env. mlock is particularly meaningful here —
606
+ // pinning prevents Metal's shared-storage reads from
607
+ // racing CPU page faults under memory pressure.
608
+ if (preload_enabled())
609
+ preload_pages(leaked_base, leaked_size);
610
+ if (mlock_enabled())
611
+ try_mlock(tag, leaked_base, leaked_size);
612
+
613
+ register_gpu_mmap(inner, leaked_base, leaked_size);
614
+ out.buf = inner;
615
+
616
+ // Pre-validate bounds (same rationale as CPU mmap path).
617
+ bool bounds_ok = true;
618
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
619
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
620
+ if (tid < 0)
621
+ continue;
622
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
623
+ if (data_off + off + ggml_nbytes(t) > leaked_size) {
624
+ fprintf(stderr,
625
+ "%s: GPU mmap bounds check failed for tensor '%s' "
626
+ "(data_off=%zu + off=%zu + nbytes=%zu > file_size=%zu) — "
627
+ "falling back to legacy loader\n",
628
+ tag, ggml_get_name(t), data_off, off, ggml_nbytes(t), leaked_size);
629
+ bounds_ok = false;
630
+ break;
631
+ }
632
+ }
633
+ if (!bounds_ok) {
634
+ out.buf = nullptr;
635
+ // inner is registered in g_gpu_mmap and deliberately
636
+ // leaked (same as the normal teardown path).
637
+ // Fall through to legacy path.
638
+ } else {
639
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
640
+ out.tensors[ggml_get_name(t)] = t;
641
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
642
+ if (tid < 0)
643
+ continue;
644
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
645
+ ggml_backend_tensor_alloc(out.buf, t, tensor_base + off);
646
+ }
647
+
648
+ gguf_free(gctx);
649
+ return true;
650
+ }
651
+ }
652
+ // buffer_from_host_ptr returned null — release mmap and fall
653
+ // through to the legacy path. No warning; same rationale as
654
+ // the CPU mmap branch.
655
+ }
656
+ }
657
+ }
658
+
659
+ out.buf = ggml_backend_alloc_ctx_tensors(out.ctx, backend);
660
+ if (!out.buf) {
661
+ fprintf(stderr, "%s: failed to allocate backend buffer\n", tag);
662
+ gguf_free(gctx);
663
+ ggml_free(out.ctx);
664
+ out.ctx = nullptr;
665
+ return false;
666
+ }
667
+
668
+ MappedFile mf(path);
669
+ if (mf.ok) {
670
+ // Issue #94: the legacy alloc+copy path took 30-60 s for the
671
+ // 658 MB chatterbox-turbo T3 GGUF on slow disks, because each
672
+ // ggml_backend_tensor_set hit a synchronous page fault on
673
+ // its first access to the mmap source region. The zero-copy
674
+ // mmap path already hints WILLNEED (line 526) for the same
675
+ // reason; doing it here brings the legacy path's load time
676
+ // back in line for users who opt out of the zero-copy path
677
+ // with CRISPASR_GGUF_MMAP=0 (e.g. model files on network
678
+ // mounts where mmap would SIGBUS on disconnect).
679
+ #if !defined(_WIN32)
680
+ ::posix_madvise(mf.base, mf.size, POSIX_MADV_WILLNEED);
681
+ #endif
682
+ }
683
+ if (!mf.ok) {
684
+ // Fallback: read via FILE* pread/fseek. This is the rare path —
685
+ // most systems have working mmap. We implement it inline here so
686
+ // models don't have to.
687
+ FILE* fp = fopen(path, "rb");
688
+ if (!fp) {
689
+ fprintf(stderr, "%s: cannot open '%s' for fread fallback\n", tag, path);
690
+ gguf_free(gctx);
691
+ return false;
692
+ }
693
+ const size_t data_off = gguf_get_data_offset(gctx);
694
+ std::vector<uint8_t> tbuf;
695
+ bool load_ok = true;
696
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
697
+ out.tensors[ggml_get_name(t)] = t;
698
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
699
+ if (tid < 0)
700
+ continue;
701
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
702
+ const size_t nbytes = ggml_nbytes(t);
703
+ if (tbuf.size() < nbytes)
704
+ tbuf.resize(nbytes);
705
+ #if defined(_WIN32)
706
+ if (_fseeki64(fp, (int64_t)(data_off + off), SEEK_SET) != 0) {
707
+ fprintf(stderr, "%s: fseek failed for tensor '%s' — file truncated?\n", tag, ggml_get_name(t));
708
+ load_ok = false;
709
+ break;
710
+ }
711
+ #else
712
+ if (fseeko(fp, (off_t)(data_off + off), SEEK_SET) != 0) {
713
+ fprintf(stderr, "%s: fseek failed for tensor '%s' — file truncated?\n", tag, ggml_get_name(t));
714
+ load_ok = false;
715
+ break;
716
+ }
717
+ #endif
718
+ if (fread(tbuf.data(), 1, nbytes, fp) != nbytes) {
719
+ fprintf(stderr, "%s: short read for tensor '%s' (%zu bytes expected) — file truncated?\n", tag,
720
+ ggml_get_name(t), nbytes);
721
+ load_ok = false;
722
+ break;
723
+ }
724
+ ggml_backend_tensor_set(t, tbuf.data(), 0, nbytes);
725
+ }
726
+ fclose(fp);
727
+ if (!load_ok) {
728
+ fprintf(stderr, "%s: legacy loader failed — model file may be truncated or corrupt\n", tag);
729
+ gguf_free(gctx);
730
+ ggml_backend_buffer_free(out.buf);
731
+ out.buf = nullptr;
732
+ ggml_free(out.ctx);
733
+ out.ctx = nullptr;
734
+ return false;
735
+ }
736
+ } else {
737
+ const size_t data_off = gguf_get_data_offset(gctx);
738
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
739
+ out.tensors[ggml_get_name(t)] = t;
740
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
741
+ if (tid < 0)
742
+ continue;
743
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
744
+ const size_t nbytes = ggml_nbytes(t);
745
+ // Bounds check: prevent segfault on truncated GGUF files
746
+ if (data_off + off + nbytes > mf.size) {
747
+ fprintf(stderr,
748
+ "%s: mmap legacy path: tensor '%s' exceeds file bounds "
749
+ "(off=%zu + nbytes=%zu > file_size=%zu) — file truncated?\n",
750
+ tag, ggml_get_name(t), data_off + off, nbytes, mf.size);
751
+ gguf_free(gctx);
752
+ ggml_backend_buffer_free(out.buf);
753
+ out.buf = nullptr;
754
+ ggml_free(out.ctx);
755
+ out.ctx = nullptr;
756
+ return false;
757
+ }
758
+ ggml_backend_tensor_set(t, (const char*)mf.base + data_off + off, 0, nbytes);
759
+ }
760
+ }
761
+
762
+ gguf_free(gctx);
763
+ return true;
764
+ }
765
+
766
+ void free_weights(WeightLoad& wl) {
767
+ if (wl.buf) {
768
+ ggml_backend_buffer_free(wl.buf);
769
+ wl.buf = nullptr;
770
+ }
771
+ if (wl.buf_cpu) {
772
+ ggml_backend_buffer_free(wl.buf_cpu);
773
+ wl.buf_cpu = nullptr;
774
+ }
775
+ if (wl.ctx) {
776
+ ggml_free(wl.ctx);
777
+ wl.ctx = nullptr;
778
+ }
779
+ wl.tensors.clear();
780
+ }
781
+
782
+ int blk_layer_of_with_prefix(const char* tensor_name, const char* prefix) {
783
+ if (!tensor_name || !prefix)
784
+ return -1;
785
+ const size_t plen = std::strlen(prefix);
786
+ if (std::strncmp(tensor_name, prefix, plen) != 0)
787
+ return -1;
788
+ char* end = nullptr;
789
+ long il = std::strtol(tensor_name + plen, &end, 10);
790
+ if (!end || *end != '.' || il < 0)
791
+ return -1;
792
+ return (int)il;
793
+ }
794
+
795
+ int blk_layer_of(const char* tensor_name) {
796
+ return blk_layer_of_with_prefix(tensor_name, "blk.");
797
+ }
798
+
799
+ bool is_gpu_tensor_with_prefix(const char* tensor_name, void* user) {
800
+ const auto* cfg = static_cast<const LayerSplitConfig*>(user);
801
+ const int il = blk_layer_of_with_prefix(tensor_name, cfg->prefix);
802
+ if (il < 0)
803
+ return true; // non-layered tensors stay on GPU
804
+ return il < cfg->threshold;
805
+ }
806
+
807
+ bool is_gpu_tensor_blk(const char* tensor_name, void* user) {
808
+ const int threshold = *static_cast<const int*>(user);
809
+ const int il = blk_layer_of(tensor_name);
810
+ if (il < 0)
811
+ return true;
812
+ return il < threshold;
813
+ }
814
+
815
+ bool load_weights_split(const char* path, ggml_backend_t gpu_backend, ggml_backend_t cpu_backend, IsGpuTensor is_gpu,
816
+ void* user, const char* model_tag, WeightLoad& out) {
817
+ const char* tag = model_tag ? model_tag : "core_gguf";
818
+
819
+ if (!gpu_backend || !cpu_backend) {
820
+ fprintf(stderr, "%s: load_weights_split requires both gpu and cpu backends\n", tag);
821
+ return false;
822
+ }
823
+ if (!is_gpu) {
824
+ fprintf(stderr, "%s: load_weights_split requires a non-null is_gpu predicate\n", tag);
825
+ return false;
826
+ }
827
+
828
+ // Open metadata + create ggml_context with all tensor metadata (no_alloc).
829
+ gguf_init_params gp = {/*.no_alloc=*/true, /*.ctx=*/&out.ctx};
830
+ gguf_context* gctx = gguf_init_from_file(path, gp);
831
+ if (!gctx || !out.ctx) {
832
+ fprintf(stderr, "%s: failed to load tensor metadata from '%s'\n", tag, path);
833
+ if (gctx)
834
+ gguf_free(gctx);
835
+ return false;
836
+ }
837
+
838
+ // Pass 1: partition tensors by predicate, sum sizes per partition.
839
+ std::vector<ggml_tensor*> gpu_tensors, cpu_tensors;
840
+ size_t gpu_size = 0, cpu_size = 0;
841
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
842
+ const char* tname = ggml_get_name(t);
843
+ const bool to_gpu = is_gpu(tname, user);
844
+ if (to_gpu) {
845
+ gpu_tensors.push_back(t);
846
+ gpu_size += ggml_nbytes(t);
847
+ } else {
848
+ cpu_tensors.push_back(t);
849
+ cpu_size += ggml_nbytes(t);
850
+ }
851
+ out.tensors[tname] = t;
852
+ }
853
+
854
+ // Allocate per-partition backend buffers. Tensor alignment within the
855
+ // buffer follows the backend buffer-type's alignment requirement;
856
+ // pad each per-tensor offset up to that alignment.
857
+ auto round_up = [](size_t n, size_t a) { return (n + a - 1) & ~(a - 1); };
858
+ auto bind_partition = [&](ggml_backend_t be, const std::vector<ggml_tensor*>& tensors, size_t total,
859
+ ggml_backend_buffer_t* out_buf) -> bool {
860
+ if (tensors.empty())
861
+ return true;
862
+ const size_t align = ggml_backend_get_alignment(be);
863
+ // Compute final size with per-tensor alignment slack.
864
+ size_t aligned_total = 0;
865
+ for (ggml_tensor* t : tensors)
866
+ aligned_total = round_up(aligned_total, align) + ggml_nbytes(t);
867
+ (void)total;
868
+ ggml_backend_buffer_t buf = ggml_backend_alloc_buffer(be, aligned_total);
869
+ if (!buf) {
870
+ fprintf(stderr, "%s: failed to allocate %zu MiB backend buffer\n", tag, aligned_total / 1048576);
871
+ return false;
872
+ }
873
+ char* base = (char*)ggml_backend_buffer_get_base(buf);
874
+ size_t cursor = 0;
875
+ for (ggml_tensor* t : tensors) {
876
+ cursor = round_up(cursor, align);
877
+ ggml_backend_tensor_alloc(buf, t, base + cursor);
878
+ cursor += ggml_nbytes(t);
879
+ }
880
+ *out_buf = buf;
881
+ return true;
882
+ };
883
+
884
+ if (!bind_partition(gpu_backend, gpu_tensors, gpu_size, &out.buf)) {
885
+ gguf_free(gctx);
886
+ ggml_free(out.ctx);
887
+ out.ctx = nullptr;
888
+ return false;
889
+ }
890
+ if (!bind_partition(cpu_backend, cpu_tensors, cpu_size, &out.buf_cpu)) {
891
+ if (out.buf) {
892
+ ggml_backend_buffer_free(out.buf);
893
+ out.buf = nullptr;
894
+ }
895
+ gguf_free(gctx);
896
+ ggml_free(out.ctx);
897
+ out.ctx = nullptr;
898
+ return false;
899
+ }
900
+
901
+ // Copy tensor data from the file. Use mmap when available for zero-
902
+ // copy where the kernel will demand-page; fall back to pread.
903
+ MappedFile mf(path);
904
+ if (!mf.ok) {
905
+ FILE* fp = fopen(path, "rb");
906
+ if (!fp) {
907
+ fprintf(stderr, "%s: cannot open '%s' for fread fallback\n", tag, path);
908
+ free_weights(out);
909
+ gguf_free(gctx);
910
+ return false;
911
+ }
912
+ const size_t data_off = gguf_get_data_offset(gctx);
913
+ std::vector<uint8_t> tbuf;
914
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
915
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
916
+ if (tid < 0)
917
+ continue;
918
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
919
+ const size_t nbytes = ggml_nbytes(t);
920
+ if (tbuf.size() < nbytes)
921
+ tbuf.resize(nbytes);
922
+ #if defined(_WIN32)
923
+ if (_fseeki64(fp, (int64_t)(data_off + off), SEEK_SET) != 0)
924
+ break;
925
+ #else
926
+ if (fseeko(fp, (off_t)(data_off + off), SEEK_SET) != 0)
927
+ break;
928
+ #endif
929
+ if (fread(tbuf.data(), 1, nbytes, fp) != nbytes)
930
+ break;
931
+ ggml_backend_tensor_set(t, tbuf.data(), 0, nbytes);
932
+ }
933
+ fclose(fp);
934
+ } else {
935
+ const size_t data_off = gguf_get_data_offset(gctx);
936
+ for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
937
+ const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
938
+ if (tid < 0)
939
+ continue;
940
+ const size_t off = gguf_get_tensor_offset(gctx, tid);
941
+ const size_t nbytes = ggml_nbytes(t);
942
+ ggml_backend_tensor_set(t, (const char*)mf.base + data_off + off, 0, nbytes);
943
+ }
944
+ }
945
+
946
+ fprintf(stderr, "%s: weight residency: gpu=%zu MiB (%zu tensors), cpu=%zu MiB (%zu tensors)\n", tag,
947
+ gpu_size / 1048576, gpu_tensors.size(), cpu_size / 1048576, cpu_tensors.size());
948
+
949
+ gguf_free(gctx);
950
+ return true;
951
+ }
952
+
953
+ // PLAN #60g: switch a previously-WILLNEED-hinted region to MADV_RANDOM.
954
+ // Used by callers (e.g., mimo-asr's transcribe loop) to tell the kernel
955
+ // "I'm done with sequential prefill access; my next reads will be
956
+ // random-order layer revisits during decode — please stop wasting IO
957
+ // on speculative readahead."
958
+ //
959
+ // We dispatch on the buffer's iface fields to detect which of our two
960
+ // mmap paths the buffer came from, since the buffer types themselves
961
+ // aren't exposed publicly. No-op if the buffer wasn't allocated through
962
+ // either path (incl. the legacy alloc+copy fallback when MMAP=0 or
963
+ // mmap failed).
964
+ void mmap_advise_random(ggml_backend_buffer_t buf) {
965
+ #if !defined(_WIN32)
966
+ if (!buf)
967
+ return;
968
+ void* base = nullptr;
969
+ size_t size = 0;
970
+ if (buf->iface.free_buffer == mmap_buffer_free) {
971
+ // CPU mmap path — context is mmap_buffer_ctx (our own iface).
972
+ auto* mctx = (mmap_buffer_ctx*)buf->context;
973
+ base = mctx->mmap_base;
974
+ size = mctx->mmap_size;
975
+ } else {
976
+ // Non-CPU (Metal) mmap path — buffer is the inner backend buffer,
977
+ // its context belongs to that backend; look the mmap region up
978
+ // in our side-map instead.
979
+ gpu_mmap_handle h = lookup_gpu_mmap(buf);
980
+ base = h.base;
981
+ size = h.size;
982
+ }
983
+ if (base && size > 0)
984
+ ::posix_madvise(base, size, POSIX_MADV_RANDOM);
985
+ #else
986
+ (void)buf;
987
+ #endif
988
+ }
989
+
990
+ // ---------------------------------------------------------------------------
991
+ // Tensor lookup helpers
992
+ // ---------------------------------------------------------------------------
993
+
994
+ // Signatures use `core_gguf::tensor_map` (see gguf_loader.h cross-repo contract).
995
+ ggml_tensor* try_get(const tensor_map& tensors, const char* name) {
996
+ auto it = tensors.find(name);
997
+ return it != tensors.end() ? it->second : nullptr;
998
+ }
999
+
1000
+ ggml_tensor* require(const tensor_map& tensors, const char* name, const char* model_tag) {
1001
+ auto it = tensors.find(name);
1002
+ if (it == tensors.end()) {
1003
+ fprintf(stderr, "%s: required tensor '%s' not found in GGUF\n", model_tag ? model_tag : "core_gguf", name);
1004
+ return nullptr;
1005
+ }
1006
+ return it->second;
1007
+ }
1008
+
1009
+ std::string format_layer_name(const char* fmt, int i) {
1010
+ char buf[256];
1011
+ snprintf(buf, sizeof(buf), fmt, i);
1012
+ return std::string(buf);
1013
+ }
1014
+
1015
+ std::string format_layer_name(const char* fmt, int i, int j) {
1016
+ char buf[256];
1017
+ snprintf(buf, sizeof(buf), fmt, i, j);
1018
+ return std::string(buf);
1019
+ }
1020
+
1021
+ } // namespace core_gguf