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 +53 -0
- litert_lm/_ffi.py +444 -0
- litert_lm/benchmark.py +114 -0
- litert_lm/conversation.py +246 -0
- litert_lm/dxcompiler.dll +0 -0
- litert_lm/dxil.dll +0 -0
- litert_lm/engine.py +290 -0
- litert_lm/interfaces.py +474 -0
- litert_lm/litert-lm.dll +0 -0
- litert_lm/session.py +158 -0
- litert_lm/tools.py +130 -0
- litert_lm/utils.py +60 -0
- litert_lm_api-0.11.0.dist-info/METADATA +22 -0
- litert_lm_api-0.11.0.dist-info/RECORD +15 -0
- litert_lm_api-0.11.0.dist-info/WHEEL +4 -0
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
|