lemonade-sdk 8.0.3__py3-none-any.whl → 8.0.5__py3-none-any.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.
Potentially problematic release.
This version of lemonade-sdk might be problematic. Click here for more details.
- lemonade/api.py +50 -0
- lemonade/common/inference_engines.py +415 -0
- lemonade/common/system_info.py +493 -47
- lemonade/tools/humaneval.py +1 -1
- lemonade/tools/management_tools.py +53 -7
- lemonade/tools/mmlu.py +1 -1
- lemonade/tools/oga/load.py +1 -1
- lemonade/tools/perplexity.py +2 -2
- lemonade/tools/quark/quark_load.py +1 -1
- lemonade/tools/quark/quark_quantize.py +2 -2
- lemonade/tools/server/llamacpp.py +130 -9
- lemonade/tools/server/serve.py +102 -0
- lemonade/tools/server/static/styles.css +458 -55
- lemonade/tools/server/static/webapp.html +322 -35
- lemonade/version.py +1 -1
- lemonade_sdk-8.0.5.dist-info/METADATA +295 -0
- {lemonade_sdk-8.0.3.dist-info → lemonade_sdk-8.0.5.dist-info}/RECORD +26 -25
- lemonade_server/cli.py +168 -22
- lemonade_server/model_manager.py +12 -2
- lemonade_server/pydantic_models.py +25 -1
- lemonade_server/server_models.json +46 -44
- lemonade_sdk-8.0.3.dist-info/METADATA +0 -183
- {lemonade_sdk-8.0.3.dist-info → lemonade_sdk-8.0.5.dist-info}/WHEEL +0 -0
- {lemonade_sdk-8.0.3.dist-info → lemonade_sdk-8.0.5.dist-info}/entry_points.txt +0 -0
- {lemonade_sdk-8.0.3.dist-info → lemonade_sdk-8.0.5.dist-info}/licenses/LICENSE +0 -0
- {lemonade_sdk-8.0.3.dist-info → lemonade_sdk-8.0.5.dist-info}/licenses/NOTICE.md +0 -0
- {lemonade_sdk-8.0.3.dist-info → lemonade_sdk-8.0.5.dist-info}/top_level.txt +0 -0
lemonade/common/system_info.py
CHANGED
|
@@ -1,37 +1,104 @@
|
|
|
1
|
-
from abc import ABC
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
2
|
import importlib.metadata
|
|
3
3
|
import platform
|
|
4
4
|
import re
|
|
5
5
|
import subprocess
|
|
6
6
|
import ctypes
|
|
7
|
+
from .inference_engines import detect_inference_engines
|
|
8
|
+
|
|
9
|
+
# AMD GPU classification keywords - shared across all OS implementations
|
|
10
|
+
# If a GPU name contains any of these keywords, it's considered discrete
|
|
11
|
+
# Everything else is assumed to be integrated
|
|
12
|
+
AMD_DISCRETE_GPU_KEYWORDS = [
|
|
13
|
+
"rx ",
|
|
14
|
+
"xt",
|
|
15
|
+
"pro w",
|
|
16
|
+
"pro v",
|
|
17
|
+
"radeon pro",
|
|
18
|
+
"firepro",
|
|
19
|
+
"fury",
|
|
20
|
+
]
|
|
7
21
|
|
|
8
22
|
|
|
9
23
|
class SystemInfo(ABC):
|
|
10
|
-
"""
|
|
24
|
+
"""
|
|
25
|
+
Abstract base class for OS-dependent system information classes.
|
|
26
|
+
"""
|
|
11
27
|
|
|
12
28
|
def __init__(self):
|
|
13
29
|
pass
|
|
14
30
|
|
|
15
31
|
def get_dict(self):
|
|
16
32
|
"""
|
|
17
|
-
Retrieves all the system information into a dictionary
|
|
33
|
+
Retrieves all the system information into a dictionary.
|
|
18
34
|
|
|
19
35
|
Returns:
|
|
20
|
-
dict: System information
|
|
36
|
+
dict: System information.
|
|
21
37
|
"""
|
|
22
38
|
info_dict = {
|
|
23
39
|
"OS Version": self.get_os_version(),
|
|
24
|
-
"Python Packages": self.get_python_packages(),
|
|
25
40
|
}
|
|
26
41
|
return info_dict
|
|
27
42
|
|
|
43
|
+
def get_device_dict(self):
|
|
44
|
+
"""
|
|
45
|
+
Retrieves device information into a dictionary.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
dict: Device information.
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
device_dict = {
|
|
52
|
+
"cpu": self.get_cpu_device(),
|
|
53
|
+
"amd_igpu": self.get_amd_igpu_device(),
|
|
54
|
+
"amd_dgpu": self.get_amd_dgpu_devices(),
|
|
55
|
+
"npu": self.get_npu_device(),
|
|
56
|
+
}
|
|
57
|
+
return device_dict
|
|
58
|
+
|
|
59
|
+
@abstractmethod
|
|
60
|
+
def get_cpu_device(self) -> dict:
|
|
61
|
+
"""
|
|
62
|
+
Retrieves CPU device information.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
dict: CPU device information.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def get_amd_igpu_device(self) -> dict:
|
|
70
|
+
"""
|
|
71
|
+
Retrieves AMD integrated GPU device information.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
dict: AMD iGPU device information.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
@abstractmethod
|
|
78
|
+
def get_amd_dgpu_devices(self) -> list:
|
|
79
|
+
"""
|
|
80
|
+
Retrieves AMD discrete GPU device information.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
list: List of AMD dGPU device information.
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
@abstractmethod
|
|
87
|
+
def get_npu_device(self) -> dict:
|
|
88
|
+
"""
|
|
89
|
+
Retrieves NPU device information.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
dict: NPU device information.
|
|
93
|
+
"""
|
|
94
|
+
|
|
28
95
|
@staticmethod
|
|
29
96
|
def get_os_version() -> str:
|
|
30
97
|
"""
|
|
31
98
|
Retrieves the OS version.
|
|
32
99
|
|
|
33
100
|
Returns:
|
|
34
|
-
str: OS Version
|
|
101
|
+
str: OS Version.
|
|
35
102
|
"""
|
|
36
103
|
try:
|
|
37
104
|
return platform.platform()
|
|
@@ -55,7 +122,9 @@ class SystemInfo(ABC):
|
|
|
55
122
|
|
|
56
123
|
|
|
57
124
|
class WindowsSystemInfo(SystemInfo):
|
|
58
|
-
"""
|
|
125
|
+
"""
|
|
126
|
+
Class used to access system information in Windows.
|
|
127
|
+
"""
|
|
59
128
|
|
|
60
129
|
def __init__(self):
|
|
61
130
|
super().__init__()
|
|
@@ -63,6 +132,148 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
63
132
|
|
|
64
133
|
self.connection = wmi.WMI()
|
|
65
134
|
|
|
135
|
+
def get_cpu_device(self) -> dict:
|
|
136
|
+
"""
|
|
137
|
+
Retrieves CPU device information using WMI.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
dict: CPU device information.
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
processors = self.connection.Win32_Processor()
|
|
144
|
+
if processors:
|
|
145
|
+
processor = processors[0]
|
|
146
|
+
cpu_info = {
|
|
147
|
+
"name": processor.Name.strip(),
|
|
148
|
+
"cores": processor.NumberOfCores,
|
|
149
|
+
"threads": processor.NumberOfLogicalProcessors,
|
|
150
|
+
"max_clock_speed_mhz": processor.MaxClockSpeed,
|
|
151
|
+
"available": True,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# Add inference engine detection
|
|
155
|
+
cpu_info["inference_engines"] = self._detect_inference_engines("cpu")
|
|
156
|
+
return cpu_info
|
|
157
|
+
|
|
158
|
+
except Exception as e: # pylint: disable=broad-except
|
|
159
|
+
return {"available": False, "error": f"CPU detection failed: {e}"}
|
|
160
|
+
|
|
161
|
+
return {"available": False, "error": "No CPU information found"}
|
|
162
|
+
|
|
163
|
+
def _detect_amd_gpus(self, gpu_type: str):
|
|
164
|
+
"""
|
|
165
|
+
Shared AMD GPU detection logic for both integrated and discrete GPUs.
|
|
166
|
+
Uses keyword-based classification for simplicity and reliability.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
gpu_type: Either "integrated" or "discrete"
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
list: List of detected GPU info dictionaries
|
|
173
|
+
"""
|
|
174
|
+
gpu_devices = []
|
|
175
|
+
try:
|
|
176
|
+
video_controllers = self.connection.Win32_VideoController()
|
|
177
|
+
for controller in video_controllers:
|
|
178
|
+
if (
|
|
179
|
+
controller.Name
|
|
180
|
+
and "AMD" in controller.Name
|
|
181
|
+
and "Radeon" in controller.Name
|
|
182
|
+
):
|
|
183
|
+
|
|
184
|
+
name_lower = controller.Name.lower()
|
|
185
|
+
|
|
186
|
+
# Keyword-based classification - simple and reliable
|
|
187
|
+
is_discrete_by_name = any(
|
|
188
|
+
kw in name_lower for kw in AMD_DISCRETE_GPU_KEYWORDS
|
|
189
|
+
)
|
|
190
|
+
is_integrated = not is_discrete_by_name
|
|
191
|
+
|
|
192
|
+
# Filter based on requested type
|
|
193
|
+
if (gpu_type == "integrated" and is_integrated) or (
|
|
194
|
+
gpu_type == "discrete" and not is_integrated
|
|
195
|
+
):
|
|
196
|
+
|
|
197
|
+
driver_version = self.get_driver_version(
|
|
198
|
+
"AMD-OpenCL User Mode Driver"
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
device_type = "amd_igpu" if is_integrated else "amd_dgpu"
|
|
202
|
+
gpu_info = {
|
|
203
|
+
"name": controller.Name,
|
|
204
|
+
"driver_version": (
|
|
205
|
+
driver_version if driver_version else "Unknown"
|
|
206
|
+
),
|
|
207
|
+
"available": True,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
# Add inference engine detection
|
|
211
|
+
gpu_info["inference_engines"] = self._detect_inference_engines(
|
|
212
|
+
device_type
|
|
213
|
+
)
|
|
214
|
+
gpu_devices.append(gpu_info)
|
|
215
|
+
|
|
216
|
+
except Exception as e: # pylint: disable=broad-except
|
|
217
|
+
error_msg = f"AMD {gpu_type} GPU detection failed: {e}"
|
|
218
|
+
return [{"available": False, "error": error_msg}]
|
|
219
|
+
|
|
220
|
+
return gpu_devices
|
|
221
|
+
|
|
222
|
+
def get_amd_igpu_device(self) -> dict:
|
|
223
|
+
"""
|
|
224
|
+
Retrieves AMD integrated GPU device information using keyword-based classification.
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
dict: AMD iGPU device information.
|
|
228
|
+
"""
|
|
229
|
+
igpu_devices = self._detect_amd_gpus("integrated")
|
|
230
|
+
return (
|
|
231
|
+
igpu_devices[0]
|
|
232
|
+
if igpu_devices
|
|
233
|
+
else {"available": False, "error": "No AMD integrated GPU found"}
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
def get_amd_dgpu_devices(self):
|
|
237
|
+
"""
|
|
238
|
+
Retrieves AMD discrete GPU device information using keyword-based classification.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
list: List of AMD dGPU device information.
|
|
242
|
+
"""
|
|
243
|
+
dgpu_devices = self._detect_amd_gpus("discrete")
|
|
244
|
+
return (
|
|
245
|
+
dgpu_devices
|
|
246
|
+
if dgpu_devices
|
|
247
|
+
else {"available": False, "error": "No AMD discrete GPU found"}
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
def get_npu_device(self) -> dict:
|
|
251
|
+
"""
|
|
252
|
+
Retrieves NPU device information using existing methods.
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
dict: NPU device information.
|
|
256
|
+
"""
|
|
257
|
+
try:
|
|
258
|
+
# Check if NPU driver is present
|
|
259
|
+
driver_version = self.get_driver_version("NPU Compute Accelerator Device")
|
|
260
|
+
if driver_version:
|
|
261
|
+
power_mode = self.get_npu_power_mode()
|
|
262
|
+
npu_info = {
|
|
263
|
+
"name": "AMD NPU",
|
|
264
|
+
"driver_version": driver_version,
|
|
265
|
+
"power_mode": power_mode,
|
|
266
|
+
"available": True,
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# Add inference engine detection
|
|
270
|
+
npu_info["inference_engines"] = self._detect_inference_engines("npu")
|
|
271
|
+
return npu_info
|
|
272
|
+
except Exception as e: # pylint: disable=broad-except
|
|
273
|
+
return {"available": False, "error": f"NPU detection failed: {e}"}
|
|
274
|
+
|
|
275
|
+
return {"available": False, "error": "No NPU device found"}
|
|
276
|
+
|
|
66
277
|
def get_processor_name(self) -> str:
|
|
67
278
|
"""
|
|
68
279
|
Retrieves the name of the processor.
|
|
@@ -79,6 +290,18 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
79
290
|
)
|
|
80
291
|
return "Processor information not found."
|
|
81
292
|
|
|
293
|
+
def get_basic_processor_name(self) -> str:
|
|
294
|
+
"""
|
|
295
|
+
Retrieves the basic name of the processor without core/thread details.
|
|
296
|
+
|
|
297
|
+
Returns:
|
|
298
|
+
str: Basic name of the processor.
|
|
299
|
+
"""
|
|
300
|
+
processors = self.connection.Win32_Processor()
|
|
301
|
+
if processors:
|
|
302
|
+
return processors[0].Name.strip()
|
|
303
|
+
return "Processor information not found."
|
|
304
|
+
|
|
82
305
|
def get_system_model(self) -> str:
|
|
83
306
|
"""
|
|
84
307
|
Retrieves the model of the computer system.
|
|
@@ -96,19 +319,13 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
96
319
|
Retrieves the physical memory of the computer system.
|
|
97
320
|
|
|
98
321
|
Returns:
|
|
99
|
-
str: Physical memory
|
|
322
|
+
str: Physical memory.
|
|
100
323
|
"""
|
|
101
324
|
memory = self.connection.Win32_PhysicalMemory()
|
|
102
325
|
if memory:
|
|
103
326
|
total_capacity = sum([int(m.Capacity) for m in memory])
|
|
104
327
|
total_capacity_str = f"{total_capacity/(1024**3)} GB"
|
|
105
|
-
|
|
106
|
-
[
|
|
107
|
-
f"{m.Manufacturer} {int(m.Capacity)/(1024**3)} GB {m.Speed} ns"
|
|
108
|
-
for m in memory
|
|
109
|
-
]
|
|
110
|
-
)
|
|
111
|
-
return total_capacity_str + " (" + details_str + ")"
|
|
328
|
+
return total_capacity_str
|
|
112
329
|
return "Physical memory information not found."
|
|
113
330
|
|
|
114
331
|
def get_bios_version(self) -> str:
|
|
@@ -116,7 +333,7 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
116
333
|
Retrieves the BIOS Version of the computer system.
|
|
117
334
|
|
|
118
335
|
Returns:
|
|
119
|
-
str: BIOS Version
|
|
336
|
+
str: BIOS Version.
|
|
120
337
|
"""
|
|
121
338
|
bios = self.connection.Win32_BIOS()
|
|
122
339
|
if bios:
|
|
@@ -128,7 +345,7 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
128
345
|
Retrieves the max clock speed of the CPU of the system.
|
|
129
346
|
|
|
130
347
|
Returns:
|
|
131
|
-
str: Max CPU clock speed
|
|
348
|
+
str: Max CPU clock speed.
|
|
132
349
|
"""
|
|
133
350
|
processor = self.connection.Win32_Processor()
|
|
134
351
|
if processor:
|
|
@@ -140,7 +357,7 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
140
357
|
Retrieves the driver version for the specified device name.
|
|
141
358
|
|
|
142
359
|
Returns:
|
|
143
|
-
str: Driver version, or None if device driver not found
|
|
360
|
+
str: Driver version, or None if device driver not found.
|
|
144
361
|
"""
|
|
145
362
|
drivers = self.connection.Win32_PnPSignedDriver(DeviceName=device_name)
|
|
146
363
|
if drivers:
|
|
@@ -153,7 +370,7 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
153
370
|
Retrieves the NPU power mode.
|
|
154
371
|
|
|
155
372
|
Returns:
|
|
156
|
-
str: NPU power mode
|
|
373
|
+
str: NPU power mode.
|
|
157
374
|
"""
|
|
158
375
|
try:
|
|
159
376
|
out = subprocess.check_output(
|
|
@@ -207,37 +424,66 @@ class WindowsSystemInfo(SystemInfo):
|
|
|
207
424
|
|
|
208
425
|
def get_dict(self) -> dict:
|
|
209
426
|
"""
|
|
210
|
-
Retrieves all the system information into a dictionary
|
|
427
|
+
Retrieves all the system information into a dictionary.
|
|
211
428
|
|
|
212
429
|
Returns:
|
|
213
|
-
dict: System information
|
|
430
|
+
dict: System information.
|
|
214
431
|
"""
|
|
215
432
|
info_dict = super().get_dict()
|
|
216
|
-
info_dict["Processor"] = self.
|
|
433
|
+
info_dict["Processor"] = self.get_basic_processor_name()
|
|
217
434
|
info_dict["OEM System"] = self.get_system_model()
|
|
218
435
|
info_dict["Physical Memory"] = self.get_physical_memory()
|
|
219
436
|
info_dict["BIOS Version"] = self.get_bios_version()
|
|
220
437
|
info_dict["CPU Max Clock"] = self.get_max_clock_speed()
|
|
221
438
|
info_dict["Windows Power Setting"] = self.get_windows_power_setting()
|
|
222
|
-
if "AMD" in info_dict["Processor"]:
|
|
223
|
-
device_names = [
|
|
224
|
-
"NPU Compute Accelerator Device",
|
|
225
|
-
"AMD-OpenCL User Mode Driver",
|
|
226
|
-
]
|
|
227
|
-
driver_versions = {
|
|
228
|
-
device_name: self.get_driver_version(device_name)
|
|
229
|
-
for device_name in device_names
|
|
230
|
-
}
|
|
231
|
-
info_dict["Driver Versions"] = {
|
|
232
|
-
k: (v if len(v) else "DEVICE NOT FOUND")
|
|
233
|
-
for k, v in driver_versions.items()
|
|
234
|
-
}
|
|
235
|
-
info_dict["NPU Power Mode"] = self.get_npu_power_mode()
|
|
236
439
|
return info_dict
|
|
237
440
|
|
|
441
|
+
def _detect_inference_engines(self, device_type: str) -> dict:
|
|
442
|
+
"""
|
|
443
|
+
Detect available inference engines for a specific device type.
|
|
444
|
+
|
|
445
|
+
Args:
|
|
446
|
+
device_type: Device type ("cpu", "amd_igpu", "amd_dgpu", "npu")
|
|
447
|
+
|
|
448
|
+
Returns:
|
|
449
|
+
dict: Available inference engines and their information.
|
|
450
|
+
"""
|
|
451
|
+
try:
|
|
452
|
+
from .inference_engines import detect_inference_engines
|
|
453
|
+
|
|
454
|
+
return detect_inference_engines(device_type)
|
|
455
|
+
except Exception as e: # pylint: disable=broad-except
|
|
456
|
+
return {"error": f"Inference engine detection failed: {str(e)}"}
|
|
457
|
+
|
|
238
458
|
|
|
239
459
|
class WSLSystemInfo(SystemInfo):
|
|
240
|
-
"""
|
|
460
|
+
"""
|
|
461
|
+
Class used to access system information in WSL.
|
|
462
|
+
"""
|
|
463
|
+
|
|
464
|
+
def get_cpu_device(self) -> dict:
|
|
465
|
+
"""
|
|
466
|
+
Retrieves CPU device information in WSL environment.
|
|
467
|
+
"""
|
|
468
|
+
return {"available": False, "error": "Device detection not supported in WSL"}
|
|
469
|
+
|
|
470
|
+
def get_amd_igpu_device(self) -> dict:
|
|
471
|
+
"""
|
|
472
|
+
Retrieves AMD integrated GPU device information in WSL environment.
|
|
473
|
+
"""
|
|
474
|
+
return {"available": False, "error": "GPU detection not supported in WSL"}
|
|
475
|
+
|
|
476
|
+
def get_amd_dgpu_devices(self) -> list:
|
|
477
|
+
"""
|
|
478
|
+
Retrieves AMD discrete GPU device information in WSL environment.
|
|
479
|
+
"""
|
|
480
|
+
return []
|
|
481
|
+
|
|
482
|
+
def get_npu_device(self) -> dict:
|
|
483
|
+
"""
|
|
484
|
+
Retrieves NPU device information in WSL environment.
|
|
485
|
+
"""
|
|
486
|
+
return {"available": False, "error": "NPU detection not supported in WSL"}
|
|
241
487
|
|
|
242
488
|
@staticmethod
|
|
243
489
|
def get_system_model() -> str:
|
|
@@ -265,10 +511,10 @@ class WSLSystemInfo(SystemInfo):
|
|
|
265
511
|
|
|
266
512
|
def get_dict(self) -> dict:
|
|
267
513
|
"""
|
|
268
|
-
Retrieves all the system information into a dictionary
|
|
514
|
+
Retrieves all the system information into a dictionary.
|
|
269
515
|
|
|
270
516
|
Returns:
|
|
271
|
-
dict: System information
|
|
517
|
+
dict: System information.
|
|
272
518
|
"""
|
|
273
519
|
info_dict = super().get_dict()
|
|
274
520
|
info_dict["OEM System"] = self.get_system_model()
|
|
@@ -276,7 +522,147 @@ class WSLSystemInfo(SystemInfo):
|
|
|
276
522
|
|
|
277
523
|
|
|
278
524
|
class LinuxSystemInfo(SystemInfo):
|
|
279
|
-
"""
|
|
525
|
+
"""
|
|
526
|
+
Class used to access system information in Linux.
|
|
527
|
+
"""
|
|
528
|
+
|
|
529
|
+
def get_cpu_device(self) -> dict:
|
|
530
|
+
"""
|
|
531
|
+
Retrieves CPU device information using /proc/cpuinfo and lscpu.
|
|
532
|
+
|
|
533
|
+
Returns:
|
|
534
|
+
dict: CPU device information.
|
|
535
|
+
"""
|
|
536
|
+
try:
|
|
537
|
+
cpu_info = subprocess.check_output("lscpu", shell=True).decode()
|
|
538
|
+
cpu_data = {}
|
|
539
|
+
|
|
540
|
+
for line in cpu_info.split("\n"):
|
|
541
|
+
if "Model name:" in line:
|
|
542
|
+
cpu_data["name"] = line.split(":")[1].strip()
|
|
543
|
+
elif "CPU(s):" in line and "NUMA" not in line:
|
|
544
|
+
cpu_data["threads"] = int(line.split(":")[1].strip())
|
|
545
|
+
elif "Core(s) per socket:" in line:
|
|
546
|
+
cores_per_socket = int(line.split(":")[1].strip())
|
|
547
|
+
sockets = (
|
|
548
|
+
1 # Default to 1 socket as most laptops have a single socket
|
|
549
|
+
)
|
|
550
|
+
for l in cpu_info.split("\n"):
|
|
551
|
+
if "Socket(s):" in l:
|
|
552
|
+
sockets = int(l.split(":")[1].strip())
|
|
553
|
+
break
|
|
554
|
+
cpu_data["cores"] = cores_per_socket * sockets
|
|
555
|
+
elif "Architecture:" in line:
|
|
556
|
+
cpu_data["architecture"] = line.split(":")[1].strip()
|
|
557
|
+
|
|
558
|
+
if "name" in cpu_data:
|
|
559
|
+
cpu_info = {
|
|
560
|
+
"name": cpu_data.get("name", "Unknown"),
|
|
561
|
+
"cores": cpu_data.get("cores", "Unknown"),
|
|
562
|
+
"threads": cpu_data.get("threads", "Unknown"),
|
|
563
|
+
"architecture": cpu_data.get("architecture", "Unknown"),
|
|
564
|
+
"available": True,
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
# Add inference engine detection
|
|
568
|
+
cpu_info["inference_engines"] = self._detect_inference_engines("cpu")
|
|
569
|
+
return cpu_info
|
|
570
|
+
except Exception as e: # pylint: disable=broad-except
|
|
571
|
+
return {"available": False, "error": f"CPU detection failed: {e}"}
|
|
572
|
+
|
|
573
|
+
return {"available": False, "error": "No CPU information found"}
|
|
574
|
+
|
|
575
|
+
def _detect_amd_gpus(self, gpu_type: str):
|
|
576
|
+
"""
|
|
577
|
+
Shared AMD GPU detection logic for both integrated and discrete GPUs.
|
|
578
|
+
Uses keyword-based classification for simplicity and reliability.
|
|
579
|
+
|
|
580
|
+
Args:
|
|
581
|
+
gpu_type: Either "integrated" or "discrete".
|
|
582
|
+
|
|
583
|
+
Returns:
|
|
584
|
+
list: List of detected GPU info dictionaries.
|
|
585
|
+
"""
|
|
586
|
+
gpu_devices = []
|
|
587
|
+
try:
|
|
588
|
+
lspci_output = subprocess.check_output(
|
|
589
|
+
"lspci | grep -i 'vga\\|3d\\|display'", shell=True
|
|
590
|
+
).decode()
|
|
591
|
+
|
|
592
|
+
for line in lspci_output.split("\n"):
|
|
593
|
+
if line.strip() and "AMD" in line:
|
|
594
|
+
name_lower = line.lower()
|
|
595
|
+
|
|
596
|
+
# Keyword-based classification - simple and reliable
|
|
597
|
+
is_discrete_by_name = any(
|
|
598
|
+
kw in name_lower for kw in AMD_DISCRETE_GPU_KEYWORDS
|
|
599
|
+
)
|
|
600
|
+
is_integrated = not is_discrete_by_name
|
|
601
|
+
|
|
602
|
+
# Filter based on requested type
|
|
603
|
+
if (gpu_type == "integrated" and is_integrated) or (
|
|
604
|
+
gpu_type == "discrete" and not is_integrated
|
|
605
|
+
):
|
|
606
|
+
|
|
607
|
+
device_type = "amd_igpu" if is_integrated else "amd_dgpu"
|
|
608
|
+
device_name = line.split(": ")[1] if ": " in line else line
|
|
609
|
+
|
|
610
|
+
gpu_info = {
|
|
611
|
+
"name": device_name,
|
|
612
|
+
"available": True,
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
# Add inference engine detection
|
|
616
|
+
gpu_info["inference_engines"] = self._detect_inference_engines(
|
|
617
|
+
device_type
|
|
618
|
+
)
|
|
619
|
+
gpu_devices.append(gpu_info)
|
|
620
|
+
|
|
621
|
+
except Exception as e: # pylint: disable=broad-except
|
|
622
|
+
error_msg = f"AMD {gpu_type} GPU detection failed: {e}"
|
|
623
|
+
return [{"available": False, "error": error_msg}]
|
|
624
|
+
|
|
625
|
+
return gpu_devices
|
|
626
|
+
|
|
627
|
+
def get_amd_igpu_device(self) -> dict:
|
|
628
|
+
"""
|
|
629
|
+
Retrieves AMD integrated GPU device information using keyword-based classification.
|
|
630
|
+
|
|
631
|
+
Returns:
|
|
632
|
+
dict: AMD iGPU device information.
|
|
633
|
+
"""
|
|
634
|
+
igpu_devices = self._detect_amd_gpus("integrated")
|
|
635
|
+
return (
|
|
636
|
+
igpu_devices[0]
|
|
637
|
+
if igpu_devices
|
|
638
|
+
else {"available": False, "error": "No AMD integrated GPU found"}
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
def get_amd_dgpu_devices(self):
|
|
642
|
+
"""
|
|
643
|
+
Retrieves AMD discrete GPU device information using keyword-based classification.
|
|
644
|
+
|
|
645
|
+
Returns:
|
|
646
|
+
list: List of AMD dGPU device information.
|
|
647
|
+
"""
|
|
648
|
+
dgpu_devices = self._detect_amd_gpus("discrete")
|
|
649
|
+
return (
|
|
650
|
+
dgpu_devices
|
|
651
|
+
if dgpu_devices
|
|
652
|
+
else {"available": False, "error": "No AMD discrete GPU found"}
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
def get_npu_device(self) -> dict:
|
|
656
|
+
"""
|
|
657
|
+
Retrieves NPU device information (limited support on Linux).
|
|
658
|
+
|
|
659
|
+
Returns:
|
|
660
|
+
dict: NPU device information.
|
|
661
|
+
"""
|
|
662
|
+
return {
|
|
663
|
+
"available": False,
|
|
664
|
+
"error": "NPU detection not yet implemented for Linux",
|
|
665
|
+
}
|
|
280
666
|
|
|
281
667
|
@staticmethod
|
|
282
668
|
def get_processor_name() -> str:
|
|
@@ -328,7 +714,7 @@ class LinuxSystemInfo(SystemInfo):
|
|
|
328
714
|
Retrieves the physical memory of the computer system.
|
|
329
715
|
|
|
330
716
|
Returns:
|
|
331
|
-
str: Physical memory
|
|
717
|
+
str: Physical memory.
|
|
332
718
|
"""
|
|
333
719
|
try:
|
|
334
720
|
mem_info = (
|
|
@@ -344,10 +730,10 @@ class LinuxSystemInfo(SystemInfo):
|
|
|
344
730
|
|
|
345
731
|
def get_dict(self) -> dict:
|
|
346
732
|
"""
|
|
347
|
-
Retrieves all the system information into a dictionary
|
|
733
|
+
Retrieves all the system information into a dictionary.
|
|
348
734
|
|
|
349
735
|
Returns:
|
|
350
|
-
dict: System information
|
|
736
|
+
dict: System information.
|
|
351
737
|
"""
|
|
352
738
|
info_dict = super().get_dict()
|
|
353
739
|
info_dict["Processor"] = self.get_processor_name()
|
|
@@ -355,16 +741,66 @@ class LinuxSystemInfo(SystemInfo):
|
|
|
355
741
|
info_dict["Physical Memory"] = self.get_physical_memory()
|
|
356
742
|
return info_dict
|
|
357
743
|
|
|
744
|
+
def _detect_inference_engines(self, device_type: str) -> dict:
|
|
745
|
+
"""
|
|
746
|
+
Detect available inference engines for a specific device type.
|
|
747
|
+
|
|
748
|
+
Args:
|
|
749
|
+
device_type: Device type ("cpu", "amd_igpu", "amd_dgpu", "npu")
|
|
750
|
+
|
|
751
|
+
Returns:
|
|
752
|
+
dict: Available inference engines and their information.
|
|
753
|
+
"""
|
|
754
|
+
try:
|
|
755
|
+
return detect_inference_engines(device_type)
|
|
756
|
+
except Exception as e: # pylint: disable=broad-except
|
|
757
|
+
return {"error": f"Inference engine detection failed: {str(e)}"}
|
|
758
|
+
|
|
358
759
|
|
|
359
760
|
class UnsupportedOSSystemInfo(SystemInfo):
|
|
360
|
-
"""
|
|
761
|
+
"""
|
|
762
|
+
Class used to access system information in unsupported operating systems.
|
|
763
|
+
"""
|
|
764
|
+
|
|
765
|
+
def get_cpu_device(self) -> dict:
|
|
766
|
+
"""
|
|
767
|
+
Retrieves CPU device information for unsupported OS.
|
|
768
|
+
"""
|
|
769
|
+
return {
|
|
770
|
+
"available": False,
|
|
771
|
+
"error": "Device detection not supported on this operating system",
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
def get_amd_igpu_device(self) -> dict:
|
|
775
|
+
"""
|
|
776
|
+
Retrieves AMD integrated GPU device information for unsupported OS.
|
|
777
|
+
"""
|
|
778
|
+
return {
|
|
779
|
+
"available": False,
|
|
780
|
+
"error": "Device detection not supported on this operating system",
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
def get_amd_dgpu_devices(self) -> list:
|
|
784
|
+
"""
|
|
785
|
+
Retrieves AMD discrete GPU device information for unsupported OS.
|
|
786
|
+
"""
|
|
787
|
+
return []
|
|
788
|
+
|
|
789
|
+
def get_npu_device(self) -> dict:
|
|
790
|
+
"""
|
|
791
|
+
Retrieves NPU device information for unsupported OS.
|
|
792
|
+
"""
|
|
793
|
+
return {
|
|
794
|
+
"available": False,
|
|
795
|
+
"error": "Device detection not supported on this operating system",
|
|
796
|
+
}
|
|
361
797
|
|
|
362
798
|
def get_dict(self):
|
|
363
799
|
"""
|
|
364
|
-
Retrieves all the system information into a dictionary
|
|
800
|
+
Retrieves all the system information into a dictionary.
|
|
365
801
|
|
|
366
802
|
Returns:
|
|
367
|
-
dict: System information
|
|
803
|
+
dict: System information.
|
|
368
804
|
"""
|
|
369
805
|
info_dict = super().get_dict()
|
|
370
806
|
info_dict["Error"] = "UNSUPPORTED OS"
|
|
@@ -382,7 +818,7 @@ def get_system_info() -> SystemInfo:
|
|
|
382
818
|
if os_type == "Windows":
|
|
383
819
|
return WindowsSystemInfo()
|
|
384
820
|
elif os_type == "Linux":
|
|
385
|
-
# WSL has to be handled differently compared to native Linux
|
|
821
|
+
# WSL has to be handled differently compared to native Linux.
|
|
386
822
|
if "microsoft" in str(platform.release()):
|
|
387
823
|
return WSLSystemInfo()
|
|
388
824
|
else:
|
|
@@ -401,5 +837,15 @@ def get_system_info_dict() -> dict:
|
|
|
401
837
|
return get_system_info().get_dict()
|
|
402
838
|
|
|
403
839
|
|
|
840
|
+
def get_device_info_dict() -> dict:
|
|
841
|
+
"""
|
|
842
|
+
Puts the device information into a dictionary.
|
|
843
|
+
|
|
844
|
+
Returns:
|
|
845
|
+
dict: Dictionary containing the device information.
|
|
846
|
+
"""
|
|
847
|
+
return get_system_info().get_device_dict()
|
|
848
|
+
|
|
849
|
+
|
|
404
850
|
# This file was originally licensed under Apache 2.0. It has been modified.
|
|
405
851
|
# Modifications Copyright (c) 2025 AMD
|