litert-lm-api 0.11.0__py3-none-win_amd64.whl

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.
litert_lm/__init__.py ADDED
@@ -0,0 +1,53 @@
1
+ # Copyright 2026 The ODML Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """LiteRT LM is a library for running GenAI models on devices."""
16
+
17
+ from ._ffi import LogSeverity
18
+ from ._ffi import set_min_log_severity
19
+ from .benchmark import Benchmark
20
+ from .conversation import Conversation
21
+ from .engine import Engine
22
+ from .interfaces import AbstractBenchmark
23
+ from .interfaces import AbstractConversation
24
+ from .interfaces import AbstractEngine
25
+ from .interfaces import AbstractSession
26
+ from .interfaces import Backend
27
+ from .interfaces import BenchmarkInfo
28
+ from .interfaces import Responses
29
+ from .interfaces import SamplerConfig
30
+ from .interfaces import Tool
31
+ from .interfaces import ToolEventHandler
32
+ from .session import Session
33
+ from .tools import tool_from_function
34
+
35
+ __all__ = (
36
+ "AbstractBenchmark",
37
+ "AbstractConversation",
38
+ "AbstractEngine",
39
+ "AbstractSession",
40
+ "Backend",
41
+ "Benchmark",
42
+ "BenchmarkInfo",
43
+ "Conversation",
44
+ "Engine",
45
+ "LogSeverity",
46
+ "Responses",
47
+ "SamplerConfig",
48
+ "Session",
49
+ "Tool",
50
+ "ToolEventHandler",
51
+ "set_min_log_severity",
52
+ "tool_from_function",
53
+ )
litert_lm/_ffi.py ADDED
@@ -0,0 +1,444 @@
1
+ # Copyright 2026 The ODML Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Low-level C library loading and FFI signatures."""
15
+
16
+ from __future__ import annotations
17
+
18
+ import ctypes
19
+ import enum
20
+ from importlib import resources
21
+ import os
22
+
23
+
24
+ class c_string_p(ctypes.c_char_p): # pylint: disable=invalid-name
25
+ """Custom ctypes type that automatically encodes Python strings to UTF-8 bytes."""
26
+
27
+ @classmethod
28
+ def from_param(cls, obj):
29
+ if obj is None:
30
+ return None
31
+ if isinstance(obj, str):
32
+ return obj.encode("utf-8")
33
+ return obj
34
+
35
+
36
+ class LiteRtLmSamplerParams(ctypes.Structure):
37
+ _fields_ = [
38
+ ("type", ctypes.c_int),
39
+ ("top_k", ctypes.c_int),
40
+ ("top_p", ctypes.c_float),
41
+ ("temperature", ctypes.c_float),
42
+ ("seed", ctypes.c_int),
43
+ ]
44
+
45
+
46
+ class LiteRtLmInputData(ctypes.Structure):
47
+ _fields_ = [
48
+ ("type", ctypes.c_int),
49
+ ("data", ctypes.c_void_p),
50
+ ("size", ctypes.c_size_t),
51
+ ]
52
+
53
+
54
+ class InputDataType(enum.IntEnum):
55
+ TEXT = 0
56
+ IMAGE = 1
57
+ IMAGE_END = 2
58
+ AUDIO = 3
59
+ AUDIO_END = 4
60
+
61
+
62
+ class TokenUnionType(enum.IntEnum):
63
+ STRING = 0
64
+ IDS = 1
65
+
66
+
67
+ class SamplerType(enum.IntEnum):
68
+ UNSPECIFIED = 0
69
+ TOP_K = 1
70
+ TOP_P = 2
71
+ GREEDY = 3
72
+
73
+
74
+ # C-compatible callback type that matches 'LiteRtLmStreamCallback' in engine.h.
75
+ STREAM_CALLBACK_TYPE = ctypes.CFUNCTYPE(
76
+ None, ctypes.c_void_p, ctypes.c_char_p, ctypes.c_bool, ctypes.c_char_p
77
+ )
78
+
79
+
80
+ class LogSeverity(enum.IntEnum):
81
+ VERBOSE = 0
82
+ DEBUG = 1
83
+ INFO = 2
84
+ WARNING = 3
85
+ ERROR = 4
86
+ FATAL = 5
87
+ SILENT = 1000
88
+
89
+
90
+ _LIB: ctypes.CDLL | None = None
91
+
92
+
93
+ def _get_lib() -> ctypes.CDLL:
94
+ """Loads and returns the LiteRT-LM C shared library."""
95
+ global _LIB
96
+ if _LIB is not None:
97
+ return _LIB
98
+
99
+ import sys
100
+ if sys.platform == "win32":
101
+ lib_name = "litert-lm.dll"
102
+ else:
103
+ extension = "dylib" if sys.platform == "darwin" else "so"
104
+ lib_name = f"liblitert-lm.{extension}"
105
+
106
+ # 1. Try loading using importlib.resources (handles .par and package files)
107
+ try:
108
+ ref = resources.files(__package__) / lib_name
109
+ with resources.as_file(ref) as path:
110
+ if path.exists():
111
+ _LIB = ctypes.CDLL(str(path))
112
+ except (ImportError, FileNotFoundError, TypeError):
113
+ pass
114
+
115
+ # 2. Fallback to direct path in runfiles for local development/Bazel
116
+ if _LIB is None:
117
+ path = os.path.join(os.path.dirname(__file__), lib_name)
118
+ if os.path.exists(path):
119
+ _LIB = ctypes.CDLL(path)
120
+
121
+ if _LIB is None:
122
+ raise RuntimeError(
123
+ f"Could not find {lib_name}. Ensure it is built and included in the"
124
+ " package or runfiles."
125
+ )
126
+
127
+ _setup_lib_signatures(_LIB)
128
+ return _LIB
129
+
130
+
131
+ def _setup_lib_signatures(lib):
132
+ """Configures the argument and return types for C API functions."""
133
+ # Log level
134
+ lib.litert_lm_set_min_log_level.argtypes = [ctypes.c_int]
135
+
136
+ # Engine Settings
137
+ lib.litert_lm_engine_settings_create.restype = ctypes.c_void_p
138
+ lib.litert_lm_engine_settings_create.argtypes = [
139
+ c_string_p,
140
+ c_string_p,
141
+ c_string_p,
142
+ c_string_p,
143
+ ]
144
+ lib.litert_lm_engine_settings_delete.argtypes = [ctypes.c_void_p]
145
+ lib.litert_lm_engine_settings_set_max_num_tokens.argtypes = [
146
+ ctypes.c_void_p,
147
+ ctypes.c_int,
148
+ ]
149
+ lib.litert_lm_engine_settings_set_cache_dir.argtypes = [
150
+ ctypes.c_void_p,
151
+ c_string_p,
152
+ ]
153
+ lib.litert_lm_engine_settings_set_enable_speculative_decoding.argtypes = [
154
+ ctypes.c_void_p,
155
+ ctypes.c_bool,
156
+ ]
157
+ lib.litert_lm_engine_settings_enable_benchmark.argtypes = [ctypes.c_void_p]
158
+ lib.litert_lm_engine_settings_set_num_prefill_tokens.argtypes = [
159
+ ctypes.c_void_p,
160
+ ctypes.c_int,
161
+ ]
162
+ lib.litert_lm_engine_settings_set_num_decode_tokens.argtypes = [
163
+ ctypes.c_void_p,
164
+ ctypes.c_int,
165
+ ]
166
+
167
+ # Engine
168
+ lib.litert_lm_engine_create.restype = ctypes.c_void_p
169
+ lib.litert_lm_engine_create.argtypes = [ctypes.c_void_p]
170
+ lib.litert_lm_engine_delete.argtypes = [ctypes.c_void_p]
171
+
172
+ # Session Config
173
+ lib.litert_lm_session_config_create.restype = ctypes.c_void_p
174
+ lib.litert_lm_session_config_create.argtypes = []
175
+ lib.litert_lm_session_config_delete.argtypes = [ctypes.c_void_p]
176
+ lib.litert_lm_session_config_set_max_output_tokens.argtypes = [
177
+ ctypes.c_void_p,
178
+ ctypes.c_int,
179
+ ]
180
+ lib.litert_lm_session_config_set_apply_prompt_template.argtypes = [
181
+ ctypes.c_void_p,
182
+ ctypes.c_bool,
183
+ ]
184
+ lib.litert_lm_session_config_set_sampler_params.argtypes = [
185
+ ctypes.c_void_p,
186
+ ctypes.POINTER(LiteRtLmSamplerParams),
187
+ ]
188
+
189
+ # Session
190
+ lib.litert_lm_engine_create_session.restype = ctypes.c_void_p
191
+ lib.litert_lm_engine_create_session.argtypes = [
192
+ ctypes.c_void_p,
193
+ ctypes.c_void_p,
194
+ ]
195
+ lib.litert_lm_session_delete.argtypes = [ctypes.c_void_p]
196
+ lib.litert_lm_session_cancel_process.argtypes = [ctypes.c_void_p]
197
+ lib.litert_lm_session_run_prefill.restype = ctypes.c_int
198
+ lib.litert_lm_session_run_prefill.argtypes = [
199
+ ctypes.c_void_p,
200
+ ctypes.POINTER(LiteRtLmInputData),
201
+ ctypes.c_size_t,
202
+ ]
203
+ lib.litert_lm_session_run_decode.restype = ctypes.c_void_p
204
+ lib.litert_lm_session_run_decode.argtypes = [ctypes.c_void_p]
205
+ lib.litert_lm_session_run_decode_async.restype = ctypes.c_int
206
+ lib.litert_lm_session_run_decode_async.argtypes = [
207
+ ctypes.c_void_p,
208
+ STREAM_CALLBACK_TYPE,
209
+ ctypes.c_void_p,
210
+ ]
211
+ lib.litert_lm_session_run_text_scoring.restype = ctypes.c_void_p
212
+ lib.litert_lm_session_run_text_scoring.argtypes = [
213
+ ctypes.c_void_p,
214
+ ctypes.POINTER(ctypes.c_char_p),
215
+ ctypes.c_size_t,
216
+ ctypes.c_bool,
217
+ ]
218
+ lib.litert_lm_session_generate_content.restype = ctypes.c_void_p
219
+ lib.litert_lm_session_generate_content.argtypes = [
220
+ ctypes.c_void_p,
221
+ ctypes.POINTER(LiteRtLmInputData),
222
+ ctypes.c_size_t,
223
+ ]
224
+ lib.litert_lm_session_generate_content_stream.restype = ctypes.c_int
225
+ lib.litert_lm_session_generate_content_stream.argtypes = [
226
+ ctypes.c_void_p,
227
+ ctypes.POINTER(LiteRtLmInputData),
228
+ ctypes.c_size_t,
229
+ STREAM_CALLBACK_TYPE,
230
+ ctypes.c_void_p,
231
+ ]
232
+
233
+ # Conversation Config
234
+ lib.litert_lm_conversation_config_create.restype = ctypes.c_void_p
235
+ lib.litert_lm_conversation_config_create.argtypes = []
236
+ lib.litert_lm_conversation_config_delete.argtypes = [ctypes.c_void_p]
237
+ lib.litert_lm_conversation_config_set_session_config.argtypes = [
238
+ ctypes.c_void_p,
239
+ ctypes.c_void_p,
240
+ ]
241
+ lib.litert_lm_conversation_config_set_system_message.argtypes = [
242
+ ctypes.c_void_p,
243
+ c_string_p,
244
+ ]
245
+ lib.litert_lm_conversation_config_set_tools.argtypes = [
246
+ ctypes.c_void_p,
247
+ c_string_p,
248
+ ]
249
+ lib.litert_lm_conversation_config_set_messages.argtypes = [
250
+ ctypes.c_void_p,
251
+ c_string_p,
252
+ ]
253
+ lib.litert_lm_conversation_config_set_extra_context.argtypes = [
254
+ ctypes.c_void_p,
255
+ c_string_p,
256
+ ]
257
+ lib.litert_lm_conversation_config_set_enable_constrained_decoding.argtypes = [
258
+ ctypes.c_void_p,
259
+ ctypes.c_bool,
260
+ ]
261
+ lib.litert_lm_conversation_config_set_filter_channel_content_from_kv_cache.argtypes = [
262
+ ctypes.c_void_p,
263
+ ctypes.c_bool,
264
+ ]
265
+
266
+ # Conversation
267
+ lib.litert_lm_conversation_create.restype = ctypes.c_void_p
268
+ lib.litert_lm_conversation_create.argtypes = [
269
+ ctypes.c_void_p,
270
+ ctypes.c_void_p,
271
+ ]
272
+ lib.litert_lm_conversation_delete.argtypes = [ctypes.c_void_p]
273
+ lib.litert_lm_conversation_send_message.restype = ctypes.c_void_p
274
+ lib.litert_lm_conversation_send_message.argtypes = [
275
+ ctypes.c_void_p,
276
+ c_string_p,
277
+ c_string_p,
278
+ ]
279
+ lib.litert_lm_conversation_send_message_stream.restype = ctypes.c_int
280
+ lib.litert_lm_conversation_send_message_stream.argtypes = [
281
+ ctypes.c_void_p,
282
+ c_string_p,
283
+ c_string_p,
284
+ STREAM_CALLBACK_TYPE,
285
+ ctypes.c_void_p,
286
+ ]
287
+ lib.litert_lm_conversation_cancel_process.argtypes = [ctypes.c_void_p]
288
+ lib.litert_lm_conversation_render_message_to_string.restype = ctypes.c_char_p
289
+ lib.litert_lm_conversation_render_message_to_string.argtypes = [
290
+ ctypes.c_void_p,
291
+ c_string_p,
292
+ ]
293
+
294
+ # interfaces.Responses
295
+ lib.litert_lm_responses_delete.argtypes = [ctypes.c_void_p]
296
+ lib.litert_lm_responses_get_num_candidates.restype = ctypes.c_int
297
+ lib.litert_lm_responses_get_num_candidates.argtypes = [ctypes.c_void_p]
298
+ lib.litert_lm_responses_get_response_text_at.restype = ctypes.c_char_p
299
+ lib.litert_lm_responses_get_response_text_at.argtypes = [
300
+ ctypes.c_void_p,
301
+ ctypes.c_int,
302
+ ]
303
+ lib.litert_lm_responses_has_score_at.restype = ctypes.c_bool
304
+ lib.litert_lm_responses_has_score_at.argtypes = [
305
+ ctypes.c_void_p,
306
+ ctypes.c_int,
307
+ ]
308
+ lib.litert_lm_responses_get_score_at.restype = ctypes.c_float
309
+ lib.litert_lm_responses_get_score_at.argtypes = [
310
+ ctypes.c_void_p,
311
+ ctypes.c_int,
312
+ ]
313
+ lib.litert_lm_responses_has_token_length_at.restype = ctypes.c_bool
314
+ lib.litert_lm_responses_has_token_length_at.argtypes = [
315
+ ctypes.c_void_p,
316
+ ctypes.c_int,
317
+ ]
318
+ lib.litert_lm_responses_get_token_length_at.restype = ctypes.c_int
319
+ lib.litert_lm_responses_get_token_length_at.argtypes = [
320
+ ctypes.c_void_p,
321
+ ctypes.c_int,
322
+ ]
323
+ lib.litert_lm_responses_has_token_scores_at.restype = ctypes.c_bool
324
+ lib.litert_lm_responses_has_token_scores_at.argtypes = [
325
+ ctypes.c_void_p,
326
+ ctypes.c_int,
327
+ ]
328
+ lib.litert_lm_responses_get_num_token_scores_at.restype = ctypes.c_int
329
+ lib.litert_lm_responses_get_num_token_scores_at.argtypes = [
330
+ ctypes.c_void_p,
331
+ ctypes.c_int,
332
+ ]
333
+ lib.litert_lm_responses_get_token_scores_at.restype = ctypes.POINTER(
334
+ ctypes.c_float
335
+ )
336
+ lib.litert_lm_responses_get_token_scores_at.argtypes = [
337
+ ctypes.c_void_p,
338
+ ctypes.c_int,
339
+ ]
340
+
341
+ # JSON Response
342
+ lib.litert_lm_json_response_delete.argtypes = [ctypes.c_void_p]
343
+ lib.litert_lm_json_response_get_string.restype = ctypes.c_char_p
344
+ lib.litert_lm_json_response_get_string.argtypes = [ctypes.c_void_p]
345
+
346
+ # Benchmark Info
347
+ lib.litert_lm_session_get_benchmark_info.restype = ctypes.c_void_p
348
+ lib.litert_lm_session_get_benchmark_info.argtypes = [ctypes.c_void_p]
349
+ lib.litert_lm_conversation_get_benchmark_info.restype = ctypes.c_void_p
350
+ lib.litert_lm_conversation_get_benchmark_info.argtypes = [ctypes.c_void_p]
351
+ lib.litert_lm_benchmark_info_delete.argtypes = [ctypes.c_void_p]
352
+ lib.litert_lm_benchmark_info_get_time_to_first_token.restype = ctypes.c_double
353
+ lib.litert_lm_benchmark_info_get_time_to_first_token.argtypes = [
354
+ ctypes.c_void_p
355
+ ]
356
+ lib.litert_lm_benchmark_info_get_total_init_time_in_second.restype = (
357
+ ctypes.c_double
358
+ )
359
+ lib.litert_lm_benchmark_info_get_total_init_time_in_second.argtypes = [
360
+ ctypes.c_void_p
361
+ ]
362
+ lib.litert_lm_benchmark_info_get_num_prefill_turns.restype = ctypes.c_int
363
+ lib.litert_lm_benchmark_info_get_num_prefill_turns.argtypes = [
364
+ ctypes.c_void_p
365
+ ]
366
+ lib.litert_lm_benchmark_info_get_num_decode_turns.restype = ctypes.c_int
367
+ lib.litert_lm_benchmark_info_get_num_decode_turns.argtypes = [ctypes.c_void_p]
368
+ lib.litert_lm_benchmark_info_get_prefill_token_count_at.restype = ctypes.c_int
369
+ lib.litert_lm_benchmark_info_get_prefill_token_count_at.argtypes = [
370
+ ctypes.c_void_p,
371
+ ctypes.c_int,
372
+ ]
373
+ lib.litert_lm_benchmark_info_get_decode_token_count_at.restype = ctypes.c_int
374
+ lib.litert_lm_benchmark_info_get_decode_token_count_at.argtypes = [
375
+ ctypes.c_void_p,
376
+ ctypes.c_int,
377
+ ]
378
+ lib.litert_lm_benchmark_info_get_prefill_tokens_per_sec_at.restype = (
379
+ ctypes.c_double
380
+ )
381
+ lib.litert_lm_benchmark_info_get_prefill_tokens_per_sec_at.argtypes = [
382
+ ctypes.c_void_p,
383
+ ctypes.c_int,
384
+ ]
385
+ lib.litert_lm_benchmark_info_get_decode_tokens_per_sec_at.restype = (
386
+ ctypes.c_double
387
+ )
388
+ lib.litert_lm_benchmark_info_get_decode_tokens_per_sec_at.argtypes = [
389
+ ctypes.c_void_p,
390
+ ctypes.c_int,
391
+ ]
392
+
393
+ # Tokenizer
394
+ lib.litert_lm_engine_tokenize.restype = ctypes.c_void_p
395
+ lib.litert_lm_engine_tokenize.argtypes = [ctypes.c_void_p, c_string_p]
396
+ lib.litert_lm_tokenize_result_delete.argtypes = [ctypes.c_void_p]
397
+ lib.litert_lm_tokenize_result_get_tokens.restype = ctypes.POINTER(
398
+ ctypes.c_int
399
+ )
400
+ lib.litert_lm_tokenize_result_get_tokens.argtypes = [ctypes.c_void_p]
401
+ lib.litert_lm_tokenize_result_get_num_tokens.restype = ctypes.c_size_t
402
+ lib.litert_lm_tokenize_result_get_num_tokens.argtypes = [ctypes.c_void_p]
403
+
404
+ lib.litert_lm_engine_detokenize.restype = ctypes.c_void_p
405
+ lib.litert_lm_engine_detokenize.argtypes = [
406
+ ctypes.c_void_p,
407
+ ctypes.POINTER(ctypes.c_int),
408
+ ctypes.c_size_t,
409
+ ]
410
+ lib.litert_lm_detokenize_result_delete.argtypes = [ctypes.c_void_p]
411
+ lib.litert_lm_detokenize_result_get_string.restype = ctypes.c_char_p
412
+ lib.litert_lm_detokenize_result_get_string.argtypes = [ctypes.c_void_p]
413
+
414
+ # Token Union / Metadata
415
+ lib.litert_lm_token_union_delete.argtypes = [ctypes.c_void_p]
416
+ lib.litert_lm_token_union_get_type.restype = ctypes.c_int
417
+ lib.litert_lm_token_union_get_type.argtypes = [ctypes.c_void_p]
418
+ lib.litert_lm_token_union_get_string.restype = ctypes.c_char_p
419
+ lib.litert_lm_token_union_get_string.argtypes = [ctypes.c_void_p]
420
+ lib.litert_lm_token_union_get_ids.restype = ctypes.c_int
421
+ lib.litert_lm_token_union_get_ids.argtypes = [
422
+ ctypes.c_void_p,
423
+ ctypes.POINTER(ctypes.POINTER(ctypes.c_int)),
424
+ ctypes.POINTER(ctypes.c_size_t),
425
+ ]
426
+
427
+ lib.litert_lm_token_unions_delete.argtypes = [ctypes.c_void_p]
428
+ lib.litert_lm_token_unions_get_num_tokens.restype = ctypes.c_size_t
429
+ lib.litert_lm_token_unions_get_num_tokens.argtypes = [ctypes.c_void_p]
430
+ lib.litert_lm_token_unions_get_token_at.restype = ctypes.c_void_p
431
+ lib.litert_lm_token_unions_get_token_at.argtypes = [
432
+ ctypes.c_void_p,
433
+ ctypes.c_size_t,
434
+ ]
435
+
436
+ lib.litert_lm_engine_get_start_token.restype = ctypes.c_void_p
437
+ lib.litert_lm_engine_get_start_token.argtypes = [ctypes.c_void_p]
438
+ lib.litert_lm_engine_get_stop_tokens.restype = ctypes.c_void_p
439
+ lib.litert_lm_engine_get_stop_tokens.argtypes = [ctypes.c_void_p]
440
+
441
+
442
+ def set_min_log_severity(severity: LogSeverity):
443
+ """Sets the minimum logging severity for the C library."""
444
+ _get_lib().litert_lm_set_min_log_level(int(severity))
litert_lm/benchmark.py ADDED
@@ -0,0 +1,114 @@
1
+ # Copyright 2026 The ODML Authors.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Benchmark wrapper for LiteRT-LM."""
15
+
16
+ import ctypes
17
+
18
+ from . import interfaces
19
+ from ._ffi import _get_lib
20
+ from ._ffi import InputDataType
21
+ from ._ffi import LiteRtLmInputData
22
+
23
+
24
+ class Benchmark(interfaces.AbstractBenchmark):
25
+ """Benchmark wrapper for the LiteRT-LM C API."""
26
+
27
+ def run(self) -> interfaces.BenchmarkInfo:
28
+ lib = _get_lib()
29
+ model_path = self.model_path
30
+ backend_str = self.backend.name.lower()
31
+
32
+ settings = lib.litert_lm_engine_settings_create(
33
+ model_path,
34
+ backend_str,
35
+ None,
36
+ None,
37
+ )
38
+ if not settings:
39
+ raise RuntimeError(
40
+ "Failed to create engine settings for benchmark"
41
+ f" (model_path={model_path}, backend={backend_str})"
42
+ )
43
+
44
+ lib.litert_lm_engine_settings_enable_benchmark(settings)
45
+ lib.litert_lm_engine_settings_set_num_prefill_tokens(
46
+ settings, self.prefill_tokens
47
+ )
48
+ lib.litert_lm_engine_settings_set_num_decode_tokens(
49
+ settings, self.decode_tokens
50
+ )
51
+ if self.cache_dir:
52
+ lib.litert_lm_engine_settings_set_cache_dir(settings, self.cache_dir)
53
+
54
+ engine_ptr = lib.litert_lm_engine_create(settings)
55
+ lib.litert_lm_engine_settings_delete(settings)
56
+
57
+ if not engine_ptr:
58
+ raise RuntimeError(
59
+ f"Failed to create engine for benchmark (model_path={model_path},"
60
+ f" backend={backend_str})"
61
+ )
62
+
63
+ session_ptr = lib.litert_lm_engine_create_session(engine_ptr, None)
64
+ if not session_ptr:
65
+ lib.litert_lm_engine_delete(engine_ptr)
66
+ raise RuntimeError(
67
+ f"Failed to create session for benchmark (model_path={model_path})"
68
+ )
69
+
70
+ dummy_prompt = b"benchmark"
71
+ input_data = LiteRtLmInputData()
72
+ input_data.type = InputDataType.TEXT
73
+ input_data.data = ctypes.cast(
74
+ ctypes.c_char_p(dummy_prompt), ctypes.c_void_p
75
+ )
76
+ input_data.size = len(dummy_prompt)
77
+
78
+ responses = lib.litert_lm_session_generate_content(
79
+ session_ptr, ctypes.byref(input_data), 1
80
+ )
81
+ if responses:
82
+ lib.litert_lm_responses_delete(responses)
83
+
84
+ info_ptr = lib.litert_lm_session_get_benchmark_info(session_ptr)
85
+ if not info_ptr:
86
+ lib.litert_lm_session_delete(session_ptr)
87
+ lib.litert_lm_engine_delete(engine_ptr)
88
+ raise RuntimeError("Failed to get benchmark info")
89
+
90
+ info = interfaces.BenchmarkInfo(
91
+ init_time_in_second=lib.litert_lm_benchmark_info_get_total_init_time_in_second(
92
+ info_ptr
93
+ ),
94
+ time_to_first_token_in_second=lib.litert_lm_benchmark_info_get_time_to_first_token(
95
+ info_ptr
96
+ ),
97
+ last_prefill_token_count=lib.litert_lm_benchmark_info_get_prefill_token_count_at(
98
+ info_ptr, 0
99
+ ),
100
+ last_prefill_tokens_per_second=lib.litert_lm_benchmark_info_get_prefill_tokens_per_sec_at(
101
+ info_ptr, 0
102
+ ),
103
+ last_decode_token_count=lib.litert_lm_benchmark_info_get_decode_token_count_at(
104
+ info_ptr, 0
105
+ ),
106
+ last_decode_tokens_per_second=lib.litert_lm_benchmark_info_get_decode_tokens_per_sec_at(
107
+ info_ptr, 0
108
+ ),
109
+ )
110
+
111
+ lib.litert_lm_benchmark_info_delete(info_ptr)
112
+ lib.litert_lm_session_delete(session_ptr)
113
+ lib.litert_lm_engine_delete(engine_ptr)
114
+ return info