1#![allow(non_camel_case_types)]
6
7use std::os::raw::{c_char, c_float, c_int, c_void};
8
9pub type baseRT_model_t = *mut c_void;
11
12#[repr(C)]
21#[derive(Debug, Clone, Copy)]
22pub struct BaseRTModelConfig {
23 pub dim: u32,
25 pub n_layers: u32,
26 pub n_heads: u32,
27 pub n_kv_heads: u32,
28 pub head_dim: u32,
29 pub q_dim: u32,
30 pub kv_dim: u32,
31 pub ffn_dim: u32,
32 pub vocab_size: u32,
33 pub max_seq_len: u32,
34 pub norm_eps: c_float,
35 pub rope_theta: c_float,
36 pub sliding_window_pattern: u32,
37 pub sliding_window: u32,
38 pub rope_local_theta: c_float,
39 pub architecture: [c_char; 32],
40
41 pub enc_n_layers: u32,
43 pub enc_n_heads: u32,
44 pub enc_dim: u32,
45 pub enc_ffn_dim: u32,
46 pub n_mels: u32,
47 pub enc_max_seq_len: u32,
48
49 pub n_embd_per_layer: u32,
51 pub n_layer_kv_from_start: u32,
52 pub logit_softcap: c_float,
53 pub attention_scale: c_float,
54 pub head_dim_swa: u32,
55 pub head_dim_global: u32,
56 pub global_rope_partial_factor: c_float,
57 pub swa_layers: [u8; 64],
58 pub ffn_dims: [u32; 128],
59 pub n_kv_heads_per_layer: [u32; 128],
60
61 pub attn_output_gate: u8,
63 pub _qwen35_pad: [u8; 3],
64 pub partial_rotary_factor: c_float,
65 pub full_attention_interval: u32,
66 pub linear_attn_layers: [u8; 64],
67 pub gdn_num_k_heads: u32,
68 pub gdn_num_v_heads: u32,
69 pub gdn_key_head_dim: u32,
70 pub gdn_value_head_dim: u32,
71 pub gdn_conv_kernel: u32,
72
73 pub ssm_state_size: u32,
75 pub ssm_conv_kernel: u32,
76 pub ssm_num_groups: u32,
77 pub ssm_inner_size: u32,
78 pub ssm_num_heads: u32,
79
80 pub n_experts: u32,
82 pub n_experts_used: u32,
83 pub n_experts_shared: u32,
84 pub expert_ffn_dim: u32,
85 pub expert_gating: u8,
86 pub norm_topk_prob: u8,
87 pub _moe_pad: [u8; 2],
88 pub expert_weights_scale: c_float,
89
90 pub vision_n_layers: u32,
92 pub vision_dim: u32,
93 pub vision_n_heads: u32,
94 pub vision_head_dim: u32,
95 pub vision_ffn_dim: u32,
96 pub vision_patch_size: u32,
97 pub vision_image_size: u32,
98 pub vision_pooling_kernel: u32,
99 pub vision_soft_tokens: u32,
100 pub vision_norm_eps: c_float,
101 pub vision_rope_theta: c_float,
102 pub vision_pos_embed_size: u32,
103 pub image_token_id: u32,
104 pub boi_token_id: u32,
105 pub eoi_token_id: u32,
106
107 pub vision_arch: u32,
109 pub vision_spatial_merge: u32,
110 pub vision_temporal_patch: u32,
111 pub vision_out_dim: u32,
112
113 pub audio_n_layers: u32,
115 pub audio_dim: u32,
116 pub audio_n_heads: u32,
117 pub audio_head_dim: u32,
118 pub audio_ffn_dim: u32,
119 pub audio_output_proj_dim: u32,
120 pub audio_chunk_size: u32,
121 pub audio_left_context: u32,
122 pub audio_conv_kernel: u32,
123 pub audio_soft_tokens: u32,
124 pub audio_logit_softcap: c_float,
125 pub audio_norm_eps: c_float,
126 pub audio_gradient_clip: c_float,
127 pub audio_residual_weight: c_float,
128 pub audio_ms_per_token: c_float,
129 pub audio_sscp_channels: [u32; 2],
130 pub audio_token_id: u32,
131 pub boa_token_id: u32,
132 pub eoa_token_id: u32,
133 pub mrope_section: [u32; 3],
134 pub mrope_interleaved: u8,
135 pub _mrope_pad: [u8; 3],
136 pub rope_scaling_factor: c_float,
137 pub rope_low_freq_factor: c_float,
138 pub rope_high_freq_factor: c_float,
139 pub rope_orig_max_pos: u32,
140 pub rope_scaling_type: u32,
141 pub qk_scale_factor: c_float,
143 pub output_multiplier: c_float,
144 pub post_norm_eps: c_float,
145 pub nope_layers: [u8; 64],
146 pub embed_norm_eps: c_float,
147 pub vision_window_layers: [u8; 64],
148 pub vision_window_size: u32,
149 pub vision_pos_embed_h: u32,
150 pub vision_pos_embed_w: u32,
151 pub vision_adapter_dim: u32,
152 pub video_token_id: u32,
153 pub q_lora_rank: u32,
155 pub kv_lora_rank: u32,
156 pub qk_nope_head_dim: u32,
157 pub qk_rope_head_dim: u32,
158 pub v_head_dim: u32,
159 pub routed_scaling_factor: c_float,
160 pub first_k_dense_replace: u32,
161 pub nextn_predict_layers: u32,
162 pub indexer_head_count: u32,
163 pub indexer_key_length: u32,
164 pub indexer_top_k: u32,
165 pub rope_yarn_beta_fast: f32,
167 pub rope_yarn_beta_slow: f32,
168 pub swiglu_limit: f32,
169 pub swiglu_alpha: f32,
170 pub attention_sinks: u8,
171 pub attention_bias: u8,
172 pub rope_yarn_truncate: u8,
173 pub _gptoss_pad: u8,
174}
175
176#[repr(C)]
178#[derive(Debug, Clone, Copy, Default)]
179pub struct BaseRTTranscribeStats {
180 pub n_tokens: c_int,
181 pub audio_ms: c_float,
182 pub encode_ms: c_float,
183 pub decode_ms: c_float,
184 pub total_ms: c_float,
185}
186
187#[repr(C)]
191#[derive(Debug, Clone, Copy)]
192pub struct BaseRTTranscribeSegment {
193 pub start_ms: c_int,
194 pub end_ms: c_int,
195 pub text: *const c_char,
196 pub avg_logprob: c_float,
197 pub no_speech_prob: c_float,
198 pub compression_ratio: c_float,
199 pub temperature: c_float,
200}
201
202impl Default for BaseRTTranscribeSegment {
203 fn default() -> Self {
204 Self {
205 start_ms: 0,
206 end_ms: 0,
207 text: std::ptr::null(),
208 avg_logprob: 0.0,
209 no_speech_prob: 0.0,
210 compression_ratio: 0.0,
211 temperature: 0.0,
212 }
213 }
214}
215
216#[repr(C)]
223#[derive(Debug, Clone, Copy)]
224pub struct BaseRTSamplingConfig {
225 pub temperature: c_float,
226 pub top_k: c_int,
227 pub top_p: c_float,
228 pub min_p: c_float,
229 pub repeat_penalty: c_float,
230 pub presence_penalty: c_float,
231 pub frequency_penalty: c_float,
232 pub seed: u32,
233 pub n_logit_bias: i32,
234 pub logit_bias_tokens: *const i32,
235 pub logit_bias_values: *const c_float,
236}
237
238impl Default for BaseRTSamplingConfig {
239 fn default() -> Self {
240 Self {
241 temperature: 0.0,
242 top_k: 40,
243 top_p: 0.9,
244 min_p: 0.0,
245 repeat_penalty: 1.0,
246 presence_penalty: 0.0,
247 frequency_penalty: 0.0,
248 seed: 0,
249 n_logit_bias: 0,
250 logit_bias_tokens: std::ptr::null(),
251 logit_bias_values: std::ptr::null(),
252 }
253 }
254}
255
256#[repr(C)]
258#[derive(Debug, Clone, Copy, Default)]
259pub struct BaseRTGenerationStats {
260 pub prompt_tokens: c_int,
261 pub generated_tokens: c_int,
262 pub prefill_time_ms: c_float,
263 pub decode_time_ms: c_float,
264 pub prefill_tokens_per_sec: c_float,
265 pub decode_tokens_per_sec: c_float,
266}
267
268pub type baseRT_sequence_t = *mut c_void;
271
272#[repr(C)]
277#[derive(Debug, Clone, Copy)]
278pub struct BaseRTPrefixMatch {
279 pub matched_tokens: c_int,
280 pub n_blocks: c_int,
281 pub blocks: *const c_int,
282 pub handle: u64,
283}
284
285pub type baseRT_token_callback = Option<
287 unsafe extern "C" fn(token_id: u32, text: *const c_char, user_data: *mut c_void) -> bool,
288>;
289
290pub type baseRT_segment_callback = Option<
292 unsafe extern "C" fn(
293 start_ms: c_int,
294 end_ms: c_int,
295 text: *const c_char,
296 user_data: *mut c_void,
297 ) -> bool,
298>;
299
300extern "C" {
301 pub fn baseRT_load_model(
304 model_path: *const c_char,
305 kernel_library_path: *const c_char,
306 max_context: c_int,
307 ) -> baseRT_model_t;
308
309 pub fn baseRT_free_model(model: baseRT_model_t);
310 pub fn baseRT_load_tokenizer_only(model_path: *const c_char) -> baseRT_model_t;
313
314 pub fn baseRT_get_config(model: baseRT_model_t) -> BaseRTModelConfig;
317 pub fn baseRT_model_config_sizeof() -> usize;
318 pub fn baseRT_model_memory(model: baseRT_model_t) -> usize;
319 pub fn baseRT_device_memory_budget() -> usize;
322 pub fn baseRT_suggest_max_context(
325 model_path: *const c_char,
326 max_batch: c_int,
327 kv_bits: c_int,
328 paged_kv: c_int,
329 ) -> c_int;
330 pub fn baseRT_suggest_max_context_multi(
334 model_paths: *const *const c_char,
335 n_models: c_int,
336 max_batch: c_int,
337 kv_bits: c_int,
338 paged_kv: c_int,
339 ) -> c_int;
340 pub fn baseRT_suggest_max_context_spec(
349 model_paths: *const *const c_char,
350 n_models: c_int,
351 speculator_paths: *const *const c_char,
352 speculator_embedded: *const c_int,
353 speculator_target: *const c_int,
354 n_speculators: c_int,
355 max_batch: c_int,
356 kv_bits: c_int,
357 paged_kv: c_int,
358 ) -> c_int;
359 pub fn baseRT_context_window_fits(
361 model_paths: *const *const c_char,
362 n_models: c_int,
363 max_batch: c_int,
364 kv_bits: c_int,
365 paged_kv: c_int,
366 window: c_int,
367 ) -> c_int;
368 pub fn baseRT_get_error() -> *const c_char;
369
370 pub fn baseRT_encode(
373 model: baseRT_model_t,
374 text: *const c_char,
375 out_tokens: *mut u32,
376 max_tokens: c_int,
377 ) -> c_int;
378 pub fn baseRT_encode_plain(
381 model: baseRT_model_t,
382 text: *const c_char,
383 out_tokens: *mut u32,
384 max_tokens: c_int,
385 ) -> c_int;
386 pub fn baseRT_encode_pieces(
390 model: baseRT_model_t,
391 texts: *const *const c_char,
392 plain: *const c_int,
393 n_pieces: c_int,
394 out_tokens: *mut u32,
395 max_tokens: c_int,
396 ) -> c_int;
397
398 pub fn baseRT_decode_token(model: baseRT_model_t, token_id: u32) -> *const c_char;
399 pub fn baseRT_decode_token_raw(
402 model: baseRT_model_t,
403 token_id: u32,
404 out: *mut c_char,
405 max_bytes: c_int,
406 ) -> c_int;
407
408 pub fn baseRT_generate(
411 model: baseRT_model_t,
412 prompt_tokens: *const u32,
413 n_prompt: c_int,
414 max_tokens: c_int,
415 sampling: BaseRTSamplingConfig,
416 callback: baseRT_token_callback,
417 user_data: *mut c_void,
418 ) -> BaseRTGenerationStats;
419
420 pub fn baseRT_generate_continue(
421 model: baseRT_model_t,
422 new_tokens: *const u32,
423 n_new: c_int,
424 max_tokens: c_int,
425 sampling: BaseRTSamplingConfig,
426 callback: baseRT_token_callback,
427 user_data: *mut c_void,
428 ) -> BaseRTGenerationStats;
429
430 pub fn baseRT_prefill(model: baseRT_model_t, tokens: *const u32, n_tokens: c_int) -> u32;
433
434 pub fn baseRT_decode_step(model: baseRT_model_t, token_id: u32, position: c_int) -> u32;
435
436 pub fn baseRT_chain_decode(
437 model: baseRT_model_t,
438 first_token: u32,
439 start_position: c_int,
440 count: c_int,
441 out_tokens: *mut u32,
442 ) -> c_int;
443
444 pub fn baseRT_get_position(model: baseRT_model_t) -> c_int;
445
446 pub fn baseRT_set_speculation(model: baseRT_model_t, enabled: bool);
447
448 pub fn baseRT_reset(model: baseRT_model_t);
449
450 pub fn baseRT_transcribe(
453 model: baseRT_model_t,
454 wav_path: *const c_char,
455 language: *const c_char,
456 stats_out: *mut BaseRTTranscribeStats,
457 ) -> *const c_char;
458
459 pub fn baseRT_transcribe_pcm(
460 model: baseRT_model_t,
461 samples: *const c_float,
462 n_samples: c_int,
463 language: *const c_char,
464 stats_out: *mut BaseRTTranscribeStats,
465 ) -> *const c_char;
466
467 pub fn baseRT_set_timestamps(model: baseRT_model_t, enabled: bool);
468
469 pub fn baseRT_set_task(model: baseRT_model_t, task: *const c_char) -> bool;
470
471 pub fn baseRT_set_initial_prompt(model: baseRT_model_t, text: *const c_char);
472
473 pub fn baseRT_set_condition_on_previous_text(model: baseRT_model_t, enabled: bool);
474
475 pub fn baseRT_transcribe_language(model: baseRT_model_t) -> *const c_char;
476
477 pub fn baseRT_transcribe_audio_duration_ms(model: baseRT_model_t) -> c_int;
478
479 pub fn baseRT_transcribe_segment_count(model: baseRT_model_t) -> c_int;
480
481 pub fn baseRT_transcribe_segment(
482 model: baseRT_model_t,
483 index: c_int,
484 out: *mut BaseRTTranscribeSegment,
485 ) -> bool;
486
487 pub fn baseRT_is_whisper(model: baseRT_model_t) -> bool;
488
489 pub fn baseRT_transcribe_pcm_stream(
492 model: baseRT_model_t,
493 samples: *const c_float,
494 n_samples: c_int,
495 language: *const c_char,
496 stats_out: *mut BaseRTTranscribeStats,
497 callback: baseRT_segment_callback,
498 user_data: *mut c_void,
499 ) -> *const c_char;
500
501 pub fn baseRT_transcribe_stream(
502 model: baseRT_model_t,
503 wav_path: *const c_char,
504 language: *const c_char,
505 stats_out: *mut BaseRTTranscribeStats,
506 callback: baseRT_segment_callback,
507 user_data: *mut c_void,
508 ) -> *const c_char;
509
510 pub fn baseRT_embed(
513 model: baseRT_model_t,
514 tokens: *const u32,
515 n_tokens: c_int,
516 out_embedding: *mut c_float,
517 max_dims: c_int,
518 ) -> c_int;
519
520 pub fn baseRT_embed_text(
521 model: baseRT_model_t,
522 text: *const c_char,
523 out_embedding: *mut c_float,
524 max_dims: c_int,
525 ) -> c_int;
526
527 pub fn baseRT_embedding_dim(model: baseRT_model_t) -> c_int;
528 pub fn baseRT_is_embedding_model(model: baseRT_model_t) -> bool;
529
530 pub fn baseRT_format_chat(
533 model: baseRT_model_t,
534 system_prompt: *const c_char,
535 user_message: *const c_char,
536 ) -> *const c_char;
537
538 pub fn baseRT_chat_template(model: baseRT_model_t) -> *const c_char;
539
540 pub fn baseRT_chat_template_jinja(model: baseRT_model_t) -> *const c_char;
543
544 pub fn baseRT_grammar_create_from_schema(
548 model: baseRT_model_t,
549 json_schema: *const c_char,
550 ) -> *mut std::os::raw::c_void;
551
552 pub fn baseRT_grammar_create_from_structural_tag(
558 model: baseRT_model_t,
559 tag_json: *const c_char,
560 ) -> *mut std::os::raw::c_void;
561
562 pub fn baseRT_grammar_create(
564 model: baseRT_model_t,
565 gbnf: *const c_char,
566 ) -> *mut std::os::raw::c_void;
567
568 pub fn baseRT_grammar_accept_token(
573 grammar: *mut std::os::raw::c_void,
574 token_id: u32,
575 ) -> std::os::raw::c_int;
576
577 pub fn baseRT_grammar_reset(grammar: *mut std::os::raw::c_void);
580
581 pub fn baseRT_grammar_free(grammar: *mut std::os::raw::c_void);
583
584 pub fn baseRT_special_token_count(model: baseRT_model_t) -> c_int;
586
587 pub fn baseRT_special_token(
589 model: baseRT_model_t,
590 index: c_int,
591 id_out: *mut u32,
592 ) -> *const c_char;
593
594 pub fn baseRT_token_count(model: baseRT_model_t, text: *const c_char) -> c_int;
597
598 pub fn baseRT_tensor_count(model: baseRT_model_t) -> c_int;
601 pub fn baseRT_tensor_name(model: baseRT_model_t, index: c_int) -> *const c_char;
602 pub fn baseRT_tensor_dtype(model: baseRT_model_t, index: c_int) -> u32;
603 pub fn baseRT_tensor_raw_dtype(model: baseRT_model_t, index: c_int) -> *const c_char;
604
605 pub fn baseRT_profile_decode_step(
608 model: baseRT_model_t,
609 token_id: u32,
610 position: c_int,
611 timing_out: *mut c_float,
612 max_entries: c_int,
613 ) -> c_int;
614
615 pub fn baseRT_profile_label(model: baseRT_model_t, index: c_int) -> *const c_char;
616
617 pub fn baseRT_gpu_temperature_scale(model: baseRT_model_t, temperature: c_float);
620
621 pub fn baseRT_gpu_repetition_penalty(
622 model: baseRT_model_t,
623 token_ids: *const u32,
624 n_tokens: c_int,
625 penalty: c_float,
626 );
627
628 pub fn baseRT_set_paged_kv(enable: c_int);
631 pub fn baseRT_set_baked_decode(enable: c_int);
632 pub fn baseRT_set_max_batch_size(n: c_int);
633 pub fn baseRT_set_prefix_cache(enable: c_int);
634 pub fn baseRT_set_prefill_chunk(n: c_int);
635 pub fn baseRT_set_kv_bits(bits: c_int);
636 pub fn baseRT_set_verbose(on: c_int);
637
638 pub fn baseRT_get_error_code() -> c_int;
641 pub fn baseRT_strerror(code: c_int) -> *const c_char;
642 pub fn baseRT_capabilities(model: baseRT_model_t) -> u32;
643 pub fn baseRT_eos_token_id(model: baseRT_model_t) -> u32;
644 pub fn baseRT_is_eos_token(model: baseRT_model_t, token: u32) -> i32;
645 pub fn baseRT_weights_identity(model: baseRT_model_t) -> u64;
646 pub fn baseRT_kv_bits_effective(model: baseRT_model_t) -> c_int;
647 pub fn baseRT_bos_id(model: baseRT_model_t) -> u32;
648
649 pub fn baseRT_sequence_create(model: baseRT_model_t) -> baseRT_sequence_t;
652 pub fn baseRT_sequence_free(seq: baseRT_sequence_t);
653 pub fn baseRT_sequence_rollback(seq: baseRT_sequence_t, length: c_int) -> c_int;
654
655 pub fn baseRT_batch_step(
658 model: baseRT_model_t,
659 seqs: *mut baseRT_sequence_t,
660 n_seqs: c_int,
661 in_tokens: *const u32,
662 in_token_counts: *const c_int,
663 out_tokens: *mut u32,
664 ) -> c_int;
665 pub fn baseRT_batch_step_fused(
666 model: baseRT_model_t,
667 seqs: *mut baseRT_sequence_t,
668 n_seqs: c_int,
669 in_tokens: *const u32,
670 in_token_counts: *const c_int,
671 out_tokens: *mut u32,
672 ) -> c_int;
673 pub fn baseRT_batch_step_fused_logits(
674 model: baseRT_model_t,
675 seqs: *mut baseRT_sequence_t,
676 n_seqs: c_int,
677 in_tokens: *const u32,
678 in_token_counts: *const c_int,
679 ) -> c_int;
680 pub fn baseRT_batch_warmup(model: baseRT_model_t, max_batch: c_int) -> c_int;
681 pub fn baseRT_max_prefill_chunk(model: baseRT_model_t) -> c_int;
682
683 pub fn baseRT_read_batch_logits(
686 model: baseRT_model_t,
687 n_seqs: c_int,
688 out_logits_f16: *mut c_void,
689 ) -> c_int;
690 pub fn baseRT_batch_logits_stride(model: baseRT_model_t) -> usize;
691 pub fn baseRT_mask_logits_row(
692 model: baseRT_model_t,
693 row: *mut c_void,
694 bitmask: *const i32,
695 ) -> c_int;
696 pub fn baseRT_sample_logits_row(
697 model: baseRT_model_t,
698 row: *const c_void,
699 cfg: *const BaseRTSamplingConfig,
700 prev_tokens: *const u32,
701 n_prev: c_int,
702 repeat_window: c_int,
703 seed_offset: u32,
704 ) -> u32;
705 pub fn baseRT_argmax_logits_row(model: baseRT_model_t, row: *const c_void) -> u32;
706 pub fn baseRT_logits_row_logprobs(
707 model: baseRT_model_t,
708 row: *const c_void,
709 token: u32,
710 top_k: c_int,
711 out_token_logprob: *mut c_float,
712 out_ids: *mut u32,
713 out_logprobs: *mut c_float,
714 ) -> c_int;
715
716 pub fn baseRT_prefix_match(
719 model: baseRT_model_t,
720 tokens: *const u32,
721 n_tokens: c_int,
722 ) -> BaseRTPrefixMatch;
723 pub fn baseRT_sequence_seed_prefix(
724 seq: baseRT_sequence_t,
725 blocks: *const c_int,
726 n_blocks: c_int,
727 n_tokens: c_int,
728 ) -> c_int;
729 pub fn baseRT_page_size(model: baseRT_model_t) -> c_int;
730 pub fn baseRT_prefix_insert(
731 model: baseRT_model_t,
732 tokens: *const u32,
733 n_tokens: c_int,
734 seq: baseRT_sequence_t,
735 ) -> c_int;
736 pub fn baseRT_prefix_unlock(model: baseRT_model_t, handle: u64);
737 pub fn baseRT_prefix_release(model: baseRT_model_t, handle: u64);
738 pub fn baseRT_prefix_discard(model: baseRT_model_t, handle: u64);
739 pub fn baseRT_prefix_evict(model: baseRT_model_t, n_blocks: c_int) -> c_int;
740 pub fn baseRT_prefix_cache_stats(
741 model: baseRT_model_t,
742 out_hits: *mut u64,
743 out_misses: *mut u64,
744 out_reused_tokens: *mut u64,
745 out_blocks_cached: *mut c_int,
746 );
747
748 pub fn baseRT_gdn_snapshot_size(model: baseRT_model_t) -> c_int;
751 pub fn baseRT_sequence_gdn_capture(seq: baseRT_sequence_t, out: *mut u8, cap: c_int) -> c_int;
752 pub fn baseRT_sequence_gdn_restore(
753 seq: baseRT_sequence_t,
754 blob: *const u8,
755 len: c_int,
756 ) -> c_int;
757}
758
759#[cfg(test)]
760mod tests {
761 use super::*;
762 use std::mem;
763
764 #[test]
769 fn model_config_size() {
770 assert!(
775 mem::size_of::<BaseRTModelConfig>() > 1000,
776 "config struct unexpectedly small ({})",
777 mem::size_of::<BaseRTModelConfig>()
778 );
779 assert_eq!(mem::size_of::<BaseRTModelConfig>(), 1792);
780 }
781
782 #[test]
783 fn model_config_size_matches_library() {
784 assert_eq!(
789 unsafe { baseRT_model_config_sizeof() },
790 mem::size_of::<BaseRTModelConfig>(),
791 "BaseRTModelConfig mirror drifted from include/baseRT/types.h"
792 );
793 }
794
795 #[test]
796 fn model_config_alignment() {
797 assert_eq!(mem::align_of::<BaseRTModelConfig>(), 4);
798 }
799
800 #[test]
801 fn sampling_config_size() {
802 assert_eq!(mem::size_of::<BaseRTSamplingConfig>(), 56);
806 }
807
808 #[test]
809 fn sampling_config_alignment() {
810 assert_eq!(mem::align_of::<BaseRTSamplingConfig>(), 8);
812 }
813
814 #[test]
815 fn generation_stats_size() {
816 assert_eq!(mem::size_of::<BaseRTGenerationStats>(), 24);
818 }
819
820 #[test]
821 fn generation_stats_alignment() {
822 assert_eq!(mem::align_of::<BaseRTGenerationStats>(), 4);
823 }
824
825 #[test]
826 fn transcribe_stats_size() {
827 assert_eq!(mem::size_of::<BaseRTTranscribeStats>(), 20);
829 }
830
831 #[test]
832 fn transcribe_stats_alignment() {
833 assert_eq!(mem::align_of::<BaseRTTranscribeStats>(), 4);
834 }
835
836 #[test]
841 fn model_config_field_offsets() {
842 let base: BaseRTModelConfig = unsafe { mem::zeroed() };
844 let base_ptr = &base as *const _ as usize;
845
846 assert_eq!(&base.dim as *const _ as usize - base_ptr, 0);
847 assert_eq!(&base.n_layers as *const _ as usize - base_ptr, 4);
848 assert_eq!(&base.norm_eps as *const _ as usize - base_ptr, 40);
849 assert_eq!(&base.rope_theta as *const _ as usize - base_ptr, 44);
850 assert_eq!(
851 &base.sliding_window_pattern as *const _ as usize - base_ptr,
852 48
853 );
854 assert_eq!(&base.sliding_window as *const _ as usize - base_ptr, 52);
856 assert_eq!(&base.rope_local_theta as *const _ as usize - base_ptr, 56);
857 assert_eq!(&base.architecture as *const _ as usize - base_ptr, 60);
858 assert_eq!(&base.enc_n_layers as *const _ as usize - base_ptr, 92);
859 assert_eq!(&base.enc_max_seq_len as *const _ as usize - base_ptr, 112);
860 assert_eq!(&base.swa_layers as *const _ as usize - base_ptr, 144);
862 assert_eq!(&base.ffn_dims as *const _ as usize - base_ptr, 208);
863 assert_eq!(&base.attn_output_gate as *const _ as usize - base_ptr, 1232);
864 assert_eq!(
865 &base.linear_attn_layers as *const _ as usize - base_ptr,
866 1244
867 );
868 assert_eq!(&base.gdn_num_k_heads as *const _ as usize - base_ptr, 1308);
869 assert_eq!(&base.ssm_state_size as *const _ as usize - base_ptr, 1328);
872 assert_eq!(&base.ssm_num_heads as *const _ as usize - base_ptr, 1344);
873 assert_eq!(&base.n_experts as *const _ as usize - base_ptr, 1348);
874 assert_eq!(
875 &base.expert_weights_scale as *const _ as usize - base_ptr,
876 1368
877 );
878 assert_eq!(&base.vision_n_layers as *const _ as usize - base_ptr, 1372);
879 assert_eq!(&base.vision_arch as *const _ as usize - base_ptr, 1432);
880 assert_eq!(&base.audio_n_layers as *const _ as usize - base_ptr, 1448);
881 assert_eq!(&base.eoa_token_id as *const _ as usize - base_ptr, 1524);
882 assert_eq!(&base.mrope_section as *const _ as usize - base_ptr, 1528);
883 assert_eq!(
884 &base.mrope_interleaved as *const _ as usize - base_ptr,
885 1540
886 );
887 assert_eq!(
888 &base.rope_scaling_factor as *const _ as usize - base_ptr,
889 1544
890 );
891 assert_eq!(
892 &base.rope_orig_max_pos as *const _ as usize - base_ptr,
893 1556
894 );
895 assert_eq!(
896 &base.rope_scaling_type as *const _ as usize - base_ptr,
897 1560
898 );
899 assert_eq!(&base.qk_scale_factor as *const _ as usize - base_ptr, 1564);
900 assert_eq!(&base.nope_layers as *const _ as usize - base_ptr, 1576);
901 assert_eq!(&base.embed_norm_eps as *const _ as usize - base_ptr, 1640);
902 assert_eq!(
903 &base.vision_window_layers as *const _ as usize - base_ptr,
904 1644
905 );
906 assert_eq!(&base.video_token_id as *const _ as usize - base_ptr, 1724);
907 assert_eq!(&base.q_lora_rank as *const _ as usize - base_ptr, 1728);
908 assert_eq!(&base.indexer_top_k as *const _ as usize - base_ptr, 1768);
909 assert_eq!(
910 &base.rope_yarn_beta_fast as *const _ as usize - base_ptr,
911 1772
912 );
913 }
914
915 #[test]
916 fn sampling_config_field_offsets() {
917 let base = BaseRTSamplingConfig::default();
918 let base_ptr = &base as *const _ as usize;
919
920 assert_eq!(&base.temperature as *const _ as usize - base_ptr, 0);
921 assert_eq!(&base.top_k as *const _ as usize - base_ptr, 4);
922 assert_eq!(&base.top_p as *const _ as usize - base_ptr, 8);
923 assert_eq!(&base.min_p as *const _ as usize - base_ptr, 12);
924 assert_eq!(&base.repeat_penalty as *const _ as usize - base_ptr, 16);
925 assert_eq!(&base.presence_penalty as *const _ as usize - base_ptr, 20);
926 assert_eq!(&base.frequency_penalty as *const _ as usize - base_ptr, 24);
927 assert_eq!(&base.seed as *const _ as usize - base_ptr, 28);
928 assert_eq!(&base.n_logit_bias as *const _ as usize - base_ptr, 32);
929 assert_eq!(&base.logit_bias_tokens as *const _ as usize - base_ptr, 40);
931 assert_eq!(&base.logit_bias_values as *const _ as usize - base_ptr, 48);
932 }
933
934 #[test]
935 fn generation_stats_field_offsets() {
936 let base = BaseRTGenerationStats::default();
937 let base_ptr = &base as *const _ as usize;
938
939 assert_eq!(&base.prompt_tokens as *const _ as usize - base_ptr, 0);
940 assert_eq!(&base.generated_tokens as *const _ as usize - base_ptr, 4);
941 assert_eq!(&base.prefill_time_ms as *const _ as usize - base_ptr, 8);
942 assert_eq!(&base.decode_time_ms as *const _ as usize - base_ptr, 12);
943 assert_eq!(
944 &base.prefill_tokens_per_sec as *const _ as usize - base_ptr,
945 16
946 );
947 assert_eq!(
948 &base.decode_tokens_per_sec as *const _ as usize - base_ptr,
949 20
950 );
951 }
952
953 #[test]
958 fn sampling_config_default_values() {
959 let cfg = BaseRTSamplingConfig::default();
960 assert_eq!(cfg.temperature, 0.0);
961 assert_eq!(cfg.top_k, 40);
962 assert!((cfg.top_p - 0.9).abs() < f32::EPSILON);
963 assert_eq!(cfg.min_p, 0.0);
964 assert_eq!(cfg.repeat_penalty, 1.0);
965 assert_eq!(cfg.presence_penalty, 0.0);
966 assert_eq!(cfg.frequency_penalty, 0.0);
967 assert_eq!(cfg.seed, 0);
968 assert_eq!(cfg.n_logit_bias, 0);
969 assert!(cfg.logit_bias_tokens.is_null());
970 assert!(cfg.logit_bias_values.is_null());
971 }
972
973 #[test]
974 fn prefix_match_layout() {
975 assert_eq!(mem::size_of::<BaseRTPrefixMatch>(), 24);
980 assert_eq!(mem::offset_of!(BaseRTPrefixMatch, matched_tokens), 0);
981 assert_eq!(mem::offset_of!(BaseRTPrefixMatch, n_blocks), 4);
982 assert_eq!(mem::offset_of!(BaseRTPrefixMatch, blocks), 8);
983 assert_eq!(mem::offset_of!(BaseRTPrefixMatch, handle), 16);
984 }
985
986 #[test]
987 fn transcribe_stats_default_values() {
988 let stats = BaseRTTranscribeStats::default();
989 assert_eq!(stats.n_tokens, 0);
990 assert_eq!(stats.audio_ms, 0.0);
991 assert_eq!(stats.encode_ms, 0.0);
992 assert_eq!(stats.decode_ms, 0.0);
993 assert_eq!(stats.total_ms, 0.0);
994 }
995
996 #[test]
997 fn generation_stats_default_values() {
998 let stats = BaseRTGenerationStats::default();
999 assert_eq!(stats.prompt_tokens, 0);
1000 assert_eq!(stats.generated_tokens, 0);
1001 assert_eq!(stats.prefill_time_ms, 0.0);
1002 assert_eq!(stats.decode_time_ms, 0.0);
1003 assert_eq!(stats.prefill_tokens_per_sec, 0.0);
1004 assert_eq!(stats.decode_tokens_per_sec, 0.0);
1005 }
1006}