model.py Source File

model.py Source File#

SDK qb Runtime Library: model.py Source File
SDK qb Runtime Library v1.3
MCS001-EN
model.py
Go to the documentation of this file.
1
4
5from typing import List, Optional, Tuple, Union
6
7import numpy as np
8
9import qbruntime.qbruntime as _cQbRuntime
10from .accelerator import Accelerator
11from .future import *
12from .model_variant_handle import *
13from .pinned_memory import PinnedMemory
14from .type import *
15
16_Shape = Tuple[int, ...]
17
18__all__ = ["Model", "load"]
19
20
23
24
25# input ndarray의 shape이 유효한 shape인지 판별한다.
26def _is_valid_shape(input_shape: _Shape, shape: _Shape) -> bool:
27 if (len(input_shape) < len(shape)) or (len(input_shape) > len(shape) + 1):
28 return False
29 # input을 batch일 경우도 고려하여 [h, w, c] 및 [batch, h, w, c] 모두 고려한다
30 offset = 1 if len(input_shape) > len(shape) else 0
31 for s1, s2 in zip(input_shape[offset:], shape):
32 # Dimensions that allow variable lengths are represented by negative values.
33 # A variable-length dimension only permits multiples of the original value.
34 if s1 % s2 != 0 or (s2 > 0 and s1 != s2):
35 return False
36 return True
37
38
39# input ndarray의 shape를 검사하여 HWC인지 CHW인지 판별한다. HWC/CHW의
40# shape이 동일한 경우, `is_hwc`와 `is_chw`를 모두 true로 반환한다.
41def _find_memory_format(
42 inputs: List[np.ndarray], shapes: List[_Shape]
43) -> Optional[Tuple[bool, bool]]:
44 if len(inputs) != len(shapes):
45 return None
46
47 is_hwc = True
48 is_chw = True
49 for arr, shape in zip(inputs, shapes):
50 shape_hwc = (shape[0], shape[1], shape[2])
51 shape_chw = (shape[2], shape[0], shape[1])
52 is_hwc = is_hwc and _is_valid_shape(arr.shape, shape_hwc)
53 is_chw = is_chw and _is_valid_shape(arr.shape, shape_chw)
54
55 if not is_hwc and not is_chw:
56 return None
57 return is_hwc, is_chw
58
59
60# input ndarray에 맞는 model variant index와 shape를 판별한다.
61def _find_matching_variant_idx_and_memory_format(
62 model, inputs: List[np.ndarray]
63) -> Tuple[int, Tuple[bool, bool]]:
64 variant_idx = None
65 is_hwc = None
66 is_chw = None
67 for i in range(model.get_num_model_variants()):
68 res = _find_memory_format(
69 inputs, model.get_model_variant_handle(i).get_model_input_shape()
70 )
71 if res is not None:
72 variant_idx = i
73 is_hwc, is_chw = res
74 break
75
76 if variant_idx is None:
77 raise ValueError("Input shape is invalid.")
78 return variant_idx, (is_hwc, is_chw)
79
80
81# shape에 맞게 numpy ndarray를 생성한다.
82def _build_outputs(
83 shapes: List[_Shape], is_hwc: bool, dtype: np.dtype
84) -> List[np.ndarray]:
85 outputs = []
86 for shape in shapes:
87 if is_hwc:
88 shape = (shape[0], shape[1], shape[2])
89 else:
90 shape = (shape[2], shape[0], shape[1])
91 outputs.append(np.empty(shape, dtype=dtype))
92 return outputs
93
94
95# output에 들어있는 numpy ndarray의 shape가 올바른지 검사한다.
96def _check_output_shapes(
97 outputs: List[np.ndarray], shapes: List[_Shape], is_hwc: bool, dtype: np.dtype
98) -> None:
99 if len(outputs) != len(shapes):
100 raise ValueError("The number of outputs is different.")
101
102 for output, shape in zip(outputs, shapes):
103 if output.dtype != dtype:
104 raise ValueError("Output dtype mismatch.")
105
106 if is_hwc:
107 shape = (shape[0], shape[1], shape[2])
108 else:
109 shape = (shape[2], shape[0], shape[1])
110 if output.shape != shape:
111 raise ValueError("Output shape mismatch.")
112
113
114class Model:
115 """
116 @brief Represents an AI model loaded from an MXQ file.
117
118 This class loads an AI model from an MXQ file and provides functions to launch it
119 on the NPU and perform inference.
120 """
121
122 def __init__(self, path: str, model_config: Optional[ModelConfig] = None):
123 """
124 @brief Creates a Model object from the specified MXQ model file and configuration.
125
126 Parses the MXQ file and constructs a Model object using the provided configuration,
127 initializing the model with the given settings.
128
129 @note The created Model object must be launched before performing inference.
130 See Model.launch for more details.
131
132 @param[in] path The path to the MXQ model file.
133 @param[in] model_config The configuration settings to initialize the Model.
134 """
135 if model_config is None:
136 self._model = _cQbRuntime.Model(path)
137 else:
138 self._model = _cQbRuntime.Model(path, model_config._model_config)
139
140 # 기존 BufferInfo 대신에 ModelShape를 사용한다.
141 # Model {input,output} shape는 batch를 포함한 4D이다.
144
145 def launch(self, acc: Accelerator) -> None:
146 """
147 @brief Launches the model on the specified Accelerator, which represents
148 the actual NPU.
149
150 @param[in] acc The accelerator on which to launch the model.
151 """
152 self._model.launch(acc._accelerator)
153 self._acc = acc
154
155 def dispose(self) -> None:
156 """
157 @brief Disposes of the model loaded onto the NPU.
158
159 Releases any resources associated with the model on the NPU.
160 """
161 self._model.dispose()
162 self._acc = None
163
164 def is_target(self, core_id: CoreId) -> bool:
165 """
166 @brief Checks if the NPU core specified by CoreId is the target of the model.
167 In other words, whether the model is configured to use the given NPU core.
168
169 @param[in] core_id The CoreId to check.
170 @return True if the model is configured to use the specified CoreId, false
171 otherwise.
172 """
173 return self._model.is_target(core_id._core_id)
174
175 def get_core_mode(self) -> CoreMode:
176 """
177 @brief Retrieves the core mode of the model.
178
179 @return The CoreMode of the model.
180 """
181 return CoreMode(self._model.get_core_mode())
182
183 def get_target_cores(self) -> List[CoreId]:
184 """
185 @brief Returns the NPU cores the model is configured to use.
186
187 @return A list of CoreIds representing the target NPU cores.
188 """
189 return [CoreId.from_cpp(target) for target in self._model.target_cores]
190
191 @property
192 def target_cores(self) -> List[CoreId]:
193 """@deprecated"""
194 return [CoreId.from_cpp(target) for target in self._model.target_cores]
195
196 def infer(
197 self,
198 inputs: Union[np.ndarray, List[np.ndarray]],
199 outputs: Optional[List[np.ndarray]] = None,
200 cache_size: int = 0,
201 params: Optional[List[BatchParam]] = None,
202 ) -> Optional[List[np.ndarray]]:
203 """
204 @brief Performs inference.
205
206 Fowllowing types of inference supported.
207 1. infer(in:List[numpy]) -> List[numpy] (float / int)
208 2. infer(in:numpy) -> List[numpy] (float / int)
209 3. infer(in:List[numpy], out:List[numpy]) (float / int)
210 4. infer(in:List[numpy], out:List[]) (float / int)
211 5. infer(in:numpy, out:List[numpy]) (float / int)
212 6. infer(in:numpy, out:List[]) (float / int)
213
214 @param[in] inputs Input data as a single numpy.ndarray or a list
215 of numpy.ndarray's.
216 @param[out] outputs Optional pre-allocated list of numpy.ndarray's
217 to store inference results.
218 @param[in] cache_size The number of tokens accumulated in the KV cache so far.
219 @param[in] params A List of `BatchParam`, specifying each batch's information
220 for BatchLLM inference. If `params` is specified,
221 `cache_size` is ignored.
222 @return Inference results as a list of numpy.ndarray.
223 """
224 return self._infer(inputs, outputs, cache_size, params=params)
225
226 def infer_hwc(
227 self,
228 inputs: Union[np.ndarray, List[np.ndarray]],
229 outputs: Optional[List[np.ndarray]] = None,
230 cache_size: int = 0,
231 params: Optional[List[BatchParam]] = None,
232 ) -> Optional[List[np.ndarray]]:
233 return self._infer(inputs, outputs, cache_size, True, params)
234
235 def infer_chw(
236 self,
237 inputs: Union[np.ndarray, List[np.ndarray]],
238 outputs: Optional[List[np.ndarray]] = None,
239 cache_size: int = 0,
240 params: Optional[List[BatchParam]] = None,
241 ) -> Optional[List[np.ndarray]]:
242 return self._infer(inputs, outputs, cache_size, False, params)
243
244 def _infer(
245 self,
246 inputs: Union[np.ndarray, List[np.ndarray]],
247 outputs: Optional[List[np.ndarray]],
248 cache_size: int,
249 is_target_hwc: Optional[bool] = None,
250 params: Optional[List[BatchParam]] = None,
251 ) -> Optional[List[np.ndarray]]:
252 if not isinstance(inputs, list):
253 inputs = [inputs]
254
255 variant_idx, (is_hwc, is_chw) = _find_matching_variant_idx_and_memory_format(
256 self, inputs
257 )
258 if (is_target_hwc is not None) and (
259 (is_target_hwc != is_hwc) and (is_target_hwc == is_chw)
260 ):
261 raise ValueError("Input shape is invalid.")
262 elif is_target_hwc is None:
263 is_target_hwc = is_hwc
264 inputs = [np.ascontiguousarray(i) for i in inputs]
265
266 infer_func = self._model.infer if is_target_hwc else self._model.infer_chw
267 if outputs is None:
268 # No Output Parameter
269 if params == None:
270 return [np.asarray(o) for o in infer_func(inputs, cache_size)]
271 else:
272 return [
273 np.asarray(o)
274 for o in infer_func(
275 inputs, [param._batch_param for param in params]
276 )
277 ]
278 else:
279 if outputs:
280 _check_output_shapes(
281 outputs,
283 is_target_hwc,
284 inputs[0].dtype,
285 )
286 for oi in range(len(outputs)):
287 outputs[oi] = np.ascontiguousarray(outputs[oi])
288 else:
289 outputs[:] = _build_outputs(
291 is_target_hwc,
292 inputs[0].dtype,
293 )
294
295 if params == None:
296 infer_func(inputs, outputs, cache_size)
297 else:
298 infer_func(inputs, outputs, [param._batch_param for param in params])
299
301 self,
302 inputs: Union[
303 np.ndarray,
304 List[np.ndarray],
305 ],
306 cache_size: int = 0,
307 ) -> List[np.ndarray]:
308 """
309 @brief int8_t-to-float inference
310 Performs inference with input and output elements of type `int8_t`
311
312 Using these inference APIs requires manual scaling (quantization)
313 of float values to `int8_t` for input.
314
315 @note These APIs are intended for advanced use rather than typical usage.
316 """
317 return self._infer_to_float(inputs, cache_size)
318
319 def infer_hwc_to_float(
320 self,
321 inputs: Union[
322 np.ndarray,
323 List[np.ndarray],
324 ],
325 cache_size: int = 0,
326 ) -> List[np.ndarray]:
327 return self._infer_to_float(inputs, cache_size, True)
328
329 def infer_chw_to_float(
330 self,
331 inputs: Union[
332 np.ndarray,
333 List[np.ndarray],
334 ],
335 cache_size: int = 0,
336 ) -> List[np.ndarray]:
337 return self._infer_to_float(inputs, cache_size, False)
338
340 self,
341 inputs: Union[
342 np.ndarray,
343 List[np.ndarray],
344 ],
345 cache_size: int,
346 is_target_hwc: Optional[bool] = None,
347 ) -> List[np.ndarray]:
348 """
349 @brief int8_t-to-float inference
350 Performs inference with input and output elements of type `int8_t`
351
352 Using these inference APIs requires manual scaling (quantization)
353 of float values to `int8_t` for input.
354
355 @note These APIs are intended for advanced use rather than typical usage.
356 """
357 if not isinstance(inputs, list):
358 inputs = [inputs]
359
360 _, (is_hwc, is_chw) = _find_matching_variant_idx_and_memory_format(self, inputs)
361 if (is_target_hwc is not None) and (
362 (is_target_hwc != is_hwc) and (is_target_hwc == is_chw)
363 ):
364 raise ValueError("Input shape is invalid.")
365 elif is_target_hwc is None:
366 is_target_hwc = is_hwc
367 inputs = [np.ascontiguousarray(i) for i in inputs]
368
369 if is_target_hwc:
370 outputs = self._model.infer_to_float(inputs, cache_size)
371 else:
372 outputs = self._model.infer_chw_to_float(inputs, cache_size)
373
374 return [np.asarray(o) for o in outputs]
375
377 self,
378 inputs: List[Buffer],
379 outputs: List[Buffer],
380 shape: List[List[int]] = [],
381 cache_size: int = 0,
382 ) -> None:
383 """
384 @brief Buffer-to-Buffer inference
385
386 Performs inference using input and output elements in the NPU’s internal data type.
387 The inference operates on buffers allocated via the following APIs:
388
389 - `Model.acquire_input_buffer()`
390 - `Model.acquire_output_buffer()`
391 - `ModelVariantHandle.acquire_input_buffer()`
392 - `ModelVariantHandle.acquire_output_buffer()`
393
394 Additionally, `Model.reposition_inputs()`, `Model.reposition_outputs()`,
395 `ModelVariantHandle.reposition_inputs()`, `ModelVariantHandle.reposition_outputs()`
396 must be used properly.
397
398 @note These APIs are intended for advanced use rather than typical usage.
399 """
400 self._model.infer_buffer(
401 [i._buffer for i in inputs], [o._buffer for o in outputs], shape, cache_size
402 )
403
404 def infer_speedrun(self) -> None:
405 """
406 @brief Development-only API for measuring pure NPU inference speed.
407
408 Runs NPU inference without uploading inputs and without retrieving outputs.
409 """
411
413 self,
414 inputs: List[PinnedMemory],
415 outputs: Optional[List[PinnedMemory]] = None,
416 cache_size: int = 0,
417 ) -> Optional[List[PinnedMemory]]:
418 """
419 @brief Performs inference directly on pinned memory buffers (zero-copy).
420
421 The NPU reads the inputs from and writes the outputs into the pinned
422 buffers in place, avoiding host-to-device copies of the I/O tensors. Write
423 the input data into each input buffer via indexing (e.g. `pm[...] = data`)
424 before calling, and read the results from the output buffers afterwards.
425
426 @note This is an experimental API and is only supported on Regulus hardware.
427 It is not supported for models that use CPU offload.
428
429 @param inputs A list of PinnedMemory buffers holding the input data. All
430 inputs must share the same dtype (`numpy.float32` or
431 `numpy.uint8`).
432 @param outputs A list of pre-allocated PinnedMemory buffers (dtype
433 `numpy.float32`) that will receive the output data. If `None`
434 (the default), the output buffers are allocated internally and
435 returned by this method.
436 @param cache_size The size of the cache to use for inference.
437 @return If `outputs` is `None`, a list of newly allocated PinnedMemory
438 buffers (dtype `numpy.float32`) holding the output data; otherwise
439 `None` (the given `outputs` are filled in place).
440 """
441 if outputs is None:
442 _pms = self._model.infer_pinned_memory(
443 [pm._pinned_memory for pm in inputs],
444 [],
445 cache_size,
446 )
447 return [PinnedMemory(_pm) for _pm in _pms]
448
450 [pm._pinned_memory for pm in inputs],
451 [pm._pinned_memory for pm in outputs],
452 cache_size,
453 )
454 return None
455
457 self,
458 inputs: Union[np.ndarray, List[np.ndarray]],
459 ) -> Future:
460 """
461 @brief Asynchronous Inference
462
463 Performs inference asynchronously.
464
465 To use asynchronous inference, the model must be created using a `ModelConfig`
466 object with the async pipeline configured to be enabled. This is done by calling
467 @ref ModelConfig.set_async_pipeline_enabled
468 "ModelConfig.set_async_pipeline_enabled(True)" before passing the configuration to
469 `Model()`.
470
471 Example:
472 @code
473 import qbruntime
474
475 mc = qbruntime.ModelConfig()
476 mc.set_async_pipeline_enabled(True)
477
478 model = qbruntime.Model(MXQ_PATH, mc)
479 acc = qbruntime.Accelerator()
480
481 model.launch(acc)
482
483 future = model.infer_async(inputs)
484
485 ret = future.get()
486 @endcode
487
488 @note Currently, only CNN-based models are supported, as asynchronous execution is
489 particularly effective for this type of workload.
490
491 @note Limitations:
492 - RNN/LSTM and LLM models are not supported yet.
493 - Models requiring CPU offloading are not supported yet.
494 - Currently, only single-batch inference is supported (i.e., N = 1).
495 - Currently, Buffer inference is not supported. The following types
496 are supported in the synchronous API for advanced use cases, but are not
497 yet available for asynchronous inference:
498 - Buffer to Buffer
499 - Buffer to float
500 """
501 if not isinstance(inputs, list):
502 inputs = [inputs]
503 _, (is_hwc, _) = _find_matching_variant_idx_and_memory_format(self, inputs)
504 inputs = [np.ascontiguousarray(i) for i in inputs]
505 infer_async_func = (
506 self._model.infer_async if is_hwc else self._model.infer_async_chw
507 )
508 return Future.from_cpp(infer_async_func(inputs), inputs)
509
511 self,
512 inputs: Union[np.ndarray, List[np.ndarray]],
513 ) -> Future:
514 """
515 @brief This method supports int8_t-to-float asynchronous inference.
516
517 @param[in] inputs Input data as a single numpy.ndarray or a list
518 of numpy.ndarray's.
519
520 @return A future that can be used to retrieve the inference result.
521 """
522 if not isinstance(inputs, list):
523 inputs = [inputs]
524 _, (is_hwc, _) = _find_matching_variant_idx_and_memory_format(self, inputs)
525 inputs = [np.ascontiguousarray(i) for i in inputs]
526 infer_async_func = (
527 self._model.infer_async_to_float
528 if is_hwc
529 else self._model.infer_async_chw_to_float
530 )
531 return Future.from_cpp(infer_async_func(inputs), inputs)
532
534 self,
535 inputs: List[np.ndarray],
536 input_bufs: List[Buffer],
537 seqlens: List[List[int]] = [],
538 ) -> None:
539 """Reposition input"""
540 inputs = [np.ascontiguousarray(i) for i in inputs]
542 inputs, [buf._buffer for buf in input_bufs], seqlens
543 )
544
546 self,
547 output_bufs: List[Buffer],
548 outputs: List[np.ndarray],
549 seqlens: List[List[int]] = [],
550 ) -> None:
551 """Reposition output"""
552 if len(outputs) != len(self._output_shape):
553 outputs.clear()
554 for shape in self._output_shape:
555 outputs.append(np.empty(shape=shape, dtype=np.float32))
556 else:
557 for oi in range(len(outputs)):
558 outputs[oi] = np.ascontiguousarray(outputs[oi])
560 [buf._buffer for buf in output_bufs], outputs, seqlens
561 )
562
563 def get_num_model_variants(self) -> int:
564 """
565 @brief Returns the total number of model variants available in this model.
566
567 The `variant_idx` parameter passed to `Model.get_model_variant_handle()` must be
568 in the range [0, return value of this function).
569
570 @return The total number of model variants.
571 """
572 return self._model.get_num_model_variants()
573
574 def get_model_variant_handle(self, variant_idx) -> ModelVariantHandle:
575 """
576 @brief Retrieves a handle to the specified model variant.
577
578 Use the returned `ModelVariantHandle` to query details such as input and output
579 shapes for the selected variant.
580
581 @param[in] variant_idx Index of the model variant to retrieve.
582 Must be in the range [0, getNumModelVariants()).
583
584 @return A `ModelVariantHandle` object if successful;
585 otherwise, raise qbruntime.QbRuntimeError "Model_InvalidVariantIdx".
586 """
587 return ModelVariantHandle.from_cpp(
588 self._model.get_model_variant_handle(variant_idx)
589 )
590
591 def get_model_input_shape(self) -> List[_Shape]:
592 """
593 @brief Returns the input shape of the model.
594
595 @return A list of input shape of the model.
596 """
597 return self._model.get_model_input_shape()
598
599 def get_model_output_shape(self) -> List[_Shape]:
600 """
601 @brief Returns the output shape of the model.
602
603 @return A list of output shape of the model.
604 """
605 return self._model.get_model_output_shape()
606
607 def get_input_scale(self) -> List[Scale]:
608 """
609 @brief Returns the input quantization scale(s) of the model.
610
611 @return A list of input scales.
612 """
613 return [Scale.from_cpp(s) for s in self._model.get_input_scale()]
614
615 def get_output_scale(self) -> List[Scale]:
616 """
617 @brief Returns the output quantization scale(s) of the model.
618
619 @return A list of output scales.
620 """
621 return [Scale.from_cpp(s) for s in self._model.get_output_scale()]
622
623 def get_input_buffer_info(self) -> List[BufferInfo]:
624 """
625 @brief Returns the input buffer information for the model.
626
627 @return A list of input buffer information.
628 """
629 return [BufferInfo.from_cpp(bi) for bi in self._model.get_input_buffer_info()]
630
631 def get_output_buffer_info(self) -> List[BufferInfo]:
632 """
633 @brief Returns the output buffer information of the model.
634
635 @return A list of output buffer information.
636 """
637 return [BufferInfo.from_cpp(bi) for bi in self._model.get_output_buffer_info()]
638
639 def get_model_input_data_type(self) -> DataType:
640 """
641 @brief Returns a data type for model inputs.
642
643 @return An input data type.
644 """
646
647 def get_model_output_data_type(self) -> DataType:
648 """
649 @brief Returns a data type for model outputs.
650
651 @return An output data type.
652 """
654
655 def acquire_input_buffer(self, seqlens: List[List[int]] = []) -> List[Buffer]:
656 """
657 @brief Buffer Management API
658
659 Acquires list of `Buffer` for input.
660 These API is required when calling `Model.infer_buffer()`.
661
662 @note These APIs are intended for advanced use rather than typical usage.
663 """
664 return [Buffer(b) for b in self._model.acquire_input_buffer(seqlens)]
665
666 def acquire_output_buffer(self, seqlens: List[List[int]] = []) -> List[Buffer]:
667 """
668 @brief Buffer Management API
669
670 Acquires list of `Buffer` for output.
671 These API is required when calling `Model.infer_buffer()`.
672
673 @note These APIs are intended for advanced use rather than typical usage.
674 """
675 return [Buffer(b) for b in self._model.acquire_output_buffer(seqlens)]
676
677 def release_buffer(self, buffer: List[Buffer]) -> None:
678 """
679 @brief Buffer Management API
680
681 Deallocate acquired Input/Output buffer
682
683 @note These APIs are intended for advanced use rather than typical usage.
684 """
685 self._model.release_buffer([b._buffer for b in buffer])
686
687 def get_identifier(self) -> int:
688 """
689 @brief Returns the model's unique identifier.
690
691 This identifier distinguishes multiple models within a single user program.
692 It is assigned incrementally, starting from 0 (e.g., 0, 1, 2, 3, ...).
693
694 @return The model identifier.
695 """
696 return self._model.get_identifier()
697
698 def get_model_path(self) -> str:
699 """
700 @brief Returns the path to the MXQ model file associated with the Model.
701
702 @return The MXQ file path.
703 """
704 return self._model.get_model_path()
705
706 def get_cache_infos(self) -> List[CacheInfo]:
707 """
708 @brief Returns informations of KV-cache of the model.
709
710 @return A list of CacheInfo objects.
711 """
712 return [CacheInfo.from_cpp(c) for c in self._model.get_cache_infos()]
713
714 def get_latency_consumed(self) -> int:
715 """@deprecated"""
716 return self._model.get_latency_consumed()
717
718 def get_latency_finished(self) -> int:
719 """@deprecated"""
720 return self._model.get_latency_finished()
721
722 def dump_cache_memory(self, cache_id: int = 0) -> List[bytes]:
723 """
724 @brief Dumps the KV cache memory into buffers.
725
726 Writes the current KV cache data into provided buffers.
727
728 @param[in] cache_id Index of target cache.
729
730 @return A list of bytes containing the KV cache data.
731 """
732 bufs = self._model.dump_cache_memory(cache_id)
733 return [np.asarray(buf, np.int8).tobytes() for buf in bufs]
734
735 def load_cache_memory(self, bufs: List[bytes], cache_id: int = 0) -> None:
736 """
737 @brief Loads the KV cache memory from buffers.
738
739 Restores the KV cache from the provided buffers.
740
741 @param[in] bufs A list of bytes containing the KV cache
742 """
744 [np.frombuffer(buf, dtype=np.int8) for buf in bufs], cache_id
745 )
746
747 def dump_cache_memory_to(self, cache_dir: str, cache_id: int = 0) -> None:
748 """
749 @brief Dumps KV cache memory to files in the specified directory.
750
751 Writes the KV cache data to binary files within the given directory.
752 Each file is named using the format: `cache_<layer_hash>.bin`.
753
754 @param[in] cache_dir Path to the directory where KV cache files will be saved.
755 @param[in] cache_id Index of target cache.
756 """
757 self._model.dump_cache_memory(cache_dir, cache_id)
758
759 def load_cache_memory_from(self, cache_dir: str, cache_id: int = 0) -> None:
760 """
761 @brief Loads the KV cache memory from files in the specified directory.
762
763 Reads KV cache data from files within the given directory and restores them.
764 Each file is named using the format: `cache_<layer_hash>.bin`.
765
766 @param[in] cache_dir Path to the directory where KV cache files are saved.
767 """
768 self._model.load_cache_memory(cache_dir, cache_id)
769
771 self, cache_size: int, tail_size: int, mask: List[bool]
772 ) -> int:
773 """
774 @brief Filter the tail of the KV cache memory
775
776 Retains the desired caches in the tail of the KV cache memory, excludes the others,
777 and shifts the remaining caches forward.
778
779 @param[in] cache_size The number of tokens accumulated in the KV cache so far.
780 @param[in] tail_size The tail size of the KV cache to filter (<=32).
781 @param[in] mask A mask indicating tokens to retain or exclude at the tail of the KV
782 cache.
783
784 @return New cache size after tail filtering.
785 """
786 return self._model.filter_cache_tail(cache_size, tail_size, mask)
787
788 def move_cache_tail(self, num_head: int, num_tail: int, cache_size: int) -> int:
789 """
790 @brief Moves the tail of the KV cache memory to the end of the head.
791
792 Slice the tail of the KV cache memory up to the specified size
793 and moves it to the designated cache position.
794
795 @param[in] num_head The size of the KV cache head where the tail is appended.
796 @param[in] num_tail The size of the KV cache tail to be moved.
797 @param[in] cache_size The total number of tokens accumulated in the KV cache so
798 far.
799
800 @return The updated cache size after moving the tail.
801 """
802 return self._model.move_cache_tail(num_head, num_tail, cache_size)
803
804
805def load(path: str, model_config: Optional[ModelConfig] = None) -> Model:
806 """
807 @brief Single-step inference API. Creates model and uploads the model
808 into NPU immediately.
809
810 This operation performs the Accelerator declaration, Model declaration,
811 and launch in a single step.
812 """
813 acc = Accelerator()
814 model = Model(path, model_config)
815 model.launch(acc)
816 return model
817
818
819
Represents an accelerator, i.e., an NPU, used for executing models.
Represents an AI model loaded from an MXQ file.
Definition model.py:114
DataType get_model_input_data_type(self)
Returns a data type for model inputs.
Definition model.py:639
None launch(self, Accelerator acc)
Launches the model on the specified Accelerator, which represents the actual NPU.
Definition model.py:145
None reposition_outputs(self, List[Buffer] output_bufs, List[np.ndarray] outputs, List[List[int]] seqlens=[])
Reposition output.
Definition model.py:550
List[Scale] get_input_scale(self)
Returns the input quantization scale(s) of the model.
Definition model.py:607
CoreMode get_core_mode(self)
Retrieves the core mode of the model.
Definition model.py:175
List[CoreId] get_target_cores(self)
Returns the NPU cores the model is configured to use.
Definition model.py:183
List[_Shape] _input_shape
Definition model.py:142
List[CoreId] target_cores(self)
Definition model.py:192
List[_Shape] _output_shape
Definition model.py:143
List[Buffer] acquire_input_buffer(self, List[List[int]] seqlens=[])
Buffer Management API.
Definition model.py:655
Optional[List[PinnedMemory]] infer_pinned_memory(self, List[PinnedMemory] inputs, Optional[List[PinnedMemory]] outputs=None, int cache_size=0)
Performs inference directly on pinned memory buffers (zero-copy).
Definition model.py:417
List[BufferInfo] get_output_buffer_info(self)
Returns the output buffer information of the model.
Definition model.py:631
str get_model_path(self)
Returns the path to the MXQ model file associated with the Model.
Definition model.py:698
Future infer_async(self, Union[np.ndarray, List[np.ndarray]] inputs)
Asynchronous Inference.
Definition model.py:459
DataType get_model_output_data_type(self)
Returns a data type for model outputs.
Definition model.py:647
List[Buffer] acquire_output_buffer(self, List[List[int]] seqlens=[])
Buffer Management API.
Definition model.py:666
int filter_cache_tail(self, int cache_size, int tail_size, List[bool] mask)
Filter the tail of the KV cache memory.
Definition model.py:772
List[np.ndarray] _infer_to_float(self, Union[np.ndarray, List[np.ndarray],] inputs, int cache_size, Optional[bool] is_target_hwc=None)
int8_t-to-float inference Performs inference with input and output elements of type int8_t
Definition model.py:347
int get_num_model_variants(self)
Returns the total number of model variants available in this model.
Definition model.py:563
None load_cache_memory_from(self, str cache_dir, int cache_id=0)
Loads the KV cache memory from files in the specified directory.
Definition model.py:759
bool is_target(self, CoreId core_id)
Checks if the NPU core specified by CoreId is the target of the model.
Definition model.py:164
None infer_speedrun(self)
Development-only API for measuring pure NPU inference speed.
Definition model.py:404
int get_latency_consumed(self)
Definition model.py:714
None dump_cache_memory_to(self, str cache_dir, int cache_id=0)
Dumps KV cache memory to files in the specified directory.
Definition model.py:747
Future infer_async_to_float(self, Union[np.ndarray, List[np.ndarray]] inputs)
This method supports int8_t-to-float asynchronous inference.
Definition model.py:513
ModelVariantHandle get_model_variant_handle(self, variant_idx)
Retrieves a handle to the specified model variant.
Definition model.py:574
None load_cache_memory(self, List[bytes] bufs, int cache_id=0)
Loads the KV cache memory from buffers.
Definition model.py:735
List[_Shape] get_model_output_shape(self)
Returns the output shape of the model.
Definition model.py:599
List[CacheInfo] get_cache_infos(self)
Returns informations of KV-cache of the model.
Definition model.py:706
int get_latency_finished(self)
Definition model.py:718
None release_buffer(self, List[Buffer] buffer)
Buffer Management API.
Definition model.py:677
List[bytes] dump_cache_memory(self, int cache_id=0)
Dumps the KV cache memory into buffers.
Definition model.py:722
None dispose(self)
Disposes of the model loaded onto the NPU.
Definition model.py:155
List[_Shape] get_model_input_shape(self)
Returns the input shape of the model.
Definition model.py:591
List[Scale] get_output_scale(self)
Returns the output quantization scale(s) of the model.
Definition model.py:615
None infer_buffer(self, List[Buffer] inputs, List[Buffer] outputs, List[List[int]] shape=[], int cache_size=0)
Buffer-to-Buffer inference.
Definition model.py:382
List[np.ndarray] infer_to_float(self, Union[np.ndarray, List[np.ndarray],] inputs, int cache_size=0)
int8_t-to-float inference Performs inference with input and output elements of type int8_t
Definition model.py:307
__init__(self, str path, Optional[ModelConfig] model_config=None)
Creates a Model object from the specified MXQ model file and configuration.
Definition model.py:122
Optional[List[np.ndarray]] _infer(self, Union[np.ndarray, List[np.ndarray]] inputs, Optional[List[np.ndarray]] outputs, int cache_size, Optional[bool] is_target_hwc=None, Optional[List[BatchParam]] params=None)
Definition model.py:251
Optional[List[np.ndarray]] infer(self, Union[np.ndarray, List[np.ndarray]] inputs, Optional[List[np.ndarray]] outputs=None, int cache_size=0, Optional[List[BatchParam]] params=None)
Performs inference.
Definition model.py:202
None reposition_inputs(self, List[np.ndarray] inputs, List[Buffer] input_bufs, List[List[int]] seqlens=[])
Reposition input.
Definition model.py:538
List[BufferInfo] get_input_buffer_info(self)
Returns the input buffer information for the model.
Definition model.py:623
int get_identifier(self)
Returns the model's unique identifier.
Definition model.py:687
int move_cache_tail(self, int num_head, int num_tail, int cache_size)
Moves the tail of the KV cache memory to the end of the head.
Definition model.py:788
An NPU-accessible pinned (physically contiguous) memory buffer.
A simple byte-sized buffer.
Definition type.py:219
Defines the core mode for NPU execution.
Definition type.py:244
Model load(str path, Optional[ModelConfig] model_config=None)
Single-step inference API.
Definition model.py:805