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,1209 @@
1
+ // Lean Cohere-only implementation of the CrispASR session C ABI consumed by
2
+ // lib/cohere/transcribe/asr/native.rb. The model implementation and grouping
3
+ // behavior are copied from the pinned CrispASR sources; unrelated backends are
4
+ // intentionally omitted from this private gem runtime.
5
+
6
+ #include "cohere.h"
7
+ #include "cohere_decoder_batch_layout.h"
8
+ #include "cohere_encoder_padded_layout.h"
9
+ #include "cohere_token_renderer.h"
10
+ #include "core/gpu_backend_pref.h"
11
+ #include "core/repetition_loop_guard.h"
12
+ #include "ggml.h"
13
+ #include "ggml-backend.h"
14
+
15
+ #include <algorithm>
16
+ #include <atomic>
17
+ #include <cctype>
18
+ #include <cstdlib>
19
+ #include <cstdint>
20
+ #include <cstring>
21
+ #include <exception>
22
+ #include <memory>
23
+ #include <mutex>
24
+ #include <new>
25
+ #include <string>
26
+ #include <thread>
27
+ #include <utility>
28
+ #include <vector>
29
+
30
+ #if defined(_WIN32)
31
+ #define CRISPASR_GEM_EXPORT extern "C" __declspec(dllexport)
32
+ #else
33
+ #define CRISPASR_GEM_EXPORT extern "C" __attribute__((visibility("default")))
34
+ #endif
35
+
36
+ struct crispasr_open_params_v1 {
37
+ int abi_version;
38
+ int n_threads;
39
+ int use_gpu;
40
+ int verbosity;
41
+ int flash_attn;
42
+ int n_gpu_layers;
43
+ int reserved[6];
44
+ };
45
+
46
+ struct crispasr_session_word {
47
+ std::string text;
48
+ int64_t t0 = 0;
49
+ int64_t t1 = 0;
50
+ float p = 1.0f;
51
+ };
52
+
53
+ struct crispasr_session_segment {
54
+ std::string text;
55
+ int64_t t0 = 0;
56
+ int64_t t1 = 0;
57
+ std::vector<crispasr_session_word> words;
58
+ };
59
+
60
+ struct crispasr_session_result {
61
+ std::vector<crispasr_session_segment> segments;
62
+ int generated_tokens = 0;
63
+ int generation_limit = 0;
64
+ int generation_capacity = 0;
65
+ bool stopped_by_max_tokens = false;
66
+ bool repetition_stopped = false;
67
+ };
68
+
69
+ struct crispasr_session_batch_stats {
70
+ int64_t total_us = 0;
71
+ int64_t feature_wall_us = 0;
72
+ int64_t feature_worker_us = 0;
73
+ int64_t mel_pack_us = 0;
74
+ int64_t encoder_graph_build_us = 0;
75
+ int64_t encoder_graph_alloc_us = 0;
76
+ int64_t encoder_input_us = 0;
77
+ int64_t encoder_compute_us = 0;
78
+ int64_t encoder_readback_us = 0;
79
+ int64_t encoder_repack_us = 0;
80
+ int64_t decoder_total_us = 0;
81
+ int64_t decoder_cross_kv_us = 0;
82
+ int64_t decoder_reserve_us = 0;
83
+ int64_t decoder_decode_us = 0;
84
+ int64_t render_us = 0;
85
+ int64_t decoder_calls = 0;
86
+ int64_t generation_steps = 0;
87
+ int64_t encoder_microbatches = 0;
88
+ int64_t token_id_readback_bytes = 0;
89
+ };
90
+
91
+ struct crispasr_session_batch_result {
92
+ std::vector<std::unique_ptr<crispasr_session_result>> lanes;
93
+ crispasr_session_batch_stats stats;
94
+ };
95
+
96
+ enum class crispasr_operation_state : unsigned char {
97
+ idle = 0,
98
+ running = 1,
99
+ cancel_requested = 2,
100
+ };
101
+
102
+ struct crispasr_session {
103
+ std::string backend = "cohere";
104
+ cohere_context* cohere_ctx = nullptr;
105
+ int n_threads = 4;
106
+ int max_new_tokens = 0;
107
+ int beam_size = 1;
108
+ bool repetition_loop_guard = true;
109
+ std::atomic<crispasr_operation_state> operation_state{crispasr_operation_state::idle};
110
+ };
111
+
112
+ // One logical session batch may span several padded-encoder microbatches.
113
+ // CrispASR deliberately gives those two stages different structural limits:
114
+ // the activation-heavy encoder is bounded independently while the ragged
115
+ // decoder owns collision-tested cache layouts for up to twenty-four lanes.
116
+ static constexpr int crispasr_session_batch_capacity_value() {
117
+ static_assert(cohere_encoder_padded::max_batch > 0);
118
+ static_assert(cohere_decoder_batch::max_batch >= cohere_encoder_padded::max_batch);
119
+ return cohere_decoder_batch::max_batch;
120
+ }
121
+
122
+ enum class crispasr_error_kind : int {
123
+ none = 0,
124
+ invalid_argument = 1,
125
+ out_of_memory = 2,
126
+ invariant = 3,
127
+ runtime = 4,
128
+ cancelled = 5,
129
+ };
130
+
131
+ struct crispasr_error_state {
132
+ crispasr_error_kind kind = crispasr_error_kind::none;
133
+ char message[512] = {};
134
+ };
135
+
136
+ static thread_local crispasr_error_state crispasr_thread_error;
137
+
138
+ static void crispasr_clear_error() noexcept {
139
+ crispasr_thread_error = {};
140
+ }
141
+
142
+ static void crispasr_set_error(crispasr_error_kind kind, const char* message) noexcept {
143
+ crispasr_thread_error.kind = kind;
144
+ const char* source = message ? message : "";
145
+ const size_t length = std::min(std::strlen(source), sizeof(crispasr_thread_error.message) - 1);
146
+ std::memcpy(crispasr_thread_error.message, source, length);
147
+ crispasr_thread_error.message[length] = '\0';
148
+ }
149
+
150
+ template <typename T>
151
+ static T* crispasr_fail(crispasr_error_kind kind, const char* message) noexcept {
152
+ crispasr_set_error(kind, message);
153
+ return nullptr;
154
+ }
155
+
156
+ static void crispasr_import_cohere_error(crispasr_error_kind fallback_kind, const char* fallback_message) noexcept {
157
+ crispasr_error_kind kind = fallback_kind;
158
+ switch (cohere_last_error_kind()) {
159
+ case COHERE_ERROR_INVALID_ARGUMENT: kind = crispasr_error_kind::invalid_argument; break;
160
+ case COHERE_ERROR_OUT_OF_MEMORY: kind = crispasr_error_kind::out_of_memory; break;
161
+ case COHERE_ERROR_INVARIANT: kind = crispasr_error_kind::invariant; break;
162
+ case COHERE_ERROR_RUNTIME: kind = crispasr_error_kind::runtime; break;
163
+ case COHERE_ERROR_CANCELLED: kind = crispasr_error_kind::cancelled; break;
164
+ case COHERE_ERROR_NONE: break;
165
+ }
166
+ const char* message = cohere_last_error_message();
167
+ crispasr_set_error(kind, message && message[0] != '\0' ? message : fallback_message);
168
+ }
169
+
170
+ static bool crispasr_session_abort_requested(void* opaque) noexcept {
171
+ const auto* session = static_cast<const crispasr_session*>(opaque);
172
+ return session && session->operation_state.load(std::memory_order_acquire) ==
173
+ crispasr_operation_state::cancel_requested;
174
+ }
175
+
176
+ class crispasr_operation_guard {
177
+ public:
178
+ explicit crispasr_operation_guard(crispasr_session* session) noexcept : session_(session) {
179
+ if (!session_)
180
+ return;
181
+ auto expected = crispasr_operation_state::idle;
182
+ acquired_ = session_->operation_state.compare_exchange_strong(
183
+ expected,
184
+ crispasr_operation_state::running,
185
+ std::memory_order_acq_rel,
186
+ std::memory_order_acquire);
187
+ }
188
+
189
+ ~crispasr_operation_guard() {
190
+ if (acquired_)
191
+ session_->operation_state.store(crispasr_operation_state::idle, std::memory_order_release);
192
+ }
193
+
194
+ explicit operator bool() const noexcept { return acquired_; }
195
+
196
+ crispasr_operation_guard(const crispasr_operation_guard&) = delete;
197
+ crispasr_operation_guard& operator=(const crispasr_operation_guard&) = delete;
198
+
199
+ private:
200
+ crispasr_session* session_ = nullptr;
201
+ bool acquired_ = false;
202
+ };
203
+
204
+ template <typename T>
205
+ static T* crispasr_cancelled() noexcept {
206
+ return crispasr_fail<T>(crispasr_error_kind::cancelled, "Cohere inference was cancelled");
207
+ }
208
+
209
+ struct token_record {
210
+ std::string text;
211
+ int64_t t0 = 0;
212
+ int64_t t1 = 0;
213
+ float p = 1.0f;
214
+ };
215
+
216
+ static bool backend_name_starts_with(const char* name, const char* prefix) {
217
+ if (!name || !prefix)
218
+ return false;
219
+ while (*prefix) {
220
+ if (!*name)
221
+ return false;
222
+ const auto left = static_cast<unsigned char>(*name++);
223
+ const auto right = static_cast<unsigned char>(*prefix++);
224
+ if (std::tolower(left) != std::tolower(right))
225
+ return false;
226
+ }
227
+ return true;
228
+ }
229
+
230
+ static const char* canonical_device_for_backend(const char* name) {
231
+ if (backend_name_starts_with(name, "cuda"))
232
+ return "cuda";
233
+ if (backend_name_starts_with(name, "metal"))
234
+ return "mps";
235
+ if (backend_name_starts_with(name, "cpu"))
236
+ return "cpu";
237
+ return "";
238
+ }
239
+
240
+ CRISPASR_GEM_EXPORT int crispasr_last_error_kind() {
241
+ return static_cast<int>(crispasr_thread_error.kind);
242
+ }
243
+
244
+ CRISPASR_GEM_EXPORT const char* crispasr_last_error_message() {
245
+ return crispasr_thread_error.message;
246
+ }
247
+
248
+ // Resolve only the public devices supported by the Ruby/Python contract.
249
+ // Merely compiling a CUDA or Metal backend is insufficient: the corresponding
250
+ // ggml device must be registered on this machine. Returning an empty string for
251
+ // an unavailable explicit accelerator prevents CrispASR's useful command-line
252
+ // fallback from becoming a silent API contract violation in the gem.
253
+ CRISPASR_GEM_EXPORT const char* crispasr_runtime_resolve_device(const char* requested) {
254
+ const std::string request = requested ? requested : "auto";
255
+ if (request == "cpu")
256
+ return "cpu";
257
+ if (request != "auto" && request != "cuda" && request != "mps")
258
+ return "";
259
+
260
+ ggml_backend_load_all();
261
+ bool cuda_available = false;
262
+ bool metal_available = false;
263
+ for (size_t index = 0; index < ggml_backend_dev_count(); ++index) {
264
+ ggml_backend_dev_t device = ggml_backend_dev_get(index);
265
+ const auto type = ggml_backend_dev_type(device);
266
+ if (type != GGML_BACKEND_DEVICE_TYPE_GPU && type != GGML_BACKEND_DEVICE_TYPE_IGPU)
267
+ continue;
268
+ const char* canonical = canonical_device_for_backend(ggml_backend_dev_name(device));
269
+ cuda_available = cuda_available || std::strcmp(canonical, "cuda") == 0;
270
+ metal_available = metal_available || std::strcmp(canonical, "mps") == 0;
271
+ }
272
+
273
+ if (request == "cuda")
274
+ return cuda_available ? "cuda" : "";
275
+ if (request == "mps")
276
+ return metal_available ? "mps" : "";
277
+ if (cuda_available)
278
+ return "cuda";
279
+ if (metal_available)
280
+ return "mps";
281
+ return "cpu";
282
+ }
283
+
284
+ CRISPASR_GEM_EXPORT int crispasr_runtime_supports_bf16(const char* requested) {
285
+ const char* resolved = crispasr_runtime_resolve_device(requested);
286
+ if (!resolved || resolved[0] == '\0' || std::strcmp(resolved, "cpu") == 0)
287
+ return 0;
288
+
289
+ ggml_backend_dev_t selected = nullptr;
290
+ for (size_t index = 0; index < ggml_backend_dev_count(); ++index) {
291
+ ggml_backend_dev_t candidate = ggml_backend_dev_get(index);
292
+ const char* canonical = canonical_device_for_backend(ggml_backend_dev_name(candidate));
293
+ if (std::strcmp(canonical, resolved) == 0) {
294
+ selected = candidate;
295
+ break;
296
+ }
297
+ }
298
+ if (!selected)
299
+ return 0;
300
+
301
+ // Ask the selected backend about an actual BF16 graph node. This follows
302
+ // Metal's per-device `has_bfloat` capability and CUDA's operation support
303
+ // without linking the embedding ABI to either platform SDK.
304
+ ggml_init_params params = {};
305
+ params.mem_size = 16 * 1024;
306
+ params.mem_buffer = nullptr;
307
+ params.no_alloc = true;
308
+ ggml_context* context = ggml_init(params);
309
+ if (!context)
310
+ return 0;
311
+ ggml_tensor* input = ggml_new_tensor_1d(context, GGML_TYPE_BF16, 16);
312
+ ggml_tensor* operation = input ? ggml_dup(context, input) : nullptr;
313
+ const bool supported = operation && ggml_backend_dev_supports_op(selected, operation);
314
+ ggml_free(context);
315
+ return supported ? 1 : 0;
316
+ }
317
+
318
+ // Keep Dense checkpoint conversion vectorized without exposing ggml's broad
319
+ // internal ABI. These three wrappers are the only numeric helpers consumed by
320
+ // the Ruby Safetensors streamer.
321
+ CRISPASR_GEM_EXPORT void crispasr_bf16_to_fp32_row(const void* source, void* destination, int64_t count) {
322
+ ggml_bf16_to_fp32_row(
323
+ static_cast<const ggml_bf16_t*>(source),
324
+ static_cast<float*>(destination),
325
+ count);
326
+ }
327
+
328
+ CRISPASR_GEM_EXPORT void crispasr_fp16_to_fp32_row(const void* source, void* destination, int64_t count) {
329
+ ggml_fp16_to_fp32_row(
330
+ static_cast<const ggml_fp16_t*>(source),
331
+ static_cast<float*>(destination),
332
+ count);
333
+ }
334
+
335
+ CRISPASR_GEM_EXPORT void crispasr_fp32_to_fp16_row(const void* source, void* destination, int64_t count) {
336
+ ggml_fp32_to_fp16_row(
337
+ static_cast<const float*>(source),
338
+ static_cast<ggml_fp16_t*>(destination),
339
+ count);
340
+ }
341
+
342
+ CRISPASR_GEM_EXPORT void crispasr_fp32_to_bf16_row(const void* source, void* destination, int64_t count) {
343
+ ggml_fp32_to_bf16_row(
344
+ static_cast<const float*>(source),
345
+ static_cast<ggml_bf16_t*>(destination),
346
+ count);
347
+ }
348
+
349
+ static bool punctuation_only(const std::string& value) {
350
+ if (value.empty())
351
+ return false;
352
+ for (char character : value) {
353
+ const unsigned char byte = static_cast<unsigned char>(character);
354
+ if ((byte >= 'A' && byte <= 'Z') || (byte >= 'a' && byte <= 'z') ||
355
+ (byte >= '0' && byte <= '9') || byte >= 0x80) {
356
+ return false;
357
+ }
358
+ }
359
+ return true;
360
+ }
361
+
362
+ // Preserve CrispASR's SentencePiece word grouping: a leading space starts a
363
+ // word, continuation pieces append, and punctuation attaches to the previous
364
+ // word. Confidence is the mean probability of the contributing tokens.
365
+ static std::vector<crispasr_session_word> group_words(const std::vector<token_record>& tokens) {
366
+ std::vector<crispasr_session_word> output;
367
+ crispasr_session_word current;
368
+ bool has_current = false;
369
+ float probability_sum = 0.0f;
370
+ int probability_count = 0;
371
+
372
+ auto flush = [&]() {
373
+ current.p = probability_count > 0 ? probability_sum / static_cast<float>(probability_count) : 1.0f;
374
+ output.push_back(std::move(current));
375
+ current = {};
376
+ has_current = false;
377
+ probability_sum = 0.0f;
378
+ probability_count = 0;
379
+ };
380
+
381
+ for (const auto& token : tokens) {
382
+ if (token.text.empty())
383
+ continue;
384
+ if (token.text == " ") {
385
+ if (has_current)
386
+ flush();
387
+ continue;
388
+ }
389
+
390
+ const bool leading_space = token.text.front() == ' ';
391
+ if (leading_space && !punctuation_only(token.text) && has_current)
392
+ flush();
393
+
394
+ if (!has_current) {
395
+ current.t0 = token.t0;
396
+ has_current = true;
397
+ }
398
+ current.t1 = token.t1;
399
+ probability_sum += token.p;
400
+ probability_count += 1;
401
+ current.text += leading_space ? token.text.substr(1) : token.text;
402
+ }
403
+
404
+ if (has_current)
405
+ flush();
406
+ return output;
407
+ }
408
+
409
+ static std::vector<token_record> timed_token_records(
410
+ const cohere_token_renderer::render_result& rendered,
411
+ int n_samples) {
412
+ size_t total_bytes = 0;
413
+ for (const auto& token : rendered.tokens)
414
+ total_bytes += token.text.size();
415
+
416
+ const int64_t duration_cs = static_cast<int64_t>(static_cast<double>(n_samples) * 100.0 / 16000.0);
417
+ size_t byte_offset = 0;
418
+ std::vector<token_record> records;
419
+ records.reserve(rendered.tokens.size());
420
+ for (const auto& token : rendered.tokens) {
421
+ const int64_t t0 = total_bytes == 0
422
+ ? 0
423
+ : static_cast<int64_t>(static_cast<double>(byte_offset) / total_bytes * duration_cs);
424
+ byte_offset += token.text.size();
425
+ const int64_t t1 = total_bytes == 0
426
+ ? duration_cs
427
+ : static_cast<int64_t>(static_cast<double>(byte_offset) / total_bytes * duration_cs);
428
+ records.push_back({token.text, t0, t1, token.probability});
429
+ }
430
+ return records;
431
+ }
432
+
433
+ CRISPASR_GEM_EXPORT void crispasr_set_gpu_backend(const char* name) {
434
+ crispasr_set_gpu_backend_pref(name);
435
+ }
436
+
437
+ CRISPASR_GEM_EXPORT crispasr_session* crispasr_session_open_with_params(
438
+ const char* model_path,
439
+ const char* backend_name,
440
+ const crispasr_open_params_v1* params) {
441
+ crispasr_clear_error();
442
+ if (!model_path || model_path[0] == '\0')
443
+ return crispasr_fail<crispasr_session>(
444
+ crispasr_error_kind::invalid_argument,
445
+ "model path must not be empty");
446
+ if (backend_name && backend_name[0] != '\0' && std::strcmp(backend_name, "cohere") != 0)
447
+ return crispasr_fail<crispasr_session>(
448
+ crispasr_error_kind::invalid_argument,
449
+ "only the Cohere backend is supported");
450
+
451
+ int n_threads = 4;
452
+ bool use_gpu = true;
453
+ bool flash_attn = true;
454
+ int verbosity = 0;
455
+ if (params && params->abi_version >= 1) {
456
+ n_threads = params->n_threads > 0 ? params->n_threads : 4;
457
+ use_gpu = params->use_gpu != 0;
458
+ verbosity = params->verbosity;
459
+ if (params->abi_version >= 2)
460
+ flash_attn = params->flash_attn != 0;
461
+ }
462
+
463
+ try {
464
+ auto session = std::make_unique<crispasr_session>();
465
+ session->n_threads = n_threads;
466
+ cohere_context_params cohere_params = cohere_context_default_params();
467
+ cohere_params.n_threads = n_threads;
468
+ cohere_params.use_gpu = use_gpu;
469
+ cohere_params.use_flash = flash_attn;
470
+ cohere_params.verbosity = verbosity;
471
+ session->cohere_ctx = cohere_init_from_file(model_path, cohere_params);
472
+ if (!session->cohere_ctx) {
473
+ crispasr_import_cohere_error(
474
+ crispasr_error_kind::runtime,
475
+ "could not initialize the Cohere model");
476
+ return nullptr;
477
+ }
478
+ cohere_set_abort_callback(
479
+ session->cohere_ctx,
480
+ crispasr_session_abort_requested,
481
+ session.get());
482
+ return session.release();
483
+ } catch (const std::bad_alloc&) {
484
+ return crispasr_fail<crispasr_session>(
485
+ crispasr_error_kind::out_of_memory,
486
+ "could not allocate the Cohere session");
487
+ } catch (const std::exception& error) {
488
+ return crispasr_fail<crispasr_session>(crispasr_error_kind::invariant, error.what());
489
+ } catch (...) {
490
+ return crispasr_fail<crispasr_session>(
491
+ crispasr_error_kind::invariant,
492
+ "unknown exception while opening the Cohere session");
493
+ }
494
+ }
495
+
496
+ CRISPASR_GEM_EXPORT const char* crispasr_session_backend(crispasr_session* session) {
497
+ return session ? session->backend.c_str() : "";
498
+ }
499
+
500
+ CRISPASR_GEM_EXPORT const char* crispasr_session_compute_backend(crispasr_session* session) {
501
+ return session && session->cohere_ctx ? cohere_backend_name(session->cohere_ctx) : "";
502
+ }
503
+
504
+ CRISPASR_GEM_EXPORT int crispasr_session_memory(
505
+ crispasr_session* session,
506
+ uint64_t* free_bytes,
507
+ uint64_t* total_bytes) {
508
+ if (free_bytes)
509
+ *free_bytes = 0;
510
+ if (total_bytes)
511
+ *total_bytes = 0;
512
+ if (!session || !session->cohere_ctx || !free_bytes || !total_bytes)
513
+ return -1;
514
+ size_t available = 0;
515
+ size_t total = 0;
516
+ cohere_backend_memory(session->cohere_ctx, &available, &total);
517
+ *free_bytes = static_cast<uint64_t>(available);
518
+ *total_bytes = static_cast<uint64_t>(total);
519
+ return total > 0 ? 0 : -1;
520
+ }
521
+
522
+ CRISPASR_GEM_EXPORT int crispasr_session_batch_capacity(crispasr_session* session) {
523
+ return session && session->cohere_ctx ? crispasr_session_batch_capacity_value() : 0;
524
+ }
525
+
526
+ // Request cancellation only for the operation that is active at this instant.
527
+ // An idle request is deliberately a no-op, so it cannot poison the next call.
528
+ CRISPASR_GEM_EXPORT int crispasr_session_cancel(crispasr_session* session) {
529
+ if (!session)
530
+ return -1;
531
+ auto expected = crispasr_operation_state::running;
532
+ if (session->operation_state.compare_exchange_strong(
533
+ expected,
534
+ crispasr_operation_state::cancel_requested,
535
+ std::memory_order_acq_rel,
536
+ std::memory_order_acquire)) {
537
+ return 1;
538
+ }
539
+ return expected == crispasr_operation_state::cancel_requested ? 1 : 0;
540
+ }
541
+
542
+ CRISPASR_GEM_EXPORT crispasr_session_result* crispasr_session_transcribe_lang(
543
+ crispasr_session* session,
544
+ const float* pcm,
545
+ int n_samples,
546
+ const char* language) {
547
+ crispasr_clear_error();
548
+ if (!session || !session->cohere_ctx || !pcm || n_samples <= 0)
549
+ return crispasr_fail<crispasr_session_result>(
550
+ crispasr_error_kind::invalid_argument,
551
+ "invalid single-row transcription arguments");
552
+ crispasr_operation_guard operation(session);
553
+ if (!operation)
554
+ return crispasr_fail<crispasr_session_result>(
555
+ crispasr_error_kind::invalid_argument,
556
+ "the Cohere session already has an active inference operation");
557
+ if (crispasr_session_abort_requested(session))
558
+ return crispasr_cancelled<crispasr_session_result>();
559
+
560
+ try {
561
+ cohere_set_max_new_tokens(session->cohere_ctx, session->max_new_tokens);
562
+ cohere_set_beam_size(session->cohere_ctx, session->beam_size);
563
+ cohere_set_repetition_loop_guard(session->cohere_ctx, session->repetition_loop_guard);
564
+ const char* source_language = language && language[0] != '\0' ? language : "en";
565
+ std::unique_ptr<cohere_result, decltype(&cohere_result_free)> native_result(
566
+ cohere_transcribe_ex(session->cohere_ctx, pcm, n_samples, source_language, 0),
567
+ &cohere_result_free);
568
+ if (!native_result) {
569
+ if (crispasr_session_abort_requested(session))
570
+ return crispasr_cancelled<crispasr_session_result>();
571
+ crispasr_import_cohere_error(
572
+ crispasr_error_kind::runtime,
573
+ "single-row Cohere inference failed");
574
+ return nullptr;
575
+ }
576
+
577
+ auto result = std::make_unique<crispasr_session_result>();
578
+ crispasr_session_segment segment;
579
+ segment.text = native_result->text ? native_result->text : "";
580
+ segment.t0 = 0;
581
+ segment.t1 = static_cast<int64_t>(static_cast<double>(n_samples) * 100.0 / 16000.0);
582
+
583
+ std::vector<token_record> tokens;
584
+ if (native_result->tokens && native_result->n_tokens > 0) {
585
+ tokens.reserve(static_cast<size_t>(native_result->n_tokens));
586
+ for (int i = 0; i < native_result->n_tokens; ++i) {
587
+ const auto& token = native_result->tokens[i];
588
+ tokens.push_back({token.text, token.t0, token.t1, token.p});
589
+ }
590
+ }
591
+ segment.words = group_words(tokens);
592
+ result->segments.push_back(std::move(segment));
593
+ result->generated_tokens = native_result->generated_tokens;
594
+ result->generation_limit = native_result->generation_limit;
595
+ result->generation_capacity = native_result->generation_capacity;
596
+ result->stopped_by_max_tokens = native_result->stopped_by_max_tokens;
597
+ result->repetition_stopped = native_result->repetition_stopped;
598
+ if (crispasr_session_abort_requested(session))
599
+ return crispasr_cancelled<crispasr_session_result>();
600
+ return result.release();
601
+ } catch (const std::bad_alloc&) {
602
+ return crispasr_fail<crispasr_session_result>(
603
+ crispasr_error_kind::out_of_memory,
604
+ "could not allocate the single-row transcription result");
605
+ } catch (const std::exception& error) {
606
+ return crispasr_fail<crispasr_session_result>(crispasr_error_kind::invariant, error.what());
607
+ } catch (...) {
608
+ return crispasr_fail<crispasr_session_result>(
609
+ crispasr_error_kind::invariant,
610
+ "unknown exception during single-row transcription");
611
+ }
612
+ }
613
+
614
+ CRISPASR_GEM_EXPORT crispasr_session_batch_result* crispasr_session_transcribe_batch_lang(
615
+ crispasr_session* session,
616
+ const float* const* pcm,
617
+ const int* n_samples,
618
+ int n_batch,
619
+ const char* language) {
620
+ crispasr_clear_error();
621
+ // The encoder is microbatched below at its independent eight-lane limit;
622
+ // the logical call is therefore bounded by the decoder's 24-lane cache
623
+ // layout rather than by one encoder graph.
624
+ if (!session || !session->cohere_ctx || !pcm || !n_samples || n_batch < 1 ||
625
+ n_batch > crispasr_session_batch_capacity_value())
626
+ return crispasr_fail<crispasr_session_batch_result>(
627
+ crispasr_error_kind::invalid_argument,
628
+ "invalid batch transcription arguments");
629
+ for (int lane = 0; lane < n_batch; ++lane) {
630
+ if (!pcm[lane] || n_samples[lane] <= 0 || n_samples[lane] > 35 * 16000)
631
+ return crispasr_fail<crispasr_session_batch_result>(
632
+ crispasr_error_kind::invalid_argument,
633
+ "batch audio row is empty or exceeds 35 seconds");
634
+ }
635
+ crispasr_operation_guard operation(session);
636
+ if (!operation)
637
+ return crispasr_fail<crispasr_session_batch_result>(
638
+ crispasr_error_kind::invalid_argument,
639
+ "the Cohere session already has an active inference operation");
640
+ if (crispasr_session_abort_requested(session))
641
+ return crispasr_cancelled<crispasr_session_batch_result>();
642
+ const int64_t total_start_us = ggml_time_us();
643
+ crispasr_session_batch_stats batch_stats{};
644
+
645
+ struct alignment_restore {
646
+ cohere_context* context;
647
+ ~alignment_restore() { cohere_set_alignment_collection(context, true); }
648
+ } restore{session->cohere_ctx};
649
+
650
+ try {
651
+ cohere_set_max_new_tokens(session->cohere_ctx, session->max_new_tokens);
652
+ cohere_set_beam_size(session->cohere_ctx, 1);
653
+ // The independent batch decoder intentionally omits cross-attention
654
+ // collection. Word-aligned calls stay on the single-row path.
655
+ cohere_set_alignment_collection(session->cohere_ctx, false);
656
+
657
+ struct feature_lane {
658
+ int n_mels = 0;
659
+ int T_mel = 0;
660
+ std::vector<float> values;
661
+ };
662
+ std::vector<feature_lane> features(static_cast<size_t>(n_batch));
663
+ enum class feature_failure : int {
664
+ none = 0,
665
+ cancelled,
666
+ compute,
667
+ dimensions,
668
+ overflow,
669
+ };
670
+ std::atomic<int> next_feature_lane{0};
671
+ std::atomic<int64_t> feature_worker_us{0};
672
+ std::atomic<feature_failure> feature_failure_kind{feature_failure::none};
673
+ std::exception_ptr feature_exception;
674
+ std::mutex feature_exception_mutex;
675
+ auto record_feature_failure = [&](feature_failure failure) {
676
+ feature_failure expected = feature_failure::none;
677
+ feature_failure_kind.compare_exchange_strong(expected, failure);
678
+ };
679
+ auto compute_feature_lanes = [&]() {
680
+ try {
681
+ for (;;) {
682
+ if (feature_failure_kind.load() != feature_failure::none)
683
+ return;
684
+ if (crispasr_session_abort_requested(session)) {
685
+ record_feature_failure(feature_failure::cancelled);
686
+ return;
687
+ }
688
+ const int lane = next_feature_lane.fetch_add(1);
689
+ if (lane >= n_batch)
690
+ return;
691
+
692
+ const int64_t feature_lane_start_us = ggml_time_us();
693
+ feature_lane feature;
694
+ std::unique_ptr<float, decltype(&std::free)> raw(
695
+ cohere_compute_mel(
696
+ session->cohere_ctx,
697
+ pcm[lane],
698
+ n_samples[lane],
699
+ &feature.n_mels,
700
+ &feature.T_mel),
701
+ &std::free);
702
+ if (!raw) {
703
+ record_feature_failure(
704
+ crispasr_session_abort_requested(session)
705
+ ? feature_failure::cancelled
706
+ : feature_failure::compute);
707
+ return;
708
+ }
709
+ if (feature.n_mels <= 0 || feature.T_mel <= 0) {
710
+ record_feature_failure(feature_failure::dimensions);
711
+ return;
712
+ }
713
+ if (static_cast<size_t>(feature.T_mel) >
714
+ SIZE_MAX / static_cast<size_t>(feature.n_mels)) {
715
+ record_feature_failure(feature_failure::overflow);
716
+ return;
717
+ }
718
+ const size_t value_count =
719
+ static_cast<size_t>(feature.n_mels) * feature.T_mel;
720
+ feature.values.assign(raw.get(), raw.get() + value_count);
721
+ features[static_cast<size_t>(lane)] = std::move(feature);
722
+ feature_worker_us.fetch_add(
723
+ ggml_time_us() - feature_lane_start_us,
724
+ std::memory_order_relaxed);
725
+ }
726
+ } catch (...) {
727
+ {
728
+ std::lock_guard<std::mutex> lock(feature_exception_mutex);
729
+ if (!feature_exception)
730
+ feature_exception = std::current_exception();
731
+ }
732
+ record_feature_failure(feature_failure::compute);
733
+ }
734
+ };
735
+
736
+ int feature_worker_count = 1;
737
+ #if !defined(_OPENMP)
738
+ // The packaged build does not use OpenMP, so each frontend call is
739
+ // serial and independent rows can share the session's bounded CPU
740
+ // budget. OpenMP builds retain one outer worker because their frontend
741
+ // already distributes frames across the configured thread count.
742
+ feature_worker_count = std::min(n_batch, std::max(1, session->n_threads));
743
+ #endif
744
+ std::vector<std::jthread> feature_workers;
745
+ const int64_t feature_wall_start_us = ggml_time_us();
746
+ feature_workers.reserve(static_cast<size_t>(feature_worker_count - 1));
747
+ for (int worker = 1; worker < feature_worker_count; ++worker)
748
+ feature_workers.emplace_back(compute_feature_lanes);
749
+ compute_feature_lanes();
750
+ for (auto& worker : feature_workers)
751
+ worker.join();
752
+ batch_stats.feature_wall_us = ggml_time_us() - feature_wall_start_us;
753
+ batch_stats.feature_worker_us = feature_worker_us.load(std::memory_order_relaxed);
754
+
755
+ if (feature_exception)
756
+ std::rethrow_exception(feature_exception);
757
+ if (crispasr_session_abort_requested(session))
758
+ return crispasr_cancelled<crispasr_session_batch_result>();
759
+ switch (feature_failure_kind.load()) {
760
+ case feature_failure::none:
761
+ break;
762
+ case feature_failure::cancelled:
763
+ return crispasr_cancelled<crispasr_session_batch_result>();
764
+ case feature_failure::compute:
765
+ return crispasr_fail<crispasr_session_batch_result>(
766
+ crispasr_error_kind::runtime,
767
+ "mel feature extraction failed");
768
+ case feature_failure::dimensions:
769
+ return crispasr_fail<crispasr_session_batch_result>(
770
+ crispasr_error_kind::invariant,
771
+ "mel feature extraction returned invalid dimensions");
772
+ case feature_failure::overflow:
773
+ return crispasr_fail<crispasr_session_batch_result>(
774
+ crispasr_error_kind::invariant,
775
+ "mel feature dimensions overflow size_t");
776
+ }
777
+
778
+ const int n_mels = features.front().n_mels;
779
+ int T_mel_max = 0;
780
+ for (const auto& feature : features) {
781
+ if (feature.n_mels != n_mels)
782
+ return crispasr_fail<crispasr_session_batch_result>(
783
+ crispasr_error_kind::invariant,
784
+ "mel feature dimensions differ across batch rows");
785
+ T_mel_max = std::max(T_mel_max, feature.T_mel);
786
+ }
787
+
788
+ const int logical_T_enc_max = cohere_encoder_padded::encoder_length(T_mel_max);
789
+ if (logical_T_enc_max < 1 || logical_T_enc_max > cohere_decoder_batch::max_encoder_frames)
790
+ return crispasr_fail<crispasr_session_batch_result>(
791
+ crispasr_error_kind::invariant,
792
+ "encoder length is outside the decoder batch layout");
793
+ std::vector<int> valid_T_enc(static_cast<size_t>(n_batch));
794
+ int d_model = 0;
795
+ std::vector<float> encoded_states;
796
+ for (int first_lane = 0; first_lane < n_batch; first_lane += cohere_encoder_padded::max_batch) {
797
+ if (crispasr_session_abort_requested(session))
798
+ return crispasr_cancelled<crispasr_session_batch_result>();
799
+ const int physical_batch = std::min(cohere_encoder_padded::max_batch, n_batch - first_lane);
800
+ int physical_T_mel_max = 0;
801
+ for (int physical_lane = 0; physical_lane < physical_batch; ++physical_lane) {
802
+ const auto& feature = features[static_cast<size_t>(first_lane + physical_lane)];
803
+ physical_T_mel_max = std::max(physical_T_mel_max, feature.T_mel);
804
+ }
805
+ if (physical_T_mel_max < 1 ||
806
+ static_cast<size_t>(physical_T_mel_max) >
807
+ SIZE_MAX / static_cast<size_t>(n_mels) / static_cast<size_t>(physical_batch) / sizeof(float)) {
808
+ return crispasr_fail<crispasr_session_batch_result>(
809
+ crispasr_error_kind::invariant,
810
+ "encoder microbatch dimensions overflow size_t");
811
+ }
812
+
813
+ const size_t mel_lane_stride = static_cast<size_t>(physical_T_mel_max) * n_mels;
814
+ const int64_t mel_pack_start_us = ggml_time_us();
815
+ std::vector<float> packed_mel(static_cast<size_t>(physical_batch) * mel_lane_stride, 0.0f);
816
+ std::vector<int> physical_T_mel(static_cast<size_t>(physical_batch));
817
+ for (int physical_lane = 0; physical_lane < physical_batch; ++physical_lane) {
818
+ const auto& feature = features[static_cast<size_t>(first_lane + physical_lane)];
819
+ physical_T_mel[static_cast<size_t>(physical_lane)] = feature.T_mel;
820
+ std::copy(
821
+ feature.values.begin(),
822
+ feature.values.end(),
823
+ packed_mel.begin() + static_cast<size_t>(physical_lane) * mel_lane_stride);
824
+ }
825
+ batch_stats.mel_pack_us += ggml_time_us() - mel_pack_start_us;
826
+
827
+ std::vector<int> physical_T_enc(static_cast<size_t>(physical_batch));
828
+ int physical_T_enc_max = 0;
829
+ int physical_d_model = 0;
830
+ cohere_encoder_batch_stats encoder_stats{};
831
+ std::unique_ptr<float, decltype(&std::free)> encoded(
832
+ cohere_run_encoder_batch_padded(
833
+ session->cohere_ctx,
834
+ packed_mel.data(),
835
+ physical_T_mel.data(),
836
+ physical_batch,
837
+ n_mels,
838
+ physical_T_mel_max,
839
+ physical_T_enc.data(),
840
+ &physical_T_enc_max,
841
+ &physical_d_model,
842
+ &encoder_stats),
843
+ &std::free);
844
+ batch_stats.encoder_microbatches++;
845
+ batch_stats.encoder_graph_build_us += encoder_stats.graph_build_us;
846
+ batch_stats.encoder_graph_alloc_us += encoder_stats.graph_alloc_us;
847
+ batch_stats.encoder_input_us += encoder_stats.input_us;
848
+ batch_stats.encoder_compute_us += encoder_stats.compute_us;
849
+ batch_stats.encoder_readback_us += encoder_stats.readback_us;
850
+ if (!encoded) {
851
+ if (crispasr_session_abort_requested(session))
852
+ return crispasr_cancelled<crispasr_session_batch_result>();
853
+ crispasr_import_cohere_error(
854
+ crispasr_error_kind::runtime,
855
+ "padded encoder microbatch failed");
856
+ return nullptr;
857
+ }
858
+ if (physical_T_enc_max <= 0 || physical_T_enc_max > logical_T_enc_max ||
859
+ physical_d_model <= 0 || (d_model > 0 && physical_d_model != d_model))
860
+ return crispasr_fail<crispasr_session_batch_result>(
861
+ crispasr_error_kind::invariant,
862
+ "padded encoder returned inconsistent dimensions");
863
+
864
+ const int64_t encoder_repack_start_us = ggml_time_us();
865
+ if (d_model == 0) {
866
+ d_model = physical_d_model;
867
+ if (static_cast<size_t>(n_batch) >
868
+ SIZE_MAX / static_cast<size_t>(logical_T_enc_max) /
869
+ static_cast<size_t>(d_model) / sizeof(float)) {
870
+ return crispasr_fail<crispasr_session_batch_result>(
871
+ crispasr_error_kind::invariant,
872
+ "logical encoder batch dimensions overflow size_t");
873
+ }
874
+ encoded_states.assign(
875
+ static_cast<size_t>(n_batch) * logical_T_enc_max * d_model,
876
+ 0.0f);
877
+ }
878
+
879
+ const size_t source_lane_stride = static_cast<size_t>(physical_T_enc_max) * d_model;
880
+ const size_t destination_lane_stride = static_cast<size_t>(logical_T_enc_max) * d_model;
881
+ for (int physical_lane = 0; physical_lane < physical_batch; ++physical_lane) {
882
+ const int valid = physical_T_enc[static_cast<size_t>(physical_lane)];
883
+ if (valid < 1 || valid > physical_T_enc_max)
884
+ return crispasr_fail<crispasr_session_batch_result>(
885
+ crispasr_error_kind::invariant,
886
+ "padded encoder returned an invalid row length");
887
+ const int logical_lane = first_lane + physical_lane;
888
+ valid_T_enc[static_cast<size_t>(logical_lane)] = valid;
889
+ std::copy_n(
890
+ encoded.get() + static_cast<size_t>(physical_lane) * source_lane_stride,
891
+ static_cast<size_t>(valid) * d_model,
892
+ encoded_states.begin() + static_cast<size_t>(logical_lane) * destination_lane_stride);
893
+ }
894
+ batch_stats.encoder_repack_us += ggml_time_us() - encoder_repack_start_us;
895
+ if (crispasr_session_abort_requested(session))
896
+ return crispasr_cancelled<crispasr_session_batch_result>();
897
+ }
898
+ if (d_model <= 0 || encoded_states.empty())
899
+ return crispasr_fail<crispasr_session_batch_result>(
900
+ crispasr_error_kind::invariant,
901
+ "padded encoder produced no logical batch state");
902
+
903
+ std::unique_ptr<cohere_decoder_batch_generate_result,
904
+ decltype(&cohere_decoder_batch_generate_result_free)>
905
+ generated(
906
+ cohere_run_decoder_batch_generate_ex(
907
+ session->cohere_ctx,
908
+ encoded_states.data(),
909
+ valid_T_enc.data(),
910
+ n_batch,
911
+ logical_T_enc_max,
912
+ d_model,
913
+ language && language[0] != '\0' ? language : "en",
914
+ session->max_new_tokens,
915
+ // Ruby publishes the selected token stream, not the decoder's
916
+ // per-token softmax values. Reduce logits on the compute backend
917
+ // so each step transfers one token ID per lane instead of the
918
+ // complete batch-by-vocabulary matrix.
919
+ COHERE_DECODER_BATCH_OUTPUT_DEVICE_ARGMAX),
920
+ &cohere_decoder_batch_generate_result_free);
921
+ if (!generated) {
922
+ if (crispasr_session_abort_requested(session))
923
+ return crispasr_cancelled<crispasr_session_batch_result>();
924
+ crispasr_import_cohere_error(
925
+ crispasr_error_kind::runtime,
926
+ "ragged decoder batch failed");
927
+ return nullptr;
928
+ }
929
+ if (generated->n_batch != n_batch || !generated->sequences)
930
+ return crispasr_fail<crispasr_session_batch_result>(
931
+ crispasr_error_kind::invariant,
932
+ "ragged decoder returned an inconsistent batch result");
933
+ batch_stats.decoder_total_us = generated->stats.total_us;
934
+ batch_stats.decoder_cross_kv_us = generated->stats.cross_kv_us;
935
+ batch_stats.decoder_reserve_us = generated->stats.reserve_us;
936
+ batch_stats.decoder_decode_us = generated->stats.decode_us;
937
+ batch_stats.decoder_calls = generated->stats.decode_calls;
938
+ batch_stats.generation_steps = generated->stats.generation_steps;
939
+ batch_stats.token_id_readback_bytes = static_cast<int64_t>(generated->stats.token_id_readback_bytes);
940
+
941
+ const int64_t render_start_us = ggml_time_us();
942
+ const int vocabulary_size = cohere_n_vocab(session->cohere_ctx);
943
+ if (vocabulary_size <= 0)
944
+ return crispasr_fail<crispasr_session_batch_result>(
945
+ crispasr_error_kind::invariant,
946
+ "model vocabulary is empty");
947
+ std::vector<std::string> vocabulary(static_cast<size_t>(vocabulary_size));
948
+ for (int token = 0; token < vocabulary_size; ++token) {
949
+ const char* piece = cohere_token_to_str(session->cohere_ctx, token);
950
+ if (piece)
951
+ vocabulary[static_cast<size_t>(token)] = piece;
952
+ }
953
+ const cohere_token_renderer::speaker_token_ids speaker_tokens = {
954
+ cohere_str_to_token(session->cohere_ctx, "<|spkchange|>"),
955
+ cohere_str_to_token(session->cohere_ctx, "<|spk0|>"),
956
+ };
957
+
958
+ auto output = std::make_unique<crispasr_session_batch_result>();
959
+ output->lanes.reserve(static_cast<size_t>(n_batch));
960
+ for (int lane = 0; lane < n_batch; ++lane) {
961
+ if (crispasr_session_abort_requested(session))
962
+ return crispasr_cancelled<crispasr_session_batch_result>();
963
+ const auto& sequence = generated->sequences[lane];
964
+ if (sequence.n_tokens < 0 ||
965
+ (sequence.n_tokens > 0 && (!sequence.token_ids || !sequence.probabilities))) {
966
+ return crispasr_fail<crispasr_session_batch_result>(
967
+ crispasr_error_kind::invariant,
968
+ "ragged decoder returned an invalid token sequence");
969
+ }
970
+
971
+ std::vector<int> token_ids;
972
+ std::vector<float> probabilities;
973
+ if (sequence.n_tokens > 0) {
974
+ token_ids.assign(sequence.token_ids, sequence.token_ids + sequence.n_tokens);
975
+ probabilities.assign(sequence.probabilities, sequence.probabilities + sequence.n_tokens);
976
+ }
977
+
978
+ bool repetition_stopped = false;
979
+ if (session->repetition_loop_guard) {
980
+ const size_t stop_length = core_repetition_loop::first_trigger_length(token_ids);
981
+ repetition_stopped = stop_length > 0;
982
+ if (repetition_stopped) {
983
+ token_ids.resize(stop_length);
984
+ probabilities.resize(stop_length);
985
+ }
986
+ }
987
+
988
+ const auto rendered = cohere_token_renderer::render(
989
+ token_ids, probabilities, vocabulary, speaker_tokens);
990
+ if (!rendered.ok())
991
+ return crispasr_fail<crispasr_session_batch_result>(
992
+ crispasr_error_kind::invariant,
993
+ "token renderer rejected the ragged decoder output");
994
+
995
+ auto result = std::make_unique<crispasr_session_result>();
996
+ crispasr_session_segment segment;
997
+ segment.text = rendered.full_text;
998
+ segment.t0 = 0;
999
+ segment.t1 = static_cast<int64_t>(static_cast<double>(n_samples[lane]) * 100.0 / 16000.0);
1000
+ segment.words = group_words(timed_token_records(rendered, n_samples[lane]));
1001
+ result->segments.push_back(std::move(segment));
1002
+ const bool saw_eos = sequence.stop_reason == COHERE_GENERATION_STOP_EOS;
1003
+ result->generated_tokens = static_cast<int>(token_ids.size()) + (saw_eos && !repetition_stopped ? 1 : 0);
1004
+ result->generation_limit = sequence.stop_reason == COHERE_GENERATION_STOP_MAX_TOKENS
1005
+ ? sequence.n_tokens
1006
+ : session->max_new_tokens;
1007
+ result->generation_capacity = generated->generation_capacity;
1008
+ result->stopped_by_max_tokens =
1009
+ !repetition_stopped && sequence.stop_reason == COHERE_GENERATION_STOP_MAX_TOKENS;
1010
+ result->repetition_stopped = repetition_stopped;
1011
+ output->lanes.push_back(std::move(result));
1012
+ }
1013
+ if (crispasr_session_abort_requested(session))
1014
+ return crispasr_cancelled<crispasr_session_batch_result>();
1015
+ batch_stats.render_us = ggml_time_us() - render_start_us;
1016
+ batch_stats.total_us = ggml_time_us() - total_start_us;
1017
+ output->stats = batch_stats;
1018
+ return output.release();
1019
+ } catch (const std::bad_alloc&) {
1020
+ return crispasr_fail<crispasr_session_batch_result>(
1021
+ crispasr_error_kind::out_of_memory,
1022
+ "could not allocate the batch transcription result");
1023
+ } catch (const std::exception& error) {
1024
+ return crispasr_fail<crispasr_session_batch_result>(crispasr_error_kind::invariant, error.what());
1025
+ } catch (...) {
1026
+ return crispasr_fail<crispasr_session_batch_result>(
1027
+ crispasr_error_kind::invariant,
1028
+ "unknown exception during batch transcription");
1029
+ }
1030
+ }
1031
+
1032
+ CRISPASR_GEM_EXPORT int crispasr_session_batch_result_count(crispasr_session_batch_result* result) {
1033
+ return result ? static_cast<int>(result->lanes.size()) : 0;
1034
+ }
1035
+
1036
+ CRISPASR_GEM_EXPORT int crispasr_session_batch_result_stats_v1(
1037
+ crispasr_session_batch_result* result,
1038
+ int64_t* values,
1039
+ int capacity) {
1040
+ constexpr int64_t abi_version = 1;
1041
+ constexpr int64_t field_count = 21;
1042
+ if (!result || !values || capacity <= 0)
1043
+ return field_count;
1044
+ const auto& stats = result->stats;
1045
+ const int64_t fields[field_count] = {
1046
+ abi_version,
1047
+ field_count,
1048
+ stats.total_us,
1049
+ stats.feature_wall_us,
1050
+ stats.feature_worker_us,
1051
+ stats.mel_pack_us,
1052
+ stats.encoder_graph_build_us,
1053
+ stats.encoder_graph_alloc_us,
1054
+ stats.encoder_input_us,
1055
+ stats.encoder_compute_us,
1056
+ stats.encoder_readback_us,
1057
+ stats.encoder_repack_us,
1058
+ stats.decoder_total_us,
1059
+ stats.decoder_cross_kv_us,
1060
+ stats.decoder_reserve_us,
1061
+ stats.decoder_decode_us,
1062
+ stats.render_us,
1063
+ stats.decoder_calls,
1064
+ stats.generation_steps,
1065
+ stats.encoder_microbatches,
1066
+ stats.token_id_readback_bytes,
1067
+ };
1068
+ std::copy_n(fields, std::min(capacity, static_cast<int>(field_count)), values);
1069
+ return field_count;
1070
+ }
1071
+
1072
+ CRISPASR_GEM_EXPORT crispasr_session_result* crispasr_session_batch_result_at(
1073
+ crispasr_session_batch_result* result,
1074
+ int lane) {
1075
+ return result && lane >= 0 && lane < static_cast<int>(result->lanes.size())
1076
+ ? result->lanes[static_cast<size_t>(lane)].get()
1077
+ : nullptr;
1078
+ }
1079
+
1080
+ CRISPASR_GEM_EXPORT void crispasr_session_batch_result_free(crispasr_session_batch_result* result) {
1081
+ delete result;
1082
+ }
1083
+
1084
+ CRISPASR_GEM_EXPORT int crispasr_session_result_n_segments(crispasr_session_result* result) {
1085
+ return result ? static_cast<int>(result->segments.size()) : 0;
1086
+ }
1087
+
1088
+ CRISPASR_GEM_EXPORT const char* crispasr_session_result_segment_text(crispasr_session_result* result, int index) {
1089
+ return result && index >= 0 && index < static_cast<int>(result->segments.size())
1090
+ ? result->segments[static_cast<size_t>(index)].text.c_str()
1091
+ : "";
1092
+ }
1093
+
1094
+ CRISPASR_GEM_EXPORT int64_t crispasr_session_result_segment_t0(crispasr_session_result* result, int index) {
1095
+ return result && index >= 0 && index < static_cast<int>(result->segments.size())
1096
+ ? result->segments[static_cast<size_t>(index)].t0
1097
+ : 0;
1098
+ }
1099
+
1100
+ CRISPASR_GEM_EXPORT int64_t crispasr_session_result_segment_t1(crispasr_session_result* result, int index) {
1101
+ return result && index >= 0 && index < static_cast<int>(result->segments.size())
1102
+ ? result->segments[static_cast<size_t>(index)].t1
1103
+ : 0;
1104
+ }
1105
+
1106
+ CRISPASR_GEM_EXPORT int crispasr_session_result_n_words(crispasr_session_result* result, int segment_index) {
1107
+ if (!result || segment_index < 0 || segment_index >= static_cast<int>(result->segments.size()))
1108
+ return 0;
1109
+ return static_cast<int>(result->segments[static_cast<size_t>(segment_index)].words.size());
1110
+ }
1111
+
1112
+ static const crispasr_session_word* result_word(
1113
+ crispasr_session_result* result,
1114
+ int segment_index,
1115
+ int word_index) {
1116
+ if (!result || segment_index < 0 || segment_index >= static_cast<int>(result->segments.size()))
1117
+ return nullptr;
1118
+ const auto& words = result->segments[static_cast<size_t>(segment_index)].words;
1119
+ if (word_index < 0 || word_index >= static_cast<int>(words.size()))
1120
+ return nullptr;
1121
+ return &words[static_cast<size_t>(word_index)];
1122
+ }
1123
+
1124
+ CRISPASR_GEM_EXPORT const char* crispasr_session_result_word_text(
1125
+ crispasr_session_result* result,
1126
+ int segment_index,
1127
+ int word_index) {
1128
+ const auto* word = result_word(result, segment_index, word_index);
1129
+ return word ? word->text.c_str() : "";
1130
+ }
1131
+
1132
+ CRISPASR_GEM_EXPORT int64_t crispasr_session_result_word_t0(
1133
+ crispasr_session_result* result,
1134
+ int segment_index,
1135
+ int word_index) {
1136
+ const auto* word = result_word(result, segment_index, word_index);
1137
+ return word ? word->t0 : 0;
1138
+ }
1139
+
1140
+ CRISPASR_GEM_EXPORT int64_t crispasr_session_result_word_t1(
1141
+ crispasr_session_result* result,
1142
+ int segment_index,
1143
+ int word_index) {
1144
+ const auto* word = result_word(result, segment_index, word_index);
1145
+ return word ? word->t1 : 0;
1146
+ }
1147
+
1148
+ CRISPASR_GEM_EXPORT float crispasr_session_result_word_p(
1149
+ crispasr_session_result* result,
1150
+ int segment_index,
1151
+ int word_index) {
1152
+ const auto* word = result_word(result, segment_index, word_index);
1153
+ return word ? word->p : -1.0f;
1154
+ }
1155
+
1156
+ CRISPASR_GEM_EXPORT int crispasr_session_result_generated_tokens(crispasr_session_result* result) {
1157
+ return result ? result->generated_tokens : 0;
1158
+ }
1159
+
1160
+ CRISPASR_GEM_EXPORT int crispasr_session_result_generation_limit(crispasr_session_result* result) {
1161
+ return result ? result->generation_limit : 0;
1162
+ }
1163
+
1164
+ CRISPASR_GEM_EXPORT int crispasr_session_result_generation_capacity(crispasr_session_result* result) {
1165
+ return result ? result->generation_capacity : 0;
1166
+ }
1167
+
1168
+ CRISPASR_GEM_EXPORT int crispasr_session_result_stopped_by_max_tokens(crispasr_session_result* result) {
1169
+ return result && result->stopped_by_max_tokens ? 1 : 0;
1170
+ }
1171
+
1172
+ CRISPASR_GEM_EXPORT int crispasr_session_result_repetition_stopped(crispasr_session_result* result) {
1173
+ return result && result->repetition_stopped ? 1 : 0;
1174
+ }
1175
+
1176
+ CRISPASR_GEM_EXPORT void crispasr_session_result_free(crispasr_session_result* result) {
1177
+ delete result;
1178
+ }
1179
+
1180
+ CRISPASR_GEM_EXPORT void crispasr_session_close(crispasr_session* session) {
1181
+ if (!session)
1182
+ return;
1183
+ cohere_free(session->cohere_ctx);
1184
+ delete session;
1185
+ }
1186
+
1187
+ CRISPASR_GEM_EXPORT int crispasr_session_set_max_new_tokens(crispasr_session* session, int count) {
1188
+ if (!session)
1189
+ return -1;
1190
+ session->max_new_tokens = count > 0 ? count : 0;
1191
+ cohere_set_max_new_tokens(session->cohere_ctx, session->max_new_tokens);
1192
+ return 0;
1193
+ }
1194
+
1195
+ CRISPASR_GEM_EXPORT int crispasr_session_set_beam_size(crispasr_session* session, int width) {
1196
+ if (!session)
1197
+ return -1;
1198
+ session->beam_size = width > 0 ? width : 1;
1199
+ cohere_set_beam_size(session->cohere_ctx, session->beam_size);
1200
+ return 0;
1201
+ }
1202
+
1203
+ CRISPASR_GEM_EXPORT int crispasr_session_set_repetition_loop_guard(crispasr_session* session, int enabled) {
1204
+ if (!session)
1205
+ return -1;
1206
+ session->repetition_loop_guard = enabled != 0;
1207
+ cohere_set_repetition_loop_guard(session->cohere_ctx, session->repetition_loop_guard);
1208
+ return 0;
1209
+ }